Siirry sisältöön

Saraketason yhdistäminen

Saraketason yhdistäminen on merqlin tärkein etu verrattuna yksinkertaiseen rivitason vertailuun. Kun molemmat puolet muuttavat samaa riviä, merql vertaa kutakin saraketta erikseen eikä merkitse koko riviä ristiriidaksi.

Rivitason yhdistämisen ongelma

Tarkastellaan posts-taulua, jossa kaksi henkilöä muokkaa samaa riviä:

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

Rivitason yhdistäminen havaitsee, että molemmat puolet muuttivat riviä, ja ilmoittaa ristiriidan. Muutokset eivät kuitenkaan mene päällekkäin. Ours muokkasi kohdetta content, theirs kohteita title ja status.

Näin saraketason yhdistäminen ratkaisee ongelman

merql soveltaa samoja kolmen osapuolen yhdistämissääntöjä kuhunkin sarakkeeseen erikseen:

Koodi
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

Tulos: { title: "New Title", content: "Body v2", status: "publish" }. Yhdistäminen onnistui ilman ristiriitaa.

Näin se toimii

Kun ThreeWayMerge havaitsee, että molemmat puolet päivittivät saman rivin, se siirtää tehtävän kohteelle 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)

Kuhunkin sarakkeeseen sovelletaan samoja sääntöjä:

Lähtötila Ours Theirs Tulos
A A A Säilytä lähtötila (ei muutosta)
A A B Hyväksy theirs
A B A Hyväksy ours
A B B Hyväksy (molemmat samaa mieltä)
A B C Ristiriita (eri arvot)

Milloin ristiriitoja silti syntyy

Saraketason ristiriita syntyy, kun molemmat puolet muuttavat saman sarakkeen eri arvoiksi:

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

Molemmat muuttivat sarakkeen title eri arvoksi. Kyseessä on todellinen ristiriita, joka vaatii ratkaisun.

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"

Osittaiset ristiriidat

Yhdellä rivillä voi olla sekä puhtaita yhdistämisiä että ristiriitoja. Jos yksi sarake yhdistyy puhtaasti mutta toisessa on ristiriita, rivin MergeOperation sisältää puhtaasti yhdistettyjen sarakkeiden arvot ja ristiriitaisten sarakkeiden arvona meidän arvomme (oletuksena). Ristiriita ilmoitetaan silti erikseen.

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

Tässä title aiheuttaa ristiriidan (molemmat muuttivat sitä eri tavalla), content yhdistyy puhtaasti (vain meidän puolemme muuttui) ja status yhdistyy puhtaasti (vain heidän puolensa muuttui). Toiminto sisältää:

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

Arvojen vertailu

Sarakkeiden arvoja verrataan merkkijonoina tyyppimuunnoksen jälkeen. NULL on eri arvo:

  • NULL–NULL = ei muutosta.
  • NULL–"hello" = päivitys.
  • "hello"–NULL = päivitys.
  • "1"–1 = ei muutosta (molemmat muunnetaan merkkijonoksi "1").

Tämä vastaa MerQL-yhteyssovittimen noutosemantiikkaa: kaikki tietokanta-arvot palautetaan merkkijonoina (tai NULL-arvona).

Solutason yhdistäminen

Jos saraketason yhdistäminen tuottaa silti ristiriidan (molemmat puolet muuttivat saman sarakkeen eri arvoon), merql voi mennä vielä yhden tason syvemmälle solutason yhdistämisellä. Tätä sovelletaan TEXT-sarakkeisiin (rivikohtainen diff) ja JSON-sarakkeisiin (avainkohtainen diff), jolloin ratkaistaan tapaukset, joissa molemmat puolet muokkasivat saman sarakearvon eri osia.