
# Σχέδια συγχώνευσης

Ένα `MergeResult` είναι το εκτελέσιμο αποτέλεσμα μιας συγχώνευσης. Ένα `MergePlan` είναι η μορφή αυτού του αποτελέσματος που μπορείτε να επιθεωρήσετε. Χρησιμοποιήστε το όταν μια εφαρμογή χρειάζεται να εμφανίσει, να προετοιμάσει, να σειριοποιήσει ή να εφαρμόσει επιλεκτικά αλλαγές βάσης δεδομένων πριν τις γράψει στην τελική βάση δεδομένων.

```php
use Merql\Merql;

$plan = Merql::plan(
    id: 'plan-2026-06-06',
    base: 'base',
    ours: 'ours',
    theirs: 'theirs',
    metadata: ['sandbox_id' => 'ow_123'],
);
```

Το `Merql::plan()` φορτώνει τα τρία ονομασμένα στιγμιότυπα και τα συγχωνεύει σε επίπεδο στήλης, όπως το `Merql::merge()`. Για να σχεδιάσετε συγχώνευση που χρησιμοποιεί συγχώνευση σε επίπεδο κελιού για στήλες TEXT και JSON, δημιουργήστε μόνοι σας το αποτέλεσμα και περάστε το στο `MergePlanBuilder`:

```php
use Merql\CellMerge\CellMergeConfig;
use Merql\Merge\ThreeWayMerge;
use Merql\Plan\MergePlanBuilder;
use Merql\Snapshot\SnapshotStore;

$base = SnapshotStore::load('base');
$ours = SnapshotStore::load('ours');
$theirs = SnapshotStore::load('theirs');

$result = (new ThreeWayMerge(CellMergeConfig::auto()))->merge($base, $ours, $theirs);
$plan = (new MergePlanBuilder())->build('plan-2026-06-06', $base, $ours, $theirs, $result);
```

Το σχέδιο περιλαμβάνει:

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

## Σταθερά αναγνωριστικά

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

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

```php
foreach ($plan->changeGroups as $group) {
    echo $group->id . ': ' . implode(', ', $group->operationIds);
}
```

## Μορφή πράξης

Κάθε `MergePlanOperation` διατηρεί αρκετές πληροφορίες για έλεγχο και επαναφορά.

```php
$operation = $plan->operations[0];

$operation->id;              // stable operation ID
$operation->type;            // insert, update, delete
$operation->table;           // canonical table name
$operation->rowKey;          // encoded identity key
$operation->identityColumns; // columns used for identity
$operation->identityValues;  // decoded identity values
$operation->source;          // ours, theirs, or merged
$operation->baseRow;         // row in base snapshot, or null
$operation->oursRow;         // row in ours snapshot, or null
$operation->theirsRow;       // row in theirs snapshot, or null
$operation->resultValues;    // values the merge would write
$operation->changedColumns;  // changed result columns
```

## Επιλογές

Χρησιμοποιήστε το `ChangeGroupSelection` όταν το UI προετοιμάζει ομάδες. Μετατρέψτε το σε `OperationSelection` κατά την εφαρμογή ή τη δημιουργία τεχνουργημάτων επαναφοράς.

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

$selection = ChangeGroupSelection::fromIds([
    $plan->changeGroups[0]->id,
]);

$operationSelection = $selection->toOperationSelection($plan);

$selectedResult = (new SelectedMergeResultFactory())->fromOperationSelection(
    $plan,
    $operationSelection,
    SnapshotStore::load($plan->baseSnapshot),
);
```

Το επιλεγμένο αποτέλεσμα είναι ένα καθαρό `MergeResult` που περιέχει μόνο τις επιλεγμένες πράξεις. Μπορεί να περαστεί στο `Merql::apply()` ή στο `Merql::applyGuarded()`.

## Επιλογή όσων λείπουν από έναν στόχο

Ένα σχέδιο περιέχει τις πράξεις και των δύο πλευρών, επειδή το αποτέλεσμα συγχώνευσης μετατρέπει τη βάση στην κατάσταση συγχώνευσης. Όταν ο στόχος περιέχει ήδη τη μία πλευρά, επιλέξτε μόνο τις πράξεις που δεν έχει ακόμη. Για στόχο που περιέχει την άλλη πλευρά, όπως μια ενεργή βάση δεδομένων που λαμβάνει τις αλλαγές ενός δοκιμαστικού αντιγράφου, επιλέξτε όλες τις πράξεις με προέλευση `ours`, καθώς και τις ενημερώσεις `merged` που συνδυάζουν τις αλλαγές στηλών και των δύο πλευρών:

```php
use Merql\Plan\OperationSelection;
use Merql\Plan\SelectedMergeResultFactory;
use Merql\Snapshot\SnapshotStore;

// Rows with an unresolved conflict stay out of the selection.
$conflicted = [];
foreach ($plan->conflicts as $conflict) {
    $conflicted[$conflict->table . "\0" . $conflict->rowKey] = true;
}

$ids = [];
foreach ($plan->operations as $operation) {
    $missing = $operation->source === 'ours'
        || ($operation->source === 'merged' && $operation->type === 'update');

    if ($missing && !isset($conflicted[$operation->table . "\0" . $operation->rowKey])) {
        $ids[] = $operation->id;
    }
}

$selected = (new SelectedMergeResultFactory())->fromOperationSelection(
    $plan,
    OperationSelection::fromIds($ids),
    SnapshotStore::load($plan->baseSnapshot),
);
```

Οι πράξεις με προέλευση `theirs` και οι διαγραφές `merged` (γραμμές που διαγράφηκαν και από τις δύο πλευρές) υπάρχουν ήδη σε αυτόν τον στόχο.

Ένα σχέδιο που δημιουργήθηκε από συγχώνευση με διενέξεις εξακολουθεί να περιέχει μια πράξη για κάθε γραμμή με διένεξη που ενημέρωσαν και οι δύο πλευρές. Οι τιμές αποτελέσματός της περιέχουν την τιμή της δικής μας πλευράς στη στήλη που προκάλεσε τη διένεξη, και το `SelectedMergeResultFactory` επιστρέφει καθαρό αποτέλεσμα για οποιαδήποτε επιλογή. Οι ενδείξεις της πράξης και της ομάδας αλλαγών `conflictState` εξακολουθούν προς το παρόν να εμφανίζουν `clean` ακόμη και τότε ([#9](https://github.com/inline0/merql/issues/9)), επομένως ελέγξτε μόνοι σας το `$plan->conflicts` όπως παραπάνω ή επιλύστε τις διενέξεις με το `ConflictResolver` και δημιουργήστε το σχέδιο από το επιλυμένο αποτέλεσμα με το `MergePlanBuilder`. Δείτε το [Guarded Apply](https://merql.inline0.dev/el/docs/apply/guarded) για εγγραφή της επιλογής με προϋποθέσεις στις ενεργές γραμμές.

## Σειριοποίηση

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

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

$json = MergePlanSerializer::toJson($plan);
$restored = MergePlanSerializer::fromJson($json);

$selectionJson = json_encode($selection->toArray(), JSON_THROW_ON_ERROR);
$selection = ChangeGroupSelection::fromArray(
    json_decode($selectionJson, true, flags: JSON_THROW_ON_ERROR),
);
```

## Ψευδώνυμα στιγμιότυπων

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

```php
use Merql\Snapshot\SnapshotStore;
use Merql\Snapshot\Snapshotter;

$snapshotter = new Snapshotter($connection);

SnapshotStore::save($snapshotter->captureAliased('live', [
    'wp_posts' => 'wp_posts',
]));

SnapshotStore::save($snapshotter->captureAliased('sandbox', [
    'wp_onumia_abc_posts' => 'wp_posts',
]));
```

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