
# PHP API Başvurusu

merql içindeki tüm genel sınıflar ve yöntemler için eksiksiz başvuru.

## Merql (cephe)

`Merql\Merql`, yaygın işlemler için statik giriş noktasıdır. Alt düzey sınıfları sarmalar ve anlık görüntü kalıcılığını otomatik olarak yönetir.

```php
use Merql\Connection;
use Merql\Identity\IdentityRule;
use Merql\Identity\IdentityRuleSet;
use Merql\Merql;

$connection = Connection::sqlite(':memory:');
Merql::init($connection, identityRules: new IdentityRuleSet([
    'options' => IdentityRule::natural(['option_name']),
]));
```

### `init(DatabaseConnection $connection, ?Driver $driver = null, ?IdentityRuleSet $identityRules = null): void`

Veritabanı bağlantısıyla cepheyi başlatın. `snapshot()`, `apply()` veya `applyGuarded()` öncesinde çağrılmalıdır; veritabanlarını değiştirmek için yeniden çağırın, örneğin iki farklı kopyadan ours ve theirs için anlık görüntü almak üzere. `$driver` yoksa, sürücü kaydedilmediği sürece MySQL ve SQLite dışındaki motorlarda hata veren `DriverFactory::create()` çağrılır. Otomatik algılamayı geçersiz kılmak için sürücü, anlık görüntü alma sırasında tablo bazında satır kimliğini geçersiz kılmak içinse kimlik kuralı kümesi sağlayın.

### `snapshot(string $name, array $tables = []): Snapshot`

Geçerli veritabanı durumunu yakalayın ve diske kaydedin. Belirli tabloların anlık görüntüsünü almak için tablo adlarından oluşan bir dizi verin; tüm tablolar için parametreyi atlayın.

```php
$snapshot = Merql::snapshot('baseline');
$snapshot = Merql::snapshot('baseline', ['posts', 'users']);
```

### `diff(string $base, string $current): Changeset`

İki adlandırılmış anlık görüntüyü yükleyin ve aralarındaki değişiklik kümesini hesaplayın. Kalıcı anlık görüntüler üzerinden çalıştığından `init()` gerektirmez.

```php
$changeset = Merql::diff('before', 'after');
```

### `merge(string $base, string $ours, string $theirs): MergeResult`

Üç adlandırılmış anlık görüntünün üç yönlü birleştirmesi. Temiz işlemleri ve varsa çakışmaları içeren bir sonuç döndürür. Sütun düzeyinde birleştirir: cephe, `CellMergeConfig` olmadan `ThreeWayMerge` oluşturduğundan hücre düzeyinde birleştirme uygulanmaz. Bunun için doğrudan [`ThreeWayMerge`](#threewaymerge) kullanın.

```php
$result = Merql::merge('base', 'ours', 'theirs');
```

### `patch(string $base, string $changes): MergeResult`

İki yönlü birleştirme: değişiklikleri temel duruma uygular. `merge($base, $base, $changes)` ile eşdeğerdir. Eşzamanlı düzenleme olmadığından her zaman temiz sonuç üretir. `merge()` gibi yalnızca sütun düzeyindedir.

```php
$result = Merql::patch('base', 'changes');
```

### `apply(MergeResult $result): ApplyResult`

Temiz birleştirme sonucunu `init()` öğesine geçirilen veritabanında yürütün. `init()` gerektirir. Çözülmemiş çakışmalar kalmışsa `ConflictException` fırlatır.

Sonuçtaki tüm işlemler yürütülür; bu nedenle `merge()` işleminin tam sonucu yalnızca hâlâ temel durumu içeren bir veritabanına temiz biçimde uygulanır. Zaten taraflardan birinin durumunu içeren veritabanında, eksik işlemlerden bir seçkiyi uygulayın; bkz. [Guarded Apply](https://merql.inline0.dev/tr/docs/apply/guarded).

```php
$applied = Merql::apply($result);
echo $applied->rowsAffected();
```

### `plan(string $id, string $base, string $ours, string $theirs, array $metadata = []): MergePlan`

Üç adlandırılmış anlık görüntüden UI için hazır bir birleştirme planı oluşturun. Plan; kararlı işlem kimliklerini, değişiklik grubu kimliklerini, işlem bağlamını, çakışmaları, şema uyuşmazlıklarını, özeti, meta verileri ve plan özetini içerir. Birleştirme, `merge()` içindeki gibi sütun düzeyindedir; hücre düzeyinde birleştirme için hücre düzeyinde birleştirilmiş sonucu `MergePlanBuilder::build()` öğesine geçirin.

```php
$plan = Merql::plan('plan-1', 'base', 'ours', 'theirs', [
    'source' => 'review-ui',
]);
```

### `applyGuarded(MergeResult $result, Snapshot $expectedLive): ApplyResult`

Temiz birleştirme sonucunu, canlı satırlar için iyimser önkoşullarla uygulayın. Güncelleme ve silme işlemleri, mevcut canlı satırların `$expectedLive` ile eşleşmesini gerektirir; ekleme işlemleri hedef kimliğin henüz mevcut olmamasını gerektirir. `$expectedLive` hedef veritabanının anlık görüntüsüdür (ours'u, theirs'ın alındığı veritabanına yükseltirken theirs). Sıfır satırı etkileyen her ifade işlemi geri alır.

```php
use Merql\Snapshot\SnapshotStore;

$applied = Merql::applyGuarded($selectedResult, SnapshotStore::load('theirs'));
```

### `reset(): void`

Dahili bağlantı ve Snapshotter örneklerini temizler. Genellikle testlerde çalıştırmalar arasında durumu sıfırlamak için kullanılır.

---

## Bağlantı

`Merql\Connection`, makul varsayılanlarla bağlantı adaptörleri oluşturur. PDO bağlantılarında hata durumunda istisnalar, ilişkisel dizi getirme modu, benzetimli olmayan prepared statement'lar ve dizgeye dönüştürülmüş getirilen değerler kullanılır. mysqli adaptörü, getirilen değerleri aynı dizge veya null biçiminde normalleştirir.

### `mysql(string $host, string $database, string $username, string $password = '', int $port = 3306, string $charset = 'utf8mb4'): PdoDatabaseConnection`

```php
use Merql\Connection;

$connection = Connection::mysql('127.0.0.1', 'my_app', 'root', 'secret');
```

### `mysqli(string $host, string $database, string $username, string $password = '', int $port = 3306, string $charset = 'utf8mb4'): MysqliDatabaseConnection`

```php
$connection = Connection::mysqli('127.0.0.1', 'my_app', 'root', 'secret');
```

### `sqlite(string $path = ':memory:'): PdoDatabaseConnection`

Bir SQLite bağlantısı oluşturur. `PRAGMA foreign_keys = ON` aracılığıyla yabancı anahtarları otomatik olarak etkinleştirir.

```php
$connection = Connection::sqlite('/var/data/app.sqlite');
$connection = Connection::sqlite(':memory:');
```

### `fromDsn(string $dsn, string $username = '', string $password = ''): PdoDatabaseConnection`

Herhangi bir PDO DSN dizgesiyle bağlanın. merql yalnızca `mysql` ve `sqlite` için sürücüler içerir; diğer DSN'ler bağlantı açar, ancak sürücü `DriverFactory::register()` ile kaydedilmedikçe `Merql::init()`, `Snapshotter` ve uygulayıcılar `Unsupported database driver` fırlatır.

```php
$connection = Connection::fromDsn('mysql:host=localhost;dbname=app', 'root', 'pass');
```

### `fromPdo(PDO $pdo): PdoDatabaseConnection`

Mevcut bir PDO örneğini sarar.

### `fromMysqli(mysqli $mysqli, string $charset = 'utf8mb4'): MysqliDatabaseConnection`

Mevcut bir mysqli örneğini sarar.

### Adaptör sözleşmesi

Tüm adaptörler `Merql\Database\DatabaseConnection` arayüzünü uygular:

```php
interface DatabaseConnection
{
    public function driverName(): string;
    public function execute(string $sql, array $params = []): int;
    public function query(string $sql, array $params = []): array;
    public function scalar(string $sql, array $params = []): ?string;
    public function beginTransaction(): void;
    public function commit(): void;
    public function rollBack(): void;
    public function lastInsertId(): string;
}
```

`execute()`, `query()` ve `scalar()`, `?` yer tutucuları için konumsal `list<scalar|null>` parametrelerini kabul eder. `query()`, `list<array<string, scalar|null>>` döndürür; değerler PDO ve mysqli adaptörlerinde aynı dizge veya null biçimine normalleştirilir.

---

## Snapshotter

`Merql\Snapshot\Snapshotter` veritabanı durumunu yakalar. Cepheden farklı olarak filtreler üzerinde tam denetim sağlar ve otomatik kaydetme yapmaz.

### `__construct(DatabaseConnection $connection, ?Driver $driver = null, ?IdentityRuleSet $identityRules = null)`

Belirtilmemişse sürücü, bağlantı kimliğinden otomatik algılanır. Tabloya özgü satır kimliği şema varsayılanını geçersiz kılacaksa bir `IdentityRuleSet` sağlayın.

### `capture(string $name, array $tables = [], array $filters = []): Snapshot`

Geçerli durumu yakalar. Kapsamı sınırlamak için tablo adları verin. Tabloları, sütunları veya satırları hariç tutmak için filtre nesneleri sağlayın.

```php
use Merql\Snapshot\Snapshotter;
use Merql\Filter\TableFilter;
use Merql\Filter\ColumnFilter;
use Merql\Filter\RowFilter;
use Merql\Identity\IdentityRule;
use Merql\Identity\IdentityRuleSet;

$snapshotter = new Snapshotter(
    $connection,
    identityRules: new IdentityRuleSet([
        'wp_options' => IdentityRule::natural(['option_name']),
    ]),
);

// All tables.
$snapshot = $snapshotter->capture('full');

// Specific tables with filters.
$snapshot = $snapshotter->capture('filtered', ['posts', 'users'], [
    TableFilter::exclude(['cache_*', 'sessions']),
    ColumnFilter::ignore(['updated_at', 'created_at']),
    RowFilter::create(fn(string $table, array $row) => $row['status'] !== 'trash'),
]);
```

### `captureAliased(string $name, array $physicalToCanonicalTableMap, array $filters = []): Snapshot`

Fiziksel tabloları kanonik tablo adları altında yakalayın. Aynı mantıksal tablonun farklı ortamlarda farklı fiziksel adları varsa bunu kullanın.

```php
$snapshot = $snapshotter->captureAliased('sandbox', [
    'wp_onumia_abcd_posts' => 'wp_posts',
    'wp_onumia_abcd_postmeta' => 'wp_postmeta',
]);
```

Ortaya çıkan anlık görüntü, fiziksel tablo şemasını, yapılandırılmış kimlik sütunlarını, satır anahtarlarını ve filtreleri korurken kanonik tablo adlarını saklar.

### `fromData(string $name, array $tableData): Snapshot` (statik)

Veritabanı bağlantısı olmadan ham verilerden anlık görüntü oluşturur. Testler veya başka bir kaynaktan veri içe aktarma için kullanışlıdır.

```php
use Merql\Snapshot\Snapshotter;
use Merql\Snapshot\TableSnapshotData;
use Merql\Schema\TableSchema;

$schema = new TableSchema('posts', ['id' => 'int', 'title' => 'varchar'], ['id']);

$snapshot = Snapshotter::fromData('test', [
    'posts' => new TableSnapshotData($schema, [
        ['id' => '1', 'title' => 'Hello'],
        ['id' => '2', 'title' => 'World'],
    ], ['id']),
]);
```

---

## Anlık görüntü

`Merql\Snapshot\Snapshot`, veritabanının tüm durumunu temsil eden salt okunur bir değer nesnesidir.

```php
$snapshot->name;                    // string: snapshot identifier
$snapshot->tables;                  // array<string, TableSnapshot>
$snapshot->tableNames();            // list<string>
$snapshot->hasTable('posts');       // bool
$snapshot->getTable('posts');       // ?TableSnapshot
```

---

## TableSnapshot

`Merql\Snapshot\TableSnapshot`, bir tablonun satırlarını, parmak izlerini ve şemasını içerir.

```php
$table = $snapshot->getTable('posts');

$table->schema;                    // TableSchema
$table->identityColumns;           // list<string>: columns used for row identity
$table->fingerprints;              // array<string, string>: row key to hash
$table->rows;                      // array<string, array<string, mixed>>

$table->rowKeys();                 // list<string>
$table->rowCount();                // int
$table->hasRow('42');              // bool
$table->getRow('42');              // ?array<string, mixed>
$table->getFingerprint('42');      // ?string
```

---

## TableSnapshotData

`Merql\Snapshot\TableSnapshotData`, `Snapshotter::fromData()` için girdi verisidir.

```php
use Merql\Snapshot\TableSnapshotData;
use Merql\Schema\TableSchema;

$data = new TableSnapshotData(
    schema: new TableSchema('posts', ['id' => 'int', 'title' => 'varchar'], ['id']),
    rows: [
        ['id' => '1', 'title' => 'First Post'],
    ],
    identityColumns: ['id'],
);
```

---

## IdentityRule

`Merql\Identity\IdentityRule`, satır anahtarlarını oluşturmak için kullanılan sütunları tanımlar.

```php
use Merql\Identity\IdentityRule;

$primary = IdentityRule::primary(['id']);
$natural = IdentityRule::natural(['option_name']);
$composite = IdentityRule::composite(['object_id', 'term_taxonomy_id']);
$content = IdentityRule::content(['name', 'value']);

$key = $natural->key(['option_name' => 'siteurl']);
// "siteurl"
```

### `forSchema(TableSchema $schema): IdentityRule` (statik)

Şemadan varsayılan kimlik kuralını belirler: birincil anahtar, ilk benzersiz anahtar, ardından içerik yedeği.

### `toArray(): array`

Kuralı `['type' => string, 'columns' => list<string>]` olarak serileştirir.

### `fromArray(array $data): IdentityRule` (statik)

Serileştirilmiş verilerden bir kuralı yeniden oluşturur.

---

## IdentityRuleSet

`Merql\Identity\IdentityRuleSet`, tabloya özgü kimlik geçersiz kılmalarını saklar.

```php
use Merql\Identity\IdentityRule;
use Merql\Identity\IdentityRuleSet;

$rules = new IdentityRuleSet([
    'wp_options' => IdentityRule::natural(['option_name']),
]);

$rule = $rules->ruleFor($schema);
```

### `with(string $table, IdentityRule $rule): IdentityRuleSet`

Bir tablo için geçersiz kılma eklenmiş yeni bir kural kümesi döndürür.

### `conflictsFor(string $table, IdentityRule $rule, array $rows): array`

Bir kural için birden fazla satır aynı anahtarı ürettiğinde `IdentityConflict` girdilerini döndürür.

### `toArray(): array`

Tablo kurallarını JSON ile güvenli bir dizi olarak serileştirir.

### `fromArray(array $data): IdentityRuleSet` (statik)

Serileştirilmiş verilerden bir kural kümesini yeniden oluşturur.

---

## SnapshotStore

`Merql\Snapshot\SnapshotStore`, anlık görüntüleri kalıcı olarak saklar ve JSON dosyaları olarak yükler.

### `setDirectory(string $directory): void`

Depolama dizinini ayarlar. Varsayılan: `.merql/snapshots`.

### `save(Snapshot $snapshot): void`

Bir anlık görüntüyü diske yazar.

### `load(string $name): Snapshot`

Bir anlık görüntüyü adına göre yükler. Bulunamazsa `SnapshotException` fırlatır.

### `exists(string $name): bool`

Bir anlık görüntü dosyasının var olup olmadığını denetler.

### `delete(string $name): void`

Bir anlık görüntü dosyasını kaldırır.

---

## Differ

`Merql\Diff\Differ` iki anlık görüntüyü karşılaştırır ve bir değişiklik kümesi oluşturur.

### `diff(Snapshot $base, Snapshot $current): Changeset`

```php
use Merql\Diff\Differ;

$differ = new Differ();
$changeset = $differ->diff($baseSnapshot, $currentSnapshot);
```

### `valuesEqual(mixed $a, mixed $b): bool` (statik)

İki değeri dizgeye dönüştürerek karşılaştırır. NULL ayrı bir değer olarak ele alınır: `NULL === NULL` doğrudur, `NULL === ''` yanlıştır.

---

## Değişiklik kümesi

`Merql\Diff\Changeset`, satır düzeyindeki işlemlerden oluşan salt okunur bir koleksiyondur.

```php
$changeset->inserts();             // list<RowInsert>
$changeset->updates();             // list<RowUpdate>
$changeset->deletes();             // list<RowDelete>
$changeset->isEmpty();             // bool
$changeset->count();               // int: total operations
$changeset->forTable('posts');     // Changeset: filtered to one table
```

---

## RowInsert, RowUpdate, RowDelete

Tekil satır değişikliklerini temsil eden salt okunur değer nesneleri.

### RowInsert

```php
$insert->table;                    // string
$insert->rowKey;                   // string
$insert->values;                   // array<string, mixed>
```

### RowUpdate

```php
$update->table;                    // string
$update->rowKey;                   // string
$update->columnDiffs;              // list<ColumnDiff>
$update->fullRow;                  // array<string, mixed>: complete current row
$update->columnDiffMap();          // array<string, ColumnDiff>: keyed by column name
```

### RowDelete

```php
$delete->table;                    // string
$delete->rowKey;                   // string
$delete->oldValues;                // array<string, mixed>: values before deletion
```

---

## ColumnDiff

`Merql\Diff\ColumnDiff`, bir satır güncellemesi içindeki tek bir sütun değişikliğini temsil eder.

```php
$diff->column;                     // string
$diff->oldValue;                   // mixed
$diff->newValue;                   // mixed
```

---

## ThreeWayMerge

`Merql\Merge\ThreeWayMerge`, temel birleştirme algoritmasıdır.

### `__construct(?CellMergeConfig $cellMergeConfig = null)`

`CellMergeConfig` geçerek TEXT ve JSON sütunları için hücre düzeyinde birleştirmeyi etkinleştirin.

```php
use Merql\Merge\ThreeWayMerge;
use Merql\CellMerge\CellMergeConfig;

// Default: column-level merge only.
$merge = new ThreeWayMerge();

// With cell-level merge for TEXT and JSON columns.
$merge = new ThreeWayMerge(CellMergeConfig::auto());
```

### `merge(Snapshot $base, Snapshot $ours, Snapshot $theirs): MergeResult`

Üç yönlü birleştirme gerçekleştirir. Değişiklik kümelerini dahili olarak hesaplar (base'den ours'a, base'den theirs'a) ve bunları birleştirir.

```php
$result = $merge->merge($baseSnapshot, $oursSnapshot, $theirsSnapshot);
```

### `patch(Snapshot $base, Snapshot $changes): MergeResult`

İki yönlü birleştirme kısayolu. `merge($base, $base, $changes)` ile eşdeğerdir.

### `schemaMismatches(): array`

Son birleştirme sırasında algılanan şema farklılıkları (anlık görüntüler arasında eklenen veya kaldırılan sütunlar) için `SchemaException[]` döndürür.

---

## MergeResult

`Merql\Merge\MergeResult`, birleştirme sonucunu içeren salt okunur bir değer nesnesidir.

```php
$result->isClean();                // bool: no conflicts
$result->operations();             // list<MergeOperation>
$result->conflicts();              // list<Conflict>
$result->operationCount();         // int
$result->conflictCount();          // int
$result->baseSnapshot();           // ?Snapshot
$result->schemaMismatches();       // list<SchemaException>
$result->hasSchemaMismatches();    // bool
```

---

## MergePlan

`Merql\Plan\MergePlan`, birleştirme için serileştirilebilir bir inceleme modelidir.

```php
$plan->id;                        // string
$plan->baseSnapshot;              // string
$plan->oursSnapshot;              // string
$plan->theirsSnapshot;            // string
$plan->summary;                   // MergePlanSummary
$plan->changeGroups;              // list<MergePlanChangeGroup>
$plan->operations;                // list<MergePlanOperation>
$plan->conflicts;                 // list<MergePlanConflict>
$plan->schemaMismatches;          // list<string>
$plan->hash;                      // string
$plan->metadata;                  // array<string, mixed>
```

Kararlı JSON gidiş dönüşleri için `MergePlanSerializer::toJson()` ve `::fromJson()` kullanın.

## Seçimler

`ChangeGroupSelection`, aşamaya alınmış değişiklik grubu kimliklerini saklar. Seçili birleştirme sonuçları veya geri alma planları oluştururken bunu bir `OperationSelection` biçimine dönüştürün.

```php
use Merql\Plan\ChangeGroupSelection;
use Merql\Plan\SelectedMergeResultFactory;

$selection = ChangeGroupSelection::fromIds([$groupId]);
$operationSelection = $selection->toOperationSelection($plan);

$selected = (new SelectedMergeResultFactory())
    ->fromOperationSelection($plan, $operationSelection);
```

## RollbackPlan

`Merql\Rollback\RollbackPlan`, seçili bir uygulama için ters işlemleri ve sapma beklentilerini saklar.

```php
use Merql\Rollback\RollbackPlanBuilder;
use Merql\Rollback\RollbackPlanSerializer;

$rollback = (new RollbackPlanBuilder())->build(
    'rollback-1',
    $plan,
    $operationSelection,
    $liveBeforeRows,
);

$json = RollbackPlanSerializer::toJson($rollback);
```

Geri almayı uygulamadan önce `RollbackDrift` kullanın; ardından ters işlemleri çalıştırmak için `RollbackPlanApplier` kullanın.

---

## MergeOperation

`Merql\Merge\MergeOperation`, birleştirmeden çözümlenmiş tek bir işlemdir.

```php
$op->type;                         // string: 'insert' | 'update' | 'delete'
$op->table;                        // string
$op->rowKey;                       // string
$op->values;                       // array<string, mixed>
$op->source;                       // string: 'ours' | 'theirs' | 'merged'
```

Tür sabitleri:

```php
MergeOperation::TYPE_INSERT;       // 'insert'
MergeOperation::TYPE_UPDATE;       // 'update'
MergeOperation::TYPE_DELETE;       // 'delete'
```

---

## Çakışma

`Merql\Merge\Conflict`, çözülmemiş bir birleştirme çakışmasını temsil eder.

```php
$conflict->table();                // string
$conflict->rowKey();               // string
$conflict->type();                 // string: 'update_update' | 'update_delete' | 'delete_update' | 'insert_insert'
$conflict->column();               // ?string (null for structural conflicts)
$conflict->oursValue();            // mixed
$conflict->theirsValue();          // mixed
$conflict->baseValue();            // mixed
$conflict->primaryKey(['id']);     // array<string, string>: decoded from rowKey
```

### Çakışma türleri

| Tür | Anlamı |
|---|---|
| `update_update` | İki taraf da aynı sütunu farklı değerlere değiştirdi |
| `update_delete` | Ours, theirs tarafından silinen bir satırı güncelledi |
| `delete_update` | Ours, theirs tarafından güncellenen bir satırı sildi |
| `insert_insert` | İki taraf da aynı birincil anahtara sahip bir satır ekledi |

---

## ConflictResolver

`Merql\Merge\ConflictResolver`, birleştirme sonucundaki tüm çakışmalara bir çözüm ilkesi uygular.

### `resolve(MergeResult $result, ConflictPolicy $policy): MergeResult` (statik)

İlkeye göre çakışmaları çözülmüş yeni bir `MergeResult` döndürür.

```php
use Merql\Merge\ConflictResolver;
use Merql\Merge\ConflictPolicy;

// Accept all "theirs" values when conflicts arise.
$resolved = ConflictResolver::resolve($result, ConflictPolicy::TheirsWins);

// Accept all "ours" values.
$resolved = ConflictResolver::resolve($result, ConflictPolicy::OursWins);

// Return unchanged (for manual inspection).
$resolved = ConflictResolver::resolve($result, ConflictPolicy::Manual);
```

---

## ConflictPolicy

`Merql\Merge\ConflictPolicy`, üç durumu olan bir backed enum'dur.

```php
use Merql\Merge\ConflictPolicy;

ConflictPolicy::OursWins;          // Resolve all conflicts in favor of "ours"
ConflictPolicy::TheirsWins;        // Resolve all conflicts in favor of "theirs"
ConflictPolicy::Manual;            // Leave conflicts unresolved for manual handling
```

---

## ColumnMerge

`Merql\Merge\ColumnMerge`, tek bir satır için sütun başına birleştirme mantığını uygular. Dahili olarak `ThreeWayMerge` tarafından kullanılır.

### `merge(string $table, string $rowKey, array $base, array $ours, array $theirs, ?CellMergeConfig $cellMergeConfig = null, array $columnTypes = []): array` (statik)

`['values' => array, 'conflicts' => list<Conflict>]` döndürür.

```php
use Merql\Merge\ColumnMerge;

$result = ColumnMerge::merge(
    'posts',
    '42',
    ['title' => 'Hello', 'status' => 'draft'],     // base
    ['title' => 'Hello', 'status' => 'published'],  // ours
    ['title' => 'New Title', 'status' => 'draft'],   // theirs
);

// $result['values'] = ['title' => 'New Title', 'status' => 'published']
// $result['conflicts'] = [] (clean merge)
```

---

## Uygulayıcı

`Merql\Apply\Applier`, bir birleştirme sonucunu veritabanına uygular.

### `__construct(DatabaseConnection $connection, ?Driver $driver = null)`

### `apply(MergeResult $result, ?Snapshot $base = null): ApplyResult`

Tüm işlemleri tek bir işlem içinde yürütür. Herhangi bir hata oluşursa geri alır ve hatayı fırlatmak yerine `ApplyResult::errors()` içinde bildirir. Sonuçta çözümlenmemiş çakışmalar varsa `ConflictException` fırlatır.

```php
use Merql\Apply\Applier;

$applier = new Applier($connection);
$applied = $applier->apply($result);

echo "Rows affected: {$applied->rowsAffected()}\n";
if ($applied->hasErrors()) {
    print_r($applied->errors());
}
```

Yabancı anahtar sıralaması otomatik olarak yapılır: eklemeler bağımlılık sırasına, silmeler ters bağımlılık sırasına göre sıralanır.

---

## ApplyResult

`Merql\Apply\ApplyResult`, uygulayıcının döndürdüğü salt okunur bir değer nesnesidir.

```php
$applied->rowsAffected();         // int
$applied->errors();               // list<string>
$applied->hasErrors();            // bool
```

Geri alınan bir uygulamadan sonra `rowsAffected()`, hata oluşmadan önce çalıştırılan ifadeleri saymaya devam eder ([#4](https://github.com/inline0/merql/issues/4)). Sayıya güvenmeden önce `hasErrors()` değerini kontrol edin.

---

## DryRun

`Merql\Apply\DryRun`, hiçbir şeyi yürütmeden insanlar tarafından okunabilir SQL üretir.

### `generate(MergeResult $result, ?Snapshot $base = null, array $fkDependencies = [], ?Driver $driver = null): array` (statik)

Değerleri satır içine eklenmiş SQL dizelerinin listesini döndürür (yalnızca görüntüleme amacıyla).

```php
use Merql\Apply\DryRun;

$statements = DryRun::generate($result);

foreach ($statements as $sql) {
    echo "{$sql};\n";
}

// Output:
// INSERT INTO `posts` (`id`, `title`) VALUES ('10', 'New Post');
// UPDATE `posts` SET `title` = 'Updated' WHERE `id` = '5';
// DELETE FROM `comments` WHERE `id` = '3';
```

---

## SqlGenerator

`Merql\Apply\SqlGenerator`, parametreli SQL ifadeleri üretir. Hem `Applier` hem de `DryRun` tarafından dahili olarak kullanılır.

### `generate(MergeResult $result, ?Snapshot $base = null, array $fkDependencies = [], ?Driver $driver = null): array` (statik)

`list<array{sql: string, params: list<scalar|null>}>` döndürür.

```php
use Merql\Apply\SqlGenerator;

$statements = SqlGenerator::generate($result);

foreach ($statements as $stmt) {
    $connection->execute($stmt['sql'], $stmt['params']);
}
```

---

## CellMergeConfig

`Merql\CellMerge\CellMergeConfig`, belirli sütunlar veya sütun türleri için hücre düzeyindeki birleştirme stratejilerini yapılandırır.

### `auto(): self` (statik)

TEXT/LONGTEXT sütunlarına `TextCellMerger`, JSON sütunlarına ise `JsonCellMerger` atayan kullanışlı bir fabrika.

```php
use Merql\CellMerge\CellMergeConfig;

$config = CellMergeConfig::auto();
```

### `forColumn(string $column, CellMerger $merger): self`

Belirli bir sütuna birleştirici atayın. Nitelikli adlar için `table.column`, tüm tablolar için yalnızca `column` kullanın.

```php
use Merql\CellMerge\CellMergeConfig;
use Merql\CellMerge\TextCellMerger;

$config = (new CellMergeConfig())
    ->forColumn('posts.content', new TextCellMerger())
    ->forColumn('description', new TextCellMerger());
```

### `forType(string $typePattern, CellMerger $merger): self`

Tür desenine uyan tüm sütunlara birleştirici atayın (büyük/küçük harfe duyarsız alt dize eşleşmesi).

```php
use Merql\CellMerge\CellMergeConfig;
use Merql\CellMerge\JsonCellMerger;

$config = (new CellMergeConfig())
    ->forType('json', new JsonCellMerger());
```

### `getMerger(string $table, string $column, string $columnType = ''): CellMerger`

Belirtilen tablo, sütun ve tür için birleştiriciyi arar. Öncelik: nitelikli sütun adı, nitelenmemiş sütun adı, tür deseni, varsayılan (opak).

---

## CellMerger (arayüz)

`Merql\CellMerge\CellMerger`, hücre düzeyindeki birleştirme stratejilerinin arayüzüdür.

```php
use Merql\CellMerge\CellMerger;
use Merql\CellMerge\CellMergeResult;

interface CellMerger
{
    public function merge(mixed $base, mixed $ours, mixed $theirs): CellMergeResult;
}
```

Yerleşik üç uygulama sunulur.

### TextCellMerger

`Merql\CellMerge\TextCellMerger`, çok satırlı metni üç yönlü, satır satır bir fark algoritmasıyla birleştirir (git dosya içeriği için kullandığı algoritmanın aynısı). İki taraf farklı satırları düzenlediğinde birleştirme sorunsuz olur. İkisi de aynı satırı farklı biçimde düzenlerse çakışma bildirir.

```php
use Merql\CellMerge\TextCellMerger;

$merger = new TextCellMerger();
$result = $merger->merge(
    "line 1\nline 2\nline 3",
    "line 1\nline 2 modified\nline 3",
    "line 1\nline 2\nline 3 modified",
);
// $result->clean === true
// $result->value === "line 1\nline 2 modified\nline 3 modified"
```

### JsonCellMerger

`Merql\CellMerge\JsonCellMerger`, JSON değerlerini üst düzey anahtarları bağımsız olarak karşılaştırarak birleştirir. Her anahtar üç yönlü mantıkla birleştirilir. İç içe nesneler, özyinelemeli olarak birleştirilmek yerine opak JSON dizeleri olarak karşılaştırılır.

```php
use Merql\CellMerge\JsonCellMerger;

$merger = new JsonCellMerger();
$result = $merger->merge(
    '{"a": 1, "b": 2}',
    '{"a": 10, "b": 2}',        // changed "a"
    '{"a": 1, "b": 20}',         // changed "b"
);
// $result->clean === true
// $result->value === '{"a":10,"b":20}'
```

### OpaqueCellMerger

`Merql\CellMerge\OpaqueCellMerger` varsayılandır. Değerleri opak dizeler olarak ele alır ve farklı olduklarında her zaman çakışma bildirir.

---

## CellMergeResult

`Merql\CellMerge\CellMergeResult`, tüm hücre birleştiricilerinin dönüş türüdür.

```php
$result->clean;                    // bool: true if merge succeeded
$result->value;                    // mixed: merged value (or ours on conflict)
$result->conflicts;                // int: number of conflicts

// Factory methods.
CellMergeResult::resolved($value);           // clean merge
CellMergeResult::conflict($oursValue, $n);   // conflict with count
```

---

## TableSchema

`Merql\Schema\TableSchema`, tablo yapısının salt okunur bir gösterimidir.

```php
use Merql\Schema\TableSchema;

$schema = new TableSchema(
    name: 'posts',
    columns: ['id' => 'int', 'title' => 'varchar(255)', 'content' => 'text'],
    primaryKey: ['id'],
    uniqueKeys: [['slug']],
);

$schema->name;                     // string
$schema->columns;                  // array<string, string>: name to type
$schema->primaryKey;               // list<string>
$schema->uniqueKeys;               // list<list<string>>
$schema->hasPrimaryKey();          // bool
$schema->hasUniqueKeys();          // bool
$schema->columnNames();            // list<string>
```

---

## Sürücü sistemi

merql, veritabanına özgü işlemleri soyutlamak için takılabilir bir sürücü sistemi kullanır. Sürücüler, bağlantı sürücüsü kimliğine göre otomatik algılanır.

### Driver (arayüz)

`Merql\Driver\Driver`, tüm veritabanı sürücülerinin uygulaması gereken sözleşmeyi tanımlar.

```php
interface Driver
{
    public function quoteIdentifier(string $name): string;
    public function listTables(DatabaseConnection $connection): array;
    public function readSchema(DatabaseConnection $connection, string $table): TableSchema;
    public function readForeignKeys(DatabaseConnection $connection): array;
    public function selectAll(string $table): string;
}
```

Yerleşik uygulamalar: `MysqlDriver` ve `SqliteDriver`.

### DriverFactory

`Merql\Driver\DriverFactory`, bir bağlantıdan sürücüyü otomatik algılar.

```php
use Merql\Driver\DriverFactory;

$driver = DriverFactory::create($connection);
```

Diğer veritabanları için özel bir sürücü kaydedin:

```php
DriverFactory::register('pgsql', MyPostgresDriver::class);
```

---

## Filtreler

### TableFilter

`Merql\Filter\TableFilter`, glob desenlerini kullanarak tabloları dahil eder veya hariç tutar.

```php
use Merql\Filter\TableFilter;

$filter = TableFilter::exclude(['cache_*', 'sessions', 'temp_*']);
$filter = TableFilter::include(['posts', 'users', 'comments']);
```

### ColumnFilter

`Merql\Filter\ColumnFilter`, belirli sütunları anlık görüntülerden çıkarır.

```php
use Merql\Filter\ColumnFilter;

$filter = ColumnFilter::ignore(['updated_at', 'created_at', 'modified_date']);
```

### RowFilter

`Merql\Filter\RowFilter`, bir koşul işlevi kullanarak satırları filtreler.

```php
use Merql\Filter\RowFilter;

$filter = RowFilter::create(function (string $table, array $row): bool {
    // Exclude trashed posts.
    if ($table === 'posts' && ($row['status'] ?? '') === 'trash') {
        return false;
    }
    return true;
});
```

---

## İstisnalar

### SnapshotException

`Merql\Exceptions\SnapshotException`, bir anlık görüntü bulunamadığında veya geçersiz bir adı olduğunda fırlatılır.

```php
SnapshotException::notFound('baseline', '/path/to/baseline.json');
```

### MergeException

`Merql\Exceptions\MergeException`, bir birleştirme için gerekli anlık görüntü eksik olduğunda fırlatılır.

```php
MergeException::snapshotRequired('base');
```

### ConflictException

`Merql\Exceptions\ConflictException`, çözümlenmemiş çakışmalar içeren bir birleştirme sonucunu uygulamaya çalışırken fırlatılır.

```php
ConflictException::unresolved(3);
// Message: "Cannot apply merge with 3 unresolved conflict(s)"
```

### SchemaException

`Merql\Exceptions\SchemaException`, anlık görüntüler arasında şema farkları olduğunda fırlatılır (veya toplanır).

```php
SchemaException::mismatch('posts', 'column "tags" exists in current but not in base');
```

Şema uyuşmazlıkları birleştirmeyi durdurmaz. İncelenmek üzere toplanır ve `$result->schemaMismatches()` üzerinden erişilebilir.
