
# Referenca CLI

merql vključuje CLI za zajem posnetkov, izračun razlik in izvajanje združitev neposredno iz terminala. Composer ga namesti kot `vendor/bin/merql`; v klonu repozitorija merql je `bin/merql`.

`vendor/bin/merql` deluje tudi pri namestitvi odvisnosti, saj merql 0.4.1. Starejše izdaje so samodejni nalagalnik Composer iskale samo v lastni mapi paketa `vendor/` in odpovedale, ko je bil merql nameščen kot odvisnost.

## Hiter začetek

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

Za tristransko združitev morata biti na voljo posnetka »naše« in »njihovo«, zajeta iz dveh podatkovnih zbirk, ki sta se razšli od osnove. Za vsak posnetek usmerite `MERQL_DB_DSN` na ustrezno podatkovno zbirko:

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

Če vse tri posnetke zaporedoma zajamete iz iste podatkovne zbirke, združitev ne bo delovala: »njihovo« bo že vsebovalo spremembe »našega«, zato bo vsaka vrstica, ki jo je vstavil »naš«, prijavljena kot konflikt `insert_insert`.

## Spremenljivke okolja

CLI prebere podrobnosti povezave s podatkovno zbirko iz spremenljivk okolja. Povežete se lahko z nizom DSN za PDO ali s posameznimi parametri MySQL.

### Povezava prek DSN

Za povezave PDO uporabite `MERQL_DB_DSN`. To je priporočeni pristop za SQLite in nestandardne konfiguracije. DSN mora kazati na podatkovno zbirko MySQL ali SQLite, saj CLI ne more registrirati gonilnika za druge pogone.

| Spremenljivka | Opis | Primer |
|---|---|---|
| `MERQL_DB_DSN` | Celoten niz DSN za PDO | `sqlite:/path/to/db.sqlite` |
| `MERQL_DB_USER` | Uporabniško ime (izbirno z DSN) | `root` |
| `MERQL_DB_PASS` | Geslo (izbirno z 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"
```

Uporabite podatkovno zbirko SQLite, shranjeno v datoteki. Vsak ukaz CLI se izvede v svojem procesu, zato `sqlite::memory:` vedno odpre novo, prazno podatkovno zbirko, njen posnetek pa ne vsebuje tabel.

### Okrajšava MySQL

Če `MERQL_DB_DSN` ni nastavljena, CLI uporabi nadomestne spremenljivke, specifične za MySQL.

| Spremenljivka | Privzeto | Opis |
|---|---|---|
| `MERQL_DB_NAME` | (obvezno) | Ime podatkovne zbirke |
| `MERQL_DB_HOST` | `127.0.0.1` | Gostitelj MySQL |
| `MERQL_DB_PORT` | `3306` | Vrata MySQL |
| `MERQL_DB_USER` | `root` | Uporabniško ime MySQL |
| `MERQL_DB_PASS` | (prazno) | Geslo MySQL |
| `MERQL_DB_ADAPTER` | `pdo` | Nastavite na `mysqli` za uporabo povezovalnika mysqli |

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

## Ukazi

### `merql snapshot <name>`

Zajame trenutno stanje podatkovne zbirke, določene s spremenljivkami okolja, in ga shrani kot poimenovan posnetek. To je edini ukaz, ki se poveže s podatkovno zbirko.

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

Izhod:

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

Posnetki se privzeto shranijo kot datoteke JSON v `.merql/snapshots/` pod delovnim imenikom (glejte [Shranjevanje posnetkov](#snapshot-storage)). Ime lahko vsebuje samo črke, številke, vezaje in podčrtaje.

Običajen potek dela: zajemite posnetek pred spremembami, nato pa še enega po njih. Ta posnetka sta osnova za izračun razlike ali združitev.

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

Primerja dva poimenovana posnetka in prikaže povzetek razlik.

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

Izhod:

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

Oba posnetka morata že obstajati (predhodno morata biti zajeta z ukazom `merql snapshot`). Za izračun razlike povezava s podatkovno zbirko ni potrebna, saj se uporabijo shranjene datoteke posnetkov.

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

Izvede tristransko združitev treh poimenovanih posnetkov.

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

Izhod:

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

Vsi trije posnetki morajo že obstajati. Za združitev povezava s podatkovno zbirko ni potrebna, saj se uporabijo shranjene datoteke posnetkov; ukaz CLI ne vsebuje ukaza za uporabo. Za uporabo rezultata združitve uporabite PHP API.

CLI združuje na ravni stolpcev. Ne izvaja združevanja na ravni celic za stolpce TEXT ali JSON, zato sta različni spremembi istega stolpca vedno konflikt ([#7](https://github.com/inline0/merql/issues/7)). Za združevanje na ravni celic uporabite `ThreeWayMerge` z `CellMergeConfig` v PHP.

#### `--dry-run`

Dodajte zastavico `--dry-run` za predogled stavkov SQL, ki bi jih ustvarila združitev, ne da bi jih izvedli. Stavki opisujejo pretvorbo osnovnega stanja v združeni rezultat, zato vključujejo spremembe obeh strani.

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

Izhod:

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

## Razvojni ukazi

Klon repozitorija merql vsebuje v `bin/` dodatne skripte za testno zbirko, vodeno z referenčnimi rezultati. Ti niso del paketa Composer, zato so pri namestitvi odvisnosti na voljo samo `vendor/bin/merql`. Zaženite jih iz korenske mape repozitorija po ukazu `composer install`.

| Ukaz | Opis |
|---|---|
| `./bin/oracle <name>` | Izračuna pričakovani rezultat združitve za scenarij |
| `./bin/actual <name>` | Zažene merql za scenarij in zajame izhod |
| `./bin/compare <name>` | Primerja referenčni in dejanski izhod |
| `./bin/test-scenario <name>` | Celoten potek: nastavitev, referenčni rezultat, dejanski rezultat, primerjava |
| `./bin/test-regression` | Zažene vse scenarije |
| `./bin/test-regression --category clean` | Zažene eno kategorijo: `clean`, `conflict`, `identity`, `types`, `scale` ali `edge` |
| `./bin/test-regression --fast` | Samo uspeh/neuspeh, brez poročil |
| `./bin/verify-compliance` | Celotno poročilo o skladnosti |
| `./bin/verify-all` | PHPStan + slog kode + PHPUnit + regresijski preizkusi referenčnih rezultatov |

`bin/test-regression` sprejema tudi `--jobs`, vendar trenutno prezre vrednost in scenarije zažene enega za drugim ([#5](https://github.com/inline0/merql/issues/5)). Neznan `--category` izpiše `No scenarios found` in se uspešno zaključi.

Za razporeditev scenarijev glejte [Strategija testiranja](https://merql.inline0.dev/sl/docs/advanced/testing).

## Izhodno stanje

Ukazi `merql snapshot`, `diff` in `merge` se končajo s statusom 1, če manjka argument; enako velja za `snapshot`, kadar povezava ni konfigurirana. Če posnetek manjka, se ukaz konča z neujeto izjemo `SnapshotException` in statusom, ki ni nič. Neznan ukaz izpiše `Unknown command`, trenutno pa se konča s statusom 0 ([#3](https://github.com/inline0/merql/issues/3)).

## Shranjevanje posnetkov

Posnetki so shranjeni v `.merql/snapshots/` glede na delovni imenik. Vsak posnetek je ena sama datoteka JSON z imenom `<name>.json`. Vse ukaze zaženite iz istega imenika, da bodo lahko našli posnetke drug drugega.

CLI nima možnosti ali spremenljivke okolja za drugo lokacijo ([#8](https://github.com/inline0/merql/issues/8)). Če želite uporabiti drugo, pred zagonom spremenite delovni imenik. V PHP nastavite imenik pred zajemom ali nalaganjem posnetkov:

```php
use Merql\Snapshot\SnapshotStore;

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

Datoteke posnetkov so prenosljive. Lahko jih kopirate med računalniki, vključite v sistem za nadzor različic ali delite za skupinsko odpravljanje napak. Posnetek, zajet z CLI, lahko naložite v PHP z ukazom `SnapshotStore::load()` in tudi obratno, če oba uporabljata isti imenik.
