Files
skills/docs/persistence/database/db-sqlite/src/unsafe/unsafe.md
2026-05-29 08:20:56 +01:00

2.8 KiB

unsafe

(no submodules)

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

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

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.