Oszlopszintű egyesítés
Az oszlopszintű egyesítés a merql legfőbb előnye a naiv, soronkénti összehasonlítással szemben. Ha mindkét oldal módosítja ugyanazt a sort, a merql az egész sor ütközésként való megjelölése helyett külön-külön hasonlítja össze az oszlopokat.
A soronkénti egyesítés problémája
Tegyük fel, hogy egy posts táblában két ember ugyanazt a sort szerkeszti:
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" }
A soronkénti egyesítés észleli, hogy mindkét oldal módosította a sort, és ütközést állapít meg. A módosítások azonban egyáltalán nem fedik egymást. Az ours a(z) content értékét, a theirs pedig a(z) title és status értékét módosította.
Az ütközés feloldása oszlopszintű egyesítéssel
A merql ugyanazokat a háromutas egyesítési szabályokat alkalmazza minden egyes oszlopra:
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
Eredmény: { title: "New Title", content: "Body v2", status: "publish" }. Ütközésmentes, tiszta egyesítés.
Működés
Amikor a(z) ThreeWayMerge észleli, hogy mindkét oldal módosította ugyanazt a sort, átadja a feladatot a(z) ColumnMerge::merge() számára:
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)
Minden oszlopra ugyanazok a szabályok érvényesek:
| Base | Ours | Theirs | Eredmény |
|---|---|---|---|
| A | A | A | Az alap megtartása (nincs változás) |
| A | A | B | A theirs elfogadása |
| A | B | A | Az ours elfogadása |
| A | B | B | Elfogadás (mindkét oldal egyetért) |
| A | B | C | Ütközés (eltérő értékek) |
Mikor fordul elő továbbra is ütközés
Oszlopszintű ütközés akkor fordul elő, ha mindkét oldal ugyanazt az oszlopot módosítja, de eltérő értékre:
Base: post #42 { title: "Hello" }
Ours: post #42 { title: "Welcome" }
Theirs: post #42 { title: "Greetings" }
Mindkét oldal módosította a(z) title értékét, de eltérő eredményre. Ez valódi ütközés, amely feloldást igényel.
$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"
Részleges ütközések
Egy soron belül lehetnek tisztán egyesíthető értékek és ütközések is. Ha az egyik oszlop tisztán egyesül, a másik pedig ütközik, a sorhoz tartozó MergeOperation a tisztán egyesíthető oszlopok egyesített értékeit, az ütköző oszlopoknál pedig alapértelmezés szerint az ours értékét tartalmazza. Az ütközést ettől függetlenül külön jelzi.
Base: { title: "Hello", content: "Body", status: "draft" }
Ours: { title: "Welcome", content: "Body v2", status: "draft" }
Theirs: { title: "Greetings", content: "Body", status: "publish" }
Itt a(z) title ütközik (mindkét oldal eltérően módosította), a(z) content tisztán egyesül (csak az ours módosította), a(z) status pedig tisztán egyesül (csak a theirs módosította). A művelet tartalmazza:
// values: { title: "Welcome", content: "Body v2", status: "publish" }
// One conflict on the "title" column.
Értékek összehasonlítása
Az oszlopértékeket konvertálás után karakterláncként hasonlítja össze. A NULL különálló értéknek számít:
NULLésNULLközött = nincs változás.NULLés"hello"között = módosítás."hello"ésNULLközött = módosítás."1"és1között = nincs változás (mindkettő a(z)"1"karakterlánccá alakul).
Ez megfelel a(z) MerQL kapcsolatadapter adatlekérési szemantikájának: az adatbázis értékei karakterláncként (vagy NULL-ként) érkeznek vissza.
Cellaszintű egyesítés
Ha az oszlopszintű egyesítés továbbra is ütközést eredményez (mindkét oldal ugyanazt az oszlopot módosította eltérő értékre), a merql egy szinttel mélyebbre is mehet a cellaszintű egyesítéssel. Ez a TEXT oszlopokra (soronkénti különbségvizsgálat) és az JSON oszlopokra (kulcsonkénti különbségvizsgálat) vonatkozik, és azokat az eseteket oldja meg, amikor mindkét oldal ugyanazon oszlopérték különböző részeit szerkesztette.