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:
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:
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:
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:
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.
$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.
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:
// 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:
NULLkeNULL= tidak berubah.NULLke"hello"= diperbarui."hello"keNULL= diperbarui."1"ke1= 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.