diff --git a/.changeset/fix-schema-compat-comment-truncation.md b/.changeset/fix-schema-compat-comment-truncation.md new file mode 100644 index 0000000000..01ca42a482 --- /dev/null +++ b/.changeset/fix-schema-compat-comment-truncation.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": patch +--- + +summary: Fix legacy databases missing newer task columns (e.g. checkout-lease, column dwell) after upgrade. +category: fix +dev: parseCreateTableSchemasFromSql now strips `--` comments before the non-greedy CREATE TABLE body regex, so a `);` inside a schema comment can no longer truncate a parsed table body and silently drop columns from ensureSchemaCompatibility()'s backfill set. diff --git a/packages/core/src/db.ts b/packages/core/src/db.ts index 5cf342f39b..755e23a49c 100644 --- a/packages/core/src/db.ts +++ b/packages/core/src/db.ts @@ -1375,7 +1375,20 @@ function parseCreateTableSchemasFromSql(sql: string): Map>(); const createTableRegex = /CREATE TABLE\s+(?:IF NOT EXISTS\s+)?((?:["`]|\[)?[A-Za-z_][A-Za-z0-9_]*(?:["`]|\])?)\s*\(([\s\S]*?)\)\s*;/g; - for (const match of sql.matchAll(createTableRegex)) { + /* + FNXC:SchemaCompatBackfill 2026-06-26-17:30: + Strip `--` line comments from the whole schema BEFORE matching each table-definition block. + The body-capture regex is non-greedy (`([\s\S]*?)\)\s*;`), so a `)` immediately followed by `;` + inside a comment (e.g. a doc reference like `getSchemaCompatibilityTableSchemas();` or + `task.workflowStepResults);`) truncates the matched table body early. That silently dropped every + column after the comment from the parsed schema, so ensureSchemaCompatibility() stopped backfilling + them on legacy DBs whose schemaVersion was already current (regression surfaced as a missing + `checkoutNodeId`/`columnDwellMs` column on the tasks table). Stripping comments up front keeps the + per-line strip below as defense-in-depth while preventing comment content from ending a table body. + */ + const sqlWithoutComments = sql.replace(/--[^\n]*/g, ""); + + for (const match of sqlWithoutComments.matchAll(createTableRegex)) { const tableName = normalizeSqlIdentifier(match[1]); const body = match[2] ?? ""; const columns = new Map();