Files
bun-sqlite/dist/lib/schema/create-db-schema.js
T
tbenandClaude Opus 5.5 938a1da71d Add queue tables, quote SQL identifiers (v1.3.0)
- isQueue table option adds queue columns and a (status, available_at)
  index; BunSQLite.queue exposes add, claim, complete, fail and
  release_stale with atomic claims
- Set busy_timeout on connections so workers in separate processes wait
  instead of failing with SQLITE_BUSY
- Quote table and column names with backticks in generated SQL, so
  reserved words (to, order, group) work and unknown columns error
  instead of matching as string literals
- Tests for queue ops, multi-process claims and reserved-word names

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 16:29:14 +01:00

72 lines
2.5 KiB
JavaScript

import _ from "lodash";
import createDBManagerTable from "./create-db-manager-table";
import dropRemovedTables from "./drop-removed-tables";
import getExistingTablesFromTablesManagerTable from "./get-existing-tables-from-tables-manager-table";
import handleDBSchemaTable from "./handle-db-schema-table";
import orderDBSchema from "./order-db-schema";
/**
* # Sync the database to the schema
* @description Changed tables are rebuilt by copying into a new table and
* dropping the old one. With foreign keys ON, `DROP TABLE` runs an implicit
* `DELETE FROM` that fires `ON DELETE CASCADE` on child tables, so keys are
* disabled for the sync and checked before committing. (`PRAGMA
* foreign_keys` is a no-op inside a transaction.) With `dry_run` the
* transaction is rolled back, so `changes` is the exact plan.
*/
export default function createDBSchema(params) {
const { db, dry_run } = params;
/**
* Reorder Tables (parents before children with FKs)
*/
const db_schema = orderDBSchema(params);
for (const table of db_schema.tables) {
if (table.isQueue && table.isVector) {
throw new Error(`Table "${table.tableName}" can't be both a queue and a vector table`);
}
}
db.run("PRAGMA foreign_keys = OFF;");
db.run("BEGIN");
try {
/**
* Create Schema Manager Table
*/
createDBManagerTable({ db });
const existing_tables = getExistingTablesFromTablesManagerTable({
db,
});
/**
* Create or update tables
*/
for (const table of db_schema.tables) {
handleDBSchemaTable({
...params,
db_schema,
table,
existing_tables,
});
}
/**
* Drop tables that no longer exist in schema
*/
dropRemovedTables({
...params,
existing_tables,
schema_tables: db_schema.tables.map((t) => t.tableName),
});
const fkViolations = db.query(`PRAGMA foreign_key_check`).all();
if (fkViolations.length) {
const tables = _.uniq(fkViolations.map((v) => `${v.table} -> ${v.parent}`));
throw new Error(`Foreign key violations after schema sync: ${tables.join(", ")}`);
}
db.run(dry_run ? "ROLLBACK" : "COMMIT");
}
catch (error) {
if (db.inTransaction)
db.run("ROLLBACK");
throw error;
}
finally {
db.run("PRAGMA foreign_keys = ON;");
}
}