Lewati ke konten

Penggabungan Tingkat Kolom

Penggabungan tingkat kolom adalah keunggulan utama merql dibandingkan perbandingan naif pada tingkat baris. Ketika kedua sisi mengubah baris yang sama, merql membandingkan setiap kolom secara terpisah, alih-alih menandai seluruh baris sebagai konflik.

Masalah penggabungan tingkat baris

Bayangkan sebuah tabel posts tempat dua orang mengedit baris yang sama:

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

Penggabungan tingkat baris melihat kedua sisi mengubah baris itu dan menyatakan konflik. Namun, perubahan tersebut sama sekali tidak bertumpang tindih. Ours mengedit content, sedangkan theirs mengedit title dan status.

Cara penggabungan tingkat kolom menyelesaikannya

merql menerapkan aturan penggabungan tiga arah yang sama pada setiap kolom secara terpisah:

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

Hasil: { title: "New Title", content: "Body v2", status: "publish" }. Penggabungan bersih, tanpa konflik.

Cara kerjanya

Saat ThreeWayMerge mendeteksi bahwa kedua sisi memperbarui baris yang sama, ColumnMerge::merge() akan mengambil alih:

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)

Aturan yang sama berlaku untuk setiap kolom:

Base Ours Theirs Hasil
A A A Pertahankan base (tidak berubah)
A A B Terima theirs
A B A Terima ours
A B B Terima (keduanya sepakat)
A B C Konflik (nilai berbeda)

Saat konflik tetap terjadi

Konflik tingkat kolom terjadi ketika kedua sisi mengubah kolom yang sama menjadi nilai yang berbeda:

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

Keduanya mengubah title menjadi nilai yang berbeda. Ini merupakan konflik nyata yang memerlukan penyelesaian.

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"

Konflik sebagian

Satu baris dapat berisi penggabungan yang bersih sekaligus konflik. Jika satu kolom bergabung dengan bersih tetapi kolom lain berkonflik, MergeOperation untuk baris tersebut berisi nilai gabungan bagi kolom yang bersih dan nilai ours (secara default) bagi kolom yang berkonflik. Konflik tetap dilaporkan secara terpisah.

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

Di sini title berkonflik (keduanya mengubahnya secara berbeda), content bergabung dengan bersih (hanya ours yang mengubahnya), dan status bergabung dengan bersih (hanya theirs yang mengubahnya). Operasi tersebut memuat:

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

Perbandingan nilai

Nilai kolom dibandingkan sebagai string setelah dikonversi. NULL adalah nilai yang berbeda:

  • NULL ke NULL = tidak berubah.
  • NULL ke "hello" = diperbarui.
  • "hello" ke NULL = diperbarui.
  • "1" ke 1 = tidak berubah (keduanya dikonversi menjadi string "1").

Ini sesuai dengan semantik pengambilan adaptor koneksi MerQL: semua nilai database dikembalikan sebagai string (atau NULL).

Penggabungan tingkat sel

Ketika penggabungan tingkat kolom masih menghasilkan konflik (kedua sisi mengubah kolom yang sama menjadi nilai berbeda), merql dapat bekerja lebih mendalam dengan penggabungan tingkat sel. Fitur ini berlaku untuk kolom TEXT (diff baris demi baris) dan kolom JSON (diff kunci demi kunci), sehingga kasus ketika kedua sisi mengedit bagian berbeda dari nilai kolom yang sama dapat diselesaikan.