Lewati ke konten

Pembuatan SQL

SqlGenerator mengubah MergeResult menjadi pernyataan SQL berparameter. Semua nilai diikat sebagai parameter, tidak pernah disisipkan ke dalam string SQL.

PHP
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.

PHP
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:

PHP
[
    '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:

  1. INSERT terlebih dahulu -- baris baru harus ada sebelum dapat dirujuk oleh pembaruan.
  2. UPDATE berikutnya.
  3. DELETE terakhir -- referensi ke baris harus dihapus sebelum penghapusan.
PHP
$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.

PHP
$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:

PHP
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

Sql
INSERT INTO `posts` (`id`, `title`, `content`, `status`) VALUES (?, ?, ?, ?)
-- params: [42, 'New Post', 'Body text', 'draft']

Semua kolom dari nilai operasi disertakan.

UPDATE

Sql
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

Sql
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.

Sql
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.

Sql
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:

PHP
$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:

PHP
use Merql\Driver\SqliteDriver;

$statements = SqlGenerator::generate(
    $result,
    driver: new SqliteDriver(),
);
// Uses double-quote quoting: "posts", "title"