Mesclagem no nível da coluna
A mesclagem no nível das colunas é a principal vantagem do merql em relação à comparação simplista no nível das linhas. Quando os dois lados modificam a mesma linha, o merql compara cada coluna de forma independente, em vez de marcar a linha inteira como conflito.
O problema da mesclagem no nível das linhas
Considere uma tabela posts em que duas pessoas editam a mesma linha:
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" }
Uma mesclagem no nível das linhas detecta que os dois lados alteraram a linha e declara um conflito. Mas as alterações não se sobrepõem. Nosso editou content; deles editaram title e status.
Como a mesclagem no nível das colunas resolve o problema
merql aplica as mesmas regras de mesclagem de três vias a cada coluna individualmente:
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
Resultado: { title: "New Title", content: "Body v2", status: "publish" }. Mesclagem sem conflitos.
Como funciona
Quando ThreeWayMerge detecta que os dois lados atualizaram a mesma linha, delega a operação para 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)
Para cada coluna, aplicam-se as mesmas regras:
| Base | Nosso | Deles | Resultado |
|---|---|---|---|
| A | A | A | Manter a base (sem alterações) |
| A | A | B | Aceitar deles |
| A | B | A | Aceitar nosso |
| A | B | B | Aceitar (ambos concordam) |
| A | B | C | Conflito (valores diferentes) |
Quando ainda ocorrem conflitos
Ocorre um conflito no nível da coluna quando os dois lados alteram a mesma coluna para valores diferentes:
Base: post #42 { title: "Hello" }
Ours: post #42 { title: "Welcome" }
Theirs: post #42 { title: "Greetings" }
Os dois lados alteraram title para valores diferentes. Esse é um conflito real que precisa ser resolvido.
$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"
Conflitos parciais
Uma única linha pode conter mesclagens sem conflitos e conflitos. Se uma coluna for mesclada sem conflitos, mas outra gerar um conflito, o MergeOperation da linha conterá os valores mesclados das colunas sem conflitos e, por padrão, o valor de nosso nas colunas conflitantes. O conflito ainda será informado separadamente.
Base: { title: "Hello", content: "Body", status: "draft" }
Ours: { title: "Welcome", content: "Body v2", status: "draft" }
Theirs: { title: "Greetings", content: "Body", status: "publish" }
Neste caso, title gera um conflito (ambos alteraram a coluna de forma diferente), content é mesclada sem conflitos (apenas nosso alterou) e status é mesclada sem conflitos (apenas deles alteraram). A operação contém:
// values: { title: "Welcome", content: "Body v2", status: "publish" }
// One conflict on the "title" column.
Comparação de valores
Os valores das colunas são comparados como strings após a conversão de tipo. NULL é um valor distinto:
NULLparaNULL= sem alterações.NULLpara"hello"= atualização."hello"paraNULL= atualização."1"para1= sem alterações (ambos são convertidos para a string"1").
Isso corresponde à semântica de recuperação de dados do adaptador de conexão MerQL: todos os valores do banco de dados são retornados como strings (ou NULL).
Mesclagem no nível da célula
Quando a mesclagem no nível das colunas ainda resulta em um conflito (os dois lados alteraram a mesma coluna para valores diferentes), o merql pode ir além com a mesclagem no nível da célula. Ela se aplica a colunas TEXT (diff linha a linha) e colunas JSON (diff chave por chave), resolvendo casos em que os dois lados editaram partes diferentes do valor da mesma coluna.