
# Zlučovanie na úrovni stĺpcov

Zlučovanie na úrovni stĺpcov je hlavnou výhodou merql oproti naivnému porovnávaniu riadkov. Keď obe strany upravia ten istý riadok, merql porovnáva každý stĺpec samostatne namiesto toho, aby označil celý riadok ako konflikt.

## Problém so zlučovaním na úrovni riadkov

Predstavte si tabuľku `posts`, v ktorej dvaja ľudia upravujú ten istý riadok:

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

Zlúčenie na úrovni riadkov zistí, že obe strany zmenili riadok, a označí ho za konflikt. Zmeny sa však vôbec neprekrývajú. Ours upravilo `content`, zatiaľ čo theirs upravilo `title` a `status`.

## Ako to rieši zlučovanie na úrovni stĺpcov

merql použije rovnaké pravidlá trojstranného zlúčenia na každý stĺpec samostatne:

```
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
```

Výsledok: `{ title: "New Title", content: "Body v2", status: "publish" }`. Čisté zlúčenie bez konfliktu.

## Ako to funguje

Keď `ThreeWayMerge` zistí, že obe strany aktualizovali ten istý riadok, deleguje spracovanie na `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)
```

Pre každý stĺpec platia rovnaké pravidlá:

| Base | Ours | Theirs | Výsledok |
|---|---|---|---|
| A | A | A | Ponechať base (bez zmeny) |
| A | A | B | Prijať theirs |
| A | B | A | Prijať ours |
| A | B | B | Prijať (zhoda) |
| A | B | C | **Konflikt** (rôzne hodnoty) |

## Kedy stále dochádza ku konfliktom

Konflikt na úrovni stĺpca nastane, keď obe strany zmenia ten istý stĺpec na rôzne hodnoty:

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

Obe strany zmenili `title` na rôzne hodnoty. Ide o skutočný konflikt, ktorý treba vyriešiť.

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

## Čiastočné konflikty

Jeden riadok môže obsahovať čisté zlúčenia aj konflikty. Ak sa jeden stĺpec zlúči bez problémov, ale pri inom dôjde ku konfliktu, `MergeOperation` pre daný riadok obsahuje zlúčené hodnoty čistých stĺpcov a hodnotu ours (predvolene) v stĺpcoch s konfliktom. Konflikt sa naďalej uvádza samostatne.

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

Tu dochádza ku konfliktu v `title` (obe strany ho zmenili odlišne), `content` sa zlúči bez konfliktu (zmenilo ho iba ours) a `status` sa zlúči bez konfliktu (zmenilo ho iba theirs). Operácia obsahuje:

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

## Porovnávanie hodnôt

Hodnoty stĺpcov sa po pretypovaní porovnávajú ako reťazce. `NULL` sa považuje za samostatnú hodnotu:

- `NULL` na `NULL` = bez zmeny.
- `NULL` na `"hello"` = aktualizácia.
- `"hello"` na `NULL` = aktualizácia.
- `"1"` na `1` = bez zmeny (obe hodnoty sa prevedú na reťazec `"1"`).

To zodpovedá spôsobu načítania hodnôt adaptérom pripojenia MerQL: všetky hodnoty databázy sa vracajú ako reťazce (alebo NULL).

## Zlučovanie na úrovni buniek

Ak zlučovanie na úrovni stĺpcov stále vedie ku konfliktu (obe strany zmenili ten istý stĺpec na rôzne hodnoty), merql môže prejsť o úroveň nižšie a použiť [zlúčenie na úrovni buniek](https://merql.inline0.dev/sk/docs/merge/cell-level). Vzťahuje sa na stĺpce TEXT (porovnávanie rozdielov po riadkoch) a JSON (porovnávanie rozdielov po kľúčoch) a rieši prípady, keď obe strany upravili rôzne časti hodnoty toho istého stĺpca.
