
# Referens för CLI

merql levereras med en CLI för att ta snapshots, beräkna skillnader och köra sammanfogningar direkt från terminalen. Composer installerar den som `vendor/bin/merql`; i en utcheckning av merql:s kodarkiv är den `bin/merql`.

`vendor/bin/merql` fungerar vid installation som beroende eftersom merql 0.4.1. Tidigare versioner letade efter Composer-autoloadern endast i paketets egen katalog `vendor/` och misslyckades när merql installerades som ett beroende.

## Snabbstart

```bash
# Capture a baseline from your database.
export MERQL_DB_DSN="sqlite:/path/to/db.sqlite"
vendor/bin/merql snapshot base

# Make some changes, then capture again.
vendor/bin/merql snapshot current

# See what changed.
vendor/bin/merql diff base current
```

En trevägssammanfogning kräver att ours och theirs tas från två databaser som förgrenats från base. Rikta `MERQL_DB_DSN` mot rätt databas för varje snapshot:

```bash
# Base: live before the sandbox was copied from it.
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

# Three-way merge with dry-run preview.
vendor/bin/merql merge base ours theirs --dry-run
```

Det fungerar inte att ta alla tre snapshots efter varandra från samma databas vid en sammanfogning: theirs skulle redan innehålla ours ändringar, så varje rad som ours infogade skulle rapporteras som en `insert_insert`-konflikt.

## Miljövariabler

CLI hämtar databasanslutningsuppgifter från miljövariabler. Du kan ansluta med antingen en PDO DSN-sträng eller enskilda parametrar för MySQL.

### DSN-baserad anslutning

Använd `MERQL_DB_DSN` för PDO-baserade anslutningar. Det här är det rekommenderade tillvägagångssättet för SQLite och för icke-standardkonfigurationer. DSN måste peka på en MySQL- eller SQLite-databas: CLI kan inte registrera en drivrutin för andra databasmotorer.

| Variabel | Beskrivning | Exempel |
|---|---|---|
| `MERQL_DB_DSN` | Fullständig PDO DSN-sträng | `sqlite:/path/to/db.sqlite` |
| `MERQL_DB_USER` | Användarnamn (valfritt med DSN) | `root` |
| `MERQL_DB_PASS` | Lösenord (valfritt med DSN) | `secret` |

```bash
# SQLite file.
export MERQL_DB_DSN="sqlite:/var/data/myapp.sqlite"

# MySQL via DSN.
export MERQL_DB_DSN="mysql:host=127.0.0.1;dbname=mydb;charset=utf8mb4"
export MERQL_DB_USER="root"
export MERQL_DB_PASS="secret"
```

Använd en filbaserad SQLite-databas. Varje CLI-kommando körs i en egen process, så `sqlite::memory:` öppnar alltid en ny, tom databas och en snapshot av den innehåller inga tabeller.

### Kortform för MySQL

När `MERQL_DB_DSN` inte har angetts använder CLI variabler som är specifika för MySQL.

| Variabel | Standardvärde | Beskrivning |
|---|---|---|
| `MERQL_DB_NAME` | (obligatorisk) | Databasnamn |
| `MERQL_DB_HOST` | `127.0.0.1` | Värd för MySQL |
| `MERQL_DB_PORT` | `3306` | Port för MySQL |
| `MERQL_DB_USER` | `root` | Användarnamn för MySQL |
| `MERQL_DB_PASS` | (tomt) | Lösenord för MySQL |
| `MERQL_DB_ADAPTER` | `pdo` | Ställ in på `mysqli` för att använda mysqli-adaptern |

```bash
export MERQL_DB_NAME="wordpress"
export MERQL_DB_HOST="127.0.0.1"
export MERQL_DB_PORT="3306"
export MERQL_DB_USER="root"
export MERQL_DB_PASS="password"
```

## Kommandon

### `merql snapshot <name>`

Ta en snapshot av det aktuella tillståndet för databasen som anges av miljövariablerna och spara den med ett namn. Det här är det enda kommandot som ansluter till en databas.

```bash
vendor/bin/merql snapshot baseline
```

Utdata:

```
Snapshot 'baseline' saved
Tables: posts, comments, users, settings
```

Snapshots sparas som JSON-filer i `.merql/snapshots/` under arbetskatalogen (se [Lagring av snapshots](#snapshot-storage)). Namnet får bara innehålla alfanumeriska tecken, bindestreck och understreck.

Typiskt arbetsflöde: ta en snapshot innan du gör ändringar och ta sedan en till efteråt. De två snapshots ligger till grund för en jämförelse eller sammanfogning.

### `merql diff <base> <current>`

Jämför två namngivna snapshots och visa en sammanfattning av skillnaderna.

```bash
vendor/bin/merql diff baseline current
```

Utdata:

```
Changeset: baseline -> current
  Inserts: 3
  Updates: 7
  Deletes: 1
```

Båda snapshots måste redan finnas (tidigare tagna med `merql snapshot`). Jämförelsen kräver ingen databasanslutning eftersom den arbetar med sparade snapshotfiler.

### `merql merge <base> <ours> <theirs>`

Utför en trevägssammanfogning av tre namngivna snapshots.

```bash
vendor/bin/merql merge base ours theirs
```

Utdata:

```
Merge: base + ours + theirs
  Operations: 12
  Conflicts:  0
  Clean:      yes
```

Alla tre snapshots måste redan finnas. Sammanfogningen kräver ingen databasanslutning eftersom den arbetar med sparade snapshotfiler, och den skriver aldrig till en databas: CLI har inget tillämpningskommando. Använd PHP API för att tillämpa ett sammanfogningsresultat.

CLI sammanfogar på kolumnnivå. Den tillämpar ingen cellbaserad sammanfogning på kolumner av typen TEXT eller JSON, så två olika ändringar av samma kolumn blir alltid en konflikt här ([#7](https://github.com/inline0/merql/issues/7)). Använd `ThreeWayMerge` med en `CellMergeConfig` i PHP för cellbaserad sammanfogning.

#### `--dry-run`

Lägg till flaggan `--dry-run` för att förhandsgranska de SQL-satser som sammanfogningen skulle generera, utan att köra något. Satserna beskriver hur bastillståndet omvandlas till det sammanfogade resultatet, så de omfattar ändringarna från båda sidor.

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

Utdata:

```
Merge: base + ours + theirs
  Operations: 3
  Conflicts:  0
  Clean:      yes

Dry run SQL:
  INSERT INTO `posts` (`id`, `title`, `status`) VALUES ('10', 'New Post', 'draft');
  UPDATE `posts` SET `title` = 'Updated Title' WHERE `id` = '5';
  DELETE FROM `comments` WHERE `id` = '3';
```

## Utvecklingskommandon

En utcheckning av merql:s kodarkiv innehåller fler skript i `bin/` för dess orakelbaserade testsvit. De ingår inte i paketet Composer, så en installation som beroende innehåller bara `vendor/bin/merql`. Kör dem från kodarkivets rot efter `composer install`.

| Kommando | Beskrivning |
|---|---|
| `./bin/oracle <name>` | Beräkna förväntat sammanfogningsresultat för ett scenario |
| `./bin/actual <name>` | Kör merql för ett scenario och fånga utdata |
| `./bin/compare <name>` | Jämför orakelutdata med faktisk utdata |
| `./bin/test-scenario <name>` | Hela flödet: konfigurera, kör orakel, kör faktiskt, jämför |
| `./bin/test-regression` | Kör alla scenarier |
| `./bin/test-regression --category clean` | Kör en kategori: `clean`, `conflict`, `identity`, `types`, `scale` eller `edge` |
| `./bin/test-regression --fast` | Endast godkänt/underkänt, inga rapporter |
| `./bin/verify-compliance` | Fullständig kompatibilitetsrapport |
| `./bin/verify-all` | PHPStan + kodstil + PHPUnit + orakelregression |

`bin/test-regression` accepterar också `--jobs`, men ignorerar för närvarande värdet och kör scenarier ett i taget ([#5](https://github.com/inline0/merql/issues/5)). Ett okänt `--category` skriver ut `No scenarios found` och avslutas utan fel.

Se [Teststrategi](https://merql.inline0.dev/sv/docs/advanced/testing) för scenariostrukturen.

## Avslutningsstatus

`merql snapshot`, `diff` och `merge` avslutas med status 1 när ett argument saknas, och `snapshot` gör det också när ingen anslutning har konfigurerats. Om en snapshot saknas avslutas kommandot med ett ohanterat `SnapshotException` och status som inte är noll. Ett okänt kommando skriver ut `Unknown command` men avslutas för närvarande med status 0 ([#3](https://github.com/inline0/merql/issues/3)).

## Lagring av snapshots

Snapshots lagras i `.merql/snapshots/` relativt arbetskatalogen. Varje snapshot är en enda JSON-fil med namnet `<name>.json`. Kör alla kommandon från samma katalog så att de hittar varandras snapshots.

CLI har inget alternativ eller någon miljövariabel för en annan plats ([#8](https://github.com/inline0/merql/issues/8)). Om du vill använda en annan plats byter du arbetskatalog innan du kör kommandot. I PHP anger du katalogen innan du tar eller läser in snapshots:

```php
use Merql\Snapshot\SnapshotStore;

SnapshotStore::setDirectory('/var/data/merql-snapshots');
```

Snapshotfiler är portabla. Du kan kopiera dem mellan datorer, checka in dem i versionshantering eller dela dem för gemensam felsökning. En snapshot som tagits av CLI kan läsas in i PHP med `SnapshotStore::load()`, och omvänt, så länge båda använder samma katalog.
