Liigu sisu juurde

Veerutaseme liitmine

Veerutaseme liitmine on merqli peamine eelis lihtsa reataseme võrdluse ees. Kui mõlemad pooled muudavad sama rida, võrdleb merql iga veergu eraldi, selle asemel et märkida kogu rida konfliktseks.

Reataseme liitmise probleem

Vaatleme tabelit posts, kus kaks inimest muudavad sama rida:

Kood
Base:    post #42  { title: "Hello",     content: "Body",    status: "draft"   }
Ours:    post #42  { title: "Hello",     content: "Body v2", status: "draft"   }
Theirs:  post #42  { title: "New Title", content: "Body",    status: "publish" }

Reataseme liitmine tuvastab, et mõlemad pooled muutsid rida, ja kuulutab välja konflikti. Muudatused aga ei kattu üldse. Meie muutsime content, nemad muutsid title ja status.

Kuidas veerutaseme liitmine probleemi lahendab

merql rakendab igale veerule eraldi samu kolme osapoole liitmisreegleid:

Kood
title:   base="Hello", ours="Hello",  theirs="New Title"  -> accept theirs
content: base="Body",  ours="Body v2", theirs="Body"      -> accept ours
status:  base="draft", ours="draft",  theirs="publish"    -> accept theirs

Tulemus: { title: "New Title", content: "Body v2", status: "publish" }. Puhas liitmine, konflikti pole.

Kuidas see töötab

Kui ThreeWayMerge tuvastab, et mõlemad pooled uuendasid sama rida, delegeerib see töö objektile ColumnMerge::merge():

PHP
use Merql\Merge\ColumnMerge;

$result = ColumnMerge::merge(
    table: 'posts',
    rowKey: '42',
    base: ['title' => 'Hello', 'content' => 'Body', 'status' => 'draft'],
    ours: ['title' => 'Hello', 'content' => 'Body v2', 'status' => 'draft'],
    theirs: ['title' => 'New Title', 'content' => 'Body', 'status' => 'publish'],
);

// $result['values']    -> merged column values
// $result['conflicts'] -> list of Conflict objects (empty if clean)

Iga veeru puhul kehtivad samad reeglid:

Alus Meie Nende Tulemus
A A A Jäta alusväärtus alles (muudatusi pole)
A A B Võta vastu nende väärtus
A B A Võta vastu meie väärtus
A B B Võta vastu (mõlemad nõustuvad)
A B C Konflikt (erinevad väärtused)

Millal konfliktid siiski tekivad

Veerutaseme konflikt tekib siis, kui mõlemad pooled muutsid sama veeru väärtuseks erineva väärtuse:

Kood
Base:    post #42  { title: "Hello" }
Ours:    post #42  { title: "Welcome" }
Theirs:  post #42  { title: "Greetings" }

Mõlemad muutsid välja title, kuid eri väärtuseks. See on tegelik konflikt, mis vajab lahendamist.

PHP
$result = ColumnMerge::merge(
    'posts', '42',
    ['title' => 'Hello'],
    ['title' => 'Welcome'],
    ['title' => 'Greetings'],
);

// $result['conflicts'] contains one Conflict:
//   table: "posts", column: "title"
//   oursValue: "Welcome", theirsValue: "Greetings", baseValue: "Hello"

Osalised konfliktid

Ühes reas võib olla nii puhtaid liitmisi kui ka konflikte. Kui üks veerg liidetakse puhtalt, kuid teises tekib konflikt, sisaldab rea MergeOperation puhtalt liidetud veergude väärtusi ja konfliktsete veergude puhul vaikimisi meie väärtust. Konfliktist teatatakse eraldi.

Kood
Base:    { title: "Hello", content: "Body",    status: "draft" }
Ours:    { title: "Welcome", content: "Body v2", status: "draft" }
Theirs:  { title: "Greetings", content: "Body",    status: "publish" }

Siin on välja title konfliktne (mõlemad muutsid seda eri viisil), content liidetakse puhtalt (muutsime ainult meie) ja status liidetakse puhtalt (muutsid ainult nemad). Tehe sisaldab järgmist:

PHP
// values: { title: "Welcome", content: "Body v2", status: "publish" }
// One conflict on the "title" column.

Väärtuste võrdlus

Veeru väärtusi võrreldakse pärast teisendamist stringidena. NULL on eraldi väärtus:

  • NULL kuni NULL = muutusi pole.
  • NULL kuni "hello" = uuendus.
  • "hello" kuni NULL = uuendus.
  • "1" kuni 1 = muutusi pole (mõlemad teisendatakse stringiks "1").

See vastab ühendusadapteri MerQL andmete laadimise semantikale: kõik andmebaasi väärtused tagastatakse stringidena (või väärtusena NULL).

Lahtritaseme liitmine

Kui veerutaseme liitmisel tekib endiselt konflikt (mõlemad pooled muutsid sama veeru eri väärtuseks), saab merql minna veel ühe taseme võrra sügavamale, kasutades lahtritaseme liitmist. See kehtib TEXT-veergude puhul (ridade kaupa diff) ja JSON veergude puhul (võtmete kaupa diff), lahendades olukorrad, kus pooled muutsid sama veeruväärtuse eri osi.