
# PHP API referencia

A merql összes nyilvános osztályának és metódusának teljes referenciája.

## Merql (homlokzat)

A `Merql\Merql` a gyakori műveletek statikus belépési pontja. Az alacsonyabb szintű osztályokat burkolja be, és automatikusan kezeli a pillanatképek megőrzését.

```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`

Inicializálja a homlokzatot egy adatbázis-kapcsolattal. A `snapshot()`, `apply()` vagy `applyGuarded()` előtt meg kell hívni; hívja meg újra adatbázis-váltáshoz, például hogy két különböző példányból készítsen pillanatképet a saját és az ő oldaláról. `$driver` nélkül a `DriverFactory::create()` metódust hívja meg, amely kivételt dob a MySQL és a SQLite kivételével minden motor esetén, ha nincs regisztrált illesztőprogram. Az automatikus felismerés felülbírálásához adjon meg illesztőprogramot, a pillanatkép rögzítésekor pedig táblánkénti sorazonosítás felülbírálásához adjon meg egy azonosítási szabálykészletet.

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

Rögzíti az adatbázis aktuális állapotát, és lemezre menti. Adjon meg táblaneveket tartalmazó tömböt az adott táblák pillanatképéhez, vagy hagyja el az összes tábla felvételéhez.

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

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

Betölt két elnevezett pillanatképet, és kiszámítja a köztük lévő változáskészletet. Nem igényli a `init()` használatát, mivel mentett pillanatképekből dolgozik.

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

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

Háromutas összevonás három elnevezett pillanatképből. Olyan eredményt ad vissza, amely tartalmazza az ütközésmentes műveleteket és az esetleges ütközéseket. Oszlopszinten von össze: a homlokzat `ThreeWayMerge` objektumot hoz létre `CellMergeConfig` nélkül, ezért a cellaszintű összevonás nem történik meg. Ehhez közvetlenül a [`ThreeWayMerge`](#threewaymerge) elemet használja.

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

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

Kétutas összevonás: a változtatások alkalmazása az alapállapotra. A `merge($base, $base, $changes)` művelettel egyenértékű. Mindig ütközésmentes eredményt ad, mivel nincs párhuzamos szerkesztés. A `merge()`-hez hasonlóan csak oszlopszinten működik.

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

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

Ütközésmentes összevonási eredményt hajt végre a `init()` metódusnak átadott adatbázison. A `init()` szükséges hozzá. `ConflictException` kivételt dob, ha feloldatlan ütközések maradnak.

Az eredmény minden műveletét végrehajtja, ezért a `merge()` teljes eredménye csak olyan adatbázison alkalmazható ütközésmentesen, amely még az alapállapotot tartalmazza. Ha az adatbázis már az egyik oldal állapotát tartalmazza, alkalmazza a hiányzó műveletek egy részhalmazát; lásd a [Feltételes alkalmazás](https://merql.inline0.dev/hu/docs/apply/guarded) részt.

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

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

Három elnevezett pillanatképből UI-kompatibilis összevonási tervet készít. A terv stabil műveletazonosítókat, változáscsoport-azonosítókat, műveleti környezetet, ütközéseket, sémabeli eltéréseket, összefoglalót, metaadatokat és tervkivonatot tartalmaz. Az összevonás oszlopszinten történik, a `merge()` művelethez hasonlóan; cellaszintű összevonáshoz adjon át cellaszinten összevont eredményt a `MergePlanBuilder::build()` műveletnek.

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

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

Ütközésmentes összevonási eredményt alkalmaz optimista, élő sorokra vonatkozó előfeltételekkel. Frissítés és törlés esetén az aktuális élő soroknak egyezniük kell a `$expectedLive` értékével; beszúrás esetén a célazonosító még nem létezhet. A `$expectedLive` a céladatbázis pillanatképe (az ő oldali, amikor a saját állapotunkat abba az adatbázisba emeljük át, amelyről az ő pillanatképe készült). Ha bármelyik utasítás nulla sort érint, a tranzakció visszagörgetésre kerül.

```php
use Merql\Snapshot\SnapshotStore;

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

### `reset(): void`

Törli a belső kapcsolat- és Snapshotter-példányokat. Elsősorban tesztekben használatos, hogy a futtatások között visszaállítsa az állapotot.

---

## Kapcsolat

A `Merql\Connection` ésszerű alapbeállításokkal hoz létre kapcsolati adaptereket. A PDO-kapcsolatok hibánál kivételeket használnak, asszociatív lekérési módot állítanak be, letiltják az emulált előkészített utasításokat, és szövegként kérik le az értékeket. A mysqli-adapter a lekért értékeket ugyanarra a szöveg vagy null alakra normalizálja.

### `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`

Létrehoz egy SQLite-kapcsolatot. Automatikusan engedélyezi az idegen kulcsokat a `PRAGMA foreign_keys = ON` segítségével.

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

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

Bármilyen PDO DSN-karakterlánccal csatlakozik. A merql csak a `mysql` és a `sqlite` illesztőprogramját tartalmazza; más DSN-ekkel is létrejön a kapcsolat, de a `Merql::init()`, a `Snapshotter` és az alkalmazók `Unsupported database driver` kivételt dobnak, ha nincs illesztőprogram regisztrálva a `DriverFactory::register()` metódussal.

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

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

Meglévő PDO-példány beburkolása.

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

Meglévő mysqli-példány beburkolása.

### Adapterinterfész

Minden adapter megvalósítja a `Merql\Database\DatabaseConnection` interfészt:

```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;
}
```

A `execute()`, a `query()` és a `scalar()` pozicionális `list<scalar|null>` paramétereket fogad el a `?` helyőrzőkhöz. A `query()` `list<array<string, scalar|null>>` értéket ad vissza; a PDO- és mysqli-adapterek értékei egyaránt szöveg vagy null alakra vannak normalizálva.

---

## Snapshotter

A `Merql\Snapshot\Snapshotter` rögzíti az adatbázis állapotát. A homlokzattal ellentétben teljes vezérlést ad a szűrők felett, és nem ment automatikusan.

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

Ha nincs megadva, az illesztőprogramot a rendszer automatikusan, a kapcsolat azonosítója alapján ismeri fel. Adjon meg egy `IdentityRuleSet` objektumot, ha a táblaspecifikus sorazonosításnak felül kell írnia a séma alapértelmezéseit.

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

Rögzíti az aktuális állapotot. A hatókör korlátozásához adjon meg táblaneveket. A táblák, oszlopok vagy sorok kizárásához adjon meg szűrőobjektumokat.

```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`

Fizikai táblákat rögzít kanonikus táblaneveken. Akkor használja, ha ugyanannak a logikai táblának eltérő fizikai neve van a különböző környezetekben.

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

Az eredményül kapott pillanatkép kanonikus táblaneveket tárol, miközben megőrzi a fizikai táblasémát, a beállított azonosítóoszlopokat, a sorazonosítókat és a szűrőket.

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

Adatokból készít pillanatképet adatbázis-kapcsolat nélkül. Teszteléshez vagy más forrásból származó adatok importálásához hasznos.

```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']),
]);
```

---

## Pillanatkép

A `Merql\Snapshot\Snapshot` egy csak olvasható értékobjektum, amely egy teljes adatbázis-állapotot képvisel.

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

---

## TableSnapshot

A `Merql\Snapshot\TableSnapshot` egy tábla sorait, ujjlenyomatait és sémáját tárolja.

```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

A `Merql\Snapshot\TableSnapshotData` a `Snapshotter::fromData()` bemeneti adata.

```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

A `Merql\Identity\IdentityRule` határozza meg a sorazonosítók létrehozásához használt oszlopokat.

```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` (statikus)

Az alapértelmezett azonosítási szabály meghatározása a sémából: elsődleges kulcs, első egyedi kulcs, majd tartalomalapú tartalékmegoldás.

### `toArray(): array`

A szabály sorosítása `['type' => string, 'columns' => list<string>]` formátumban.

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

Szabály létrehozása sorosított adatokból.

---

## IdentityRuleSet

A `Merql\Identity\IdentityRuleSet` tárolja a táblánkénti azonosítási felülbírálásokat.

```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`

Új szabálykészletet ad vissza egy táblához hozzáadott felülbírálással.

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

A `IdentityConflict` bejegyzéseket adja vissza, ha egy szabály alapján több sorhoz ugyanaz a kulcs jön létre.

### `toArray(): array`

Táblaszabályok sorosítása JSON-kompatibilis tömbként.

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

Szabálykészlet létrehozása sorosított adatokból.

---

## SnapshotStore

A `Merql\Snapshot\SnapshotStore` pillanatképeket tartósan tárol, és JSON fájlként tölti be őket.

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

Beállítja a tárolási könyvtárat. Alapértelmezése: `.merql/snapshots`.

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

Pillanatkép lemezre írása.

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

Pillanatkép betöltése név alapján. `SnapshotException` kivételt dob, ha nem található.

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

Ellenőrzi, hogy létezik-e a pillanatképfájl.

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

Eltávolít egy pillanatképfájlt.

---

## Eltérésvizsgáló

A `Merql\Diff\Differ` két pillanatképet hasonlít össze, és változáskészletet állít elő.

### `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` (statikus)

Két értéket hasonlít össze karakterlánccá alakítva. A NULL különálló értéknek számít: a `NULL === NULL` igaz, a `NULL === ''` hamis.

---

## Változáskészlet

A `Merql\Diff\Changeset` sorok szintjén végrehajtott műveletek csak olvasható gyűjteménye.

```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

Egyedi sorváltozásokat képviselő, csak olvasható értékobjektumok.

### 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

A `Merql\Diff\ColumnDiff` egy sorfrissítésen belüli oszlopváltozást képvisel.

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

---

## ThreeWayMerge

A `Merql\Merge\ThreeWayMerge` az összevonási algoritmus magja.

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

Adjon át egy `CellMergeConfig` objektumot a TEXT és JSON oszlopok cellaszintű összevonásának engedélyezéséhez.

```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`

Háromutas összevonást hajt végre. Belsőleg kiszámítja a változáskészleteket (az alapállapot és a sajátunk, valamint az alapállapot és az övék között), majd összevonja őket.

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

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

Kétutas összevonást megvalósító rövidített eljárás. A `merge($base, $base, $changes)` művelettel egyenértékű.

### `schemaMismatches(): array`

Visszaadja az `SchemaException[]` értéket a legutóbbi egyesítés során észlelt bármilyen sémabeli eltérés esetén (a pillanatképek között hozzáadott vagy eltávolított oszlopok).

---

## MergeResult

A `Merql\Merge\MergeResult` csak olvasható értékobjektum, amely az összevonás eredményét tartalmazza.

```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

A `Merql\Plan\MergePlan` az összevonás szerializálható áttekintési modellje.

```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>
```

A stabil JSON körutakhoz használja a `MergePlanSerializer::toJson()` és a `::fromJson()` elemet.

## Kijelölések

A `ChangeGroupSelection` tárolja az előkészített változáscsoport-azonosítókat. Alakítsa át `OperationSelection` objektummá kijelölt összevonási eredmények vagy visszaállítási tervek létrehozásakor.

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

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

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

## RollbackPlan

A `Merql\Rollback\RollbackPlan` egy kijelölt alkalmazáshoz szükséges inverz műveleteket és eltérési elvárásokat tárolja.

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

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

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

A visszaállítás alkalmazása előtt használja a `RollbackDrift` elemet, majd az inverz műveletek futtatásához a `RollbackPlanApplier` elemet.

---

## MergeOperation

A `Merql\Merge\MergeOperation` egyetlen, az összevonásból feloldott művelet.

```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ípuskonstansok:

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

---

## Ütközés

A `Merql\Merge\Conflict` egy feloldatlan összevonási ütközést képvisel.

```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
```

### Ütközéstípusok

| Típus | Jelentés |
|---|---|
| `update_update` | Mindkét oldal ugyanazt az oszlopot módosította, de eltérő értékre |
| `update_delete` | A saját oldalunk frissített egy sort, amelyet az ő oldaluk törölt |
| `delete_update` | A saját oldalunk törölt egy sort, amelyet az ő oldaluk frissített |
| `insert_insert` | Mindkét oldal azonos elsődleges kulccsal szúrt be egy sort |

---

## ConflictResolver

A `Merql\Merge\ConflictResolver` feloldási szabályzatot alkalmaz egy összevonás eredményének összes ütközésére.

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

Új `MergeResult` objektumot ad vissza a szabályzat szerint feloldott ütközésekkel.

```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

A `Merql\Merge\ConflictPolicy` három esetet tartalmazó backed enum.

```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

A `Merql\Merge\ColumnMerge` egyetlen sor oszloponkénti összevonási logikáját hajtja végre. Belső használatára a `ThreeWayMerge` szolgál.

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

Visszaadja a `['values' => array, 'conflicts' => list<Conflict>]` értéket.

```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)
```

---

## Alkalmazó

A `Merql\Apply\Applier` adatbázison hajt végre összevonási eredményt.

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

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

Az összes műveletet egyetlen tranzakcióban hajtja végre. Hiba esetén visszagörget, és az állapotot a `ApplyResult::errors()` értékében jelenti, kivétel dobása helyett. `ConflictException` kivételt dob, ha az eredményben feloldatlan ütközések vannak.

```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());
}
```

Az idegen kulcsok sorrendjét automatikusan kezeli: a beszúrásokat függőségi sorrendbe rendezi, a törléseket pedig fordított függőségi sorrendbe.

---

## ApplyResult

A `Merql\Apply\ApplyResult` az alkalmazó által visszaadott, csak olvasható értékobjektum.

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

A visszagörgetett alkalmazás után a `rowsAffected()` továbbra is számolja a hiba előtt lefutott utasításokat ([#4](https://github.com/inline0/merql/issues/4)). Mielőtt megbízna a számban, ellenőrizze a `hasErrors()` értékét.

---

## DryRun

A `Merql\Apply\DryRun` ember által olvasható SQL utasításokat állít elő végrehajtás nélkül.

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

Visszaadja az SQL karakterláncok listáját beillesztett értékekkel (kizárólag megjelenítésre).

```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

A `Merql\Apply\SqlGenerator` paraméterezett SQL utasításokat állít elő. Belső használatára a `Applier` és a `DryRun` is ezt használja.

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

Visszaadja a `list<array{sql: string, params: list<scalar|null>}>` értéket.

```php
use Merql\Apply\SqlGenerator;

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

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

---

## CellMergeConfig

A `Merql\CellMerge\CellMergeConfig` cellaszintű összevonási stratégiákat rendel adott oszlopokhoz vagy oszloptípusokhoz.

### `auto(): self` (statikus)

Kényelmi gyárfüggvény, amely a `TextCellMerger` elemet a TEXT/LONGTEXT oszlopokhoz, a `JsonCellMerger` elemet pedig a JSON oszlopokhoz rendeli.

```php
use Merql\CellMerge\CellMergeConfig;

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

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

Összevonó hozzárendelése egy adott oszlophoz. Minősített névhez használja a `table.column` értéket, az összes táblához pedig csak a `column` értéket.

```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`

Összevonó hozzárendelése minden olyan oszlophoz, amely megfelel egy típusmintának (kis- és nagybetűket nem megkülönböztető részkarakterlánc-egyezés).

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

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

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

Megkeresi az adott táblához, oszlophoz és típushoz tartozó összevonót. Sorrend: minősített oszlopnév, minősítés nélküli oszlopnév, típusminta, alapértelmezett (átlátszatlan).

---

## CellMerger (interfész)

A `Merql\CellMerge\CellMerger` a cellaszintű összevonási stratégiák interfésze.

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

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

Három beépített megvalósítás áll rendelkezésre.

### TextCellMerger

Az `Merql\CellMerge\TextCellMerger` háromutas, sorról sorra végzett különbségvizsgálattal egyesíti a többsoros szöveget (ugyanazzal az algoritmussal, amelyet az git fájltartalomhoz használ). Ha a két oldal különböző sorokat szerkeszt, az egyesítés tiszta. Ha ugyanazt a sort eltérően módosítják, ütközést jelez.

```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

A `Merql\CellMerge\JsonCellMerger` a JSON értékeket úgy vonja össze, hogy külön-külön hasonlítja össze a legfelső szintű kulcsokat. Minden kulcs összevonása háromutas logikával történik. A beágyazott objektumokat átlátszatlan JSON karakterláncként hasonlítja össze (nem vonja össze rekurzívan).

```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

A `Merql\CellMerge\OpaqueCellMerger` az alapértelmezett. Az értékeket átlátszatlan karakterláncként kezeli, és eltérés esetén mindig ütközést jelez.

---

## CellMergeResult

A `Merql\CellMerge\CellMergeResult` az összes cellaösszevonó visszatérési típusa.

```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

A `Merql\Schema\TableSchema` a táblaszerkezet csak olvasható ábrázolása.

```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>
```

---

## Illesztőprogram-rendszer

A merql csatlakoztatható illesztőprogram-rendszerrel választja el az adatbázis-specifikus műveleteket. Az illesztőprogramokat a kapcsolat illesztőprogram-azonosítója alapján automatikusan ismeri fel.

### Driver (interfész)

A `Merql\Driver\Driver` határozza meg az összes adatbázis-illesztőprogram által megvalósítandó szerződést.

```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;
}
```

Beépített megvalósítások: `MysqlDriver` és `SqliteDriver`.

### DriverFactory

A `Merql\Driver\DriverFactory` automatikusan felismeri az illesztőprogramot a kapcsolatból.

```php
use Merql\Driver\DriverFactory;

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

Egyéni illesztőprogram regisztrálása más adatbázisokhoz:

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

---

## Szűrők

### TableFilter

A `Merql\Filter\TableFilter` globminták alapján vesz fel vagy zár ki táblákat.

```php
use Merql\Filter\TableFilter;

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

### ColumnFilter

A `Merql\Filter\ColumnFilter` adott oszlopokat távolít el a pillanatképekből.

```php
use Merql\Filter\ColumnFilter;

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

### RowFilter

A `Merql\Filter\RowFilter` predikátumfüggvénnyel szűri a sorokat.

```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;
});
```

---

## Kivételek

### SnapshotException

A `Merql\Exceptions\SnapshotException` akkor dobódik, ha egy pillanatkép nem található vagy érvénytelen a neve.

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

### MergeException

A `Merql\Exceptions\MergeException` akkor dobódik, ha egy összevonáshoz szükséges pillanatkép hiányzik.

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

### ConflictException

`Merql\Exceptions\ConflictException` keletkezik, amikor feloldatlan ütközéseket tartalmazó egyesítési eredményt próbálnak alkalmazni.

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

### SchemaException

`Merql\Exceptions\SchemaException` keletkezik (vagy kerül összegyűjtésre), ha a pillanatképek sémái eltérnek.

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

A sémák eltérései nem állítják le az egyesítést. A rendszer összegyűjti őket, és a `$result->schemaMismatches()` segítségével megvizsgálhatók.
