# Schema Inspector / information_schema 實作前確認

## 1. 文件目的

本文件整理進入 `Schema Inspector / information_schema` 前需要確認的範圍、資料來源、讀取欄位、測試方式與停止條件。

此節點的目標不是執行 DDL，也不是啟動自動建表，而是先確認「如何安全讀取 MySQL 既有 schema」，讓後續 Dry Run Plan 可以從真實資料庫現況產生。

## 2. 目前前置狀態

| 項目 | 狀態 |
|---|---|
| MySQL 版本 | 使用者指定為 MySQL 5.6.2 |
| SQL Generator | 已完成 `CREATE TABLE IF NOT EXISTS`、`ADD COLUMN`、`ADD INDEX` |
| Dry Run Plan | 已完成第一版純程式比對 |
| 目前測試數 | `dotnet test` 通過 278 個測試 |
| 最新程式 commit | `db0b1b8` |
| 真實 MySQL 連線 | 尚未導入 |
| DDL 執行 | 尚未導入 |
| MySQL 套件導入 | 尚未在本節點執行 |

## 3. 本節點建議目標

第一版 Schema Inspector 建議只做「讀取真實 DB schema 快照」，不做任何修改。

| 目標 | 說明 |
|---|---|
| 讀取 table 清單 | 從 `information_schema.TABLES` 取得指定 database 的 table |
| 讀取 column 清單 | 從 `information_schema.COLUMNS` 取得欄位名稱、型別、nullable、預設值、comment |
| 讀取 index 清單 | 從 `information_schema.STATISTICS` 取得 index 名稱、欄位順序、是否 unique |
| 讀取 primary key | 可由 `information_schema.KEY_COLUMN_USAGE` 或 `STATISTICS` 判斷 |
| 轉成 schema snapshot | 轉成專案內部 `SchemaDefinition` / `TableDefinition` / `ColumnDefinition` / `IndexDefinition` 相容資料 |
| 提供給 Dry Run Plan | 將現有 DB snapshot 與目標 schema 比對 |

## 4. 明確不做的事

| 不做項目 | 原因 |
|---|---|
| 不執行 `CREATE TABLE` | Inspector 只讀，不負責建表 |
| 不執行 `ALTER TABLE` | 避免尚未確認前修改資料庫 |
| 不執行 `DROP` / `MODIFY` / `CHANGE` | 破壞性或高風險 SQL 必須另行確認 |
| 不把密碼寫進文件或 repo | 避免洩漏敏感資訊 |
| 不在 Core 直接依賴 MySQL 套件 | 避免破壞分層，DB 讀取應放在 Infrastructure 或專屬 schema 模組 |
| 不接 ConsoleHost 自動啟動流程 | 啟動自動建表需等 Inspector、Plan、Executor 都確認後再做 |

## 5. information_schema 查詢範圍

### 5.1 `information_schema.TABLES`

建議讀取欄位：

| 欄位 | 用途 |
|---|---|
| `TABLE_SCHEMA` | 限制 database |
| `TABLE_NAME` | 對應 table name |
| `TABLE_COMMENT` | 對應 table description |
| `ENGINE` | 確認是否為 InnoDB 等預期 engine |
| `TABLE_COLLATION` | 後續判斷字元集與排序規則 |

### 5.2 `information_schema.COLUMNS`

建議讀取欄位：

| 欄位 | 用途 |
|---|---|
| `TABLE_NAME` | 對應所屬 table |
| `COLUMN_NAME` | 對應 column name |
| `COLUMN_TYPE` | 保留完整 MySQL 型別，例如 `varchar(64)` |
| `DATA_TYPE` | 判斷基礎型別，例如 `varchar`、`datetime` |
| `CHARACTER_MAXIMUM_LENGTH` | 判斷字串長度 |
| `NUMERIC_PRECISION` / `NUMERIC_SCALE` | 判斷數值精度 |
| `IS_NULLABLE` | 對應 nullable |
| `COLUMN_DEFAULT` | 保留 default 資訊 |
| `COLUMN_COMMENT` | 對應欄位描述 |
| `ORDINAL_POSITION` | 保留欄位順序 |

### 5.3 `information_schema.STATISTICS`

建議讀取欄位：

| 欄位 | 用途 |
|---|---|
| `TABLE_NAME` | 對應所屬 table |
| `INDEX_NAME` | 對應 index name |
| `COLUMN_NAME` | 對應 index 欄位 |
| `NON_UNIQUE` | 判斷 unique / non-unique |
| `SEQ_IN_INDEX` | 還原複合 index 欄位順序 |

### 5.4 `information_schema.KEY_COLUMN_USAGE`

建議用途：

| 用途 | 說明 |
|---|---|
| 判斷 primary key | 可輔助確認 primary key 欄位 |
| 保留外鍵資訊 | 第一版可先讀取但不進入自動修正 |

第一版可以只把外鍵列為 `ManualReviewItems` 或 warning，不建議自動產生 foreign key DDL。

## 6. MySQL 5.6.2 注意事項

| 項目 | 注意事項 |
|---|---|
| JSON 型別 | MySQL 5.6.2 不支援原生 `json`，仍需映射為 `text` 或 `varchar` |
| `datetime` 精度 | 需避免使用較新版本才穩定支援的語法 |
| generated column | 第一版不納入 |
| online DDL | 第一版不依賴 |
| collation | 先讀取與記錄，不在第一版自動修正 |
| foreign key | 先讀取與記錄，不在第一版自動建立或修改 |

## 7. 建議程式邊界

| 元件 | 建議責任 |
|---|---|
| `ISchemaInspector` | 定義讀取目前 schema snapshot 的抽象介面 |
| `MySqlSchemaInspector` | 透過 MySQL 連線讀取 `information_schema` |
| `SchemaDefinition` | 表示目標 schema 或目前 DB snapshot |
| `MySqlSchemaSqlGenerator` | 只負責產生 SQL 字串 |
| `SchemaMigrationPlan` | 表示 dry run 比對結果 |
| `SchemaInitializer` | 後續才負責串接 inspector、generator、executor |

建議第一版不要把 MySQL 讀取邏輯放進 Core。Core 可以保留抽象 model 與比對結果，真實 DB 讀取應放在 Infrastructure 或專門的 MySQL schema 實作區。

## 8. 測試策略

| 測試層級 | 建議方式 |
|---|---|
| 單元測試 | 使用 fake / in-memory reader 模擬 `information_schema` 查詢結果 |
| mapping 測試 | 確認 table、column、index 可正確轉成 schema snapshot |
| MySQL 5.6.2 相容測試 | 先以文件列出必要查詢語法，實際連線測試需使用者提供測試 DB |
| 安全測試 | 確認 Inspector 不產生 DDL、不呼叫 executor、不修改 DB |
| 異常測試 | 連線失敗、權限不足、database 不存在、查詢結果空集合 |

## 9. 需要使用者確認的項目

| 項目 | 為什麼需要確認 |
|---|---|
| 是否允許導入 `MySqlConnector` | 這會新增核心資料庫連線套件 |
| MySQL 測試 DB 連線資訊 | Inspector 若要做真實連線測試，需要 host、port、dbname、user 與密碼提供方式 |
| 測試帳號權限 | 第一版建議只需要 `SELECT` `information_schema` 與目標 database metadata |
| 是否允許新增 Infrastructure 專案或資料夾 | 會影響專案分層與檔案位置 |
| 是否需要先只做 mock inspector | 可避免先接真實 DB，也能完成 mapping 與 Dry Run 串接測試 |

## 10. 建議決策

我的建議是先採用「兩段式」：

1. 先做 `ISchemaInspector` 與 mock / fake inspector，驗證 mapping 到 `SchemaDefinition` 與 Dry Run Plan 串接。
2. 再經使用者確認後導入 `MySqlConnector`，實作 `MySqlSchemaInspector` 查詢 `information_schema`。

這樣可以先把架構與測試補齊，同時避免太早接觸真實資料庫、密碼與外部環境。

## 11. 建議下一步

建議下一步先做：

> `Schema Inspector 抽象介面與 mock inspector 實作前確認`

此步驟可先不導入 MySQL 套件、不連線 DB，只確認介面、回傳模型、錯誤格式與測試案例。

若要直接進入真實 MySQL Inspector，則需先確認：

- 是否允許新增 `MySqlConnector`。
- MySQL 測試連線資訊如何提供。
- 測試帳號是否只有讀取權限。
- Inspector 實作放在哪一層。
