From 5cefa04a45ef438c652feccbfecba5df16eb9333 Mon Sep 17 00:00:00 2001 From: Mitchell R Date: Sat, 23 May 2026 12:50:07 +0200 Subject: [PATCH] fix(db): PG adapter coerce 0/1 to boolean for PG strict typing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PG rejects integer values for BOOLEAN columns. B() helper returns 0/1 for SQLite compat. PG adapter now converts 0→false, 1→true in params before sending — safe for both INTEGER and BOOLEAN column types. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/plugins/service-store/pg-adapter.ts | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/server/src/plugins/service-store/pg-adapter.ts b/server/src/plugins/service-store/pg-adapter.ts index 5bc2cef..8f30537 100644 --- a/server/src/plugins/service-store/pg-adapter.ts +++ b/server/src/plugins/service-store/pg-adapter.ts @@ -59,6 +59,19 @@ export class PgAdapter implements DbAdapter { return out; } + private coerceParams(params: ReadonlyArray): unknown[] { + return params.map((v) => { + if (v === 0 || v === 1) { + // Could be integer or boolean. PG is strict about boolean columns + // receiving integer values. We can't know the column type here, but + // the `pg` driver accepts JS booleans for both INTEGER and BOOLEAN + // columns, so converting 0/1 to false/true is always safe. + return v === 1; + } + return v; + }); + } + private async runner(fn: (c: PoolClient) => Promise): Promise { if (this.currentTxClient) return fn(this.currentTxClient); const client = await this.pool.connect(); @@ -68,8 +81,9 @@ export class PgAdapter implements DbAdapter { async run(sql: string, params: ReadonlyArray = []): Promise { const pgSql = this.rewriteSql(sql); + const pgParams = this.coerceParams(params); return this.runner(async (c) => { - const res = await c.query(pgSql, params as unknown[]); + const res = await c.query(pgSql, pgParams); let lastInsertRowid = 0n; // If the caller added RETURNING id, pluck it. if (res.rows.length > 0 && res.rows[0] && "id" in res.rows[0]) { @@ -84,16 +98,18 @@ export class PgAdapter implements DbAdapter { async get(sql: string, params: ReadonlyArray = []): Promise { const pgSql = this.rewriteSql(sql); + const pgParams = this.coerceParams(params); return this.runner(async (c) => { - const res = await c.query(pgSql, params as unknown[]); + const res = await c.query(pgSql, pgParams); return (res.rows[0] as T | undefined); }); } async all(sql: string, params: ReadonlyArray = []): Promise { const pgSql = this.rewriteSql(sql); + const pgParams = this.coerceParams(params); return this.runner(async (c) => { - const res = await c.query(pgSql, params as unknown[]); + const res = await c.query(pgSql, pgParams); return res.rows as T[]; }); }