SQL Генериране
SqlGenerator преобразува MergeResult в параметризирани инструкции SQL. Всички стойности се подават като параметри и никога не се вмъкват в низа 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']
}
Използвайте generateGuarded(), когато прегледан план за сливане трябва да се приложи само ако активните редове все още съвпадат с очаквана моментна снимка.
use Merql\Apply\SqlGenerator;
use Merql\Snapshot\SnapshotStore;
$statements = SqlGenerator::generateGuarded(
$selectedResult,
SnapshotStore::load('theirs'),
);
Формат на инструкциите
Всяка инструкция е асоциативен масив с два ключа:
[
'sql' => 'INSERT INTO `posts` (`id`, `title`) VALUES (?, ?)',
'params' => [42, 'New Title'],
]
Идентификаторите (имена на таблици и колони) се ограждат според стила на драйвера на базата данни. MySQL използва обратни апострофи, а SQLite — двойни кавички. Ако не е предоставен драйвер, по подразбиране се използват обратни апострофи.
Ред на операциите
Операциите се групират по тип и се изпълняват в този ред:
- Първо INSERT — новите редове трябва да съществуват, преди актуализациите да могат да се позовават на тях.
- След това UPDATE.
- Накрая DELETE — връзките към редовете трябва да бъдат премахнати, преди да бъдат изтрити.
$statements = SqlGenerator::generate($result);
// All INSERTs, then all UPDATEs, then all DELETEs.
Подреждане по външни ключове
Когато са зададени зависимости по външни ключове, операциите във всяка група се подреждат топологично. Родителските таблици се обработват преди дъщерните при вмъквания и актуализации. Дъщерните таблици се обработват преди родителските при изтривания.
$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 извършва топологично сортиране на графа на зависимостите. Цикличните зависимости се откриват и прекъсват, за да се предотвратят безкрайни цикли.
Автоматично откриване на външни ключове
Applier автоматично прочита връзките по външни ключове от базата данни:
use Merql\Apply\Applier;
$applier = new Applier($connection);
$applied = $applier->apply($result);
// FK dependencies are read from the database via the driver.
Примери за генерирани SQL
INSERT
INSERT INTO `posts` (`id`, `title`, `content`, `status`) VALUES (?, ?, ?, ?)
-- params: [42, 'New Post', 'Body text', 'draft']
Включват се всички колони от стойностите на операцията.
UPDATE
UPDATE `posts` SET `title` = ?, `status` = ? WHERE `id` = ?
-- params: ['New Title', 'publish', 42]
Колоните за идентичност (първичният ключ) се изключват от клаузата SET и се използват в клаузата WHERE. Стойностите за клаузата WHERE се извличат чрез декодиране на ключа на реда.
DELETE
DELETE FROM `posts` WHERE `id` = ?
-- params: [42]
В клаузата WHERE присъстват само колоните за идентичност.
Защитен UPDATE
Защитените актуализации включват както клаузи за идентичност, така и клаузи за очаквания активен ред.
UPDATE `posts` SET `title` = ? WHERE `id` = ? AND `status` = ?
-- params: ['New Title', 42, 'draft']
Ако редът вече няма очакваното status, инструкцията не засяга нито един ред и защитеното прилагане отменя транзакцията.
Защитен INSERT
Защитените вмъквания използват NOT EXISTS, за да избегнат вмъкване в идентичност, появила се след създаването на плана.
INSERT INTO `posts` (`id`, `title`) SELECT ?, ? WHERE NOT EXISTS (
SELECT 1 FROM `posts` WHERE `id` = ?
)
-- params: [42, 'New Post', 42]
Обработка на NULL
Стойностите NULL се подават като PHP null в масива с параметри. Адаптерът за връзка обработва обвързването:
$statements = SqlGenerator::generate($result);
// params might contain: [42, null, 'draft']
// The adapter binds null as SQL NULL
В изхода от пробно изпълнение стойностите NULL се показват като буквалния низ NULL без кавички.
Откриване на колони за идентичност
SqlGenerator определя кои колони формират идентичността на реда, като преглежда TableSnapshot::identityColumns в базовата моментна снимка. Тези колони се използват в клаузите WHERE на инструкциите UPDATE и DELETE и се изключват от клаузите SET на UPDATE.
Ако няма налична базова моментна снимка, за резервен вариант се използва първата колона в масива със стойности. Ако масивът със стойности е празен, се приема id.
Подаване на драйвер
За да управлявате ограждането на идентификаторите, подайте екземпляр на Driver:
use Merql\Driver\SqliteDriver;
$statements = SqlGenerator::generate(
$result,
driver: new SqliteDriver(),
);
// Uses double-quote quoting: "posts", "title"