
# Združevanje na ravni stolpcev

Združevanje na ravni stolpcev je glavna prednost merql pred preprosto primerjavo na ravni vrstic. Ko obe strani spremenita isto vrstico, merql primerja vsak stolpec posebej, namesto da bi celotno vrstico označil kot spor.

## Težava pri združevanju na ravni vrstic

Oglejmo si tabelo `posts`, v kateri dve osebi urejata isto vrstico:

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

Združevanje na ravni vrstic zazna, da sta obe strani spremenili vrstico, in razglasi spor. Toda spremembe se sploh ne prekrivajo. Mi smo uredili `content`, oni pa `title` in `status`.

## Kako združevanje na ravni stolpcev razreši težavo

merql za vsak stolpec posebej uporabi ista trosmerna pravila združevanja:

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

Rezultat: `{ title: "New Title", content: "Body v2", status: "publish" }`. Čista združitev brez sporov.

## Kako deluje

Ko `ThreeWayMerge` zazna, da sta obe strani posodobili isto vrstico, delo prepusti `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)
```

Za vsak stolpec veljajo ista pravila:

| Osnova | Naši | Njihovi | Rezultat |
|---|---|---|---|
| A | A | A | Ohranimo osnovo (brez sprememb) |
| A | A | B | Sprejmemo njihovega |
| A | B | A | Sprejmemo našega |
| A | B | B | Sprejmemo (oba se strinjata) |
| A | B | C | **Spor** (različni vrednosti) |

## Kdaj še vedno pride do sporov

Spor na ravni stolpca nastane, kadar obe strani spremenita isti stolpec na različni vrednosti:

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

Obe strani sta spremenili `title` na različni vrednosti. To je dejanski spor, ki ga je treba razrešiti.

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

## Delni spori

V eni vrstici so lahko hkrati čisto združene vrednosti in spori. Če se en stolpec združi brez težav, pri drugem pa pride do spora, `MergeOperation` za vrstico vsebuje združene vrednosti čistih stolpcev in našo vrednost (privzeto) za stolpce s spori. Spor je še vedno naveden ločeno.

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

Tukaj je pri `title` prišlo do spora (obe strani sta ga različno spremenili), `content` je bil čisto združen (spremenila ga je samo naša stran), `status` pa prav tako (spremenila ga je samo njihova stran). Operacija vsebuje:

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

## Primerjava vrednosti

Vrednosti stolpcev se po pretvorbi primerjajo kot nizi. `NULL` je ločena vrednost:

- `NULL` do `NULL` = brez spremembe.
- `NULL` do `"hello"` = posodobitev.
- `"hello"` do `NULL` = posodobitev.
- `"1"` do `1` = brez spremembe (oboje se pretvori v niz `"1"`).

To ustreza semantiki pridobivanja podatkov adapterja povezave MerQL: vse vrednosti podatkovne zbirke so vrnjene kot nizi (ali NULL).

## Združevanje na ravni celic

Če pri združevanju na ravni stolpcev še vedno pride do spora (obe strani sta isti stolpec spremenili na različni vrednosti), lahko merql združevanje poglobi na [združevanje na ravni celic](https://merql.inline0.dev/sl/docs/merge/cell-level). To velja za stolpce TEXT (razlike po vrsticah) in JSON (razlike po ključih) ter razreši primere, ko sta obe strani spremenili različne dele vrednosti istega stolpca.
