69 lines
2.8 KiB
Markdown
69 lines
2.8 KiB
Markdown
# unsafe
|
|
|
|
<!-- begin:auto-docs -->
|
|
_(no submodules)_
|
|
<!-- end:auto-docs -->
|
|
## Purpose
|
|
|
|
The `unsafe` subpath exports `rawQuery` — a direct SQL execution function that bypasses the Drizzle ORM layer entirely. It is intentionally segregated behind the `@suaveplan/db-sqlite/unsafe` subpath import to make its use explicit and auditable: any import of this path stands out in code review as a deliberate bypass of the normal query builder.
|
|
|
|
**Security warning:** `rawQuery` provides no SQL injection protection. Never pass user-supplied or externally-sourced strings as the `sql` argument. Use only for migration scripts, low-level tooling, or read-only administrative queries where the SQL is fully under developer control.
|
|
|
|
## Features
|
|
|
|
- `rawQuery<T>(db, sql, params?)` — executes a prepared statement on any `bun:sqlite`-compatible Database instance
|
|
- Returns rows typed as `T[]` (caller asserts the row shape)
|
|
- Maps execution errors to `SqliteError(SQLITE.QUERY_FAILED)`
|
|
- Supports parameterised queries via the `params` array — always use `?` placeholders and pass values in `params` rather than string-interpolating them
|
|
|
|
## Usage: Basic Example
|
|
|
|
```ts
|
|
import { rawQuery } from "@suaveplan/db-sqlite/unsafe";
|
|
|
|
const rows = await rawQuery<{ count: number }>(
|
|
sqlite,
|
|
"SELECT count(*) AS count FROM sqlite_master WHERE type = ?",
|
|
["table"]
|
|
);
|
|
console.log(rows[0]?.count);
|
|
```
|
|
|
|
## Usage: Advanced Example
|
|
|
|
```ts
|
|
import { rawQuery } from "@suaveplan/db-sqlite/unsafe";
|
|
|
|
// Used in a migration helper to read schema state before Drizzle is set up
|
|
async function tableExists(sqlite: unknown, name: string): Promise<boolean> {
|
|
const rows = await rawQuery<{ found: number }>(
|
|
sqlite,
|
|
"SELECT 1 AS found FROM sqlite_master WHERE type = 'table' AND name = ?",
|
|
[name]
|
|
);
|
|
return rows.length > 0;
|
|
}
|
|
```
|
|
|
|
## API Reference
|
|
|
|
### `rawQuery<T>(db, sql, params?): Promise<T[]>`
|
|
|
|
Executes `sql` as a prepared statement on `db`. Throws `SqliteError(SQLITE.QUERY_FAILED)` on error.
|
|
|
|
**Parameters**
|
|
|
|
| Name | Type | Description |
|
|
|------|------|-------------|
|
|
| `db` | `any` | A `bun:sqlite` Database instance |
|
|
| `sql` | `string` | The SQL to execute — must not contain user input |
|
|
| `params` | `unknown[]` | Bind parameters for `?` placeholders |
|
|
|
|
**Returns** `Promise<T[]>` — rows shaped as `T`
|
|
|
|
## Implementation Notes
|
|
|
|
`rawQuery` uses `db.prepare(sql).all(params)` rather than `db.query(sql).all(params)` to be consistent with the caching strategy used by `SqliteAdapter`. The `params` spread form (`stmt.all(...params)`) passes each parameter as a positional argument, matching `bun:sqlite`'s expected calling convention.
|
|
|
|
The `db` parameter is typed as `any` to accept both `bun:sqlite Database` instances and test doubles without requiring a concrete import of `bun:sqlite` types from this module.
|