Kolmen tilan yhdistäminen
Kolmen tilan yhdistämisessä verrataan kahta muutosjoukkoa yhteiseen kantatilaan ja yhdistetään ne yhdeksi tulokseksi. merql käyttää tätä algoritmia tiedostorivien sijaan tietokannan riveihin.
use Merql\Merge\ThreeWayMerge;
$merge = new ThreeWayMerge();
$result = $merge->merge($base, $ours, $theirs);
echo $result->operationCount(); // resolved operations
echo $result->conflictCount(); // unresolved conflicts
Kolme tilaa
Jokainen yhdistäminen edellyttää täsmälleen kolmea tilannevedosta:
- Perusta -- tietokannan tila siinä vaiheessa, kun haarat erkanivat toisistaan.
- Meidän puolemme -- yksi haara muutostensa jälkeen, esimerkiksi muokattu hiekkalaatikkokopio.
- Heidän puolensa -- toinen haara muutostensa jälkeen, esimerkiksi käynnissä pysynyt tuotantotietokanta.
Meidän ja heidän puolensa on kumpikin tallennettava tietokannasta, jossa kyseinen haara sijaitsee. Yhdistämissäännöt käsittelevät molempia puolia samalla tavalla; nimet määrittävät kunkin toiminnon source, ristiriitatyyppien nimet (update_delete tarkoittaa, että me päivitimme ja he poistivat) sekä sen, kumpaa puolta ConflictPolicy::OursWins ja TheirsWins suosivat.
Base (snapshot at fork time)
/ \
Ours (our changes) Theirs (their changes)
\ /
--------- MERGE ----------
|
Merged result
+ conflicts (if any)
Ilman yhteistä perustaa et voi erottaa lisäystä muuttumattomasta. Kahden tilan vertailussa nähdään, että puolella A on arvo ja puolelta B se puuttuu, mutta ei voida päätellä, lisäsikö A sen vai poistiko B sen. Perusta antaa vastauksen.
Muutossarjojen laskeminen
Differ vertaa kumpaakin tilannevedosta perustaan ja tuottaa kaksi muutossarjaa. Kummassakin muutossarjassa on kolmenlaisia toimintoja:
| Perusta | Nykyinen | Toiminto |
|---|---|---|
| Rivi on olemassa | Rivi on olemassa, sama sormenjälki | Ei muutosta |
| Rivi on olemassa | Rivi on olemassa, eri sormenjälki | UPDATE (sarakkeittainen diff) |
| Rivi on olemassa | Rivi puuttuu | DELETE |
| Rivi puuttuu | Rivi on olemassa | INSERT |
Sormenjäljet (SHA-256 normalisoidun rivisisällön hajautusarvot) tarjoavat nopean käsittelypolun. Jos kaksi sormenjälkeä täsmää, rivi on muuttumaton eikä sarakekohtaista vertailua tarvita.
use Merql\Diff\Differ;
$differ = new Differ();
$oursChangeset = $differ->diff($base, $ours);
$theirsChangeset = $differ->diff($base, $theirs);
Yhdistämissäännöt
Sen jälkeen kaksi muutossarjaa yhdistetään toiminto kerrallaan. Tässä taulukossa esitetään lopputulos jokaiselle yhdistelmälle:
| Meidän puolemme | Heidän puolensa | Tulos |
|---|---|---|
| Ei muutosta | Ei muutosta | Säilytä perusta |
| Ei muutosta | Päivitetty | Hyväksy heidän muutoksensa |
| Päivitetty | Ei muutosta | Hyväksy meidän muutoksemme |
| Päivitetty (sama arvo) | Päivitetty (sama arvo) | Hyväksy (molemmat samaa mieltä) |
| Päivitetty (eri arvo) | Päivitetty (eri arvo) | Ristiriita |
| Ei muutosta | Poistettu | Hyväksy poisto |
| Poistettu | Ei muutosta | Hyväksy poisto |
| Poistettu | Poistettu | Hyväksy poisto (molemmat samaa mieltä) |
| Päivitetty | Poistettu | Ristiriita |
| Poistettu | Päivitetty | Ristiriita |
| Lisätty (vain meidän puolellamme) | -- | Hyväksy lisäys |
| -- | Lisätty (vain heidän puolellaan) | Hyväksy lisäys |
| Lisätty (sama PK) | Lisätty (sama PK) | Ristiriita |
Kun molemmat puolet päivittävät samaa riviä, merql ei ilmoita ristiriidasta heti. Se siirtyy saraketason yhdistämiseen ja vertaa jokaista saraketta erikseen. Katso lisätiedot kohdasta saraketason yhdistäminen.
Käyttö julkisivun kautta
Merql-julkisivu käsittelee levylle tallennettuja nimettyjä tilannevedoksia. Kutsu Merql::init()-toimintoa kunkin tilan sisältävällä tietokannalla ennen tilannevedoksen ottamista:
use Merql\Connection;
use Merql\Merql;
$live = Connection::sqlite('/data/live.sqlite');
$sandbox = Connection::sqlite('/data/sandbox.sqlite');
Merql::init($live);
Merql::snapshot('base'); // before the sandbox is copied from live
// ... copy live.sqlite to sandbox.sqlite, then both databases change ...
Merql::init($sandbox);
Merql::snapshot('ours');
Merql::init($live);
Merql::snapshot('theirs');
$result = Merql::merge('base', 'ours', 'theirs');
Älä ota kaikkia kolmea tilannevedosta peräkkäin samasta tietokannasta. Heidän tilannevedoksensa sisältäisi silloin myös meidän muutoksemme, joten jokainen meidän lisäämämme rivi näyttäisi olevan lisätty molemmilla puolilla ja aiheuttaisi insert_insert-ristiriidan.
Merql::merge(), Merql::patch() ja Merql::plan() luovat ThreeWayMerge-tuloksen ilman CellMergeConfig-toimintoa, joten yhdistäminen tapahtuu vain saraketasolla. Solutason yhdistämistä varten lataa tilannevedokset ja käytä suoraan luokkaa, kuten alla.
Luokkien suora käyttö
Voit hallita toimintaa tarkemmin luomalla komponentit itse. Snapshotter::capture() ei tallenna mitään, joten pidä tilannevedokset muistissa tai tallenna ne SnapshotStore::save()-toiminnolla:
use Merql\CellMerge\CellMergeConfig;
use Merql\Merge\ThreeWayMerge;
use Merql\Snapshot\Snapshotter;
use Merql\Snapshot\SnapshotStore;
$base = (new Snapshotter($live))->capture('base');
// ... copy live to the sandbox, then both databases change ...
$ours = (new Snapshotter($sandbox))->capture('ours');
$theirs = (new Snapshotter($live))->capture('theirs');
$merge = new ThreeWayMerge();
$result = $merge->merge($base, $ours, $theirs);
// Snapshots saved earlier, merged with cell-level merge for TEXT and JSON columns.
$merge = new ThreeWayMerge(CellMergeConfig::auto());
$result = $merge->merge(
SnapshotStore::load('base'),
SnapshotStore::load('ours'),
SnapshotStore::load('theirs'),
);
Pikakuvake korjaustiedoston käyttöön
Kun vain toisella puolella on muutoksia (samanaikaisia muokkauksia ei ole), käytä patch()-toimintoa. Kyseessä on kahden tilan yhdistäminen, jossa meidän puolemme vastaa perustaa, joten ristiriitoja ei voi syntyä:
$result = $merge->patch($base, $changes);
// Always clean: ours is identical to base.
Julkisivun kautta:
$result = Merql::patch('base', 'changes');
patch() vastaa toimintoa merge($base, $base, $changes). Koska meidän puolemme ei koskaan eronnut perustasta, kaikki heidän muutoksensa hyväksytään ilman ristiriitoja.
Skeemapoikkeamien tunnistus
Jos tauluun lisättiin tai siitä poistettiin sarakkeita tilannevedosten välillä, yhdistäminen jatkuu mutta poikkeamat kirjataan. Muuttuneita saraketyyppejä ei verrata, ja uudelleennimetty sarake näkyy yhtenä poistettuna ja yhtenä lisättynä; katso skeeman validointi.
$result = $merge->merge($base, $ours, $theirs);
if ($result->hasSchemaMismatches()) {
foreach ($result->schemaMismatches() as $mismatch) {
echo $mismatch->getMessage() . "\n";
}
}
merql ei siirrä skeemaa automaattisesti. Skeemamuutokset ovat kutsujan vastuulla. Yhdistäminen ilmoittaa niistä, jotta voit päättää, miten jatkat.
MergeResult
Tulosolio sisältää kaiken tarvittavan:
$result->isClean(); // true if no conflicts
$result->operations(); // list of MergeOperation objects
$result->conflicts(); // list of Conflict objects
$result->operationCount(); // number of resolved operations
$result->conflictCount(); // number of unresolved conflicts
$result->hasSchemaMismatches(); // true if schemas differ
$result->baseSnapshot(); // the base snapshot used for the merge
Jokaisella MergeOperation-toiminnolla on tyyppi (insert, update tai delete), taulun nimi, rivin avain, sarakearvot ja lähde (ours, theirs tai merged). merged merkitsee riviä, jonka molemmat puolet päivittivät (sarakkeet yhdistettiin) tai jonka molemmat puolet poistivat.
Yhdistämistuloksen käyttökohde
Yhdistämistulos kuvaa, miten perusta muutetaan yhdistetyksi tilaksi. Sen toiminnot sisältävät molempien puolten muutokset: sekä meidän että heidän tekemänsä lisäys näkyy lisäyksenä.
Merql::apply()(taiApplier) suorittaa kaikki toiminnot yhdistetyssä tietokannassa. Se soveltuu sellaisenaan tietokantaan, jossa on edelleen perusta, kuten uuteen kopioon perustilasta. Jos tietokanta sisältää jo toisen puolen muutokset, olemassa olevan rivin lisäys epäonnistuu ja tapahtuma peruutetaan.- Jos haluat tuoda meidän muutoksemme tietokantaan, jossa on jo heidän muutoksensa, esimerkiksi siirtää hiekkalaatikon muutokset käytössä olevaan ympäristöön, ota käyttöön vain toiminnot, joita tietokannasta puuttuu: lähteen
ourstoiminnot sekämerged-päivitykset. Valitse ne yhdistämissuunnitelman avulla ja kirjoita ne tietokantaan Suojatun käyttöönoton avulla käyttämällä käytössä olevien rivien ennakkoehtoja.