
# Αναφορά PHP API

Πλήρης αναφορά για όλες τις δημόσιες κλάσεις και μεθόδους του merql.

## Merql (πρόσοψη)

Το `Merql\Merql` είναι το στατικό σημείο εισόδου για συνήθεις λειτουργίες. Περιτυλίγει τις κλάσεις χαμηλότερου επιπέδου και διαχειρίζεται αυτόματα τη διατήρηση στιγμιότυπων.

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

Αρχικοποιήστε την πρόσοψη με μια σύνδεση βάσης δεδομένων. Πρέπει να κληθεί πριν από τα
`snapshot()`, `apply()` ή `applyGuarded()`· καλέστε την ξανά για εναλλαγή βάσεων δεδομένων,
για παράδειγμα για να δημιουργήσετε στιγμιότυπα των ours και theirs από δύο διαφορετικά αντίγραφα. Χωρίς `$driver`, καλεί το `DriverFactory::create()`, το οποίο προκαλεί εξαίρεση για μηχανές εκτός από MySQL και SQLite, εκτός αν έχει καταχωριστεί πρόγραμμα οδήγησης. Περάστε ένα πρόγραμμα οδήγησης για να παρακάμψετε τον αυτόματο εντοπισμό ή ένα σύνολο κανόνων ταυτοποίησης για να παρακάμψετε την ταυτότητα γραμμών ανά πίνακα κατά τη λήψη στιγμιότυπου.

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

Καταγράψτε την τρέχουσα κατάσταση της βάσης δεδομένων και αποθηκεύστε την στον δίσκο. Περάστε έναν πίνακα ονομάτων για να δημιουργήσετε στιγμιότυπο συγκεκριμένων πινάκων ή παραλείψτε τον για όλους τους πίνακες.

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

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

Φορτώστε δύο στιγμιότυπα με όνομα και υπολογίστε το σύνολο αλλαγών μεταξύ τους. Δεν απαιτείται το `init()`, καθώς λειτουργεί με αποθηκευμένα στιγμιότυπα.

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

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

Συγχώνευση τριών στιγμιότυπων τριών κατευθύνσεων. Επιστρέφει αποτέλεσμα με καθαρές λειτουργίες και τυχόν διενέξεις. Συγχωνεύει σε επίπεδο στηλών: η πρόσοψη δημιουργεί το `ThreeWayMerge` χωρίς `CellMergeConfig`, επομένως δεν εφαρμόζεται συγχώνευση σε επίπεδο κελιού. Χρησιμοποιήστε απευθείας το [`ThreeWayMerge`](#threewaymerge) γι' αυτό.

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

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

Συγχώνευση δύο κατευθύνσεων: εφαρμογή αλλαγών στο base. Ισοδυναμεί με το `merge($base, $base, $changes)`. Παράγει πάντα καθαρό αποτέλεσμα, καθώς δεν υπάρχουν ταυτόχρονες επεξεργασίες. Μόνο σε επίπεδο στηλών, όπως το `merge()`.

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

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

Εκτελέστε ένα καθαρό αποτέλεσμα συγχώνευσης στη βάση δεδομένων που περάστηκε στο `init()`. Απαιτείται το `init()`. Προκαλεί εξαίρεση `ConflictException` αν παραμένουν ανεπίλυτες διενέξεις.

Εκτελείται κάθε λειτουργία του αποτελέσματος, επομένως ολόκληρο το αποτέλεσμα του `merge()` εφαρμόζεται ομαλά μόνο σε βάση δεδομένων που εξακολουθεί να έχει την κατάσταση base. Για βάση δεδομένων που έχει ήδη την κατάσταση μιας πλευράς, εφαρμόστε επιλεγμένες λειτουργίες που της λείπουν· δείτε την ενότητα [Guarded Apply](https://merql.inline0.dev/el/docs/apply/guarded).

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

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

Δημιουργήστε σχέδιο συγχώνευσης έτοιμο για UI από τρία στιγμιότυπα με όνομα. Το σχέδιο περιλαμβάνει σταθερά ID λειτουργιών, ID ομάδων αλλαγών, περιβάλλον λειτουργιών, διενέξεις, ασυμφωνίες σχήματος, σύνοψη, μεταδεδομένα και κατακερματισμό σχεδίου. Η συγχώνευση γίνεται σε επίπεδο στηλών, όπως στο `merge()`· περάστε αποτέλεσμα συγχώνευσης κελιών στο `MergePlanBuilder::build()` για συγχώνευση σε επίπεδο κελιού.

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

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

Εφαρμόστε ένα καθαρό αποτέλεσμα συγχώνευσης με αισιόδοξες προϋποθέσεις στις ζωντανές γραμμές. Οι ενημερώσεις και οι διαγραφές απαιτούν οι τρέχουσες ζωντανές γραμμές να αντιστοιχούν στο `$expectedLive`· για τις εισαγωγές απαιτείται να μην υπάρχει ήδη η ταυτότητα-στόχος. Το `$expectedLive` είναι στιγμιότυπο της βάσης δεδομένων-στόχου (theirs, όταν προωθείτε το ours στη βάση από την οποία λήφθηκε το theirs). Κάθε εντολή που επηρεάζει μηδέν γραμμές προκαλεί rollback της συναλλαγής.

```php
use Merql\Snapshot\SnapshotStore;

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

### `reset(): void`

Καθαρίστε τις εσωτερικές συνδέσεις και τις παρουσίες Snapshotter. Χρησιμοποιείται κυρίως στις δοκιμές για επαναφορά της κατάστασης μεταξύ εκτελέσεων.

---

## Σύνδεση

Το `Merql\Connection` δημιουργεί προσαρμογείς σύνδεσης με κατάλληλες προεπιλογές. Οι συνδέσεις PDO χρησιμοποιούν εξαιρέσεις σε περίπτωση σφάλματος, συσχετισμένη λειτουργία ανάκτησης, απενεργοποιημένες προσομοιωμένες προετοιμασμένες εντολές και ανακτημένες τιμές ως συμβολοσειρές. Ο προσαρμογέας mysqli κανονικοποιεί τις ανακτημένες τιμές στην ίδια μορφή συμβολοσειράς ή null.

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

Δημιουργεί σύνδεση SQLite. Ενεργοποιεί αυτόματα τα ξένα κλειδιά μέσω του `PRAGMA foreign_keys = ON`.

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

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

Συνδεθείτε με οποιαδήποτε συμβολοσειρά DSN του PDO. Το merql παρέχει προγράμματα οδήγησης μόνο για τα `mysql` και `sqlite`· με άλλα DSN η σύνδεση ανοίγει, αλλά τα `Merql::init()`, `Snapshotter` και οι appliers προκαλούν `Unsupported database driver`, εκτός αν καταχωριστεί πρόγραμμα οδήγησης με το `DriverFactory::register()`.

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

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

Περιτυλίξτε μια υπάρχουσα παρουσία PDO.

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

Περιτυλίξτε μια υπάρχουσα παρουσία mysqli.

### Σύμβαση προσαρμογέα

Όλοι οι προσαρμογείς υλοποιούν το `Merql\Database\DatabaseConnection`:

```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()` και `scalar()` δέχονται παραμέτρους `list<scalar|null>` κατά θέση για placeholders `?`. Το `query()` επιστρέφει `list<array<string, scalar|null>>`· οι τιμές κανονικοποιούνται στην ίδια μορφή συμβολοσειράς ή null στους προσαρμογείς PDO και mysqli.

---

## Εργαλείο λήψης στιγμιότυπων

Το `Merql\Snapshot\Snapshotter` καταγράφει την κατάσταση της βάσης δεδομένων. Σε αντίθεση με την πρόσοψη, σας δίνει πλήρη έλεγχο στα φίλτρα και δεν αποθηκεύει αυτόματα.

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

Το πρόγραμμα οδήγησης εντοπίζεται αυτόματα από την ταυτότητα σύνδεσης, αν δεν δοθεί. Περάστε ένα
`IdentityRuleSet` όταν η ταυτότητα γραμμών ανά πίνακα πρέπει να παρακάμπτει τις προεπιλογές του σχήματος.

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

Καταγράψτε την τρέχουσα κατάσταση. Περάστε ονόματα πινάκων για περιορισμό του πεδίου εφαρμογής. Περάστε αντικείμενα φίλτρων για να εξαιρέσετε πίνακες, στήλες ή γραμμές.

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

Καταγράψτε φυσικούς πίνακες με κανονικά ονόματα πινάκων. Χρησιμοποιήστε το όταν ο ίδιος λογικός πίνακας έχει διαφορετικά φυσικά ονόματα σε διαφορετικά περιβάλλοντα.

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

Το στιγμιότυπο που προκύπτει αποθηκεύει τα κανονικά ονόματα πινάκων, διατηρώντας παράλληλα το σχήμα φυσικών πινάκων, τις διαμορφωμένες στήλες ταυτοποίησης, τα κλειδιά γραμμών και τα φίλτρα.

### `fromData(string $name, array $tableData): Snapshot` (στατικό)

Δημιουργήστε ένα στιγμιότυπο από ακατέργαστα δεδομένα χωρίς σύνδεση σε βάση δεδομένων. Χρήσιμο για δοκιμές ή για εισαγωγή δεδομένων από άλλη πηγή.

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

---

## Στιγμιότυπο

Το `Merql\Snapshot\Snapshot` είναι ένα αντικείμενο τιμής μόνο για ανάγνωση που αναπαριστά μια πλήρη κατάσταση βάσης δεδομένων.

```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` περιέχει τις γραμμές, τα αποτυπώματα και το σχήμα ενός πίνακα.

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

```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` ορίζει τις στήλες που χρησιμοποιούνται για τη δημιουργία κλειδιών γραμμών.

```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` (στατικό)

Επιλύει τον προεπιλεγμένο κανόνα ταυτότητας από το σχήμα: πρωτεύον κλειδί, πρώτο μοναδικό κλειδί,
έπειτα εναλλακτική βάσει περιεχομένου.

### `toArray(): array`

Σειριοποιεί τον κανόνα ως `['type' => string, 'columns' => list<string>]`.

### `fromArray(array $data): IdentityRule` (στατικό)

Δημιουργεί έναν κανόνα από σειριοποιημένα δεδομένα.

---

## IdentityRuleSet

Το `Merql\Identity\IdentityRuleSet` αποθηκεύει παρακάμψεις ταυτότητας ανά πίνακα.

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

Επιστρέφει ένα νέο σύνολο κανόνων με μια παράκαμψη για έναν πίνακα.

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

Επιστρέφει τις εγγραφές `IdentityConflict` όταν πολλές γραμμές παράγουν το ίδιο κλειδί για έναν
κανόνα.

### `toArray(): array`

Σειριοποιεί τους κανόνες πινάκων ως πίνακα ασφαλή για JSON.

### `fromArray(array $data): IdentityRuleSet` (στατικό)

Δημιουργεί ένα σύνολο κανόνων από σειριοποιημένα δεδομένα.

---

## SnapshotStore

Το `Merql\Snapshot\SnapshotStore` αποθηκεύει και φορτώνει στιγμιότυπα ως αρχεία JSON.

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

Ορίζει τον κατάλογο αποθήκευσης. Η προεπιλογή είναι `.merql/snapshots`.

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

Εγγράφει ένα στιγμιότυπο στον δίσκο.

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

Φορτώνει ένα στιγμιότυπο με βάση το όνομά του. Αν δεν βρεθεί, προκαλείται το `SnapshotException`.

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

Ελέγχει αν υπάρχει αρχείο στιγμιότυπου.

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

Αφαιρεί ένα αρχείο στιγμιότυπου.

---

## Διαφορές

Το `Merql\Diff\Differ` συγκρίνει δύο στιγμιότυπα και παράγει ένα σύνολο αλλαγών.

### `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` (στατικό)

Συγκρίνει δύο τιμές μετατρέποντάς τες σε συμβολοσειρές. Το NULL αντιμετωπίζεται ως διακριτή τιμή: το `NULL === NULL` είναι true, το `NULL === ''` είναι false.

---

## Σύνολο αλλαγών

Το `Merql\Diff\Changeset` είναι μια συλλογή λειτουργιών ανά γραμμή, μόνο για ανάγνωση.

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

Αντικείμενα τιμής μόνο για ανάγνωση που αναπαριστούν μεμονωμένες αλλαγές γραμμών.

### 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` αναπαριστά μία αλλαγή στήλης σε μια ενημέρωση γραμμής.

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

---

## ThreeWayMerge

Το `Merql\Merge\ThreeWayMerge` είναι ο βασικός αλγόριθμος συγχώνευσης.

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

Περάστε ένα `CellMergeConfig` για να ενεργοποιήσετε τη συγχώνευση σε επίπεδο κελιού για στήλες TEXT και JSON.

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

Εκτελεί μια συγχώνευση τριών κατευθύνσεων. Υπολογίζει εσωτερικά τα σύνολα αλλαγών (από τη βάση σε εμάς, από τη βάση σε εκείνους) και τα συγχωνεύει.

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

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

Συντόμευση για συγχώνευση δύο κατευθύνσεων. Ισοδυναμεί με `merge($base, $base, $changes)`.

### `schemaMismatches(): array`

Επιστρέφει το `SchemaException[]` για τυχόν διαφορές σχήματος που εντοπίστηκαν στην τελευταία συγχώνευση (στήλες που προστέθηκαν ή αφαιρέθηκαν μεταξύ στιγμιότυπων).

---

## MergeResult

Το `Merql\Merge\MergeResult` είναι ένα αντικείμενο τιμής μόνο για ανάγνωση που περιέχει το αποτέλεσμα της συγχώνευσης.

```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` είναι ένα μοντέλο ελέγχου συγχώνευσης που μπορεί να σειριοποιηθεί.

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

Χρησιμοποιήστε τα `MergePlanSerializer::toJson()` και `::fromJson()` για σταθερούς κύκλους JSON
μετατροπής.

## Επιλογές

Το `ChangeGroupSelection` αποθηκεύει αναγνωριστικά ομάδων αλλαγών που έχουν τεθεί σε στάδιο προετοιμασίας. Μετατρέψτε το σε ένα
`OperationSelection` κατά τη δημιουργία επιλεγμένων αποτελεσμάτων συγχώνευσης ή σχεδίων επαναφοράς.

```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` αποθηκεύει αντίστροφες λειτουργίες και προσδοκίες απόκλισης
για μια επιλεγμένη εφαρμογή.

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

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

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

Χρησιμοποιήστε το `RollbackDrift` πριν από την εφαρμογή επαναφοράς και έπειτα το `RollbackPlanApplier` για να εκτελέσετε
τις αντίστροφες λειτουργίες.

---

## MergeOperation

Το `Merql\Merge\MergeOperation` είναι μία επιλυμένη λειτουργία από τη συγχώνευση.

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

Σταθερές τύπων:

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

---

## Σύγκρουση

Το `Merql\Merge\Conflict` αναπαριστά μια ανεπίλυτη σύγκρουση συγχώνευσης.

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

### Τύποι συγκρούσεων

| Τύπος | Σημασία |
|---|---|
| `update_update` | Και οι δύο πλευρές άλλαξαν την ίδια στήλη σε διαφορετικές τιμές |
| `update_delete` | Εμείς ενημερώσαμε μια γραμμή που εκείνοι διέγραψαν |
| `delete_update` | Εμείς διαγράψαμε μια γραμμή που εκείνοι ενημέρωσαν |
| `insert_insert` | Και οι δύο πλευρές εισήγαγαν μια γραμμή με το ίδιο πρωτεύον κλειδί |

---

## ConflictResolver

Το `Merql\Merge\ConflictResolver` εφαρμόζει μια πολιτική επίλυσης σε όλες τις συγκρούσεις ενός αποτελέσματος συγχώνευσης.

### `resolve(MergeResult $result, ConflictPolicy $policy): MergeResult` (στατικό)

Επιστρέφει ένα νέο `MergeResult` με τις συγκρούσεις επιλυμένες σύμφωνα με την πολιτική.

```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` είναι απαριθμημένος τύπος με τρεις περιπτώσεις.

```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` εκτελεί λογική συγχώνευσης ανά στήλη για μία γραμμή. Χρησιμοποιείται εσωτερικά από το `ThreeWayMerge`.

### `merge(string $table, string $rowKey, array $base, array $ours, array $theirs, ?CellMergeConfig $cellMergeConfig = null, array $columnTypes = []): array` (στατικό)

Επιστρέφει το `['values' => array, 'conflicts' => list<Conflict>]`.

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

---

## Εφαρμογή

Το `Merql\Apply\Applier` εκτελεί ένα αποτέλεσμα συγχώνευσης σε μια βάση δεδομένων.

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

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

Εκτελεί όλες τις λειτουργίες σε μία συναλλαγή. Σε οποιοδήποτε σφάλμα, κάνει επαναφορά και το αναφέρει στο `ApplyResult::errors()` αντί να προκαλέσει εξαίρεση. Προκαλεί το `ConflictException` αν το αποτέλεσμα έχει ανεπίλυτες συγκρούσεις.

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

Η σειρά των ξένων κλειδιών διεκπεραιώνεται αυτόματα: οι εισαγωγές ταξινομούνται κατά σειρά εξάρτησης και οι διαγραφές με αντίστροφη σειρά εξάρτησης.

---

## ApplyResult

Το `Merql\Apply\ApplyResult` είναι ένα αντικείμενο τιμής μόνο για ανάγνωση που επιστρέφεται από το εργαλείο εφαρμογής.

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

Μετά από μια εφαρμογή που έγινε επαναφορά, το `rowsAffected()` εξακολουθεί να μετρά τις εντολές που εκτελέστηκαν πριν από την αποτυχία ([#4](https://github.com/inline0/merql/issues/4)). Ελέγξτε το `hasErrors()` πριν βασιστείτε στον αριθμό.

---

## DryRun

Το `Merql\Apply\DryRun` δημιουργεί αναγνώσιμες από τον άνθρωπο εντολές SQL χωρίς να εκτελεί τίποτα.

### `generate(MergeResult $result, ?Snapshot $base = null, array $fkDependencies = [], ?Driver $driver = null): array` (στατικό)

Επιστρέφει μια λίστα συμβολοσειρών SQL με ενσωματωμένες τιμές (μόνο για εμφάνιση).

```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` δημιουργεί παραμετροποιημένες εντολές SQL. Χρησιμοποιείται εσωτερικά τόσο από το `Applier` όσο και από το `DryRun`.

### `generate(MergeResult $result, ?Snapshot $base = null, array $fkDependencies = [], ?Driver $driver = null): array` (στατικό)

Επιστρέφει το `list<array{sql: string, params: list<scalar|null>}>`.

```php
use Merql\Apply\SqlGenerator;

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

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

---

## CellMergeConfig

Το `Merql\CellMerge\CellMergeConfig` διαμορφώνει στρατηγικές συγχώνευσης σε επίπεδο κελιού για συγκεκριμένες στήλες ή τύπους στηλών.

### `auto(): self` (στατικό)

Εργοστασιακή μέθοδος ευκολίας που αντιστοιχίζει το `TextCellMerger` σε στήλες TEXT/LONGTEXT και το `JsonCellMerger` σε στήλες JSON.

```php
use Merql\CellMerge\CellMergeConfig;

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

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

Αντιστοιχίστε έναν συγχωνευτή σε μια συγκεκριμένη στήλη. Χρησιμοποιήστε το `table.column` για πλήρως προσδιορισμένα ονόματα ή μόνο το `column` για όλους τους πίνακες.

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

Αντιστοιχίζει έναν συγχωνευτή σε όλες τις στήλες που ταιριάζουν με ένα μοτίβο τύπου (αντιστοίχιση υποσυμβολοσειράς χωρίς διάκριση πεζών-κεφαλαίων).

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

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

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

Αναζητά τον συγχωνευτή για έναν συγκεκριμένο πίνακα, στήλη και τύπο. Προτεραιότητα: πλήρως προσδιορισμένο όνομα στήλης, μη προσδιορισμένο όνομα στήλης, μοτίβο τύπου, προεπιλογή (αδιαφανής).

---

## CellMerger (διεπαφή)

Το `Merql\CellMerge\CellMerger` είναι η διεπαφή για στρατηγικές συγχώνευσης σε επίπεδο κελιού.

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

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

Παρέχονται τρεις ενσωματωμένες υλοποιήσεις.

### TextCellMerger

Το `Merql\CellMerge\TextCellMerger` συγχωνεύει κείμενο πολλών γραμμών χρησιμοποιώντας σύγκριση διαφορών γραμμή προς γραμμή τριών κατευθύνσεων (τον ίδιο αλγόριθμο που χρησιμοποιεί το git για το περιεχόμενο αρχείων). Όταν οι δύο πλευρές επεξεργάζονται διαφορετικές γραμμές, η συγχώνευση γίνεται χωρίς σύγκρουση. Όταν και οι δύο πλευρές επεξεργάζονται διαφορετικά την ίδια γραμμή, αναφέρει σύγκρουση.

```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 συγκρίνοντας ανεξάρτητα τα κλειδιά ανώτατου επιπέδου. Κάθε κλειδί συγχωνεύεται με λογική τριών κατευθύνσεων. Τα ένθετα αντικείμενα συγκρίνονται ως αδιαφανείς συμβολοσειρές JSON (δεν συγχωνεύονται αναδρομικά).

```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` είναι η προεπιλογή. Αντιμετωπίζει τις τιμές ως αδιαφανείς συμβολοσειρές και αναφέρει πάντα σύγκρουση όταν διαφέρουν.

---

## CellMergeResult

Το `Merql\CellMerge\CellMergeResult` είναι ο τύπος επιστροφής όλων των συγχωνευτών κελιών.

```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` είναι μια αναπαράσταση της δομής πίνακα μόνο για ανάγνωση.

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

---

## Σύστημα οδηγών

Το merql χρησιμοποιεί ένα σύστημα οδηγών με δυνατότητα προσθήκης εναλλακτικών, για την αφαίρεση των λειτουργιών που εξαρτώνται από τη βάση δεδομένων. Οι οδηγοί εντοπίζονται αυτόματα με βάση την ταυτότητα του οδηγού σύνδεσης.

### Driver (διεπαφή)

Το `Merql\Driver\Driver` ορίζει τη σύμβαση που υλοποιούν όλοι οι οδηγοί βάσεων δεδομένων.

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

Ενσωματωμένες υλοποιήσεις: `MysqlDriver` και `SqliteDriver`.

### DriverFactory

Το `Merql\Driver\DriverFactory` εντοπίζει αυτόματα τον οδηγό από μια σύνδεση.

```php
use Merql\Driver\DriverFactory;

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

Καταχωρίστε έναν προσαρμοσμένο οδηγό για άλλες βάσεις δεδομένων:

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

---

## Φίλτρα

### TableFilter

Το `Merql\Filter\TableFilter` συμπεριλαμβάνει ή εξαιρεί πίνακες χρησιμοποιώντας μοτίβα glob.

```php
use Merql\Filter\TableFilter;

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

### ColumnFilter

Το `Merql\Filter\ColumnFilter` αφαιρεί συγκεκριμένες στήλες από τα στιγμιότυπα.

```php
use Merql\Filter\ColumnFilter;

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

### RowFilter

Το `Merql\Filter\RowFilter` φιλτράρει γραμμές με μια συνάρτηση κατηγόρημα.

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

---

## Εξαιρέσεις

### SnapshotException

Το `Merql\Exceptions\SnapshotException` προκαλείται όταν δεν μπορεί να βρεθεί ένα στιγμιότυπο ή το όνομά του δεν είναι έγκυρο.

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

### MergeException

Το `Merql\Exceptions\MergeException` προκαλείται όταν λείπει ένα απαιτούμενο στιγμιότυπο για συγχώνευση.

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

### ConflictException

Το `Merql\Exceptions\ConflictException` προκαλείται κατά την προσπάθεια εφαρμογής ενός αποτελέσματος συγχώνευσης με ανεπίλυτες συγκρούσεις.

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

### SchemaException

Το `Merql\Exceptions\SchemaException` προκαλείται (ή συλλέγεται) όταν διαφέρουν τα σχήματα μεταξύ στιγμιότυπων.

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

Οι ασυμφωνίες σχήματος δεν διακόπτουν τη συγχώνευση. Συλλέγονται και είναι διαθέσιμες για επιθεώρηση μέσω του `$result->schemaMismatches()`.
