
# 试运行预览

`DryRun::generate()` 会生成易读的 SQL 语句，并将值内插到语句中。应用到数据库之前，可用它检查合并将执行的操作。

```php
use Merql\Apply\DryRun;

$statements = DryRun::generate($result);

foreach ($statements as $sql) {
    echo "{$sql};\n";
}
```

预览会为结果中的每个操作生成一条语句，并按照 `Applier` 的分组方式排列：先插入，再更新，最后删除。对于完整的合并结果，这些语句涵盖两侧相对于 base 的所有变更，也就是在数据库仍保存 base 时 `Merql::apply()` 将执行的操作。预览[所选结果](https://merql.inline0.dev/zh/docs/merge/plans)，即可查看你计划应用的操作对应的语句。

## 输出示例

```sql
INSERT INTO `posts` (`id`, `title`, `content`, `status`) VALUES ('42', 'New Post', 'Body text', 'draft');
UPDATE `posts` SET `title` = 'Updated Title', `status` = 'publish' WHERE `id` = '42';
DELETE FROM `posts` WHERE `id` = '99';
```

更新会设置操作包含的每个非标识列，而不仅是已更改的列；如果某次更新不会设置任何列，则会将其省略。

## 值格式

所有值都用单引号括起。特殊字符会经过转义，以便安全显示：

| 字符 | 转义后 |
|---|---|
| `\`（反斜杠） | `\\` |
| `'`（单引号） | `''` |
| `\0`（空字节） | `\0` |
| `\n`（换行符） | `\n` |
| `\r`（回车符） | `\r` |

NULL 值显示为不带引号的字面量 `NULL`：

```sql
UPDATE `posts` SET `subtitle` = NULL WHERE `id` = '42';
```

## 参数

`DryRun::generate()` 接受与 `SqlGenerator::generate()` 相同的参数：

```php
$statements = DryRun::generate(
    $result,
    base: $baseSnapshot,
    fkDependencies: ['comments' => ['posts']],
    driver: new SqliteDriver(),
);
```

| 参数 | 类型 | 说明 |
|---|---|---|
| `$result` | `MergeResult` | 要预览的合并结果。 |
| `$base` | `?Snapshot` | 用于标识列的基础快照。默认使用 `$result->baseSnapshot()`。 |
| `$fkDependencies` | `array` | 用于排序的外键依赖关系映射。 |
| `$driver` | `?Driver` | 用于为标识符加引号的数据库驱动。 |

## 试运行与 SqlGenerator 的区别

`DryRun` 对 `SqlGenerator` 进行了封装。区别如下：

- `SqlGenerator::generate()` 返回供适配器执行预处理语句使用的 `['sql' => '...', 'params' => [...]]` 数组。
- `DryRun::generate()` 返回值已内联的普通字符串，供人阅读。

不要将试运行输出作为 SQL 执行。它的格式仅供显示，并不适合安全执行。要执行合并，请直接使用 `Applier` 或 `SqlGenerator`，并配合预处理语句。

## 通过门面使用

通过门面获取合并结果并预览：

```php
use Merql\Merql;
use Merql\Apply\DryRun;

$result = Merql::merge('base', 'ours', 'theirs');

$statements = DryRun::generate($result);

foreach ($statements as $sql) {
    echo "{$sql};\n";
}
```

也可以通过 CLI 并设置 `--dry-run` 标志：

```bash
vendor/bin/merql merge base ours theirs --dry-run
```

CLI 不使用外键排序或驱动来打印语句，因此无论数据库类型如何，标识符都使用默认的反引号引号格式。它会传入基础快照以处理标识列。其合并方式与 `Merql::merge()` 一样，是列级合并。
