Pembuatan SQL
SqlGenerator mengubah MergeResult menjadi pernyataan SQL berparameter. Semua nilai diikat sebagai parameter, tidak pernah disisipkan ke dalam string 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']
}
Gunakan generateGuarded() ketika rencana penggabungan yang telah ditinjau hanya boleh diterapkan jika baris aktif masih cocok dengan snapshot yang diharapkan.
use Merql\Apply\SqlGenerator;
use Merql\Snapshot\SnapshotStore;
$statements = SqlGenerator::generateGuarded(
$selectedResult,
SnapshotStore::load('theirs'),
);
Format pernyataan
Setiap pernyataan berupa array asosiatif dengan dua kunci:
[
'sql' => 'INSERT INTO `posts` (`id`, `title`) VALUES (?, ?)',
'params' => [42, 'New Title'],
]
Identifier (nama tabel dan kolom) diberi tanda kutip menggunakan gaya pengutipan driver database. MySQL menggunakan backtick, sedangkan SQLite menggunakan tanda kutip ganda. Jika driver tidak diberikan, backtick digunakan secara default.
Urutan operasi
Operasi dikelompokkan berdasarkan jenis dan dijalankan dengan urutan berikut:
- INSERT terlebih dahulu -- baris baru harus ada sebelum dapat dirujuk oleh pembaruan.
- UPDATE berikutnya.
- DELETE terakhir -- referensi ke baris harus dihapus sebelum penghapusan.
$statements = SqlGenerator::generate($result);
// All INSERTs, then all UPDATEs, then all DELETEs.
Urutan foreign key
Jika dependensi foreign key diberikan, operasi dalam setiap kelompok diurutkan secara topologis. Tabel induk diproses sebelum tabel anak untuk insert dan update. Tabel anak diproses sebelum tabel induk untuk delete.
$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 melakukan pengurutan topologis pada graf dependensi. Dependensi melingkar dideteksi dan diputus untuk mencegah loop tanpa akhir.
Deteksi FK otomatis
Applier membaca relasi foreign key dari database secara otomatis:
use Merql\Apply\Applier;
$applier = new Applier($connection);
$applied = $applier->apply($result);
// FK dependencies are read from the database via the driver.
Contoh SQL yang dihasilkan
INSERT
INSERT INTO `posts` (`id`, `title`, `content`, `status`) VALUES (?, ?, ?, ?)
-- params: [42, 'New Post', 'Body text', 'draft']
Semua kolom dari nilai operasi disertakan.
UPDATE
UPDATE `posts` SET `title` = ?, `status` = ? WHERE `id` = ?
-- params: ['New Title', 'publish', 42]
Kolom identitas (kunci utama) tidak disertakan dalam klausa SET dan digunakan dalam klausa WHERE. Nilai klausa WHERE berasal dari hasil dekode kunci baris.
DELETE
DELETE FROM `posts` WHERE `id` = ?
-- params: [42]
Hanya kolom identitas yang muncul dalam klausa WHERE.
UPDATE dengan penjagaan
Update dengan penjagaan menyertakan klausa identitas dan klausa baris aktif yang diharapkan.
UPDATE `posts` SET `title` = ? WHERE `id` = ? AND `status` = ?
-- params: ['New Title', 42, 'draft']
Jika baris tidak lagi memiliki status yang diharapkan, pernyataan memengaruhi nol baris dan penerapan dengan penjagaan membatalkan transaksi.
INSERT dengan penjagaan
Insert dengan penjagaan menggunakan NOT EXISTS untuk mencegah penyisipan pada identitas yang muncul sejak rencana dibuat.
INSERT INTO `posts` (`id`, `title`) SELECT ?, ? WHERE NOT EXISTS (
SELECT 1 FROM `posts` WHERE `id` = ?
)
-- params: [42, 'New Post', 42]
Penanganan NULL
Nilai NULL diteruskan sebagai PHP null dalam array params. Adapter koneksi menangani pengikatan:
$statements = SqlGenerator::generate($result);
// params might contain: [42, null, 'draft']
// The adapter binds null as SQL NULL
Dalam keluaran uji kering, nilai NULL ditampilkan sebagai string literal NULL tanpa tanda kutip.
Deteksi kolom identitas
SqlGenerator menentukan kolom yang membentuk identitas baris dengan melihat TableSnapshot::identityColumns dari snapshot base. Kolom ini digunakan dalam klausa WHERE pada pernyataan UPDATE dan DELETE, serta dikecualikan dari klausa SET pada UPDATE.
Jika snapshot base tidak tersedia, kolom pertama dalam array values digunakan sebagai cadangan. Jika array values kosong, id diasumsikan.
Meneruskan driver
Untuk mengontrol pengutipan identifier, teruskan instance Driver:
use Merql\Driver\SqliteDriver;
$statements = SqlGenerator::generate(
$result,
driver: new SqliteDriver(),
);
// Uses double-quote quoting: "posts", "title"