
# Uvod

merql je čista knjižnica PHP za trosmerno združevanje stanj podatkovne zbirke. Ustvari posnetke tabel, izračuna nabore sprememb med posnetki, združi dva nabora sprememb glede na skupno osnovo in zazna spore na ravni stolpcev. Uporablja isti algoritem kot git za izvorne datoteke, le da namesto vrstic obdeluje zapise in stolpce.

Brez zunanjih orodij. Podpira MySQL in SQLite prek prilagodljivih povezovalnih adapterjev in gonilnikov za dialekte.

## Kratek primer

Za združitev potrebujete tri stanja istih podatkov: osnovo, iz katere sta izšli obe kopiji, in obe kopiji po njunih neodvisnih spremembah. Tukaj je bilo testno okolje kopirano iz produkcijske podatkovne zbirke, od takrat pa sta bili obe spremenjeni.

```php
use Merql\Connection;
use Merql\Merql;

$live    = Connection::sqlite('/data/live.sqlite');
$sandbox = Connection::sqlite('/data/sandbox.sqlite');

// Base: live at the moment the sandbox was copied from it.
Merql::init($live);
Merql::snapshot('base');

// ... copy live.sqlite to sandbox.sqlite, then both databases change ...

// Ours: the sandbox with our edits. Theirs: live with its own changes.
Merql::init($sandbox);
Merql::snapshot('ours');
Merql::init($live);
Merql::snapshot('theirs');

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

if ($result->isClean()) {
    foreach ($result->operations() as $operation) {
        echo "{$operation->type} {$operation->table} #{$operation->rowKey} ({$operation->source})\n";
    }
} else {
    echo "Conflicts: {$result->conflictCount()}\n";
}
```

Vsak posnetek se ustvari iz podatkovne zbirke, ki vsebuje to stanje. Če vse tri posnetke zaporedoma ustvarite v eni podatkovni zbirki, ne dobite dveh razšlih se kopij: njihova kopija bi že vsebovala naše spremembe, vsaka vrstica, ki smo jo dodali, pa bi bila označena kot spor `insert_insert`.

Rezultat navede operacije z obeh strani, ki osnovo pretvorijo v združeno stanje, pri čemer je vsaka označena s svojim virom (`ours`, `theirs` ali `merged`). Če želite spremembe iz testnega okolja zapisati v produkcijsko okolje, z orodjem [Zaščitena uporaba](https://merql.inline0.dev/sl/docs/apply/guarded) uveljavite operacije, ki jih v produkcijskem okolju še ni.

Ali iz CLI, ki se poveže s podatkovno zbirko, navedeno v `MERQL_DB_DSN` za vsak `snapshot`:

```bash
MERQL_DB_DSN="sqlite:/data/live.sqlite" vendor/bin/merql snapshot base
# ... copy live.sqlite to sandbox.sqlite, then both databases change ...
MERQL_DB_DSN="sqlite:/data/sandbox.sqlite" vendor/bin/merql snapshot ours
MERQL_DB_DSN="sqlite:/data/live.sqlite" vendor/bin/merql snapshot theirs

vendor/bin/merql merge base ours theirs --dry-run
```

## Zakaj merql

Večina orodij za primerjavo stanj podatkovnih zbirk deluje na ravni vrstic: če se med dvema različicama razlikuje kateri koli stolpec v vrstici, je celotna vrstica označena kot spor. To povzroči lažne spore, kadar dve osebi urejata različna stolpca iste vrstice.

merql združuje na ravni stolpcev. Če je ena stran spremenila `title`, druga pa `status`, se spremembe združijo brez spora. Spor nastane le, če obe strani spremenita isti stolpec na različni vrednosti.

Za stolpca TEXT in JSON lahko merql združevanje poglobi na raven celic. Dve spremembi različnih vrstic v besedilnem stolpcu ali različnih ključev stolpca JSON se lahko brez težav združita z istim trosmernim algoritmom. Združevanje na ravni celic je izbirno: posredujte `CellMergeConfig` v `ThreeWayMerge`. Vmesnik `Merql` in CLI združujeta samo na ravni stolpcev. Glejte [Združevanje na ravni celic](https://merql.inline0.dev/sl/docs/merge/cell-level).

## Model združevanja

```
         Base (snapshot at fork time)
        /                              \
   Ours (one copy's changes)            Theirs (the other copy's changes)
        \                              /
         --------- MERGE ----------
                     |
              Merged result
              + conflicts (if any)
```

Tri stanja, enako kot pri git. Osnova je skupni prednik. Naši in njihovi podatki sta kopiji po razhajanju, vsaka zajeta iz svoje podatkovne zbirke. Pravila združevanja obe strani obravnavajo enako. Imena se pojavijo v `source` vsake operacije, pri vrstah sporov (`update_delete` pomeni, da smo mi posodobili, oni pa izbrisali) ter v pravilih razreševanja `OursWins` in `TheirsWins`. Brez skupne osnove ni mogoče razlikovati med »dodano« in »nespremenjeno«.

Združitev sama po sebi ničesar ne zapiše. Njene operacije pretvorijo osnovo v združeno stanje, zato jih `Merql::apply()` uspešno izvede samo v podatkovni zbirki, ki še vedno vsebuje osnovo. Če želite spremembe ene strani prenesti v podatkovno zbirko, ki že vsebuje spremembe druge strani, na primer spremembe iz testnega okolja v produkcijsko, uveljavite samo operacije, ki ji manjkajo; glejte [Zaščitena uporaba](https://merql.inline0.dev/sl/docs/apply/guarded).

## Zahteve

- PHP 8.2 ali novejša različica.
- `ext-mbstring` in `ext-zlib`, ki ju zahteva odvisnost `pitmaster/pitmaster` za prikaz razlik v besedilu.
- Razširitev podatkovne zbirke za adapter, ki ga uporabljate: `ext-pdo` z `ext-pdo_sqlite` ali `ext-pdo_mysql` oziroma `ext-mysqli`. Konfiguracija `composer.json` za merql predlaga samo `ext-pdo` in `ext-mysqli`, zato jih Composer ne preverja.
- Podatkovna zbirka MySQL ali SQLite. Za druge pogone potrebujete prilagojen [gonilnik](https://merql.inline0.dev/sl/docs/apply/drivers).

## Kaj ni

merql ni orodje za selitev shem. Ne podvaja podatkovnih zbirk in jih ne sinhronizira v realnem času. Rešuje eno samo težavo: iz treh stanj podatkovne zbirke ustvari četrto, združeno stanje, in označi spore.

## Dokumentacija

- [Uvod](https://merql.inline0.dev/sl/docs/getting-started) -- namestitev, prvi posnetek, prva združitev.
- [CLI Referenca](https://merql.inline0.dev/sl/docs/cli) -- celotna referenca za ukaz `vendor/bin/merql`.
- [PHP API Referenca](https://merql.inline0.dev/sl/docs/api) -- popolna dokumentacija API za vse razrede.
- [Načrti združevanja](https://merql.inline0.dev/sl/docs/merge/plans) -- stabilni ID-ji operacij, skupine sprememb in izbori.
- [Zaščitena uporaba](https://merql.inline0.dev/sl/docs/apply/guarded) -- izbrani zapisi s predpogoji za aktivne vrstice.
- [Povrnitev](https://merql.inline0.dev/sl/docs/apply/rollback) -- artefakti za povrnitev in preverjanje odstopanj.
