# 程式 repo 結構檢查與第一版實作範圍盤點

## 1. 文件目的

本文件整理進入 `MySqlSchemaInspector` Query Builder / Row Mapper 第一版實作前，對程式 repo 的實際結構、既有 contract、測試位置與停止線的檢查結果。

本次只做結構盤點與範圍確認，尚未修改程式 repo，尚未新增套件，尚未修改 `.csproj`，尚未連線 MySQL，也尚未讀取真實 `information_schema`。

## 2. 檢查基準

| 項目 | 內容 |
|---|---|
| 程式 repo | `hs-device-control-template` |
| 分支 | `poc/nmodbus-tcp` |
| 檢查版本 | `ac52376` 接入 Schema Initializer ConsoleHost DryRun 顯示 |
| 工作區狀態 | 檢查時為乾淨狀態 |
| 文件 repo | `hs-device-control-template-docs` |
| 本次性質 | 文件盤點，不修改程式碼 |

## 3. 已確認的程式結構

目前 Schema Automation 相關程式集中在 `src/HS.DeviceControl.Core/Schema`。

| 區域 | 既有內容 | 判斷 |
|---|---|---|
| Schema model | `SchemaDefinition`、`TableDefinition`、`ColumnDefinition`、`IndexDefinition` | 已足夠承接真實 DB metadata snapshot |
| Attribute parser | `DbTableAttribute`、`DbColumnAttribute`、`DbIndexAttribute`、`SchemaDefinitionParser` | 已能從 C# class 產生 expected schema |
| SQL generator | `MySqlSchemaSqlGenerator`、`MySqlSchemaSqlGeneratorOptions` | 已能產生 create / alter / dry run SQL |
| Inspector abstraction | `ISchemaInspector`、`SchemaInspectRequest`、`SchemaInspectResult` | 已有抽象介面與 mock inspector |
| Dry run / initializer | `SchemaDryRunPlanner`、`SchemaInitializer` | 已能用 expected schema 與 inspected schema 產生 dry run 結果 |
| 測試專案 | `tests/HS.DeviceControl.Core.Tests` | 已有 Schema parser、SQL generator、inspector、dry run、initializer 測試 |
| Infrastructure project | 尚未存在 | 第一版不應新增 Infrastructure project；若要新增需另行確認 |

## 4. 已確認的既有 contract

### 4.1 Inspector 介面

目前 inspector contract 已固定為：

```csharp
SchemaInspectResult Inspect(SchemaInspectRequest request);
```

第一版 Query Builder / Row Mapper 不應修改此簽章。

### 4.2 Request 已具備的資訊

`SchemaInspectRequest` 已包含：

| 欄位 | 用途 |
|---|---|
| `DatabaseName` | 指定要檢查的 database / schema |
| `ExpectedTables` | 限定要讀取的 table 清單 |
| `IncludeIndexes` | 是否讀取 index metadata |
| `IncludeComments` | 是否讀取 table / column comment |
| `CorrelationId` | 追蹤本次檢查 |

第一版不需要新增 request 欄位。

### 4.3 Result 已具備的資訊

`SchemaInspectResult` 已包含：

| 欄位 | 用途 |
|---|---|
| `Success` | 是否成功 |
| `Schema` | 實際讀到的 schema snapshot |
| `Warnings` | metadata 不完整或需人工檢查的提醒 |
| `Error` | 標準錯誤資訊 |
| `TimeTakenMs` | 耗時 |
| `Source` | 來源，例如 `Mock` 或未來 `MySQL` |

第一版不需要修改 result contract。

## 5. 可安全實作的第一版範圍

若使用者確認可進入程式 repo 實作，第一版建議仍維持「不依賴真實 DB 的純程式元件」。

| 元件 | 建議位置 | 職責 |
|---|---|---|
| `MySqlSchemaInspectorQueryBuilder` | `src/HS.DeviceControl.Core/Schema` | 產生 `information_schema` table / column / index 查詢字串與參數名稱 |
| `MySqlSchemaQuery` | `src/HS.DeviceControl.Core/Schema` | 保存 SQL 與參數名稱，方便測試 |
| `MySqlTableMetadataRow` | `src/HS.DeviceControl.Core/Schema` | 承接 table metadata row |
| `MySqlColumnMetadataRow` | `src/HS.DeviceControl.Core/Schema` | 承接 column metadata row |
| `MySqlIndexMetadataRow` | `src/HS.DeviceControl.Core/Schema` | 承接 index metadata row |
| `MySqlSchemaMetadataMapper` | `src/HS.DeviceControl.Core/Schema` | 將 metadata row 轉成 schema model |
| `MySqlSchemaSnapshotAssembler` | `src/HS.DeviceControl.Core/Schema` | 將 table / column / index row 組合成 `SchemaDefinition` |

建議測試放在：

| 測試檔 | 驗證重點 |
|---|---|
| `MySqlSchemaInspectorQueryBuilderTests.cs` | SQL 限制 `TABLE_SCHEMA = @DatabaseName`、table filter 參數化、排序穩定、不產生 DDL |
| `MySqlSchemaMetadataMapperTests.cs` | MySQL 5.6.2 欄位型態、nullable、comment、primary key metadata mapping |
| `MySqlSchemaSnapshotAssemblerTests.cs` | table / column / index row 組裝、missing table warning、index 欄位排序 |

## 6. 需先確認的實作策略

這次盤點後發現，第一版實作最大的決策點不是 SQL 內容，而是「helper class 要用 public 還是 internal」。

| 方案 | 優點 | 風險 |
|---|---|---|
| 方案 A：helper class 設為 `public` | 測試最直接，不需新增 assembly metadata | 會擴大 public API surface，後續較難收斂 |
| 方案 B：helper class 設為 `internal`，並使用 `InternalsVisibleTo` | 對外 contract 較乾淨，符合不擴大 public API 的方向 | 需要新增 assembly metadata；雖不改 `.csproj`，仍屬專案層級設定，建議先確認 |
| 方案 C：全部藏在 `MySqlSchemaInspector` private method | public API 不擴大 | 測試粒度差，之後導入真實 DB 時風險較高 |

建議採用方案 B：`internal helper + InternalsVisibleTo`。  
但因這會新增 assembly metadata，建議在正式實作前先取得使用者確認。

## 7. 不建議現在做的事情

| 不做項目 | 原因 |
|---|---|
| 新增 `MySqlConnector` | 會修改套件依賴與 `.csproj`，需另行確認 |
| 新增 Infrastructure project | 會改變專案結構，需另行確認 |
| 連線 MySQL | 涉及真實環境、帳密與網路設定 |
| 讀取真實 `information_schema` | 需要 DB 連線與套件 |
| 執行 DDL / ALTER TABLE | 會修改資料庫，必須另行確認與備份策略 |
| 修改 `ISchemaInspector` public method 簽章 | 會改變既有 contract |
| 修改 ConsoleHost 啟動方式 | 屬於專案啟動方式變更，需另行確認 |

## 8. 目前判斷

目前程式 repo 結構可以支援下一步進入「不連 DB 的 Query Builder / Row Mapper / Snapshot Assembler 第一版實作」。

但若要同時維持 public API 乾淨與可測試性，建議先確認是否接受新增 `InternalsVisibleTo`。若不接受，則需改採 public helper 或降低測試粒度。

## 9. 建議下一步

建議下一步先由使用者確認 helper class 策略：

1. 採用方案 B：`internal helper + InternalsVisibleTo`，再進入程式 repo 實作。
2. 若不想新增 assembly metadata，採用方案 A：public helper，但需接受 public API surface 增加。
3. 若希望最保守，先只實作 Query Builder public class，不做 mapper / assembler。

建議選擇方案 B，因為它最符合「不任意擴大對外 contract」的方向，也最利於後續維護。
