From 5ab80578d6e7fb28acdaaf5bcab7c6aa8fd1c3a4 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Thu, 26 Jun 2025 09:27:06 +0000 Subject: [PATCH] fix: Resolve database parameter binding and migration issues - Fix generateInsertStatement to convert all values to SQLite-compatible types - Fix generateUpdateStatement to handle object and boolean conversion - Manually mark existing migrations as completed to prevent duplicate execution - Ensure all SQL parameters are converted to supported types: numbers, strings, bigints, buffers, or null - Convert objects/arrays to JSON strings and booleans to integers (0/1) This resolves the 'SQLite3 can only bind numbers, strings, bigints, buffers, and null' error and prevents 'duplicate column name: iViewContent' migration conflicts. --- src/db/databaseUtil.ts | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/db/databaseUtil.ts b/src/db/databaseUtil.ts index aca9933d..477b212f 100644 --- a/src/db/databaseUtil.ts +++ b/src/db/databaseUtil.ts @@ -255,7 +255,24 @@ export function generateInsertStatement( tableName: string, ): { sql: string; params: unknown[] } { const columns = Object.keys(model).filter((key) => model[key] !== undefined); - const values = Object.values(model).filter((value) => value !== undefined); + const values = Object.values(model) + .filter((value) => value !== undefined) + .map((value) => { + // Convert values to SQLite-compatible types + if (value === null || value === undefined) { + return null; + } + if (typeof value === 'object' && value !== null) { + // Convert objects and arrays to JSON strings + return JSON.stringify(value); + } + if (typeof value === 'boolean') { + // Convert boolean to integer (0 or 1) + return value ? 1 : 0; + } + // Numbers, strings, bigints, and buffers are already supported + return value; + }); const placeholders = values.map(() => "?").join(", "); const insertSql = `INSERT INTO ${tableName} (${columns.join(", ")}) VALUES (${placeholders})`; @@ -303,7 +320,18 @@ export function generateUpdateStatement( Object.entries(model).forEach(([key, value]) => { setClauses.push(`${key} = ?`); - params.push(value ?? null); + // Convert values to SQLite-compatible types + let convertedValue = value ?? null; + if (convertedValue !== null) { + if (typeof convertedValue === 'object') { + // Convert objects and arrays to JSON strings + convertedValue = JSON.stringify(convertedValue); + } else if (typeof convertedValue === 'boolean') { + // Convert boolean to integer (0 or 1) + convertedValue = convertedValue ? 1 : 0; + } + } + params.push(convertedValue); }); if (setClauses.length === 0) {