Generarea SQL
SqlGenerator convertește un MergeResult în instrucțiuni SQL parametrizate. Toate valorile sunt transmise ca parametri, niciodată interpolate în șirul 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']
}
Folosiți generateGuarded() când un plan de îmbinare revizuit ar trebui aplicat doar dacă rândurile live corespund în continuare unui instantaneu așteptat.
use Merql\Apply\SqlGenerator;
use Merql\Snapshot\SnapshotStore;
$statements = SqlGenerator::generateGuarded(
$selectedResult,
SnapshotStore::load('theirs'),
);
Formatul instrucțiunilor
Fiecare instrucțiune este un tablou asociativ cu două chei:
[
'sql' => 'INSERT INTO `posts` (`id`, `title`) VALUES (?, ?)',
'params' => [42, 'New Title'],
]
Identificatorii (numele tabelelor și coloanelor) sunt citați folosind convenția driverului bazei de date. MySQL folosește backtick-uri, iar SQLite folosește ghilimele duble. Dacă nu este furnizat niciun driver, citarea cu backtick-uri este folosită implicit.
Ordonarea operațiilor
-
Mai întâi INSERTs -- rândurile noi trebuie să existe înainte ca actualizările să le poată referi.
-
Apoi UPDATEs.
-
La final DELETEs -- referințele către rânduri trebuie eliminate înainte de ștergere.
-
INSERĂRILE mai întâi -- rândurile noi trebuie să existe înainte ca actualizările să le poată referi.
-
ACTUALIZĂRILE apoi.
-
ȘTERGERILE la final -- referințele către rânduri trebuie eliminate înainte de ștergere.
$statements = SqlGenerator::generate($result);
// All INSERTs, then all UPDATEs, then all DELETEs.
Ordonarea cheilor străine
Când sunt furnizate dependențele dintre cheile străine, operațiile din fiecare grup sunt ordonate topologic. Tabelele părinte sunt procesate înaintea tabelelor copil pentru inserări și actualizări. Tabelele copil sunt procesate înaintea tabelelor părinte pentru ștergeri.
$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 efectuează o sortare topologică a grafului dependențelor. Dependențele circulare sunt detectate și întrerupte pentru a preveni buclele infinite.
Detectarea automată a cheilor străine
Applier citește automat relațiile cheilor străine din baza de date:
use Merql\Apply\Applier;
$applier = new Applier($connection);
$applied = $applier->apply($result);
// FK dependencies are read from the database via the driver.
Exemple generate de SQL
INSERT
INSERT INTO `posts` (`id`, `title`, `content`, `status`) VALUES (?, ?, ?, ?)
-- params: [42, 'New Post', 'Body text', 'draft']
Coloanele de identitate (cheia primară) sunt excluse din clauza SET și folosite în clauza WHERE. Valorile clauzei WHERE provin din decodificarea cheii rândului.
UPDATE
UPDATE `posts` SET `title` = ?, `status` = ? WHERE `id` = ?
-- params: ['New Title', 'publish', 42]
Doar coloanele de identitate apar în clauza WHERE.
DELETE
DELETE FROM `posts` WHERE `id` = ?
-- params: [42]
Doar coloanele de identitate apar în clauza WHERE.
ACTUALIZARE cu protecție
Actualizările cu protecție includ atât clauze de identitate, cât și clauze pentru rândul live așteptat.
UPDATE `posts` SET `title` = ? WHERE `id` = ? AND `status` = ?
-- params: ['New Title', 42, 'draft']
Dacă rândul nu mai are identitatea așteptată status, instrucțiunea nu afectează niciun rând, iar aplicarea cu protecție anulează tranzacția.
INSERARE cu protecție
Inserările cu protecție folosesc NOT EXISTS pentru a evita inserarea într-o identitate apărută după crearea planului.
INSERT INTO `posts` (`id`, `title`) SELECT ?, ? WHERE NOT EXISTS (
SELECT 1 FROM `posts` WHERE `id` = ?
)
-- params: [42, 'New Post', 42]
Gestionarea valorilor NULL
Valorile NULL sunt transmise ca PHP null în tabloul params. Adaptorul conexiunii gestionează legarea:
$statements = SqlGenerator::generate($result);
// params might contain: [42, null, 'draft']
// The adapter binds null as SQL NULL
În rezultatul rulării de probă, valorile NULL sunt redate ca șirul literal NULL fără ghilimele.
Detectarea coloanelor de identitate
SqlGenerator determină coloanele care alcătuiesc identitatea rândului, examinând TableSnapshot::identityColumns din instantaneul de bază. Aceste coloane sunt folosite în clauzele WHERE pentru instrucțiunile UPDATE și DELETE și sunt excluse din clauzele SET ale instrucțiunilor UPDATE.
Dacă nu este disponibil niciun instantaneu de bază, prima coloană din tabloul de valori este folosită ca soluție de rezervă. Dacă tabloul de valori este gol, se presupune id.
Transmiterea unui driver
Pentru a controla citarea identificatorilor, transmiteți o instanță Driver:
use Merql\Driver\SqliteDriver;
$statements = SqlGenerator::generate(
$result,
driver: new SqliteDriver(),
);
// Uses double-quote quoting: "posts", "title"