
# CLI-viite

merql sisältää CLI-ohjelman tilannevedosten ottamiseen, erojen laskemiseen ja yhdistämisten suorittamiseen suoraan päätteessä. Composer asentaa sen nimellä `vendor/bin/merql`; merql-tietovaraston työkopiossa sen nimi on `bin/merql`.

`vendor/bin/merql` toimii riippuvuusasennuksesta, koska merql 0.4.1. Aiemmat julkaisut etsivät Composer-automaattisesti latautuvaa tiedostoa vain paketin omasta `vendor/`-hakemistosta ja epäonnistuivat, kun merql asennettiin riippuvuutena.

## Pika-aloitus

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

Kolmen suunnan yhdistäminen edellyttää, että meidän-puoli ja heidän-puoli on tallennettu kahdesta pohjasta erkaantuneesta tietokannasta. Osoita `MERQL_DB_DSN` kunkin tilannevedoksen ottamista varten oikeaan tietokantaan:

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

Kaikkien kolmen tilannevedoksen ottaminen samasta tietokannasta peräkkäin ei toimi yhdistämisessä: heidän-puolensa sisältäisi jo meidän muutoksemme, joten jokaisesta meidän lisäämästämme rivistä ilmoitettaisiin `insert_insert`-ristiriitana.

## Ympäristömuuttujat

CLI lukee tietokantayhteyden tiedot ympäristömuuttujista. Yhteyden voi muodostaa joko PDO DSN -merkkijonolla tai yksittäisillä MySQL-parametreilla.

### DSN-yhteys

Käytä PDO-pohjaisissa yhteyksissä arvoa `MERQL_DB_DSN`. Tämä on suositeltu tapa SQLite-asetuksissa ja muissa kuin vakiomäärityksissä. DSN:n on viitattava MySQL- tai SQLite-tietokantaan: CLI-ohjelmalla ei voi rekisteröidä ajuria muille tietokantamoottoreille.

| Muuttuja | Kuvaus | Esimerkki |
|---|---|---|
| `MERQL_DB_DSN` | Koko PDO DSN -merkkijono | `sqlite:/path/to/db.sqlite` |
| `MERQL_DB_USER` | Käyttäjätunnus (valinnainen DSN:n kanssa) | `root` |
| `MERQL_DB_PASS` | Salasana (valinnainen DSN:n kanssa) | `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"
```

Käytä tiedostopohjaista SQLite-tietokantaa. Jokainen CLI-komento suoritetaan omassa prosessissaan, joten `sqlite::memory:` avaa aina uuden, tyhjän tietokannan, eikä sen tilannevedoksessa ole tauluja.

### MySQL-lyhenne

Jos arvoa `MERQL_DB_DSN` ei aseteta, CLI käyttää MySQL-kohtaisia muuttujia varavaihtoehtona.

| Muuttuja | Oletusarvo | Kuvaus |
|---|---|---|
| `MERQL_DB_NAME` | (pakollinen) | Tietokannan nimi |
| `MERQL_DB_HOST` | `127.0.0.1` | MySQL-palvelin |
| `MERQL_DB_PORT` | `3306` | MySQL-portti |
| `MERQL_DB_USER` | `root` | MySQL-käyttäjätunnus |
| `MERQL_DB_PASS` | (tyhjä) | MySQL-salasana |
| `MERQL_DB_ADAPTER` | `pdo` | Aseta arvoon `mysqli` käyttääksesi mysqli-adapteria |

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

## Komennot

### `merql snapshot <name>`

Tallenna ympäristömuuttujien määrittämän tietokannan nykytila nimettynä tilannevedoksena. Tämä on ainoa komento, joka muodostaa yhteyden tietokantaan.

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

Tuloste:

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

Tilannevedokset tallennetaan JSON-tiedostoina työhakemiston alla olevaan hakemistoon `.merql/snapshots/` (katso [Tilannevedosten tallennus](#snapshot-storage)). Nimessä saa olla vain aakkosnumeerisia merkkejä, tavuviivoja ja alaviivoja.

Tavallinen työnkulku: ota tilannevedos ennen muutosten tekemistä ja toinen niiden jälkeen. Nämä kaksi tilannevedosta muodostavat vertailun tai yhdistämisen perustan.

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

Vertaa kahta nimettyä tilannevedosta ja näytä eroista yhteenveto.

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

Tuloste:

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

Molempien tilannevedosten on oltava jo olemassa (aiemmin tallennettu komennolla `merql snapshot`). Vertailu ei tarvitse tietokantayhteyttä, koska se käsittelee tallennettuja tilannevedostiedostoja.

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

Suorita kolmen nimetyn tilannevedoksen kolmen suunnan yhdistäminen.

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

Tuloste:

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

Kaikkien kolmen tilannevedoksen on oltava jo olemassa. Yhdistäminen ei tarvitse tietokantayhteyttä, koska se käsittelee tallennettuja tilannevedostiedostoja, eikä se koskaan kirjoita tietokantaan: CLI-ohjelmassa ei ole käyttöönottokomentoa. Käytä yhdistämistuloksen käyttöönottoon komentoa PHP API.

CLI yhdistää saraketasolla. Se ei yhdistä TEXT- tai JSON-sarakkeita solutasolla, joten saman sarakkeen kaksi erilaista muutosta ovat aina ristiriita tässä ([#7](https://github.com/inline0/merql/issues/7)). Solutason yhdistämiseen käytä toimintoa `ThreeWayMerge` paketin `CellMergeConfig` kanssa PHP-ympäristössä.

#### `--dry-run`

Lisää lippu `--dry-run` esikatsellaksesi SQL-lausekkeita, jotka yhdistäminen loisi, suorittamatta mitään. Lausekkeet kuvaavat pohjatilan muuttamista yhdistetyksi tulokseksi, joten niihin sisältyvät molempien puolten muutokset.

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

Tuloste:

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

## Kehityskomennot

merql-tietovaraston työkopiossa on lisää skriptejä hakemistossa `bin/` oraakkelipohjaista testisarjaa varten. Ne eivät sisälly Composer-pakettiin, joten riippuvuusasennuksessa käytettävissä on vain `vendor/bin/merql`. Suorita ne tietovaraston juuresta komennon `composer install` jälkeen.

| Komento | Kuvaus |
|---|---|
| `./bin/oracle <name>` | Laske skenaarion odotettu yhdistämistulos |
| `./bin/actual <name>` | Suorita merql skenaariossa ja tallenna tuloste |
| `./bin/compare <name>` | Vertaa oraakkelin ja toteutuksen tulosteita |
| `./bin/test-scenario <name>` | Koko työnkulku: alustus, oraakkeli, toteutus, vertailu |
| `./bin/test-regression` | Suorita kaikki skenaariot |
| `./bin/test-regression --category clean` | Suorita yksi luokka: `clean`, `conflict`, `identity`, `types`, `scale` tai `edge` |
| `./bin/test-regression --fast` | Vain läpäisy tai hylkäys, ei raportteja |
| `./bin/verify-compliance` | Täysi vaatimustenmukaisuusraportti |
| `./bin/verify-all` | PHPStan + koodityyli + PHPUnit + oraakkeliregressio |

`bin/test-regression` hyväksyy myös arvon `--jobs`, mutta jättää sen tällä hetkellä huomiotta ja suorittaa skenaariot peräkkäin ([#5](https://github.com/inline0/merql/issues/5)). Tuntematon `--category` tulostaa viestin `No scenarios found` ja päättyy onnistuneesti.

Katso [Testausstrategia](https://merql.inline0.dev/fi/docs/advanced/testing) skenaarion rakenteesta.

## Poistumistila

`merql snapshot`, `diff` ja `merge` päättyvät tilakoodilla 1, jos argumentti puuttuu. Myös `snapshot` päättyy tilakoodilla 1, jos yhteyttä ei ole määritetty. Puuttuva tilannevedos keskeyttää komennon käsittelemättömällä poikkeuksella `SnapshotException` ja nollasta poikkeavalla tilakoodilla. Tuntematon komento tulostaa `Unknown command`, mutta päättyy tällä hetkellä tilakoodilla 0 ([#3](https://github.com/inline0/merql/issues/3)).

## Tilannevedosten tallennus

Tilannevedokset tallennetaan työhakemistoon suhteelliseen polkuun `.merql/snapshots/`. Kukin tilannevedos on yksi JSON-tiedosto nimeltä `<name>.json`. Suorita kaikki komennot samasta hakemistosta, jotta ne löytävät toistensa tilannevedokset.

CLI-komennossa ei ole valitsinta tai ympäristömuuttujaa toisen sijainnin määrittämiseen ([#8](https://github.com/inline0/merql/issues/8)). Jos haluat käyttää toista sijaintia, siirry toiseen työhakemistoon ennen komennon suorittamista. Määritä hakemisto komennossa PHP ennen tilannevedosten tallentamista tai lataamista:

```php
use Merql\Snapshot\SnapshotStore;

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

Tilannevedostiedostot ovat siirrettäviä. Voit kopioida niitä koneiden välillä, lisätä ne versionhallintaan tai jakaa niitä yhteistyötä varten tapahtuvassa virheenjäljityksessä. CLI-komennolla tallennetun tilannevedoksen voi ladata komennossa PHP komennolla `SnapshotStore::load()`, ja myös toisin päin, kunhan molemmat käyttävät samaa hakemistoa.
