# ALTER TABLE / Schema Initializer 實作前確認

## 1. 文件目的

本文件用來確認 `MySqlSchemaSqlGenerator` 第一版完成後，是否可以進入下一個節點：`ALTER TABLE / Schema Initializer`。

目前已完成的範圍是：

- C# Class 可透過 Schema Attribute 維護 table、column、index 與 description。
- `SchemaDefinitionParser` 可將 Attribute 轉成 schema definition。
- `MySqlSchemaSqlGenerator` 可產生 `CREATE TABLE IF NOT EXISTS` SQL 字串。
- `dotnet test` 已通過 270 個測試。

本文件要先釐清：

- 是否允許產生 `ALTER TABLE` SQL。
- 是否允許查詢 `information_schema`。
- 是否允許實際連線 MySQL。
- 是否允許執行 DDL。
- Dry Run 報告格式要如何呈現。
- 哪些項目可由 Codex 自動執行，哪些必須停下確認。

## 2. 自動化分級規則

| 分級 | 定義 | Codex 是否可自動執行 |
|---|---|---|
| A：可自動執行 | 只影響文件、測試、純字串產生器、Dry Run 格式、非真實 DB 的單元測試 | 可以 |
| B：需先回報但可建議預設方案 | 可能影響實作方向，但尚未碰真實 DB、套件或 public contract | 先回報確認點，再依已確認方向執行 |
| C：必須停下確認 | 會改資料模型、設定檔格式、public method 簽章、新增套件、連線 MySQL、執行 DDL、修改外部服務或使用敏感資訊 | 不可自動執行 |

本節點預設採用：

> 文件、設計、測試清單與純字串 SQL 產生器可自動化；真實 DB 連線與 DDL 執行必須停下確認。

## 3. 建議採用的第一版邊界

### 3.1 第一版允許

| 項目 | 是否允許 | 自動化分級 | 說明 |
|---|---|---|---|
| 產生 `ALTER TABLE ADD COLUMN` SQL 字串 | 允許 | A | 只產生字串，不執行 |
| 產生 `ALTER TABLE ADD INDEX` SQL 字串 | 允許 | A | 包含一般 index 與 unique index |
| 產生 Dry Run 報告物件 | 允許 | A | 報告將新增 table、column、index |
| 新增 Schema Diff 模型 | 允許 | B | 若只是 internal model 可自動；若會變 public contract 需確認 |
| 新增單元測試 | 允許 | A | 不需真實 DB |
| 更新文件網站進度 | 允許 | A | 屬文件同步 |

### 3.2 第一版禁止

| 項目 | 是否禁止 | 自動化分級 | 原因 |
|---|---|---|---|
| 修改既有欄位型別 | 禁止 | C | 可能破壞資料或造成資料截斷 |
| 刪除欄位 | 禁止 | C | 高風險資料破壞 |
| 刪除 index | 禁止 | C | 可能影響查詢與現場效能 |
| 自動 rename 欄位 | 禁止 | C | 難以可靠判斷意圖 |
| 自動建立 database | 禁止 | C | 涉及 DB 權限與環境邊界 |
| 自動連線正式 MySQL | 禁止 | C | 需要 host、port、user、password、dbname |
| 自動執行 DDL | 禁止 | C | 會改動真實 DB schema |

## 4. Schema Initializer 建議分層

建議把功能拆成三層，避免一開始就讓啟動流程碰真實 DB：

| 層級 | 元件 | 責任 | 是否可先實作 |
|---|---|---|---|
| Schema Parser | `SchemaDefinitionParser` | 從 C# Class 解析 schema | 已完成 |
| SQL Generator | `MySqlSchemaSqlGenerator` | 產生 `CREATE TABLE` / `ALTER TABLE` SQL 字串 | 可先做 |
| Schema Plan / Dry Run | `MySqlSchemaPlan` / `SchemaMigrationPlan` | 描述將新增哪些 table / column / index | 可先做 |
| Schema Inspector | `MySqlSchemaInspector` | 查詢 `information_schema` 取得現況 | 需確認套件與連線 |
| Schema Initializer | `MySqlSchemaInitializer` | 組合 inspector、generator、executor | 需確認套件與啟動流程 |
| Schema Executor | `MySqlSchemaExecutor` | 實際執行 DDL | 必須停下確認 |

第一版建議先做：

1. `ALTER TABLE` SQL 字串產生器。
2. Dry Run / Plan 模型。
3. 不連 DB 的單元測試。

暫不做：

1. `information_schema` 查詢。
2. MySQL 實際連線。
3. DDL 執行。
4. ConsoleHost 啟動自動建表。

## 5. ALTER TABLE 規則建議

### 5.1 新增欄位

第一版建議只支援新增缺少欄位：

```sql
ALTER TABLE `task_executions`
  ADD COLUMN `status` varchar(32) NOT NULL COMMENT '任務狀態';
```

規則：

- 只允許 `ADD COLUMN`。
- 欄位型別仍走 MySQL 5.6.2 白名單。
- 欄位名稱仍走 identifier 驗證。
- comment 仍需 escaping。
- 不支援 `AFTER column` 排序，避免欄位順序造成非必要差異。

### 5.2 新增索引

第一版建議支援新增缺少 index：

```sql
ALTER TABLE `task_executions`
  ADD INDEX `idx_task_executions_status` (`status`);
```

unique index：

```sql
ALTER TABLE `task_executions`
  ADD UNIQUE INDEX `uk_task_executions_workflow` (`workflow_id`, `task_id`);
```

規則：

- 只允許 `ADD INDEX` / `ADD UNIQUE INDEX`。
- index name 必須通過 identifier 驗證。
- index columns 必須存在於目標 table schema。
- 不自動刪除或重建既有 index。

### 5.3 不修改既有欄位

若 DB 現況欄位與 C# schema 不一致，第一版只回報差異，不自動修正：

| 差異 | 第一版處理方式 |
|---|---|
| 型別不同 | 報告 `RequiresManualReview` |
| nullable 不同 | 報告 `RequiresManualReview` |
| comment 不同 | 報告 `RequiresManualReview` |
| primary key 不同 | 報告 `RequiresManualReview` |
| index 欄位不同但名稱相同 | 報告 `RequiresManualReview` |

## 6. Dry Run 報告格式建議

第一版 Dry Run 報告建議包含：

| 欄位 | 說明 |
|---|---|
| `Success` | 是否成功產生計畫 |
| `Mode` | `DryRun` / `Execute`，第一版只允許 `DryRun` |
| `TablesToCreate` | 預計新增的 table |
| `ColumnsToAdd` | 預計新增的 column |
| `IndexesToAdd` | 預計新增的 index |
| `ManualReviewItems` | 需要人工判斷的差異 |
| `SqlStatements` | 預計產生的 SQL 字串 |
| `Warnings` | 風險或限制提醒 |
| `Error` | 失敗時的標準錯誤資訊 |

範例：

```json
{
  "mode": "DryRun",
  "tablesToCreate": ["task_executions"],
  "columnsToAdd": ["task_executions.status"],
  "indexesToAdd": ["task_executions.idx_task_executions_status"],
  "manualReviewItems": [],
  "sqlStatements": [
    "CREATE TABLE IF NOT EXISTS `task_executions` (...)",
    "ALTER TABLE `task_executions` ADD COLUMN `status` varchar(32) NOT NULL COMMENT '任務狀態'"
  ],
  "warnings": [
    "Dry Run 不會連線或修改 MySQL。"
  ]
}
```

## 7. 實作前確認表

| 確認項目 | 建議決策 | 自動化分級 | 是否已確認 |
|---|---|---|---|
| 第一版是否只產生 SQL 字串，不執行 DDL | 是 | A | 建議確認 |
| 是否允許產生 `ALTER TABLE ADD COLUMN` | 是 | A | 建議確認 |
| 是否允許產生 `ALTER TABLE ADD INDEX` | 是 | A | 建議確認 |
| 是否允許修改既有欄位型別 | 否 | C | 必須確認 |
| 是否允許刪除欄位 / index | 否 | C | 必須確認 |
| 是否新增 Dry Run Plan 模型 | 是 | B | 建議確認 |
| 是否新增 MySqlConnector | 暫不新增 | C | 必須確認 |
| 是否查詢 `information_schema` | 暫不查 | C | 必須確認 |
| 是否連線真實 MySQL | 暫不連 | C | 必須確認 |
| 是否接 ConsoleHost 啟動流程 | 暫不接 | C | 必須確認 |

## 8. 建議實作順序

### 8.1 可自動執行

1. 新增 `SchemaMigrationPlan` / `SchemaMigrationOperation` 類型。
2. 新增 `GenerateAlterTableSql` 或等效方法，但只產生 SQL 字串。
3. 新增 Dry Run 報告模型。
4. 新增不連 DB 的單元測試。
5. 更新文件與進度。

### 8.2 需停下確認後才執行

1. 新增 `MySqlConnector`。
2. 建立 `MySqlSchemaInspector` 查詢 `information_schema`。
3. 建立 `MySqlSchemaExecutor` 執行 DDL。
4. 將 Schema Initializer 接入 ConsoleHost / ServiceHost / WebApi 啟動流程。
5. 使用真實 MySQL host、port、database、user、password 測試。

## 9. 建議結論

建議下一步不要直接做完整 Schema Initializer，而是先做：

> `ALTER TABLE SQL 字串產生器 + Dry Run Plan 第一版`

理由：

- 可保持在不連 DB、不執行 DDL 的安全範圍。
- 可先把 schema diff 與報告格式定穩。
- 可用單元測試保護規則。
- 後續要接 MySQL 實際連線時，邏輯邊界會更清楚。

## 10. 下一步建議

若採用本文件建議，下一步可以進入：

> `ALTER TABLE SQL 產生器與 Dry Run Plan 第一版實作`

實作前仍需確認兩個決策：

1. 第一版是否只允許新增缺少的 column / index，不允許修改或刪除既有項目。
2. 第一版是否完全不連 MySQL，只做純字串與 Dry Run Plan。
