
# Introdução

merql é uma biblioteca pura de PHP que realiza mesclagens de três vias do estado do banco de dados. Ela captura snapshots de tabelas, calcula conjuntos de alterações entre snapshots, mescla dois conjuntos de alterações com base em uma base comum e detecta conflitos no nível das colunas. O mesmo algoritmo que git usa para arquivos de código-fonte, aplicado a linhas e colunas em vez de linhas de texto.

Sem ferramentas externas. Compatível com MySQL e SQLite por meio de adaptadores de conexão e drivers de dialeto conectáveis.

## Exemplo rápido

Uma mesclagem precisa de três estados dos mesmos dados: a base da qual as duas cópias partiram e as duas cópias depois de terem sido alteradas de forma independente. Aqui, uma sandbox foi copiada do banco de dados ativo, e ambos foram editados desde então.

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

Cada snapshot é capturado do banco de dados que contém aquele estado. Capturar os três de um único banco de dados, em sequência, não representa duas cópias divergentes: nesse caso, deles já conteria as alterações de nosso, e cada linha inserida por nosso seria indicada como um conflito `insert_insert`.

O resultado lista as operações que transformam a base no estado mesclado, considerando os dois lados, cada uma marcada com sua origem (`ours`, `theirs` ou `merged`). Para gravar as alterações da sandbox no ambiente ativo, aplique as operações que ainda faltam no ambiente ativo usando [Aplicação protegida](https://merql.inline0.dev/pt/docs/apply/guarded).

Ou pela CLI, que se conecta ao banco de dados indicado em `MERQL_DB_DSN` para cada `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
```

## Por que usar merql

A maioria das ferramentas de banco de dados que compara estados trabalha no nível das linhas: se qualquer coluna de uma linha for diferente entre duas versões, a linha inteira é marcada como conflito. Isso gera conflitos falsos quando duas pessoas editam colunas diferentes da mesma linha.

merql mescla no nível das colunas. Se um lado alterou `title` e o outro alterou `status`, as alterações são mescladas sem conflito. Um conflito só é gerado quando os dois lados alteram a mesma coluna para valores diferentes.

Para colunas TEXT e JSON, o merql pode ir além, com a mesclagem no nível da célula. Duas edições em linhas diferentes de uma coluna de texto, ou em chaves diferentes de uma coluna JSON, podem ser mescladas sem conflitos usando o mesmo algoritmo de três vias. A mesclagem no nível da célula é opcional: passe um `CellMergeConfig` para `ThreeWayMerge`. A fachada `Merql` e o CLI fazem a mesclagem apenas no nível das colunas. Consulte [Mesclagem no nível da célula](https://merql.inline0.dev/pt/docs/merge/cell-level).

## O modelo de mesclagem

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

Três estados, como em git. A base é o ancestral comum. Nosso e deles são as duas cópias após divergirem, cada uma capturada do próprio banco de dados. As regras de mesclagem tratam os dois lados da mesma forma. Esses nomes aparecem em `source` de cada operação, nos tipos de conflito (`update_delete` significa que nosso foi atualizado e deles foi excluído) e nas políticas de resolução `OursWins` e `TheirsWins`. Sem uma base comum, não é possível distinguir “adicionado” de “inalterado”.

Uma mesclagem não grava nada por si só. Suas operações transformam a base no estado mesclado, então `Merql::apply()` só executa todas sem problemas em um banco de dados que ainda contém a base. Para incorporar as alterações de um lado a um banco de dados que já contém as alterações do outro, como ao promover alterações da sandbox para o ambiente ativo, aplique apenas as operações que ainda faltam; consulte [Aplicação protegida](https://merql.inline0.dev/pt/docs/apply/guarded).

## Requisitos

- PHP 8.2 ou posterior.
- `ext-mbstring` e `ext-zlib`, exigidos pela dependência `pitmaster/pitmaster` que fornece o diff de texto.
- Uma extensão de banco de dados para o adaptador usado: `ext-pdo` com `ext-pdo_sqlite` ou `ext-pdo_mysql`, ou `ext-mysqli`. `composer.json` do merql apenas sugere `ext-pdo` e `ext-mysqli`, então Composer não verifica se estão instalados.
- Um banco de dados MySQL ou SQLite. Outros mecanismos precisam de um [driver](https://merql.inline0.dev/pt/docs/apply/drivers) personalizado.

## O que não é

merql não é uma ferramenta de migração de esquemas. Ele não replica bancos de dados nem os sincroniza em tempo real. Resolve um problema específico: dado três estados de um banco de dados, produzir um quarto estado mesclado com os conflitos identificados.

## Documentação

- [Primeiros passos](https://merql.inline0.dev/pt/docs/getting-started) -- instalação, primeiro snapshot e primeira mesclagem.
- [CLIReferência](https://merql.inline0.dev/pt/docs/cli) -- referência completa para o comando `vendor/bin/merql`.
- [PHP APIReferência](https://merql.inline0.dev/pt/docs/api) -- documentação completa de API para todas as classes.
- [Planos de mesclagem](https://merql.inline0.dev/pt/docs/merge/plans) -- IDs de operação estáveis, grupos de alterações e seleções.
- [Aplicação protegida](https://merql.inline0.dev/pt/docs/apply/guarded) -- gravações selecionadas com pré-condições para as linhas no ambiente ativo.
- [Reversão](https://merql.inline0.dev/pt/docs/apply/rollback) -- artefatos de reversão e verificações de divergência.
