
# スキーマ検証

スナップショット間でスキーマが変化すると（カラムの追加、削除、名前変更など）、merqlはその差異を検出して報告します。スキーマの不一致によってマージが妨げられることはありませんが、呼び出し側が対処方法を判断できるように提示されます。

## 検出

`SchemaValidator::validate()`は、base、ours、theirsの各スナップショットにあるテーブルのカラム集合を比較し、次の内容を報告します。

- oursで追加されたカラム（baseにはなく、oursに存在）
- oursで削除されたカラム（baseにはあり、oursには存在しない）
- theirsで追加されたカラム
- theirsで削除されたカラム

```php
use Merql\Merge\ThreeWayMerge;

$merge = new ThreeWayMerge();
$result = $merge->merge($base, $ours, $theirs);

if ($result->hasSchemaMismatches()) {
    foreach ($result->schemaMismatches() as $mismatch) {
        echo $mismatch->getMessage() . "\n";
        // "Schema mismatch on table 'posts': columns added in theirs: subtitle"
    }
}
```

## 検出される変更

| 変更 | 検出 | 備考 |
|---|---|---|
| カラムの追加 | はい | 側ごと（ours/theirs）に報告 |
| カラムの削除 | はい | 側ごとに報告 |
| カラム型の変更 | いいえ | 型は保存されますが、比較されません |
| カラム名の変更 | いいえ | 追加と削除として表示されます |
| 主キーの変更 | いいえ | 識別情報はスナップショット時に固定されます |

## マージ時の動作

あるスナップショットには存在し、別のスナップショットには存在しないカラムについて、マージでは欠落したカラムの値を`null`として扱います。つまり、次のようになります。

- theirsで追加されたカラムにnull以外の値がある場合、`null -> value`として表示されます（theirs側の変更として受け入れられます）
- theirsで削除されたカラムは、theirsのすべての行で`null`を持つものとして扱われます

マージは続行され、結果が生成されます。スキーマの不一致は情報として提示されます。適用前に、対象データベースのスキーマがマージ済みデータと一致することを確認してください。

## 不一致へのアクセス

スキーマの不一致は`ThreeWayMerge`（`schemaMismatches()`経由）と`MergeResult`（`schemaMismatches()`および`hasSchemaMismatches()`経由）の両方で確認でき、`ConflictResolver::resolve()`を通じて保持されます。

```php
// On the merge result directly
$result->hasSchemaMismatches(); // bool
$result->schemaMismatches();    // list<SchemaException>

// Each mismatch is a SchemaException with a descriptive message
foreach ($result->schemaMismatches() as $e) {
    // $e->getMessage() includes table name and column details
}
```
