Genereren van SQL
SqlGenerator zet een MergeResult om in geparametriseerde SQL-instructies. Alle waarden worden als parameters gebonden en nooit in de SQL-string ingevuld.
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']
}
Gebruik generateGuarded() wanneer een beoordeeld samenvoegingsplan alleen mag worden toegepast als live rijen nog overeenkomen met een verwachte snapshot.
use Merql\Apply\SqlGenerator;
use Merql\Snapshot\SnapshotStore;
$statements = SqlGenerator::generateGuarded(
$selectedResult,
SnapshotStore::load('theirs'),
);
Instructieformaat
Elke instructie is een associatieve array met twee sleutels:
[
'sql' => 'INSERT INTO `posts` (`id`, `title`) VALUES (?, ?)',
'params' => [42, 'New Title'],
]
Identifiers (tabel- en kolomnamen) worden geciteerd volgens de stijl van de databasedriver. MySQL gebruikt backticks en SQLite gebruikt dubbele aanhalingstekens. Als er geen driver is opgegeven, worden standaard backticks gebruikt.
Volgorde van bewerkingen
Bewerkingen worden gegroepeerd op type en in deze volgorde uitgevoerd:
- Eerst INSERTs -- nieuwe rijen moeten bestaan voordat ernaar kan worden verwezen in updates.
- Daarna UPDATEs.
- Tot slot DELETEs -- verwijzingen naar rijen moeten worden verwijderd voordat die rijen worden verwijderd.
$statements = SqlGenerator::generate($result);
// All INSERTs, then all UPDATEs, then all DELETEs.
Volgorde op basis van foreign keys
Wanneer afhankelijkheden van foreign keys zijn opgegeven, worden bewerkingen binnen elke groep topologisch gesorteerd. Bovenliggende tabellen worden vóór onderliggende tabellen verwerkt bij inserts en updates. Bij deletes worden onderliggende tabellen vóór bovenliggende tabellen verwerkt.
$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 voert een topologische sortering uit op de afhankelijkheidsgraaf. Circulaire afhankelijkheden worden gedetecteerd en doorbroken om oneindige lussen te voorkomen.
FK's automatisch detecteren
Applier leest automatisch relaties tussen foreign keys uit de database:
use Merql\Apply\Applier;
$applier = new Applier($connection);
$applied = $applier->apply($result);
// FK dependencies are read from the database via the driver.
Voorbeelden van gegenereerde SQL
INSERT
INSERT INTO `posts` (`id`, `title`, `content`, `status`) VALUES (?, ?, ?, ?)
-- params: [42, 'New Post', 'Body text', 'draft']
Alle kolommen uit de waarden van de bewerking worden opgenomen.
UPDATE
UPDATE `posts` SET `title` = ?, `status` = ? WHERE `id` = ?
-- params: ['New Title', 'publish', 42]
Identiteitskolommen (primary key) worden uitgesloten van de SET-clausule en gebruikt in de WHERE-clausule. De waarden voor de WHERE-clausule worden verkregen door de rijsleutel te decoderen.
DELETE
DELETE FROM `posts` WHERE `id` = ?
-- params: [42]
Alleen identiteitskolommen staan in de WHERE-clausule.
Beveiligde UPDATE
Beveiligde updates bevatten zowel identiteitsclausules als clausules voor verwachte live rijen.
UPDATE `posts` SET `title` = ? WHERE `id` = ? AND `status` = ?
-- params: ['New Title', 42, 'draft']
Als de rij niet langer de verwachte status heeft, beïnvloedt de instructie nul rijen en draait beveiligd toepassen de transactie terug.
Beveiligde INSERT
Beveiligde inserts gebruiken NOT EXISTS om te voorkomen dat er wordt ingevoegd voor een identiteit die is verschenen nadat het plan is gemaakt.
INSERT INTO `posts` (`id`, `title`) SELECT ?, ? WHERE NOT EXISTS (
SELECT 1 FROM `posts` WHERE `id` = ?
)
-- params: [42, 'New Post', 42]
NULL verwerken
NULL-waarden worden als PHP null doorgegeven in de params-array. De verbindingsadapter verzorgt de binding:
$statements = SqlGenerator::generate($result);
// params might contain: [42, null, 'draft']
// The adapter binds null as SQL NULL
In de uitvoer van een dry run worden NULL-waarden weergegeven als de letterlijke string NULL, zonder aanhalingstekens.
Identiteitskolommen detecteren
SqlGenerator bepaalt welke kolommen de rij-identiteit vormen door naar TableSnapshot::identityColumns van de basissnapshot te kijken. Deze kolommen worden gebruikt voor WHERE-clausules bij UPDATE- en DELETE-instructies en uitgesloten van SET-clausules bij UPDATE's.
Als er geen basissnapshot beschikbaar is, wordt de eerste kolom in de values-array als terugvaloptie gebruikt. Als de values-array leeg is, wordt id aangenomen.
Een driver doorgeven
Geef een instantie van Driver door om te bepalen hoe identifiers worden geciteerd:
use Merql\Driver\SqliteDriver;
$statements = SqlGenerator::generate(
$result,
driver: new SqliteDriver(),
);
// Uses double-quote quoting: "posts", "title"