Gå til indhold

Fletning på kolonneniveau

Fletning på kolonneniveau er merqls største fordel frem for en naiv sammenligning på rækkeniveau. Når begge sider ændrer den samme række, sammenligner merql hver kolonne for sig i stedet for at markere hele rækken som en konflikt.

Problemet med fletning på rækkeniveau

Forestil dig en tabel af typen posts, hvor to personer redigerer den samme række:

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

En fletning på rækkeniveau registrerer, at begge sider har ændret rækken, og erklærer en konflikt. Men ændringerne overlapper slet ikke. Vores ændrede content, mens deres ændrede title og status.

Sådan løser fletning på kolonneniveau problemet

merql anvender de samme trevejsfletteregler på hver enkelt kolonne:

Kode
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

Resultat: { title: "New Title", content: "Body v2", status: "publish" }. Konfliktfri fletning.

Sådan fungerer det

Når ThreeWayMerge registrerer, at begge sider har opdateret den samme række, overlader den arbejdet til 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)

De samme regler gælder for hver kolonne:

Base Vores Deres Resultat
A A A Behold base (ingen ændring)
A A B Brug deres
A B A Brug vores
A B B Brug værdien (begge er enige)
A B C Konflikt (forskellige værdier)

Hvornår opstår der stadig konflikter

Der opstår en konflikt på kolonneniveau, når begge sider har ændret den samme kolonne til forskellige værdier:

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

Begge ændrede title til forskellige værdier. Det er en reel konflikt, der kræver en løsning.

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"

Delvise konflikter

En enkelt række kan indeholde både konfliktfri fletninger og konflikter. Hvis én kolonne flettes uden konflikt, men en anden giver en konflikt, indeholder rækkens MergeOperation de flettede værdier for konfliktfri kolonner og vores værdi som standard for kolonner med konflikter. Konflikten rapporteres stadig separat.

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

Her giver title en konflikt (begge ændrede den forskelligt), content flettes uden konflikt (kun vores side ændrede den), og status flettes uden konflikt (kun deres side ændrede den). Handlingen indeholder:

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

Værdisammenligning

Kolonneværdier sammenlignes som strenge efter konvertering. NULL er en særskilt værdi:

  • NULL til NULL = ingen ændring.
  • NULL til "hello" = opdatering.
  • "hello" til NULL = opdatering.
  • "1" til 1 = ingen ændring (begge konverteres til strengen "1").

Dette svarer til MerQL-forbindelsesadapterens hentningssemantik: alle databaseværdier returneres som strenge (eller NULL).

Fletning på celleniveau

Hvis fletning på kolonneniveau stadig giver en konflikt (begge sider har ændret den samme kolonne til forskellige værdier), kan merql gå et niveau dybere med fletning på celleniveau. Det gælder TEXT-kolonner (linjevis difference) og JSON-kolonner (nøglevis difference) og løser tilfælde, hvor begge sider har redigeret forskellige dele af den samme kolonneværdi.