
# Introduktion

merql er et rent PHP-bibliotek, der udfører trevejsfletninger af databasetilstand. Det tager snapshots af tabeller, beregner ændringssæt mellem snapshots, fletter to sæt ændringer ud fra en fælles basis og registrerer konflikter på kolonneniveau. Den samme algoritme, som git bruger til kildefiler, anvendes her på rækker og kolonner i stedet for linjer.

Ingen eksterne værktøjer. Understøtter MySQL og SQLite via tilslutningsbare forbindelsesadaptere og dialektdrivere.

## Hurtigt eksempel

En fletning kræver tre tilstande af de samme data: den base, begge kopier startede fra, og de to kopier efter uafhængige ændringer. Her blev en sandkasse kopieret fra live-databasen, og begge er siden blevet redigeret.

```php
use Merql\Connection;
use Merql\Merql;

$live    = Connection::sqlite('/data/live.sqlite');
$sandbox = Connection::sqlite('/data/sandbox.sqlite');

// Base: live at the moment the sandbox was copied from it.
Merql::init($live);
Merql::snapshot('base');

// ... copy live.sqlite to sandbox.sqlite, then both databases change ...

// Ours: the sandbox with our edits. Theirs: live with its own changes.
Merql::init($sandbox);
Merql::snapshot('ours');
Merql::init($live);
Merql::snapshot('theirs');

$result = Merql::merge('base', 'ours', 'theirs');

if ($result->isClean()) {
    foreach ($result->operations() as $operation) {
        echo "{$operation->type} {$operation->table} #{$operation->rowKey} ({$operation->source})\n";
    }
} else {
    echo "Conflicts: {$result->conflictCount()}\n";
}
```

Hvert øjebliksbillede tages fra den database, der indeholder den pågældende tilstand. At tage alle tre fra én database i rækkefølge beskriver ikke to divergerede kopier: theirs ville allerede indeholde ændringerne fra ours, og hver række, som ours indsatte, ville blive rapporteret som en `insert_insert`-konflikt.

Resultatet viser de handlinger fra begge sider, der ændrer base til den flettede tilstand, hver markeret med sin kilde (`ours`, `theirs` eller `merged`). Hvis sandboxens ændringer skal overføres til live, skal du anvende de handlinger, som live endnu ikke har, med [Guarded Apply](https://merql.inline0.dev/da/docs/apply/guarded).

Eller fra CLI, som opretter forbindelse til databasen med navnet i `MERQL_DB_DSN` for hver `snapshot`:

```bash
MERQL_DB_DSN="sqlite:/data/live.sqlite" vendor/bin/merql snapshot base
# ... copy live.sqlite to sandbox.sqlite, then both databases change ...
MERQL_DB_DSN="sqlite:/data/sandbox.sqlite" vendor/bin/merql snapshot ours
MERQL_DB_DSN="sqlite:/data/live.sqlite" vendor/bin/merql snapshot theirs

vendor/bin/merql merge base ours theirs --dry-run
```

## Hvorfor merql

De fleste databaseværktøjer, der sammenligner tilstande, arbejder på rækkeniveau: Hvis en kolonne i en række afviger mellem to versioner, markeres hele rækken som en konflikt. Det giver falske konflikter, når to personer redigerer forskellige kolonner i samme række.

merql fletter på kolonneniveau. Hvis den ene side har ændret `title`, og den anden har ændret `status`, flettes ændringerne uden konflikt. Der opstår kun en konflikt, hvis begge sider ændrer den samme kolonne til forskellige værdier.

For TEXT- og JSON-kolonner kan merql gå et niveau dybere med fletning på celleniveau. To redigeringer af forskellige linjer i en tekstkolonne eller forskellige nøgler i en JSON-kolonne kan flettes uden konflikt ved hjælp af den samme trevejsalgoritme. Fletning på celleniveau er valgfri: Send en `CellMergeConfig` til `ThreeWayMerge`. Facaden `Merql` og CLI fletter kun på kolonneniveau. Se [Fletning på celleniveau](https://merql.inline0.dev/da/docs/merge/cell-level).

## Flettemodellen

```
         Base (snapshot at fork time)
        /                              \
   Ours (one copy's changes)            Theirs (the other copy's changes)
        \                              /
         --------- MERGE ----------
                     |
              Merged result
              + conflicts (if any)
```

Tre tilstande, som i git. Base er den fælles forfader. Vores og deres er de to kopier efter deres forgrening, hver hentet fra sin egen database. Flettereglerne behandler begge sider ens. Navnene vises i hver handlings `source`, i konflikttyper (`update_delete` betyder, at vores er opdateret, og deres er slettet) og i løsningspolitikkerne `OursWins` og `TheirsWins`. Uden en fælles base kan du ikke skelne mellem »tilføjet« og »uændret«.

En fletning skriver ikke noget i sig selv. Handlingerne ændrer base til den flettede tilstand, så `Merql::apply()` udfører dem alle uden problemer kun på en database, der stadig indeholder base. Hvis du vil overføre den ene sides ændringer til en database, der allerede indeholder den anden side, f.eks. sandbox-redigeringer til live, skal du kun anvende de handlinger, den mangler. Se [Guarded Apply](https://merql.inline0.dev/da/docs/apply/guarded).

## Krav

- PHP 8.2 eller nyere.
- `ext-mbstring` og `ext-zlib`, som kræves af afhængigheden `pitmaster/pitmaster`, der leverer tekstdifferencen.
- En databaseudvidelse til den adapter, du bruger: `ext-pdo` med `ext-pdo_sqlite` eller `ext-pdo_mysql`, eller `ext-mysqli`. merqls `composer.json` foreslår kun `ext-pdo` og `ext-mysqli`, så Composer kontrollerer ikke, om de findes.
- En database af typen MySQL eller SQLite. Andre systemer kræver en brugerdefineret [driver](https://merql.inline0.dev/da/docs/apply/drivers).

## Hvad det ikke er

merql er ikke et værktøj til skemamigrering. Det replikerer ikke databaser eller synkroniserer dem i realtid. Det løser ét specifikt problem: Givet tre databasetilstande opretter det en flettet fjerde tilstand, hvor konflikterne er identificeret.

## Dokumentation

- [Kom godt i gang](https://merql.inline0.dev/da/docs/getting-started) -- installation, første øjebliksbillede, første fletning.
- [CLI Reference](https://merql.inline0.dev/da/docs/cli) -- fuld reference til kommandoen `vendor/bin/merql`.
- [PHP API Reference](https://merql.inline0.dev/da/docs/api) -- komplet API-dokumentation for alle klasser.
- [Fletteplaner](https://merql.inline0.dev/da/docs/merge/plans) -- stabile handlings-id'er, ændringsgrupper og valg.
- [Guarded Apply](https://merql.inline0.dev/da/docs/apply/guarded) -- udvalgte skrivninger med forudbetingelser for live-rækker.
- [Tilbagerulning](https://merql.inline0.dev/da/docs/apply/rollback) -- tilbagerulningsartefakter og afvigelseskontroller.
