index.js (2128B)
1 // src/lib/db/index.js - database driver selection 2 // 3 // Every driver exposes the same surface: 4 // all(sql, params) -> array of rows 5 // get(sql, params) -> first row, or undefined 6 // run(sql, params) -> { changes, lastInsertId } 7 // exec(sql) -> no result, for DDL, bind markers are not parsed 8 // transaction(fn) -> fn receives a scoped handle, nesting uses savepoints 9 // close() 10 // 11 // Params is an object, and queries use named {name} markers which each driver 12 // compiles to its own placeholder syntax. See query.js. 13 // 14 // db.get('SELECT * FROM tasks WHERE job_id = {job}', { job: jobId }) 15 // 16 // Portability rules that apply to every query written against this layer: 17 // - named {name} markers only, never ? or $n directly 18 // - timestamps are epoch milliseconds, produced by Date.now() 19 // - booleans are stored as 0 and 1, never a native boolean type 20 // - no dialect specific functions; keep those behind a driver method 21 // - no reliance on lastInsertId; identifiers are generated by the caller 22 // - no upsert syntax; ON DUPLICATE KEY and ON CONFLICT are not portable, 23 // so do the read and the write explicitly inside a transaction 24 // 25 // One behavioural note on run().changes: mysql counts rows actually changed, 26 // while sqlite and postgres count rows matched. An UPDATE that writes a value 27 // identical to the current one therefore reports 0 on mysql and 1 elsewhere. 28 // The conditional claim pattern used by the scheduler always writes a 29 // different state, so it is unaffected; avoid depending on changes for an 30 // update that may be a no-op. 31 32 import { openSqlite } from './sqlite.js'; 33 import { openMysql } from './mysql.js'; 34 import { openPostgres } from './postgres.js'; 35 36 export { DIALECTS, dialectFromUrl } from './dialect.js'; 37 38 export async function openDatabase(cfg) { 39 switch (cfg.database.dialect) { 40 case 'mysql': return openMysql(cfg); 41 case 'postgres': return openPostgres(cfg); 42 case 'sqlite': return openSqlite(cfg); 43 default: throw new Error(`unknown database dialect: ${cfg.database.dialect}`); 44 } 45 } 46 47 export { runMigrations } from './migrate.js';