Preskoči na vsebino

Nadzorovana uporaba

GuardedApplier uveljavi čisto MergeResult le, če se ciljna zbirka podatkov še vedno ujema s pričakovanim posnetkom aktivnih podatkov. To je uporabno, kadar je bil načrt združevanja pregledan prej, aktivne vrstice pa so se pred uveljavitvijo morda spremenile.

Običajna nastavitev prenese spremembe iz peskovnika v aktivno zbirko podatkov. Osnova je aktivna zbirka v trenutku, ko je bil iz nje ustvarjen peskovnik; naše spremembe so urejeni peskovnik, njihove spremembe pa trenutno stanje aktivne zbirke. Cilj je aktivna zbirka, zato je pričakovani posnetek aktivnih podatkov theirs, operacije za zapis pa so tiste, ki jih aktivna zbirka še nima (glejte Izbiranje operacij).

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() zapisuje v zbirko podatkov, posredovano komponenti Merql::init(). Pričakovani posnetek aktivnih podatkov mora opisovati isto zbirko podatkov: zajemite ga iz cilja in dovolj nedavno, da imajo predpogoji smisel.

Predpogoji

Nadzorovana SQL dodaja ustvarjenim stavkom predpogoje za aktivne vrstice:

  • posodobitve zahtevajo, da identiteta ciljne vrstice obstaja, vrednosti stolpcev, ki niso identifikacijski, pa se ujemajo s pričakovano aktivno vrstico,
  • brisanja zahtevajo, da identiteta ciljne vrstice obstaja, vrednosti stolpcev, ki niso identifikacijski, pa se ujemajo s pričakovano aktivno vrstico,
  • vstavljanja zahtevajo, da ciljna identiteta še ne obstaja.

Če katerikoli stavek ne vpliva na nobeno vrstico, merql načrt obravnava kot zastarel. Transakcija se povrne, vrnjeni ApplyResult pa vsebuje napako Optimistic precondition failed for guarded merge statement.

V sistemu MySQL posodobitev, katere vrednosti so že enake aktivni vrstici, prav tako ne vpliva na nobeno vrstico, ker MySQL šteje spremenjene vrstice, ne pa ujemajočih se. Takšna posodobitev je neuspešna kot zastarela, čeprav se vrstica ujema (#2). SQLite šteje ujemajoče se vrstice in jo sprejme. To se lahko zgodi pri posodobitvi merged, kadar obe strani vrstico spremenita enako.

Izbiranje operacij

Rezultat združevanja vsebuje operacije obeh strani, saj osnovno stanje spremeni v združeno. Če ga uporabimo za cilj, ki že vsebuje njihove spremembe, operacije, ki izvirajo z njihove strani, opisujejo spremembe, ki jih cilj že ima, zato njihovi predpogoji niso izpolnjeni:

Operacija Stanje v cilju, ki vsebuje njihove spremembe Izberite
ours vstavljanje, posodobitev ali brisanje Manjka Da
merged posodobitev (obe strani sta spremenili vrstico) Vsebuje njihove stolpce, naših pa ne Da
theirs vstavljanje Vrstica obstaja, zato nadzorovano vstavljanje ne vpliva na nobeno vrstico Ne
merged brisanje (obe strani sta izbrisali vrstico) Vrstice ni več, zato nadzorovano brisanje ne vpliva na nobeno vrstico Ne
theirs posodobitev ali brisanje Že uveljavljeno Ne

Če celoten rezultat Merql::merge() posredujete komponenti applyGuarded(), se zato uveljavitev prekine takoj, ko so njihove spremembe vstavile vrstico ali sta obe strani vrstico izbrisali. Najprej izberite operacije po izvoru, kot je opisano zgoraj, ali z uporabo ChangeGroupSelection, ustvarjenega iz pregleda UI. Izpustite vrstice s seznama $plan->conflicts: izbran rezultat je vedno čist, operacija za vrstico v konfliktu pa vsebuje našo vrednost v stolpcu s konfliktom (glejte Načrti združevanja).

Izbrana uporaba

Nadzorovana uporaba deluje z izbranimi rezultati združevanja, ustvarjenimi iz načrta združevanja, vključno z izbori po skupinah sprememb.

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

To omogoča gostiteljski aplikaciji, da pripravi podmnožico pregledanih skupin in hkrati potrdi, da se aktivne vrstice po ustvarjanju načrta niso spremenile.

SQL Predogled

Z SqlGenerator::generateGuarded() si lahko ogledate zaščitene stavke, ne da bi jih izvedli.

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

Ustvarjeni stavki so še vedno parametrizirani. Predpogoji so izraženi z dodatnimi pogoji WHERE za posodobitve/brisanja in preverjanji NOT EXISTS za vstavljanja.

Zaščitena ali navadna uporaba

Merql::apply() izvede enake operacije brez predpogojev. Posodobitve in brisanja so tako uspešna ne glede na to, ali se je aktivna vrstica od izdelave načrta spremenila, vstavljanje že obstoječe vrstice pa ne uspe zaradi napake podvojitve ključa v podatkovni zbirki. Navadno uporabo izberite za cilj, za katerega veste, da še vedno vsebuje osnovno stanje, zaščiteno uporabo pa, kadar so drugi zapisovalci morda spreminjali cilj od trenutka zajema posnetka.