Přejít k obsahu

Generování SQL

SqlGenerator převádí MergeResult na parametrizované příkazy SQL. Všechny hodnoty se předávají jako parametry; nikdy se nevkládají přímo do řetězce SQL.

PHP
use Merql\Apply\SqlGenerator;

$statements = SqlGenerator::generate($result);

foreach ($statements as $stmt) {
    echo $stmt['sql'] . "\n";
    // INSERT INTO `posts` (`id`, `title`, `status`) VALUES (?, ?, ?)
    print_r($stmt['params']);
    // [42, 'New Title', 'publish']
}

Použijte generateGuarded(), když se má zkontrolovaný plán sloučení použít pouze tehdy, pokud aktuální řádky stále odpovídají očekávanému snímku.

PHP
use Merql\Apply\SqlGenerator;
use Merql\Snapshot\SnapshotStore;

$statements = SqlGenerator::generateGuarded(
    $selectedResult,
    SnapshotStore::load('theirs'),
);

Formát příkazů

Každý příkaz je asociativní pole se dvěma klíči:

PHP
[
    'sql'    => 'INSERT INTO `posts` (`id`, `title`) VALUES (?, ?)',
    'params' => [42, 'New Title'],
]

Identifikátory (názvy tabulek a sloupců) se uzavírají podle stylu uvozování databázového ovladače. MySQL používá zpětné apostrofy, SQLite používá dvojité uvozovky. Pokud ovladač není zadán, standardně se použijí zpětné apostrofy.

Pořadí operací

Operace se seskupují podle typu a provádějí v tomto pořadí:

  1. Nejprve INSERTs — nové řádky musí existovat předtím, než se na ně mohou odkazovat aktualizace.
  2. Poté UPDATEs.
  3. Nakonec DELETEs — před odstraněním je třeba zrušit odkazy na řádky.
PHP
$statements = SqlGenerator::generate($result);
// All INSERTs, then all UPDATEs, then all DELETEs.

Řazení podle cizích klíčů

Jsou-li zadány závislosti cizích klíčů, operace v každé skupině se seřadí topologicky. Při vkládání a aktualizaci se nejprve zpracují nadřazené tabulky, před podřízenými. Při odstranění se nejprve zpracují podřízené tabulky, před nadřazenými.

PHP
$fkDependencies = [
    'comments' => ['posts'],        // comments references posts
    'post_meta' => ['posts'],       // post_meta references posts
];

$statements = SqlGenerator::generate($result, fkDependencies: $fkDependencies);
// INSERTs: posts first, then comments and post_meta
// DELETEs: comments and post_meta first, then posts

ForeignKeyResolver provádí topologické řazení grafu závislostí. Kruhové závislosti detekuje a přeruší, aby se zabránilo nekonečným smyčkám.

Automatická detekce FK

Applier automaticky načítá vztahy cizích klíčů z databáze:

PHP
use Merql\Apply\Applier;

$applier = new Applier($connection);
$applied = $applier->apply($result);
// FK dependencies are read from the database via the driver.

Ukázky generovaného SQL

INSERT

Sql
INSERT INTO `posts` (`id`, `title`, `content`, `status`) VALUES (?, ?, ?, ?)
-- params: [42, 'New Post', 'Body text', 'draft']

Zahrnou se všechny sloupce z hodnot operace.

UPDATE

Sql
UPDATE `posts` SET `title` = ?, `status` = ? WHERE `id` = ?
-- params: ['New Title', 'publish', 42]

Sloupce identity (primární klíč) jsou vyloučeny z klauzule SET a použity v klauzuli WHERE. Hodnoty pro WHERE se získají dekódováním klíče řádku.

DELETE

Sql
DELETE FROM `posts` WHERE `id` = ?
-- params: [42]

V klauzuli WHERE se objeví pouze sloupce identity.

Chráněná UPDATE

Chráněné aktualizace obsahují klauzule identity i klauzule pro očekávaný aktuální řádek.

Sql
UPDATE `posts` SET `title` = ? WHERE `id` = ? AND `status` = ?
-- params: ['New Title', 42, 'draft']

Pokud řádek již nemá očekávané status, příkaz ovlivní nula řádků a chráněné použití vrátí transakci zpět.

Chráněná INSERT

Chráněné vložení používá NOT EXISTS, aby nevložilo řádek s identitou, která se objevila od vytvoření plánu.

Sql
INSERT INTO `posts` (`id`, `title`) SELECT ?, ? WHERE NOT EXISTS (
  SELECT 1 FROM `posts` WHERE `id` = ?
)
-- params: [42, 'New Post', 42]

Zpracování NULL

Hodnoty NULL se předávají jako PHP null v poli parametrů. Adaptér připojení se postará o navázání parametrů:

PHP
$statements = SqlGenerator::generate($result);
// params might contain: [42, null, 'draft']
// The adapter binds null as SQL NULL

Ve výstupu náhledu nanečisto se hodnoty NULL zobrazují jako řetězec NULL bez uvozovek.

Detekce sloupců identity

SqlGenerator určuje sloupce tvořící identitu řádku podle TableSnapshot::identityColumns základního snímku. Tyto sloupce se používají v klauzulích WHERE příkazů UPDATE a DELETE a jsou vyloučeny z klauzulí SET příkazů UPDATE.

Pokud základní snímek není k dispozici, jako náhradní řešení se použije první sloupec v poli hodnot. Pokud je pole hodnot prázdné, předpokládá se id.

Předání ovladače

Chcete-li řídit uvozování identifikátorů, předejte instanci Driver:

PHP
use Merql\Driver\SqliteDriver;

$statements = SqlGenerator::generate(
    $result,
    driver: new SqliteDriver(),
);
// Uses double-quote quoting: "posts", "title"