Liigu sisu juurde

Piiratud rakendamine

GuardedApplier rakendab puhta MergeResult ainult siis, kui sihtandmebaas vastab endiselt eeldatud aktiivsele hetktõmmisele. See on kasulik, kui liitmisplaan vaadati üle varem ja aktiivsed read võisid enne rakendamist muutuda.

Tüüpilise seadistuse korral viiakse liivakasti muudatused aktiivsesse andmebaasi. Baas on aktiivne andmebaas liivakasti kopeerimise hetkel, meie on muudetud liivakast ja nemad on aktiivne andmebaas praegusel hetkel. Siht on aktiivne andmebaas, seega on eeldatud aktiivne hetktõmmis theirs ning kirjutatavad operatsioonid on need, mida aktiivses andmebaasis veel pole (vt Operatsioonide valimine).

PHP
use Merql\Connection;
use Merql\Merql;
use Merql\Plan\OperationSelection;
use Merql\Plan\SelectedMergeResultFactory;
use Merql\Snapshot\SnapshotStore;

Merql::init(Connection::sqlite('/data/live.sqlite'));

$plan = Merql::plan('promote-1', 'base', 'ours', 'theirs');

// Skip rows with unresolved conflicts.
$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('base'),
);

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

if ($applied->hasErrors()) {
    foreach ($applied->errors() as $error) {
        echo $error . "\n";
    }
}

Merql::applyGuarded() kirjutab andmebaasi, mis edastati väärtusele Merql::init(). Eeldatud aktiivne hetktõmmis peab kirjeldama sama andmebaasi: võtke see sihtandmebaasist ja piisavalt hiljuti, et eeltingimustel oleks tähendus.

Eeltingimused

Piiratud SQL lisab genereeritud lausetele aktiivsete ridade eeltingimused:

  • uuenduste korral peab sihtrida selle identiteedi järgi olemas olema ning mitteidentiteedi veergude väärtused peavad vastama eeldatud aktiivsele reale,
  • kustutamiste korral peab sihtrida selle identiteedi järgi olemas olema ning mitteidentiteedi veergude väärtused peavad vastama eeldatud aktiivsele reale,
  • lisamiste korral ei tohi sihtidentiteet juba olemas olla.

Kui mõni lause ei mõjuta ühtegi rida, käsitleb merql plaani aegununa. Tehing tühistatakse ning tagastatud ApplyResult sisaldab viga Optimistic precondition failed for guarded merge statement.

MySQL puhul mõjutab uuendus, mille väärtused on juba võrdsed aktiivse rea omadega, samuti null rida, sest MySQL loendab muudetud, mitte sobitatud ridu. Selline uuendus nurjub aegununa, kuigi rida vastab tingimustele (#2). SQLite loendab sobitatud ridu ja aktsepteerib selle. Nii võib juhtuda merged uuenduse korral, kui mõlemad harud tegid reale sama muudatuse.

Operatsioonide valimine

Liitmise tulemus sisaldab mõlema haru operatsioone, sest see muudab baasi liidetud olekuks. Kui rakendada tulemus sihile, kus on juba nemad, kirjeldavad neist tulenevad operatsioonid muudatusi, mis sihil juba olemas on, mistõttu nende eeltingimused nurjuvad:

Operatsioon Olek sihis, kus on nemad Vali
ours lisamine, uuendamine või kustutamine Puudub Jah
merged uuendamine (mõlemad harud muutsid rida) Nende veerud olemas, meie omad puuduvad Jah
theirs lisamine Rida on olemas, seega piiratud lisamine ei mõjuta ühtegi rida Ei
merged kustutamine (mõlemad harud kustutasid rea) Rida on kustutatud, seega piiratud kustutamine ei mõjuta ühtegi rida Ei
theirs uuendamine või kustutamine Juba rakendatud Ei

Seega nurjub kogu Merql::merge() tulemuse edastamine väärtusele applyGuarded() kohe, kui nemad lisasid rea või mõlemad harud selle kustutasid. Valige esmalt operatsioonid alltoodud allika järgi või ülevaate UI põhjal loodud ChangeGroupSelection abil. Jätke välja väärtuses $plan->conflicts loetletud read: valitud tulemus on alati puhas ning konfliktse rea operatsioon kasutab konfliktses veerus meie väärtust (vt Liitmisplaanid).

Valitud rakendamine

Piiratud rakendamine töötab valitud liitmistulemustega, mis on loodud liitmisplaani põhjal, sealhulgas muudatuste rühma järgi tehtud valikutega.

PHP
use Merql\Plan\ChangeGroupSelection;
use Merql\Plan\SelectedMergeResultFactory;
use Merql\Snapshot\SnapshotStore;

$selection = ChangeGroupSelection::fromIds([$plan->changeGroups[0]->id]);
$selected = (new SelectedMergeResultFactory())->fromChangeGroupSelection(
    $plan,
    $selection,
    SnapshotStore::load($plan->baseSnapshot),
);

$applied = Merql::applyGuarded($selected, SnapshotStore::load($plan->theirsSnapshot));

See võimaldab hostrakendusel ette valmistada osa üle vaadatud rühmadest ja samal ajal kontrollida, et aktiivsed read poleks pärast plaani loomist muutunud.

SQL eelvaade

Kasutage väärtust SqlGenerator::generateGuarded() piiratud lausete vaatamiseks ilma neid käivitamata.

PHP
use Merql\Apply\SqlGenerator;
use Merql\Snapshot\SnapshotStore;

$statements = SqlGenerator::generateGuarded(
    $selected,
    SnapshotStore::load($plan->theirsSnapshot),
);

foreach ($statements as $statement) {
    echo $statement['sql'] . "\n";
}

Genereeritud laused on endiselt parameetriseeritud. Eeltingimused väljendatakse täiendavate WHERE-klauslitega uuenduste ja kustutamiste puhul ning NOT EXISTS-kontrollidega lisamiste puhul.

Piiratud või tavaline rakendamine

Merql::apply() käivitab samad operatsioonid ilma eeltingimusteta. Uuendused ja kustutamised õnnestuvad siis sõltumata sellest, kas aktiivne rida on pärast plaani koostamist muutunud, ning olemasoleva rea lisamine nurjub andmebaasi duplikaatvõtme veaga. Kasutage tavalist rakendamist sihi puhul, kus on teadaolevalt endiselt baas, ning piiratud rakendamist siis, kui teised kirjutajad võisid sihti pärast hetktõmmise tegemist muuta.