
# Dokumentacja CLI

merql zawiera CLI do tworzenia migawek, obliczania różnic i przeprowadzania scaleń bezpośrednio z terminala. Composer instaluje go jako `vendor/bin/merql`; w kopii repozytorium merql jest dostępny jako `bin/merql`.

`vendor/bin/merql` działa po instalacji jako zależność, ponieważ merql 0.4.1. Wcześniejsze wydania szukały autoloadera Composer tylko w katalogu własnym pakietu `vendor/` i nie działały, gdy merql instalowano jako zależność.

## Szybki start

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

Scalenie trójstronne wymaga migawek ours i theirs utworzonych na podstawie dwóch baz danych, które rozeszły się ze stanu base. Dla każdej migawki wskaż `MERQL_DB_DSN` właściwą bazę danych:

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

Utworzenie wszystkich trzech migawek kolejno z tej samej bazy danych nie zadziała jako scalanie: theirs zawierałaby już zmiany ours, więc każdy wiersz wstawiony przez ours zostałby zgłoszony jako konflikt `insert_insert`.

## Zmienne środowiskowe

CLI pobiera dane połączenia z bazą z zmiennych środowiskowych. Możesz
połączyć się za pomocą ciągu DSN PDO lub osobnych parametrów MySQL.

### Połączenie na podstawie DSN

W przypadku połączeń obsługiwanych przez PDO użyj `MERQL_DB_DSN`. To zalecane podejście
dla SQLite i konfiguracji niestandardowych. DSN musi wskazywać bazę danych MySQL
lub SQLite: CLI nie może zarejestrować sterownika dla innych silników.

| Zmienna | Opis | Przykład |
|---|---|---|
| `MERQL_DB_DSN` | Pełny ciąg DSN PDO | `sqlite:/path/to/db.sqlite` |
| `MERQL_DB_USER` | Nazwa użytkownika (opcjonalna przy DSN) | `root` |
| `MERQL_DB_PASS` | Hasło (opcjonalne przy 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"
```

Użyj bazy danych SQLite przechowywanej w pliku. Każde polecenie CLI działa w osobnym procesie, więc
`sqlite::memory:` zawsze otwiera nową, pustą bazę danych, a jej migawka
nie zawiera żadnych tabel.

### Skrócona forma MySQL

Jeśli `MERQL_DB_DSN` nie jest ustawiona, CLI korzysta ze zmiennych właściwych dla MySQL.

| Zmienna | Wartość domyślna | Opis |
|---|---|---|
| `MERQL_DB_NAME` | (wymagane) | Nazwa bazy danych |
| `MERQL_DB_HOST` | `127.0.0.1` | Host MySQL |
| `MERQL_DB_PORT` | `3306` | Port MySQL |
| `MERQL_DB_USER` | `root` | Nazwa użytkownika MySQL |
| `MERQL_DB_PASS` | (puste) | Hasło MySQL |
| `MERQL_DB_ADAPTER` | `pdo` | Ustaw `mysqli`, aby użyć adaptera 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"
```

## Polecenia

### `merql snapshot <name>`

Utwórz migawkę bieżącego stanu bazy danych wskazanej przez zmienne środowiskowe i zapisz ją pod wybraną nazwą. To jedyne polecenie, które łączy się z bazą danych.

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

Wynik:

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

Migawki są zapisywane jako pliki JSON w katalogu `.merql/snapshots/` w katalogu roboczym (zobacz [Przechowywanie migawek](#snapshot-storage)). Nazwa może zawierać wyłącznie znaki alfanumeryczne, myślniki i podkreślenia.

Typowy przebieg pracy: utwórz migawkę przed wprowadzeniem zmian, a potem kolejną po ich wprowadzeniu. Te dwie migawki stanowią podstawę do obliczenia różnicy lub przeprowadzenia scalenia.

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

Porównaj dwie migawki o podanych nazwach i wyświetl podsumowanie różnic.

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

Wynik:

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

Obie migawki muszą już istnieć (wcześniej utworzone za pomocą `merql snapshot`). Obliczenie różnicy nie wymaga połączenia z bazą danych, ponieważ odbywa się na zapisanych plikach migawek.

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

Przeprowadź scalenie trzech migawek o podanych nazwach.

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

Wynik:

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

Wszystkie trzy migawki muszą już istnieć. Scalenie nie wymaga połączenia z bazą danych, ponieważ odbywa się na zapisanych plikach migawek, i nigdy nie zapisuje zmian w bazie danych: CLI nie ma polecenia apply. Użyj PHP API, aby zastosować wynik scalenia.

CLI scala na poziomie kolumn. Nie wykonuje scalenia na poziomie komórek w kolumnach TEXT ani JSON, dlatego dwie różne zmiany w tej samej kolumnie zawsze powodują konflikt ([#7](https://github.com/inline0/merql/issues/7)). Aby scalać na poziomie komórek, użyj `ThreeWayMerge` z `CellMergeConfig` w PHP.

#### `--dry-run`

Dodaj flagę `--dry-run`, aby wyświetlić podgląd instrukcji SQL generowanych przez scalenie, bez ich wykonywania. Instrukcje opisują sposób przekształcenia stanu base w wynik scalenia, uwzględniają więc zmiany z obu stron.

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

Wynik:

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

## Polecenia deweloperskie

Kopia repozytorium merql zawiera więcej skryptów w `bin/` dla zestawu testów opartego na oracle. Nie należą one do pakietu Composer, dlatego po instalacji zależności dostępne jest tylko `vendor/bin/merql`. Uruchamiaj je z katalogu głównego repozytorium po `composer install`.

| Polecenie | Opis |
|---|---|
| `./bin/oracle <name>` | Oblicza oczekiwany wynik scalenia dla danego scenariusza |
| `./bin/actual <name>` | Uruchamia merql dla scenariusza i zapisuje wynik |
| `./bin/compare <name>` | Porównuje wynik oracle z rzeczywistym wynikiem |
| `./bin/test-scenario <name>` | Pełny proces: konfiguracja, oracle, wynik rzeczywisty, porównanie |
| `./bin/test-regression` | Uruchamia wszystkie scenariusze |
| `./bin/test-regression --category clean` | Uruchamia jedną kategorię: `clean`, `conflict`, `identity`, `types`, `scale` lub `edge` |
| `./bin/test-regression --fast` | Tylko wynik zaliczone/niezaliczone, bez raportów |
| `./bin/verify-compliance` | Pełny raport zgodności |
| `./bin/verify-all` | PHPStan + styl kodu + PHPUnit + test regresji oracle |

`bin/test-regression` przyjmuje również `--jobs`, ale obecnie ignoruje tę wartość i uruchamia scenariusze jeden po drugim ([#5](https://github.com/inline0/merql/issues/5)). Nieznany `--category` wyświetla `No scenarios found` i kończy działanie powodzeniem.

Zobacz [Strategia testowania](https://merql.inline0.dev/pl/docs/advanced/testing), aby poznać układ scenariuszy.

## Kod wyjścia

`merql snapshot`, `diff` i `merge` kończą działanie z kodem 1, gdy brakuje argumentu, a `snapshot` również wtedy, gdy nie skonfigurowano połączenia. Brak migawki kończy polecenie nieobsłużonym wyjątkiem `SnapshotException` i niezerowym kodem. Nieznane polecenie wyświetla `Unknown command`, ale obecnie kończy działanie z kodem 0 ([#3](https://github.com/inline0/merql/issues/3)).

## Przechowywanie migawek

Migawki są przechowywane w `.merql/snapshots/` względem katalogu roboczego. Każda migawka to pojedynczy plik JSON o nazwie `<name>.json`. Uruchamiaj wszystkie polecenia z tego samego katalogu, aby mogły odnaleźć migawki utworzone przez inne polecenia.

CLI nie ma opcji ani zmiennej środowiskowej pozwalającej wskazać inną lokalizację ([#8](https://github.com/inline0/merql/issues/8)). Aby z niej skorzystać, przejdź do innego katalogu roboczego przed uruchomieniem programu. W PHP ustaw katalog przed tworzeniem lub wczytywaniem migawek:

```php
use Merql\Snapshot\SnapshotStore;

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

Pliki migawek są przenośne. Możesz kopiować je między komputerami, dodawać do systemu kontroli wersji lub udostępniać w celu wspólnego debugowania. Migawkę utworzoną przez CLI można wczytać w PHP za pomocą `SnapshotStore::load()` i odwrotnie, o ile oba programy korzystają z tego samego katalogu.
