# SQLite shared 示例

## 功能

`examples/extensions/shared-sqlite` 是 shared WASM 扩展验证示例，用 SQLite 文件数据库验证项目级 `ExtensionService` 是否能承载常驻连接、事务、并发读、busy timeout、结果上限和对象释放。

该示例不是内置标准库。使用前需要把示例编译成 `module.wasm`，再打包为 `.bts` 并安装到项目 `extensions/` 目录。

## 语法

```bt
db = sqlite_open(path, options)
row = db.one(sql, params)
rows = db.all(sql, params)
changed = db.exec(sql, params)
changed = db.transaction(statements)
query = db.query(sql).bind(value)
db.close()
```

## 参数

| 名称 | 类型 | 说明 |
| ------ | ------ | ------ |
| `path` | String | SQLite 数据库文件路径，bindings 使用 `path_write` role，宿主会改写为 WASI 相对路径。 |
| `options` | Object | 连接配置。 |
| `options.wal` | Bool | 是否执行 `PRAGMA journal_mode = WAL`，默认 `false`。 |
| `options.busy_timeout_ms` | Int | SQLite busy timeout，默认 `1000`，最大 `300000`。 |
| `options.max_rows` | Int | `all()` 最大返回行数，默认 `1000`，最大 `100000`。 |
| `options.max_result_bytes` | Int | `one()` / `all()` 返回值字节估算上限，默认 `4194304`，最大 `16777216`。 |
| `sql` | String | 待执行 SQL。 |
| `params` | Array | SQL 参数数组，支持 `null`、Bool、Int、Float、String、Bytes；不允许 `empty`。 |
| `statements` | Array | 事务语句数组，元素可以是 SQL 字符串，也可以是 `{ sql, params }` 对象。 |

## 返回值

| 调用 | 返回 |
| ------ | ------ |
| `sqlite_open()` | `Sqlite` 扩展对象。 |
| `one()` | 有结果时返回 Object；无结果时返回 `empty`。SQLite `NULL` 返回 BT `null`，BLOB 返回 BT Bytes。 |
| `all()` | Object 数组，受 `max_rows` 和 `max_result_bytes` 限制。 |
| `exec()` | 影响行数 Int。 |
| `transaction()` | 事务内累计影响行数 Int。 |
| `query().bind()` | 返回同一个 `SqliteQuery` 对象，便于链式绑定。 |
| `close()` | Bool；成功后宿主会让旧对象句柄失效。 |

## 代码示例

```bt
db = sqlite_open('@/data/shared-demo.db', {
    wal: true,
    busy_timeout_ms: 1000,
    max_rows: 100,
    max_result_bytes: 1048576
})

db.exec('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, payload BLOB, note TEXT)', [])
db.exec('DELETE FROM users', [])
db.exec('INSERT INTO users (name, payload, note) VALUES (?, ?, ?)', ['Alice', bytes('4254', 'hex'), null])
db.transaction([
    { sql: 'INSERT INTO users (name, payload, note) VALUES (?, ?, ?)', params: ['Bob', bytes('0102', 'hex'), 'writer'] },
    { sql: 'INSERT INTO users (name, payload, note) VALUES (?, ?, ?)', params: ['Carol', bytes('0304', 'hex'), 'writer'] }
])

row = db.one('SELECT name, payload, note FROM users WHERE name = ?', ['Alice'])

// 输出：Alice
print row.name

// 输出：true
print is_null(row.note)

missing = db.one('SELECT name FROM users WHERE name = ?', ['Missing'])

// 输出：true
print is_empty(missing)

rows = db.all('SELECT id, name FROM users ORDER BY id', [])

// 输出：3
print rows.len()

query = db.query('SELECT name FROM users WHERE id = ?').bind(2)
second = query.one()

// 输出：Bob
print second.name

query.close()
db.close()
```

## 构建

```text
rustup target add wasm32-wasip1
cargo build --manifest-path examples/extensions/shared-sqlite/Cargo.toml --target wasm32-wasip1 --release
copy examples\extensions\shared-sqlite\target\wasm32-wasip1\release\shared_sqlite.wasm examples\extensions\shared-sqlite\module.wasm
cargo run --features extensions -- ext build examples/extensions/shared-sqlite -o examples/extensions/shared-sqlite/shared_sqlite.bts
```

`rusqlite` 的 bundled SQLite 在 WASI 目标下需要 C 编译器。Windows 环境需要先安装 LLVM clang 或 WASI SDK，并确保 `clang` 在 `PATH` 中。

## 注意事项

- 这个示例优先验证 shared runtime 能力，不替代未来正式 SQLite 标准库或扩展发布包。
- 粗粒度 `one/all/exec/transaction` 是性能主路径；`query().bind()` 只是易用层。
- `all()` 必须设置合理的 `max_rows` 和 `max_result_bytes`，避免大结果无控进入 BT VM。
- `close()` / `SqliteQuery.close()` 应显式调用；bindings 已标记 `lifecycle: "dispose"`，调用成功后旧句柄失效。
- `busy_timeout_ms` 只处理 SQLite 锁等待，不是 SQL 逻辑超时；shared worker 的 `call_timeout_ms` 仍由宿主 ExtensionService 负责。
