
# الدمج على مستوى الأعمدة

يتمثل التفوق الأساسي لـ 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" }
```

يرى الدمج على مستوى الصفوف أن الجانبين غيّرا الصف، فيعلن وجود تعارض. لكن التغييرات لا تتداخل إطلاقًا. عدّلت نسختنا `content`، بينما عدّلت نسختهم `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()`:

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

تُطبّق القواعد نفسها على كل عمود:

| الأساس | 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` إلى قيمتين مختلفتين. هذا تعارض حقيقي يتطلب الحل.

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

## التعارضات الجزئية

يمكن أن يحتوي الصف الواحد على دمج سليم وتعارضات معًا. إذا دُمج أحد الأعمدة بسلاسة بينما تعارض عمود آخر، فسيحتوي `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 فقط). تتضمن العملية:

```php
// 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 التعمق مستوى إضافيًا عبر [الدمج على مستوى الخلية](https://merql.inline0.dev/ar/docs/merge/cell-level). ينطبق ذلك على أعمدة TEXT (مقارنة الفروق سطرًا بسطر) وأعمدة JSON (مقارنة الفروق مفتاحًا بمفتاح)، لحل الحالات التي عدّل فيها الطرفان أجزاء مختلفة من قيمة العمود نفسه.
