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.
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.
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:
[
'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í:
- Nejprve INSERTs — nové řádky musí existovat předtím, než se na ně mohou odkazovat aktualizace.
- Poté UPDATEs.
- Nakonec DELETEs — před odstraněním je třeba zrušit odkazy na řádky.
$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.
$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:
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
INSERT INTO `posts` (`id`, `title`, `content`, `status`) VALUES (?, ?, ?, ?)
-- params: [42, 'New Post', 'Body text', 'draft']
Zahrnou se všechny sloupce z hodnot operace.
UPDATE
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
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.
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.
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ů:
$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:
use Merql\Driver\SqliteDriver;
$statements = SqlGenerator::generate(
$result,
driver: new SqliteDriver(),
);
// Uses double-quote quoting: "posts", "title"