# MySqlSchemaSqlGenerator 第一版實作與驗證紀錄

## 1. 驗證節點摘要

| 項目 | 內容 |
|---|---|
| 驗證節點名稱 | MySqlSchemaSqlGenerator 第一版 |
| 驗證日期 | 2026-05-30 |
| 程式 repo | `hs-device-control-template` |
| 實作 commit | `9bd1ec1` |
| 驗證分支 | `poc/nmodbus-tcp` |
| 驗證 commit | `6c5cd01` |
| 文件網站同步 commit | `fdabf8d` |
| 自動測試結果 | `dotnet test` 通過 270 個測試 |
| 狀態 | 已完成第一版驗證 |

本節點確認 `MySqlSchemaSqlGenerator` 已能從 Schema Definition 產生 MySQL 5.6.2 相容的 `CREATE TABLE IF NOT EXISTS` SQL 字串。

本節點仍不代表已連線 MySQL，也不代表已執行 DDL。第一版刻意停在「可產生 SQL、可測試、可被審查」的安全範圍內。

## 2. 驗證目的

本次驗證的目的如下：

- 確認 C# Class 維護的欄位、型別、索引與描述可以轉成 SQL 字串。
- 確認 SQL Generator 不直接連線 MySQL、不執行 DDL，避免在尚未確認環境前改動真實資料庫。
- 確認 MySQL 5.6.2 型別白名單與 identifier 規則有測試保護。
- 確認錯誤情境會回傳標準錯誤結果，而不是丟出未處理 exception。
- 確認後續可承接 `ALTER TABLE`、Schema Initializer、Dry Run 與 TaskStore PoC。

## 3. 已完成範圍

| 項目 | 實際完成內容 |
|---|---|
| SQL 產生器 | 新增 `MySqlSchemaSqlGenerator` |
| Options | 新增 `MySqlSchemaSqlGeneratorOptions` |
| 結果模型 | 新增 `SchemaSqlGenerateResult` |
| 支援輸入 | `SchemaDefinition`、`TableDefinition` |
| 支援輸出 | `CREATE TABLE IF NOT EXISTS` SQL 字串 |
| MySQL 版本 | 以 MySQL 5.6.2 相容性作為第一版約束 |
| Identifier | 驗證 table、column、index name 格式 |
| 型別白名單 | 支援第一版 TaskStore 需要的基礎型別 |
| Comment | 支援 table / column comment，並處理單引號 escaping |
| Index | 支援 primary key、一般 index、unique index |
| 錯誤處理 | 使用 `SchemaDefinitionInvalid` 回傳可讀錯誤 |
| 測試 | 新增 `MySqlSchemaSqlGeneratorTests` |

## 4. 實際測試結果

執行指令：

```powershell
dotnet test
```

結果：

| 測試專案 | 通過數 |
|---|---:|
| `HS.DeviceControl.Core.Tests` | 125 |
| `HS.DeviceControl.WorkflowSimulation.Tests` | 11 |
| `HS.DeviceControl.Adapters.Tests` | 108 |
| `HS.DeviceControl.ModbusPoc.Tests` | 26 |
| 合計 | 270 |

測試結果為全部通過。

執行時仍會出現 `.NET 5.0 已不受支援` 的 `NETSDK1138` warning，這是目前指定 .NET 5.0 的預期限制，不是本次 SQL Generator 新增造成的錯誤。

## 5. SQL Generator 測試涵蓋

| 測試方向 | 驗證結果 |
|---|---|
| 產生 MySQL 5.6.2 相容 SQL | 可產生 `CREATE TABLE IF NOT EXISTS` |
| 欄位 required / nullable | 可輸出 `NOT NULL` / `NULL` |
| Primary key | 可輸出 `PRIMARY KEY`，且 primary key 欄位強制 `NOT NULL` |
| 一般 index | 可輸出 `INDEX` |
| Unique index | 可輸出 `UNIQUE INDEX` |
| 多 table | 可由 `SchemaDefinition` 產生多筆 SQL |
| Comment escaping | 單引號會轉成 SQL 可接受的 `''` |
| 不支援型別 | `json`、`timestamp`、超出範圍的 `varchar` 等會被擋下 |
| 不合法 table name | 空白、dash、dot、中文 identifier 會被擋下 |
| 缺少 primary key | 會回傳 `SchemaDefinitionInvalid` |
| index 指向不存在欄位 | 會回傳 `SchemaDefinitionInvalid` |
| 不使用反引號 | `QuoteIdentifiers = false` 時可產生未 quote 的 identifier |

## 6. 第一版明確不做事項

| 不做事項 | 原因 |
|---|---|
| 不連線 MySQL | 目前仍未進入真實 DB 驗證 |
| 不執行 DDL | 避免在行前資訊未確認前改動資料庫 |
| 不做 `ALTER TABLE` | 需要先設計 schema diff 與補欄位策略 |
| 不查 `information_schema` | 屬於 Schema Initializer 範圍 |
| 不導入 MySqlConnector | 第一版只產生字串，不需要 DB driver |
| 不接 ConsoleHost / API | 啟動流程與 DB 初始化要另外設計 |
| 不建立 TaskStore | TaskStore 寫入 / 查詢 / 狀態恢復屬於後續節點 |

## 7. 實際效果

目前實際效果是：

- 工程師可以先在 C# Class 維護 schema 欄位、型別、索引與描述。
- 程式可以將解析後的 schema 轉成可審查的 MySQL `CREATE TABLE` SQL。
- 系統尚不會碰真實資料庫，因此適合在導入 DB 前先檢查 SQL 格式與欄位規格。
- 後續可以用這個 SQL Generator 承接 Dry Run、Schema Initializer 與 TaskStore PoC。

換句話說，本節點把「欄位規格可由 C# Class 維護」往前推進到「可產生 SQL 並被測試保護」，但還沒有進入「自動建表執行」。

## 8. 風險與限制

| 風險 / 限制 | 說明 |
|---|---|
| 尚未實測 MySQL 5.6.2 | 目前是以字串規則與白名單測試保護，尚未送到真實 MySQL 執行 |
| 尚無 schema diff | 既有資料表缺欄位或缺索引時，還沒有 `ALTER TABLE` 產生策略 |
| 尚無 Dry Run 報告 | 目前只有 SQL 字串，還沒有輸出「將新增哪些 table / column / index」的報告格式 |
| 尚無初始化入口 | ConsoleHost / ServiceHost / WebApi 尚未接 DB 初始化流程 |
| 尚未處理正式 DB 權限 | 真實 DB 的 user、password、host、port、dbname 仍需由使用者提供並確認權限 |

## 9. 結論

`MySqlSchemaSqlGenerator` 第一版已達成目前節點目標：可由 schema definition 產生 MySQL 5.6.2 相容的 `CREATE TABLE IF NOT EXISTS` SQL，並由 270 個自動測試確認現有功能沒有回歸。

本節點可以標記為完成。

## 10. 建議下一步

建議下一步進入：

> `ALTER TABLE / Schema Initializer 實作前確認`

建議先不要直接寫 DB 初始化器，而是先確認：

- 是否第一版只允許新增缺少欄位，不允許修改既有欄位型別。
- index 缺少時是否自動補上。
- table / column / index 已存在時如何判斷。
- Dry Run 報告格式要如何讓使用者確認。
- 真實 MySQL 連線測試是否仍維持人工確認後才執行。
