Preskočiť na obsah

Zlučovanie na úrovni stĺpcov

Zlučovanie na úrovni stĺpcov je hlavnou výhodou merql oproti naivnému porovnávaniu riadkov. Keď obe strany upravia ten istý riadok, merql porovnáva každý stĺpec samostatne namiesto toho, aby označil celý riadok ako konflikt.

Problém so zlučovaním na úrovni riadkov

Predstavte si tabuľku posts, v ktorej dvaja ľudia upravujú ten istý riadok:

Kód
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" }

Zlúčenie na úrovni riadkov zistí, že obe strany zmenili riadok, a označí ho za konflikt. Zmeny sa však vôbec neprekrývajú. Ours upravilo content, zatiaľ čo theirs upravilo title a status.

Ako to rieši zlučovanie na úrovni stĺpcov

merql použije rovnaké pravidlá trojstranného zlúčenia na každý stĺpec samostatne:

Kód
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

Výsledok: { title: "New Title", content: "Body v2", status: "publish" }. Čisté zlúčenie bez konfliktu.

Ako to funguje

Keď ThreeWayMerge zistí, že obe strany aktualizovali ten istý riadok, deleguje spracovanie na 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)

Pre každý stĺpec platia rovnaké pravidlá:

Base Ours Theirs Výsledok
A A A Ponechať base (bez zmeny)
A A B Prijať theirs
A B A Prijať ours
A B B Prijať (zhoda)
A B C Konflikt (rôzne hodnoty)

Kedy stále dochádza ku konfliktom

Konflikt na úrovni stĺpca nastane, keď obe strany zmenia ten istý stĺpec na rôzne hodnoty:

Kód
Base:    post #42  { title: "Hello" }
Ours:    post #42  { title: "Welcome" }
Theirs:  post #42  { title: "Greetings" }

Obe strany zmenili title na rôzne hodnoty. Ide o skutočný konflikt, ktorý treba vyriešiť.

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"

Čiastočné konflikty

Jeden riadok môže obsahovať čisté zlúčenia aj konflikty. Ak sa jeden stĺpec zlúči bez problémov, ale pri inom dôjde ku konfliktu, MergeOperation pre daný riadok obsahuje zlúčené hodnoty čistých stĺpcov a hodnotu ours (predvolene) v stĺpcoch s konfliktom. Konflikt sa naďalej uvádza samostatne.

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

Tu dochádza ku konfliktu v title (obe strany ho zmenili odlišne), content sa zlúči bez konfliktu (zmenilo ho iba ours) a status sa zlúči bez konfliktu (zmenilo ho iba theirs). Operácia obsahuje:

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

Porovnávanie hodnôt

Hodnoty stĺpcov sa po pretypovaní porovnávajú ako reťazce. NULL sa považuje za samostatnú hodnotu:

  • NULL na NULL = bez zmeny.
  • NULL na "hello" = aktualizácia.
  • "hello" na NULL = aktualizácia.
  • "1" na 1 = bez zmeny (obe hodnoty sa prevedú na reťazec "1").

To zodpovedá spôsobu načítania hodnôt adaptérom pripojenia MerQL: všetky hodnoty databázy sa vracajú ako reťazce (alebo NULL).

Zlučovanie na úrovni buniek

Ak zlučovanie na úrovni stĺpcov stále vedie ku konfliktu (obe strany zmenili ten istý stĺpec na rôzne hodnoty), merql môže prejsť o úroveň nižšie a použiť zlúčenie na úrovni buniek. Vzťahuje sa na stĺpce TEXT (porovnávanie rozdielov po riadkoch) a JSON (porovnávanie rozdielov po kľúčoch) a rieši prípady, keď obe strany upravili rôzne časti hodnoty toho istého stĺpca.