Generowanie SQL
SqlGenerator przekształca MergeResult w parametryzowane instrukcje SQL. Wszystkie wartości są przekazywane jako parametry, nigdy nie są wstawiane bezpośrednio do ciągu 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']
}
Użyj generateGuarded(), gdy sprawdzony plan scalania powinien zostać zastosowany tylko wtedy, gdy bieżące wiersze nadal odpowiadają oczekiwanemu zrzutowi.
use Merql\Apply\SqlGenerator;
use Merql\Snapshot\SnapshotStore;
$statements = SqlGenerator::generateGuarded(
$selectedResult,
SnapshotStore::load('theirs'),
);
Format instrukcji
Każda instrukcja to tablica asocjacyjna z dwoma kluczami:
[
'sql' => 'INSERT INTO `posts` (`id`, `title`) VALUES (?, ?)',
'params' => [42, 'New Title'],
]
Identyfikatory (nazwy tabel i kolumn) są cytowane zgodnie ze stylem sterownika bazy danych. MySQL używa znaków odwrotnego apostrofu, a SQLite używa podwójnych cudzysłowów. Jeśli nie podano sterownika, domyślnie używane są znaki odwrotnego apostrofu.
Kolejność operacji
Operacje są grupowane według typu i wykonywane w następującej kolejności:
- Najpierw INSERTs — nowe wiersze muszą istnieć, zanim odwołają się do nich aktualizacje.
- Następnie UPDATEs.
- Na końcu DELETEs — przed usunięciem trzeba usunąć odwołania do wierszy.
$statements = SqlGenerator::generate($result);
// All INSERTs, then all UPDATEs, then all DELETEs.
Kolejność kluczy obcych
Jeśli podano zależności kluczy obcych, operacje w każdej grupie są sortowane topologicznie. Tabele nadrzędne są przetwarzane przed podrzędnymi przy wstawianiu i aktualizowaniu. Przy usuwaniu tabele podrzędne są przetwarzane przed nadrzędnymi.
$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 wykonuje sortowanie topologiczne grafu zależności. Wykrywa i przerywa zależności cykliczne, aby zapobiec nieskończonym pętlom.
Automatyczne wykrywanie kluczy obcych
Applier automatycznie odczytuje z bazy danych relacje kluczy obcych:
use Merql\Apply\Applier;
$applier = new Applier($connection);
$applied = $applier->apply($result);
// FK dependencies are read from the database via the driver.
Przykłady wygenerowanych SQL
INSERT
INSERT INTO `posts` (`id`, `title`, `content`, `status`) VALUES (?, ?, ?, ?)
-- params: [42, 'New Post', 'Body text', 'draft']
Uwzględniane są wszystkie kolumny z wartości przekazanych w operacji.
UPDATE
UPDATE `posts` SET `title` = ?, `status` = ? WHERE `id` = ?
-- params: ['New Title', 'publish', 42]
Kolumny identyfikacyjne (klucz główny) są pomijane w klauzuli SET i używane w klauzuli WHERE. Wartości klauzuli WHERE pochodzą z dekodowania klucza wiersza.
DELETE
DELETE FROM `posts` WHERE `id` = ?
-- params: [42]
W klauzuli WHERE występują wyłącznie kolumny identyfikacyjne.
UPDATE z kontrolą
Aktualizacje z kontrolą zawierają zarówno klauzule dotyczące tożsamości, jak i klauzule dotyczące oczekiwanego bieżącego wiersza.
UPDATE `posts` SET `title` = ? WHERE `id` = ? AND `status` = ?
-- params: ['New Title', 42, 'draft']
Jeśli wiersz nie ma już oczekiwanej status, instrukcja nie zmienia żadnych wierszy, a zabezpieczone zastosowanie wycofuje transakcję.
Zabezpieczony INSERT
Zabezpieczone wstawienia używają NOT EXISTS, aby uniknąć wstawienia do tożsamości, która pojawiła się po utworzeniu planu.
INSERT INTO `posts` (`id`, `title`) SELECT ?, ? WHERE NOT EXISTS (
SELECT 1 FROM `posts` WHERE `id` = ?
)
-- params: [42, 'New Post', 42]
Obsługa NULL
Wartości NULL są przekazywane jako PHP null w tablicy params. Adapter połączenia obsługuje wiązanie parametrów:
$statements = SqlGenerator::generate($result);
// params might contain: [42, null, 'draft']
// The adapter binds null as SQL NULL
W wynikach próbnego uruchomienia wartości NULL są wyświetlane jako literał NULL bez cudzysłowów.
Wykrywanie kolumny tożsamości
SqlGenerator ustala, które kolumny tworzą tożsamość wiersza, na podstawie TableSnapshot::identityColumns migawki bazowej. Kolumny te są używane w klauzulach WHERE instrukcji UPDATE i DELETE oraz pomijane w klauzulach SET instrukcji UPDATE.
Jeśli migawka bazowa jest niedostępna, jako rozwiązanie awaryjne używana jest pierwsza kolumna w tablicy values. Jeśli tablica values jest pusta, zakłada się id.
Przekazywanie sterownika
Aby kontrolować sposób cytowania identyfikatorów, przekaż instancję Driver:
use Merql\Driver\SqliteDriver;
$statements = SqlGenerator::generate(
$result,
driver: new SqliteDriver(),
);
// Uses double-quote quoting: "posts", "title"