Συγχώνευση σε επίπεδο στήλης
Η συγχώνευση σε επίπεδο στήλης είναι το κύριο πλεονέκτημα του merql έναντι της απλοϊκής σύγκρισης σε επίπεδο γραμμής. Όταν και οι δύο πλευρές τροποποιούν την ίδια γραμμή, το merql συγκρίνει κάθε στήλη ξεχωριστά αντί να επισημαίνει ολόκληρη τη γραμμή ως σύγκρουση.
Το πρόβλημα της συγχώνευσης σε επίπεδο γραμμής
Σκεφτείτε έναν πίνακα posts όπου δύο άτομα επεξεργάζονται την ίδια γραμμή:
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" }
Μια συγχώνευση σε επίπεδο γραμμής βλέπει ότι και οι δύο πλευρές άλλαξαν τη γραμμή και δηλώνει σύγκρουση. Όμως οι αλλαγές δεν αλληλεπικαλύπτονται καθόλου. Το ours επεξεργάστηκε το content, ενώ το theirs επεξεργάστηκε τα title και status.
Πώς την επιλύει η συγχώνευση σε επίπεδο στήλης
Το merql εφαρμόζει τους ίδιους κανόνες συγχώνευσης τριών κατευθύνσεων ξεχωριστά σε κάθε στήλη:
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
Αποτέλεσμα: { title: "New Title", content: "Body v2", status: "publish" }. Καθαρή συγχώνευση, χωρίς σύγκρουση.
Πώς λειτουργεί
Όταν το ThreeWayMerge εντοπίζει ότι και οι δύο πλευρές ενημέρωσαν την ίδια γραμμή, αναθέτει τη συγχώνευση στο ColumnMerge::merge():
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)
Για κάθε στήλη ισχύουν οι ίδιοι κανόνες:
| Βάση | Ours | Theirs | Αποτέλεσμα |
|---|---|---|---|
| A | A | A | Διατήρηση βάσης (χωρίς αλλαγή) |
| A | A | B | Αποδοχή του theirs |
| A | B | A | Αποδοχή του ours |
| A | B | B | Αποδοχή (συμφωνούν και οι δύο) |
| A | B | C | Σύγκρουση (διαφορετικές τιμές) |
Πότε εξακολουθούν να προκύπτουν συγκρούσεις
Σύγκρουση σε επίπεδο στήλης προκύπτει όταν και οι δύο πλευρές αλλάξουν την ίδια στήλη σε διαφορετικές τιμές:
Base: post #42 { title: "Hello" }
Ours: post #42 { title: "Welcome" }
Theirs: post #42 { title: "Greetings" }
Και οι δύο άλλαξαν το title σε διαφορετικές τιμές. Πρόκειται για πραγματική σύγκρουση που απαιτεί επίλυση.
$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"
Μερικές συγκρούσεις
Μια γραμμή μπορεί να περιέχει τόσο καθαρές συγχωνεύσεις όσο και συγκρούσεις. Αν μία στήλη συγχωνευθεί ομαλά αλλά μια άλλη έχει σύγκρουση, το MergeOperation της γραμμής περιέχει τις συγχωνευμένες τιμές για τις στήλες που συγχωνεύθηκαν ομαλά και την τιμή ours (από προεπιλογή) για τις στήλες με σύγκρουση. Η σύγκρουση εξακολουθεί να αναφέρεται ξεχωριστά.
Base: { title: "Hello", content: "Body", status: "draft" }
Ours: { title: "Welcome", content: "Body v2", status: "draft" }
Theirs: { title: "Greetings", content: "Body", status: "publish" }
Εδώ, το title έχει σύγκρουση (και οι δύο πλευρές το άλλαξαν διαφορετικά), το content συγχωνεύεται ομαλά (άλλαξε μόνο το ours) και το status συγχωνεύεται ομαλά (άλλαξε μόνο το theirs). Η λειτουργία περιλαμβάνει:
// values: { title: "Welcome", content: "Body v2", status: "publish" }
// One conflict on the "title" column.
Σύγκριση τιμών
Οι τιμές στηλών συγκρίνονται ως συμβολοσειρές μετά τη μετατροπή τύπου. Το NULL είναι διακριτή τιμή:
NULLσεNULL= καμία αλλαγή.NULLσε"hello"= ενημέρωση."hello"σεNULL= ενημέρωση."1"σε1= καμία αλλαγή (και τα δύο μετατρέπονται στη συμβολοσειρά"1").
Αυτό συμφωνεί με τη σημασιολογία λήψης δεδομένων του προσαρμογέα σύνδεσης MerQL: όλες οι τιμές της βάσης δεδομένων επιστρέφονται ως συμβολοσειρές (ή NULL).
Συγχώνευση σε επίπεδο κελιού
Όταν η συγχώνευση σε επίπεδο στήλης εξακολουθεί να οδηγεί σε σύγκρουση (και οι δύο πλευρές άλλαξαν την ίδια στήλη σε διαφορετικές τιμές), το merql μπορεί να προχωρήσει ένα επίπεδο βαθύτερα με συγχώνευση σε επίπεδο κελιού. Αυτό εφαρμόζεται σε στήλες TEXT (διαφορές ανά γραμμή) και στήλες JSON (διαφορές ανά κλειδί), επιλύοντας περιπτώσεις όπου και οι δύο πλευρές επεξεργάστηκαν διαφορετικά μέρη της τιμής της ίδιας στήλης.