@dbsp/adapter-pgsql 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +68 -0
- package/dist/index.d.ts +2154 -0
- package/dist/index.js +16240 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/assert-field.ts","../src/naming-plugin.ts","../src/ast-helpers.ts","../src/param-ref.ts","../src/handlers/expression/case-value.ts","../src/handlers/expression/custom.ts","../src/handlers/types.ts","../src/raw-expression-parser.ts","../src/compiler-utils.ts","../src/validate.ts","../src/handlers/where/utils.ts","../src/handlers/where/any.ts","../src/handlers/where/between.ts","../src/handlers/where/comparison.ts","../src/handlers/where/custom-expression.ts","../src/handlers/where/exists.ts","../src/handlers/where/in.ts","../src/handlers/where/json.ts","../src/handlers/where/like.ts","../src/handlers/where/logical.ts","../src/handlers/where/null.ts","../src/handlers/where/range.ts","../src/compile-where.ts","../src/handlers/where/raw-exists.ts","../src/handlers/where/relation-filter.ts","../src/handlers/where/subquery.ts","../src/handlers/where/index.ts","../src/handlers/include/cte.ts","../src/handlers/include/join.ts","../src/handlers/include/shared.ts","../src/handlers/include/json-agg.ts","../src/handlers/include/lateral.ts","../src/handlers/include/index.ts","../src/handlers/index.ts","../src/handlers/expression/aggregate.ts","../src/handlers/expression/arithmetic.ts","../src/handlers/expression/case.ts","../src/handlers/expression/coalesce.ts","../src/handlers/expression/column.ts","../src/handlers/expression/json.ts","../src/handlers/expression/pseudo.ts","../src/handlers/expression/raw.ts","../src/handlers/expression/relation.ts","../src/handlers/expression/window.ts","../src/handlers/expression/index.ts","../src/index.ts","../src/compiler.ts","../src/pgsql-deparser.ts","../src/deparse.ts","../src/intent-to-decisions.ts","../src/select-expression-handlers.ts","../src/ddl/ddl-generator.ts","../src/ddl/phases/types.ts","../src/ddl/phases/utils.ts","../src/ddl/phases/comments.ts","../src/ddl/phases/constraints.ts","../src/ddl/phases/drop-statements.ts","../src/ddl/phases/enum-types.ts","../src/ddl/phases/extensions.ts","../src/ddl/phases/indexes.ts","../src/ddl/phases/rls.ts","../src/ddl/migration-sql.ts","../src/ddl/type-mapping.ts","../src/ddl/phases/sequences.ts","../src/ddl/phases/tables.ts","../src/ddl/migration-file.ts","../src/ddl/migration-tracker.ts","../src/ddl/schema-diff.ts","../src/explain/explain.ts","../src/extensions/paradedb.ts","../src/extensions/pgsql-builtins.ts","../src/extensions/pgvector.ts","../src/introspection.ts","../src/mutations/mutation-compiler.ts","../src/mutations/upsert.ts","../src/naming.ts","../src/pgsql-adapter.ts","../src/adapter-compiler-includes.ts","../src/adapter-compiler-mutations.ts","../src/adapter-compiler-select.ts","../src/plan-decision-extractor.ts","../src/adapter-compiler-recursive.ts","../src/recursive/cte-compiler.ts","../src/recursive/cycle-detection.ts","../src/recursive/path-tracking.ts","../src/ddl/index-operations.ts","../src/ddl/table-operations.ts","../src/set-operation.ts","../src/streaming/cursor.ts","../src/redact-params.ts"],"sourcesContent":["/**\n * Default primary key column name used as convention fallback\n * when schema metadata doesn't provide an explicit PK.\n *\n * Consumers (handlers, compiler) must NOT use this directly —\n * they use `requiredColumn()` to throw on missing data.\n * Only convention mappers (extractors, introspection) should reference this.\n */\nexport const DEFAULT_PK_COLUMN = 'id';\n\n/**\n * Derive a foreign key column name from a table name and the PK column it references.\n *\n * Convention: `${singularTableName}_${pkColumnName}`\n * e.g. (authors, id) → author_id, (categories, id) → category_id\n *\n * Consumers should use `deriveFkColumnName` from CompilerContext or options\n * for configurable behavior.\n */\nexport type FkColumnDerivation = (\n\ttableName: string,\n\tpkColumnName: string,\n) => string;\n\nimport { singularize } from '@dbsp/core';\n\nexport const defaultFkDerivation: FkColumnDerivation = (\n\ttableName,\n\tpkColumnName,\n) => `${singularize(tableName)}_${pkColumnName}`;\n\n/**\n * Assert that a column field expected from a PlanDecision is defined.\n * Throws instead of silently falling back to 'id' — catches upstream bugs\n * where WhereIntent fields (field/kind) aren't converted to PlanDecision (column/type).\n */\nexport function requiredColumn(\n\tvalue: string | undefined,\n\tfield: string,\n\tcontext?: string,\n): string {\n\tif (!value) {\n\t\tthrow new Error(\n\t\t\t`Missing required column '${field}'${context ? ` in ${context}` : ''}`,\n\t\t);\n\t}\n\treturn value;\n}\n","/**\n * NamingPlugin - Identifier transformation between model and database naming conventions\n *\n * Inspired by Kysely's CamelCasePlugin architecture.\n * The plugin transforms identifiers bidirectionally:\n * - toDatabase: model name (camelCase) → database name (snake_case)\n * - toModel: database name (snake_case) → model name (camelCase)\n */\n\n/**\n * Interface for naming convention transformation plugins\n */\nexport interface NamingPlugin {\n\t/**\n\t * Transform a model identifier to database format\n\t * Example: \"createdAt\" → \"created_at\"\n\t */\n\ttoDatabase(identifier: string): string;\n\n\t/**\n\t * Transform a database identifier to model format\n\t * Example: \"created_at\" → \"createdAt\"\n\t */\n\ttoModel(identifier: string): string;\n}\n\n/**\n * Identity plugin - no transformation\n * Use this when model and database naming conventions match\n */\nexport class IdentityNamingPlugin implements NamingPlugin {\n\ttoDatabase(identifier: string): string {\n\t\treturn identifier;\n\t}\n\n\ttoModel(identifier: string): string {\n\t\treturn identifier;\n\t}\n}\n\n/**\n * CamelCase ↔ snake_case transformation plugin\n *\n * Follows the same logic as Kysely's CamelCasePlugin:\n * - Handles consecutive uppercase letters (e.g., \"parseJSON\" → \"parse_json\")\n * - Handles numbers (e.g., \"field1Name\" → \"field1_name\")\n * - Preserves leading underscores\n */\nexport class CamelCaseNamingPlugin implements NamingPlugin {\n\t/**\n\t * camelCase → snake_case\n\t */\n\ttoDatabase(identifier: string): string {\n\t\t// Handle empty strings\n\t\tif (!identifier) return identifier;\n\n\t\t// Preserve leading underscores\n\t\tconst leadingUnderscores = identifier.match(/^_+/)?.[0] ?? '';\n\t\tconst rest = identifier.slice(leadingUnderscores.length);\n\n\t\tif (!rest) return identifier;\n\n\t\t// Convert camelCase to snake_case\n\t\t// Handles: wordWord, wordWORD, word123Word\n\t\tconst snakeCase = rest\n\t\t\t// Insert underscore before uppercase letters that follow lowercase/numbers\n\t\t\t.replace(/([a-z0-9])([A-Z])/g, '$1_$2')\n\t\t\t// Insert underscore before the last uppercase in a sequence followed by lowercase\n\t\t\t.replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')\n\t\t\t.toLowerCase();\n\n\t\treturn leadingUnderscores + snakeCase;\n\t}\n\n\t/**\n\t * snake_case → camelCase\n\t */\n\ttoModel(identifier: string): string {\n\t\t// Handle empty strings\n\t\tif (!identifier) return identifier;\n\n\t\t// Preserve leading underscores\n\t\tconst leadingUnderscores = identifier.match(/^_+/)?.[0] ?? '';\n\t\tconst rest = identifier.slice(leadingUnderscores.length);\n\n\t\tif (!rest) return identifier;\n\n\t\t// Convert snake_case to camelCase\n\t\t// First character stays lowercase, subsequent segments are capitalized\n\t\tconst camelCase = rest.replace(/_([a-z0-9])/gi, (_, char: string) =>\n\t\t\tchar.toUpperCase(),\n\t\t);\n\n\t\treturn leadingUnderscores + camelCase;\n\t}\n}\n\n/**\n * Singleton instances for convenience\n */\nexport const identityNaming = new IdentityNamingPlugin();\nexport const camelCaseNaming = new CamelCaseNamingPlugin();\n\n/**\n * Get a naming plugin by DbCasing (intuitive semantics).\n * - `'snake_case'`: DB uses snake_case → CamelCaseNamingPlugin (transforms to camelCase)\n * - `'camelCase'`: DB uses camelCase → IdentityNamingPlugin (no transform)\n * - `'preserve'`: No transformation → IdentityNamingPlugin\n */\nexport function getNamingPluginForDbCasing(\n\tcasing: 'snake_case' | 'camelCase' | 'preserve',\n): NamingPlugin {\n\tswitch (casing) {\n\t\tcase 'snake_case':\n\t\t\treturn camelCaseNaming;\n\t\tcase 'camelCase':\n\t\tcase 'preserve':\n\t\t\treturn identityNaming;\n\t\tdefault:\n\t\t\treturn identityNaming;\n\t}\n}\n","/**\n * AST Helpers - Factory functions for building PostgreSQL AST nodes\n *\n * These helpers create properly typed AST nodes for the pgsql-deparser.\n * All functions follow a consistent pattern:\n * - Return wrapped Node types (e.g., { SelectStmt: {...} })\n * - Handle optional properties with exactOptionalPropertyTypes\n * - Support the NamingPlugin for identifier transformation\n */\n\nimport type { LockIntent, LockStrength, LockWaitPolicy } from '@dbsp/types';\nimport type {\n\tA_Expr,\n\tA_Expr_Kind,\n\tBoolExpr,\n\tBoolExprType,\n\tDeleteStmt,\n\tFuncCall,\n\tInsertStmt,\n\tJoinExpr,\n\tJoinType,\n\tLockClauseStrength,\n\tNode,\n\tLockWaitPolicy as PgLockWaitPolicy,\n\tRangeVar,\n\tResTarget,\n\tSelectStmt,\n\tSortBy,\n\tTypeCast,\n\tTypeName,\n\tUpdateStmt,\n} from '@pgsql/types';\n\nimport type { NamingPlugin } from './naming-plugin.js';\nimport { identityNaming } from './naming-plugin.js';\n\n// Re-export normalizeSQL from core (canonical location since A-9 DRY refactor)\nexport { normalizeSQL } from '@dbsp/core';\n\n// ============================================================================\n// Internal Helpers\n// ============================================================================\n\nfunction applyReturningList(\n\tstmt: { returningList?: Node[] },\n\treturning: Node[] | undefined,\n): void {\n\tif (returning && returning.length > 0) {\n\t\tstmt.returningList = returning;\n\t}\n}\n\n// ============================================================================\n// Basic Value Nodes\n// ============================================================================\n\n/**\n * Create a String node (for identifiers, operators, etc.)\n */\nexport function stringNode(value: string): Node {\n\treturn { String: { sval: value } };\n}\n\n/**\n * Create an Integer node\n */\nexport function integerNode(value: number): Node {\n\treturn { Integer: { ival: value } };\n}\n\n/**\n * Create a Float node\n */\nexport function floatNode(value: string): Node {\n\treturn { Float: { fval: value } };\n}\n\n/**\n * Create a Boolean node (PostgreSQL constant)\n */\nexport function booleanConstNode(value: boolean): Node {\n\treturn {\n\t\tA_Const: {\n\t\t\tboolval: { boolval: value },\n\t\t},\n\t};\n}\n\n/**\n * Create a NULL constant node\n */\nexport function nullConstNode(): Node {\n\treturn {\n\t\tA_Const: {\n\t\t\tisnull: true,\n\t\t},\n\t};\n}\n\n// ============================================================================\n// Column and Table References\n// ============================================================================\n\n/**\n * Create a ColumnRef node\n * @param column - Column name\n * @param table - Optional table name or alias\n * @param schema - Optional schema name\n * @param naming - Naming plugin for transformation\n */\nexport function columnRef(\n\tcolumn: string,\n\ttable?: string,\n\tschema?: string,\n\tnaming: NamingPlugin = identityNaming,\n): Node {\n\tconst fields: Node[] = [];\n\n\tif (schema) {\n\t\tfields.push(stringNode(naming.toDatabase(schema)));\n\t}\n\tif (table) {\n\t\tfields.push(stringNode(naming.toDatabase(table)));\n\t}\n\tfields.push(stringNode(naming.toDatabase(column)));\n\n\treturn { ColumnRef: { fields } };\n}\n\n/**\n * Create a ColumnRef for \"table.*\" (star/wildcard)\n */\nexport function columnRefStar(\n\ttable?: string,\n\tnaming: NamingPlugin = identityNaming,\n): Node {\n\tconst fields: Node[] = [];\n\n\tif (table) {\n\t\tfields.push(stringNode(naming.toDatabase(table)));\n\t}\n\tfields.push({ A_Star: {} });\n\n\treturn { ColumnRef: { fields } };\n}\n\n/**\n * Create a RangeVar node (table reference in FROM clause)\n */\nexport function rangeVar(\n\ttable: string,\n\talias?: string,\n\tschema?: string,\n\tnaming: NamingPlugin = identityNaming,\n): Node {\n\tconst rv: RangeVar = {\n\t\trelname: naming.toDatabase(table),\n\t\tinh: true,\n\t\trelpersistence: 'p',\n\t};\n\n\tif (schema) {\n\t\trv.schemaname = naming.toDatabase(schema);\n\t}\n\n\tif (alias) {\n\t\trv.alias = { aliasname: naming.toDatabase(alias) };\n\t}\n\n\treturn { RangeVar: rv };\n}\n\n// ============================================================================\n// Target List (SELECT expressions)\n// ============================================================================\n\n/**\n * Create a ResTarget node (target in SELECT list)\n * @param val - Expression value\n * @param name - Optional alias (AS name)\n */\nexport function resTarget(val: Node, name?: string): Node {\n\tconst rt: ResTarget = { val };\n\n\tif (name) {\n\t\trt.name = name;\n\t}\n\n\treturn { ResTarget: rt };\n}\n\n/**\n * Create a ResTarget for a simple column\n */\nexport function columnTarget(\n\tcolumn: string,\n\talias?: string,\n\ttable?: string,\n\tnaming: NamingPlugin = identityNaming,\n): Node {\n\treturn resTarget(columnRef(column, table, undefined, naming), alias);\n}\n\n/**\n * Create a ResTarget for \"*\" (all columns)\n */\nexport function starTarget(\n\ttable?: string,\n\tnaming: NamingPlugin = identityNaming,\n): Node {\n\treturn resTarget(columnRefStar(table, naming));\n}\n\n// ============================================================================\n// Expressions\n// ============================================================================\n\n/**\n * Create an A_Expr node for binary operations\n */\nexport function binaryExpr(\n\toperator: string,\n\tleft: Node,\n\tright: Node,\n\tkind: A_Expr_Kind = 'AEXPR_OP',\n): Node {\n\tconst expr: A_Expr = {\n\t\tkind,\n\t\tname: [stringNode(operator)],\n\t\tlexpr: left,\n\t\trexpr: right,\n\t};\n\n\treturn { A_Expr: expr };\n}\n\n/**\n * Create an equality expression (col = value)\n */\nexport function eqExpr(left: Node, right: Node): Node {\n\treturn binaryExpr('=', left, right);\n}\n\n/**\n * Build an FK-based correlation condition: alias1.col1 = alias2.col2\n * Used by all include handlers (JOIN, LATERAL, CTE, JSON_AGG).\n */\nexport function fkCorrelation(\n\tcol1: string,\n\talias1: string,\n\tcol2: string,\n\talias2: string,\n\tnaming: NamingPlugin,\n): Node {\n\treturn eqExpr(\n\t\tcolumnRef(col1, alias1, undefined, naming),\n\t\tcolumnRef(col2, alias2, undefined, naming),\n\t);\n}\n\n/**\n * Create a not-equal expression (col <> value)\n */\nexport function neExpr(left: Node, right: Node): Node {\n\treturn binaryExpr('<>', left, right);\n}\n\n/**\n * Create comparison expressions\n */\nexport function ltExpr(left: Node, right: Node): Node {\n\treturn binaryExpr('<', left, right);\n}\n\nexport function lteExpr(left: Node, right: Node): Node {\n\treturn binaryExpr('<=', left, right);\n}\n\nexport function gtExpr(left: Node, right: Node): Node {\n\treturn binaryExpr('>', left, right);\n}\n\nexport function gteExpr(left: Node, right: Node): Node {\n\treturn binaryExpr('>=', left, right);\n}\n\n/**\n * Create a LIKE expression\n */\nexport function likeExpr(left: Node, right: Node): Node {\n\treturn binaryExpr('~~', left, right, 'AEXPR_LIKE');\n}\n\n/**\n * Create an ILIKE expression (case-insensitive)\n */\nexport function ilikeExpr(left: Node, right: Node): Node {\n\treturn binaryExpr('~~*', left, right, 'AEXPR_ILIKE');\n}\n\n/**\n * Create a BoolExpr node (AND, OR, NOT)\n */\nexport function boolExpr(type: BoolExprType, args: Node[]): Node {\n\tconst expr: BoolExpr = {\n\t\tboolop: type,\n\t\targs,\n\t};\n\n\treturn { BoolExpr: expr };\n}\n\n/**\n * Create an AND expression\n */\nexport function andExpr(...args: Node[]): Node {\n\treturn boolExpr('AND_EXPR', args);\n}\n\n/**\n * Create an OR expression\n */\nexport function orExpr(...args: Node[]): Node {\n\treturn boolExpr('OR_EXPR', args);\n}\n\n/**\n * Create a NOT expression\n */\nexport function notExpr(arg: Node): Node {\n\treturn boolExpr('NOT_EXPR', [arg]);\n}\n\n// ============================================================================\n// Type Casts\n// ============================================================================\n\n/**\n * Create a TypeCast node\n */\nexport function typeCast(arg: Node, typeName: string, isArray = false): Node {\n\tconst tn: TypeName = {\n\t\tnames: [stringNode(typeName)],\n\t\ttypemod: -1,\n\t};\n\n\tif (isArray) {\n\t\ttn.arrayBounds = [integerNode(-1)];\n\t}\n\n\tconst tc: TypeCast = {\n\t\targ,\n\t\ttypeName: tn,\n\t};\n\n\treturn { TypeCast: tc };\n}\n\n// ============================================================================\n// Function Calls\n// ============================================================================\n\n/**\n * Create a FuncCall node for database functions.\n *\n * Note: SQL keywords like COALESCE, NULLIF, CASE, GREATEST, LEAST have their\n * own dedicated AST nodes (CoalesceExpr, NullIfExpr, CaseExpr, MinMaxExpr).\n * Use FuncCall for:\n * - Aggregate functions (count, sum, avg, etc.)\n * - User-defined functions\n * - Extension functions (PostGIS, pgcrypto, etc.)\n *\n * The pgsql-deparser will quote function names to preserve case.\n * This is correct behavior for user-defined and extension functions.\n */\nexport function funcCall(\n\tname: string | string[],\n\targs: Node[] = [],\n\toptions: {\n\t\tdistinct?: boolean;\n\t\tstar?: boolean;\n\t\torderBy?: Node[];\n\t\tfilter?: Node;\n\t} = {},\n): Node {\n\tconst names = Array.isArray(name) ? name.map(stringNode) : [stringNode(name)];\n\n\tconst fc: FuncCall = {\n\t\tfuncname: names,\n\t};\n\n\tif (options.star) {\n\t\tfc.agg_star = true;\n\t} else if (args.length > 0) {\n\t\tfc.args = args;\n\t}\n\n\tif (options.distinct) {\n\t\tfc.agg_distinct = true;\n\t}\n\n\tif (options.orderBy && options.orderBy.length > 0) {\n\t\tfc.agg_order = options.orderBy;\n\t}\n\n\tif (options.filter) {\n\t\tfc.agg_filter = options.filter;\n\t}\n\n\treturn { FuncCall: fc };\n}\n\n/**\n * Create a COALESCE expression node.\n * COALESCE is a SQL keyword (not a function), so it uses CoalesceExpr instead of FuncCall.\n */\nexport function coalesceExpr(args: Node[]): Node {\n\treturn { CoalesceExpr: { args } };\n}\n\n/**\n * Shorthand for COUNT(*)\n */\nexport function countStar(): Node {\n\treturn funcCall('count', [], { star: true });\n}\n\n/**\n * Shorthand for COUNT(DISTINCT col)\n */\nexport function countDistinct(col: Node): Node {\n\treturn funcCall('count', [col], { distinct: true });\n}\n\n/**\n * Create a COALESCE function call\n */\nexport function coalesce(...args: Node[]): Node {\n\treturn funcCall('coalesce', args);\n}\n\n// ============================================================================\n// Sort/Order By\n// ============================================================================\n\n/**\n * Create a SortBy node\n */\nexport function sortBy(\n\texpr: Node,\n\tdirection: 'ASC' | 'DESC' | 'DEFAULT' = 'DEFAULT',\n\tnulls: 'FIRST' | 'LAST' | 'DEFAULT' = 'DEFAULT',\n): Node {\n\tconst sb: SortBy = {\n\t\tnode: expr,\n\t\tsortby_dir:\n\t\t\tdirection === 'ASC'\n\t\t\t\t? 'SORTBY_ASC'\n\t\t\t\t: direction === 'DESC'\n\t\t\t\t\t? 'SORTBY_DESC'\n\t\t\t\t\t: 'SORTBY_DEFAULT',\n\t\tsortby_nulls:\n\t\t\tnulls === 'FIRST'\n\t\t\t\t? 'SORTBY_NULLS_FIRST'\n\t\t\t\t: nulls === 'LAST'\n\t\t\t\t\t? 'SORTBY_NULLS_LAST'\n\t\t\t\t\t: 'SORTBY_NULLS_DEFAULT',\n\t};\n\n\treturn { SortBy: sb };\n}\n\n// ============================================================================\n// Joins\n// ============================================================================\n\n/**\n * Create a JoinExpr node\n */\nexport function joinExpr(\n\tjoinType: JoinType,\n\tleft: Node,\n\tright: Node,\n\tquals?: Node,\n\talias?: string,\n): Node {\n\tconst je: JoinExpr = {\n\t\tjointype: joinType,\n\t\tlarg: left,\n\t\trarg: right,\n\t};\n\n\tif (quals) {\n\t\tje.quals = quals;\n\t}\n\n\tif (alias) {\n\t\tje.alias = { aliasname: alias };\n\t}\n\n\treturn { JoinExpr: je };\n}\n\n/**\n * Create an INNER JOIN\n */\nexport function innerJoin(\n\tleft: Node,\n\tright: Node,\n\ton: Node,\n\talias?: string,\n): Node {\n\treturn joinExpr('JOIN_INNER', left, right, on, alias);\n}\n\n/**\n * Create a LEFT JOIN\n */\nexport function leftJoin(\n\tleft: Node,\n\tright: Node,\n\ton: Node,\n\talias?: string,\n): Node {\n\treturn joinExpr('JOIN_LEFT', left, right, on, alias);\n}\n\n// ============================================================================\n// SELECT Statement\n// ============================================================================\n\ninterface SelectOptions {\n\ttargetList: Node[];\n\tfrom?: Node[];\n\twhere?: Node;\n\tgroupBy?: Node[];\n\thaving?: Node;\n\torderBy?: Node[];\n\tlimit?: Node;\n\toffset?: Node;\n\tdistinct?: boolean | Node[];\n\t/** WITH clause (e.g., CTEs) — { ctes: Node[], recursive?: boolean } */\n\twithClause?: { ctes: Node[]; recursive?: boolean };\n\t/** Row-level locking clause (FOR UPDATE/SHARE/etc.) */\n\tlockingClause?: {\n\t\tstrength: LockClauseStrength;\n\t\twaitPolicy?: PgLockWaitPolicy;\n\t\t/** Tables to lock (FOR UPDATE OF ...). If omitted, locks all tables. */\n\t\tlockedRels?: Node[];\n\t};\n}\n\n/**\n * Create a SelectStmt node\n */\nexport function selectStmt(options: SelectOptions): Node {\n\tconst stmt: SelectStmt = {\n\t\ttargetList: options.targetList,\n\t};\n\n\tif (options.from && options.from.length > 0) {\n\t\tstmt.fromClause = options.from;\n\t}\n\n\tif (options.where) {\n\t\tstmt.whereClause = options.where;\n\t}\n\n\tif (options.groupBy && options.groupBy.length > 0) {\n\t\tstmt.groupClause = options.groupBy;\n\t}\n\n\tif (options.having) {\n\t\tstmt.havingClause = options.having;\n\t}\n\n\tif (options.orderBy && options.orderBy.length > 0) {\n\t\tstmt.sortClause = options.orderBy;\n\t}\n\n\tif (options.limit) {\n\t\tstmt.limitCount = options.limit;\n\t}\n\n\tif (options.offset) {\n\t\tstmt.limitOffset = options.offset;\n\t}\n\n\tif (options.distinct === true) {\n\t\tstmt.distinctClause = [];\n\t} else if (Array.isArray(options.distinct) && options.distinct.length > 0) {\n\t\tstmt.distinctClause = options.distinct;\n\t}\n\n\tif (options.withClause && options.withClause.ctes.length > 0) {\n\t\tstmt.withClause = {\n\t\t\tctes: options.withClause.ctes,\n\t\t\trecursive: options.withClause.recursive ?? false,\n\t\t};\n\t}\n\n\tif (options.lockingClause) {\n\t\tconst clause: Record<string, unknown> = {\n\t\t\tstrength: options.lockingClause.strength,\n\t\t\twaitPolicy: options.lockingClause.waitPolicy ?? 'LockWaitBlock',\n\t\t};\n\t\tif (\n\t\t\toptions.lockingClause.lockedRels &&\n\t\t\toptions.lockingClause.lockedRels.length > 0\n\t\t) {\n\t\t\tclause.lockedRels = options.lockingClause.lockedRels;\n\t\t}\n\t\tstmt.lockingClause = [{ LockingClause: clause }] as Node[];\n\t}\n\n\treturn { SelectStmt: stmt };\n}\n\n// ============================================================================\n// Lock Helpers\n// ============================================================================\n\nconst STRENGTH_MAP: Record<LockStrength, LockClauseStrength> = {\n\tforUpdate: 'LCS_FORUPDATE',\n\tforNoKeyUpdate: 'LCS_FORNOKEYUPDATE',\n\tforShare: 'LCS_FORSHARE',\n\tforKeyShare: 'LCS_FORKEYSHARE',\n};\n\nconst POLICY_MAP: Record<LockWaitPolicy, PgLockWaitPolicy> = {\n\tblock: 'LockWaitBlock',\n\tskipLocked: 'LockWaitSkip',\n\tnoWait: 'LockWaitError',\n};\n\n/**\n * Map a LockIntent (domain type) to AST-level locking parameters.\n * Used by the compiler to translate intent-level lock to SelectOptions.lockingClause.\n */\nexport function mapLockToAst(lock: LockIntent): {\n\tstrength: LockClauseStrength;\n\twaitPolicy: PgLockWaitPolicy;\n} {\n\treturn {\n\t\tstrength: STRENGTH_MAP[lock.strength],\n\t\twaitPolicy: POLICY_MAP[lock.waitPolicy],\n\t};\n}\n\n// ============================================================================\n// INSERT Statement\n// ============================================================================\n\nexport interface InsertOptions {\n\ttable: string;\n\tschema?: string;\n\tcolumns?: string[];\n\t/** VALUES rows for INSERT ... VALUES */\n\tvalues?: Node[][];\n\t/** SELECT query for INSERT ... SELECT */\n\tselectQuery?: Node;\n\treturning?: Node[];\n\tonConflict?: {\n\t\ttarget?: string[];\n\t\taction: 'nothing' | 'update';\n\t\tupdateSet?: Array<{ column: string; value: Node }>;\n\t};\n\tnaming?: NamingPlugin;\n}\n\n/**\n * Create an InsertStmt node\n */\nexport function insertStmt(options: InsertOptions): Node {\n\tconst naming = options.naming ?? identityNaming;\n\n\tconst relation: RangeVar = {\n\t\trelname: naming.toDatabase(options.table),\n\t\tinh: true,\n\t\trelpersistence: 'p',\n\t};\n\n\tif (options.schema) {\n\t\trelation.schemaname = naming.toDatabase(options.schema);\n\t}\n\n\tconst stmt: InsertStmt = {\n\t\trelation,\n\t};\n\n\tif (options.columns && options.columns.length > 0) {\n\t\tstmt.cols = options.columns.map((col) => ({\n\t\t\tResTarget: { name: naming.toDatabase(col) },\n\t\t}));\n\t}\n\n\tif (options.selectQuery) {\n\t\t// INSERT ... SELECT: use provided query directly\n\t\tstmt.selectStmt = options.selectQuery;\n\t} else if (options.values && options.values.length > 0) {\n\t\t// VALUES clause represented as a SelectStmt with valuesLists\n\t\t// Each row is wrapped in a List node\n\t\tstmt.selectStmt = {\n\t\t\tSelectStmt: {\n\t\t\t\tvaluesLists: options.values.map((row) => ({ List: { items: row } })),\n\t\t\t},\n\t\t};\n\t}\n\n\tapplyReturningList(stmt, options.returning);\n\n\t// ON CONFLICT handling would go here (complex, defer for now)\n\n\treturn { InsertStmt: stmt };\n}\n\n// ============================================================================\n// UPDATE Statement\n// ============================================================================\n\nexport interface UpdateOptions {\n\ttable: string;\n\tschema?: string;\n\tset: Array<{ column: string; value: Node }>;\n\twhere?: Node;\n\tfrom?: Node[];\n\treturning?: Node[];\n\tnaming?: NamingPlugin;\n}\n\n/**\n * Create an UpdateStmt node\n */\nexport function updateStmt(options: UpdateOptions): Node {\n\tconst naming = options.naming ?? identityNaming;\n\n\tconst relation: RangeVar = {\n\t\trelname: naming.toDatabase(options.table),\n\t\tinh: true,\n\t\trelpersistence: 'p',\n\t};\n\n\tif (options.schema) {\n\t\trelation.schemaname = naming.toDatabase(options.schema);\n\t}\n\n\tconst stmt: UpdateStmt = {\n\t\trelation,\n\t\ttargetList: options.set.map(({ column, value }) => ({\n\t\t\tResTarget: {\n\t\t\t\tname: naming.toDatabase(column),\n\t\t\t\tval: value,\n\t\t\t},\n\t\t})),\n\t};\n\n\tif (options.where) {\n\t\tstmt.whereClause = options.where;\n\t}\n\n\tif (options.from && options.from.length > 0) {\n\t\tstmt.fromClause = options.from;\n\t}\n\n\tapplyReturningList(stmt, options.returning);\n\n\treturn { UpdateStmt: stmt };\n}\n\n// ============================================================================\n// DELETE Statement\n// ============================================================================\n\nexport interface DeleteOptions {\n\ttable: string;\n\tschema?: string;\n\twhere?: Node;\n\tusing?: Node[];\n\treturning?: Node[];\n\tnaming?: NamingPlugin;\n}\n\n/**\n * Create a DeleteStmt node\n */\nexport function deleteStmt(options: DeleteOptions): Node {\n\tconst naming = options.naming ?? identityNaming;\n\n\tconst relation: RangeVar = {\n\t\trelname: naming.toDatabase(options.table),\n\t\tinh: true,\n\t\trelpersistence: 'p',\n\t};\n\n\tif (options.schema) {\n\t\trelation.schemaname = naming.toDatabase(options.schema);\n\t}\n\n\tconst stmt: DeleteStmt = {\n\t\trelation,\n\t};\n\n\tif (options.where) {\n\t\tstmt.whereClause = options.where;\n\t}\n\n\tif (options.using && options.using.length > 0) {\n\t\tstmt.usingClause = options.using;\n\t}\n\n\tapplyReturningList(stmt, options.returning);\n\n\treturn { DeleteStmt: stmt };\n}\n\n// ============================================================================\n// Window Functions\n// ============================================================================\n\n/**\n * Create a window function call with OVER clause.\n * Example: ROW_NUMBER() OVER (PARTITION BY x ORDER BY y) AS alias\n */\nexport function windowFuncCall(\n\tfuncName: string,\n\targs: Node[],\n\tover: {\n\t\tpartitionBy?: readonly string[];\n\t\torderBy?: readonly { field: string; direction?: 'asc' | 'desc' }[];\n\t},\n\tnaming: NamingPlugin,\n\ttable?: string,\n): Node {\n\t// Build partition clause\n\tconst partitionClause: Node[] = (over.partitionBy ?? []).map((col) =>\n\t\tcolumnRef(col, table, undefined, naming),\n\t);\n\n\t// Build order clause using existing sortBy helper\n\tconst orderClause: Node[] = (over.orderBy ?? []).map((ob) =>\n\t\tsortBy(\n\t\t\tcolumnRef(ob.field, table, undefined, naming),\n\t\t\tob.direction === 'desc' ? 'DESC' : 'ASC',\n\t\t),\n\t);\n\n\t// Window definition\n\tconst windowDef: Record<string, unknown> = {\n\t\tframeOptions: 1034, // Implicit default frame (NONDEFAULT bit not set → no frame clause emitted)\n\t};\n\n\tif (partitionClause.length > 0) {\n\t\twindowDef.partitionClause = partitionClause;\n\t}\n\tif (orderClause.length > 0) {\n\t\twindowDef.orderClause = orderClause;\n\t}\n\n\t// Build the FuncCall with over property\n\t// Window functions like row_number, rank, etc. are actual database functions\n\t// and will work correctly even when quoted by the deparser\n\tconst funcCallObj: Record<string, unknown> = {\n\t\tfuncname: [stringNode(funcName)],\n\t\tover: windowDef,\n\t};\n\n\tif (args.length > 0) {\n\t\tfuncCallObj.args = args;\n\t} else if (funcName.toLowerCase() === 'count') {\n\t\t// count() without args → count(*) via agg_star\n\t\tfuncCallObj.agg_star = true;\n\t}\n\n\treturn { FuncCall: funcCallObj as FuncCall };\n}\n\n// ============================================================================\n// JSON Aggregation (for include strategies)\n// ============================================================================\n\n/**\n * Create a json_agg correlated subquery for relation includes.\n *\n * Generates:\n * COALESCE(\n * (SELECT json_agg(to_jsonb(__t__)) FROM schema.table AS __t__ WHERE __t__.fk = parent.pk),\n * '[]'::json\n * ) AS \"relation_json\"\n *\n * @param targetTable - The target table name (e.g., 'authors')\n * @param targetAlias - Alias for the target table in subquery (default: '__t__')\n * @param whereExpr - The correlation WHERE expression\n * @param alias - The column alias (e.g., 'author_json')\n * @param schemaName - Optional schema name\n * @param naming - Naming plugin for identifier transformation\n */\nexport function jsonAggSubquery(\n\ttargetTable: string,\n\twhereExpr: Node,\n\talias: string,\n\tschemaName?: string,\n\tnaming: NamingPlugin = identityNaming,\n\toptions?: {\n\t\t/** Nested child subqueries to merge via jsonb_build_object */\n\t\tchildNodes?: readonly { key: string; node: Node }[];\n\t\t/** Override the default __t__ alias (for nested depth) */\n\t\tinnerAlias?: string;\n\t\t/** Optional LIMIT on the subquery rows */\n\t\tlimit?: number;\n\t\t/** Column projection — if specified, use jsonb_build_object instead of to_jsonb(__t__) */\n\t\tcolumns?: readonly string[];\n\t},\n): Node {\n\tconst targetAlias = options?.innerAlias ?? '__t__';\n\n\t// Build row expression: either projected columns or full row\n\tconst cols = options?.columns;\n\tconst hasProjection =\n\t\tcols && cols.length > 0 && !(cols.length === 1 && cols[0] === '*');\n\n\tlet toJsonbCall: Node;\n\tif (hasProjection) {\n\t\t// Column projection: jsonb_build_object('col1', __t__.\"col1\", 'col2', __t__.\"col2\", ...)\n\t\tconst projArgs: Node[] = [];\n\t\tfor (const col of cols) {\n\t\t\tprojArgs.push({ A_Const: { sval: { sval: naming.toDatabase(col) } } });\n\t\t\tprojArgs.push(columnRef(col, targetAlias, undefined, naming));\n\t\t}\n\t\ttoJsonbCall = {\n\t\t\tFuncCall: {\n\t\t\t\tfuncname: [stringNode('jsonb_build_object')],\n\t\t\t\targs: projArgs,\n\t\t\t} as FuncCall,\n\t\t};\n\t} else {\n\t\t// Full row: to_jsonb(__t__)\n\t\t// In PostgreSQL, __t__ refers to the entire row when used with aggregate/jsonb functions\n\t\tconst rowRef: Node = {\n\t\t\tColumnRef: {\n\t\t\t\tfields: [stringNode(targetAlias)],\n\t\t\t},\n\t\t};\n\t\ttoJsonbCall = {\n\t\t\tFuncCall: {\n\t\t\t\tfuncname: [stringNode('to_jsonb')],\n\t\t\t\targs: [rowRef],\n\t\t\t} as FuncCall,\n\t\t};\n\t}\n\n\t// If there are nested children, merge them via:\n\t// to_jsonb(__t__) || jsonb_build_object('child1', <subquery1>, 'child2', <subquery2>)\n\tif (options?.childNodes && options.childNodes.length > 0) {\n\t\tconst buildObjectArgs: Node[] = [];\n\t\tfor (const child of options.childNodes) {\n\t\t\tbuildObjectArgs.push({ A_Const: { sval: { sval: child.key } } });\n\t\t\tbuildObjectArgs.push(child.node);\n\t\t}\n\n\t\tconst jsonbBuildObject: Node = {\n\t\t\tFuncCall: {\n\t\t\t\tfuncname: [stringNode('jsonb_build_object')],\n\t\t\t\targs: buildObjectArgs,\n\t\t\t} as FuncCall,\n\t\t};\n\n\t\t// to_jsonb(__t__) || jsonb_build_object(...)\n\t\ttoJsonbCall = {\n\t\t\tA_Expr: {\n\t\t\t\tkind: 'AEXPR_OP',\n\t\t\t\tname: [stringNode('||')],\n\t\t\t\tlexpr: toJsonbCall,\n\t\t\t\trexpr: jsonbBuildObject,\n\t\t\t},\n\t\t};\n\t}\n\n\t// Build: json_agg(to_jsonb(__t__) [|| jsonb_build_object(...)])\n\tconst jsonAggCall: Node = {\n\t\tFuncCall: {\n\t\t\tfuncname: [stringNode('json_agg')],\n\t\t\targs: [toJsonbCall],\n\t\t} as FuncCall,\n\t};\n\n\t// Build the FROM clause: schema.table AS __t__\n\tconst fromTable = rangeVar(targetTable, targetAlias, schemaName, naming);\n\n\t// Build the inner SELECT statement\n\tconst limitNode =\n\t\toptions?.limit !== undefined\n\t\t\t? { A_Const: { ival: { ival: options.limit } } }\n\t\t\t: undefined;\n\tconst innerSelect = selectStmt({\n\t\ttargetList: [{ ResTarget: { val: jsonAggCall } }],\n\t\tfrom: [fromTable],\n\t\twhere: whereExpr,\n\t\t...(limitNode && { limit: limitNode }),\n\t});\n\n\t// Wrap in SubLink (subquery expression)\n\tconst subLink: Node = {\n\t\tSubLink: {\n\t\t\tsubLinkType: 'EXPR_SUBLINK', // scalar subquery\n\t\t\tsubselect: innerSelect,\n\t\t},\n\t};\n\n\t// Build: '[]'::json (empty array default)\n\tconst emptyArrayDefault: Node = {\n\t\tTypeCast: {\n\t\t\targ: { A_Const: { sval: { sval: '[]' } } },\n\t\t\ttypeName: {\n\t\t\t\tnames: [stringNode('json')],\n\t\t\t\ttypemod: -1,\n\t\t\t} as TypeName,\n\t\t} as TypeCast,\n\t};\n\n\t// Build: COALESCE(subquery, '[]'::json)\n\tconst coalesceNode = coalesceExpr([subLink, emptyArrayDefault]);\n\n\t// Wrap in ResTarget with alias\n\treturn {\n\t\tResTarget: {\n\t\t\tval: coalesceNode,\n\t\t\tname: alias,\n\t\t} as ResTarget,\n\t};\n}\n\n/**\n * Build a correlation WHERE expression for json_agg.\n *\n * For belongsTo: target.pk = parent.fk (e.g., authors.id = posts.author_id)\n * For hasMany: target.fk = parent.pk (e.g., posts.author_id = authors.id)\n */\nexport function jsonAggCorrelation(\n\tparentAlias: string,\n\tparentColumn: string,\n\ttargetAlias: string,\n\ttargetColumn: string,\n\tnaming: NamingPlugin = identityNaming,\n): Node {\n\t// __t__.column = parent.column\n\treturn eqExpr(\n\t\tcolumnRef(targetColumn, targetAlias, undefined, naming),\n\t\tcolumnRef(parentColumn, parentAlias, undefined, naming),\n\t);\n}\n","/**\n * ParamRef validation and helpers for PostgreSQL AST\n *\n * ParamRef nodes represent parameterized query placeholders ($1, $2, etc.)\n * This module provides validation and creation helpers for safe AST construction.\n */\nimport type {\n\tA_Expr,\n\tA_Expr_Kind,\n\tFuncCall,\n\tNode,\n\tParamRef,\n\tTypeCast,\n\tTypeName,\n} from '@pgsql/types';\n\n/**\n * Validation result for ParamRef nodes\n */\nexport interface ParamRefValidationResult {\n\tvalid: boolean;\n\terrors: string[];\n}\n\n/**\n * Validates a ParamRef node\n *\n * Rules:\n * - `number` must be a positive integer (1-based indexing)\n * - `number` must not exceed reasonable bounds (e.g., 65535)\n */\nexport function validateParamRef(paramRef: ParamRef): ParamRefValidationResult {\n\tconst errors: string[] = [];\n\n\tif (paramRef.number === undefined) {\n\t\terrors.push('ParamRef.number is required');\n\t} else if (!Number.isInteger(paramRef.number)) {\n\t\terrors.push(`ParamRef.number must be an integer, got: ${paramRef.number}`);\n\t} else if (paramRef.number < 1) {\n\t\terrors.push(\n\t\t\t`ParamRef.number must be >= 1 (1-based indexing), got: ${paramRef.number}`,\n\t\t);\n\t} else if (paramRef.number > 65535) {\n\t\terrors.push(\n\t\t\t`ParamRef.number exceeds maximum (65535), got: ${paramRef.number}`,\n\t\t);\n\t}\n\n\treturn {\n\t\tvalid: errors.length === 0,\n\t\terrors,\n\t};\n}\n\n/**\n * Creates a validated ParamRef node\n * @throws Error if validation fails\n */\nexport function createParamRef(number: number, location?: number): Node {\n\tconst paramRef: ParamRef =\n\t\tlocation !== undefined ? { number, location } : { number };\n\tconst result = validateParamRef(paramRef);\n\n\tif (!result.valid) {\n\t\tthrow new Error(`Invalid ParamRef: ${result.errors.join(', ')}`);\n\t}\n\n\treturn { ParamRef: paramRef };\n}\n\n/**\n * Creates a TypeCast node wrapping a ParamRef\n * Example: $1::integer, $2::text[]\n */\nexport function createTypeCastParamRef(\n\tparamNumber: number,\n\ttypeName: string,\n\tisArray = false,\n\tlocation?: number,\n): Node {\n\tconst paramRefNode = createParamRef(paramNumber, location);\n\n\tconst typeNameNode: TypeName = isArray\n\t\t? {\n\t\t\t\tnames: [{ String: { sval: typeName } }],\n\t\t\t\ttypemod: -1,\n\t\t\t\tarrayBounds: [{ Integer: { ival: -1 } }],\n\t\t\t}\n\t\t: {\n\t\t\t\tnames: [{ String: { sval: typeName } }],\n\t\t\t\ttypemod: -1,\n\t\t\t};\n\n\tconst typeCast: TypeCast =\n\t\tlocation !== undefined\n\t\t\t? {\n\t\t\t\t\targ: paramRefNode,\n\t\t\t\t\ttypeName: typeNameNode,\n\t\t\t\t\tlocation,\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\targ: paramRefNode,\n\t\t\t\t\ttypeName: typeNameNode,\n\t\t\t\t};\n\n\treturn { TypeCast: typeCast };\n}\n\n/**\n * Creates an A_Expr node for equality comparison with ParamRef\n * Example: col = $1\n */\nexport function createEqualityExpr(\n\tcolumnName: string,\n\tparamNumber: number,\n\ttableName?: string,\n\tlocation?: number,\n): Node {\n\tconst fields: Node[] = tableName\n\t\t? [{ String: { sval: tableName } }, { String: { sval: columnName } }]\n\t\t: [{ String: { sval: columnName } }];\n\n\tconst kind: A_Expr_Kind = 'AEXPR_OP';\n\n\tconst expr: A_Expr =\n\t\tlocation !== undefined\n\t\t\t? {\n\t\t\t\t\tkind,\n\t\t\t\t\tname: [{ String: { sval: '=' } }],\n\t\t\t\t\tlexpr: { ColumnRef: { fields, location } },\n\t\t\t\t\trexpr: createParamRef(paramNumber, location),\n\t\t\t\t\tlocation,\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tkind,\n\t\t\t\t\tname: [{ String: { sval: '=' } }],\n\t\t\t\t\tlexpr: { ColumnRef: { fields } },\n\t\t\t\t\trexpr: createParamRef(paramNumber),\n\t\t\t\t};\n\n\treturn { A_Expr: expr };\n}\n\n/**\n * Creates a FuncCall node for ANY() with ParamRef\n * Example: col = ANY($1) for array parameter matching\n */\nexport function createAnyExpr(\n\tcolumnName: string,\n\tparamNumber: number,\n\ttableName?: string,\n\tlocation?: number,\n): Node {\n\tconst fields: Node[] = tableName\n\t\t? [{ String: { sval: tableName } }, { String: { sval: columnName } }]\n\t\t: [{ String: { sval: columnName } }];\n\n\tconst kind: A_Expr_Kind = 'AEXPR_OP';\n\n\t// ANY($1) is represented as a FuncCall with special handling\n\tconst anyCall: FuncCall =\n\t\tlocation !== undefined\n\t\t\t? {\n\t\t\t\t\tfuncname: [{ String: { sval: 'any' } }],\n\t\t\t\t\targs: [createParamRef(paramNumber, location)],\n\t\t\t\t\tlocation,\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tfuncname: [{ String: { sval: 'any' } }],\n\t\t\t\t\targs: [createParamRef(paramNumber)],\n\t\t\t\t};\n\n\tconst expr: A_Expr =\n\t\tlocation !== undefined\n\t\t\t? {\n\t\t\t\t\tkind,\n\t\t\t\t\tname: [{ String: { sval: '=' } }],\n\t\t\t\t\tlexpr: { ColumnRef: { fields, location } },\n\t\t\t\t\trexpr: { FuncCall: anyCall },\n\t\t\t\t\tlocation,\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tkind,\n\t\t\t\t\tname: [{ String: { sval: '=' } }],\n\t\t\t\t\tlexpr: { ColumnRef: { fields } },\n\t\t\t\t\trexpr: { FuncCall: anyCall },\n\t\t\t\t};\n\n\treturn { A_Expr: expr };\n}\n\n/**\n * Collects all ParamRef nodes from an AST, validating each\n * Returns validation results for all found ParamRefs\n */\nexport function collectAndValidateParamRefs(node: unknown): {\n\tparamRefs: Array<{ paramRef: ParamRef; path: string }>;\n\tvalidationResults: ParamRefValidationResult[];\n\tallValid: boolean;\n} {\n\tconst paramRefs: Array<{ paramRef: ParamRef; path: string }> = [];\n\n\tfunction traverse(n: unknown, path: string): void {\n\t\tif (n === null || n === undefined) return;\n\n\t\tif (typeof n === 'object') {\n\t\t\tconst obj = n as Record<string, unknown>;\n\n\t\t\t// Check if this is a ParamRef node\n\t\t\tif ('ParamRef' in obj && obj.ParamRef !== undefined) {\n\t\t\t\tparamRefs.push({\n\t\t\t\t\tparamRef: obj.ParamRef as ParamRef,\n\t\t\t\t\tpath,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Recurse into all properties\n\t\t\tfor (const [key, value] of Object.entries(obj)) {\n\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\tvalue.forEach((item, index) => {\n\t\t\t\t\t\ttraverse(item, `${path}.${key}[${index}]`);\n\t\t\t\t\t});\n\t\t\t\t} else if (typeof value === 'object') {\n\t\t\t\t\ttraverse(value, `${path}.${key}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\ttraverse(node, 'root');\n\n\tconst validationResults = paramRefs.map((p) => validateParamRef(p.paramRef));\n\tconst allValid = validationResults.every((r) => r.valid);\n\n\treturn { paramRefs, validationResults, allValid };\n}\n","/**\n * Shared CASE value resolver.\n *\n * Resolves THEN/ELSE values in CASE expressions to AST nodes.\n * Used by both the compiler (compileCaseValue) and the DX handler (resolveCaseValue).\n */\n\nimport type { Node } from '@pgsql/types';\nimport {\n\tbooleanConstNode,\n\tcolumnRef,\n\tfloatNode,\n\tintegerNode,\n\tnullConstNode,\n} from '../../ast-helpers.js';\nimport type { NamingPlugin } from '../../naming-plugin.js';\nimport { createParamRef } from '../../param-ref.js';\nimport type { CompilerState } from '../types.js';\n\n/**\n * Optional handler for nested CASE expressions.\n * The compiler provides this to delegate back to compileCaseExpression;\n * the DX handler omits it (nested CASE falls through to default parameterization).\n */\ntype NestedCaseHandler = (expr: Record<string, unknown>) => Node;\n\n/**\n * Resolve a CASE THEN/ELSE value to an AST node.\n *\n * Handles ExpressionIntent objects (column, literal, arithmetic, nested case)\n * and plain scalars (string → column ref, number/boolean → literal or param).\n */\nexport function resolveCaseValue(\n\tvalue: unknown,\n\talias: string,\n\tschema: string | undefined,\n\tnaming: NamingPlugin | undefined,\n\tstate: CompilerState,\n\tnestedCaseHandler?: NestedCaseHandler,\n): Node {\n\tif (value === null || value === undefined) {\n\t\treturn nullConstNode();\n\t}\n\n\tif (typeof value === 'string') {\n\t\treturn columnRef(value, alias, schema, naming);\n\t}\n\n\tif (typeof value !== 'object') {\n\t\tconst idx = ++state.paramIndex;\n\t\tstate.parameters.push(value);\n\t\treturn createParamRef(idx);\n\t}\n\n\tconst expr = value as Record<string, unknown>;\n\tswitch (expr.kind) {\n\t\tcase 'literal':\n\t\t\tif (expr.value === null || expr.value === undefined)\n\t\t\t\treturn nullConstNode();\n\t\t\tif (typeof expr.value === 'boolean')\n\t\t\t\treturn booleanConstNode(expr.value as boolean);\n\t\t\tif (typeof expr.value === 'number') {\n\t\t\t\tif (Number.isInteger(expr.value))\n\t\t\t\t\treturn integerNode(expr.value as number);\n\t\t\t\treturn floatNode(String(expr.value));\n\t\t\t}\n\t\t\t{\n\t\t\t\tconst idx = ++state.paramIndex;\n\t\t\t\tstate.parameters.push(expr.value);\n\t\t\t\treturn createParamRef(idx);\n\t\t\t}\n\n\t\tcase 'column':\n\t\t\treturn columnRef(expr.column as string, alias, schema, naming);\n\n\t\tcase 'arithmetic': {\n\t\t\tconst left = resolveCaseValue(\n\t\t\t\texpr.left,\n\t\t\t\talias,\n\t\t\t\tschema,\n\t\t\t\tnaming,\n\t\t\t\tstate,\n\t\t\t\tnestedCaseHandler,\n\t\t\t);\n\t\t\tconst right = resolveCaseValue(\n\t\t\t\texpr.right,\n\t\t\t\talias,\n\t\t\t\tschema,\n\t\t\t\tnaming,\n\t\t\t\tstate,\n\t\t\t\tnestedCaseHandler,\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tA_Expr: {\n\t\t\t\t\tkind: 'AEXPR_OP',\n\t\t\t\t\tname: [{ String: { sval: expr.operator as string } }],\n\t\t\t\t\tlexpr: left,\n\t\t\t\t\trexpr: right,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\t// biome-ignore lint/suspicious/noFallthroughSwitchClause: intentional — no nested handler → parameterize via default\n\t\tcase 'case':\n\t\t\tif (nestedCaseHandler) {\n\t\t\t\treturn nestedCaseHandler(expr);\n\t\t\t}\n\t\t// falls through\n\t\tdefault: {\n\t\t\tconst idx = ++state.paramIndex;\n\t\t\tstate.parameters.push(value);\n\t\t\treturn createParamRef(idx);\n\t\t}\n\t}\n}\n","/**\n * Custom Expression Handler\n *\n * Handles generic expression intents: customOp, customFn, ref, param, cast, literal, unary.\n * Core function: compileExpressionIntent — recursive dispatcher used by SELECT, WHERE, ORDER BY.\n */\n\nimport type {\n\tAggOrderByArg,\n\tArrayExpressionIntent,\n\tCastExpressionIntent,\n\tCustomFnExpressionIntent,\n\tCustomOpExpressionIntent,\n\tExpressionIntent,\n\tLiteralExpressionIntent,\n\tNamedArgExpressionIntent,\n\tParamExpressionIntent,\n\tRefExpressionIntent,\n\tSubqueryExpressionIntent,\n\tUnaryExpressionIntent,\n} from '@dbsp/types';\nimport type { Node } from '@pgsql/types';\nimport {\n\tbooleanConstNode,\n\tcolumnRef,\n\tfloatNode,\n\tfuncCall,\n\tintegerNode,\n\tnullConstNode,\n\tsortBy,\n\ttypeCast,\n} from '../../ast-helpers.js';\nimport { createParamRef } from '../../param-ref.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tExpressionHandler,\n\tWhereDispatcher,\n} from '../types.js';\n\n// ---------------------------------------------------------------------------\n// Deferred WHERE compiler injection\n// ---------------------------------------------------------------------------\n// custom.ts is loaded early (compile-where.ts imports it). handlers/index.ts\n// is loaded later and has a transitive dep back through custom.ts. To compile\n// CASE WHEN conditions we need createWhereDispatcher (from handlers/index.ts)\n// but cannot import it statically (circular) or via require() (ESM package).\n//\n// Solution: compile-where.ts (which imports BOTH custom.ts and handlers/index.ts)\n// calls registerWhereDispatcherFactory() once after both modules are loaded.\n// By the time any CASE expression is compiled, the factory is always set.\n// ---------------------------------------------------------------------------\nlet _whereDispatcherFactory: (() => WhereDispatcher) | undefined;\n\n/** Called by compile-where.ts after both modules are fully initialized. */\nexport function registerWhereDispatcherFactory(\n\tfactory: () => WhereDispatcher,\n): void {\n\t_whereDispatcherFactory = factory;\n}\n\nfunction _createWhereDispatcher(): WhereDispatcher {\n\tif (!_whereDispatcherFactory) {\n\t\tthrow new Error(\n\t\t\t'compileExpressionIntent (case): WHERE dispatcher not initialized. ' +\n\t\t\t\t'Ensure compile-where.ts is imported before any CASE expression is compiled.',\n\t\t);\n\t}\n\treturn _whereDispatcherFactory();\n}\n\n/**\n * Recursively compile an ExpressionIntent into a PostgreSQL AST Node.\n *\n * Handles all custom expression kinds: customOp, customFn, ref, param, cast, literal, unary.\n * This function is shared by SELECT, WHERE, and ORDER BY compilation paths.\n */\nexport function compileExpressionIntent(\n\tintent: ExpressionIntent,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): Node {\n\tconst kind = intent.kind;\n\n\tswitch (kind) {\n\t\tcase 'customOp': {\n\t\t\tconst i = intent as CustomOpExpressionIntent;\n\t\t\tconst leftNode = compileExpressionIntent(i.left, ctx, state);\n\t\t\tconst rightNode = compileExpressionIntent(i.right, ctx, state);\n\t\t\treturn {\n\t\t\t\tA_Expr: {\n\t\t\t\t\tkind: 'AEXPR_OP',\n\t\t\t\t\tname: [{ String: { sval: i.operator } }],\n\t\t\t\t\tlexpr: leftNode,\n\t\t\t\t\trexpr: rightNode,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tcase 'customFn': {\n\t\t\tconst i = intent as CustomFnExpressionIntent;\n\t\t\t// Schema-qualified: 'schema.func' → [String(schema), String(func)]\n\t\t\tconst nameParts = i.name.split('.');\n\t\t\tconst argNodes = i.args.map((arg) =>\n\t\t\t\tcompileExpressionIntent(arg, ctx, state),\n\t\t\t);\n\t\t\t// Compile aggOrderBy entries into SortBy nodes for agg_order.\n\t\t\tconst orderByNodes =\n\t\t\t\ti.aggOrderBy && i.aggOrderBy.length > 0\n\t\t\t\t\t? i.aggOrderBy.map((ob: AggOrderByArg) => {\n\t\t\t\t\t\t\tconst colNode = columnRef(\n\t\t\t\t\t\t\t\tob.field,\n\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\tctx.naming,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn sortBy(colNode, ob.direction === 'desc' ? 'DESC' : 'ASC');\n\t\t\t\t\t\t})\n\t\t\t\t\t: undefined;\n\t\t\t// Note: FILTER (WHERE ...) on customFn is applied at the compiler level\n\t\t\t// (selectCustomExpression branch in compiler.ts) to avoid circular deps.\n\t\t\treturn funcCall(nameParts, argNodes, {\n\t\t\t\t...(orderByNodes ? { orderBy: orderByNodes } : {}),\n\t\t\t});\n\t\t}\n\n\t\tcase 'ref': {\n\t\t\tconst i = intent as RefExpressionIntent;\n\t\t\t// Support 'table.column' dotted notation\n\t\t\tconst dotIdx = i.column.indexOf('.');\n\t\t\tif (dotIdx !== -1) {\n\t\t\t\tconst table = i.column.slice(0, dotIdx);\n\t\t\t\tconst col = i.column.slice(dotIdx + 1);\n\t\t\t\treturn columnRef(col, table, undefined, ctx.naming);\n\t\t\t}\n\t\t\treturn columnRef(i.column, undefined, undefined, ctx.naming);\n\t\t}\n\n\t\tcase 'param': {\n\t\t\tconst i = intent as ParamExpressionIntent;\n\t\t\tconst idx = ++state.paramIndex;\n\t\t\tstate.parameters.push(i.value);\n\t\t\treturn createParamRef(idx);\n\t\t}\n\n\t\tcase 'cast': {\n\t\t\tconst i = intent as CastExpressionIntent;\n\t\t\tconst argNode = compileExpressionIntent(i.expr, ctx, state);\n\t\t\treturn typeCast(argNode, i.typeName);\n\t\t}\n\n\t\tcase 'literal': {\n\t\t\tconst i = intent as LiteralExpressionIntent;\n\t\t\tif (i.value === null || i.value === undefined) {\n\t\t\t\treturn nullConstNode();\n\t\t\t}\n\t\t\tif (typeof i.value === 'boolean') {\n\t\t\t\treturn booleanConstNode(i.value);\n\t\t\t}\n\t\t\tif (typeof i.value === 'number') {\n\t\t\t\tif (Number.isInteger(i.value)) {\n\t\t\t\t\treturn integerNode(i.value);\n\t\t\t\t}\n\t\t\t\treturn floatNode(String(i.value));\n\t\t\t}\n\t\t\tif (typeof i.value === 'string') {\n\t\t\t\treturn {\n\t\t\t\t\tA_Const: { sval: { sval: i.value } },\n\t\t\t\t};\n\t\t\t}\n\t\t\t// Fallback: convert to string literal\n\t\t\treturn {\n\t\t\t\tA_Const: { sval: { sval: String(i.value) } },\n\t\t\t};\n\t\t}\n\n\t\tcase 'unary': {\n\t\t\tconst i = intent as UnaryExpressionIntent;\n\t\t\tconst operandNode = compileExpressionIntent(i.operand, ctx, state);\n\t\t\treturn {\n\t\t\t\tA_Expr: {\n\t\t\t\t\tkind: 'AEXPR_OP',\n\t\t\t\t\tname: [{ String: { sval: i.operator } }],\n\t\t\t\t\trexpr: operandNode,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tcase 'namedArg': {\n\t\t\tconst nae = intent as NamedArgExpressionIntent;\n\t\t\tconst argNode = compileExpressionIntent(nae.value, ctx, state);\n\t\t\t// NamedArgExpr is a valid PostgreSQL AST node but not included in @pgsql/types Node union.\n\t\t\t// The internal deparser handles it correctly. Cast through unknown is safe here.\n\t\t\treturn {\n\t\t\t\tNamedArgExpr: {\n\t\t\t\t\targ: argNode,\n\t\t\t\t\tname: nae.name,\n\t\t\t\t\targnumber: -1,\n\t\t\t\t},\n\t\t\t} as unknown as Node;\n\t\t}\n\n\t\tcase 'star':\n\t\t\t// ColumnRef with A_Star field — deparseColumnRef renders it as *\n\t\t\t// When passed to fn(), funcCall() puts it in args → count(*) etc.\n\t\t\treturn {\n\t\t\t\tColumnRef: { fields: [{ A_Star: {} }] },\n\t\t\t} as unknown as Node;\n\n\t\tcase 'array': {\n\t\t\tconst ae = intent as ArrayExpressionIntent;\n\t\t\tconst elements = ae.elements.map((el) =>\n\t\t\t\tcompileExpressionIntent(el, ctx, state),\n\t\t\t);\n\t\t\treturn { A_ArrayExpr: { elements } } as unknown as Node;\n\t\t}\n\n\t\tcase 'subquery': {\n\t\t\tconst sq = intent as SubqueryExpressionIntent;\n\t\t\tif (!ctx.compileSubquery) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"compileExpressionIntent: 'subquery' expression kind requires ctx.compileSubquery to be set. \" +\n\t\t\t\t\t\t'Use asExpr() only in .columns() context, not in standalone expressions.',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst { ast: innerAst, parameters: innerParams } = ctx.compileSubquery(\n\t\t\t\tsq.query,\n\t\t\t\tstate.paramIndex,\n\t\t\t);\n\t\t\t// Append inner parameters to outer state (shared array, appended in order)\n\t\t\tfor (const p of innerParams) {\n\t\t\t\tstate.parameters.push(p);\n\t\t\t}\n\t\t\tstate.paramIndex += innerParams.length;\n\t\t\t// Wrap the inner SelectStmt in a SubLink (scalar subquery expression)\n\t\t\treturn {\n\t\t\t\tSubLink: {\n\t\t\t\t\tsubLinkType: 'EXPR_SUBLINK',\n\t\t\t\t\tsubselect: innerAst,\n\t\t\t\t},\n\t\t\t} as unknown as Node;\n\t\t}\n\n\t\tcase 'relationColumn': {\n\t\t\t// Produced by relationColumn(relation, column, as) — ORDER BY a joined relation's column.\n\t\t\t// Alias lookup: state.aliases may be empty for expression-scoped states;\n\t\t\t// fall back to the relation name itself (which is used as the SQL JOIN alias).\n\t\t\tconst rc = intent as unknown as {\n\t\t\t\trelation: string;\n\t\t\t\tcolumn: string;\n\t\t\t\tas: string;\n\t\t\t};\n\t\t\tconst alias = state.aliases.get(rc.relation) ?? rc.relation;\n\t\t\treturn columnRef(rc.column, alias, undefined, ctx.naming);\n\t\t}\n\n\t\tcase 'case': {\n\t\t\t// CaseExpressionIntent: CASE WHEN condition THEN result [...] [ELSE default] END\n\t\t\t// createWhereDispatcher is imported at module top level. The circular dep with\n\t\t\t// handlers/index.ts is safe because ESM live bindings resolve before any function\n\t\t\t// is called (no top-level calls in either module).\n\t\t\tconst dispatch = _createWhereDispatcher();\n\n\t\t\tconst caseIntent = intent as import('@dbsp/types').CaseExpressionIntent;\n\n\t\t\tif (!caseIntent.when || caseIntent.when.length === 0) {\n\t\t\t\tthrow new Error('CASE expression requires at least one WHEN clause');\n\t\t\t}\n\n\t\t\tconst caseArgs: Node[] = caseIntent.when.map((branch) => {\n\t\t\t\t// dispatch accepts WhereIntent (via normalizeToDecision which handles `kind` field)\n\t\t\t\tconst whenNode = dispatch(\n\t\t\t\t\tbranch.condition as unknown as import('../types.js').Decision,\n\t\t\t\t\tctx,\n\t\t\t\t\tstate,\n\t\t\t\t);\n\t\t\t\tconst thenNode = compileExpressionIntent(branch.result, ctx, state);\n\t\t\t\treturn {\n\t\t\t\t\tCaseWhen: { expr: whenNode, result: thenNode },\n\t\t\t\t} as unknown as Node;\n\t\t\t});\n\n\t\t\tlet defresult: Node | undefined;\n\t\t\tif (caseIntent.else !== undefined) {\n\t\t\t\tdefresult = compileExpressionIntent(caseIntent.else, ctx, state);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tCaseExpr: {\n\t\t\t\t\targs: caseArgs,\n\t\t\t\t\t...(defresult !== undefined ? { defresult } : {}),\n\t\t\t\t},\n\t\t\t} as unknown as Node;\n\t\t}\n\n\t\tdefault: {\n\t\t\tthrow new Error(\n\t\t\t\t`compileExpressionIntent: unsupported expression kind '${kind}'`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Expression handler for custom expression intents in SELECT.\n * Dispatches customOp, customFn, ref, param, cast, unary to compileExpressionIntent.\n */\n\n/**\n * Compile a WhereIntent FILTER clause to an AST Node for use in customFn expressions.\n *\n * Uses require() for createWhereDispatcher and convertWhereCondition to avoid circular\n * dependencies (compiler.ts → custom.ts). The PlanDecision from convertWhereCondition\n * is structurally compatible with Decision for simple filter conditions.\n */\n/**\n * Compile a WhereIntent FILTER clause to an AST Node for use in customFn expressions.\n *\n * Uses direct imports (not require()) — both are safe:\n * - handlers/index.ts does not import custom.ts (no circular dep)\n * - intent-to-decisions.ts imports PlanDecision from compiler.ts as `import type` only\n * (type-only imports have no runtime circular dep in ESM)\n */\n/**\n * Compile a WhereIntent FILTER clause to an AST Node for use in customFn expressions.\n *\n * Uses direct import for convertWhereCondition (safe: intent-to-decisions.ts only has\n * `import type` from compiler.ts, no runtime circular dep).\n *\n * Uses require() for createWhereDispatcher to avoid circular initialization:\n * handlers/index.ts → where/index.ts → custom-expression.ts → custom.ts\n */\n\nexport const customExpressionHandler: ExpressionHandler = {\n\ttypes: [\n\t\t'customOp',\n\t\t'customFn',\n\t\t'ref',\n\t\t'param',\n\t\t'cast',\n\t\t'unary',\n\t\t'customExpression',\n\t],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst expressionIntent = decision.expressionIntent as ExpressionIntent;\n\t\treturn compileExpressionIntent(expressionIntent, ctx, state);\n\t},\n};\n","/**\n * Handler Types for adapter-pgsql\n *\n * Defines interfaces for WHERE, EXPRESSION, and INCLUDE handlers.\n * Each handler transforms a specific decision type into PostgreSQL AST nodes.\n */\n\nimport type { ModelIR } from '@dbsp/types';\nimport type { Node } from '@pgsql/types';\nimport type { FkColumnDerivation } from '../assert-field.js';\nimport type { NamingPlugin } from '../naming-plugin.js';\n\n// ============================================================================\n// Compiler Context (immutable, passed to all handlers)\n// ============================================================================\n\n/**\n * Immutable context passed to all handlers during compilation.\n */\nexport interface CompilerContext {\n\t/** Naming convention transformer */\n\treadonly naming: NamingPlugin;\n\t/** Schema name for table qualification (optional) */\n\treadonly schema?: string;\n\t/** Root table name for the query */\n\treadonly rootTable: string;\n\t/** Current table alias (for JOINs) */\n\treadonly currentAlias?: string;\n\t/** Maximum recursive depth (default: 100) */\n\treadonly maxRecursiveDepth: number;\n\t/** Optional callback for raw SQL audit trail */\n\treadonly onRawSQL?: (sql: string) => void;\n\t/** Default primary key column name for convention fallbacks (default: 'id') */\n\treadonly defaultPkColumnName?: string;\n\t/** Convention for deriving FK column names: (tableName, pkName) => fkColumnName */\n\treadonly deriveFkColumnName?: FkColumnDerivation;\n\t/** Alias of the outer (parent) query — used for FieldRef scope:'outer' resolution in EXISTS subqueries */\n\treadonly outerAlias?: string;\n\t/**\n\t * Optional callback to compile a QueryIntent into an AST Node (SubLink subselect).\n\t * Set by PlanCompiler when compiling selectCustomExpression — enables SubqueryExpressionIntent\n\t * to embed a fully compiled sub-SELECT into the parent SELECT column list.\n\t *\n\t * @param query - The inner QueryIntent to compile\n\t * @param paramOffset - Current outer paramIndex; inner $N are renumbered by this offset\n\t * @returns The compiled SelectStmt AST node and the inner parameters\n\t */\n\treadonly compileSubquery?: (\n\t\tquery: import('@dbsp/types').QueryIntent,\n\t\tparamOffset: number,\n\t) => { ast: Node; parameters: readonly unknown[] };\n\t/**\n\t * Optional ModelIR for type-aware parameter casting.\n\t * When provided, WHERE comparisons emit `$N::type` to eliminate\n\t * PostgreSQL type inference ambiguity for nullable columns.\n\t */\n\treadonly model?: ModelIR;\n}\n\n// ============================================================================\n// Compiler State (mutable, maintains compilation state)\n// ============================================================================\n\n/**\n * Mutable state maintained during compilation.\n */\nexport interface CompilerState {\n\t/** Collected parameters in order */\n\tparameters: unknown[];\n\t/** Current parameter index (1-based for PostgreSQL) */\n\tparamIndex: number;\n\t/** Registered CTEs for the query */\n\tctes: Map<string, Node>;\n\t/** Table aliases in use */\n\taliases: Map<string, string>;\n\t/** JOIN clauses accumulated */\n\tjoins: Node[];\n}\n\n/**\n * Creates a fresh compiler state.\n */\nexport function createCompilerState(): CompilerState {\n\treturn {\n\t\tparameters: [],\n\t\tparamIndex: 0,\n\t\tctes: new Map(),\n\t\taliases: new Map(),\n\t\tjoins: [],\n\t};\n}\n\n// ============================================================================\n// Decision Types (from PlanReport)\n// ============================================================================\n\n/**\n * Base decision interface matching core's PlanDecision structure.\n */\nexport interface Decision {\n\treadonly type: string;\n\treadonly table?: string;\n\treadonly column?: string;\n\treadonly alias?: string;\n\treadonly operator?: string;\n\treadonly value?: unknown;\n\treadonly paramIndex?: number;\n\treadonly dataType?: string;\n\treadonly direction?: 'ASC' | 'DESC';\n\treadonly nulls?: 'FIRST' | 'LAST';\n\treadonly joinType?: 'inner' | 'left';\n\treadonly sourceColumn?: string;\n\treadonly targetColumn?: string;\n\treadonly targetTable?: string;\n\treadonly function?: string;\n\treadonly args?: readonly unknown[];\n\treadonly conditions?: readonly Decision[];\n\treadonly columns?: readonly string[];\n\treadonly values?: readonly unknown[];\n\treadonly set?: readonly { column: string; value: unknown }[];\n\treadonly limit?: number | { paramIndex: number };\n\treadonly offset?: number | { paramIndex: number };\n\t// Include-specific\n\treadonly strategy?: 'join' | 'lateral' | 'json_agg' | 'cte';\n\treadonly relation?: string;\n\treadonly relationName?: string;\n\treadonly include?: readonly Decision[];\n\t// Relation metadata (for json_agg nesting)\n\treadonly relationType?: 'belongsTo' | 'hasMany' | 'hasOne';\n\treadonly foreignKey?: string;\n\treadonly parentKey?: string;\n\treadonly children?: readonly Decision[];\n\t// Window function specific\n\treadonly partition?: readonly string[];\n\treadonly orderBy?: readonly { column: string; direction?: 'ASC' | 'DESC' }[];\n\treadonly frame?: string;\n\t// Recursive specific\n\treadonly maxDepth?: number;\n\treadonly pathColumn?: string;\n\treadonly cycleDetection?: boolean;\n\t// Subquery specific\n\treadonly selectColumn?: string;\n\treadonly aggregate?: string;\n\treadonly subqueryOperator?: string;\n\t// Pseudo-column specific\n\treadonly traversal?: string;\n\treadonly traversals?: readonly {\n\t\ttraversal: string;\n\t\ttargetColumn?: string;\n\t}[];\n\treadonly isRecursive?: boolean;\n\treadonly fkColumn?: string;\n\treadonly pkColumn?: string;\n\t// Relation expansion specific\n\treadonly expandRelation?: string;\n\treadonly relationColumns?: readonly string[];\n\t// User-supplied aliases for specific relation columns (col -> alias).\n\t// Populated when selectRelationColumn decisions carry an `alias` field.\n\treadonly columnAliases?: Readonly<Record<string, string>>;\n\t// JSON-specific\n\treadonly jsonPath?: readonly string[];\n\treadonly jsonMode?: 'json' | 'text';\n\t// Pre-compiled filter from EXISTS propagation (set by compiler, read by json_agg handler)\n\treadonly _compiledFilterWhere?: import('@pgsql/types').Node;\n\t// Pre-compiled FILTER (WHERE ...) node for aggregate expressions (set by compiler)\n\treadonly filterWhere?: import('@pgsql/types').Node;\n\t// Custom expression intent for selectCustomExpression, WHERE expression, and ORDER BY expression\n\t// Also carries QueryIntent for rawExists/rawNotExists (operator discriminates the kind).\n\treadonly expressionIntent?: unknown;\n\t// LIKE escape character\n\treadonly escape?: string;\n}\n\n// ============================================================================\n// Handler Interfaces\n// ============================================================================\n\n/**\n * Handler for WHERE clause conditions.\n * Transforms condition decisions into PostgreSQL AST expressions.\n */\nexport interface WhereHandler {\n\t/** Operator(s) this handler supports */\n\treadonly operators: readonly string[];\n\n\t/**\n\t * Compile a WHERE condition to AST.\n\t * @param decision The condition decision\n\t * @param ctx Immutable compiler context\n\t * @param state Mutable compiler state\n\t * @param dispatch Callback to compile nested conditions\n\t * @returns PostgreSQL AST node for the condition\n\t */\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t\tdispatch: WhereDispatcher,\n\t): Node;\n}\n\n/**\n * Dispatcher for recursive WHERE compilation.\n */\nexport type WhereDispatcher = (\n\tdecision: Decision,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n) => Node;\n\n/**\n * Handler for SELECT expressions.\n * Transforms expression decisions into PostgreSQL AST nodes.\n */\nexport interface ExpressionHandler {\n\t/** Expression type(s) this handler supports */\n\treadonly types: readonly string[];\n\n\t/**\n\t * Compile an expression to AST.\n\t * @param decision The expression decision\n\t * @param ctx Immutable compiler context\n\t * @param state Mutable compiler state\n\t * @returns PostgreSQL AST node for the expression\n\t */\n\tcompile(decision: Decision, ctx: CompilerContext, state: CompilerState): Node;\n}\n\n/**\n * Handler for include/relation strategies.\n * Transforms include decisions into PostgreSQL constructs (JOIN, LATERAL, json_agg, CTE).\n */\nexport interface IncludeHandler {\n\t/** Strategy this handler implements */\n\treadonly strategy: 'join' | 'lateral' | 'json_agg' | 'cte';\n\n\t/**\n\t * Compile an include to AST.\n\t * @param decision The include decision\n\t * @param ctx Immutable compiler context\n\t * @param state Mutable compiler state\n\t * @returns Object with modifications to apply\n\t */\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): IncludeResult;\n}\n\n/**\n * Result of include compilation.\n */\nexport interface IncludeResult {\n\t/** Additional target list items (SELECT columns) */\n\ttargets?: Node[];\n\t/** JOIN to add to FROM clause */\n\tjoin?: Node;\n\t/** Additional JOINs for cascaded includes (e.g., flat deep nesting) */\n\tadditionalJoins?: Node[];\n\t/** CTE to add to WITH clause */\n\tcte?: Node;\n\t/** Subquery for LATERAL */\n\tlateral?: Node;\n}\n\n// ============================================================================\n// Operator Constants\n// ============================================================================\n\n/**\n * Standard comparison operators.\n */\nexport const COMPARISON_OPERATORS = {\n\tEQ: '=',\n\tNEQ: '!=',\n\tLT: '<',\n\tLTE: '<=',\n\tGT: '>',\n\tGTE: '>=',\n\t// Aliases\n\teq: '=',\n\tne: '!=',\n\tlt: '<',\n\tlte: '<=',\n\tgt: '>',\n\tgte: '>=',\n} as const;\n\n/**\n * Pattern matching operators.\n */\nexport const PATTERN_OPERATORS = {\n\tLIKE: 'like',\n\tILIKE: 'ilike',\n\tNOT_LIKE: 'notLike',\n\tNOT_ILIKE: 'notIlike',\n} as const;\n\n/**\n * Null check operators.\n */\nexport const NULL_OPERATORS = {\n\tIS_NULL: 'isNull',\n\tIS_NOT_NULL: 'isNotNull',\n} as const;\n\n/**\n * Collection operators.\n */\nexport const COLLECTION_OPERATORS = {\n\tIN: 'in',\n\tNOT_IN: 'notIn',\n\tANY: 'any',\n} as const;\n\n/**\n * Logical operators.\n */\nexport const LOGICAL_OPERATORS = {\n\tAND: 'and',\n\tOR: 'or',\n\tNOT: 'not',\n} as const;\n\n/**\n * All supported operators.\n */\nexport const ALL_OPERATORS = {\n\t...COMPARISON_OPERATORS,\n\t...PATTERN_OPERATORS,\n\t...NULL_OPERATORS,\n\t...COLLECTION_OPERATORS,\n\t...LOGICAL_OPERATORS,\n} as const;\n\n// ============================================================================\n// Helper Types (eliminates unsafe `as {}` casts)\n// ============================================================================\n\n/**\n * SQL expression object returned by SqlDefault utility.\n */\nexport interface SqlExpression {\n\treadonly sql: string;\n}\n\n/**\n * Range value for BETWEEN operations or range types.\n */\nexport interface RangeValue {\n\treadonly lower?: unknown;\n\treadonly upper?: unknown;\n}\n\n/**\n * Parameter reference with pre-assigned index.\n */\nexport interface ParamRef {\n\treadonly paramIndex: number;\n\treadonly value?: unknown;\n}\n\n/**\n * Window specification for window functions.\n */\nexport interface WindowOver {\n\treadonly partitionBy?: readonly string[];\n\treadonly orderBy?: readonly { field: string; direction?: 'asc' | 'desc' }[];\n}\n\n/**\n * Select options with field specification.\n */\nexport interface SelectWithFields {\n\treadonly fields?: readonly string[];\n}\n\n/**\n * PostgreSQL AST ResTarget node shape.\n */\nexport interface ResTargetNode {\n\treadonly ResTarget?: {\n\t\treadonly val: Node;\n\t\treadonly name?: string;\n\t};\n}\n\n/**\n * PostgreSQL AST SelectStmt node shape.\n */\nexport interface SelectStmtNode {\n\treadonly SelectStmt?: Record<string, unknown>;\n}\n\n/**\n * PostgreSQL AST JoinExpr node shape.\n */\nexport interface JoinExprNode {\n\treadonly JoinExpr?: Record<string, unknown>;\n}\n\n/**\n * PostgreSQL AST InsertStmt node shape.\n */\nexport interface InsertStmtNode {\n\treadonly InsertStmt: Record<string, unknown>;\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Type guard for SqlExpression.\n */\nexport function isSqlExpression(value: unknown): value is SqlExpression {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'sql' in value &&\n\t\ttypeof (value as Record<string, unknown>).sql === 'string'\n\t);\n}\n\n/**\n * Type guard for RangeValue.\n */\nexport function isRangeValue(value: unknown): value is RangeValue {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t('lower' in value || 'upper' in value)\n\t);\n}\n\n/**\n * Type guard for ParamRef.\n */\nexport function isParamRef(value: unknown): value is ParamRef {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'paramIndex' in value &&\n\t\ttypeof (value as Record<string, unknown>).paramIndex === 'number'\n\t);\n}\n\n/**\n * Type guard for SelectWithFields.\n */\nexport function isSelectWithFields(value: unknown): value is SelectWithFields {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'fields' in value &&\n\t\t(Array.isArray((value as Record<string, unknown>).fields) ||\n\t\t\t(value as Record<string, unknown>).fields === undefined)\n\t);\n}\n","/**\n * Pure-TypeScript SQL expression parser.\n *\n * Parses a raw SQL fragment (not a full statement) into a `@pgsql/types`\n * compatible `Node` object that can be placed into an AST tree and serialised\n * by `deparseSync` from `pgsql-deparser`.\n *\n * The node shapes produced here are identical to those produced by\n * `pgsql-parser`'s `parseSync` for the same fragment — verified by the\n * comparison tests in `raw-expression-parser.test.ts`.\n *\n * Supported constructs:\n * - Integer literals: `1`, `42`\n * - String literals: `'text'`\n * - Identifiers / column refs: `count`, `excluded.count`\n * - Function calls: `now()`, `gen_random_uuid()`, `COALESCE(a, b)`\n * - Arithmetic (+ - * /): `excluded.count + 1`, `a + b * c`\n * - Type casts: `a::integer`, `val::text`\n * - Parenthesised expressions: `(a + b) * c`\n *\n * @module\n */\n\nimport type { Node } from '@pgsql/types';\n\n// ---------------------------------------------------------------------------\n// Tokeniser\n// ---------------------------------------------------------------------------\n\ntype TokenKind =\n\t| 'INT'\n\t| 'FLOAT'\n\t| 'STRING'\n\t| 'IDENT'\n\t| 'OP'\n\t| 'LPAREN'\n\t| 'RPAREN'\n\t| 'COMMA'\n\t| 'DOT'\n\t| 'CAST'\n\t| 'EOF';\n\ninterface Token {\n\tkind: TokenKind;\n\tvalue: string;\n}\n\n/**\n * Note: Scientific notation (e.g., 3.14e5, 2.5E-3) is not supported.\n * The parser handles simple decimal floats only (e.g., 3.14, 0.5).\n * Scientific notation is rare in SQL expression fragments (sql() escape hatch).\n */\nfunction tokenise(input: string): Token[] {\n\tconst tokens: Token[] = [];\n\tlet i = 0;\n\tconst src = input.trim();\n\n\twhile (i < src.length) {\n\t\t// src[i] is safe here because i < src.length is the loop condition\n\t\tconst ch = src[i]!;\n\n\t\t// Whitespace\n\t\tif (/\\s/.test(ch)) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Integer or float literal\n\t\tif (/[0-9]/.test(ch)) {\n\t\t\tlet num = '';\n\t\t\twhile (i < src.length && /[0-9]/.test(src[i]!)) {\n\t\t\t\tnum += src[i++]!;\n\t\t\t}\n\t\t\t// Check for decimal fraction → float\n\t\t\tif (src[i] === '.' && i + 1 < src.length && /[0-9]/.test(src[i + 1]!)) {\n\t\t\t\tnum += src[i++]!; // consume '.'\n\t\t\t\twhile (i < src.length && /[0-9]/.test(src[i]!)) {\n\t\t\t\t\tnum += src[i++]!;\n\t\t\t\t}\n\t\t\t\ttokens.push({ kind: 'FLOAT', value: num });\n\t\t\t} else {\n\t\t\t\ttokens.push({ kind: 'INT', value: num });\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\t// String literal (single-quoted)\n\t\tif (ch === \"'\") {\n\t\t\tlet str = '';\n\t\t\ti++; // skip opening quote\n\t\t\twhile (i < src.length) {\n\t\t\t\tif (src[i]! === \"'\" && src[i + 1] === \"'\") {\n\t\t\t\t\t// Escaped single quote\n\t\t\t\t\tstr += \"'\";\n\t\t\t\t\ti += 2;\n\t\t\t\t} else if (src[i]! === \"'\") {\n\t\t\t\t\ti++; // skip closing quote\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tstr += src[i++]!;\n\t\t\t\t}\n\t\t\t}\n\t\t\ttokens.push({ kind: 'STRING', value: str });\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Identifier or keyword\n\t\tif (/[a-zA-Z_]/.test(ch)) {\n\t\t\tlet ident = '';\n\t\t\twhile (i < src.length && /[a-zA-Z0-9_]/.test(src[i]!)) {\n\t\t\t\tident += src[i++]!;\n\t\t\t}\n\t\t\ttokens.push({ kind: 'IDENT', value: ident });\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Double-colon cast operator (must come before single colon if ever added)\n\t\tif (ch === ':' && src[i + 1] === ':') {\n\t\t\ttokens.push({ kind: 'CAST', value: '::' });\n\t\t\ti += 2;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Arithmetic operators\n\t\tif (['+', '-', '*', '/'].includes(ch)) {\n\t\t\ttokens.push({ kind: 'OP', value: ch });\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (ch === '(') {\n\t\t\ttokens.push({ kind: 'LPAREN', value: '(' });\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (ch === ')') {\n\t\t\ttokens.push({ kind: 'RPAREN', value: ')' });\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (ch === ',') {\n\t\t\ttokens.push({ kind: 'COMMA', value: ',' });\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (ch === '.') {\n\t\t\ttokens.push({ kind: 'DOT', value: '.' });\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`parseExpression: unexpected character '${ch}' at position ${i} in: ${input}`,\n\t\t);\n\t}\n\n\ttokens.push({ kind: 'EOF', value: '' });\n\treturn tokens;\n}\n\n// ---------------------------------------------------------------------------\n// Parser (recursive descent)\n// ---------------------------------------------------------------------------\n\nclass Parser {\n\tprivate pos = 0;\n\n\tconstructor(private readonly tokens: Token[]) {}\n\n\tprivate peek(): Token {\n\t\t// pos is always in bounds: tokenise() guarantees a trailing EOF token\n\t\treturn this.tokens[this.pos]!;\n\t}\n\n\tprivate consume(): Token {\n\t\t// pos is always in bounds: tokenise() guarantees a trailing EOF token\n\t\tconst tok = this.tokens[this.pos]!;\n\t\tthis.pos++;\n\t\treturn tok;\n\t}\n\n\tprivate expect(kind: TokenKind): Token {\n\t\tconst tok = this.peek();\n\t\tif (tok.kind !== kind) {\n\t\t\tthrow new Error(\n\t\t\t\t`parseExpression: expected ${kind}, got ${tok.kind} ('${tok.value}')`,\n\t\t\t);\n\t\t}\n\t\treturn this.consume();\n\t}\n\n\t// expr → additive (:: type)*\n\tparseExpr(): Node {\n\t\tlet node = this.parseAdditive();\n\n\t\twhile (this.peek().kind === 'CAST') {\n\t\t\tthis.consume(); // ::\n\t\t\tconst typeName = this.parseTypeName();\n\t\t\tnode = {\n\t\t\t\tTypeCast: {\n\t\t\t\t\targ: node,\n\t\t\t\t\ttypeName,\n\t\t\t\t},\n\t\t\t} as unknown as Node;\n\t\t}\n\n\t\treturn node;\n\t}\n\n\t// additive → multiplicative (('+' | '-') multiplicative)*\n\tprivate parseAdditive(): Node {\n\t\tlet left = this.parseMultiplicative();\n\n\t\twhile (\n\t\t\tthis.peek().kind === 'OP' &&\n\t\t\t(this.peek().value === '+' || this.peek().value === '-')\n\t\t) {\n\t\t\tconst op = this.consume().value;\n\t\t\tconst right = this.parseMultiplicative();\n\t\t\tleft = buildAExpr(op, left, right);\n\t\t}\n\n\t\treturn left;\n\t}\n\n\t// multiplicative → unary (('*' | '/') unary)*\n\tprivate parseMultiplicative(): Node {\n\t\tlet left = this.parseUnary();\n\n\t\twhile (\n\t\t\tthis.peek().kind === 'OP' &&\n\t\t\t(this.peek().value === '*' || this.peek().value === '/')\n\t\t) {\n\t\t\tconst op = this.consume().value;\n\t\t\tconst right = this.parseUnary();\n\t\t\tleft = buildAExpr(op, left, right);\n\t\t}\n\n\t\treturn left;\n\t}\n\n\t// unary → ('-')? primary\n\tprivate parseUnary(): Node {\n\t\tif (this.peek().kind === 'OP' && this.peek().value === '-') {\n\t\t\tthis.consume();\n\t\t\tconst operand = this.parsePrimary();\n\t\t\t// Unary minus: represented as A_Expr with no lexpr\n\t\t\treturn {\n\t\t\t\tA_Expr: {\n\t\t\t\t\tkind: 'AEXPR_OP',\n\t\t\t\t\tname: [{ String: { sval: '-' } }],\n\t\t\t\t\trexpr: operand,\n\t\t\t\t},\n\t\t\t} as unknown as Node;\n\t\t}\n\t\treturn this.parsePrimary();\n\t}\n\n\t// primary → INT | STRING | IDENT(...) | IDENT.IDENT | (expr) | COALESCE(...)\n\tprivate parsePrimary(): Node {\n\t\tconst tok = this.peek();\n\n\t\tif (tok.kind === 'INT') {\n\t\t\tthis.consume();\n\t\t\treturn {\n\t\t\t\tA_Const: {\n\t\t\t\t\tival: { ival: parseInt(tok.value, 10) },\n\t\t\t\t},\n\t\t\t} as unknown as Node;\n\t\t}\n\n\t\tif (tok.kind === 'FLOAT') {\n\t\t\tthis.consume();\n\t\t\treturn {\n\t\t\t\tA_Const: {\n\t\t\t\t\tfval: { fval: tok.value },\n\t\t\t\t},\n\t\t\t} as unknown as Node;\n\t\t}\n\n\t\tif (tok.kind === 'STRING') {\n\t\t\tthis.consume();\n\t\t\treturn {\n\t\t\t\tA_Const: {\n\t\t\t\t\tsval: { sval: tok.value },\n\t\t\t\t},\n\t\t\t} as unknown as Node;\n\t\t}\n\n\t\tif (tok.kind === 'LPAREN') {\n\t\t\tthis.consume();\n\t\t\tconst inner = this.parseExpr();\n\t\t\tthis.expect('RPAREN');\n\t\t\treturn inner;\n\t\t}\n\n\t\tif (tok.kind === 'IDENT') {\n\t\t\treturn this.parseIdentOrCall();\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`parseExpression: unexpected token ${tok.kind} ('${tok.value}')`,\n\t\t);\n\t}\n\n\t/**\n\t * Parse an identifier, possibly followed by:\n\t * - `.ident` (qualified column ref)\n\t * - `(args)` (function call)\n\t *\n\t * COALESCE is a special case — PostgreSQL parses it as CoalesceExpr, not FuncCall.\n\t */\n\tprivate parseIdentOrCall(): Node {\n\t\tconst ident = this.consume(); // first IDENT\n\n\t\t// Function call: IDENT(...)\n\t\tif (this.peek().kind === 'LPAREN') {\n\t\t\tthis.consume(); // (\n\t\t\tconst args = this.parseArgList();\n\t\t\tthis.expect('RPAREN');\n\n\t\t\t// Special built-in functions that PostgreSQL parses differently\n\t\t\tconst upper = ident.value.toUpperCase();\n\n\t\t\tif (upper === 'COALESCE') {\n\t\t\t\treturn {\n\t\t\t\t\tCoalesceExpr: {\n\t\t\t\t\t\targs,\n\t\t\t\t\t},\n\t\t\t\t} as unknown as Node;\n\t\t\t}\n\n\t\t\tif (upper === 'NULLIF') {\n\t\t\t\t// NullIfExpr takes exactly 2 args\n\t\t\t\treturn {\n\t\t\t\t\tNullIfExpr: {\n\t\t\t\t\t\targs,\n\t\t\t\t\t},\n\t\t\t\t} as unknown as Node;\n\t\t\t}\n\n\t\t\t// Regular function call\n\t\t\treturn {\n\t\t\t\tFuncCall: {\n\t\t\t\t\tfuncname: [{ String: { sval: ident.value.toLowerCase() } }],\n\t\t\t\t\targs: args.length > 0 ? args : undefined,\n\t\t\t\t\tfuncformat: 'COERCE_EXPLICIT_CALL',\n\t\t\t\t},\n\t\t\t} as unknown as Node;\n\t\t}\n\n\t\t// Qualified: IDENT.IDENT\n\t\tif (this.peek().kind === 'DOT') {\n\t\t\tthis.consume(); // .\n\t\t\tconst field = this.expect('IDENT');\n\t\t\treturn {\n\t\t\t\tColumnRef: {\n\t\t\t\t\tfields: [\n\t\t\t\t\t\t{ String: { sval: ident.value } },\n\t\t\t\t\t\t{ String: { sval: field.value } },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t} as unknown as Node;\n\t\t}\n\n\t\t// Plain identifier → ColumnRef with single field\n\t\treturn {\n\t\t\tColumnRef: {\n\t\t\t\tfields: [{ String: { sval: ident.value } }],\n\t\t\t},\n\t\t} as unknown as Node;\n\t}\n\n\tprivate parseArgList(): Node[] {\n\t\tconst args: Node[] = [];\n\t\tif (this.peek().kind === 'RPAREN') {\n\t\t\treturn args;\n\t\t}\n\t\targs.push(this.parseExpr());\n\t\twhile (this.peek().kind === 'COMMA') {\n\t\t\tthis.consume();\n\t\t\targs.push(this.parseExpr());\n\t\t}\n\t\treturn args;\n\t}\n\n\t/**\n\t * Parse a type name after `::`.\n\t * Handles simple names like `integer`, `text`, `uuid`, `bigint`, etc.\n\t * Maps to PostgreSQL's pg_catalog qualified names to match parseSync output.\n\t */\n\tprivate parseTypeName(): {\n\t\tnames: Array<{ String: { sval: string } }>;\n\t\ttypemod: number;\n\t} {\n\t\tconst ident = this.expect('IDENT');\n\t\tconst lower = ident.value.toLowerCase();\n\n\t\t// Map SQL type aliases to pg_catalog qualified names (matches parseSync output)\n\t\tconst pgCatalogTypes: Record<string, string> = {\n\t\t\tint: 'int4',\n\t\t\tinteger: 'int4',\n\t\t\tint4: 'int4',\n\t\t\tint2: 'int2',\n\t\t\tsmallint: 'int2',\n\t\t\tint8: 'int8',\n\t\t\tbigint: 'int8',\n\t\t\tfloat4: 'float4',\n\t\t\treal: 'float4',\n\t\t\tfloat8: 'float8',\n\t\t\t'double precision': 'float8',\n\t\t\tbool: 'bool',\n\t\t\tboolean: 'bool',\n\t\t\ttext: 'text',\n\t\t\tvarchar: 'varchar',\n\t\t\tbpchar: 'bpchar',\n\t\t\tchar: 'bpchar',\n\t\t\tbytea: 'bytea',\n\t\t\tdate: 'date',\n\t\t\ttime: 'time',\n\t\t\ttimetz: 'timetz',\n\t\t\ttimestamp: 'timestamp',\n\t\t\ttimestamptz: 'timestamptz',\n\t\t\tinterval: 'interval',\n\t\t\tnumeric: 'numeric',\n\t\t\tdecimal: 'numeric',\n\t\t\tuuid: 'uuid',\n\t\t\tjson: 'json',\n\t\t\tjsonb: 'jsonb',\n\t\t\toid: 'oid',\n\t\t\tname: 'name',\n\t\t};\n\n\t\tconst pgName = pgCatalogTypes[lower];\n\t\tif (pgName) {\n\t\t\treturn {\n\t\t\t\tnames: [\n\t\t\t\t\t{ String: { sval: 'pg_catalog' } },\n\t\t\t\t\t{ String: { sval: pgName } },\n\t\t\t\t],\n\t\t\t\ttypemod: -1,\n\t\t\t};\n\t\t}\n\n\t\t// Unknown type: pass through as-is (not pg_catalog qualified)\n\t\treturn {\n\t\t\tnames: [{ String: { sval: lower } }],\n\t\t\ttypemod: -1,\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction buildAExpr(op: string, left: Node, right: Node): Node {\n\treturn {\n\t\tA_Expr: {\n\t\t\tkind: 'AEXPR_OP',\n\t\t\tname: [{ String: { sval: op } }],\n\t\t\tlexpr: left,\n\t\t\trexpr: right,\n\t\t},\n\t} as unknown as Node;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Parse a raw SQL expression fragment into a `@pgsql/types` `Node`.\n *\n * The returned node is structurally identical to what `pgsql-parser`'s\n * `parseSync` would produce for the same fragment wrapped in `SELECT <fragment>`.\n * It can be embedded in a larger AST tree and serialised by `pgsql-deparser`.\n *\n * @param sqlFragment - A SQL expression fragment, e.g. `now()`, `excluded.count + 1`\n * @returns A pg AST `Node` ready for deparsing\n * @throws Error if the fragment cannot be parsed\n *\n * @example\n * ```ts\n * parseExpression('now()')\n * // → { FuncCall: { funcname: [{ String: { sval: 'now' } }], funcformat: 'COERCE_EXPLICIT_CALL' } }\n *\n * parseExpression('excluded.count + 1')\n * // → { A_Expr: { kind: 'AEXPR_OP', name: [{ String: { sval: '+' } }], lexpr: ColumnRef, rexpr: A_Const } }\n * ```\n */\nexport function parseExpression(sqlFragment: string): Node {\n\tconst trimmed = sqlFragment.trim();\n\tif (!trimmed) {\n\t\tthrow new Error('parseExpression: empty SQL fragment');\n\t}\n\n\tconst tokens = tokenise(trimmed);\n\tconst parser = new Parser(tokens);\n\tconst node = parser.parseExpr();\n\n\t// biome-ignore lint/complexity/useLiteralKeys: accessing private members via bracket notation intentionally\n\tif (parser['peek']().kind !== 'EOF') {\n\t\tconst remaining = tokens\n\t\t\t// biome-ignore lint/complexity/useLiteralKeys: accessing private members via bracket notation intentionally\n\t\t\t.slice(parser['pos'])\n\t\t\t.map((t) => t.value)\n\t\t\t.join(' ');\n\t\tthrow new Error(\n\t\t\t`parseExpression: unexpected trailing tokens '${remaining}' in: ${sqlFragment}`,\n\t\t);\n\t}\n\n\treturn node;\n}\n","/**\n * Shared compiler utilities for unnest-based batch operations.\n *\n * Used by batch INSERT (Block 2), batch UPDATE (Block 3), batch UPSERT (Block 4),\n * and CTE unnest builder (Block 5).\n */\n\nimport { InvalidOperationError } from '@dbsp/core';\nimport type { Node } from '@pgsql/types';\nimport { parseExpression } from './raw-expression-parser.js';\n\n// ============================================================================\n// Type Inference\n// ============================================================================\n\n/**\n * Infer PostgreSQL array type for unnest parameter casting.\n * Strategy: schema-driven (columnTypes map) first, runtime fallback if absent.\n *\n * Only produces whitelisted PG types per INV-05:\n * int4[], int8[], float8[], text[], bool[], jsonb[], uuid[], date[], timestamptz[]\n * or the raw dbType value for DX-050 custom types.\n */\nexport function inferPgArrayType(\n\tcolumnName: string,\n\tcolumnTypes?: Record<string, string>,\n\tsampleValue?: unknown,\n): string {\n\t// 1. Schema-driven: use column type from ModelIR (via columnTypes map)\n\tif (columnTypes?.[columnName]) {\n\t\tconst pgBase = mapToPgBaseType(columnTypes[columnName]);\n\t\treturn `${pgBase}[]`;\n\t}\n\n\t// 2. Runtime fallback: infer from sample value type\n\tif (sampleValue !== null && sampleValue !== undefined) {\n\t\tif (typeof sampleValue === 'bigint') return 'int8[]';\n\t\tif (typeof sampleValue === 'number') {\n\t\t\treturn Number.isInteger(sampleValue) ? 'int4[]' : 'float8[]';\n\t\t}\n\t\tif (typeof sampleValue === 'string') return 'text[]';\n\t\tif (typeof sampleValue === 'boolean') return 'bool[]';\n\t\tif (typeof sampleValue === 'object') return 'jsonb[]';\n\t}\n\n\t// 3. Default fallback (ERR-03: unknown type → text[])\n\treturn 'text[]';\n}\n\n/**\n * Map a type string to the canonical PostgreSQL base type name used in array casts.\n * Accepts both PostgreSQL native types (as produced by type-mapping.ts) and\n * ColumnType values from ModelIR (e.g. 'integer', 'string', 'datetime').\n *\n * E.g. \"INTEGER\" → \"int4\", \"VARCHAR(255)\" → \"text\", \"BOOLEAN\" → \"bool\",\n * \"string\" → \"text\", \"datetime\" → \"timestamptz\", \"number\" → \"float8\"\n */\nfunction mapToPgBaseType(pgType: string): string {\n\t// Strip length/precision qualifiers like VARCHAR(255), NUMERIC(10,2)\n\tconst normalized = pgType\n\t\t.toUpperCase()\n\t\t.replace(/\\(.*\\)/, '')\n\t\t.trim();\n\tswitch (normalized) {\n\t\t// ColumnType aliases (lowercase ColumnType values from ModelIR)\n\t\tcase 'STRING':\n\t\t\treturn 'text';\n\t\tcase 'NUMBER':\n\t\t\treturn 'float8';\n\t\tcase 'DATETIME':\n\t\t\treturn 'timestamptz';\n\t\tcase 'TIME':\n\t\t\treturn 'time';\n\t\t// PostgreSQL native types\n\t\tcase 'INTEGER':\n\t\tcase 'INT':\n\t\tcase 'INT4':\n\t\tcase 'SERIAL':\n\t\t\treturn 'int4';\n\t\tcase 'BIGINT':\n\t\tcase 'INT8':\n\t\tcase 'BIGSERIAL':\n\t\t\treturn 'int8';\n\t\tcase 'SMALLINT':\n\t\tcase 'INT2':\n\t\t\treturn 'int2';\n\t\tcase 'REAL':\n\t\tcase 'FLOAT4':\n\t\t\treturn 'float4';\n\t\tcase 'DOUBLE PRECISION':\n\t\tcase 'FLOAT8':\n\t\tcase 'FLOAT':\n\t\tcase 'NUMERIC':\n\t\tcase 'DECIMAL':\n\t\t\treturn 'float8';\n\t\tcase 'TEXT':\n\t\tcase 'VARCHAR':\n\t\tcase 'CHAR':\n\t\tcase 'CHARACTER VARYING':\n\t\t\treturn 'text';\n\t\tcase 'BOOLEAN':\n\t\tcase 'BOOL':\n\t\t\treturn 'bool';\n\t\tcase 'JSON':\n\t\tcase 'JSONB':\n\t\t\treturn 'jsonb';\n\t\tcase 'UUID':\n\t\t\treturn 'uuid';\n\t\tcase 'TIMESTAMP':\n\t\tcase 'TIMESTAMPTZ':\n\t\tcase 'TIMESTAMP WITH TIME ZONE':\n\t\t\treturn 'timestamptz';\n\t\tcase 'DATE':\n\t\t\treturn 'date';\n\t\tdefault:\n\t\t\t// Pass through for custom types (DX-050 dbType) — lowercase for consistency\n\t\t\treturn pgType.toLowerCase();\n\t}\n}\n\n// ============================================================================\n// Array Suffix Helpers\n// ============================================================================\n\n/**\n * Strip the trailing `[]` suffix from a PostgreSQL array type string.\n *\n * @example\n * stripArraySuffix('int4[]') // → 'int4'\n * stripArraySuffix('text[]') // → 'text'\n * stripArraySuffix('text') // → 'text' (no-op if no suffix)\n */\nexport function stripArraySuffix(pgArrayType: string): string {\n\treturn pgArrayType.endsWith('[]') ? pgArrayType.slice(0, -2) : pgArrayType;\n}\n\n// ============================================================================\n// ModelIR Type Mapping\n// ============================================================================\n\n/**\n * Map a ModelIR column type string to a PostgreSQL base type name used in\n * array casts (without the `[]` suffix).\n *\n * Returns `undefined` when the type is not in the whitelist — callers should\n * fall back to runtime inference in that case.\n *\n * @example\n * mapModelIRTypeToPgBase('integer') // → 'int4'\n * mapModelIRTypeToPgBase('timestamp') // → 'timestamptz'\n * mapModelIRTypeToPgBase('date') // → 'date'\n */\nexport function mapModelIRTypeToPgBase(dataType: string): string | undefined {\n\tconst t = dataType.toLowerCase();\n\t// Integer types\n\tif (t === 'integer' || t === 'int' || t === 'serial' || t === 'bigserial')\n\t\treturn 'int4';\n\tif (t === 'bigint') return 'int8';\n\t// Float types\n\tif (\n\t\tt === 'decimal' ||\n\t\tt === 'float' ||\n\t\tt === 'double' ||\n\t\tt === 'real' ||\n\t\tt === 'numeric'\n\t)\n\t\treturn 'float8';\n\t// Text types\n\tif (t === 'text' || t === 'string' || t === 'varchar' || t === 'char')\n\t\treturn 'text';\n\t// Boolean\n\tif (t === 'boolean' || t === 'bool') return 'bool';\n\t// JSON\n\tif (t === 'json' || t === 'jsonb') return 'jsonb';\n\t// UUID\n\tif (t === 'uuid') return 'uuid';\n\t// Date/time — map to native PG types\n\tif (t === 'timestamp' || t === 'timestamptz' || t === 'datetime')\n\t\treturn 'timestamptz';\n\tif (t === 'date') return 'date';\n\t// Not in whitelist — caller falls back to runtime inference\n\treturn undefined;\n}\n\n// ============================================================================\n// Array Transposition\n// ============================================================================\n\n/**\n * Transpose row-major values to column-major arrays for unnest.\n *\n * Input (rows): [[1, 'a'], [2, 'b']]\n * Output (cols): [[1, 2], ['a', 'b']]\n */\nexport function transposeToColumnArrays(\n\tcolumns: string[],\n\tvalues: unknown[][],\n): unknown[][] {\n\treturn columns.map((_, colIdx) => values.map((row) => row[colIdx]));\n}\n\n// ============================================================================\n// Validation\n// ============================================================================\n\n/**\n * Validate that all rows have the same number of values as columns.\n * Throws InvalidOperationError on mismatch (INV-02 / ERR-02).\n *\n * PostgreSQL's unnest silently NULL-pads shorter arrays — we must prevent this.\n */\nexport function validateBatchCardinality(\n\tcolumns: string[],\n\tvalues: unknown[][],\n): void {\n\tfor (let i = 0; i < values.length; i++) {\n\t\tconst row = values[i];\n\t\tif (row === undefined || row.length !== columns.length) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'insert',\n\t\t\t\t`Array length mismatch at row ${i}: expected ${columns.length} columns, got ${row?.length ?? 0}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n// ============================================================================\n// Raw SQL Expression Parsing\n// ============================================================================\n\n/**\n * Parse a raw SQL fragment into a pg AST expression node.\n *\n * Wraps the fragment in `SELECT <fragment>` to obtain a valid statement,\n * then extracts the expression from the first target-list entry.\n * Used by mutation compilers to inject raw SQL into SET clauses.\n *\n * @throws Error if the fragment cannot be parsed as a valid SQL expression.\n * @internal\n */\nexport function parseRawExpression(sqlFragment: string): Node {\n\ttry {\n\t\treturn parseExpression(sqlFragment);\n\t} catch {\n\t\tthrow new Error(\n\t\t\t`sql(): cannot parse raw SQL fragment as expression: ${sqlFragment}`,\n\t\t);\n\t}\n}\n","/**\n * Identifier Validation for adapter-pgsql\n *\n * Security layer to prevent SQL injection via identifiers.\n * All table names, column names, schema names, and aliases MUST pass validation.\n */\n\n// ============================================================================\n// SQL Reserved Keywords (PostgreSQL)\n// ============================================================================\n\n/**\n * PostgreSQL reserved keywords that cannot be used as unquoted identifiers.\n * This is a subset of the most common ones - full list is much larger.\n * We allow these but they must be quoted.\n */\nconst SQL_RESERVED_KEYWORDS = new Set([\n\t'all',\n\t'analyse',\n\t'analyze',\n\t'and',\n\t'any',\n\t'array',\n\t'as',\n\t'asc',\n\t'asymmetric',\n\t'authorization',\n\t'binary',\n\t'both',\n\t'case',\n\t'cast',\n\t'check',\n\t'collate',\n\t'collation',\n\t'column',\n\t'concurrently',\n\t'constraint',\n\t'create',\n\t'cross',\n\t'current_catalog',\n\t'current_date',\n\t'current_role',\n\t'current_schema',\n\t'current_time',\n\t'current_timestamp',\n\t'current_user',\n\t'default',\n\t'deferrable',\n\t'desc',\n\t'distinct',\n\t'do',\n\t'else',\n\t'end',\n\t'except',\n\t'false',\n\t'fetch',\n\t'for',\n\t'foreign',\n\t'freeze',\n\t'from',\n\t'full',\n\t'grant',\n\t'group',\n\t'having',\n\t'ilike',\n\t'in',\n\t'initially',\n\t'inner',\n\t'intersect',\n\t'into',\n\t'is',\n\t'isnull',\n\t'join',\n\t'lateral',\n\t'leading',\n\t'left',\n\t'like',\n\t'limit',\n\t'localtime',\n\t'localtimestamp',\n\t'natural',\n\t'not',\n\t'notnull',\n\t'null',\n\t'offset',\n\t'on',\n\t'only',\n\t'or',\n\t'order',\n\t'outer',\n\t'overlaps',\n\t'placing',\n\t'primary',\n\t'references',\n\t'returning',\n\t'right',\n\t'select',\n\t'session_user',\n\t'similar',\n\t'some',\n\t'symmetric',\n\t'table',\n\t'timestamp',\n\t'tablesample',\n\t'then',\n\t'to',\n\t'trailing',\n\t'true',\n\t'union',\n\t'unique',\n\t'user',\n\t'using',\n\t'variadic',\n\t'verbose',\n\t'when',\n\t'where',\n\t'window',\n\t'with',\n]);\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\n/**\n * Error thrown when an identifier fails validation.\n */\nexport class InvalidIdentifierError extends Error {\n\tconstructor(\n\t\tpublic readonly identifier: string,\n\t\tpublic readonly identifierType: string,\n\t\tpublic readonly reason: string,\n\t) {\n\t\tsuper(`Invalid ${identifierType} identifier \"${identifier}\": ${reason}`);\n\t\tthis.name = 'InvalidIdentifierError';\n\t}\n}\n\n// ============================================================================\n// Validation Functions\n// ============================================================================\n\n// ────────────────────────────────────────────────────────────────────\n// NAMEDATALEN and character-length bookkeeping\n//\n// PostgreSQL caps identifier/role/collation names at NAMEDATALEN-1 bytes\n// (63 bytes in the default build). Two length-check styles coexist in\n// this file for historical reasons:\n//\n// • `validateIdentifier()` uses `name.length > 63` (UTF-16 code units\n// as JavaScript counts them → effectively character count).\n// • `quoteRoleName()` / `validateCollationName()` use\n// `Buffer.byteLength(name, 'utf8') > 63` (actual byte count).\n//\n// Why the two styles coexist:\n// • `validateIdentifier` and `validateCollationName` sit *after* an\n// ASCII-only allowlist regex that rejects any multi-byte character,\n// so every accepted name has `.length === Buffer.byteLength(...)`\n// and the char-count form is equivalent to a byte-count form.\n// • `quoteRoleName` deliberately does NOT gate on an ASCII allowlist\n// (role names like `\"utilisateur\"` are legitimate); it rejects only\n// `\"`, NUL, and control chars, then counts *bytes* because role\n// names can contain multi-byte UTF-8 and PostgreSQL truncates at\n// the byte level (strlen semantics).\n// The asymmetry is intentional and safe. Do not collapse either style\n// without also widening/narrowing the upstream input-validation rules.\n// ────────────────────────────────────────────────────────────────────\n\n/**\n * Validate that a string is a safe SQL identifier.\n *\n * Rules:\n * 1. Must not be empty\n * 2. Must not exceed 63 characters (PostgreSQL limit)\n * 3. Must start with letter or underscore\n * 4. Must contain only alphanumeric, underscore, or dollar sign\n * 5. Must not contain null bytes or control characters\n * 6. Reserved keywords are allowed (will be quoted)\n *\n * @param value The identifier to validate\n * @param type Type of identifier (for error messages): 'table', 'column', 'schema', 'alias'\n * @throws InvalidIdentifierError if validation fails\n */\nexport function validateIdentifier(\n\tvalue: string,\n\ttype: 'table' | 'column' | 'schema' | 'alias',\n): void {\n\t// Rule 1: Not empty\n\tif (!value || value.length === 0) {\n\t\tthrow new InvalidIdentifierError(value, type, 'cannot be empty');\n\t}\n\n\t// Rule 2: Length limit\n\tif (value.length > 63) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tvalue,\n\t\t\ttype,\n\t\t\t`exceeds maximum length of 63 characters (got ${value.length})`,\n\t\t);\n\t}\n\n\t// Rule 3 & 4: Character validation\n\t// PostgreSQL identifiers: start with letter/underscore, contain letter/digit/underscore/$\n\tconst validIdentifierPattern = /^[a-zA-Z_][a-zA-Z0-9_$]*$/;\n\tif (!validIdentifierPattern.test(value)) {\n\t\t// Check for specific issues\n\t\tif (/[\\x00-\\x1f\\x7f]/.test(value)) {\n\t\t\tthrow new InvalidIdentifierError(\n\t\t\t\tvalue,\n\t\t\t\ttype,\n\t\t\t\t'contains control characters',\n\t\t\t);\n\t\t}\n\t\tif (/^[0-9]/.test(value)) {\n\t\t\tthrow new InvalidIdentifierError(\n\t\t\t\tvalue,\n\t\t\t\ttype,\n\t\t\t\t'cannot start with a digit',\n\t\t\t);\n\t\t}\n\t\tif (/[^\\w$]/.test(value)) {\n\t\t\tthrow new InvalidIdentifierError(\n\t\t\t\tvalue,\n\t\t\t\ttype,\n\t\t\t\t'contains invalid characters (only letters, digits, underscore, and $ allowed)',\n\t\t\t);\n\t\t}\n\t\tthrow new InvalidIdentifierError(\n\t\t\tvalue,\n\t\t\ttype,\n\t\t\t'does not match valid identifier pattern',\n\t\t);\n\t}\n\n\t// Rule 5: No null bytes (extra safety)\n\tif (value.includes('\\0')) {\n\t\tthrow new InvalidIdentifierError(value, type, 'contains null byte');\n\t}\n\n\t// Note: Reserved keywords are allowed - they will be quoted by the AST helpers\n}\n\n/**\n * Check if an identifier is a SQL reserved keyword.\n */\nexport function isReservedKeyword(value: string): boolean {\n\treturn SQL_RESERVED_KEYWORDS.has(value.toLowerCase());\n}\n\n/**\n * Validate a schema-qualified identifier (schema.table).\n *\n * @param schemaTable String in format \"schema.table\" or just \"table\"\n * @returns Object with validated schema and table names\n * @throws InvalidIdentifierError if validation fails\n */\nexport function validateQualifiedIdentifier(schemaTable: string): {\n\tschema?: string;\n\ttable: string;\n} {\n\tconst parts = schemaTable.split('.');\n\n\tif (parts.length === 1) {\n\t\tvalidateIdentifier(parts[0]!, 'table');\n\t\treturn { table: parts[0]! };\n\t}\n\n\tif (parts.length === 2) {\n\t\tconst schema = parts[0]!;\n\t\tconst table = parts[1]!;\n\t\tvalidateIdentifier(schema, 'schema');\n\t\tvalidateIdentifier(table, 'table');\n\t\treturn { schema, table };\n\t}\n\n\tthrow new InvalidIdentifierError(\n\t\tschemaTable,\n\t\t'table',\n\t\t'too many dots in qualified name (expected schema.table or table)',\n\t);\n}\n\n/**\n * Batch validate multiple identifiers.\n *\n * @param identifiers Map of identifier values to their types\n * @throws InvalidIdentifierError on first validation failure\n */\nexport function validateIdentifiers(\n\tidentifiers: Record<string, 'table' | 'column' | 'schema' | 'alias'>,\n): void {\n\tfor (const [value, type] of Object.entries(identifiers)) {\n\t\tif (value) {\n\t\t\tvalidateIdentifier(value, type);\n\t\t}\n\t}\n}\n\n// ============================================================================\n// Sanitization (for display/logging only - NOT for SQL)\n// ============================================================================\n\n/**\n * Sanitize an identifier for safe logging/display.\n * NOT for use in SQL - use validateIdentifier + AST helpers for that.\n */\nexport function sanitizeForDisplay(value: string): string {\n\t// Replace control characters with placeholders\n\treturn value.replace(/[\\x00-\\x1f\\x7f]/g, '?').slice(0, 100); // Truncate for display\n}\n\n/**\n * Validate a PostgreSQL extension name for safe use in DDL statements.\n *\n * Extension names differ from regular SQL identifiers: they can contain\n * hyphens and dots (e.g. `uuid-ossp`, `postgis-raster`, `pg_trgm`).\n * However they must not contain injection vectors.\n *\n * Allowed: letters, digits, underscore, hyphen, dot (`[a-zA-Z0-9_\\-.]+`)\n * Forbidden: double-quote, single-quote, semicolon, --, /*, *\\/, dollar-quoted strings ($$), whitespace, NUL, backslash\n *\n * @param name The extension name to validate (e.g. `uuid-ossp`)\n * @param context Human-readable context label for the error message\n * @throws InvalidIdentifierError if the name fails validation\n */\nexport function validateExtensionName(\n\tname: string,\n\tcontext = 'extension',\n): void {\n\tif (!name || name.length === 0) {\n\t\tthrow new InvalidIdentifierError(name, context, 'cannot be empty');\n\t}\n\n\t// PostgreSQL NAMEDATALEN - 1 = 63 character limit\n\tif (name.length > 63) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t`exceeds maximum length of 63 characters (got ${name.length})`,\n\t\t);\n\t}\n\n\t// Reject injection vectors before the character allowlist check\n\tif (/[\\x00-\\x1f\\x7f]/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains control characters',\n\t\t);\n\t}\n\tif (/[\\\\]/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains backslash (forbidden in extension names)',\n\t\t);\n\t}\n\tif (/\"/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains double-quote (identifier injection risk)',\n\t\t);\n\t}\n\tif (/'/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains single-quote (string injection risk)',\n\t\t);\n\t}\n\tif (/;/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains semicolon (statement injection risk)',\n\t\t);\n\t}\n\tif (/--/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains line-comment marker (--)',\n\t\t);\n\t}\n\tif (/\\/\\*/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains block-comment opener (/*)',\n\t\t);\n\t}\n\tif (/\\*\\//.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains block-comment closer (*/)',\n\t\t);\n\t}\n\tif (/\\$\\$/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains dollar-quoting ($$)',\n\t\t);\n\t}\n\tif (/\\s/.test(name)) {\n\t\tthrow new InvalidIdentifierError(name, context, 'contains whitespace');\n\t}\n\n\t// Final allowlist: letters, digits, underscore, hyphen, dot\n\tif (!/^[a-zA-Z0-9_\\-.]+$/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains characters not allowed in extension names (only letters, digits, underscore, hyphen, and dot allowed)',\n\t\t);\n\t}\n}\n\n/**\n * Validate a PostgreSQL collation name for safe use in DDL statements.\n *\n * Collation names differ from regular SQL identifiers: they can contain\n * hyphens and dots to represent locale strings (e.g. `en_US.utf8`,\n * `en-US-x-icu`, `C.UTF-8`, `C`). They must not contain injection vectors.\n *\n * Allowed: letter or underscore start, then letters, digits, underscore,\n * hyphen, dot, and an optional trailing `@modifier` (1-10 characters\n * from `[A-Za-z0-9-]`, e.g. `@euro`, `@latin9`, `@iso8859-15`).\n * Modifier hyphens are allowed to cover codepage suffixes like\n * `iso8859-15`. Pattern: `[a-zA-Z_][a-zA-Z0-9_.-]*(?:@[A-Za-z0-9-]{1,10})?`\n * Forbidden: any character outside [A-Za-z0-9_.-] and the optional\n * @modifier (including single-quote, double-quote, semicolon, --,\n * block-comment markers, dollar-quoting, whitespace, NUL byte,\n * backslash, bare @, or @modifier longer than 10 characters)\n *\n * @param name The collation name to validate (e.g. en_US.utf8, de_DE.utf8@euro)\n * @param context Human-readable context label for the error message\n * @throws InvalidIdentifierError if the name fails validation\n */\nexport function validateCollationName(\n\tname: string,\n\tcontext = 'collation',\n): void {\n\tif (!name || name.length === 0) {\n\t\tthrow new InvalidIdentifierError(name, context, 'cannot be empty');\n\t}\n\n\t// PostgreSQL NAMEDATALEN - 1 = 63 byte limit. For collation names the\n\t// equivalence of .length and Buffer.byteLength() still holds because the\n\t// accepted charset ([A-Za-z0-9_.-] plus the @modifier [A-Za-z0-9-]) is\n\t// entirely ASCII — every character is a single byte in UTF-8.\n\tif (Buffer.byteLength(name, 'utf8') > 63) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t`exceeds maximum length of 63 bytes (got ${Buffer.byteLength(name, 'utf8')})`,\n\t\t);\n\t}\n\n\t// Reject NUL bytes — PostgreSQL silently truncates at the first NUL\n\tif (/\\x00/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains NUL byte (\\\\x00) which would be silently truncated by PostgreSQL',\n\t\t);\n\t}\n\n\t// Reject other control characters (0x01-0x1F, 0x7F)\n\tif (/[\\x01-\\x1f\\x7f]/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains control characters (only printable characters allowed)',\n\t\t);\n\t}\n\n\t// Reject backslash\n\tif (/[\\\\]/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains backslash (forbidden in collation names)',\n\t\t);\n\t}\n\n\t// Reject embedded double-quotes — not valid inside a collation name\n\tif (/\"/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains double-quote (identifier injection risk)',\n\t\t);\n\t}\n\n\t// Reject single-quotes\n\tif (/'/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains single-quote (string injection risk)',\n\t\t);\n\t}\n\n\t// Reject semicolons\n\tif (/;/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains semicolon (statement injection risk)',\n\t\t);\n\t}\n\n\t// Reject line-comment marker\n\tif (/--/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains line-comment marker (--)',\n\t\t);\n\t}\n\n\t// Reject block-comment opener\n\tif (/\\/\\*/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains block-comment opener (/*)',\n\t\t);\n\t}\n\n\t// Reject block-comment closer\n\tif (/\\*\\//.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains block-comment closer (*/)',\n\t\t);\n\t}\n\n\t// Reject dollar-quoting\n\tif (/\\$\\$/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains dollar-quoting ($$)',\n\t\t);\n\t}\n\n\t// Reject whitespace\n\tif (/\\s/.test(name)) {\n\t\tthrow new InvalidIdentifierError(name, context, 'contains whitespace');\n\t}\n\n\t// Final allowlist: must start with letter or underscore, then allow\n\t// letters, digits, underscore, hyphen, dot (covers en_US.utf8, en-US-x-icu, C.UTF-8).\n\t// An optional trailing @modifier (1-10 alphanumeric or hyphen chars) is also\n\t// accepted, e.g. de_DE.utf8@euro, en_US.utf8@latin9, en_US@iso8859-15. Bare @,\n\t// overlong modifiers, and non-[A-Za-z0-9-] characters inside the modifier are\n\t// rejected. Must match: [a-zA-Z_][a-zA-Z0-9_.-]*(?:@[A-Za-z0-9-]{1,10})?\n\tif (!/^[a-zA-Z_][a-zA-Z0-9_.-]*(?:@[A-Za-z0-9-]{1,10})?$/.test(name)) {\n\t\tthrow new InvalidIdentifierError(\n\t\t\tname,\n\t\t\tcontext,\n\t\t\t'contains characters not allowed in collation names (only letters, digits, underscore, hyphen, and dot allowed; optional @modifier must be 1-10 alphanumeric/hyphen characters, e.g. @euro, @latin9, @iso8859-15)',\n\t\t);\n\t}\n}\n\n/** Safe PostgreSQL type name pattern: base_name, optional (precision,scale), optional [] */\nconst SAFE_TYPE_PATTERN =\n\t/^[a-zA-Z_][a-zA-Z0-9_ ]*(\\(\\d+(,\\s*\\d+)?\\))?(\\[\\])?$/;\n\n/**\n * Validate a raw SQL expression used in DDL contexts (defaults, policy USING/CHECK).\n * Rejects injection vectors: semicolons, line-comment markers, block-comment markers.\n *\n * @security Called before any ModelIR-sourced string is interpolated into DDL.\n * @param sql The raw SQL expression string to validate.\n * @param context Human-readable context label for the error message.\n * @throws Error if the expression contains forbidden characters.\n */\nexport function validateSqlExpression(sql: string, context: string): void {\n\t// Forbidden: semicolons (statement injection), line comments (--),\n\t// block comment openers (/*), block comment closers (*/) — defense-in-depth\n\t// so a partial payload cannot close an enclosing comment to inject SQL —\n\t// dollar-quoted strings ($$), backslashes.\n\tif (/[;]|--|\\/\\*|\\*\\/|\\$\\$|\\\\/.test(sql)) {\n\t\tthrow new Error(\n\t\t\t`Unsafe SQL expression in ${context}: contains forbidden characters (;, --, /*, */, \"$$\" (dollar-quoted strings), \\\\). Value: \"${sql}\"`,\n\t\t);\n\t}\n}\n\n/**\n * Validate a PostgreSQL type name coming from `originalDbType` (populated by introspection).\n * Rejects strings that do not match the PostgreSQL type-name grammar to prevent injection.\n *\n * @security Called before any originalDbType value is interpolated into DDL column types.\n * @param type The type name string to validate.\n * @returns The original string (unchanged) when valid.\n * @throws Error if the type name does not match the safe pattern.\n */\nexport function validateDbTypeName(type: string): string {\n\tif (!SAFE_TYPE_PATTERN.test(type)) {\n\t\tthrow new Error(\n\t\t\t`Unsafe database type name: \"${type}\". Must match PostgreSQL type name rules.`,\n\t\t);\n\t}\n\treturn type;\n}\n","/**\n * Shared helpers for WHERE handlers.\n * @internal Extracted from comparison, in, like, null handlers (PGSQL-008, PGSQL-009).\n */\n\nimport { isFieldRef } from '@dbsp/types';\nimport type { Node } from '@pgsql/types';\nimport { columnRef, nullConstNode } from '../../ast-helpers.js';\nimport { createParamRef, createTypeCastParamRef } from '../../param-ref.js';\nimport { validateDbTypeName } from '../../validate.js';\nimport type { CompilerContext, CompilerState } from '../types.js';\nimport { isParamRef } from '../types.js';\n\n/**\n * Build column reference from decision column, using current alias or root table.\n */\nexport function buildColumnRef(column: string, ctx: CompilerContext): Node {\n\t// Handle qualified names like 'alias.column' — split and use the explicit table qualifier.\n\t// This is required when ref('alias.col') is used inside filter conditions (e.g. isNotNull).\n\t// Without splitting, the full dotted string becomes a column name and the root table is\n\t// prepended, producing \"root\".\"alias.col\" (3-part) instead of \"alias\".\"col\" (2-part).\n\tif (column.includes('.')) {\n\t\tconst dotIndex = column.indexOf('.');\n\t\tconst table = column.substring(0, dotIndex);\n\t\tconst col = column.substring(dotIndex + 1);\n\t\treturn columnRef(col, table, undefined, ctx.naming);\n\t}\n\tconst alias = ctx.currentAlias ?? ctx.rootTable;\n\t// Schema is NOT used for column references — aliases and table names in WHERE\n\t// are query-scoped, not schema-qualified. Schema is only for FROM/JOIN entries.\n\treturn columnRef(column, alias, undefined, ctx.naming);\n}\n\n/**\n * Build parameter reference and register value in compiler state.\n * If value has a pre-assigned `paramIndex` (from PlanDecision), use it directly.\n */\nexport function buildParamRef(value: unknown, state: CompilerState): Node {\n\tif (isParamRef(value)) {\n\t\tstate.parameters.push(value.value);\n\t\treturn createParamRef(value.paramIndex);\n\t}\n\tstate.paramIndex++;\n\tstate.parameters.push(value);\n\treturn createParamRef(state.paramIndex);\n}\n\n/**\n * Compile a value into a parameterized AST node.\n * Handles null, pre-assigned paramIndex, and normal values.\n * Ported from compiler-conditions.ts for DRY consolidation.\n */\nexport function compileValue(\n\tvalue: unknown,\n\tstate: Pick<CompilerState, 'parameters' | 'paramIndex'>,\n\tcolumnType?: string,\n): Node {\n\tif (value === null || value === undefined) {\n\t\treturn nullConstNode();\n\t}\n\n\tif (isParamRef(value)) {\n\t\tstate.parameters.push(value.value);\n\t\treturn columnType\n\t\t\t? createTypeCastParamRef(value.paramIndex, columnType)\n\t\t\t: createParamRef(value.paramIndex);\n\t}\n\n\tconst idx = ++state.paramIndex;\n\tstate.parameters.push(value);\n\treturn columnType\n\t\t? createTypeCastParamRef(idx, columnType)\n\t\t: createParamRef(idx);\n}\n\n/**\n * Compile a value that may be a FieldRef (column-to-column comparison) or a regular value.\n * FieldRef with scope:'inner' resolves to the current context alias.\n * FieldRef with scope:'outer' resolves to the outer query alias (for EXISTS subqueries).\n */\nexport function compileValueOrFieldRef(\n\tvalue: unknown,\n\tctx: CompilerContext,\n\tstate: Pick<CompilerState, 'parameters' | 'paramIndex'>,\n\tcolumnType?: string,\n): Node {\n\tif (isFieldRef(value)) {\n\t\tconst alias =\n\t\t\tvalue.scope === 'outer'\n\t\t\t\t? (ctx.outerAlias ?? ctx.rootTable)\n\t\t\t\t: (ctx.currentAlias ?? ctx.rootTable);\n\t\treturn columnRef(value.column, alias, undefined, ctx.naming);\n\t}\n\treturn compileValue(value, state, columnType);\n}\n\n/**\n * Resolve the PostgreSQL type for a column from the ModelIR in the context.\n * Returns undefined when model is absent or column is not found.\n */\nexport function resolveColumnPgType(\n\tcolumnName: string,\n\tctx: CompilerContext,\n): string | undefined {\n\tif (!ctx.model) return undefined;\n\tconst table = ctx.model.getTable(ctx.rootTable);\n\tif (!table) return undefined;\n\tconst column = table.columns.find((c) => c.name === columnName);\n\tif (!column) return undefined;\n\t// Only cast when originalDbType is explicitly set (populated by introspection).\n\t// Manually defined schemas omit this field — we do not guess the PG type from\n\t// the abstract ColumnType to avoid breaking queries on non-introspected schemas.\n\tif (column.originalDbType) return validateDbTypeName(column.originalDbType);\n\treturn undefined;\n}\n","/**\n * ANY Operator Handler\n *\n * Handles: any (col = ANY($N::type[]))\n *\n * Unlike the `in` handler which omits the type cast, this handler always\n * emits an explicit `$N::type[]` cast, derived from:\n * 1. decision.dataType (set by normalizeToDecision when schema info is available)\n * 2. Runtime value inspection of the first non-null value in the array\n */\n\nimport type { Node } from '@pgsql/types';\nimport { mapModelIRTypeToPgBase } from '../../compiler-utils.js';\nimport { createParamRef } from '../../param-ref.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tWhereHandler,\n} from '../types.js';\nimport { COLLECTION_OPERATORS } from '../types.js';\nimport { buildColumnRef } from './utils.js';\n\n/**\n * Infer PostgreSQL base type from a runtime value sample.\n * Returns the base type name (without []) — the caller appends the array cast.\n */\nfunction inferPgBaseType(sample: unknown): string {\n\tif (typeof sample === 'bigint') return 'int8';\n\tif (typeof sample === 'boolean') return 'bool';\n\tif (typeof sample === 'number') {\n\t\treturn Number.isInteger(sample) ? 'int4' : 'float8';\n\t}\n\treturn 'text';\n}\n\n/**\n * Build a typed TypeCast node for an array parameter: $N::type[]\n */\nfunction createTypedArrayParam(paramNumber: number, pgBaseType: string): Node {\n\treturn {\n\t\tTypeCast: {\n\t\t\targ: createParamRef(paramNumber),\n\t\t\ttypeName: {\n\t\t\t\tnames: [{ String: { sval: pgBaseType } }],\n\t\t\t\ttypemod: -1,\n\t\t\t\tarrayBounds: [{ Integer: { ival: -1 } }],\n\t\t\t},\n\t\t},\n\t};\n}\n\n/**\n * ANY operator handler.\n *\n * Compiles WhereAnyIntent (kind='any') to: \"col\" = ANY($N::type[])\n */\nexport const anyHandler: WhereHandler = {\n\toperators: [COLLECTION_OPERATORS.ANY],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst column = decision.column;\n\n\t\tif (!column) {\n\t\t\tthrow new Error('ANY handler requires a column');\n\t\t}\n\n\t\tconst values = Array.isArray(decision.values) ? decision.values : [];\n\t\tconst columnNode = buildColumnRef(column, ctx);\n\n\t\t// Determine the PG base type\n\t\tlet pgBaseType: string;\n\t\tif (decision.dataType) {\n\t\t\t// mapModelIRTypeToPgBase returns undefined for custom DX-050 dbType — use verbatim\n\t\t\tpgBaseType =\n\t\t\t\tmapModelIRTypeToPgBase(decision.dataType) ?? decision.dataType;\n\t\t} else {\n\t\t\t// Runtime inspection: find first non-null value\n\t\t\tconst sample = values.find((v) => v !== null && v !== undefined);\n\t\t\tpgBaseType = sample !== undefined ? inferPgBaseType(sample) : 'text';\n\t\t}\n\n\t\t// Register the array as a single parameter\n\t\tstate.paramIndex++;\n\t\tstate.parameters.push(values);\n\n\t\tconst typedParam = createTypedArrayParam(state.paramIndex, pgBaseType);\n\n\t\treturn {\n\t\t\tA_Expr: {\n\t\t\t\tkind: 'AEXPR_OP_ANY',\n\t\t\t\tname: [{ String: { sval: '=' } }],\n\t\t\t\tlexpr: columnNode,\n\t\t\t\trexpr: typedParam,\n\t\t\t},\n\t\t};\n\t},\n};\n","/**\n * BETWEEN Operator Handler\n *\n * Handles: between\n */\n\nimport type { Node } from '@pgsql/types';\nimport { createParamRef } from '../../param-ref.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tWhereHandler,\n} from '../types.js';\nimport { buildColumnRef } from './utils.js';\n\n/**\n * BETWEEN operator handler\n *\n * Compiles: column BETWEEN $min AND $max\n */\nexport const betweenHandler: WhereHandler = {\n\toperators: ['between'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst column = decision.column;\n\t\tif (!column) {\n\t\t\tthrow new Error('BETWEEN handler requires a column');\n\t\t}\n\n\t\tconst range = decision.value as [unknown, unknown];\n\t\tif (!Array.isArray(range) || range.length !== 2) {\n\t\t\tthrow new Error('BETWEEN condition requires [min, max] array');\n\t\t}\n\n\t\tconst columnNode = buildColumnRef(column, ctx);\n\n\t\tconst minIdx = ++state.paramIndex;\n\t\tstate.parameters.push(range[0]);\n\t\tconst minNode = createParamRef(minIdx);\n\n\t\tconst maxIdx = ++state.paramIndex;\n\t\tstate.parameters.push(range[1]);\n\t\tconst maxNode = createParamRef(maxIdx);\n\n\t\treturn {\n\t\t\tA_Expr: {\n\t\t\t\tkind: 'AEXPR_BETWEEN',\n\t\t\t\tname: [{ String: { sval: 'BETWEEN' } }],\n\t\t\t\tlexpr: columnNode,\n\t\t\t\trexpr: { List: { items: [minNode, maxNode] } },\n\t\t\t},\n\t\t};\n\t},\n};\n","/**\n * Comparison Operators Handler\n *\n * Handles: =, !=, <, <=, >, >=\n */\n\nimport type { Node } from '@pgsql/types';\nimport {\n\teqExpr,\n\tgtExpr,\n\tgteExpr,\n\tltExpr,\n\tlteExpr,\n\tneExpr,\n} from '../../ast-helpers.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tWhereHandler,\n} from '../types.js';\nimport { COMPARISON_OPERATORS } from '../types.js';\nimport {\n\tbuildColumnRef,\n\tcompileValueOrFieldRef,\n\tresolveColumnPgType,\n} from './utils.js';\n\n/**\n * Comparison operators handler\n */\nexport const comparisonHandler: WhereHandler = {\n\toperators: [\n\t\tCOMPARISON_OPERATORS.EQ,\n\t\tCOMPARISON_OPERATORS.NEQ,\n\t\tCOMPARISON_OPERATORS.LT,\n\t\tCOMPARISON_OPERATORS.LTE,\n\t\tCOMPARISON_OPERATORS.GT,\n\t\tCOMPARISON_OPERATORS.GTE,\n\t],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst operator = decision.operator ?? '=';\n\t\tconst column = decision.column;\n\t\tconst value = decision.value;\n\n\t\tif (!column) {\n\t\t\tthrow new Error('Comparison handler requires a column');\n\t\t}\n\n\t\tconst left = buildColumnRef(column, ctx);\n\t\tconst columnType = resolveColumnPgType(column, ctx);\n\t\tconst right = compileValueOrFieldRef(value, ctx, state, columnType);\n\n\t\tswitch (operator) {\n\t\t\tcase COMPARISON_OPERATORS.EQ:\n\t\t\tcase '=':\n\t\t\t\treturn eqExpr(left, right);\n\n\t\t\tcase COMPARISON_OPERATORS.NEQ:\n\t\t\tcase '!=':\n\t\t\tcase '<>':\n\t\t\t\treturn neExpr(left, right);\n\n\t\t\tcase COMPARISON_OPERATORS.LT:\n\t\t\tcase '<':\n\t\t\t\treturn ltExpr(left, right);\n\n\t\t\tcase COMPARISON_OPERATORS.LTE:\n\t\t\tcase '<=':\n\t\t\t\treturn lteExpr(left, right);\n\n\t\t\tcase COMPARISON_OPERATORS.GT:\n\t\t\tcase '>':\n\t\t\t\treturn gtExpr(left, right);\n\n\t\t\tcase COMPARISON_OPERATORS.GTE:\n\t\t\tcase '>=':\n\t\t\t\treturn gteExpr(left, right);\n\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unknown comparison operator: ${operator}`);\n\t\t}\n\t},\n};\n","/**\n * Custom Expression WHERE Handler\n *\n * Handles WHERE conditions using custom expressions (ExpressionIntent).\n * Operator: 'expression'\n * Pattern: <expr> <op> $N\n */\n\nimport type { ExpressionIntent } from '@dbsp/types';\nimport type { Node } from '@pgsql/types';\nimport { binaryExpr } from '../../ast-helpers.js';\nimport { createParamRef } from '../../param-ref.js';\nimport { compileExpressionIntent } from '../expression/custom.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tWhereDispatcher,\n\tWhereHandler,\n} from '../types.js';\n\n/**\n * Maps comparison operator names to SQL operators.\n */\nconst OP_MAP: Record<string, string> = {\n\teq: '=',\n\tneq: '!=',\n\tgt: '>',\n\tgte: '>=',\n\tlt: '<',\n\tlte: '<=',\n\t'=': '=',\n\t'!=': '!=',\n\t'>': '>',\n\t'>=': '>=',\n\t'<': '<',\n\t'<=': '<=',\n};\n\n/**\n * WHERE handler for custom expression comparisons.\n * Compiles: <expression> <op> $N\n */\nexport const customExpressionWhereHandler: WhereHandler = {\n\toperators: ['expression'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t\t_dispatch: WhereDispatcher,\n\t): Node {\n\t\tconst exprIntent = decision.expressionIntent as ExpressionIntent;\n\n\t\t// Left side: compile the custom expression\n\t\tconst leftNode = compileExpressionIntent(exprIntent, ctx, state);\n\n\t\t// Standalone boolean expression: op('!=', exprRef('a'), exprRef('b')) passed\n\t\t// directly to .where() — no right-side value or comparison operator.\n\t\t// decision.operator === 'expression' is the WHERE handler discriminant (not a SQL op).\n\t\t// A standalone expression has no subqueryOperator and no scalar value to bind.\n\t\tif (decision.value === undefined && !decision.subqueryOperator) {\n\t\t\treturn leftNode;\n\t\t}\n\n\t\t// Right side: bind the comparison value as a parameter\n\t\tconst idx = ++state.paramIndex;\n\t\tstate.parameters.push(decision.value);\n\t\tconst rightNode = createParamRef(idx);\n\n\t\t// Map comparison operator\n\t\tconst rawOp = decision.subqueryOperator ?? decision.operator ?? '=';\n\t\tconst sqlOp = OP_MAP[rawOp];\n\t\tif (!sqlOp) {\n\t\t\tthrow new Error(\n\t\t\t\t`customExpressionWhereHandler: unsupported comparison operator: ${rawOp}`,\n\t\t\t);\n\t\t}\n\n\t\treturn binaryExpr(sqlOp, leftNode, rightNode);\n\t},\n};\n","/**\n * EXISTS Operators Handler\n *\n * Handles: exists, notExists (some, none modes)\n *\n * EXISTS checks if at least one related record exists.\n * NOT EXISTS checks that no related records exist.\n */\n\nimport type { Node, SelectStmt, SubLink } from '@pgsql/types';\nimport { DEFAULT_PK_COLUMN, defaultFkDerivation } from '../../assert-field.js';\nimport {\n\tcolumnRef,\n\teqExpr,\n\tfkCorrelation,\n\tjoinExpr,\n\trangeVar,\n} from '../../ast-helpers.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tWhereDispatcher,\n\tWhereHandler,\n} from '../types.js';\n\n/**\n * Create a SubLink node for EXISTS/NOT EXISTS\n * Note: SubLinkType only has EXISTS_SUBLINK, so we wrap with NOT BoolExpr for negation\n */\nfunction createSubLinkExists(subquery: Node, negated: boolean): Node {\n\tconst subLink: SubLink = {\n\t\tsubLinkType: 'EXISTS_SUBLINK',\n\t\tsubselect: subquery,\n\t};\n\tconst existsNode: Node = { SubLink: subLink };\n\n\tif (negated) {\n\t\treturn {\n\t\t\tBoolExpr: {\n\t\t\t\tboolop: 'NOT_EXPR',\n\t\t\t\targs: [existsNode],\n\t\t\t},\n\t\t};\n\t}\n\n\treturn existsNode;\n}\n\n/**\n * Build correlation condition: source.column = target.column\n */\nfunction buildCorrelation(\n\tsourceAlias: string,\n\tsourceColumn: string,\n\ttargetAlias: string,\n\ttargetColumn: string,\n\tctx: CompilerContext,\n): Node {\n\t// Neither source nor target uses schema — column references are query-scoped.\n\t// Schema is only for FROM/JOIN clause table entries (rangeVar).\n\tconst left = columnRef(sourceColumn, sourceAlias, undefined, ctx.naming);\n\tconst right = columnRef(targetColumn, targetAlias, undefined, ctx.naming);\n\treturn eqExpr(left, right);\n}\n\n/**\n * Build a basic EXISTS subquery\n *\n * SELECT 1 FROM targetTable AS targetAlias\n * WHERE targetAlias.fk = sourceAlias.pk [AND additional conditions]\n */\nfunction buildExistsSubquery(\n\tdecision: Decision,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n\tdispatch: WhereDispatcher,\n): Node {\n\tconst relation = decision.relation;\n\tconst targetTable = decision.targetTable ?? relation;\n\t// sourceColumn: prefer explicit value from decision (set by planner's mapToHandlerDecision).\n\t// When called directly from mutation WHERE (DELETE/UPDATE), the planner is bypassed and\n\t// sourceColumn is absent — fall back to the PK convention (typically 'id' for hasMany).\n\tconst sourceColumn =\n\t\tdecision.sourceColumn ?? ctx.defaultPkColumnName ?? DEFAULT_PK_COLUMN;\n\tconst targetColumn =\n\t\tdecision.targetColumn ??\n\t\t(ctx.deriveFkColumnName ?? defaultFkDerivation)(\n\t\t\tctx.rootTable,\n\t\t\tctx.defaultPkColumnName ?? DEFAULT_PK_COLUMN,\n\t\t);\n\n\tif (!targetTable) {\n\t\tthrow new Error('EXISTS handler requires targetTable or relation');\n\t}\n\n\t// Generate unique alias\n\tconst existingAliases = state.aliases.size;\n\tconst targetAlias = `${targetTable}_exists_${existingAliases}`;\n\tstate.aliases.set(`exists_${targetTable}`, targetAlias);\n\n\tconst sourceAlias = ctx.currentAlias ?? ctx.rootTable;\n\n\t// Build correlation condition\n\tconst correlation = buildCorrelation(\n\t\tsourceAlias,\n\t\tsourceColumn,\n\t\ttargetAlias,\n\t\ttargetColumn,\n\t\tctx,\n\t);\n\n\t// Build WHERE clause (correlation + nested conditions)\n\tlet whereClause = correlation;\n\tif (decision.conditions && decision.conditions.length > 0) {\n\t\t// Create context for subquery with target alias.\n\t\t// Schema is stripped because nested conditions reference the aliased table,\n\t\t// and aliases are query-scoped (not schema-qualified).\n\t\tconst { schema: _schema, ...ctxWithoutSchema } = ctx;\n\t\tconst subCtx: CompilerContext = {\n\t\t\t...ctxWithoutSchema,\n\t\t\trootTable: targetTable,\n\t\t\tcurrentAlias: targetAlias,\n\t\t\touterAlias: sourceAlias,\n\t\t};\n\n\t\t// Compile nested conditions\n\t\tconst nestedConditions = decision.conditions.map((cond) =>\n\t\t\tdispatch(cond, subCtx, state),\n\t\t);\n\n\t\t// AND correlation with nested conditions\n\t\twhereClause = {\n\t\t\tBoolExpr: {\n\t\t\t\tboolop: 'AND_EXPR',\n\t\t\t\targs: [correlation, ...nestedConditions],\n\t\t\t},\n\t\t};\n\t}\n\n\t// Build SELECT 1 FROM targetTable AS targetAlias [JOIN ...] WHERE ...\n\tlet fromNode: Node = rangeVar(\n\t\ttargetTable,\n\t\ttargetAlias,\n\t\tctx.schema,\n\t\tctx.naming,\n\t);\n\n\t// Add JOIN clauses for each include entry.\n\t// Each include entry in decision.include has shape: { type:'existsInclude', relation, joinType }\n\t// The relation is used as the join alias so dotted WHERE references (e.g. callerFile.project_id) resolve.\n\tconst includeDecisions = decision.include as\n\t\t| readonly { relation?: string; joinType?: string }[]\n\t\t| undefined;\n\tif (includeDecisions && includeDecisions.length > 0) {\n\t\t// Track alias → realTableName for multi-hop FK resolution.\n\t\t// When the 2nd+ include is a relation on an intermediate joined table\n\t\t// (not the root targetTable), we find the correct FK by scanning\n\t\t// previously joined tables first, then falling back to root.\n\t\tconst joinedTables = new Map<string, string>(); // alias → realTableName\n\n\t\tfor (const inc of includeDecisions) {\n\t\t\tconst joinRelation = inc.relation;\n\t\t\tif (!joinRelation) continue;\n\n\t\t\t// Resolve the join target table and FK columns from ModelIR when available.\n\t\t\tlet joinTargetTable: string = joinRelation;\n\t\t\tlet joinSourceCol: string | undefined;\n\t\t\tlet joinTargetCol: string | undefined;\n\t\t\t// sourceAliasForJoin: alias to use on the LEFT side of the JOIN ON.\n\t\t\t// Defaults to the root EXISTS alias; overridden when FK is found on an\n\t\t\t// intermediate table (multi-hop).\n\t\t\tlet sourceAliasForJoin: string = targetAlias;\n\n\t\t\tconst model = ctx.model;\n\t\t\tif (model) {\n\t\t\t\tlet rel = null;\n\n\t\t\t\t// 1. Try each previously joined table (in insertion order).\n\t\t\t\tfor (const [prevAlias, prevRealTable] of joinedTables) {\n\t\t\t\t\trel = model.getRelation(`${prevRealTable}.${joinRelation}`);\n\t\t\t\t\tif (rel) {\n\t\t\t\t\t\tsourceAliasForJoin = prevAlias;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// 2. Fallback: root target table.\n\t\t\t\tif (!rel) {\n\t\t\t\t\trel = model.getRelation(`${targetTable}.${joinRelation}`);\n\t\t\t\t\t// sourceAliasForJoin stays as targetAlias (root EXISTS alias)\n\t\t\t\t}\n\n\t\t\t\tif (rel) {\n\t\t\t\t\tjoinTargetTable = rel.target;\n\t\t\t\t\tif (rel.type === 'belongsTo') {\n\t\t\t\t\t\t// FK is on the source side (sourceTable.fkCol → joinTargetTable.id)\n\t\t\t\t\t\tconst fk =\n\t\t\t\t\t\t\ttypeof rel.foreignKey === 'string'\n\t\t\t\t\t\t\t\t? rel.foreignKey\n\t\t\t\t\t\t\t\t: Array.isArray(rel.foreignKey)\n\t\t\t\t\t\t\t\t\t? rel.foreignKey[0]\n\t\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\tjoinSourceCol = fk;\n\t\t\t\t\t\tjoinTargetCol =\n\t\t\t\t\t\t\t(ctx.defaultPkColumnName as string | undefined) ??\n\t\t\t\t\t\t\tDEFAULT_PK_COLUMN;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// hasMany/hasOne: FK is on the target side (joinTargetTable.fkCol → sourceTable.id)\n\t\t\t\t\t\tconst fk =\n\t\t\t\t\t\t\ttypeof rel.foreignKey === 'string'\n\t\t\t\t\t\t\t\t? rel.foreignKey\n\t\t\t\t\t\t\t\t: Array.isArray(rel.foreignKey)\n\t\t\t\t\t\t\t\t\t? rel.foreignKey[0]\n\t\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\tjoinSourceCol =\n\t\t\t\t\t\t\t(ctx.defaultPkColumnName as string | undefined) ??\n\t\t\t\t\t\t\tDEFAULT_PK_COLUMN;\n\t\t\t\t\t\tjoinTargetCol = fk;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fall back to FK derivation convention when ModelIR didn't resolve columns.\n\t\t\tif (!joinSourceCol) {\n\t\t\t\t// Assume belongsTo: FK on source table = joinRelation + '_id'\n\t\t\t\tjoinSourceCol = (ctx.deriveFkColumnName ?? defaultFkDerivation)(\n\t\t\t\t\tjoinRelation,\n\t\t\t\t\t(ctx.defaultPkColumnName as string | undefined) ?? DEFAULT_PK_COLUMN,\n\t\t\t\t);\n\t\t\t\tjoinTargetCol =\n\t\t\t\t\t(ctx.defaultPkColumnName as string | undefined) ?? DEFAULT_PK_COLUMN;\n\t\t\t}\n\n\t\t\tconst joinAlias = joinRelation; // e.g. 'callerFile'\n\t\t\tconst joinQuals = fkCorrelation(\n\t\t\t\tjoinSourceCol,\n\t\t\t\tsourceAliasForJoin, // resolved source alias (root or intermediate)\n\t\t\t\tjoinTargetCol ?? DEFAULT_PK_COLUMN,\n\t\t\t\tjoinAlias,\n\t\t\t\tctx.naming,\n\t\t\t);\n\n\t\t\tconst joinType =\n\t\t\t\t(inc.joinType as string | undefined) === 'left'\n\t\t\t\t\t? 'JOIN_LEFT'\n\t\t\t\t\t: 'JOIN_INNER';\n\n\t\t\tconst joinRangeVar = rangeVar(\n\t\t\t\tjoinTargetTable,\n\t\t\t\tjoinAlias,\n\t\t\t\tctx.schema,\n\t\t\t\tctx.naming,\n\t\t\t);\n\n\t\t\t// Wrap current fromNode with the new join: JoinExpr { larg: fromNode, rarg: joinRangeVar }\n\t\t\tfromNode = joinExpr(joinType, fromNode, joinRangeVar, joinQuals);\n\n\t\t\t// Track this join for subsequent iterations (multi-hop resolution).\n\t\t\tjoinedTables.set(joinAlias, joinTargetTable);\n\t\t}\n\t}\n\n\tconst stmt: SelectStmt = {\n\t\ttargetList: [\n\t\t\t{\n\t\t\t\tResTarget: {\n\t\t\t\t\tval: { A_Const: { ival: { ival: 1 } } },\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\tfromClause: [fromNode],\n\t\twhereClause,\n\t};\n\n\treturn { SelectStmt: stmt };\n}\n\n/**\n * EXISTS handler (mode: some)\n *\n * Returns rows where at least one related record exists.\n */\nexport const existsHandler: WhereHandler = {\n\toperators: ['exists', 'some'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t\tdispatch: WhereDispatcher,\n\t): Node {\n\t\tconst subquery = buildExistsSubquery(decision, ctx, state, dispatch);\n\t\treturn createSubLinkExists(subquery, false);\n\t},\n};\n\n/**\n * NOT EXISTS handler (mode: none)\n *\n * Returns rows where no related records exist.\n */\nexport const notExistsHandler: WhereHandler = {\n\toperators: ['notExists', 'none'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t\tdispatch: WhereDispatcher,\n\t): Node {\n\t\tconst subquery = buildExistsSubquery(decision, ctx, state, dispatch);\n\t\treturn createSubLinkExists(subquery, true);\n\t},\n};\n\n/**\n * EVERY handler (mode: every)\n *\n * Returns rows where ALL related records match.\n * Implemented as NOT EXISTS (... WHERE NOT condition)\n */\nexport const everyHandler: WhereHandler = {\n\toperators: ['every'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t\tdispatch: WhereDispatcher,\n\t): Node {\n\t\t// For 'every', we invert the WHERE condition and use NOT EXISTS\n\t\t// every(condition) = NOT EXISTS (SELECT 1 ... WHERE NOT condition)\n\n\t\tif (!decision.conditions || decision.conditions.length === 0) {\n\t\t\t// If no condition, every always matches (vacuous truth)\n\t\t\treturn { A_Const: { boolval: { boolval: true } } };\n\t\t}\n\n\t\t// Wrap conditions in NOT\n\t\tconst invertedDecision: Decision = {\n\t\t\t...decision,\n\t\t\tconditions: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'logical',\n\t\t\t\t\toperator: 'not',\n\t\t\t\t\tconditions: decision.conditions,\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\n\t\tconst subquery = buildExistsSubquery(\n\t\t\tinvertedDecision,\n\t\t\tctx,\n\t\t\tstate,\n\t\t\tdispatch,\n\t\t);\n\t\treturn createSubLinkExists(subquery, true);\n\t},\n};\n","/**\n * Collection Operators Handler\n *\n * Handles: in, notIn\n */\n\nimport type { Node } from '@pgsql/types';\nimport { booleanConstNode } from '../../ast-helpers.js';\nimport { createParamRef, createTypeCastParamRef } from '../../param-ref.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tWhereHandler,\n} from '../types.js';\nimport { COLLECTION_OPERATORS } from '../types.js';\nimport { buildColumnRef, resolveColumnPgType } from './utils.js';\n\n/**\n * Create IN expression using = ANY($N)\n * Uses AEXPR_OP_ANY to avoid pg-deparse quoting \"any\" as an identifier\n */\nfunction createInExpr(\n\tcolumnNode: Node,\n\tstate: CompilerState,\n\tvalues: unknown[],\n\tcolumnType?: string,\n): Node {\n\tstate.paramIndex++;\n\tstate.parameters.push(values);\n\tconst paramNode = columnType\n\t\t? createTypeCastParamRef(state.paramIndex, columnType, true)\n\t\t: createParamRef(state.paramIndex);\n\treturn {\n\t\tA_Expr: {\n\t\t\tkind: 'AEXPR_OP_ANY',\n\t\t\tname: [{ String: { sval: '=' } }],\n\t\t\tlexpr: columnNode,\n\t\t\trexpr: paramNode,\n\t\t},\n\t};\n}\n\n/**\n * Create NOT IN expression using <> ALL($N)\n * Uses AEXPR_OP_ALL to avoid pg-deparse quoting \"all\" as an identifier\n */\nfunction createNotInExpr(\n\tcolumnNode: Node,\n\tstate: CompilerState,\n\tvalues: unknown[],\n\tcolumnType?: string,\n): Node {\n\tstate.paramIndex++;\n\tstate.parameters.push(values);\n\tconst paramNode = columnType\n\t\t? createTypeCastParamRef(state.paramIndex, columnType, true)\n\t\t: createParamRef(state.paramIndex);\n\treturn {\n\t\tA_Expr: {\n\t\t\tkind: 'AEXPR_OP_ALL',\n\t\t\tname: [{ String: { sval: '<>' } }],\n\t\t\tlexpr: columnNode,\n\t\t\trexpr: paramNode,\n\t\t},\n\t};\n}\n\n/**\n * Collection operators handler (IN, NOT IN)\n */\nexport const inHandler: WhereHandler = {\n\toperators: [COLLECTION_OPERATORS.IN, COLLECTION_OPERATORS.NOT_IN],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst operator = decision.operator ?? 'in';\n\t\tconst column = decision.column;\n\t\tconst value = decision.value;\n\n\t\tif (!column) {\n\t\t\tthrow new Error('In handler requires a column');\n\t\t}\n\n\t\t// Handle empty arrays\n\t\tconst values = Array.isArray(value) ? value : [value];\n\t\tif (values.length === 0) {\n\t\t\t// Empty IN is always false, empty NOT IN is always true\n\t\t\tif (operator === COLLECTION_OPERATORS.NOT_IN || operator === 'notIn') {\n\t\t\t\treturn booleanConstNode(true);\n\t\t\t}\n\t\t\treturn booleanConstNode(false);\n\t\t}\n\n\t\tconst columnNode = buildColumnRef(column, ctx);\n\t\tconst columnType = resolveColumnPgType(column, ctx);\n\n\t\tif (operator === COLLECTION_OPERATORS.NOT_IN || operator === 'notIn') {\n\t\t\treturn createNotInExpr(columnNode, state, values, columnType);\n\t\t}\n\n\t\treturn createInExpr(columnNode, state, values, columnType);\n\t},\n};\n","/**\n * @module handlers/where/json\n * WHERE handlers for JSONB operators (@>, <@, ?, ->, ->>).\n */\n\nimport type { Node } from '@pgsql/types';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tWhereHandler,\n} from '../types.js';\nimport { buildColumnRef, compileValue } from './utils.js';\n\n/**\n * JSON containment: col @> $1 or col <@ $1\n */\nexport const jsonContainsHandler: WhereHandler = {\n\toperators: ['jsonContains', 'jsonContainedBy'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst column = decision.column;\n\t\tif (!column) {\n\t\t\tthrow new Error('JSON contains handler requires a column');\n\t\t}\n\n\t\tconst left = buildColumnRef(column, ctx);\n\t\tconst right = compileValue(decision.value, state);\n\t\tconst op = decision.operator === 'jsonContainedBy' ? '<@' : '@>';\n\n\t\treturn {\n\t\t\tA_Expr: {\n\t\t\t\tkind: 'AEXPR_OP',\n\t\t\t\tname: [{ String: { sval: op } }],\n\t\t\t\tlexpr: left,\n\t\t\t\trexpr: right,\n\t\t\t},\n\t\t};\n\t},\n};\n\n/**\n * JSON key existence: col ? $1\n */\nexport const jsonExistsHandler: WhereHandler = {\n\toperators: ['jsonExists'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst column = decision.column;\n\t\tif (!column) {\n\t\t\tthrow new Error('JSON exists handler requires a column');\n\t\t}\n\n\t\tconst left = buildColumnRef(column, ctx);\n\t\tconst right = compileValue(decision.value, state);\n\n\t\treturn {\n\t\t\tA_Expr: {\n\t\t\t\tkind: 'AEXPR_OP',\n\t\t\t\tname: [{ String: { sval: '?' } }],\n\t\t\t\tlexpr: left,\n\t\t\t\trexpr: right,\n\t\t\t},\n\t\t};\n\t},\n};\n\n/**\n * JSON comparison with path extraction: col->'key' = $1 or col->>'key' = $1\n * Handles WhereComparisonIntent with jsonPath/jsonMode.\n */\nexport const jsonComparisonHandler: WhereHandler = {\n\toperators: ['jsonComparison'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst column = decision.column;\n\t\tif (!column) {\n\t\t\tthrow new Error('JSON comparison handler requires a column');\n\t\t}\n\n\t\tconst jsonPath = decision.jsonPath;\n\t\tconst jsonMode = decision.jsonMode ?? 'text';\n\n\t\tif (!jsonPath?.length) {\n\t\t\tthrow new Error('JSON comparison handler requires jsonPath');\n\t\t}\n\n\t\t// Build chained JSON access: col->'a'->'b'->>'c'\n\t\tlet node: Node = buildColumnRef(column, ctx);\n\t\tfor (let i = 0; i < jsonPath.length; i++) {\n\t\t\tconst isLast = i === jsonPath.length - 1;\n\t\t\tconst op = isLast && jsonMode === 'text' ? '->>' : '->';\n\t\t\tnode = {\n\t\t\t\tA_Expr: {\n\t\t\t\t\tkind: 'AEXPR_OP',\n\t\t\t\t\tname: [{ String: { sval: op } }],\n\t\t\t\t\tlexpr: node,\n\t\t\t\t\trexpr: compileValue(jsonPath[i]!, state),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\t// Now apply the comparison operator\n\t\tconst operator = decision.operator;\n\t\tconst right = compileValue(decision.value, state);\n\n\t\t// Map the intent operator to SQL\n\t\tconst opMap: Record<string, string> = {\n\t\t\teq: '=',\n\t\t\tne: '!=',\n\t\t\tlt: '<',\n\t\t\tlte: '<=',\n\t\t\tgt: '>',\n\t\t\tgte: '>=',\n\t\t};\n\t\tconst sqlOp = opMap[operator ?? 'eq'] ?? '=';\n\n\t\treturn {\n\t\t\tA_Expr: {\n\t\t\t\tkind: 'AEXPR_OP',\n\t\t\t\tname: [{ String: { sval: sqlOp } }],\n\t\t\t\tlexpr: node,\n\t\t\t\trexpr: right,\n\t\t\t},\n\t\t};\n\t},\n};\n","/**\n * Pattern Operators Handler\n *\n * Handles: like, ilike\n */\n\nimport type { Node } from '@pgsql/types';\nimport { ilikeExpr, likeExpr } from '../../ast-helpers.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tWhereHandler,\n} from '../types.js';\nimport { PATTERN_OPERATORS } from '../types.js';\nimport { buildColumnRef, buildParamRef } from './utils.js';\n\n/** A_Expr with optional ESCAPE clause for LIKE operator */\ninterface A_ExprWithEscape {\n\tA_Expr: Record<string, unknown> & { escape?: Node };\n}\n\n/**\n * Pattern operators handler (LIKE, ILIKE)\n */\nexport const likeHandler: WhereHandler = {\n\toperators: [PATTERN_OPERATORS.LIKE, PATTERN_OPERATORS.ILIKE],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst operator = decision.operator ?? 'like';\n\t\tconst column = decision.column;\n\t\tconst value = decision.value;\n\n\t\tif (!column) {\n\t\t\tthrow new Error('Like handler requires a column');\n\t\t}\n\n\t\tconst left = buildColumnRef(column, ctx);\n\t\tconst right = buildParamRef(value, state);\n\n\t\tlet exprNode: Node;\n\n\t\tif (operator === PATTERN_OPERATORS.ILIKE || operator === 'ilike') {\n\t\t\texprNode = ilikeExpr(left, right);\n\t\t} else {\n\t\t\texprNode = likeExpr(left, right);\n\t\t}\n\n\t\tif (decision.escape !== undefined) {\n\t\t\t// Attach escape param as a runtime property on the A_Expr node\n\t\t\t// so that deparseAExpr can render ESCAPE $N\n\t\t\t// NOTE: escape property read by deparseAExpr() in pgsql-deparser.ts (AEXPR_LIKE case)\n\t\t\tconst escapeRef = buildParamRef(decision.escape, state);\n\t\t\t(exprNode as A_ExprWithEscape).A_Expr.escape = escapeRef;\n\t\t}\n\n\t\treturn exprNode;\n\t},\n};\n","/**\n * Logical Operators Handler\n *\n * Handles: and, or, not\n */\n\nimport type { Node } from '@pgsql/types';\nimport {\n\tandExpr,\n\tbooleanConstNode,\n\tnotExpr,\n\torExpr,\n} from '../../ast-helpers.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tWhereDispatcher,\n\tWhereHandler,\n} from '../types.js';\nimport { LOGICAL_OPERATORS } from '../types.js';\n\n/**\n * AND operator handler\n */\nexport const andHandler: WhereHandler = {\n\toperators: [LOGICAL_OPERATORS.AND],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t\tdispatch: WhereDispatcher,\n\t): Node {\n\t\tconst conditions = decision.conditions;\n\n\t\tif (!conditions || !Array.isArray(conditions)) {\n\t\t\tthrow new Error('AND handler requires conditions array');\n\t\t}\n\n\t\t// Empty AND is always true\n\t\tif (conditions.length === 0) {\n\t\t\treturn booleanConstNode(true);\n\t\t}\n\n\t\t// Single condition doesn't need AND\n\t\tif (conditions.length === 1) {\n\t\t\treturn dispatch(conditions[0]!, ctx, state);\n\t\t}\n\n\t\t// Compile all conditions recursively\n\t\tconst compiledConditions = conditions.map((condition) =>\n\t\t\tdispatch(condition, ctx, state),\n\t\t);\n\n\t\treturn andExpr(...compiledConditions);\n\t},\n};\n\n/**\n * OR operator handler\n */\nexport const orHandler: WhereHandler = {\n\toperators: [LOGICAL_OPERATORS.OR],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t\tdispatch: WhereDispatcher,\n\t): Node {\n\t\tconst conditions = decision.conditions;\n\n\t\tif (!conditions || !Array.isArray(conditions)) {\n\t\t\tthrow new Error('OR handler requires conditions array');\n\t\t}\n\n\t\t// Empty OR is always false\n\t\tif (conditions.length === 0) {\n\t\t\treturn booleanConstNode(false);\n\t\t}\n\n\t\t// Single condition doesn't need OR\n\t\tif (conditions.length === 1) {\n\t\t\treturn dispatch(conditions[0]!, ctx, state);\n\t\t}\n\n\t\t// Compile all conditions recursively\n\t\tconst compiledConditions = conditions.map((condition) =>\n\t\t\tdispatch(condition, ctx, state),\n\t\t);\n\n\t\treturn orExpr(...compiledConditions);\n\t},\n};\n\n/**\n * NOT operator handler\n *\n * Note: NOT takes a single condition in `conditions[0]`\n */\nexport const notHandler: WhereHandler = {\n\toperators: [LOGICAL_OPERATORS.NOT],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t\tdispatch: WhereDispatcher,\n\t): Node {\n\t\tconst conditions = decision.conditions;\n\n\t\tif (!conditions || conditions.length === 0) {\n\t\t\tthrow new Error('NOT handler requires a condition in conditions[0]');\n\t\t}\n\n\t\t// NOT wraps the first condition\n\t\tconst compiledCondition = dispatch(conditions[0]!, ctx, state);\n\n\t\treturn notExpr(compiledCondition);\n\t},\n};\n","/**\n * Null Operators Handler\n *\n * Handles: isNull, isNotNull\n */\n\nimport type { Node, NullTest } from '@pgsql/types';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tWhereHandler,\n} from '../types.js';\nimport { NULL_OPERATORS } from '../types.js';\nimport { buildColumnRef } from './utils.js';\n\n/**\n * Create a NullTest node\n */\nfunction nullTestExpr(arg: Node, isNull: boolean): Node {\n\tconst nullTest: NullTest = {\n\t\targ,\n\t\tnulltesttype: isNull ? 'IS_NULL' : 'IS_NOT_NULL',\n\t};\n\n\treturn { NullTest: nullTest };\n}\n\n/**\n * Null operators handler (IS NULL, IS NOT NULL)\n */\nexport const nullHandler: WhereHandler = {\n\toperators: [NULL_OPERATORS.IS_NULL, NULL_OPERATORS.IS_NOT_NULL],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\t_state: CompilerState,\n\t): Node {\n\t\tconst operator = decision.operator ?? 'isNull';\n\t\tconst column = decision.column;\n\n\t\tif (!column) {\n\t\t\tthrow new Error('Null handler requires a column');\n\t\t}\n\n\t\tconst columnNode = buildColumnRef(column, ctx);\n\n\t\tif (operator === NULL_OPERATORS.IS_NULL || operator === 'isNull') {\n\t\t\treturn nullTestExpr(columnNode, true);\n\t\t}\n\n\t\treturn nullTestExpr(columnNode, false);\n\t},\n};\n","/**\n * Range Operators Handler\n *\n * Handles: contains (@>), containedBy (<@), overlaps (&&)\n */\n\nimport type { Node } from '@pgsql/types';\nimport { createParamRef, createTypeCastParamRef } from '../../param-ref.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tWhereHandler,\n} from '../types.js';\nimport { isRangeValue } from '../types.js';\nimport { buildColumnRef } from './utils.js';\n\n/** Map operator names to PostgreSQL range operators */\nconst RANGE_OP_MAP: Record<string, string> = {\n\tcontains: '@>',\n\tcontainedBy: '<@',\n\toverlaps: '&&',\n};\n\n/**\n * Range operators handler (contains @>, containedBy <@, overlaps &&)\n *\n * Supports range objects, range strings, and scalar values with type casting.\n */\nexport const rangeHandler: WhereHandler = {\n\toperators: ['contains', 'containedBy', 'overlaps'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst column = decision.column;\n\t\tif (!column) {\n\t\t\tthrow new Error('Range handler requires a column');\n\t\t}\n\n\t\tconst operator = decision.operator ?? 'contains';\n\t\tconst pgOp = RANGE_OP_MAP[operator] ?? operator;\n\t\tconst value = decision.value;\n\n\t\tconst columnNode = buildColumnRef(column, ctx);\n\n\t\tlet paramValue: unknown;\n\t\tlet isScalar = false;\n\t\tif (isRangeValue(value)) {\n\t\t\tconst lower = value.lower ?? '';\n\t\t\tconst upper = value.upper ?? '';\n\t\t\tparamValue = `[${lower},${upper})`;\n\t\t} else if (typeof value === 'string' && /^\\[.*,.*[)\\]]$/.test(value)) {\n\t\t\tparamValue = value;\n\t\t} else {\n\t\t\tparamValue = value;\n\t\t\tisScalar = true;\n\t\t}\n\n\t\tconst paramIdx = ++state.paramIndex;\n\t\tstate.parameters.push(paramValue);\n\n\t\tlet castType = decision.dataType;\n\t\tif (castType && isScalar) {\n\t\t\tcastType = castType.replace(/range$/, '');\n\t\t\tif (castType === 'int4') castType = 'integer';\n\t\t\tif (castType === 'int8') castType = 'bigint';\n\t\t\tif (castType === 'tstz') castType = 'timestamptz';\n\t\t\tif (castType === 'ts') castType = 'timestamp';\n\t\t}\n\t\tconst rexpr = castType\n\t\t\t? createTypeCastParamRef(paramIdx, castType)\n\t\t\t: createParamRef(paramIdx);\n\n\t\treturn {\n\t\t\tA_Expr: {\n\t\t\t\tkind: 'AEXPR_OP',\n\t\t\t\tname: [{ String: { sval: pgOp } }],\n\t\t\t\tlexpr: columnNode,\n\t\t\t\trexpr,\n\t\t\t},\n\t\t};\n\t},\n};\n","/**\n * Unified WHERE compiler: compiles WhereIntent directly to PostgreSQL AST nodes.\n *\n * This is the new direct path that eliminates the intermediate\n * Decision/PlanDecision representation for WHERE clauses.\n * Both paths (Decision-based and WhereIntent-based) produce identical SQL.\n *\n * @internal\n */\n\nimport type {\n\tExpressionIntent,\n\tModelIR,\n\tQueryIntent,\n\tRefExpressionIntent,\n\tWhereAndIntent,\n\tWhereComparisonIntent,\n\tWhereIntent,\n\tWhereLikeIntent,\n\tWhereNotIntent,\n\tWhereOrIntent,\n\tWhereRawExistsIntent,\n\tWhereRawNotExistsIntent,\n\tWhereRelationFilterIntent,\n} from '@dbsp/types';\nimport type { Node, SelectStmt, SubLink } from '@pgsql/types';\nimport {\n\tandExpr,\n\tbinaryExpr,\n\tcolumnRef,\n\tnotExpr,\n\torExpr,\n\trangeVar,\n} from './ast-helpers.js';\nimport {\n\tcompileExpressionIntent,\n\tregisterWhereDispatcherFactory,\n} from './handlers/expression/custom.js';\nimport { createWhereDispatcher } from './handlers/index.js';\n\n// Register createWhereDispatcher with the expression compiler so that CASE expressions\n// in compileExpressionIntent can compile their WHEN conditions. This module is the\n// natural bridge: it imports both custom.ts and handlers/index.ts.\n// Called once at module-load time (safe: no circular calls, just stores the factory ref).\nregisterWhereDispatcherFactory(createWhereDispatcher);\n\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n} from './handlers/types.js';\nimport { createCompilerState } from './handlers/types.js';\nimport { buildColumnRef } from './handlers/where/utils.js';\nimport type { NamingPlugin } from './naming-plugin.js';\nimport { identityNaming } from './naming-plugin.js';\nimport { createParamRef } from './param-ref.js';\n\n// ============================================================================\n// Module-level constants\n// ============================================================================\n\n/** Operator name → SQL operator string. Shared by expression and subquery WHERE handlers. */\nconst OP_MAP: Record<string, string> = {\n\teq: '=',\n\tneq: '!=',\n\tgt: '>',\n\tgte: '>=',\n\tlt: '<',\n\tlte: '<=',\n\t'=': '=',\n\t'!=': '!=',\n\t'>': '>',\n\t'>=': '>=',\n\t'<': '<',\n\t'<=': '<=',\n};\n\n// ============================================================================\n// Public: WhereCompilerCtx\n// ============================================================================\n\n/**\n * Context for the unified WHERE compiler.\n * Maps to CompilerContext + CompilerState from the handler system.\n */\nexport type WhereCompilerCtx = {\n\t/** Current root table name (or alias) */\n\treadonly rootTable: string;\n\t/** Alias map: alias → real table name */\n\treadonly aliases: Map<string, string>;\n\t/** Shared mutable parameter state (parameters array + current index) */\n\treadonly paramState: CompilerState;\n\t/** Schema model for FK resolution and type-aware casting */\n\treadonly model?: ModelIR;\n\t/** Schema name for table qualification */\n\treadonly schemaName?: string;\n\t/** Naming convention plugin */\n\treadonly naming: NamingPlugin;\n\t/**\n\t * Callback to compile a QueryIntent subquery into an AST node.\n\t * Used by EXISTS/NOT EXISTS handlers that need correlated subqueries.\n\t * Returns the compiled AST node, the count of parameters consumed, and\n\t * the actual parameter values so the caller can push them to the outer state.\n\t */\n\treadonly compileSubquery: (\n\t\tintent: QueryIntent,\n\t\tparamOffset: number,\n\t) => { sql: Node; paramCount: number; parameters?: unknown[] };\n\t/**\n\t * Optional callback to compile an ExpressionIntent to a Node.\n\t * Used by the 'expression' WHERE kind.\n\t */\n\treadonly compileExpression?: (intent: ExpressionIntent) => Node;\n\t/**\n\t * Outer table alias for outerRef() resolution in EXISTS subqueries.\n\t * When set, FieldRef with scope:'outer' resolves to this alias.\n\t */\n\treadonly outerTable?: string;\n\t/**\n\t * Override for the current alias (scope:'inner' FieldRef resolution).\n\t * Defaults to `rootTable` when not set.\n\t * Used for JOIN ON conditions where the alias differs from the root table.\n\t */\n\treadonly currentAlias?: string;\n};\n\n// ============================================================================\n// Private: bridge WhereCompilerCtx → CompilerContext\n// ============================================================================\n\nfunction toHandlerContext(ctx: WhereCompilerCtx): CompilerContext {\n\treturn {\n\t\tnaming: ctx.naming,\n\t\trootTable: ctx.rootTable,\n\t\tcurrentAlias: ctx.currentAlias ?? ctx.rootTable,\n\t\tmaxRecursiveDepth: 100,\n\t\t...(ctx.schemaName !== undefined && { schema: ctx.schemaName }),\n\t\t...(ctx.model !== undefined && { model: ctx.model }),\n\t\t...(ctx.outerTable !== undefined && { outerAlias: ctx.outerTable }),\n\t};\n}\n\n// ============================================================================\n// Public: buildSubqueryFromIntent\n// ============================================================================\n\n/**\n * Build a minimal SELECT AST node from a QueryIntent.\n *\n * Used as the `compileSubquery` callback in WhereCompilerCtx so that\n * WhereSubqueryIntent (kind: 'subquery') can compile to:\n * field OP (SELECT col FROM table [WHERE ...])\n *\n * @param intent - The inner QueryIntent describing the subquery\n * @param paramOffset - Current outer $N offset; inner WHERE params start at offset+1\n * @param naming - Naming plugin (optional, defaults to identityNaming)\n * @returns The compiled SelectStmt node and the count of parameters consumed\n */\nexport function buildSubqueryFromIntent(\n\tintent: QueryIntent,\n\tparamOffset: number,\n\tnaming: NamingPlugin = identityNaming,\n\tschemaName?: string,\n): { sql: Node; paramCount: number; parameters?: unknown[] } {\n\tconst targetTable = intent.from;\n\tconst innerAlias = `${targetTable}_sq`;\n\n\t// Build target list: SELECT col or SELECT agg(col)... or SELECT 1\n\tconst select = intent.select as\n\t\t| {\n\t\t\t\tfields?: string[];\n\t\t\t\ttype?: string;\n\t\t\t\taggregates?: { function: string; field?: string }[];\n\t\t }\n\t\t| undefined;\n\n\tlet targetList: SelectStmt['targetList'];\n\tif (\n\t\tselect?.type === 'aggregate' &&\n\t\tselect.aggregates &&\n\t\tselect.aggregates.length > 0\n\t) {\n\t\t// Build a ResTarget for EACH aggregate so multi-aggregate subqueries compile correctly.\n\t\ttargetList = select.aggregates.map((agg) => {\n\t\t\tlet aggNode: Node;\n\t\t\tif (!agg.field || agg.field === '*') {\n\t\t\t\taggNode = {\n\t\t\t\t\tFuncCall: {\n\t\t\t\t\t\tfuncname: [{ String: { sval: agg.function.toLowerCase() } }],\n\t\t\t\t\t\tagg_star: true,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tconst aggArg = columnRef(agg.field, innerAlias, undefined, naming);\n\t\t\t\taggNode = {\n\t\t\t\t\tFuncCall: {\n\t\t\t\t\t\tfuncname: [{ String: { sval: agg.function.toLowerCase() } }],\n\t\t\t\t\t\targs: [aggArg],\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { ResTarget: { val: aggNode } };\n\t\t});\n\t} else if (select?.fields?.[0]) {\n\t\ttargetList = [\n\t\t\t{\n\t\t\t\tResTarget: {\n\t\t\t\t\tval: columnRef(select.fields[0], innerAlias, undefined, naming),\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\t} else {\n\t\ttargetList = [{ ResTarget: { val: { A_Const: { ival: { ival: 1 } } } } }];\n\t}\n\n\tconst stmt: SelectStmt = {\n\t\ttargetList,\n\t\t// Bug 3 fix: propagate schema name from outer context so schema-scoped\n\t\t// queries generate \"schema\".\"table\" AS alias instead of bare \"table\" AS alias.\n\t\tfromClause: [rangeVar(targetTable, innerAlias, schemaName, naming)],\n\t};\n\n\tlet paramCount = 0;\n\tlet innerParameters: unknown[] = [];\n\n\t// Compile inner WHERE if present, using a nested WhereCompilerCtx\n\tif (intent.where) {\n\t\tconst innerState = createCompilerState();\n\t\t// Seed inner param index from outer offset so params are contiguous ($offset+1, $offset+2, ...)\n\t\tinnerState.paramIndex = paramOffset;\n\t\tconst innerCtx: WhereCompilerCtx = {\n\t\t\t// Bug 2 fix: use the alias name as rootTable so WHERE handlers emit\n\t\t\t// \"posts_sq\".\"col\" = $N instead of \"posts\".\"col\" = $N (table is aliased).\n\t\t\trootTable: innerAlias,\n\t\t\taliases: new Map(),\n\t\t\tparamState: innerState,\n\t\t\tnaming,\n\t\t\tcompileSubquery: (_nestedIntent, _nestedOffset) => {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'buildSubqueryFromIntent: nested subquery not supported',\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\t\tstmt.whereClause = compileWhereIntent(\n\t\t\tintent.where as WhereIntent,\n\t\t\tinnerCtx,\n\t\t);\n\t\t// Expose inner parameters so callers (P2-3 fix) can push them to the outer state.\n\t\tparamCount = innerState.paramIndex - paramOffset;\n\t\tinnerParameters = innerState.parameters;\n\t}\n\n\treturn { sql: { SelectStmt: stmt }, paramCount, parameters: innerParameters };\n}\n\n// ============================================================================\n// Public: compileWhereIntent\n// ============================================================================\n\n/**\n * Compile a WhereIntent directly to a PostgreSQL AST Node.\n *\n * Handles all 16 WhereIntent kinds:\n * - comparison, like, in, any, null, range\n * - and, or, not\n * - exists, notExists, relationFilter\n * - subquery, jsonContains, jsonExists, expression\n *\n * Uses the existing handler dispatch system under the hood:\n * WhereIntent → normalizeToDecision (inside createWhereDispatcher) → handler → Node\n *\n * This avoids duplicating 16 handler implementations while providing a\n * clean WhereIntent → Node API that bypasses the PlanDecision layer.\n *\n * @param intent - The WhereIntent to compile\n * @param ctx - Compiler context with table info, params, model, etc.\n * @returns PostgreSQL AST node representing the WHERE condition\n */\n\n// ============================================================================\n// Private: per-kind handlers extracted from compileWhereIntent\n// Each function handles exactly one intent.kind case.\n// ============================================================================\n\n/**\n * Handle the 'range' kind: overlaps (&&), contains (@>), containedBy (<@), between.\n * Resolves the range data type from the model when available.\n */\nfunction handleRangeIntent(\n\tintent: WhereIntent,\n\tctx: WhereCompilerCtx,\n\tdispatcher: ReturnType<typeof createWhereDispatcher>,\n\thandlerCtx: CompilerContext,\n): Node {\n\tconst { field, operator, value } = intent as {\n\t\tfield: string;\n\t\toperator: string;\n\t\tvalue: unknown;\n\t};\n\n\tlet rangeDataType: string | undefined;\n\tif (ctx.model && operator !== 'between') {\n\t\tconst table = ctx.model.getTable(ctx.rootTable);\n\t\tif (table) {\n\t\t\tconst col = table.columns.find((c) => c.name === field);\n\t\t\tif (col?.type.endsWith('range')) {\n\t\t\t\trangeDataType = col.type;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (operator === 'between') {\n\t\tconst rv = value as { lower: unknown; upper: unknown };\n\t\treturn dispatcher(\n\t\t\t{\n\t\t\t\ttype: 'where',\n\t\t\t\tcolumn: field,\n\t\t\t\toperator: 'between',\n\t\t\t\tvalue: [rv.lower, rv.upper],\n\t\t\t} as Decision,\n\t\t\thandlerCtx,\n\t\t\tctx.paramState,\n\t\t);\n\t}\n\n\treturn dispatcher(\n\t\t{\n\t\t\ttype: 'where',\n\t\t\tcolumn: field,\n\t\t\toperator,\n\t\t\tvalue,\n\t\t\t...(rangeDataType !== undefined && { dataType: rangeDataType }),\n\t\t} as Decision,\n\t\thandlerCtx,\n\t\tctx.paramState,\n\t);\n}\n\n/**\n * Handle the 'like' kind when an `escape` character is present.\n * The generic dispatcher loses the escape field via normalizeToDecision,\n * so we handle it directly to preserve LIKE $1 ESCAPE $2 semantics.\n */\nfunction handleLikeWithEscape(\n\tintent: WhereLikeIntent,\n\tctx: WhereCompilerCtx,\n\tdispatcher: ReturnType<typeof createWhereDispatcher>,\n\thandlerCtx: CompilerContext,\n): Node {\n\tconst operator = intent.caseInsensitive ? 'ilike' : 'like';\n\treturn dispatcher(\n\t\t{\n\t\t\ttype: 'where',\n\t\t\tcolumn: intent.field,\n\t\t\toperator,\n\t\t\tvalue: intent.pattern,\n\t\t\tescape: intent.escape,\n\t\t} as Decision,\n\t\thandlerCtx,\n\t\tctx.paramState,\n\t);\n}\n\n/**\n * Handle the 'expression' kind: left-side ExpressionIntent with comparison or standalone.\n * The generic dispatcher would mis-dispatch via the comparison handler (which expects column).\n */\nfunction handleExpressionIntent(\n\tintent: WhereIntent,\n\tctx: WhereCompilerCtx,\n\thandlerCtx: CompilerContext,\n): Node {\n\tconst exprIntent = intent as {\n\t\texpr: ExpressionIntent;\n\t\tvalue?: unknown;\n\t\toperator: string;\n\t};\n\n\tconst leftNode = compileExpressionIntent(\n\t\texprIntent.expr,\n\t\thandlerCtx,\n\t\tctx.paramState,\n\t);\n\n\tif (exprIntent.value === undefined) {\n\t\treturn leftNode;\n\t}\n\n\tconst idx = ++ctx.paramState.paramIndex;\n\tctx.paramState.parameters.push(exprIntent.value);\n\tconst rightNode = createParamRef(idx);\n\tconst sqlOp = OP_MAP[exprIntent.operator] ?? '=';\n\treturn binaryExpr(sqlOp, leftNode, rightNode);\n}\n\n/**\n * Handle the 'subquery' kind: field OP (SELECT ... FROM ...).\n * The generic dispatcher would fall through to the comparison handler — wrong.\n */\nfunction handleSubqueryIntent(\n\tintent: WhereIntent,\n\tctx: WhereCompilerCtx,\n\t_handlerCtx: CompilerContext,\n): Node {\n\tconst { field, operator, subquery } = intent as {\n\t\tfield: string;\n\t\toperator: string;\n\t\tsubquery: Parameters<WhereCompilerCtx['compileSubquery']>[0];\n\t};\n\n\tconst {\n\t\tsql: subqueryNode,\n\t\tparamCount,\n\t\tparameters: innerParams,\n\t} = ctx.compileSubquery(subquery, ctx.paramState.paramIndex);\n\n\tif (innerParams) {\n\t\tfor (const p of innerParams) {\n\t\t\tctx.paramState.parameters.push(p);\n\t\t}\n\t}\n\tctx.paramState.paramIndex += paramCount;\n\n\tconst leftOperand = columnRef(field, ctx.rootTable, undefined, ctx.naming);\n\tconst sqlOp = OP_MAP[operator] ?? '=';\n\n\tconst subLink: SubLink = {\n\t\tsubLinkType: 'EXPR_SUBLINK',\n\t\tsubselect: subqueryNode,\n\t};\n\treturn binaryExpr(sqlOp, leftOperand, { SubLink: subLink });\n}\n\n/**\n * Handle the 'relationFilter' kind by converting to exists/notExists and recursing.\n * The generic dispatcher would fall through to '=' handler — wrong.\n */\nfunction handleRelationFilterIntent(\n\tintent: WhereIntent,\n\tctx: WhereCompilerCtx,\n): Node {\n\tconst rf = intent as WhereRelationFilterIntent;\n\tconst relation = Array.isArray(rf.relation)\n\t\t? (rf.relation[0] as string)\n\t\t: (rf.relation as string);\n\n\t// mode:'some' → EXISTS (at least one matches)\n\t// mode:'none' → NOT EXISTS (none match)\n\t// mode:'every' → NOT EXISTS WHERE NOT condition (all match)\n\tconst existsKind =\n\t\trf.mode === 'none' || rf.mode === 'every' ? 'notExists' : 'exists';\n\tconst innerWhere: WhereIntent =\n\t\trf.mode === 'every'\n\t\t\t? ({ kind: 'not', condition: rf.where } as WhereIntent)\n\t\t\t: rf.where;\n\n\tconst resolvedRelation = ctx.model?.getRelation(\n\t\t`${ctx.rootTable}.${relation}`,\n\t);\n\tconst targetTable = resolvedRelation?.target ?? relation;\n\n\treturn compileWhereIntent(\n\t\t{\n\t\t\tkind: existsKind,\n\t\t\trelation,\n\t\t\ttargetTable,\n\t\t\twhere: innerWhere,\n\t\t} as unknown as WhereIntent,\n\t\tctx,\n\t);\n}\n\n/**\n * Handle the 'rawExists' and 'rawNotExists' kinds: EXISTS / NOT EXISTS wrappers\n * around a QueryIntent subquery. No Decision equivalent — compiled directly via\n * compileSubquery callback then wrapped in a SubLink node.\n */\nfunction handleRawExistsIntent(\n\tintent: WhereIntent,\n\tctx: WhereCompilerCtx,\n): Node {\n\tconst subIntent = (intent as WhereRawExistsIntent | WhereRawNotExistsIntent)\n\t\t.subquery;\n\tconst {\n\t\tsql: subNode,\n\t\tparamCount,\n\t\tparameters: innerParams,\n\t} = ctx.compileSubquery(subIntent, ctx.paramState.paramIndex);\n\n\tif (innerParams) {\n\t\tfor (const p of innerParams) ctx.paramState.parameters.push(p);\n\t}\n\tctx.paramState.paramIndex += paramCount;\n\n\tconst subLink = {\n\t\tSubLink: { subLinkType: 'EXISTS_SUBLINK', subselect: subNode },\n\t};\n\treturn intent.kind === 'rawNotExists'\n\t\t? notExpr(subLink as unknown as Node)\n\t\t: (subLink as unknown as Node);\n}\n\n/**\n * Handle the 'and', 'or', 'not' kinds recursively via compileWhereIntent.\n * If delegated to the dispatcher, nested 'expression' conditions would mis-dispatch.\n * Returns null when the kind is not handled here (caller falls through).\n */\nfunction handleLogicalIntent(\n\tintent: WhereIntent,\n\tctx: WhereCompilerCtx,\n): Node | null {\n\tif (intent.kind === 'and') {\n\t\tconst conditions = (intent as WhereAndIntent).conditions;\n\t\tconst nodes = conditions.map((c) => compileWhereIntent(c, ctx));\n\t\tif (nodes.length === 0) {\n\t\t\treturn {\n\t\t\t\tTypeCast: {\n\t\t\t\t\targ: { Integer: { ival: 1 } },\n\t\t\t\t\ttypeName: {\n\t\t\t\t\t\tTypeName: { names: [{ String: { sval: 'bool' } }], typemod: -1 },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t} as unknown as Node;\n\t\t}\n\t\tif (nodes.length === 1) return nodes[0]!;\n\t\treturn andExpr(...nodes);\n\t}\n\tif (intent.kind === 'or') {\n\t\tconst conditions = (intent as WhereOrIntent).conditions;\n\t\tconst nodes = conditions.map((c) => compileWhereIntent(c, ctx));\n\t\tif (nodes.length === 0) {\n\t\t\treturn {\n\t\t\t\tTypeCast: {\n\t\t\t\t\targ: { Integer: { ival: 0 } },\n\t\t\t\t\ttypeName: {\n\t\t\t\t\t\tTypeName: { names: [{ String: { sval: 'bool' } }], typemod: -1 },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t} as unknown as Node;\n\t\t}\n\t\tif (nodes.length === 1) return nodes[0]!;\n\t\treturn orExpr(...nodes);\n\t}\n\tif (intent.kind === 'not') {\n\t\treturn notExpr(\n\t\t\tcompileWhereIntent((intent as WhereNotIntent).condition, ctx),\n\t\t);\n\t}\n\treturn null;\n}\n\n/**\n * Handle the 'comparison' kind when the right-hand value is an ExpressionRef\n * or a RefDefinition (schema `ref()`).\n *\n * Two distinct right-hand types arrive here:\n * - ExpressionRef (`__expr === true`) — from `exprRef()` / expressions-layer ref\n * - RefDefinition (`__brand === 'ref'`) — from the public `ref()` exported by @dbsp/core\n *\n * Both represent a column reference (not a literal value). The generic comparison\n * handler would call buildParamRef and parameterise the object — wrong.\n *\n * ExpressionRef is a column reference: ExpressionRef → compileExpressionIntent.\n * RefDefinition carries `target` (e.g. 'filter.id') and must be compiled to\n * the column-ref path so it produces \"filter\".\"id\" in SQL.\n * Note: when a `RefDefinition` is used as a column reference here, any FK options\n * carried in `RefDefinition.options` are intentionally ignored — those only apply\n * at schema declaration time. Only `target` is consulted.\n *\n * buildColumnRef is used for the left side so that dotted field names like\n * 'users.id' are split correctly into table='users', column='id'.\n *\n * Returns null when value is neither type (caller falls through to dispatcher).\n */\nfunction handleComparisonWithExprRef(\n\tintent: WhereIntent,\n\tctx: WhereCompilerCtx,\n\thandlerCtx: CompilerContext,\n): Node | null {\n\tconst cmpIntent = intent as WhereComparisonIntent;\n\tconst v = cmpIntent.value;\n\n\tif (v === null || typeof v !== 'object') return null;\n\n\tconst rec = v as Record<string, unknown>;\n\n\t// ExpressionRef path: already has a compiled ExpressionIntent — delegate directly.\n\t// ExpressionRef implements the `ExpressionSpec` duck type: __expr === true.\n\tif (rec.__expr === true) {\n\t\tconst exprRef = v as { intent: ExpressionIntent };\n\t\t// buildColumnRef handles dotted field names like 'table.col' by splitting them.\n\t\tconst leftNode = buildColumnRef(cmpIntent.field, handlerCtx);\n\t\tconst rightNode = compileExpressionIntent(\n\t\t\texprRef.intent,\n\t\t\thandlerCtx,\n\t\t\tctx.paramState,\n\t\t);\n\t\tconst sqlOp = OP_MAP[cmpIntent.operator] ?? '=';\n\t\treturn binaryExpr(sqlOp, leftNode, rightNode);\n\t}\n\n\t// RefDefinition path: the public ref() from @dbsp/core (schema DSL) returns\n\t// { __brand: 'ref', target: 'alias.col', options: {} }. When used in an ON\n\t// clause like eq('table.col', ref('alias.col')), `target` is a dotted column\n\t// reference (table.column or just column) — compile it via RefExpressionIntent\n\t// so it produces \"alias\".\"col\" instead of being parameterised as a literal.\n\tif (rec.__brand === 'ref' && typeof rec.target === 'string') {\n\t\t// buildColumnRef handles dotted field names like 'table.col' by splitting them.\n\t\tconst leftNode = buildColumnRef(cmpIntent.field, handlerCtx);\n\t\t// Reuse the existing 'ref' kind handler via RefExpressionIntent.\n\t\t// compileExpressionIntent splits 'table.col' into qualifier + column correctly.\n\t\tconst rightNode = compileExpressionIntent(\n\t\t\t{ kind: 'ref', column: rec.target } satisfies RefExpressionIntent,\n\t\t\thandlerCtx,\n\t\t\tctx.paramState,\n\t\t);\n\t\tconst sqlOp = OP_MAP[cmpIntent.operator] ?? '=';\n\t\treturn binaryExpr(sqlOp, leftNode, rightNode);\n\t}\n\n\treturn null;\n}\n\nexport function compileWhereIntent(\n\tintent: WhereIntent,\n\tctx: WhereCompilerCtx,\n): Node {\n\tconst dispatcher = createWhereDispatcher();\n\tconst handlerCtx = toHandlerContext(ctx);\n\n\tif (intent.kind === 'range') {\n\t\treturn handleRangeIntent(intent, ctx, dispatcher, handlerCtx);\n\t}\n\tif (\n\t\tintent.kind === 'like' &&\n\t\t(intent as WhereLikeIntent).escape !== undefined\n\t) {\n\t\treturn handleLikeWithEscape(\n\t\t\tintent as WhereLikeIntent,\n\t\t\tctx,\n\t\t\tdispatcher,\n\t\t\thandlerCtx,\n\t\t);\n\t}\n\tif (intent.kind === 'expression') {\n\t\treturn handleExpressionIntent(intent, ctx, handlerCtx);\n\t}\n\tif (intent.kind === 'subquery') {\n\t\treturn handleSubqueryIntent(intent, ctx, handlerCtx);\n\t}\n\tif (intent.kind === 'relationFilter') {\n\t\treturn handleRelationFilterIntent(intent, ctx);\n\t}\n\tif (intent.kind === 'rawExists' || intent.kind === 'rawNotExists') {\n\t\treturn handleRawExistsIntent(intent, ctx);\n\t}\n\n\tconst logicalResult = handleLogicalIntent(intent, ctx);\n\tif (logicalResult !== null) return logicalResult;\n\n\tif (intent.kind === 'comparison') {\n\t\tconst exprRefResult = handleComparisonWithExprRef(intent, ctx, handlerCtx);\n\t\tif (exprRefResult !== null) return exprRefResult;\n\t}\n\n\t// Fallback to dispatcher: comparison, like, in, any, null, exists, notExists,\n\t// jsonContains, jsonExists — plus pass-through for unknown kinds.\n\tconst needsColumn = intent.kind === 'comparison' || intent.kind === 'null';\n\tconst bridged = needsColumn\n\t\t? ({\n\t\t\t\t...intent,\n\t\t\t\tcolumn: (intent as unknown as Record<string, unknown>).field,\n\t\t\t} as unknown as Decision)\n\t\t: (intent as unknown as Decision);\n\treturn dispatcher(bridged, handlerCtx, ctx.paramState);\n}\n","/**\n * Raw EXISTS / NOT EXISTS WHERE Handler\n *\n * Handles WHERE conditions using rawExists() and rawNotExists() —\n * EXISTS / NOT EXISTS wrappers around a QueryIntent subquery.\n *\n * Operators: 'rawExists', 'rawNotExists'\n * Pattern: [NOT] EXISTS (SELECT ... FROM ...)\n *\n * The inner QueryIntent is carried in decision.expressionIntent (operator\n * discriminates the kind so there is no collision with the 'expression' handler).\n *\n * Subquery compilation uses buildSubqueryFromIntent() directly — mirrors\n * handleRawExistsIntent in compile-where.ts but via the handler path.\n */\n\nimport type { QueryIntent } from '@dbsp/types';\nimport type { Node } from '@pgsql/types';\nimport { notExpr } from '../../ast-helpers.js';\nimport { buildSubqueryFromIntent } from '../../compile-where.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tWhereDispatcher,\n\tWhereHandler,\n} from '../types.js';\n\n/**\n * WHERE handler for EXISTS / NOT EXISTS subquery predicates.\n *\n * Reads the inner QueryIntent from decision.expressionIntent, compiles it\n * via buildSubqueryFromIntent, wraps in a SubLink EXISTS node, and optionally\n * negates for 'rawNotExists'.\n */\nexport const rawExistsHandler: WhereHandler = {\n\toperators: ['rawExists', 'rawNotExists'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t\t_dispatch: WhereDispatcher,\n\t): Node {\n\t\tconst subIntent = decision.expressionIntent as QueryIntent;\n\n\t\t// Fail-fast contract: parameters and paramIndex are mutated unconditionally\n\t\t// before the deparser emits anything. If buildSubqueryFromIntent throws\n\t\t// (e.g. nested rawExists hitting \"nested subquery not supported\"), the\n\t\t// outer state may be left with bumped paramIndex. We do NOT roll back —\n\t\t// callers must let the throw propagate, not catch-and-recover. Same\n\t\t// contract as the mutation path.\n\t\tconst {\n\t\t\tsql: subNode,\n\t\t\tparamCount,\n\t\t\tparameters: innerParams,\n\t\t} = buildSubqueryFromIntent(\n\t\t\tsubIntent,\n\t\t\tstate.paramIndex,\n\t\t\tctx.naming,\n\t\t\tctx.schema,\n\t\t);\n\n\t\tif (innerParams) {\n\t\t\tfor (const p of innerParams) {\n\t\t\t\tstate.parameters.push(p);\n\t\t\t}\n\t\t}\n\t\tstate.paramIndex += paramCount;\n\n\t\tconst subLink = {\n\t\t\tSubLink: { subLinkType: 'EXISTS_SUBLINK', subselect: subNode },\n\t\t} as unknown as Node;\n\n\t\treturn decision.operator === 'rawNotExists' ? notExpr(subLink) : subLink;\n\t},\n};\n","/**\n * Relation Filter Handler\n *\n * Handles filtering by related records using:\n * - some: At least one related record matches (EXISTS)\n * - none: No related records match (NOT EXISTS)\n * - every: All related records match (NOT EXISTS ... WHERE NOT)\n * - is: Related record matches exactly (JOIN + conditions)\n *\n * This handler acts as a higher-level abstraction that routes to\n * the appropriate underlying handler (EXISTS, JOIN, etc.)\n */\n\nimport type { JoinExpr, Node } from '@pgsql/types';\nimport {\n\tDEFAULT_PK_COLUMN,\n\tdefaultFkDerivation,\n\trequiredColumn,\n} from '../../assert-field.js';\nimport { columnRef, eqExpr, rangeVar } from '../../ast-helpers.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tWhereDispatcher,\n\tWhereHandler,\n} from '../types.js';\n\n/**\n * Relation filter mode\n */\ntype FilterMode = 'some' | 'none' | 'every' | 'is' | 'isNot';\n\n/**\n * Determine the filter mode from the decision\n */\nfunction getFilterMode(decision: Decision): FilterMode {\n\tconst operator = decision.operator;\n\tif (operator === 'some' || operator === 'exists') return 'some';\n\tif (operator === 'none' || operator === 'notExists') return 'none';\n\tif (operator === 'every') return 'every';\n\tif (operator === 'isNot') return 'isNot';\n\treturn 'is';\n}\n\n/**\n * Build a JOIN-based filter for 'is' mode (single related record match)\n *\n * This produces a JOIN condition rather than a subquery, which can be\n * more efficient for single-record relationships (belongsTo, hasOne)\n */\nfunction buildJoinFilter(\n\tdecision: Decision,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n\tdispatch: WhereDispatcher,\n): Node {\n\tconst relation = decision.relation;\n\tconst targetTable = decision.targetTable ?? relation;\n\tconst sourceColumn = requiredColumn(\n\t\tdecision.sourceColumn,\n\t\t'sourceColumn',\n\t\t'relation filter',\n\t);\n\tconst targetColumn =\n\t\tdecision.targetColumn ??\n\t\t(ctx.deriveFkColumnName ?? defaultFkDerivation)(\n\t\t\tctx.rootTable,\n\t\t\tctx.defaultPkColumnName ?? DEFAULT_PK_COLUMN,\n\t\t);\n\n\tif (!targetTable) {\n\t\tthrow new Error('Relation filter requires targetTable');\n\t}\n\n\t// Generate unique alias\n\tconst existingAliases = state.aliases.size;\n\tconst targetAlias = `${targetTable}_rel_${existingAliases}`;\n\tstate.aliases.set(`rel_${targetTable}`, targetAlias);\n\n\tconst sourceAlias = ctx.currentAlias ?? ctx.rootTable;\n\n\t// Build join condition: source.column = target.column\n\tconst joinCondition = eqExpr(\n\t\tcolumnRef(sourceColumn, sourceAlias, ctx.schema, ctx.naming),\n\t\tcolumnRef(targetColumn, targetAlias, ctx.schema, ctx.naming),\n\t);\n\n\t// Build a proper JoinExpr node\n\t// Note: The left arg (larg) will be set by the compiler when constructing the full FROM clause\n\tconst joinExpr: JoinExpr = {\n\t\tjointype: 'JOIN_INNER',\n\t\trarg: rangeVar(targetTable, targetAlias, ctx.schema, ctx.naming),\n\t\tquals: joinCondition,\n\t};\n\n\t// Track the join for the compiler\n\tstate.joins.push({ JoinExpr: joinExpr });\n\n\t// If there are additional conditions on the relation, compile them\n\tif (decision.conditions && decision.conditions.length > 0) {\n\t\tconst subCtx: CompilerContext = {\n\t\t\t...ctx,\n\t\t\trootTable: targetTable,\n\t\t\tcurrentAlias: targetAlias,\n\t\t};\n\n\t\tif (decision.conditions.length === 1) {\n\t\t\treturn dispatch(decision.conditions[0]!, subCtx, state);\n\t\t}\n\n\t\tconst compiledConditions = decision.conditions.map((cond) =>\n\t\t\tdispatch(cond, subCtx, state),\n\t\t);\n\n\t\treturn {\n\t\t\tBoolExpr: {\n\t\t\t\tboolop: 'AND_EXPR',\n\t\t\t\targs: compiledConditions,\n\t\t\t},\n\t\t};\n\t}\n\n\t// No additional conditions, return a TRUE constant\n\t// (the join itself is the filter)\n\treturn { A_Const: { boolval: { boolval: true } } };\n}\n\n/**\n * Relation filter handler\n *\n * Routes to EXISTS-based or JOIN-based filtering depending on the mode\n */\nexport const relationFilterHandler: WhereHandler = {\n\toperators: ['relationFilter', 'relation', 'is', 'isNot'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t\tdispatch: WhereDispatcher,\n\t): Node {\n\t\tconst mode = getFilterMode(decision);\n\n\t\t// For 'some', 'none', 'every' - delegate to EXISTS handlers\n\t\t// These are registered separately and will be dispatched by the main dispatcher\n\t\tif (mode === 'some' || mode === 'none' || mode === 'every') {\n\t\t\t// Transform to EXISTS-style decision\n\t\t\tconst existsDecision: Decision = {\n\t\t\t\t...decision,\n\t\t\t\ttype: 'exists',\n\t\t\t\toperator:\n\t\t\t\t\tmode === 'some' ? 'exists' : mode === 'none' ? 'notExists' : 'every',\n\t\t\t};\n\t\t\treturn dispatch(existsDecision, ctx, state);\n\t\t}\n\n\t\t// For 'is' or 'isNot' - use JOIN-based filtering\n\t\tconst joinFilter = buildJoinFilter(decision, ctx, state, dispatch);\n\n\t\tif (mode === 'isNot') {\n\t\t\t// Negate the condition\n\t\t\treturn {\n\t\t\t\tBoolExpr: {\n\t\t\t\t\tboolop: 'NOT_EXPR',\n\t\t\t\t\targs: [joinFilter],\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn joinFilter;\n\t},\n};\n\n/**\n * Has-relation filter (sugar for relationFilter with some mode)\n */\nexport const hasRelationHandler: WhereHandler = {\n\toperators: ['has', 'hasRelation'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t\tdispatch: WhereDispatcher,\n\t): Node {\n\t\tconst existsDecision: Decision = {\n\t\t\t...decision,\n\t\t\ttype: 'exists',\n\t\t\toperator: 'exists',\n\t\t};\n\t\treturn dispatch(existsDecision, ctx, state);\n\t},\n};\n\n/**\n * Has-no-relation filter (sugar for relationFilter with none mode)\n */\nexport const hasNoRelationHandler: WhereHandler = {\n\toperators: ['hasNo', 'hasNoRelation'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t\tdispatch: WhereDispatcher,\n\t): Node {\n\t\tconst notExistsDecision: Decision = {\n\t\t\t...decision,\n\t\t\ttype: 'exists',\n\t\t\toperator: 'notExists',\n\t\t};\n\t\treturn dispatch(notExistsDecision, ctx, state);\n\t},\n};\n","/**\n * Subquery Operators Handler\n *\n * Handles scalar subquery comparisons like:\n * - WHERE price > (SELECT AVG(price) FROM products)\n * - WHERE id IN (SELECT user_id FROM active_users)\n */\n\nimport type {\n\tA_Expr,\n\tA_Expr_Kind,\n\tNode,\n\tSelectStmt,\n\tSubLink,\n} from '@pgsql/types';\nimport { columnRef, integerNode, rangeVar, sortBy } from '../../ast-helpers.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tWhereDispatcher,\n\tWhereHandler,\n} from '../types.js';\n\n/**\n * Map comparison operators to their PostgreSQL equivalents\n */\nconst PG_OPERATOR_MAP: Record<string, string> = {\n\t'=': '=',\n\t'!=': '<>',\n\t'<': '<',\n\t'<=': '<=',\n\t'>': '>',\n\t'>=': '>=',\n};\n\n/**\n * Create an A_Expr node for scalar subquery comparison.\n * Uses A_Expr with AEXPR_OP instead of SubLink.testexpr because\n * pgsql-deparser doesn't deparse EXPR_SUBLINK.testexpr/operName correctly.\n *\n * Result: lexpr OP (SELECT ... FROM ...)\n */\nfunction createScalarSubLink(\n\tsubquery: Node,\n\toperator: string,\n\tleftOperand: Node,\n): Node {\n\t// Wrap subquery in SubLink node for EXPR_SUBLINK\n\tconst subLink: SubLink = {\n\t\tsubLinkType: 'EXPR_SUBLINK',\n\t\tsubselect: subquery,\n\t};\n\n\t// Build A_Expr: column OP (subquery)\n\tconst expr: A_Expr = {\n\t\tkind: 'AEXPR_OP' as A_Expr_Kind,\n\t\tname: [{ String: { sval: PG_OPERATOR_MAP[operator] ?? operator } }],\n\t\tlexpr: leftOperand,\n\t\trexpr: { SubLink: subLink },\n\t};\n\n\treturn { A_Expr: expr };\n}\n\n/**\n * Build a simple SELECT subquery from a table\n *\n * SELECT aggregate(column) FROM table [WHERE conditions]\n */\nfunction buildScalarSubquery(\n\tdecision: Decision,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n\tdispatch: WhereDispatcher,\n): Node {\n\tconst targetTable = decision.targetTable ?? decision.relation;\n\tconst selectColumn = decision.selectColumn ?? '*';\n\tconst aggregate = decision.aggregate;\n\n\tif (!targetTable) {\n\t\tthrow new Error('Subquery handler requires targetTable');\n\t}\n\n\t// Generate unique alias\n\tconst existingAliases = state.aliases.size;\n\tconst targetAlias = `${targetTable}_subq_${existingAliases}`;\n\tstate.aliases.set(`subquery_${targetTable}`, targetAlias);\n\n\t// Build target list (what to select)\n\tlet targetVal: Node;\n\tif (aggregate) {\n\t\t// SELECT COUNT(*), AVG(column), etc.\n\t\tif (selectColumn === '*') {\n\t\t\t// Aggregate with star (e.g., COUNT(*))\n\t\t\ttargetVal = {\n\t\t\t\tFuncCall: {\n\t\t\t\t\tfuncname: [{ String: { sval: aggregate.toLowerCase() } }],\n\t\t\t\t\tagg_star: true,\n\t\t\t\t},\n\t\t\t};\n\t\t} else {\n\t\t\t// Aggregate with column (e.g., AVG(price))\n\t\t\t// Alias is query-scoped, not schema-qualified\n\t\t\tconst aggArg = columnRef(\n\t\t\t\tselectColumn,\n\t\t\t\ttargetAlias,\n\t\t\t\tundefined,\n\t\t\t\tctx.naming,\n\t\t\t);\n\t\t\ttargetVal = {\n\t\t\t\tFuncCall: {\n\t\t\t\t\tfuncname: [{ String: { sval: aggregate.toLowerCase() } }],\n\t\t\t\t\targs: [aggArg],\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t} else {\n\t\t// SELECT column — alias is query-scoped, not schema-qualified\n\t\ttargetVal = columnRef(selectColumn, targetAlias, undefined, ctx.naming);\n\t}\n\n\t// Build WHERE clause if conditions exist\n\tlet whereClause: Node | undefined;\n\tif (decision.conditions && decision.conditions.length > 0) {\n\t\t// Strip schema — nested conditions reference the aliased table\n\t\tconst { schema: _schema, ...ctxWithoutSchema } = ctx;\n\t\tconst subCtx: CompilerContext = {\n\t\t\t...ctxWithoutSchema,\n\t\t\trootTable: targetTable,\n\t\t\tcurrentAlias: targetAlias,\n\t\t};\n\n\t\tif (decision.conditions.length === 1) {\n\t\t\twhereClause = dispatch(decision.conditions[0]!, subCtx, state);\n\t\t} else {\n\t\t\tconst compiledConditions = decision.conditions.map((cond) =>\n\t\t\t\tdispatch(cond, subCtx, state),\n\t\t\t);\n\t\t\twhereClause = {\n\t\t\t\tBoolExpr: {\n\t\t\t\t\tboolop: 'AND_EXPR',\n\t\t\t\t\targs: compiledConditions,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\tconst stmt: SelectStmt = {\n\t\ttargetList: [{ ResTarget: { val: targetVal } }],\n\t\tfromClause: [rangeVar(targetTable, targetAlias, ctx.schema, ctx.naming)],\n\t\t...(whereClause && { whereClause }),\n\t};\n\n\t// Add ORDER BY if present\n\tif (decision.orderBy && decision.orderBy.length > 0) {\n\t\tstmt.sortClause = decision.orderBy.map((o) =>\n\t\t\tsortBy(\n\t\t\t\tcolumnRef(o.column, targetAlias, undefined, ctx.naming),\n\t\t\t\to.direction ?? 'ASC',\n\t\t\t\t'DEFAULT',\n\t\t\t),\n\t\t);\n\t}\n\n\t// Add LIMIT if present\n\tif (decision.limit != null) {\n\t\tif (typeof decision.limit === 'number') {\n\t\t\tstmt.limitCount = integerNode(decision.limit);\n\t\t} else {\n\t\t\tconst limitObj = decision.limit as Record<string, unknown>;\n\t\t\tif (typeof limitObj.paramIndex !== 'number') {\n\t\t\t\tthrow new Error('limit.paramIndex must be a number');\n\t\t\t}\n\t\t\t// Emit a parameter reference ($N) not the literal index integer\n\t\t\tstmt.limitCount = {\n\t\t\t\tParamRef: { number: limitObj.paramIndex },\n\t\t\t} as unknown as Node;\n\t\t}\n\t}\n\n\treturn { SelectStmt: stmt };\n}\n\n/**\n * Scalar subquery comparison handler\n *\n * Handles: column OP (SELECT ... FROM ...)\n * Where OP is =, !=, <, <=, >, >=\n */\nexport const scalarSubqueryHandler: WhereHandler = {\n\toperators: [\n\t\t'scalarSubquery',\n\t\t'subqueryEq',\n\t\t'subqueryNeq',\n\t\t'subqueryLt',\n\t\t'subqueryLte',\n\t\t'subqueryGt',\n\t\t'subqueryGte',\n\t],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t\tdispatch: WhereDispatcher,\n\t): Node {\n\t\tconst column = decision.column;\n\t\tconst operator = decision.subqueryOperator ?? '=';\n\n\t\tif (!column) {\n\t\t\tthrow new Error('Scalar subquery requires column');\n\t\t}\n\n\t\tconst sourceAlias = ctx.currentAlias ?? ctx.rootTable;\n\t\tconst leftOperand = columnRef(column, sourceAlias, undefined, ctx.naming);\n\t\tconst subquery = buildScalarSubquery(decision, ctx, state, dispatch);\n\n\t\treturn createScalarSubLink(subquery, operator, leftOperand);\n\t},\n};\n\n/**\n * IN subquery handler\n *\n * Handles: column IN (SELECT ... FROM ...)\n */\nexport const inSubqueryHandler: WhereHandler = {\n\toperators: ['inSubquery'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t\tdispatch: WhereDispatcher,\n\t): Node {\n\t\tconst column = decision.column;\n\n\t\tif (!column) {\n\t\t\tthrow new Error('IN subquery requires column');\n\t\t}\n\n\t\tconst sourceAlias = ctx.currentAlias ?? ctx.rootTable;\n\t\tconst leftOperand = columnRef(column, sourceAlias, undefined, ctx.naming);\n\t\tconst subquery = buildScalarSubquery(decision, ctx, state, dispatch);\n\n\t\tconst subLink: SubLink = {\n\t\t\tsubLinkType: 'ANY_SUBLINK',\n\t\t\tsubselect: subquery,\n\t\t\ttestexpr: leftOperand,\n\t\t\toperName: [{ String: { sval: '=' } }],\n\t\t};\n\n\t\treturn { SubLink: subLink };\n\t},\n};\n\n/**\n * NOT IN subquery handler\n *\n * Handles: column NOT IN (SELECT ... FROM ...)\n */\nexport const notInSubqueryHandler: WhereHandler = {\n\toperators: ['notInSubquery'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t\tdispatch: WhereDispatcher,\n\t): Node {\n\t\tconst column = decision.column;\n\n\t\tif (!column) {\n\t\t\tthrow new Error('NOT IN subquery requires column');\n\t\t}\n\n\t\tconst sourceAlias = ctx.currentAlias ?? ctx.rootTable;\n\t\tconst leftOperand = columnRef(column, sourceAlias, undefined, ctx.naming);\n\t\tconst subquery = buildScalarSubquery(decision, ctx, state, dispatch);\n\n\t\tconst subLink: SubLink = {\n\t\t\tsubLinkType: 'ALL_SUBLINK',\n\t\t\tsubselect: subquery,\n\t\t\ttestexpr: leftOperand,\n\t\t\toperName: [{ String: { sval: '<>' } }],\n\t\t};\n\n\t\treturn { SubLink: subLink };\n\t},\n};\n","/**\n * WHERE Handlers Registration\n *\n * Exports all WHERE handlers and provides a function to register them all.\n */\n\nimport { registerWhereHandler } from '../index.js';\nimport { anyHandler } from './any.js';\n// Handler imports - simple\nimport { betweenHandler } from './between.js';\nimport { comparisonHandler } from './comparison.js';\nimport { customExpressionWhereHandler } from './custom-expression.js';\n// Handler imports - complex (exists, subquery, relation)\nimport { everyHandler, existsHandler, notExistsHandler } from './exists.js';\nimport { inHandler } from './in.js';\nimport {\n\tjsonComparisonHandler,\n\tjsonContainsHandler,\n\tjsonExistsHandler,\n} from './json.js';\nimport { likeHandler } from './like.js';\nimport { andHandler, notHandler, orHandler } from './logical.js';\nimport { nullHandler } from './null.js';\nimport { rangeHandler } from './range.js';\nimport { rawExistsHandler } from './raw-exists.js';\nimport {\n\thasNoRelationHandler,\n\thasRelationHandler,\n\trelationFilterHandler,\n} from './relation-filter.js';\nimport {\n\tinSubqueryHandler,\n\tnotInSubqueryHandler,\n\tscalarSubqueryHandler,\n} from './subquery.js';\n\nexport { anyHandler } from './any.js';\n// Re-export individual handlers\nexport { betweenHandler } from './between.js';\nexport { comparisonHandler } from './comparison.js';\nexport { customExpressionWhereHandler } from './custom-expression.js';\nexport { everyHandler, existsHandler, notExistsHandler } from './exists.js';\nexport { inHandler } from './in.js';\nexport {\n\tjsonComparisonHandler,\n\tjsonContainsHandler,\n\tjsonExistsHandler,\n} from './json.js';\nexport { likeHandler } from './like.js';\nexport { andHandler, notHandler, orHandler } from './logical.js';\nexport { nullHandler } from './null.js';\nexport { rangeHandler } from './range.js';\nexport { rawExistsHandler } from './raw-exists.js';\nexport {\n\thasNoRelationHandler,\n\thasRelationHandler,\n\trelationFilterHandler,\n} from './relation-filter.js';\nexport {\n\tinSubqueryHandler,\n\tnotInSubqueryHandler,\n\tscalarSubqueryHandler,\n} from './subquery.js';\n\n/**\n * All simple WHERE handlers\n */\nexport const simpleWhereHandlers = [\n\tcustomExpressionWhereHandler,\n\tcomparisonHandler,\n\tlikeHandler,\n\tnullHandler,\n\tanyHandler,\n\tinHandler,\n\tandHandler,\n\torHandler,\n\tnotHandler,\n\tbetweenHandler,\n\trangeHandler,\n\tjsonContainsHandler,\n\tjsonExistsHandler,\n\tjsonComparisonHandler,\n];\n\n/**\n * Complex WHERE handlers (relation filtering, subqueries)\n */\nexport const complexWhereHandlers = [\n\t// EXISTS-based\n\texistsHandler,\n\tnotExistsHandler,\n\teveryHandler,\n\trawExistsHandler,\n\t// Subquery-based\n\tscalarSubqueryHandler,\n\tinSubqueryHandler,\n\tnotInSubqueryHandler,\n\t// Relation filters\n\trelationFilterHandler,\n\thasRelationHandler,\n\thasNoRelationHandler,\n];\n\n/**\n * All WHERE handlers\n */\nexport const allWhereHandlers = [\n\t...simpleWhereHandlers,\n\t...complexWhereHandlers,\n];\n\n/**\n * Register all simple WHERE handlers.\n * Should be called once at module initialization.\n */\nexport function registerSimpleWhereHandlers(): void {\n\tfor (const handler of simpleWhereHandlers) {\n\t\tregisterWhereHandler(handler);\n\t}\n}\n\n/**\n * Register all WHERE handlers (simple + complex).\n * Should be called once at module initialization.\n */\nexport function registerAllWhereHandlers(): void {\n\tfor (const handler of allWhereHandlers) {\n\t\tregisterWhereHandler(handler);\n\t}\n}\n","/**\n * CTE Include Strategy Handler\n *\n * Implements the 'cte' include strategy using Common Table Expressions.\n * Pre-fetches related data in a CTE, then joins with the main query.\n *\n * Produces: WITH relation_cte AS (SELECT ... FROM related) SELECT ... JOIN relation_cte\n */\n\nimport type { CommonTableExpr, JoinExpr, Node, SelectStmt } from '@pgsql/types';\nimport {\n\tDEFAULT_PK_COLUMN,\n\tdefaultFkDerivation,\n\trequiredColumn,\n} from '../../assert-field.js';\nimport {\n\tcolumnRef,\n\tfkCorrelation,\n\trangeVar,\n\tstarTarget,\n} from '../../ast-helpers.js';\nimport { createWhereDispatcher } from '../index.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tIncludeHandler,\n\tIncludeResult,\n} from '../types.js';\n\n/**\n * Build column targets for CTE\n */\nfunction buildCteTargets(\n\tcolumns: readonly string[] | undefined,\n\talias: string,\n\tctx: CompilerContext,\n): Node[] {\n\tif (columns && columns.length > 0 && !columns.every((c) => c === '*')) {\n\t\treturn columns\n\t\t\t.filter((col) => col !== '*')\n\t\t\t.map((col) => ({\n\t\t\t\tResTarget: {\n\t\t\t\t\tval: columnRef(col, alias, undefined, ctx.naming),\n\t\t\t\t\tname: ctx.naming.toDatabase(col),\n\t\t\t\t},\n\t\t\t}));\n\t}\n\n\t// Select all columns\n\treturn [starTarget(alias, ctx.naming)];\n}\n\n/**\n * Build the CTE SELECT statement\n */\nfunction buildCteSelect(\n\ttargetTable: string,\n\tinnerAlias: string,\n\tcolumns: readonly string[] | undefined,\n\twhereConditions: readonly Decision[] | undefined,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): Node {\n\tconst targetList = buildCteTargets(columns, innerAlias, ctx);\n\n\t// Build WHERE if conditions exist\n\tlet whereClause: Node | undefined;\n\tif (whereConditions && whereConditions.length > 0) {\n\t\tconst dispatch = createWhereDispatcher();\n\n\t\tconst subCtx: CompilerContext = {\n\t\t\t...ctx,\n\t\t\trootTable: targetTable,\n\t\t\tcurrentAlias: innerAlias,\n\t\t};\n\n\t\tif (whereConditions.length === 1) {\n\t\t\twhereClause = dispatch(whereConditions[0]!, subCtx, state);\n\t\t} else {\n\t\t\tconst conditions = whereConditions.map((cond) =>\n\t\t\t\tdispatch(cond, subCtx, state),\n\t\t\t);\n\t\t\twhereClause = {\n\t\t\t\tBoolExpr: {\n\t\t\t\t\tboolop: 'AND_EXPR',\n\t\t\t\t\targs: conditions,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\tconst stmt: SelectStmt = {\n\t\ttargetList,\n\t\tfromClause: [rangeVar(targetTable, innerAlias, ctx.schema, ctx.naming)],\n\t\t...(whereClause && { whereClause }),\n\t};\n\n\treturn { SelectStmt: stmt };\n}\n\n/**\n * Build a CommonTableExpr node\n */\nfunction buildCTE(\n\tcteName: string,\n\tcteSelect: Node,\n\tctx: CompilerContext,\n): Node {\n\tconst cte: CommonTableExpr = {\n\t\tctename: ctx.naming.toDatabase(cteName),\n\t\tctequery: cteSelect,\n\t};\n\n\treturn { CommonTableExpr: cte };\n}\n\n/**\n * Build a LEFT JOIN to the CTE\n */\nfunction buildCteJoin(\n\tcteName: string,\n\tcteAlias: string,\n\tsourceAlias: string,\n\tsourceColumn: string,\n\ttargetColumn: string,\n\tctx: CompilerContext,\n): Node {\n\t// Join condition: source.fk = cte.pk\n\tconst joinCondition = fkCorrelation(\n\t\tsourceColumn,\n\t\tsourceAlias,\n\t\ttargetColumn,\n\t\tcteAlias,\n\t\tctx.naming,\n\t);\n\n\t// Reference the CTE as if it were a table\n\tconst cteRef: Node = {\n\t\tRangeVar: {\n\t\t\trelname: ctx.naming.toDatabase(cteName),\n\t\t\tinh: true,\n\t\t\trelpersistence: 'p',\n\t\t\talias: { aliasname: ctx.naming.toDatabase(cteAlias) },\n\t\t},\n\t};\n\n\tconst joinExpr: JoinExpr = {\n\t\tjointype: 'JOIN_LEFT',\n\t\trarg: cteRef,\n\t\tquals: joinCondition,\n\t};\n\n\treturn { JoinExpr: joinExpr };\n}\n\n/**\n * CTE strategy include handler\n *\n * Uses Common Table Expression to pre-fetch related data.\n * Best for: Complex filtering or multiple references to same relation.\n *\n * Advantages:\n * - CTE is computed once, can be referenced multiple times\n * - Clear query structure\n * - Good for complex transformations on related data\n *\n * Disadvantages:\n * - PostgreSQL CTEs are optimization barriers (before PG12)\n * - More verbose SQL\n */\nexport const cteIncludeHandler: IncludeHandler = {\n\tstrategy: 'cte',\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): IncludeResult {\n\t\tconst relation = decision.relation;\n\t\tconst targetTable = decision.targetTable ?? relation;\n\t\tconst sourceColumn = requiredColumn(\n\t\t\tdecision.sourceColumn,\n\t\t\t'sourceColumn',\n\t\t\t'CTE include',\n\t\t);\n\t\tconst targetColumn =\n\t\t\tdecision.targetColumn ??\n\t\t\t(ctx.deriveFkColumnName ?? defaultFkDerivation)(\n\t\t\t\tctx.rootTable,\n\t\t\t\tctx.defaultPkColumnName ?? DEFAULT_PK_COLUMN,\n\t\t\t);\n\t\tconst columns = decision.columns;\n\t\tconst conditions = decision.conditions;\n\n\t\tif (!targetTable) {\n\t\t\tthrow new Error('CTE include requires targetTable');\n\t\t}\n\n\t\tif (!relation) {\n\t\t\tthrow new Error('CTE include requires relation name');\n\t\t}\n\n\t\t// Generate unique names\n\t\tconst existingAliases = state.aliases.size;\n\t\tconst cteName = `${relation}_cte`;\n\t\tconst innerAlias = `${targetTable}_inner_${existingAliases}`;\n\t\tconst cteAlias = `${relation}_ref_${existingAliases}`;\n\t\tstate.aliases.set(`cte_${targetTable}`, cteName);\n\n\t\tconst outerAlias = ctx.currentAlias ?? ctx.rootTable;\n\n\t\t// Build the CTE SELECT\n\t\tconst cteSelect = buildCteSelect(\n\t\t\ttargetTable,\n\t\t\tinnerAlias,\n\t\t\tcolumns,\n\t\t\tconditions,\n\t\t\tctx,\n\t\t\tstate,\n\t\t);\n\n\t\t// Build the CTE node\n\t\tconst cte = buildCTE(cteName, cteSelect, ctx);\n\n\t\t// Register CTE in state for WITH clause\n\t\tstate.ctes.set(cteName, cte);\n\n\t\t// Build JOIN to the CTE\n\t\tconst join = buildCteJoin(\n\t\t\tcteName,\n\t\t\tcteAlias,\n\t\t\touterAlias,\n\t\t\tsourceColumn,\n\t\t\ttargetColumn,\n\t\t\tctx,\n\t\t);\n\n\t\treturn {\n\t\t\tcte,\n\t\t\tjoin,\n\t\t};\n\t},\n};\n","/**\n * JOIN Include Strategy Handler\n *\n * Implements the 'join' include strategy using LEFT JOIN (default) or INNER JOIN.\n * This is the simplest strategy: adds a JOIN to the FROM clause.\n *\n * Produces: LEFT JOIN related_table AS relation ON source.fk = related.pk (default)\n * or: INNER JOIN related_table AS relation ON source.fk = related.pk (join: 'inner')\n * With aliased columns: \"relation.column\" for hydration\n */\n\nimport type { JoinExpr, Node } from '@pgsql/types';\nimport {\n\tDEFAULT_PK_COLUMN,\n\tdefaultFkDerivation,\n\trequiredColumn,\n} from '../../assert-field.js';\nimport {\n\tcolumnTarget,\n\tfkCorrelation,\n\trangeVar,\n\tstarTarget,\n} from '../../ast-helpers.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tIncludeHandler,\n\tIncludeResult,\n} from '../types.js';\n\n/**\n * Build a JOIN expression (LEFT JOIN by default, INNER JOIN when joinType='inner').\n */\nfunction buildJoin(\n\ttargetTable: string,\n\ttargetAlias: string,\n\tsourceAlias: string,\n\tsourceColumn: string,\n\ttargetColumn: string,\n\tctx: CompilerContext,\n\tjoinType: 'inner' | 'left' = 'left',\n): Node {\n\t// Build the join condition: source.sourceColumn = target.targetColumn\n\tconst joinCondition = fkCorrelation(\n\t\tsourceColumn,\n\t\tsourceAlias,\n\t\ttargetColumn,\n\t\ttargetAlias,\n\t\tctx.naming,\n\t);\n\n\tconst joinExpr: JoinExpr = {\n\t\tjointype: joinType === 'inner' ? 'JOIN_INNER' : 'JOIN_LEFT',\n\t\trarg: rangeVar(targetTable, targetAlias, ctx.schema, ctx.naming),\n\t\tquals: joinCondition,\n\t};\n\n\treturn { JoinExpr: joinExpr };\n}\n\n/**\n * JOIN strategy include handler\n *\n * Adds a LEFT JOIN to fetch related records.\n * Best for: hasOne, belongsTo relationships (1:1 or N:1)\n *\n * Note: May cause row explosion for hasMany (1:N) relationships.\n */\nexport const joinIncludeHandler: IncludeHandler = {\n\tstrategy: 'join',\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\t_state: CompilerState,\n\t): IncludeResult {\n\t\tconst relation = decision.relation;\n\t\tconst targetTable = decision.targetTable ?? relation;\n\n\t\tif (!targetTable) {\n\t\t\tthrow new Error('JOIN include requires targetTable');\n\t\t}\n\n\t\t// Use relationName as alias for uniqueness\n\t\t// (e.g., \"author\" and \"editor\" both from \"users\")\n\t\tconst targetAlias = relation ?? targetTable;\n\t\tconst sourceAlias = ctx.currentAlias ?? ctx.rootTable;\n\t\tconst sourceColumn = requiredColumn(\n\t\t\tdecision.sourceColumn,\n\t\t\t'sourceColumn',\n\t\t\t'JOIN include',\n\t\t);\n\t\tconst targetColumn =\n\t\t\tdecision.targetColumn ??\n\t\t\t(ctx.deriveFkColumnName ?? defaultFkDerivation)(\n\t\t\t\tctx.rootTable,\n\t\t\t\tctx.defaultPkColumnName ?? DEFAULT_PK_COLUMN,\n\t\t\t);\n\n\t\t// Build the JOIN (LEFT or INNER based on decision.joinType)\n\t\tconst join = buildJoin(\n\t\t\ttargetTable,\n\t\t\ttargetAlias,\n\t\t\tsourceAlias,\n\t\t\tsourceColumn,\n\t\t\ttargetColumn,\n\t\t\tctx,\n\t\t\tdecision.joinType ?? 'left',\n\t\t);\n\n\t\t// Build column targets with output aliases for hydration.\n\t\t// Prefer user-supplied alias from columnAliases; fall back to\n\t\t// the \"relation.column\" convention used by the hydration layer.\n\t\tconst targets: Node[] = [];\n\t\tconst columns = decision.columns;\n\t\tconst columnAliases = decision.columnAliases;\n\t\tif (columns && columns.length > 0) {\n\t\t\tif (columns.length === 1 && columns[0] === '*') {\n\t\t\t\t// Wildcard: select all columns from the joined relation\n\t\t\t\ttargets.push(starTarget(targetAlias, ctx.naming));\n\t\t\t} else {\n\t\t\t\tfor (const col of columns) {\n\t\t\t\t\tconst outputAlias = columnAliases?.[col] ?? `${relation}.${col}`;\n\t\t\t\t\ttargets.push(columnTarget(col, outputAlias, targetAlias, ctx.naming));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tjoin,\n\t\t\t...(targets.length > 0 && { targets }),\n\t\t};\n\t},\n};\n","/**\n * Shared utilities for include strategy handlers.\n *\n * Extracted from lateral.ts and json-agg.ts to eliminate FK direction duplication.\n */\n\nimport {\n\tDEFAULT_PK_COLUMN,\n\tdefaultFkDerivation,\n\ttype FkColumnDerivation,\n} from '../../assert-field.js';\n/** Minimal shape required by deriveFkColumns — works with both Decision and PlanDecision. */\nexport interface FkColumnSource {\n\treadonly relationType?: 'belongsTo' | 'hasMany' | 'hasOne';\n\treadonly foreignKey?: string;\n\treadonly parentKey?: string;\n\treadonly targetTable?: string;\n}\n\n/**\n * Derive the source (parent-side) and target (child-side) column names\n * based on the relation type and FK configuration.\n *\n * For belongsTo: the FK is on the parent side (e.g., user_roles.role_id → roles.id)\n * → sourceColumn = foreignKey (role_id), targetColumn = parentKey (id)\n * For hasMany/hasOne: the FK is on the child side (e.g., roles.id ← role_permissions.role_id)\n * → sourceColumn = parentKey (id), targetColumn = foreignKey (role_id)\n */\nexport function deriveFkColumns(\n\tdecision: FkColumnSource,\n\tparentTable: string,\n\tdefaultPk: string = DEFAULT_PK_COLUMN,\n\tderiveFk: FkColumnDerivation = defaultFkDerivation,\n): { sourceColumn: string; targetColumn: string } {\n\tif (decision.relationType === 'belongsTo') {\n\t\treturn {\n\t\t\tsourceColumn:\n\t\t\t\tdecision.foreignKey ??\n\t\t\t\t(decision.targetTable\n\t\t\t\t\t? deriveFk(decision.targetTable, defaultPk)\n\t\t\t\t\t: defaultPk),\n\t\t\ttargetColumn: decision.parentKey ?? defaultPk,\n\t\t};\n\t}\n\t// hasMany or hasOne\n\treturn {\n\t\tsourceColumn: decision.parentKey ?? defaultPk,\n\t\ttargetColumn: decision.foreignKey ?? deriveFk(parentTable, defaultPk),\n\t};\n}\n","/**\n * JSON_AGG Include Strategy Handler\n *\n * Implements the 'json_agg' include strategy using PostgreSQL's json_agg.\n * Uses to_jsonb(__t__) for wildcard row selection, with recursive nesting\n * via jsonb_build_object merge for child relations.\n *\n * Produces: COALESCE((SELECT json_agg(to_jsonb(__t__) [|| jsonb_build_object(...)]) FROM target AS __t__ WHERE ...), '[]'::json) AS relation\n */\n\nimport type { Node } from '@pgsql/types';\nimport {\n\tandExpr,\n\tjsonAggCorrelation,\n\tjsonAggSubquery,\n} from '../../ast-helpers.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tIncludeHandler,\n\tIncludeResult,\n\tResTargetNode,\n} from '../types.js';\nimport { deriveFkColumns } from './shared.js';\n\n/**\n * Recursively compile a json_agg decision into a ResTarget node.\n * For nested includes, produces nested json_agg with jsonb_build_object merging.\n * Each depth level uses a unique alias (__t0__, __t1__, etc.) to avoid conflicts.\n */\nfunction compileJsonAggRecursive(\n\tdecision: Decision,\n\tparentAlias: string,\n\tdepth: number,\n\tctx: CompilerContext,\n\t_state: CompilerState,\n): Node {\n\tconst innerAlias = depth === 0 ? '__t__' : `__t${depth}__`;\n\n\tconst relation = decision.relation ?? decision.relationName;\n\tconst targetTable = decision.targetTable ?? relation;\n\n\tif (!targetTable) {\n\t\tthrow new Error('JSON_AGG include requires targetTable');\n\t}\n\tif (!relation) {\n\t\tthrow new Error('JSON_AGG include requires relation name');\n\t}\n\n\t// Build correlation WHERE based on relation type\n\tconst { sourceColumn, targetColumn } = deriveFkColumns(\n\t\tdecision,\n\t\tparentAlias,\n\t\tctx.defaultPkColumnName,\n\t\tctx.deriveFkColumnName,\n\t);\n\tlet whereExpr: Node = jsonAggCorrelation(\n\t\tparentAlias,\n\t\tsourceColumn,\n\t\tinnerAlias,\n\t\ttargetColumn,\n\t\tctx.naming,\n\t);\n\n\t// Merge pre-compiled filter conditions (from EXISTS propagation via bridge)\n\tconst compiledFilter = decision._compiledFilterWhere;\n\tif (compiledFilter) {\n\t\twhereExpr = andExpr(whereExpr, compiledFilter);\n\t}\n\n\t// Recursively compile children\n\tlet childNodes: { key: string; node: Node }[] | undefined;\n\tif (decision.children && decision.children.length > 0) {\n\t\tchildNodes = [];\n\t\tfor (const child of decision.children) {\n\t\t\tconst childRelation = child.relation ?? child.relationName;\n\t\t\tif (childRelation && child.targetTable && child.relationType) {\n\t\t\t\tconst childResTarget = compileJsonAggRecursive(\n\t\t\t\t\tchild,\n\t\t\t\t\tinnerAlias,\n\t\t\t\t\tdepth + 1,\n\t\t\t\t\tctx,\n\t\t\t\t\t_state,\n\t\t\t\t);\n\t\t\t\t// Extract the COALESCE node from the ResTarget wrapper\n\t\t\t\tconst resTarget = childResTarget as ResTargetNode;\n\t\t\t\tif (resTarget.ResTarget?.val) {\n\t\t\t\t\tchildNodes.push({\n\t\t\t\t\t\tkey: childRelation,\n\t\t\t\t\t\tnode: resTarget.ResTarget.val,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (childNodes.length === 0) childNodes = undefined;\n\t}\n\n\tconst limit = typeof decision.limit === 'number' ? decision.limit : undefined;\n\n\treturn jsonAggSubquery(\n\t\ttargetTable,\n\t\twhereExpr,\n\t\t`${relation}_json`,\n\t\tctx.schema,\n\t\tctx.naming,\n\t\t{\n\t\t\t...(childNodes && { childNodes }),\n\t\t\tinnerAlias,\n\t\t\t...(limit !== undefined && { limit }),\n\t\t\t...(decision.columns && { columns: decision.columns }),\n\t\t},\n\t);\n}\n\n/**\n * JSON_AGG strategy include handler\n *\n * Uses correlated subquery with json_agg + to_jsonb to embed related records as JSON array.\n * Supports recursive nesting for deep relation traversal.\n *\n * Advantages:\n * - No row explosion (parent row count is preserved)\n * - Full related data in a single column\n * - Recursive nesting via jsonb_build_object merge\n *\n * Disadvantages:\n * - Correlated subquery can be slower for large datasets\n * - JSON manipulation required on client\n */\nexport const jsonAggIncludeHandler: IncludeHandler = {\n\tstrategy: 'json_agg',\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): IncludeResult {\n\t\tconst outerAlias = ctx.currentAlias ?? ctx.rootTable;\n\n\t\tconst resTarget = compileJsonAggRecursive(\n\t\t\tdecision,\n\t\t\touterAlias,\n\t\t\t0,\n\t\t\tctx,\n\t\t\tstate,\n\t\t);\n\n\t\treturn {\n\t\t\ttargets: [resTarget],\n\t\t};\n\t},\n};\n","/**\n * LATERAL Include Strategy Handler\n *\n * Implements the 'lateral' include strategy using LATERAL subquery.\n * This allows row-by-row evaluation with access to outer query columns.\n *\n * Supports deep nesting via recursive child compilation — each child\n * becomes an additional LEFT JOIN LATERAL that correlates with its parent's alias.\n *\n * Produces: LEFT JOIN LATERAL (SELECT ... WHERE fk = outer.pk) AS alias ON true\n */\n\nimport type { JoinExpr, Node, SelectStmt } from '@pgsql/types';\nimport {\n\tDEFAULT_PK_COLUMN,\n\tdefaultFkDerivation,\n\trequiredColumn,\n} from '../../assert-field.js';\nimport {\n\tcolumnRef,\n\tfkCorrelation,\n\trangeVar,\n\tstarTarget,\n} from '../../ast-helpers.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tIncludeHandler,\n\tIncludeResult,\n} from '../types.js';\nimport { deriveFkColumns } from './shared.js';\n\n/**\n * Build column targets for the LATERAL subquery\n */\nfunction buildLateralTargets(\n\tcolumns: readonly string[] | undefined,\n\talias: string,\n\tctx: CompilerContext,\n): Node[] {\n\tif (\n\t\tcolumns &&\n\t\tcolumns.length > 0 &&\n\t\t!(columns.length === 1 && columns[0] === '*')\n\t) {\n\t\treturn columns.map((col) => ({\n\t\t\tResTarget: {\n\t\t\t\tval: columnRef(col, alias, undefined, ctx.naming),\n\t\t\t},\n\t\t}));\n\t}\n\n\t// Select all columns\n\treturn [starTarget(alias, ctx.naming)];\n}\n\n/**\n * Build a LATERAL subquery\n */\nfunction buildLateralSubquery(\n\ttargetTable: string,\n\tinnerAlias: string,\n\touterAlias: string,\n\tsourceColumn: string,\n\ttargetColumn: string,\n\tcolumns: readonly string[] | undefined,\n\tlimit: number | undefined,\n\tctx: CompilerContext,\n): Node {\n\t// Build the correlation condition\n\t// LATERAL can reference outer columns directly\n\tconst whereClause = fkCorrelation(\n\t\ttargetColumn,\n\t\tinnerAlias,\n\t\tsourceColumn,\n\t\touterAlias,\n\t\tctx.naming,\n\t);\n\n\t// Build target list\n\tconst targetList = buildLateralTargets(columns, innerAlias, ctx);\n\n\tconst stmt: SelectStmt = {\n\t\ttargetList,\n\t\tfromClause: [rangeVar(targetTable, innerAlias, ctx.schema, ctx.naming)],\n\t\twhereClause,\n\t\t...(limit !== undefined && {\n\t\t\tlimitCount: { A_Const: { ival: { ival: limit } } },\n\t\t}),\n\t};\n\n\treturn { SelectStmt: stmt };\n}\n\n/**\n * Build a LEFT JOIN LATERAL expression\n */\nfunction buildLateralJoin(\n\tsubquery: Node,\n\tlateralAlias: string,\n\tctx: CompilerContext,\n): Node {\n\t// Wrap subquery as a RangeSubselect\n\tconst rangeSubselect: Node = {\n\t\tRangeSubselect: {\n\t\t\tlateral: true,\n\t\t\tsubquery,\n\t\t\talias: { aliasname: ctx.naming.toDatabase(lateralAlias) },\n\t\t},\n\t};\n\n\t// LEFT JOIN LATERAL ... ON true\n\tconst joinExpr: JoinExpr = {\n\t\tjointype: 'JOIN_LEFT',\n\t\trarg: rangeSubselect,\n\t\tquals: { A_Const: { boolval: { boolval: true } } },\n\t};\n\n\treturn { JoinExpr: joinExpr };\n}\n\n// FK direction derivation: use deriveFkColumns from shared.ts\n\n/**\n * Recursively compile a decision and its children into a cascade of LATERAL JOINs.\n *\n * Returns an array of JOIN nodes: [self, child1, grandchild1, child2, ...]\n */\nfunction compileLateralCascade(\n\tdecision: Decision,\n\touterAlias: string,\n\tsourceColumn: string,\n\ttargetColumn: string,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): { joins: Node[]; targets: Node[]; lateralAlias: string } {\n\tconst targetTable = decision.targetTable ?? decision.relation;\n\tconst columns = decision.columns;\n\tconst limit = typeof decision.limit === 'number' ? decision.limit : undefined;\n\n\tif (!targetTable) {\n\t\tthrow new Error('LATERAL include requires targetTable');\n\t}\n\n\t// Generate unique aliases\n\tconst existingAliases = state.aliases.size;\n\tconst innerAlias = `${targetTable}_inner_${existingAliases}`;\n\tconst lateralAlias = `${targetTable}_lat_${existingAliases}`;\n\tstate.aliases.set(`lateral_${targetTable}_${existingAliases}`, lateralAlias);\n\n\t// Build the LATERAL subquery\n\tconst subquery = buildLateralSubquery(\n\t\ttargetTable,\n\t\tinnerAlias,\n\t\touterAlias,\n\t\tsourceColumn,\n\t\ttargetColumn,\n\t\tcolumns,\n\t\tlimit,\n\t\tctx,\n\t);\n\n\t// Build the JOIN LATERAL\n\tconst join = buildLateralJoin(subquery, lateralAlias, ctx);\n\tconst joins: Node[] = [join];\n\n\t// Build outer SELECT targets referencing the lateral alias\n\tconst targets: Node[] = buildLateralTargets(columns, lateralAlias, ctx);\n\n\t// Recursively compile children\n\tif (decision.children && decision.children.length > 0) {\n\t\tfor (const child of decision.children) {\n\t\t\tconst { sourceColumn: childSrc, targetColumn: childTgt } =\n\t\t\t\tderiveFkColumns(\n\t\t\t\t\tchild,\n\t\t\t\t\ttargetTable,\n\t\t\t\t\tctx.defaultPkColumnName,\n\t\t\t\t\tctx.deriveFkColumnName,\n\t\t\t\t);\n\t\t\tconst childResult = compileLateralCascade(\n\t\t\t\tchild,\n\t\t\t\tlateralAlias,\n\t\t\t\tchildSrc,\n\t\t\t\tchildTgt,\n\t\t\t\tctx,\n\t\t\t\tstate,\n\t\t\t);\n\t\t\tjoins.push(...childResult.joins);\n\t\t\ttargets.push(...childResult.targets);\n\t\t}\n\t}\n\n\treturn { joins, targets, lateralAlias };\n}\n\n/**\n * LATERAL strategy include handler\n *\n * Uses LATERAL subquery to fetch related records row-by-row.\n * Best for: Complex includes with LIMIT, or when you need correlated access.\n *\n * Supports deep nesting: each child relation produces an additional\n * LEFT JOIN LATERAL that correlates with its parent's lateral alias.\n *\n * Advantages:\n * - Can apply LIMIT per parent row\n * - Avoids row explosion\n * - Can apply complex filtering per row\n * - Supports arbitrarily deep relation chains (| flat)\n */\nexport const lateralIncludeHandler: IncludeHandler = {\n\tstrategy: 'lateral',\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): IncludeResult {\n\t\tconst sourceColumn = requiredColumn(\n\t\t\tdecision.sourceColumn,\n\t\t\t'sourceColumn',\n\t\t\t'lateral include',\n\t\t);\n\t\tconst targetColumn =\n\t\t\tdecision.targetColumn ??\n\t\t\t(ctx.deriveFkColumnName ?? defaultFkDerivation)(\n\t\t\t\tctx.rootTable,\n\t\t\t\tctx.defaultPkColumnName ?? DEFAULT_PK_COLUMN,\n\t\t\t);\n\t\tconst outerAlias = ctx.currentAlias ?? ctx.rootTable;\n\n\t\tconst { joins, targets } = compileLateralCascade(\n\t\t\tdecision,\n\t\t\touterAlias,\n\t\t\tsourceColumn,\n\t\t\ttargetColumn,\n\t\t\tctx,\n\t\t\tstate,\n\t\t);\n\n\t\t// First join is the primary, rest are additional (for children)\n\t\tconst [primary, ...additional] = joins as [Node, ...Node[]];\n\n\t\treturn {\n\t\t\ttargets,\n\t\t\tlateral: primary,\n\t\t\tjoin: primary,\n\t\t\t...(additional.length > 0 && { additionalJoins: additional }),\n\t\t};\n\t},\n};\n","/**\n * INCLUDE Strategy Handlers Registration\n *\n * Exports all include strategy handlers and provides registration functions.\n */\n\nimport { registerIncludeHandler } from '../index.js';\nimport { cteIncludeHandler } from './cte.js';\n// Handler imports\nimport { joinIncludeHandler } from './join.js';\nimport { jsonAggIncludeHandler } from './json-agg.js';\nimport { lateralIncludeHandler } from './lateral.js';\n\nexport { cteIncludeHandler } from './cte.js';\n// Re-exports\nexport { joinIncludeHandler } from './join.js';\nexport { jsonAggIncludeHandler } from './json-agg.js';\nexport { lateralIncludeHandler } from './lateral.js';\n\n/**\n * All include strategy handlers\n */\nexport const allIncludeHandlers = [\n\tjoinIncludeHandler,\n\tlateralIncludeHandler,\n\tjsonAggIncludeHandler,\n\tcteIncludeHandler,\n];\n\n/**\n * Register all include handlers.\n * Should be called once at module initialization.\n */\nexport function registerAllIncludeHandlers(): void {\n\tfor (const handler of allIncludeHandlers) {\n\t\tregisterIncludeHandler(handler);\n\t}\n}\n","/**\n * Handler Registry for adapter-pgsql\n *\n * Central registry for WHERE, EXPRESSION, and INCLUDE handlers.\n * Handlers are registered at module initialization and looked up by operator/type.\n */\n\nimport type { Node } from '@pgsql/types';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tExpressionHandler,\n\tIncludeHandler,\n\tWhereDispatcher,\n\tWhereHandler,\n} from './types.js';\nimport { isSelectWithFields } from './types.js';\n\nimport { registerAllWhereHandlers } from './where/index.js';\n\n// Re-export types\nexport * from './types.js';\n\n// ============================================================================\n// Handler Registries\n// ============================================================================\n\nconst whereHandlers = new Map<string, WhereHandler>();\nconst expressionHandlers = new Map<string, ExpressionHandler>();\nconst includeHandlers = new Map<string, IncludeHandler>();\n\n// ============================================================================\n// Registration Functions\n// ============================================================================\n\n/**\n * Register a WHERE handler for one or more operators.\n */\nexport function registerWhereHandler(handler: WhereHandler): void {\n\tfor (const op of handler.operators) {\n\t\tif (whereHandlers.has(op)) {\n\t\t\tthrow new Error(`WHERE handler already registered for operator: ${op}`);\n\t\t}\n\t\twhereHandlers.set(op, handler);\n\t}\n}\n\n/**\n * Register an EXPRESSION handler for one or more types.\n */\nexport function registerExpressionHandler(handler: ExpressionHandler): void {\n\tfor (const type of handler.types) {\n\t\tif (expressionHandlers.has(type)) {\n\t\t\tthrow new Error(\n\t\t\t\t`EXPRESSION handler already registered for type: ${type}`,\n\t\t\t);\n\t\t}\n\t\texpressionHandlers.set(type, handler);\n\t}\n}\n\n/**\n * Register an INCLUDE handler for a strategy.\n */\nexport function registerIncludeHandler(handler: IncludeHandler): void {\n\tif (includeHandlers.has(handler.strategy)) {\n\t\tthrow new Error(\n\t\t\t`INCLUDE handler already registered for strategy: ${handler.strategy}`,\n\t\t);\n\t}\n\tincludeHandlers.set(handler.strategy, handler);\n}\n\n// ============================================================================\n// Lookup Functions\n// ============================================================================\n\n/**\n * Get WHERE handler for an operator.\n * @throws Error if no handler registered\n */\nexport function getWhereHandler(operator: string): WhereHandler {\n\tconst handler = whereHandlers.get(operator);\n\tif (!handler) {\n\t\tthrow new Error(`No WHERE handler registered for operator: ${operator}`);\n\t}\n\treturn handler;\n}\n\n/**\n * Get EXPRESSION handler for a type.\n * @throws Error if no handler registered\n */\nexport function getExpressionHandler(type: string): ExpressionHandler {\n\tconst handler = expressionHandlers.get(type);\n\tif (!handler) {\n\t\tthrow new Error(`No EXPRESSION handler registered for type: ${type}`);\n\t}\n\treturn handler;\n}\n\n/**\n * Get INCLUDE handler for a strategy.\n * @throws Error if no handler registered\n */\nexport function getIncludeHandler(\n\tstrategy: 'join' | 'lateral' | 'json_agg' | 'cte',\n): IncludeHandler {\n\tconst handler = includeHandlers.get(strategy);\n\tif (!handler) {\n\t\tthrow new Error(`No INCLUDE handler registered for strategy: ${strategy}`);\n\t}\n\treturn handler;\n}\n\n/**\n * Check if a WHERE handler exists for an operator.\n */\nexport function hasWhereHandler(operator: string): boolean {\n\treturn whereHandlers.has(operator);\n}\n\n/**\n * Check if an EXPRESSION handler exists for a type.\n */\nexport function hasExpressionHandler(type: string): boolean {\n\treturn expressionHandlers.has(type);\n}\n\n/**\n * Check if an INCLUDE handler exists for a strategy.\n */\nexport function hasIncludeHandler(\n\tstrategy: 'join' | 'lateral' | 'json_agg' | 'cte',\n): boolean {\n\treturn includeHandlers.has(strategy);\n}\n\n// ============================================================================\n// Dispatcher (for recursive WHERE compilation)\n// ============================================================================\n\n/**\n * Normalize symbolic operator names (from IntentAST) to SQL operator symbols.\n * IntentAST uses 'eq', 'ne', 'lt', etc. but handlers register for '=', '!=', '<', etc.\n */\nconst OPERATOR_ALIASES: Record<string, string> = {\n\teq: '=',\n\tne: '!=',\n\tneq: '!=',\n\tlt: '<',\n\tlte: '<=',\n\tgt: '>',\n\tgte: '>=',\n};\n\nlet handlersInitialized = false;\n\n/**\n * Ensure all WHERE handlers are registered (lazy initialization).\n * Called on first dispatch to avoid circular import issues.\n */\nfunction ensureHandlersRegistered(): void {\n\tif (handlersInitialized || whereHandlers.size > 0) return;\n\thandlersInitialized = true;\n\tregisterAllWhereHandlers();\n}\n\n/**\n * Superset of Decision that also accepts WhereIntent-shaped data.\n * The normalizer inspects `kind`/`field` (WhereIntent) and converts to\n * `type`/`column`/`operator` (Decision).\n */\ninterface RawDecisionInput extends Decision {\n\treadonly kind?: string;\n\treadonly field?: string;\n\treadonly pattern?: unknown;\n\treadonly not?: boolean;\n\treadonly condition?: Decision;\n\treadonly caseInsensitive?: boolean;\n\treadonly subquery?: Record<string, unknown>;\n\t// JSON-related fields\n\treadonly jsonPath?: readonly string[];\n\treadonly jsonMode?: 'json' | 'text';\n\treadonly reversed?: boolean;\n\treadonly key?: string;\n\t// Exists/NotExists intent fields\n\treadonly where?: unknown;\n}\n\n/**\n * Normalize a WhereIntent (IntentAST format) into a Decision (handler format).\n * WhereIntent uses `kind` + `field`, Decision uses `type` + `column` + `operator`.\n */\nfunction normalizeToDecision(input: Decision): Decision {\n\t// If it already has `column`, it's already a Decision.\n\t// BUT: if jsonPath is present, reroute to jsonComparison handler\n\t// (mapToHandlerDecision sets column but keeps the original operator like 'eq')\n\tif (input.column !== undefined) {\n\t\tconst raw = input as RawDecisionInput;\n\t\tif (raw.jsonPath && raw.jsonPath.length > 0) {\n\t\t\treturn {\n\t\t\t\ttype: 'where',\n\t\t\t\tcolumn: input.column,\n\t\t\t\toperator: 'jsonComparison',\n\t\t\t\tvalue: input.value,\n\t\t\t\tjsonPath: raw.jsonPath,\n\t\t\t\tjsonMode: raw.jsonMode ?? 'text',\n\t\t\t};\n\t\t}\n\t\treturn input;\n\t}\n\n\tconst raw = input as RawDecisionInput;\n\n\t// Handle PlanDecision compound types (from compiler.ts WHERE compilation)\n\t// These have `type` but no `kind` and no `column`\n\tconst planType = raw.type as string | undefined;\n\tif (\n\t\tplanType === 'whereAnd' ||\n\t\tplanType === 'whereOr' ||\n\t\tplanType === 'whereNot'\n\t) {\n\t\tconst op =\n\t\t\tplanType === 'whereAnd' ? 'and' : planType === 'whereOr' ? 'or' : 'not';\n\t\treturn {\n\t\t\ttype: op,\n\t\t\toperator: op,\n\t\t\tconditions: ((raw.conditions as unknown[]) ?? []).map((c) =>\n\t\t\t\tnormalizeToDecision(c as Decision),\n\t\t\t),\n\t\t};\n\t}\n\n\t// Handle PlanDecision 'having' type — same as 'where', just different type label\n\tif (planType === 'having' && !raw.kind) {\n\t\treturn { ...input, type: 'where' } as Decision;\n\t}\n\n\tconst kind = raw.kind as string | undefined;\n\tif (!kind) return input;\n\n\tswitch (kind) {\n\t\tcase 'comparison': {\n\t\t\tif (raw.jsonPath) {\n\t\t\t\t// Route to jsonComparison handler when jsonPath is present\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'where',\n\t\t\t\t\tcolumn: raw.field as string,\n\t\t\t\t\toperator: 'jsonComparison',\n\t\t\t\t\tvalue: raw.value,\n\t\t\t\t\tjsonPath: raw.jsonPath as readonly string[],\n\t\t\t\t\tjsonMode: (raw.jsonMode as 'json' | 'text') ?? 'text',\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\ttype: 'where',\n\t\t\t\tcolumn: raw.field as string,\n\t\t\t\toperator: raw.operator as string,\n\t\t\t\tvalue: raw.value,\n\t\t\t};\n\t\t}\n\t\tcase 'and':\n\t\t\treturn {\n\t\t\t\ttype: 'and',\n\t\t\t\toperator: 'and',\n\t\t\t\tconditions: ((raw.conditions as unknown[]) ?? []).map((c) =>\n\t\t\t\t\tnormalizeToDecision(c as Decision),\n\t\t\t\t),\n\t\t\t};\n\t\tcase 'or':\n\t\t\treturn {\n\t\t\t\ttype: 'or',\n\t\t\t\toperator: 'or',\n\t\t\t\tconditions: ((raw.conditions as unknown[]) ?? []).map((c) =>\n\t\t\t\t\tnormalizeToDecision(c as Decision),\n\t\t\t\t),\n\t\t\t};\n\t\tcase 'not':\n\t\t\treturn {\n\t\t\t\ttype: 'not',\n\t\t\t\toperator: 'not',\n\t\t\t\tconditions: [normalizeToDecision(raw.condition as Decision)],\n\t\t\t};\n\t\tcase 'null':\n\t\t\treturn {\n\t\t\t\ttype: 'where',\n\t\t\t\tcolumn: raw.field as string,\n\t\t\t\toperator: raw.operator as string,\n\t\t\t};\n\t\tcase 'any':\n\t\t\treturn {\n\t\t\t\ttype: 'where',\n\t\t\t\tcolumn: raw.field as string,\n\t\t\t\toperator: 'any',\n\t\t\t\tvalues: raw.values as readonly unknown[],\n\t\t\t};\n\t\tcase 'in': {\n\t\t\tconst sub = raw.subquery as Record<string, unknown> | undefined;\n\t\t\tif (sub) {\n\t\t\t\t// IN/NOT IN with subquery → route to inSubquery/notInSubquery handler\n\t\t\t\tconst rawSelect = sub.select as unknown;\n\t\t\t\tconst selectColumn =\n\t\t\t\t\ttypeof rawSelect === 'string'\n\t\t\t\t\t\t? rawSelect\n\t\t\t\t\t\t: isSelectWithFields(rawSelect)\n\t\t\t\t\t\t\t? (rawSelect.fields?.[0] ?? '*')\n\t\t\t\t\t\t\t: '*';\n\t\t\t\tconst subConditions = sub.where\n\t\t\t\t\t? [normalizeToDecision(sub.where as Decision)]\n\t\t\t\t\t: [];\n\t\t\t\tconst rawLimit = sub.limit as number | undefined;\n\t\t\t\tconst rawOrderBy = sub.orderBy as\n\t\t\t\t\t| readonly { field: string; direction?: string }[]\n\t\t\t\t\t| undefined;\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'where',\n\t\t\t\t\tcolumn: raw.field as string,\n\t\t\t\t\toperator: raw.not ? 'notInSubquery' : 'inSubquery',\n\t\t\t\t\ttargetTable: sub.from as string,\n\t\t\t\t\tselectColumn,\n\t\t\t\t\tconditions: subConditions,\n\t\t\t\t\t...(rawLimit != null && { limit: rawLimit }),\n\t\t\t\t\t...(rawOrderBy && {\n\t\t\t\t\t\torderBy: rawOrderBy.map((o) => ({\n\t\t\t\t\t\t\tcolumn: o.field,\n\t\t\t\t\t\t\tdirection: (o.direction?.toUpperCase() ?? 'ASC') as\n\t\t\t\t\t\t\t\t| 'ASC'\n\t\t\t\t\t\t\t\t| 'DESC',\n\t\t\t\t\t\t})),\n\t\t\t\t\t}),\n\t\t\t\t} as Decision;\n\t\t\t}\n\t\t\t// Use 'value' (not 'values') to match what inHandler.compile() reads\n\t\t\treturn {\n\t\t\t\ttype: 'where',\n\t\t\t\tcolumn: raw.field as string,\n\t\t\t\toperator: raw.not ? 'notIn' : 'in',\n\t\t\t\tvalue: raw.values as readonly unknown[],\n\t\t\t};\n\t\t}\n\t\tcase 'like':\n\t\t\treturn {\n\t\t\t\ttype: 'where',\n\t\t\t\tcolumn: raw.field as string,\n\t\t\t\toperator: raw.caseInsensitive ? 'ilike' : 'like',\n\t\t\t\tvalue: raw.pattern,\n\t\t\t};\n\t\tcase 'jsonContains':\n\t\t\treturn {\n\t\t\t\ttype: 'where',\n\t\t\t\tcolumn: raw.field as string,\n\t\t\t\toperator: raw.reversed ? 'jsonContainedBy' : 'jsonContains',\n\t\t\t\tvalue: raw.value,\n\t\t\t};\n\t\tcase 'jsonExists':\n\t\t\treturn {\n\t\t\t\ttype: 'where',\n\t\t\t\tcolumn: raw.field as string,\n\t\t\t\toperator: 'jsonExists',\n\t\t\t\tvalue: raw.key,\n\t\t\t};\n\t\tcase 'exists':\n\t\tcase 'notExists': {\n\t\t\t// WhereExistsIntent / WhereNotExistsIntent from notExists() / exists() helpers.\n\t\t\t// These are passed directly to mutations (DELETE/UPDATE WHERE) without going\n\t\t\t// through the planner, so we normalize them here for the EXISTS/NOT EXISTS handlers.\n\t\t\tconst relation = raw.relation as string;\n\t\t\tconst conditions = raw.where\n\t\t\t\t? [normalizeToDecision(raw.where as Decision)]\n\t\t\t\t: undefined;\n\t\t\t// Prefer explicit targetTable if already resolved (e.g. by compileDelete's\n\t\t\t// resolveExistsIntent which maps the logical relation name → real table name).\n\t\t\t// Fall back to relation name when no ModelIR is available.\n\t\t\tconst targetTable = (raw.targetTable as string | undefined) ?? relation;\n\t\t\t// Pass through FK column hints resolved by resolveExistsIntent from ModelIR.\n\t\t\tconst sourceColumn = raw.sourceColumn as string | undefined;\n\t\t\tconst targetColumn = raw.targetColumn as string | undefined;\n\t\t\t// Pass through include declarations (JOIN inside the subquery).\n\t\t\tconst includeIntent = raw.include as\n\t\t\t\t| Record<string, { join?: 'inner' | 'left' }>\n\t\t\t\t| undefined;\n\t\t\t// Convert include map to a Decision[] for the handler.\n\t\t\t// Each entry becomes a minimal join decision: { type: 'existsInclude', relation, joinType }.\n\t\t\tconst includeDecisions: Decision[] | undefined = includeIntent\n\t\t\t\t? Object.entries(includeIntent).map(([rel, opts]) => ({\n\t\t\t\t\t\ttype: 'existsInclude',\n\t\t\t\t\t\trelation: rel,\n\t\t\t\t\t\tjoinType: opts.join ?? 'inner',\n\t\t\t\t\t}))\n\t\t\t\t: undefined;\n\t\t\treturn {\n\t\t\t\ttype: 'exists',\n\t\t\t\toperator: kind, // 'exists' | 'notExists'\n\t\t\t\trelation,\n\t\t\t\ttargetTable,\n\t\t\t\t...(sourceColumn !== undefined && { sourceColumn }),\n\t\t\t\t...(targetColumn !== undefined && { targetColumn }),\n\t\t\t\t...(conditions && { conditions }),\n\t\t\t\t...(includeDecisions && { include: includeDecisions }),\n\t\t\t};\n\t\t}\n\t\tdefault:\n\t\t\t// Pass through for types already in Decision format or unknown\n\t\t\treturn input;\n\t}\n}\n\n/**\n * Create a WHERE dispatcher that looks up handlers from the registry.\n */\nexport function createWhereDispatcher(): WhereDispatcher {\n\treturn (\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node => {\n\t\tensureHandlersRegistered();\n\t\tconst normalized = normalizeToDecision(decision);\n\t\tconst rawOperator = normalized.operator ?? '=';\n\t\tconst operator = OPERATOR_ALIASES[rawOperator] ?? rawOperator;\n\t\tconst handler = getWhereHandler(operator);\n\t\t// Pass normalized decision with resolved operator so handler's switch matches\n\t\tconst resolved =\n\t\t\toperator !== rawOperator ? { ...normalized, operator } : normalized;\n\t\treturn handler.compile(resolved, ctx, state, createWhereDispatcher());\n\t};\n}\n\n// ============================================================================\n// Registry Stats (for debugging/testing)\n// ============================================================================\n\n/**\n * Get counts of registered handlers.\n */\nexport function getRegistryStats(): {\n\twhere: number;\n\texpression: number;\n\tinclude: number;\n} {\n\treturn {\n\t\twhere: whereHandlers.size,\n\t\texpression: expressionHandlers.size,\n\t\tinclude: includeHandlers.size,\n\t};\n}\n\n/**\n * Get all registered operator names (for debugging).\n */\nexport function getRegisteredOperators(): {\n\twhere: string[];\n\texpression: string[];\n\tinclude: string[];\n} {\n\treturn {\n\t\twhere: Array.from(whereHandlers.keys()),\n\t\texpression: Array.from(expressionHandlers.keys()),\n\t\tinclude: Array.from(includeHandlers.keys()),\n\t};\n}\n\n/**\n * Clear all handlers (for testing only).\n */\nexport function clearHandlers(): void {\n\twhereHandlers.clear();\n\texpressionHandlers.clear();\n\tincludeHandlers.clear();\n\thandlersInitialized = false;\n}\n\n// ============================================================================\n// Re-export Specific Handlers\n// ============================================================================\n\n// EXPRESSION handlers\nexport * from './expression/index.js';\n// INCLUDE handlers\nexport * from './include/index.js';\n// WHERE handlers\nexport * from './where/index.js';\n\n// ============================================================================\n// WHERE Handler Exports\n// ============================================================================\n\nexport {\n\tandHandler,\n\tbetweenHandler,\n\tcomparisonHandler,\n\tinHandler,\n\tlikeHandler,\n\tnotHandler,\n\tnullHandler,\n\torHandler,\n\trangeHandler,\n\tregisterSimpleWhereHandlers,\n\tsimpleWhereHandlers,\n} from './where/index.js';\n","/**\n * Aggregate Function Expression Handlers\n *\n * Handles: COUNT, SUM, AVG, MIN, MAX, and custom aggregates\n *\n * Produces FuncCall nodes with aggregate options.\n */\n\nimport type { Node } from '@pgsql/types';\nimport { columnRef, funcCall } from '../../ast-helpers.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tExpressionHandler,\n} from '../types.js';\n\n// Aggregate handlers for COUNT, SUM, AVG, MIN, MAX\n\n/**\n * Build an aggregate function call\n */\nfunction buildAggregate(\n\tfuncName: string,\n\tcolumn: string | undefined,\n\tdistinct: boolean,\n\tctx: CompilerContext,\n\tfilterNode?: Node,\n): Node {\n\tconst isCountStar = funcName === 'count' && (!column || column === '*');\n\n\tif (isCountStar) {\n\t\treturn funcCall(funcName, [], {\n\t\t\tstar: true,\n\t\t\t...(filterNode && { filter: filterNode }),\n\t\t});\n\t}\n\n\tif (!column) {\n\t\tthrow new Error(`Aggregate ${funcName} requires a column`);\n\t}\n\n\tconst tableAlias = ctx.currentAlias ?? ctx.rootTable;\n\tlet colRef: Node;\n\tif (column.includes('.')) {\n\t\tconst dotIdx = column.indexOf('.');\n\t\tconst table = column.slice(0, dotIdx);\n\t\tconst col = column.slice(dotIdx + 1);\n\t\tcolRef = columnRef(col, table, undefined, ctx.naming);\n\t} else {\n\t\tcolRef = columnRef(column, tableAlias, undefined, ctx.naming);\n\t}\n\n\treturn funcCall(funcName, [colRef], {\n\t\tdistinct,\n\t\t...(filterNode && { filter: filterNode }),\n\t});\n}\n\n/**\n * COUNT handler\n *\n * Produces: COUNT(*) or COUNT(column) or COUNT(DISTINCT column)\n */\nexport const countHandler: ExpressionHandler = {\n\ttypes: ['count', 'COUNT'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\t_state: CompilerState,\n\t): Node {\n\t\tconst column = decision.column;\n\t\tconst distinct =\n\t\t\tdecision.operator === 'countDistinct' || Boolean(decision.args?.[0]);\n\t\treturn buildAggregate('count', column, distinct, ctx, decision.filterWhere);\n\t},\n};\n\n/**\n * COUNT DISTINCT handler\n */\nexport const countDistinctHandler: ExpressionHandler = {\n\ttypes: ['countDistinct', 'COUNT_DISTINCT'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\t_state: CompilerState,\n\t): Node {\n\t\tconst column = decision.column;\n\t\tif (!column) {\n\t\t\tthrow new Error('COUNT DISTINCT requires a column');\n\t\t}\n\t\treturn buildAggregate('count', column, true, ctx, decision.filterWhere);\n\t},\n};\n\n/**\n * Factory for simple aggregate handlers (no distinct, column required).\n * Produces: FUNC(column) FILTER (WHERE ...)\n */\nfunction createSimpleAggregateHandler(\n\tfuncName: string,\n\ttypes: string[],\n): ExpressionHandler {\n\treturn {\n\t\ttypes,\n\t\tcompile(\n\t\t\tdecision: Decision,\n\t\t\tctx: CompilerContext,\n\t\t\t_state: CompilerState,\n\t\t): Node {\n\t\t\treturn buildAggregate(\n\t\t\t\tfuncName,\n\t\t\t\tdecision.column,\n\t\t\t\tfalse,\n\t\t\t\tctx,\n\t\t\t\tdecision.filterWhere,\n\t\t\t);\n\t\t},\n\t};\n}\n\n/** SUM handler */\nexport const sumHandler = createSimpleAggregateHandler('sum', ['sum', 'SUM']);\n\n/** AVG handler */\nexport const avgHandler = createSimpleAggregateHandler('avg', [\n\t'avg',\n\t'AVG',\n\t'average',\n]);\n\n/** MIN handler */\nexport const minHandler = createSimpleAggregateHandler('min', ['min', 'MIN']);\n\n/** MAX handler */\nexport const maxHandler = createSimpleAggregateHandler('max', ['max', 'MAX']);\n\n/**\n * Generic aggregate handler for custom aggregates\n */\nexport const genericAggregateHandler: ExpressionHandler = {\n\ttypes: ['aggregate', 'agg'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\t_state: CompilerState,\n\t): Node {\n\t\tconst funcName = decision.function;\n\t\tif (!funcName) {\n\t\t\tthrow new Error('Generic aggregate requires function name');\n\t\t}\n\t\treturn buildAggregate(\n\t\t\tfuncName,\n\t\t\tdecision.column,\n\t\t\tfalse,\n\t\t\tctx,\n\t\t\tdecision.filterWhere,\n\t\t);\n\t},\n};\n","/**\n * Arithmetic Expression Handler\n *\n * Handles arithmetic expressions like: price * quantity, a + b, -amount\n * Produces A_Expr AST nodes with AEXPR_OP kind.\n */\n\nimport type { Node } from '@pgsql/types';\nimport { columnRef } from '../../ast-helpers.js';\nimport { createParamRef } from '../../param-ref.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tExpressionHandler,\n} from '../types.js';\n\n/**\n * Resolve an operand to an AST node.\n * - string → column reference\n * - number → parameterized value ($N)\n */\nfunction resolveOperand(\n\toperand: unknown,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): Node {\n\tif (typeof operand === 'string') {\n\t\tconst alias = ctx.currentAlias ?? ctx.rootTable;\n\t\treturn columnRef(operand, alias, undefined, ctx.naming);\n\t}\n\t// Numeric or other literal → parametrize\n\tconst idx = ++state.paramIndex;\n\tstate.parameters.push(operand);\n\treturn createParamRef(idx);\n}\n\n/**\n * Arithmetic expression handler.\n * Compiles: left operator right → A_Expr(AEXPR_OP, op, left, right)\n */\nexport const arithmeticHandler: ExpressionHandler = {\n\ttypes: ['arithmetic', 'math', 'calc'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst left = decision.args?.[0];\n\t\tconst right = decision.args?.[1];\n\t\tconst operator = decision.operator ?? '+';\n\n\t\tif (left === undefined || right === undefined) {\n\t\t\tthrow new Error('Arithmetic handler requires left and right operands');\n\t\t}\n\n\t\tconst leftNode = resolveOperand(left, ctx, state);\n\t\tconst rightNode = resolveOperand(right, ctx, state);\n\n\t\treturn {\n\t\t\tA_Expr: {\n\t\t\t\tkind: 'AEXPR_OP',\n\t\t\t\tname: [{ String: { sval: operator } }],\n\t\t\t\tlexpr: leftNode,\n\t\t\t\trexpr: rightNode,\n\t\t\t},\n\t\t};\n\t},\n};\n","/**\n * CASE Expression Handler\n *\n * Handles: CASE WHEN ... THEN ... ELSE ... END\n *\n * Produces CaseExpr nodes.\n */\n\nimport type { CaseExpr, CaseWhen, Node } from '@pgsql/types';\nimport { columnRef } from '../../ast-helpers.js';\nimport { createParamRef } from '../../param-ref.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tExpressionHandler,\n} from '../types.js';\nimport { resolveCaseValue as resolveCaseValueShared } from './case-value.js';\n\n/**\n * Case condition structure\n */\ninterface CaseCondition {\n\twhen: Decision;\n\tthen: unknown;\n}\n\n/** Adapter: route CompilerContext fields to the shared resolveCaseValue signature. */\nfunction resolveCaseValue(\n\tvalue: unknown,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): Node {\n\tconst alias = ctx.currentAlias ?? ctx.rootTable;\n\treturn resolveCaseValueShared(value, alias, undefined, ctx.naming, state);\n}\n\nexport const caseHandler: ExpressionHandler = {\n\ttypes: ['case', 'CASE', 'caseWhen'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\t// CASE decisions carry { when: Decision; then: unknown } tuples in `conditions`,\n\t\t// which is structurally different from the base Decision[]. The planner\n\t\t// guarantees this shape at runtime for expressionType === 'case'.\n\t\tconst conditions = decision.conditions as\n\t\t\t| readonly CaseCondition[]\n\t\t\t| undefined;\n\t\tconst elseValue = decision.value;\n\n\t\tif (!conditions || conditions.length === 0) {\n\t\t\tthrow new Error('CASE requires at least one WHEN condition');\n\t\t}\n\n\t\t// Import WHERE dispatcher for compiling WHEN conditions\n\t\t// Note: We need to avoid circular dependencies\n\t\tconst { createWhereDispatcher } = require('../index.js');\n\t\tconst dispatch = createWhereDispatcher();\n\n\t\tconst args: Node[] = conditions.map((cond) => {\n\t\t\t// Compile the WHEN condition\n\t\t\tconst whenExpr = dispatch(cond.when, ctx, state);\n\n\t\t\t// Build the THEN result using expression-aware resolution\n\t\t\tconst thenResult = resolveCaseValue(cond.then, ctx, state);\n\n\t\t\tconst caseWhen: CaseWhen = {\n\t\t\t\texpr: whenExpr,\n\t\t\t\tresult: thenResult,\n\t\t\t};\n\n\t\t\treturn { CaseWhen: caseWhen };\n\t\t});\n\n\t\t// Build ELSE clause if present\n\t\tlet defresult: Node | undefined;\n\t\tif (elseValue !== undefined) {\n\t\t\tdefresult = resolveCaseValue(elseValue, ctx, state);\n\t\t}\n\n\t\tconst caseExpr: CaseExpr = {\n\t\t\targs,\n\t\t\t...(defresult && { defresult }),\n\t\t};\n\n\t\treturn { CaseExpr: caseExpr };\n\t},\n};\n\n/**\n * Simple CASE expression handler\n *\n * CASE expr WHEN value1 THEN result1 ... END\n */\nexport const simpleCaseHandler: ExpressionHandler = {\n\ttypes: ['simpleCase', 'simpleCaseWhen'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst column = decision.column;\n\t\t// Same structural override as in caseHandler — see above.\n\t\tconst conditions = decision.conditions as\n\t\t\t| readonly CaseCondition[]\n\t\t\t| undefined;\n\t\tconst elseValue = decision.value;\n\n\t\tif (!column) {\n\t\t\tthrow new Error('Simple CASE requires a column');\n\t\t}\n\n\t\tif (!conditions || conditions.length === 0) {\n\t\t\tthrow new Error('Simple CASE requires at least one WHEN condition');\n\t\t}\n\n\t\tconst tableAlias = ctx.currentAlias ?? ctx.rootTable;\n\t\tconst testExpr = columnRef(column, tableAlias, undefined, ctx.naming);\n\n\t\tconst args: Node[] = conditions.map((cond) => {\n\t\t\t// Build the comparison value — `when` may be a Decision with .value\n\t\t\t// or a primitive; extract the raw value for parameterization.\n\t\t\tconst whenParamNumber = ++state.paramIndex;\n\t\t\tconst whenDecision = cond.when as Decision & { value?: unknown };\n\t\t\tstate.parameters.push(whenDecision.value ?? cond.when);\n\t\t\tconst whenExpr = createParamRef(whenParamNumber);\n\n\t\t\t// Build the THEN result\n\t\t\tconst thenParamNumber = ++state.paramIndex;\n\t\t\tstate.parameters.push(cond.then);\n\t\t\tconst thenResult = createParamRef(thenParamNumber);\n\n\t\t\tconst caseWhen: CaseWhen = {\n\t\t\t\texpr: whenExpr,\n\t\t\t\tresult: thenResult,\n\t\t\t};\n\n\t\t\treturn { CaseWhen: caseWhen };\n\t\t});\n\n\t\t// Build ELSE clause if present\n\t\tlet defresult: Node | undefined;\n\t\tif (elseValue !== undefined) {\n\t\t\tconst paramNumber = ++state.paramIndex;\n\t\t\tstate.parameters.push(elseValue);\n\t\t\tdefresult = createParamRef(paramNumber);\n\t\t}\n\n\t\tconst caseExpr: CaseExpr = {\n\t\t\targ: testExpr,\n\t\t\targs,\n\t\t\t...(defresult && { defresult }),\n\t\t};\n\n\t\treturn { CaseExpr: caseExpr };\n\t},\n};\n","/**\n * COALESCE Expression Handler\n *\n * Handles: COALESCE(val1, val2, ...) - returns first non-NULL value\n *\n * Produces CoalesceExpr nodes.\n */\n\nimport type { CoalesceExpr, Node } from '@pgsql/types';\nimport { columnRef } from '../../ast-helpers.js';\nimport { createParamRef } from '../../param-ref.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tExpressionHandler,\n} from '../types.js';\n\n/**\n * Build a value node from a decision argument\n */\nfunction buildValueNode(\n\tvalue: unknown,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): Node {\n\t// If it's a column reference\n\tif (typeof value === 'string' && !value.includes(' ')) {\n\t\tconst tableAlias = ctx.currentAlias ?? ctx.rootTable;\n\t\treturn columnRef(value, tableAlias, undefined, ctx.naming);\n\t}\n\n\t// If it's a decision with type 'column'\n\tif (typeof value === 'object' && value !== null && 'type' in value) {\n\t\tconst decision = value as Decision;\n\t\tif (decision.type === 'column' && decision.column) {\n\t\t\tconst tableAlias = ctx.currentAlias ?? ctx.rootTable;\n\t\t\treturn columnRef(decision.column, tableAlias, undefined, ctx.naming);\n\t\t}\n\t}\n\n\t// Otherwise, parameterize it\n\tconst paramNumber = ++state.paramIndex;\n\tstate.parameters.push(value);\n\treturn createParamRef(paramNumber);\n}\n\n/**\n * COALESCE handler\n *\n * Returns the first non-NULL argument.\n * COALESCE(a, b, c) = first non-null of a, b, c\n */\nexport const coalesceHandler: ExpressionHandler = {\n\ttypes: ['coalesce', 'COALESCE', 'ifNull', 'nvl'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst args = decision.args;\n\t\tconst column = decision.column;\n\t\tconst defaultValue = decision.value;\n\n\t\t// Build argument list\n\t\tconst argNodes: Node[] = [];\n\n\t\t// If column is specified, add it first\n\t\tif (column) {\n\t\t\tconst tableAlias = ctx.currentAlias ?? ctx.rootTable;\n\t\t\targNodes.push(columnRef(column, tableAlias, undefined, ctx.naming));\n\t\t}\n\n\t\t// Add args array if present\n\t\tif (args && Array.isArray(args)) {\n\t\t\tfor (const arg of args) {\n\t\t\t\targNodes.push(buildValueNode(arg, ctx, state));\n\t\t\t}\n\t\t}\n\n\t\t// Add default value if present\n\t\tif (defaultValue !== undefined) {\n\t\t\targNodes.push(buildValueNode(defaultValue, ctx, state));\n\t\t}\n\n\t\tif (argNodes.length === 0) {\n\t\t\tthrow new Error('COALESCE requires at least one argument');\n\t\t}\n\n\t\tconst coalesceExpr: CoalesceExpr = {\n\t\t\targs: argNodes,\n\t\t};\n\n\t\treturn { CoalesceExpr: coalesceExpr };\n\t},\n};\n\n/**\n * NULLIF handler\n *\n * Returns NULL if the two arguments are equal, otherwise returns the first.\n * NULLIF(a, b) = CASE WHEN a = b THEN NULL ELSE a END\n */\nexport const nullIfHandler: ExpressionHandler = {\n\ttypes: ['nullIf', 'NULLIF'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst column = decision.column;\n\t\tconst value = decision.value;\n\n\t\tif (!column) {\n\t\t\tthrow new Error('NULLIF requires a column');\n\t\t}\n\n\t\tif (value === undefined) {\n\t\t\tthrow new Error('NULLIF requires a comparison value');\n\t\t}\n\n\t\tconst tableAlias = ctx.currentAlias ?? ctx.rootTable;\n\t\tconst colRef = columnRef(column, tableAlias, undefined, ctx.naming);\n\n\t\tconst paramNumber = ++state.paramIndex;\n\t\tstate.parameters.push(value);\n\t\tconst valueRef = createParamRef(paramNumber);\n\n\t\treturn {\n\t\t\tNullIfExpr: {\n\t\t\t\targs: [colRef, valueRef],\n\t\t\t},\n\t\t};\n\t},\n};\n\n/**\n * GREATEST handler\n *\n * Returns the greatest value from a list.\n */\nexport const greatestHandler: ExpressionHandler = {\n\ttypes: ['greatest', 'GREATEST'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst args = decision.args;\n\n\t\tif (!args || !Array.isArray(args) || args.length === 0) {\n\t\t\tthrow new Error('GREATEST requires at least one argument');\n\t\t}\n\n\t\tconst argNodes: Node[] = args.map((arg) => buildValueNode(arg, ctx, state));\n\n\t\treturn {\n\t\t\tMinMaxExpr: {\n\t\t\t\top: 'IS_GREATEST',\n\t\t\t\targs: argNodes,\n\t\t\t},\n\t\t};\n\t},\n};\n\n/**\n * LEAST handler\n *\n * Returns the least value from a list.\n */\nexport const leastHandler: ExpressionHandler = {\n\ttypes: ['least', 'LEAST'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst args = decision.args;\n\n\t\tif (!args || !Array.isArray(args) || args.length === 0) {\n\t\t\tthrow new Error('LEAST requires at least one argument');\n\t\t}\n\n\t\tconst argNodes: Node[] = args.map((arg) => buildValueNode(arg, ctx, state));\n\n\t\treturn {\n\t\t\tMinMaxExpr: {\n\t\t\t\top: 'IS_LEAST',\n\t\t\t\targs: argNodes,\n\t\t\t},\n\t\t};\n\t},\n};\n","/**\n * Column Expression Handlers\n *\n * Handles: column references, column aliases\n *\n * Produces ColumnRef and ResTarget nodes for SELECT lists.\n */\n\nimport type { Node, ResTarget } from '@pgsql/types';\nimport { columnRef } from '../../ast-helpers.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tExpressionHandler,\n} from '../types.js';\n\n/**\n * Column reference handler\n *\n * Produces: table.column or alias.column\n */\nexport const columnHandler: ExpressionHandler = {\n\ttypes: ['column', 'col', 'field'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\t_state: CompilerState,\n\t): Node {\n\t\tconst column = decision.column;\n\t\tif (!column) {\n\t\t\tthrow new Error('Column handler requires column');\n\t\t}\n\n\t\tconst alias = ctx.currentAlias ?? ctx.rootTable;\n\t\treturn columnRef(column, alias, undefined, ctx.naming);\n\t},\n};\n\n/**\n * Column alias handler\n *\n * Produces: expression AS alias (for SELECT list)\n * Returns a ResTarget node.\n */\nexport const columnAliasHandler: ExpressionHandler = {\n\ttypes: ['columnAlias', 'as', 'alias'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\t_state: CompilerState,\n\t): Node {\n\t\tconst column = decision.column;\n\t\tconst outputAlias = decision.alias;\n\n\t\tif (!column) {\n\t\t\tthrow new Error('Column alias handler requires column');\n\t\t}\n\n\t\tconst tableAlias = ctx.currentAlias ?? ctx.rootTable;\n\t\tconst colRef = columnRef(column, tableAlias, undefined, ctx.naming);\n\n\t\t// If no alias specified, return just the column reference\n\t\tif (!outputAlias) {\n\t\t\treturn colRef;\n\t\t}\n\n\t\t// Wrap in ResTarget with alias for SELECT list\n\t\tconst resTarget: ResTarget = {\n\t\t\tval: colRef,\n\t\t\tname: ctx.naming.toDatabase(outputAlias),\n\t\t};\n\n\t\treturn { ResTarget: resTarget };\n\t},\n};\n\n/**\n * Star (all columns) handler\n *\n * Produces: table.* or *\n */\nexport const starHandler: ExpressionHandler = {\n\ttypes: ['star', '*', 'all'],\n\n\tcompile(\n\t\t_decision: Decision,\n\t\tctx: CompilerContext,\n\t\t_state: CompilerState,\n\t): Node {\n\t\tconst tableAlias = ctx.currentAlias ?? ctx.rootTable;\n\n\t\t// table.* — qualified star\n\t\treturn {\n\t\t\tColumnRef: {\n\t\t\t\tfields: [\n\t\t\t\t\t{ String: { sval: ctx.naming.toDatabase(tableAlias) } },\n\t\t\t\t\t{ A_Star: {} },\n\t\t\t\t],\n\t\t\t},\n\t\t};\n\t},\n};\n","/**\n * @module handlers/expression/json\n * Expression handlers for JSONB extraction in SELECT.\n */\n\nimport type { Node } from '@pgsql/types';\nimport { columnRef } from '../../ast-helpers.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tExpressionHandler,\n} from '../types.js';\nimport { compileValue } from '../where/utils.js';\n\n/**\n * JSON extract: col->'key' or col->>'key' chains\n * Produces: \"col\"->'a'->'b'->>'c'\n */\nexport const jsonExtractHandler: ExpressionHandler = {\n\ttypes: ['jsonExtract'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst column = decision.column;\n\t\tif (!column) {\n\t\t\tthrow new Error('JSON extract handler requires a column');\n\t\t}\n\n\t\tconst path = (decision.args ?? []) as string[];\n\t\tconst mode = decision.jsonMode ?? 'text';\n\n\t\tconst alias = ctx.currentAlias ?? ctx.rootTable;\n\t\tlet node: Node = columnRef(column, alias, undefined, ctx.naming);\n\n\t\tfor (let i = 0; i < path.length; i++) {\n\t\t\tconst isLast = i === path.length - 1;\n\t\t\tconst op = isLast && mode === 'text' ? '->>' : '->';\n\t\t\tconst keyNode = compileValue(path[i]!, state);\n\t\t\tnode = {\n\t\t\t\tA_Expr: {\n\t\t\t\t\tkind: 'AEXPR_OP',\n\t\t\t\t\tname: [{ String: { sval: op } }],\n\t\t\t\t\tlexpr: node,\n\t\t\t\t\trexpr: keyNode,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn node;\n\t},\n};\n\n/**\n * JSON path extract: col#>'{a,b}' or col#>>'{a,b}'\n * Produces: \"col\" #> $1 or \"col\" #>> $1\n */\nexport const jsonPathExtractHandler: ExpressionHandler = {\n\ttypes: ['jsonPathExtract'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst column = decision.column;\n\t\tif (!column) {\n\t\t\tthrow new Error('JSON path extract handler requires a column');\n\t\t}\n\n\t\tconst mode = decision.jsonMode ?? 'text';\n\t\t// args[0] is the pre-built PostgreSQL array literal '{a,b}'\n\t\tconst arrayLiteral = (decision.args?.[0] as string) ?? '{}';\n\n\t\tconst alias = ctx.currentAlias ?? ctx.rootTable;\n\t\tconst left: Node = columnRef(column, alias, undefined, ctx.naming);\n\t\tconst right = compileValue(arrayLiteral, state);\n\t\tconst op = mode === 'text' ? '#>>' : '#>';\n\n\t\treturn {\n\t\t\tA_Expr: {\n\t\t\t\tkind: 'AEXPR_OP',\n\t\t\t\tname: [{ String: { sval: op } }],\n\t\t\t\tlexpr: left,\n\t\t\t\trexpr: right,\n\t\t\t},\n\t\t};\n\t},\n};\n","/**\n * Pseudo-Column Expression Handlers\n *\n * Handles hierarchy pseudo-columns that compile to scalar subqueries.\n * - Single-hop: parent, child → LEFT JOIN\n * - Recursive: ascendant, descendant → WITH RECURSIVE scalar subquery\n *\n * Produces scalar subqueries for recursive traversals.\n */\n\nimport type { CommonTableExpr, Node, SelectStmt, SubLink } from '@pgsql/types';\nimport { requiredColumn } from '../../assert-field.js';\nimport {\n\tbinaryExpr,\n\tcoalesce,\n\teqExpr,\n\tfuncCall,\n\tintegerNode,\n\tstringNode,\n\ttypeCast,\n} from '../../ast-helpers.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tExpressionHandler,\n} from '../types.js';\n\n// ============================================================================\n// Helper: Build Recursive CTE\n// ============================================================================\n\n/**\n * Configuration for recursive CTE builder\n */\ninterface RecursiveCteConfig {\n\tcteAlias: string;\n\ttable: string;\n\tpkColumn: string;\n\tfkColumn: string;\n\touterAlias: string;\n\tisAncestors: boolean;\n\tmaxDepth: number;\n\tselectColumn: string;\n\tctx: CompilerContext;\n}\n\n/**\n * Build a WITH RECURSIVE scalar subquery for hierarchy traversal.\n *\n * Generates:\n * ```sql\n * (WITH RECURSIVE __rc AS (\n * -- Anchor: start from FK (ancestors) or PK (descendants)\n * SELECT t.*, 1 AS __depth, ARRAY[t.pk] AS __visited\n * FROM table t\n * WHERE t.pk = outer.fk (ancestors) OR t.fk = outer.pk (descendants)\n *\n * UNION ALL\n *\n * -- Recursive: traverse up/down\n * SELECT n.*, __rc.__depth + 1, __rc.__visited || n.pk\n * FROM __rc\n * INNER JOIN table n ON n.pk = __rc.fk (ancestors) OR n.fk = __rc.pk (descendants)\n * WHERE __rc.__depth < maxDepth AND n.pk <> ALL(__rc.__visited)\n * )\n * SELECT COALESCE(json_agg(__rc.column ORDER BY __rc.__depth), '[]'::json)\n * FROM __rc)\n * ```\n */\nfunction buildRecursiveScalarSubquery(config: RecursiveCteConfig): Node {\n\tconst {\n\t\tcteAlias,\n\t\ttable,\n\t\tpkColumn,\n\t\tfkColumn,\n\t\touterAlias,\n\t\tisAncestors,\n\t\tmaxDepth,\n\t\tselectColumn,\n\t\tctx,\n\t} = config;\n\n\tconst naming = ctx.naming;\n\tconst dbTable = naming.toDatabase(table);\n\tconst dbPk = naming.toDatabase(pkColumn);\n\tconst dbFk = naming.toDatabase(fkColumn);\n\tconst dbOuter = naming.toDatabase(outerAlias);\n\n\t// Inner alias for CTE iterations\n\tconst innerAlias = '__n';\n\n\t// Build anchor SELECT\n\tconst anchorSelect: SelectStmt = {\n\t\ttargetList: [\n\t\t\t// Select all columns from inner table\n\t\t\t{\n\t\t\t\tResTarget: {\n\t\t\t\t\tval: {\n\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\tfields: [{ String: { sval: innerAlias } }, { A_Star: {} }],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t// __depth = 1\n\t\t\t{\n\t\t\t\tResTarget: {\n\t\t\t\t\tval: integerNode(1),\n\t\t\t\t\tname: '__depth',\n\t\t\t\t},\n\t\t\t},\n\t\t\t// __visited = ARRAY[pk]\n\t\t\t{\n\t\t\t\tResTarget: {\n\t\t\t\t\tval: {\n\t\t\t\t\t\tA_ArrayExpr: {\n\t\t\t\t\t\t\telements: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t\t\t\t\t\t{ String: { sval: dbPk } },\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tname: '__visited',\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\tfromClause: [\n\t\t\t{\n\t\t\t\tRangeVar: {\n\t\t\t\t\trelname: dbTable,\n\t\t\t\t\t...(ctx.schema && { schemaname: ctx.schema }),\n\t\t\t\t\tinh: true,\n\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t\talias: { aliasname: innerAlias },\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\t// Anchor WHERE: depends on direction\n\t\twhereClause: isAncestors\n\t\t\t? // Ancestors: start from parent of outer row (outer.fk)\n\t\t\t\teqExpr(\n\t\t\t\t\t{\n\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t\t\t{ String: { sval: dbPk } },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t{ String: { sval: dbOuter } },\n\t\t\t\t\t\t\t\t{ String: { sval: dbFk } },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t: // Descendants: start from children of outer row (where fk = outer.pk)\n\t\t\t\teqExpr(\n\t\t\t\t\t{\n\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t\t\t{ String: { sval: dbFk } },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t{ String: { sval: dbOuter } },\n\t\t\t\t\t\t\t\t{ String: { sval: dbPk } },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t),\n\t};\n\n\t// Build recursive SELECT\n\tconst recursiveSelect: SelectStmt = {\n\t\ttargetList: [\n\t\t\t// Select all from new row\n\t\t\t{\n\t\t\t\tResTarget: {\n\t\t\t\t\tval: {\n\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\tfields: [{ String: { sval: innerAlias } }, { A_Star: {} }],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t// __depth + 1\n\t\t\t{\n\t\t\t\tResTarget: {\n\t\t\t\t\tval: binaryExpr(\n\t\t\t\t\t\t'+',\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t\t\t\t{ String: { sval: '__depth' } },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tintegerNode(1),\n\t\t\t\t\t),\n\t\t\t\t\tname: '__depth',\n\t\t\t\t},\n\t\t\t},\n\t\t\t// __visited || pk (array concatenation)\n\t\t\t{\n\t\t\t\tResTarget: {\n\t\t\t\t\tval: binaryExpr(\n\t\t\t\t\t\t'||',\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t\t\t\t{ String: { sval: '__visited' } },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t\t\t\t{ String: { sval: dbPk } },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t),\n\t\t\t\t\tname: '__visited',\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\tfromClause: [\n\t\t\t// FROM __rc\n\t\t\t{\n\t\t\t\tRangeVar: {\n\t\t\t\t\trelname: cteAlias,\n\t\t\t\t\tinh: true,\n\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t},\n\t\t\t},\n\t\t\t// INNER JOIN table AS __n\n\t\t\t{\n\t\t\t\tJoinExpr: {\n\t\t\t\t\tjointype: 'JOIN_INNER',\n\t\t\t\t\tlarg: {\n\t\t\t\t\t\tRangeVar: {\n\t\t\t\t\t\t\trelname: cteAlias,\n\t\t\t\t\t\t\tinh: true,\n\t\t\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\trarg: {\n\t\t\t\t\t\tRangeVar: {\n\t\t\t\t\t\t\trelname: dbTable,\n\t\t\t\t\t\t\t...(ctx.schema && { schemaname: ctx.schema }),\n\t\t\t\t\t\t\tinh: true,\n\t\t\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t\t\t\talias: { aliasname: innerAlias },\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t// Join condition depends on direction\n\t\t\t\t\tquals: isAncestors\n\t\t\t\t\t\t? // Ancestors: n.pk = __rc.fk (traverse up)\n\t\t\t\t\t\t\teqExpr(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t\t\t\t\t\t{ String: { sval: dbPk } },\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t\t\t\t\t\t{ String: { sval: dbFk } },\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: // Descendants: n.fk = __rc.pk (traverse down)\n\t\t\t\t\t\t\teqExpr(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t\t\t\t\t\t{ String: { sval: dbFk } },\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t\t\t\t\t\t{ String: { sval: dbPk } },\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\t// WHERE: depth check AND cycle detection\n\t\twhereClause: {\n\t\t\tBoolExpr: {\n\t\t\t\tboolop: 'AND_EXPR',\n\t\t\t\targs: [\n\t\t\t\t\t// __depth < maxDepth\n\t\t\t\t\tbinaryExpr(\n\t\t\t\t\t\t'<',\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t\t\t\t{ String: { sval: '__depth' } },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tintegerNode(maxDepth),\n\t\t\t\t\t),\n\t\t\t\t\t// pk <> ALL(__visited) — cycle detection\n\t\t\t\t\t{\n\t\t\t\t\t\tA_Expr: {\n\t\t\t\t\t\t\tkind: 'AEXPR_OP_ALL',\n\t\t\t\t\t\t\tname: [{ String: { sval: '<>' } }],\n\t\t\t\t\t\t\tlexpr: {\n\t\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t\t\t\t\t{ String: { sval: dbPk } },\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\trexpr: {\n\t\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t\t\t\t\t{ String: { sval: '__visited' } },\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t};\n\n\t// Build CTE: anchor UNION ALL recursive\n\tconst cteSelect: Node = {\n\t\tSelectStmt: {\n\t\t\top: 'SETOP_UNION',\n\t\t\tall: true,\n\t\t\tlarg: anchorSelect,\n\t\t\trarg: recursiveSelect,\n\t\t},\n\t};\n\n\tconst cte: CommonTableExpr = {\n\t\tctename: cteAlias,\n\t\tctequery: cteSelect,\n\t\tcterecursive: true,\n\t};\n\n\t// Build final SELECT with json_agg\n\tconst dbSelectCol = naming.toDatabase(selectColumn);\n\tconst finalSelect: SelectStmt = {\n\t\ttargetList: [\n\t\t\t{\n\t\t\t\tResTarget: {\n\t\t\t\t\tval: coalesce(\n\t\t\t\t\t\tfuncCall('json_agg', [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t\t\t\t\t{ String: { sval: dbSelectCol } },\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]),\n\t\t\t\t\t\t// Empty array fallback: '[]'::json\n\t\t\t\t\t\ttypeCast(stringNode('[]'), 'json'),\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\tfromClause: [\n\t\t\t{\n\t\t\t\tRangeVar: {\n\t\t\t\t\trelname: cteAlias,\n\t\t\t\t\tinh: true,\n\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\t// ORDER BY __depth inside json_agg would go here but json_agg doesn't support it directly\n\t\t// We'd need to use json_agg(col ORDER BY __depth) — handled by FuncCall aggregate\n\t\twithClause: {\n\t\t\tctes: [{ CommonTableExpr: cte }],\n\t\t\trecursive: true,\n\t\t},\n\t};\n\n\t// Wrap in SubLink (scalar subquery)\n\tconst subLink: SubLink = {\n\t\tsubLinkType: 'EXPR_SUBLINK',\n\t\tsubselect: { SelectStmt: finalSelect },\n\t};\n\n\treturn { SubLink: subLink };\n}\n\n// ============================================================================\n// Handlers\n// ============================================================================\n\n/**\n * Pseudo-column handler for recursive traversals (ascendant/descendant)\n *\n * Produces: (WITH RECURSIVE ... SELECT json_agg(...))\n */\nexport const pseudoColumnHandler: ExpressionHandler = {\n\ttypes: ['pseudoColumn', 'pseudo', 'hierarchy'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst traversal = decision.traversal;\n\t\tconst targetColumn = requiredColumn(\n\t\t\tdecision.column,\n\t\t\t'column',\n\t\t\t'pseudo traversal',\n\t\t);\n\t\tconst table = decision.table ?? ctx.rootTable;\n\t\tconst pkColumn = requiredColumn(\n\t\t\tdecision.pkColumn,\n\t\t\t'pkColumn',\n\t\t\t'pseudo traversal',\n\t\t);\n\t\tconst fkColumn = decision.fkColumn ?? 'parent_id';\n\t\tconst maxDepth = decision.maxDepth ?? ctx.maxRecursiveDepth;\n\n\t\tif (!traversal) {\n\t\t\tthrow new Error('Pseudo-column handler requires traversal');\n\t\t}\n\n\t\t// Determine direction based on traversal keyword\n\t\tconst isAncestors =\n\t\t\ttraversal === 'ascendant' ||\n\t\t\ttraversal === 'ancestors' ||\n\t\t\ttraversal === 'parent' ||\n\t\t\ttraversal === 'managementChain' ||\n\t\t\ttraversal.startsWith('ascendant');\n\n\t\t// Generate unique CTE alias\n\t\tconst cteIndex = state.ctes.size;\n\t\tconst cteAlias = `__rc_${cteIndex}`;\n\n\t\tconst outerAlias = ctx.currentAlias ?? ctx.rootTable;\n\n\t\treturn buildRecursiveScalarSubquery({\n\t\t\tcteAlias,\n\t\t\ttable,\n\t\t\tpkColumn,\n\t\t\tfkColumn,\n\t\t\touterAlias,\n\t\t\tisAncestors,\n\t\t\tmaxDepth,\n\t\t\tselectColumn: targetColumn,\n\t\t\tctx,\n\t\t});\n\t},\n};\n\n/**\n * Single-hop pseudo-column handler (parent/child)\n *\n * For single-hop traversals, we use a correlated subquery rather than JOIN\n * to keep it as a scalar expression.\n *\n * Produces: (SELECT col FROM table WHERE pk = outer.fk)\n */\nexport const singleHopPseudoHandler: ExpressionHandler = {\n\ttypes: ['singleHopPseudo', 'parentPseudo', 'childPseudo'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\t_state: CompilerState,\n\t): Node {\n\t\tconst targetColumn = requiredColumn(\n\t\t\tdecision.column,\n\t\t\t'column',\n\t\t\t'single-hop pseudo',\n\t\t);\n\t\tconst table = decision.table ?? ctx.rootTable;\n\t\tconst pkColumn = requiredColumn(\n\t\t\tdecision.pkColumn,\n\t\t\t'pkColumn',\n\t\t\t'single-hop pseudo',\n\t\t);\n\t\tconst fkColumn = decision.fkColumn ?? 'parent_id';\n\t\tconst traversal = decision.traversal ?? 'parent';\n\n\t\tconst naming = ctx.naming;\n\t\tconst dbTable = naming.toDatabase(table);\n\t\tconst dbPk = naming.toDatabase(pkColumn);\n\t\tconst dbFk = naming.toDatabase(fkColumn);\n\t\tconst dbCol = naming.toDatabase(targetColumn);\n\t\tconst outerAlias = naming.toDatabase(ctx.currentAlias ?? ctx.rootTable);\n\n\t\tconst innerAlias = '__p';\n\n\t\t// Determine direction\n\t\tconst isParent = traversal === 'parent' || traversal === 'manager';\n\n\t\t// Build subquery: SELECT col FROM table WHERE pk = outer.fk (parent)\n\t\t// SELECT col FROM table WHERE fk = outer.pk (child - returns first)\n\t\tconst subSelect: SelectStmt = {\n\t\t\ttargetList: [\n\t\t\t\t{\n\t\t\t\t\tResTarget: {\n\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t\t\t\t{ String: { sval: dbCol } },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t\tfromClause: [\n\t\t\t\t{\n\t\t\t\t\tRangeVar: {\n\t\t\t\t\t\trelname: dbTable,\n\t\t\t\t\t\t...(ctx.schema && { schemaname: ctx.schema }),\n\t\t\t\t\t\tinh: true,\n\t\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t\t\talias: { aliasname: innerAlias },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t\twhereClause: isParent\n\t\t\t\t? eqExpr(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t\t\t\t{ String: { sval: dbPk } },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t{ String: { sval: outerAlias } },\n\t\t\t\t\t\t\t\t\t{ String: { sval: dbFk } },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t)\n\t\t\t\t: eqExpr(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t\t\t\t{ String: { sval: dbFk } },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t{ String: { sval: outerAlias } },\n\t\t\t\t\t\t\t\t\t{ String: { sval: dbPk } },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t),\n\t\t\tlimitCount: integerNode(1), // Return only first match for child\n\t\t};\n\n\t\tconst subLink: SubLink = {\n\t\t\tsubLinkType: 'EXPR_SUBLINK',\n\t\t\tsubselect: { SelectStmt: subSelect },\n\t\t};\n\n\t\treturn { SubLink: subLink };\n\t},\n};\n\n/**\n * Chained pseudo-column handler (parent.parent.name)\n *\n * For chained traversals, we build nested correlated subqueries.\n *\n * Produces: (SELECT (SELECT col FROM t WHERE t.pk = p.fk) FROM t AS p WHERE p.pk = outer.fk)\n */\nexport const chainedPseudoHandler: ExpressionHandler = {\n\ttypes: ['chainedPseudo', 'multiHopPseudo'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\t_state: CompilerState,\n\t): Node {\n\t\tconst traversals = decision.traversals;\n\t\tconst table = decision.table ?? ctx.rootTable;\n\t\tconst pkColumn = requiredColumn(\n\t\t\tdecision.pkColumn,\n\t\t\t'pkColumn',\n\t\t\t'chained pseudo',\n\t\t);\n\t\tconst fkColumn = decision.fkColumn ?? 'parent_id';\n\n\t\tif (!traversals || traversals.length === 0) {\n\t\t\tthrow new Error('Chained pseudo handler requires traversals array');\n\t\t}\n\n\t\tconst naming = ctx.naming;\n\t\tconst dbTable = naming.toDatabase(table);\n\t\tconst dbPk = naming.toDatabase(pkColumn);\n\t\tconst dbFk = naming.toDatabase(fkColumn);\n\n\t\t// Build from innermost to outermost\n\t\t// Start with the final column selection\n\t\tconst lastTraversal = traversals[traversals.length - 1]!;\n\t\tconst targetCol = naming.toDatabase(\n\t\t\trequiredColumn(\n\t\t\t\tlastTraversal.targetColumn,\n\t\t\t\t'targetColumn',\n\t\t\t\t'chained pseudo',\n\t\t\t),\n\t\t);\n\n\t\t// Build nested subqueries from inside out\n\t\tlet currentExpr: Node = {\n\t\t\tColumnRef: {\n\t\t\t\tfields: [\n\t\t\t\t\t{ String: { sval: `__p${traversals.length - 1}` } },\n\t\t\t\t\t{ String: { sval: targetCol } },\n\t\t\t\t],\n\t\t\t},\n\t\t};\n\n\t\t// Wrap in subqueries for each hop (reverse order)\n\t\tfor (let i = traversals.length - 1; i >= 0; i--) {\n\t\t\tconst alias = `__p${i}`;\n\t\t\tconst outerRef =\n\t\t\t\ti === 0\n\t\t\t\t\t? naming.toDatabase(ctx.currentAlias ?? ctx.rootTable)\n\t\t\t\t\t: `__p${i - 1}`;\n\n\t\t\tconst subSelect: SelectStmt = {\n\t\t\t\ttargetList: [{ ResTarget: { val: currentExpr } }],\n\t\t\t\tfromClause: [\n\t\t\t\t\t{\n\t\t\t\t\t\tRangeVar: {\n\t\t\t\t\t\t\trelname: dbTable,\n\t\t\t\t\t\t\t...(ctx.schema && { schemaname: ctx.schema }),\n\t\t\t\t\t\t\tinh: true,\n\t\t\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t\t\t\talias: { aliasname: alias },\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\twhereClause: eqExpr(\n\t\t\t\t\t{\n\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\tfields: [{ String: { sval: alias } }, { String: { sval: dbPk } }],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t{ String: { sval: outerRef } },\n\t\t\t\t\t\t\t\t{ String: { sval: dbFk } },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t};\n\n\t\t\tif (i > 0) {\n\t\t\t\t// Intermediate levels: wrap in sublink\n\t\t\t\tcurrentExpr = {\n\t\t\t\t\tSubLink: {\n\t\t\t\t\t\tsubLinkType: 'EXPR_SUBLINK',\n\t\t\t\t\t\tsubselect: { SelectStmt: subSelect },\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\t// Outermost: return the sublink\n\t\t\t\treturn {\n\t\t\t\t\tSubLink: {\n\t\t\t\t\t\tsubLinkType: 'EXPR_SUBLINK',\n\t\t\t\t\t\tsubselect: { SelectStmt: subSelect },\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\t// Fallback (shouldn't reach here)\n\t\treturn currentExpr;\n\t},\n};\n","/**\n * Raw SQL Expression Handler\n *\n * ⚠️ DANGEROUS: Allows arbitrary SQL to be injected.\n * Use only as a last resort escape hatch.\n *\n * This handler is intentionally restrictive:\n * - Requires explicit opt-in via type: 'raw'\n * - Logs warnings when used\n * - Should be audited in code reviews\n */\n\nimport { getLogger } from '@dbsp/core';\nimport type { Node } from '@pgsql/types';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tExpressionHandler,\n} from '../types.js';\n\n/**\n * Build a raw SQL expression\n *\n * ⚠️ WARNING: This bypasses all SQL safety checks.\n * Only use for expressions that cannot be represented in the planner.\n */\nfunction buildRawExpression(sql: string): Node {\n\t// Custom RawSQL node — handled by our deparser as verbatim SQL passthrough.\n\t// No WASM parser dependency — the deparser outputs the SQL string as-is.\n\treturn { RawSQL: { sql } } as unknown as Node;\n}\n\n/**\n * Raw SQL handler\n *\n * ⚠️ DANGEROUS: Use with extreme caution.\n *\n * Allows arbitrary SQL to be inserted into the query.\n * This is an escape hatch for expressions that cannot be\n * represented through the normal planner/compiler path.\n *\n * Example usage:\n * {\n * type: 'raw',\n * value: 'EXTRACT(EPOCH FROM created_at)'\n * }\n */\nexport const rawHandler: ExpressionHandler = {\n\ttypes: ['raw', 'RAW', 'rawSql', 'rawExpression'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\t_state: CompilerState,\n\t): Node {\n\t\t// SQL may arrive via args[0] (from handleRawExpression / selectFunction path)\n\t\t// or via value (legacy direct Decision construction).\n\t\tconst sql =\n\t\t\t(Array.isArray(decision.args) ? decision.args[0] : undefined) ??\n\t\t\tdecision.value;\n\n\t\tif (typeof sql !== 'string') {\n\t\t\tthrow new Error('Raw expression requires a string SQL value');\n\t\t}\n\n\t\tif (sql.length === 0) {\n\t\t\tthrow new Error('Raw expression cannot be empty');\n\t\t}\n\n\t\t// Audit trail callback (opt-in)\n\t\tctx.onRawSQL?.(sql);\n\n\t\t// Log warning in development\n\t\tif (process.env.NODE_ENV !== 'production') {\n\t\t\tgetLogger().warn(\n\t\t\t\t`[adapter-pgsql] ⚠️ Raw SQL expression used: ${sql.slice(0, 50)}${sql.length > 50 ? '...' : ''}`,\n\t\t\t);\n\t\t}\n\n\t\treturn buildRawExpression(sql);\n\t},\n};\n\n/**\n * SQL Function call handler (safer alternative to raw)\n *\n * Allows calling arbitrary SQL functions with validated arguments.\n * Safer than raw because arguments are parameterized.\n */\nexport const sqlFunctionHandler: ExpressionHandler = {\n\ttypes: ['sqlFunction', 'fn', 'func'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\t_ctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst funcName = decision.function;\n\t\tconst args = decision.args;\n\n\t\tif (!funcName) {\n\t\t\tthrow new Error('SQL function requires function name');\n\t\t}\n\n\t\t// Validate function name (alphanumeric + underscore only)\n\t\tif (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(funcName)) {\n\t\t\tthrow new Error(`Invalid function name: ${funcName}`);\n\t\t}\n\n\t\t// Build argument nodes\n\t\tconst argNodes: Node[] = [];\n\t\tif (args && Array.isArray(args)) {\n\t\t\tfor (const arg of args) {\n\t\t\t\tif (typeof arg === 'object' && arg !== null && 'type' in arg) {\n\t\t\t\t\t// Nested decision - would need recursive compilation\n\t\t\t\t\t// For now, just parameterize\n\t\t\t\t\tconst paramNumber = ++state.paramIndex;\n\t\t\t\t\tstate.parameters.push(arg);\n\t\t\t\t\targNodes.push({\n\t\t\t\t\t\tParamRef: { number: paramNumber },\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tconst paramNumber = ++state.paramIndex;\n\t\t\t\t\tstate.parameters.push(arg);\n\t\t\t\t\targNodes.push({\n\t\t\t\t\t\tParamRef: { number: paramNumber },\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tFuncCall: {\n\t\t\t\tfuncname: [{ String: { sval: funcName } }],\n\t\t\t\t...(argNodes.length > 0 && { args: argNodes }),\n\t\t\t},\n\t\t};\n\t},\n};\n\n/**\n * SQL Literal handler\n *\n * Creates a typed literal value (for constants that need specific types).\n */\nexport const literalHandler: ExpressionHandler = {\n\ttypes: ['literal', 'lit', 'const'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\t_ctx: CompilerContext,\n\t\t_state: CompilerState,\n\t): Node {\n\t\tconst value = decision.value;\n\n\t\tif (value === null || value === undefined) {\n\t\t\treturn { A_Const: { isnull: true } };\n\t\t}\n\n\t\tif (typeof value === 'boolean') {\n\t\t\treturn { A_Const: { boolval: { boolval: value } } };\n\t\t}\n\n\t\tif (typeof value === 'number') {\n\t\t\tif (Number.isInteger(value)) {\n\t\t\t\treturn { A_Const: { ival: { ival: value } } };\n\t\t\t}\n\t\t\treturn { A_Const: { fval: { fval: String(value) } } };\n\t\t}\n\n\t\tif (typeof value === 'string') {\n\t\t\treturn { A_Const: { sval: { sval: value } } };\n\t\t}\n\n\t\t// For other types, stringify\n\t\treturn { A_Const: { sval: { sval: String(value) } } };\n\t},\n};\n","/**\n * Relation Column Expansion Handlers\n *\n * Handles relation.* column expansion for includes.\n * When selecting from a relation (e.g., posts.* or author.name),\n * expands to the appropriate columns from the joined table.\n *\n * Produces: qualified column references from related tables.\n */\n\nimport type { Node, ResTarget } from '@pgsql/types';\nimport { columnRef, columnRefStar } from '../../ast-helpers.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tExpressionHandler,\n} from '../types.js';\n\n/**\n * Relation star handler\n *\n * Expands relation.* to qualified star for the relation's table alias.\n *\n * Produces: relation_alias.*\n */\nexport const relationStarHandler: ExpressionHandler = {\n\ttypes: ['relationStar', 'relation.*', 'expandStar'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst relation = decision.relation ?? decision.expandRelation;\n\n\t\tif (!relation) {\n\t\t\tthrow new Error('Relation star handler requires relation name');\n\t\t}\n\n\t\t// Look up the alias for this relation from state\n\t\tconst alias = state.aliases.get(relation) ?? relation;\n\t\tconst dbAlias = ctx.naming.toDatabase(alias);\n\n\t\t// Return qualified star: alias.*\n\t\treturn {\n\t\t\tColumnRef: {\n\t\t\t\tfields: [{ String: { sval: dbAlias } }, { A_Star: {} }],\n\t\t\t},\n\t\t};\n\t},\n};\n\n/**\n * Relation column handler\n *\n * References a specific column from a relation.\n *\n * Produces: relation_alias.column\n */\nexport const relationColumnHandler: ExpressionHandler = {\n\ttypes: ['relationColumn', 'relation.column', 'relCol'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst relation = decision.relation ?? decision.expandRelation;\n\t\tconst column = decision.column;\n\n\t\tif (!relation) {\n\t\t\tthrow new Error('Relation column handler requires relation name');\n\t\t}\n\t\tif (!column) {\n\t\t\tthrow new Error('Relation column handler requires column name');\n\t\t}\n\n\t\t// Look up the alias for this relation from state.\n\t\t// For dotted paths like 'callee.file', split and resolve only the final\n\t\t// segment — state.aliases keyed by the leaf relation name.\n\t\t// A dotted path in state (unlikely) is also supported via direct lookup.\n\t\tlet alias: string;\n\t\tif (relation.includes('.')) {\n\t\t\tconst segments = relation.split('.');\n\t\t\tconst leaf = segments[segments.length - 1]!;\n\t\t\talias = state.aliases.get(leaf) ?? state.aliases.get(relation) ?? leaf;\n\t\t} else {\n\t\t\talias = state.aliases.get(relation) ?? relation;\n\t\t}\n\n\t\t// Wildcard: relation.* should produce unquoted * (A_Star), not quoted \"*\"\n\t\tif (column === '*') {\n\t\t\treturn columnRefStar(alias, ctx.naming);\n\t\t}\n\n\t\treturn columnRef(column, alias, undefined, ctx.naming);\n\t},\n};\n\n/**\n * Relation columns expansion handler\n *\n * Expands a list of columns from a relation into ResTarget nodes.\n * Used when selecting specific columns from a relation.\n *\n * Note: This handler returns an array wrapped in a special container node.\n * The caller must unwrap it appropriately.\n *\n * Produces: Array of ResTarget nodes\n */\nexport const relationColumnsHandler: ExpressionHandler = {\n\ttypes: ['relationColumns', 'expandColumns', 'relCols'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst relation = decision.relation ?? decision.expandRelation;\n\t\tconst columns = decision.relationColumns ?? decision.columns;\n\n\t\tif (!relation) {\n\t\t\tthrow new Error('Relation columns handler requires relation name');\n\t\t}\n\t\tif (!columns || columns.length === 0) {\n\t\t\tthrow new Error('Relation columns handler requires columns array');\n\t\t}\n\n\t\t// Look up the alias for this relation from state\n\t\tconst alias = state.aliases.get(relation) ?? relation;\n\n\t\t// Build the first column reference (handler must return a single node)\n\t\t// For multiple columns, the compiler should call this handler multiple times\n\t\t// or use a different approach\n\t\tconst column = columns[0]!;\n\t\tconst colRef = columnRef(column, alias, undefined, ctx.naming);\n\n\t\t// If there's an alias specified, wrap in ResTarget\n\t\tconst outputAlias = decision.alias;\n\t\tif (outputAlias) {\n\t\t\tconst resTarget: ResTarget = {\n\t\t\t\tval: colRef,\n\t\t\t\tname: ctx.naming.toDatabase(outputAlias),\n\t\t\t};\n\t\t\treturn { ResTarget: resTarget };\n\t\t}\n\n\t\treturn colRef;\n\t},\n};\n\n/**\n * Relation alias handler\n *\n * References a column from a relation with an output alias.\n *\n * Produces: relation_alias.column AS output_alias\n */\nexport const relationAliasHandler: ExpressionHandler = {\n\ttypes: ['relationAlias', 'relation.column.as', 'relColAs'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst relation = decision.relation ?? decision.expandRelation;\n\t\tconst column = decision.column;\n\t\tconst outputAlias = decision.alias;\n\n\t\tif (!relation) {\n\t\t\tthrow new Error('Relation alias handler requires relation name');\n\t\t}\n\t\tif (!column) {\n\t\t\tthrow new Error('Relation alias handler requires column name');\n\t\t}\n\n\t\t// Look up the alias for this relation from state\n\t\tconst tableAlias = state.aliases.get(relation) ?? relation;\n\t\tconst colRef = columnRef(column, tableAlias, undefined, ctx.naming);\n\n\t\t// If no output alias, return just the column ref\n\t\tif (!outputAlias) {\n\t\t\treturn colRef;\n\t\t}\n\n\t\t// Wrap in ResTarget with output alias\n\t\tconst resTarget: ResTarget = {\n\t\t\tval: colRef,\n\t\t\tname: ctx.naming.toDatabase(outputAlias),\n\t\t};\n\n\t\treturn { ResTarget: resTarget };\n\t},\n};\n\n/**\n * Prefixed relation column handler\n *\n * References a column from a relation with automatic prefixed alias.\n * Used to avoid column name conflicts when joining multiple tables.\n *\n * Produces: relation_alias.column AS relation_column\n */\nexport const prefixedRelationColumnHandler: ExpressionHandler = {\n\ttypes: ['prefixedRelationColumn', 'prefixedRelCol'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst relation = decision.relation ?? decision.expandRelation;\n\t\tconst column = decision.column;\n\n\t\tif (!relation) {\n\t\t\tthrow new Error(\n\t\t\t\t'Prefixed relation column handler requires relation name',\n\t\t\t);\n\t\t}\n\t\tif (!column) {\n\t\t\tthrow new Error('Prefixed relation column handler requires column name');\n\t\t}\n\n\t\t// Look up the alias for this relation from state\n\t\tconst tableAlias = state.aliases.get(relation) ?? relation;\n\t\tconst colRef = columnRef(column, tableAlias, undefined, ctx.naming);\n\n\t\t// Create prefixed output alias: relation_column\n\t\tconst prefixedAlias = `${relation}_${column}`;\n\n\t\tconst resTarget: ResTarget = {\n\t\t\tval: colRef,\n\t\t\tname: ctx.naming.toDatabase(prefixedAlias),\n\t\t};\n\n\t\treturn { ResTarget: resTarget };\n\t},\n};\n","/**\n * Window Function Expression Handlers\n *\n * Handles: ROW_NUMBER, RANK, DENSE_RANK, NTILE, LEAD, LAG, FIRST_VALUE, LAST_VALUE\n *\n * Produces FuncCall nodes with WindowDef (OVER clause).\n */\n\nimport type { Node, SortBy, WindowDef } from '@pgsql/types';\nimport { columnRef } from '../../ast-helpers.js';\nimport { createParamRef } from '../../param-ref.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tExpressionHandler,\n} from '../types.js';\n\n/**\n * Default window frame options for bare OVER() clause.\n * Value: FRAMEOPTION_NONDEFAULT | FRAMEOPTION_RANGE | FRAMEOPTION_BETWEEN |\n * FRAMEOPTION_START_UNBOUNDED_PRECEDING | FRAMEOPTION_END_CURRENT_ROW\n * See: src/include/nodes/parsenodes.h in PostgreSQL source\n */\nconst WINDOW_FRAME_DEFAULT = 1034;\n\n/**\n * Build a SortBy node for ORDER BY clause\n */\nfunction buildSortBy(\n\tcolumn: string,\n\tdirection: 'ASC' | 'DESC' | undefined,\n\tctx: CompilerContext,\n): Node {\n\tconst tableAlias = ctx.currentAlias ?? ctx.rootTable;\n\tconst colRef = columnRef(column, tableAlias, undefined, ctx.naming);\n\n\tconst sortBy: SortBy = {\n\t\tnode: colRef,\n\t\tsortby_dir: direction === 'DESC' ? 'SORTBY_DESC' : 'SORTBY_ASC',\n\t\tsortby_nulls: 'SORTBY_NULLS_DEFAULT',\n\t};\n\n\treturn { SortBy: sortBy };\n}\n\n/**\n * Build a WindowDef (OVER clause)\n */\nfunction buildWindowDef(decision: Decision, ctx: CompilerContext): WindowDef {\n\tconst partition = decision.partition;\n\tconst orderBy = decision.orderBy;\n\tconst frame = decision.frame;\n\n\tconst tableAlias = ctx.currentAlias ?? ctx.rootTable;\n\n\t// frameOptions: WINDOW_FRAME_DEFAULT is the default implicit frame (NONDEFAULT\n\t// bit not set → no frame clause emitted by deparser). Required for the OVER()\n\t// clause to be emitted correctly even when there are no PARTITION BY or ORDER BY.\n\tconst windowDef: WindowDef = { frameOptions: WINDOW_FRAME_DEFAULT };\n\n\t// PARTITION BY\n\tif (partition && partition.length > 0) {\n\t\twindowDef.partitionClause = partition.map((col) =>\n\t\t\tcolumnRef(col, tableAlias, undefined, ctx.naming),\n\t\t);\n\t}\n\n\t// ORDER BY\n\tif (orderBy && orderBy.length > 0) {\n\t\twindowDef.orderClause = orderBy.map((item) =>\n\t\t\tbuildSortBy(item.column, item.direction, ctx),\n\t\t);\n\t}\n\n\t// Frame clause (ROWS/RANGE BETWEEN ... AND ...): skipped for now,\n\t// PostgreSQL uses defaults when frame is not explicitly set.\n\tif (frame) {\n\t\t// Future: parse and emit frame clause\n\t\tvoid frame;\n\t}\n\n\treturn windowDef;\n}\n\n/**\n * Build a window function call\n */\nfunction buildWindowFunction(\n\tfuncName: string,\n\targs: Node[],\n\tdecision: Decision,\n\tctx: CompilerContext,\n): Node {\n\tconst windowDef = buildWindowDef(decision, ctx);\n\n\treturn {\n\t\tFuncCall: {\n\t\t\tfuncname: [{ String: { sval: funcName.toLowerCase() } }],\n\t\t\t...(args.length > 0 && { args }),\n\t\t\tover: windowDef,\n\t\t},\n\t};\n}\n\n/**\n * Factory for no-argument window function handlers (ROW_NUMBER, RANK, DENSE_RANK, etc.).\n * Produces: FUNC() OVER (PARTITION BY ... ORDER BY ...)\n */\nfunction createNoArgWindowHandler(\n\tfuncName: string,\n\ttypes: string[],\n): ExpressionHandler {\n\treturn {\n\t\ttypes,\n\t\tcompile(\n\t\t\tdecision: Decision,\n\t\t\tctx: CompilerContext,\n\t\t\t_state: CompilerState,\n\t\t): Node {\n\t\t\treturn buildWindowFunction(funcName, [], decision, ctx);\n\t\t},\n\t};\n}\n\n/** ROW_NUMBER() OVER (...) handler */\nexport const rowNumberHandler = createNoArgWindowHandler('row_number', [\n\t'rowNumber',\n\t'ROW_NUMBER',\n\t'row_number',\n]);\n\n/** RANK() OVER (...) handler */\nexport const rankHandler = createNoArgWindowHandler('rank', ['rank', 'RANK']);\n\n/** DENSE_RANK() OVER (...) handler */\nexport const denseRankHandler = createNoArgWindowHandler('dense_rank', [\n\t'denseRank',\n\t'DENSE_RANK',\n\t'dense_rank',\n]);\n\n/**\n * NTILE(n) handler\n */\nexport const ntileHandler: ExpressionHandler = {\n\ttypes: ['ntile', 'NTILE'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst n = decision.value ?? decision.args?.[0] ?? 4;\n\t\tconst paramNumber = ++state.paramIndex;\n\t\tstate.parameters.push(n);\n\t\tconst nRef = createParamRef(paramNumber);\n\n\t\treturn buildWindowFunction('ntile', [nRef], decision, ctx);\n\t},\n};\n\n/**\n * Factory for LAG/LEAD-style window handlers: FUNC(column, offset, default) OVER (...).\n */\nfunction createLagLeadHandler(\n\tfuncName: string,\n\ttypes: string[],\n): ExpressionHandler {\n\tconst upperName = funcName.toUpperCase();\n\treturn {\n\t\ttypes,\n\t\tcompile(\n\t\t\tdecision: Decision,\n\t\t\tctx: CompilerContext,\n\t\t\tstate: CompilerState,\n\t\t): Node {\n\t\t\tconst column = decision.column;\n\t\t\tif (!column) {\n\t\t\t\tthrow new Error(`${upperName} requires a column`);\n\t\t\t}\n\n\t\t\tconst tableAlias = ctx.currentAlias ?? ctx.rootTable;\n\t\t\tconst colRef = columnRef(column, tableAlias, undefined, ctx.naming);\n\n\t\t\tconst args: Node[] = [colRef];\n\n\t\t\t// Optional offset (default 1)\n\t\t\tconst offset = decision.args?.[0] ?? 1;\n\t\t\tconst offsetParamNumber = ++state.paramIndex;\n\t\t\tstate.parameters.push(offset);\n\t\t\targs.push(createParamRef(offsetParamNumber));\n\n\t\t\t// Optional default value\n\t\t\tif (decision.value !== undefined) {\n\t\t\t\tconst defaultParamNumber = ++state.paramIndex;\n\t\t\t\tstate.parameters.push(decision.value);\n\t\t\t\targs.push(createParamRef(defaultParamNumber));\n\t\t\t}\n\n\t\t\treturn buildWindowFunction(funcName, args, decision, ctx);\n\t\t},\n\t};\n}\n\n/** LAG(column, offset, default) OVER (...) handler */\nexport const lagHandler = createLagLeadHandler('lag', ['lag', 'LAG']);\n\n/** LEAD(column, offset, default) OVER (...) handler */\nexport const leadHandler = createLagLeadHandler('lead', ['lead', 'LEAD']);\n\n/**\n * Factory for single-column window value handlers (FIRST_VALUE, LAST_VALUE).\n * Produces: FUNC(column) OVER (...)\n */\nfunction createColumnWindowHandler(\n\tfuncName: string,\n\ttypes: string[],\n): ExpressionHandler {\n\tconst upperName = funcName.toUpperCase();\n\treturn {\n\t\ttypes,\n\t\tcompile(\n\t\t\tdecision: Decision,\n\t\t\tctx: CompilerContext,\n\t\t\t_state: CompilerState,\n\t\t): Node {\n\t\t\tconst column = decision.column;\n\t\t\tif (!column) {\n\t\t\t\tthrow new Error(`${upperName} requires a column`);\n\t\t\t}\n\n\t\t\tconst tableAlias = ctx.currentAlias ?? ctx.rootTable;\n\t\t\tconst colRef = columnRef(column, tableAlias, undefined, ctx.naming);\n\n\t\t\treturn buildWindowFunction(funcName, [colRef], decision, ctx);\n\t\t},\n\t};\n}\n\n/** FIRST_VALUE(column) OVER (...) handler */\nexport const firstValueHandler = createColumnWindowHandler('first_value', [\n\t'firstValue',\n\t'FIRST_VALUE',\n\t'first_value',\n]);\n\n/** LAST_VALUE(column) OVER (...) handler */\nexport const lastValueHandler = createColumnWindowHandler('last_value', [\n\t'lastValue',\n\t'LAST_VALUE',\n\t'last_value',\n]);\n\n/**\n * Generic window function handler\n */\nexport const genericWindowHandler: ExpressionHandler = {\n\ttypes: ['window', 'windowFunc'],\n\n\tcompile(\n\t\tdecision: Decision,\n\t\tctx: CompilerContext,\n\t\tstate: CompilerState,\n\t): Node {\n\t\tconst funcName = decision.function;\n\t\tif (!funcName) {\n\t\t\tthrow new Error('Window function requires function name');\n\t\t}\n\n\t\t// count() without a column → count(*) using agg_star\n\t\tconst isCountStar =\n\t\t\tfuncName.toLowerCase() === 'count' &&\n\t\t\t!decision.column &&\n\t\t\t(!decision.args || decision.args.length === 0);\n\n\t\tif (isCountStar) {\n\t\t\tconst windowDef = buildWindowDef(decision, ctx);\n\t\t\treturn {\n\t\t\t\tFuncCall: {\n\t\t\t\t\tfuncname: [{ String: { sval: 'count' } }],\n\t\t\t\t\tagg_star: true,\n\t\t\t\t\tover: windowDef,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst args: Node[] = [];\n\n\t\t// Add column if specified\n\t\tif (decision.column) {\n\t\t\tconst tableAlias = ctx.currentAlias ?? ctx.rootTable;\n\t\t\targs.push(columnRef(decision.column, tableAlias, undefined, ctx.naming));\n\t\t}\n\n\t\t// Add other args (e.g., offset for lag/lead)\n\t\tif (decision.args && Array.isArray(decision.args)) {\n\t\t\tfor (const arg of decision.args) {\n\t\t\t\tconst paramNumber = ++state.paramIndex;\n\t\t\t\tstate.parameters.push(arg);\n\t\t\t\targs.push(createParamRef(paramNumber));\n\t\t\t}\n\t\t}\n\n\t\t// Add default value for lag/lead\n\t\tif (decision.value !== undefined) {\n\t\t\tconst defaultParamNumber = ++state.paramIndex;\n\t\t\tstate.parameters.push(decision.value);\n\t\t\targs.push(createParamRef(defaultParamNumber));\n\t\t}\n\n\t\treturn buildWindowFunction(funcName, args, decision, ctx);\n\t},\n};\n","/**\n * EXPRESSION Handlers Registration\n *\n * Exports all expression handlers and provides registration functions.\n */\n\nimport { registerExpressionHandler } from '../index.js';\nimport {\n\tavgHandler,\n\tcountDistinctHandler,\n\tcountHandler,\n\tgenericAggregateHandler,\n\tmaxHandler,\n\tminHandler,\n\tsumHandler,\n} from './aggregate.js';\nimport { arithmeticHandler } from './arithmetic.js';\nimport { caseHandler, simpleCaseHandler } from './case.js';\nimport {\n\tcoalesceHandler,\n\tgreatestHandler,\n\tleastHandler,\n\tnullIfHandler,\n} from './coalesce.js';\n// Handler imports\nimport { columnAliasHandler, columnHandler, starHandler } from './column.js';\nimport { customExpressionHandler } from './custom.js';\nimport { jsonExtractHandler, jsonPathExtractHandler } from './json.js';\nimport {\n\tchainedPseudoHandler,\n\tpseudoColumnHandler,\n\tsingleHopPseudoHandler,\n} from './pseudo.js';\nimport { literalHandler, rawHandler, sqlFunctionHandler } from './raw.js';\nimport {\n\tprefixedRelationColumnHandler,\n\trelationAliasHandler,\n\trelationColumnHandler,\n\trelationColumnsHandler,\n\trelationStarHandler,\n} from './relation.js';\nimport {\n\tdenseRankHandler,\n\tfirstValueHandler,\n\tgenericWindowHandler,\n\tlagHandler,\n\tlastValueHandler,\n\tleadHandler,\n\tntileHandler,\n\trankHandler,\n\trowNumberHandler,\n} from './window.js';\n\nexport {\n\tavgHandler,\n\tcountDistinctHandler,\n\tcountHandler,\n\tgenericAggregateHandler,\n\tmaxHandler,\n\tminHandler,\n\tsumHandler,\n} from './aggregate.js';\nexport { arithmeticHandler } from './arithmetic.js';\nexport { caseHandler, simpleCaseHandler } from './case.js';\nexport {\n\tcoalesceHandler,\n\tgreatestHandler,\n\tleastHandler,\n\tnullIfHandler,\n} from './coalesce.js';\n// Re-exports\nexport { columnAliasHandler, columnHandler, starHandler } from './column.js';\nexport { compileExpressionIntent, customExpressionHandler } from './custom.js';\nexport { jsonExtractHandler, jsonPathExtractHandler } from './json.js';\nexport {\n\tchainedPseudoHandler,\n\tpseudoColumnHandler,\n\tsingleHopPseudoHandler,\n} from './pseudo.js';\nexport { literalHandler, rawHandler, sqlFunctionHandler } from './raw.js';\nexport {\n\tprefixedRelationColumnHandler,\n\trelationAliasHandler,\n\trelationColumnHandler,\n\trelationColumnsHandler,\n\trelationStarHandler,\n} from './relation.js';\nexport {\n\tdenseRankHandler,\n\tfirstValueHandler,\n\tgenericWindowHandler,\n\tlagHandler,\n\tlastValueHandler,\n\tleadHandler,\n\tntileHandler,\n\trankHandler,\n\trowNumberHandler,\n} from './window.js';\n\n/**\n * Column expression handlers\n */\nexport const columnExpressionHandlers = [\n\tcolumnHandler,\n\tcolumnAliasHandler,\n\tstarHandler,\n];\n\n/**\n * Aggregate expression handlers\n */\nexport const aggregateExpressionHandlers = [\n\tcountHandler,\n\tcountDistinctHandler,\n\tsumHandler,\n\tavgHandler,\n\tminHandler,\n\tmaxHandler,\n\tgenericAggregateHandler,\n];\n\n/**\n * Conditional expression handlers (CASE, COALESCE, etc.)\n */\nexport const conditionalExpressionHandlers = [\n\tcaseHandler,\n\tsimpleCaseHandler,\n\tcoalesceHandler,\n\tnullIfHandler,\n\tgreatestHandler,\n\tleastHandler,\n];\n\n/**\n * Window function expression handlers\n */\nexport const windowExpressionHandlers = [\n\trowNumberHandler,\n\trankHandler,\n\tdenseRankHandler,\n\tntileHandler,\n\tlagHandler,\n\tleadHandler,\n\tfirstValueHandler,\n\tlastValueHandler,\n\tgenericWindowHandler,\n];\n\n/**\n * Raw/escape hatch expression handlers\n */\nexport const rawExpressionHandlers = [\n\trawHandler,\n\tsqlFunctionHandler,\n\tliteralHandler,\n];\n\n/**\n * JSON expression handlers\n */\nexport const jsonExpressionHandlers = [\n\tjsonExtractHandler,\n\tjsonPathExtractHandler,\n];\n\n/**\n * Pseudo-column expression handlers (hierarchy traversal)\n */\nexport const pseudoExpressionHandlers = [\n\tpseudoColumnHandler,\n\tsingleHopPseudoHandler,\n\tchainedPseudoHandler,\n];\n\n/**\n * Relation column expansion handlers\n */\nexport const relationExpressionHandlers = [\n\trelationStarHandler,\n\trelationColumnHandler,\n\trelationColumnsHandler,\n\trelationAliasHandler,\n\tprefixedRelationColumnHandler,\n];\n\n/**\n * All expression handlers\n */\nexport const allExpressionHandlers = [\n\t...columnExpressionHandlers,\n\t...aggregateExpressionHandlers,\n\t...conditionalExpressionHandlers,\n\t...windowExpressionHandlers,\n\t...rawExpressionHandlers,\n\t...pseudoExpressionHandlers,\n\t...relationExpressionHandlers,\n\t...jsonExpressionHandlers,\n\tarithmeticHandler,\n\tcustomExpressionHandler,\n];\n\n/**\n * Register all expression handlers.\n * Should be called once at module initialization.\n */\nexport function registerAllExpressionHandlers(): void {\n\tfor (const handler of allExpressionHandlers) {\n\t\tregisterExpressionHandler(handler);\n\t}\n}\n","/**\n * @dbsp/adapter-pgsql\n *\n * Native PostgreSQL adapter using tree-to-tree transformation:\n * PlanReport → PostgreSQL AST → SQL (via pgsql-deparser)\n */\n\n// Assert & Convention helpers — public API\nexport {\n\tDEFAULT_PK_COLUMN,\n\tdefaultFkDerivation,\n\ttype FkColumnDerivation,\n} from './assert-field.js';\n// AST Helpers — public API (internal helpers remain in ./ast-helpers.js)\nexport { normalizeSQL } from './ast-helpers.js';\n// Compiler\nexport {\n\ttype BatchValuesJoinDecision,\n\ttype CompiledResult,\n\ttype CompilerOptions,\n\tcompilePlan,\n\tisBatchValuesJoinDecision,\n\tisJoinDecision,\n\tisPrecompiledJoinDecision,\n\ttype JoinDecision,\n\tPlanCompiler,\n\ttype PlanDecision,\n\ttype PrecompiledJoinDecision,\n\ttype SimplifiedPlanReport,\n} from './compiler.js';\n// DDL Generation\nexport {\n\tacquireMigrationLock,\n\ttype ChangeKind,\n\ttype CompareSchemataOptions,\n\tcompareSchemata,\n\ttype DiffSummary,\n\tensureMigrationsTable,\n\ttype GenerateDDLOptions,\n\tgenerateDDL,\n\tgenerateDownSQL,\n\tgenerateMigrationFile,\n\tgenerateMigrationSQL,\n\tgetAppliedMigrations,\n\tgetNextSchemaVersion,\n\tisDestructiveDown,\n\tisMigrationApplied,\n\ttype MigrationRecord,\n\ttype MigrationSQLOptions,\n\tmapColumnType,\n\tmapOnDeleteAction,\n\ttype ParsedMigrationFile,\n\tparseMigrationFile,\n\trecordMigration,\n\treleaseMigrationLock,\n\tremoveMigrationRecord,\n\ttype SchemaChange,\n\ttype SchemaDiff,\n\twithMigrationLock,\n} from './ddl/index.js';\n// EXPLAIN support\nexport {\n\tbuildExplain,\n\tbuildExplainAnalyzeJson,\n\tbuildExplainPlan,\n\tbuildExplainVerbose,\n\ttype ExplainFormat,\n\ttype ExplainOptions,\n\ttype ExplainPlan,\n\tgetRowEstimates,\n\tgetTotalExecutionTime,\n\tparseExplainJson,\n} from './explain/index.js';\n// Extensions (pgvector, ParadeDB, PG builtins)\nexport {\n\tbm25Search,\n\tbooleanSearch,\n\tboost,\n\tcosineDistance,\n\tgenerateSeries,\n\tinnerProduct,\n\tl2Distance,\n\tnextval,\n\tparse,\n\trawDistance,\n\tscore,\n\tvectorDims,\n} from './extensions/index.js';\n// Handler Registry — types only (implementation details remain in ./handlers/index.js)\nexport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tExpressionHandler,\n\tIncludeHandler,\n\tIncludeResult,\n\tWhereDispatcher,\n\tWhereHandler,\n} from './handlers/index.js';\n// Introspection\nexport {\n\ttype DetectedHierarchy,\n\ttype IntrospectedModelIR,\n\ttype IntrospectionOptions,\n\tintrospect,\n} from './introspection.js';\n// Mutations\nexport {\n\tbuildOnConflictClause,\n\ttype ConflictAction,\n\ttype ConflictTarget,\n\tcompileDelete,\n\tcompileInsert,\n\tcompileMutation,\n\tcompileUpdate,\n\tcompileUpsert,\n\tconditionalUpdate,\n\ttype DeleteConfig,\n\texcludedRef,\n\ttype InsertConfig,\n\ttype UpdateConfig,\n\ttype UpsertConfig,\n} from './mutations/index.js';\n// Naming resolution\nexport { resolveLogicalName } from './naming.js';\n// Naming plugins\nexport {\n\tCamelCaseNamingPlugin,\n\tcamelCaseNaming,\n\tgetNamingPluginForDbCasing,\n\tIdentityNamingPlugin,\n\tidentityNaming,\n\ttype NamingPlugin,\n} from './naming-plugin.js';\n// ParamRef validation\nexport {\n\tcollectAndValidateParamRefs,\n\tcreateAnyExpr,\n\tcreateEqualityExpr,\n\tcreateParamRef,\n\tcreateTypeCastParamRef,\n\ttype ParamRefValidationResult,\n\tvalidateParamRef,\n} from './param-ref.js';\n// Adapter\nexport {\n\tcreatePgsqlAdapter,\n\tcreatePgsqlCompileOnlyAdapter,\n\tPgsqlAdapter,\n\ttype PgsqlAdapterOptions,\n} from './pgsql-adapter.js';\n// Redaction (params logging safety)\nexport {\n\tDEFAULT_REDACTION_PATTERNS,\n\ttype RedactionConfig,\n\ttype RedactionPattern,\n\tredactParams,\n} from './redact-params.js';\n// Set operations (UNION/INTERSECT/EXCEPT)\nexport {\n\tcompileSetOperation,\n\tcreateLeafCompileFn,\n\ttype LeafCompileFn,\n\ttype SetOperationResult,\n} from './set-operation.js';\n// Streaming (cursor-based)\nexport {\n\tbuildCloseCursor,\n\tbuildDeclareCursor,\n\tbuildFetch,\n\tbuildFetchAll,\n\tbuildFetchFirst,\n\tbuildFetchForward,\n\tbuildFetchNext,\n\tbuildStreamingStatements,\n\ttype CursorHoldOption,\n\ttype CursorOptions,\n\ttype CursorScrollOption,\n\ttype FetchDirection,\n\ttype FetchOptions,\n\tgenerateCursorName,\n\ttype StreamConfig,\n} from './streaming/index.js';\n// Validation\nexport {\n\tInvalidIdentifierError,\n\tisReservedKeyword,\n\tsanitizeForDisplay,\n\tvalidateIdentifier,\n\tvalidateIdentifiers,\n\tvalidateQualifiedIdentifier,\n} from './validate.js';\n","/**\n * PlanReport Compiler\n *\n * Transforms PlanReport → PostgreSQL AST → SQL\n *\n * This is the core of the adapter-pgsql spike: tree-to-tree transformation\n * that builds PostgreSQL AST nodes and deparses them to SQL.\n */\n\nimport type { ExpressionIntent } from '@dbsp/types';\nimport type { Node } from '@pgsql/types';\nimport {\n\tDEFAULT_PK_COLUMN,\n\tdefaultFkDerivation,\n\ttype FkColumnDerivation,\n\trequiredColumn,\n} from './assert-field.js';\nimport {\n\tandExpr,\n\tcolumnRef,\n\tcolumnTarget,\n\tdeleteStmt,\n\teqExpr,\n\tinnerJoin,\n\tinsertStmt,\n\tintegerNode,\n\tleftJoin,\n\tmapLockToAst,\n\tnotExpr,\n\torExpr,\n\trangeVar,\n\tselectStmt,\n\tsortBy,\n\tstarTarget,\n\tupdateStmt,\n} from './ast-helpers.js';\nimport { deparseQuoted } from './deparse.js';\nimport { resolveCaseValue as resolveCaseValueShared } from './handlers/expression/case-value.js';\nimport {\n\tcompileExpressionIntent,\n\tregisterWhereDispatcherFactory,\n} from './handlers/expression/custom.js';\nimport { registerAllExpressionHandlers } from './handlers/expression/index.js';\nimport { genericWindowHandler } from './handlers/expression/window.js';\nimport { registerAllIncludeHandlers } from './handlers/include/index.js';\nimport { deriveFkColumns } from './handlers/include/shared.js';\nimport {\n\tcreateWhereDispatcher,\n\tgetExpressionHandler,\n\tgetIncludeHandler,\n} from './handlers/index.js';\n\n// Register createWhereDispatcher with compileExpressionIntent so CASE expressions\n// can compile their WHEN conditions. compiler.ts is the bridge: it imports both\n// compileExpressionIntent (from custom.ts) and createWhereDispatcher (from handlers/index.ts).\nregisterWhereDispatcherFactory(createWhereDispatcher);\n\nimport type {\n\tCompilerContext as HandlerCompilerContext,\n\tCompilerState as HandlerCompilerState,\n\tDecision as HandlerDecision,\n\tJoinExprNode,\n\tSelectStmtNode,\n} from './handlers/types.js';\nimport { isSelectWithFields } from './handlers/types.js';\nimport { compileValue } from './handlers/where/utils.js';\nimport {\n\tconvertWhereCondition,\n\tintentToDecisions,\n} from './intent-to-decisions.js';\nimport type { NamingPlugin } from './naming-plugin.js';\nimport { identityNaming } from './naming-plugin.js';\nimport { createParamRef } from './param-ref.js';\n\n// ============================================================================\n// PlanDecision → HandlerDecision mapper\n// ============================================================================\n\n/**\n * Recursively map a PlanDecision tree to a HandlerDecision tree.\n *\n * Both types are structurally similar but nominally distinct. This explicit\n * mapper avoids `as unknown as` double casts by doing the conversion\n * field-by-field, including recursive children/conditions.\n */\nfunction mapToHandlerDecision(\n\tpd: PlanDecision,\n\trootTable: string,\n\tdefaultPk: string,\n\tderiveFk: FkColumnDerivation,\n): HandlerDecision {\n\treturn {\n\t\ttype: pd.type,\n\t\ttable: pd.table,\n\t\tcolumn: pd.column ?? pd.field,\n\t\talias: pd.alias,\n\t\toperator: pd.operator,\n\t\tvalue: pd.value,\n\t\tparamIndex: pd.paramIndex,\n\t\tdirection: pd.direction,\n\t\tjoinType: pd.joinType,\n\t\t...deriveFkColumns(pd, pd.sourceTable ?? rootTable, defaultPk, deriveFk),\n\t\ttargetTable: pd.targetTable,\n\t\tfunction: pd.function,\n\t\targs: pd.args,\n\t\tcolumns: pd.columns,\n\t\tvalues: pd.values,\n\t\tset: pd.set,\n\t\tlimit: pd.limit,\n\t\toffset: pd.offset,\n\t\tstrategy: (pd.choice === 'subquery'\n\t\t\t? 'json_agg'\n\t\t\t: pd.choice) as HandlerDecision['strategy'],\n\t\trelation: pd.relation ?? pd.relationName,\n\t\trelationName: pd.relationName,\n\t\trelationType: pd.relationType,\n\t\tforeignKey: pd.foreignKey,\n\t\tparentKey: pd.parentKey,\n\t\tdataType: pd.dataType,\n\t\ttraversal: pd.traversal,\n\t\tpkColumn: pd.pkColumn,\n\t\tfkColumn: pd.fkColumn,\n\t\tmaxDepth: pd.maxDepth,\n\t\tchildren: pd.children?.map((c) =>\n\t\t\tmapToHandlerDecision(c, pd.targetTable ?? rootTable, defaultPk, deriveFk),\n\t\t),\n\t\tconditions: pd.conditions?.map((c) =>\n\t\t\tmapToHandlerDecision(c, rootTable, defaultPk, deriveFk),\n\t\t),\n\t\tinclude: pd.include?.map((c) =>\n\t\t\tmapToHandlerDecision(c, rootTable, defaultPk, deriveFk),\n\t\t),\n\t\torderBy: pd.orderBy?.map((o) => ({\n\t\t\tcolumn: o.field,\n\t\t\tdirection: (o.direction?.toUpperCase() ?? 'ASC') as 'ASC' | 'DESC',\n\t\t})),\n\t\tpartition: pd.partitionBy,\n\t\tjsonPath: pd.jsonPath,\n\t\tjsonMode: pd.jsonMode,\n\t\texpressionIntent: pd.expressionIntent,\n\t\tsubqueryOperator: pd.subqueryOperator,\n\t\tselectColumn: pd.selectColumn,\n\t\taggregate: pd.aggregate,\n\t\tcolumnAliases: pd.columnAliases,\n\t\tescape: pd.escape,\n\t} as HandlerDecision;\n}\n\n/**\n * Compile an optional filterCondition (PlanDecision) to an AST Node.\n * Used to hydrate filterWhere on aggregate handler decisions.\n */\nfunction compileFilterCondition(\n\tfilterCondition: PlanDecision | undefined,\n\tdispatcher: ReturnType<typeof createWhereDispatcher>,\n\tctx: HandlerCompilerContext,\n\tstate: HandlerCompilerState,\n): import('@pgsql/types').Node | undefined {\n\tif (!filterCondition) return undefined;\n\tconst mapped = mapToHandlerDecision(\n\t\tfilterCondition,\n\t\tctx.rootTable,\n\t\tctx.defaultPkColumnName ?? 'id',\n\t\tctx.deriveFkColumnName ?? defaultFkDerivation,\n\t);\n\treturn dispatcher(mapped, ctx, state);\n}\n\n// ============================================================================\n// Types (simplified for spike - would import from @dbsp/core)\n// ============================================================================\n\n/**\n * Simplified PlanDecision for the spike\n * (In production, import from @dbsp/core)\n */\nexport interface PlanDecision {\n\treadonly type: string;\n\treadonly table?: string;\n\treadonly column?: string;\n\treadonly alias?: string;\n\treadonly field?: string;\n\treadonly operator?: string;\n\treadonly value?: unknown;\n\treadonly paramIndex?: number;\n\treadonly direction?: 'ASC' | 'DESC';\n\treadonly nulls?: 'FIRST' | 'LAST';\n\treadonly joinType?: 'inner' | 'left';\n\treadonly sourceColumn?: string;\n\treadonly targetColumn?: string;\n\treadonly targetTable?: string;\n\treadonly function?: string;\n\treadonly args?: readonly unknown[];\n\treadonly conditions?: readonly PlanDecision[];\n\treadonly columns?: readonly string[];\n\treadonly values?: readonly unknown[];\n\treadonly set?: readonly { column: string; value: unknown }[];\n\treadonly limit?: number | { paramIndex: number };\n\treadonly offset?: number | { paramIndex: number };\n\t// Window function properties\n\treadonly partitionBy?: readonly string[];\n\treadonly orderBy?: readonly { field: string; direction?: 'asc' | 'desc' }[];\n\t// Column data type (for range type casting, e.g. 'daterange', 'int4range')\n\treadonly dataType?: string;\n\t// JSON aggregation (include strategy: 'json_agg')\n\treadonly sourceTable?: string;\n\treadonly relationName?: string;\n\treadonly relationType?: 'belongsTo' | 'hasMany' | 'hasOne';\n\treadonly foreignKey?: string;\n\treadonly parentKey?: string;\n\t// Nested json_agg children (for deep relation traversal)\n\treadonly children?: readonly PlanDecision[];\n\treadonly intentPath?: string;\n\t// Filter/include strategy choice from planner ('join' | 'exists' | 'json_agg')\n\treadonly choice?: string;\n\t// IN (subquery) reference\n\treadonly subquery?: {\n\t\treadonly from: string;\n\t\treadonly select: string;\n\t\treadonly where?: PlanDecision;\n\t\treadonly limit?: number;\n\t\treadonly orderBy?: readonly { field: string; direction?: string }[];\n\t};\n\t// Expression type discriminator (e.g. 'case' for CASE WHEN)\n\treadonly expressionType?: string;\n\t// Relation column properties\n\treadonly relation?: string;\n\t// User-supplied aliases for specific relation columns (col -> alias).\n\t// Populated when selectRelationColumn decisions carry an `alias` field.\n\treadonly columnAliases?: Readonly<Record<string, string>>;\n\t// Pseudo-column (recursive traversal) properties\n\treadonly traversal?: string;\n\treadonly pkColumn?: string;\n\treadonly fkColumn?: string;\n\treadonly maxDepth?: number;\n\treadonly role?: string;\n\t// JSON extraction metadata\n\treadonly jsonPath?: readonly string[];\n\treadonly jsonMode?: 'json' | 'text';\n\t// Arithmetic expressions use args: [left, right] instead of dedicated fields\n\t// Scalar subquery comparison properties\n\treadonly selectColumn?: string;\n\treadonly aggregate?: string;\n\treadonly subqueryOperator?: string;\n\t// FILTER (WHERE ...) condition for aggregate expressions (WhereIntent serialized as PlanDecision)\n\treadonly filterCondition?: PlanDecision;\n\t// Custom expression intent for selectCustomExpression, WHERE expression, and ORDER BY expression\n\treadonly expressionIntent?: unknown;\n\t// LIKE escape character\n\treadonly escape?: string;\n\t// Include declarations (JOIN inside EXISTS subquery)\n\treadonly include?: readonly PlanDecision[];\n\t// Pre-compiled right-side AST node for table-mode JoinIntent (explicit ON condition).\n\t// When set, the 'join' case in compileSelect uses joinRarg + joinOnNode to build\n\t// the JoinExpr wrapping from[0] as larg — enabling correct multi-join chaining.\n\treadonly joinRarg?: Node;\n\treadonly joinOnNode?: Node;\n\t// Parameters for BatchValues joins (unnest() source).\n\t// When set, these are spliced into this.state.parameters BEFORE other query params.\n\t// The joinRarg contains ParamRefs ($1, $2, ...) aligned with these values.\n\treadonly batchValuesParams?: readonly unknown[];\n}\n\n// ============================================================================\n// PlanDecision sub-types (discriminated sub-interfaces + type guards)\n// ============================================================================\n\n/**\n * Any decision of type 'join'.\n * Narrows `type` to the literal 'join' for safe switch exhaustion.\n */\nexport interface JoinDecision extends PlanDecision {\n\treadonly type: 'join';\n}\n\n/**\n * A 'join' decision that carries pre-compiled PostgreSQL AST nodes.\n * Used by both table-mode and BatchValues-mode joins when the ON condition\n * has been compiled ahead of time in adapter-compiler-select.ts.\n *\n * The `joinRarg` is the right-hand RangeVar/RangeFunction; `joinOnNode` is\n * the A_Expr tree for the ON clause.\n */\nexport interface PrecompiledJoinDecision extends JoinDecision {\n\treadonly joinRarg: Node;\n\treadonly joinOnNode: Node;\n}\n\n/**\n * A pre-compiled 'join' decision backed by a BatchValues unnest() source.\n * `batchValuesParams` must be spliced into compiler state BEFORE other query\n * parameters so that $1/$2/… ParamRefs in the RangeFunction align correctly.\n */\nexport interface BatchValuesJoinDecision extends PrecompiledJoinDecision {\n\treadonly batchValuesParams: readonly unknown[];\n}\n\n/** Narrows a PlanDecision to JoinDecision (type === 'join'). */\nexport function isJoinDecision(d: PlanDecision): d is JoinDecision {\n\treturn d.type === 'join';\n}\n\n/**\n * Narrows a PlanDecision to PrecompiledJoinDecision.\n * True when the join carries pre-compiled `joinRarg` + `joinOnNode` AST nodes\n * (table mode or BatchValues mode).\n */\nexport function isPrecompiledJoinDecision(\n\td: PlanDecision,\n): d is PrecompiledJoinDecision {\n\treturn (\n\t\td.type === 'join' && d.joinRarg !== undefined && d.joinOnNode !== undefined\n\t);\n}\n\n/**\n * Narrows a PlanDecision to BatchValuesJoinDecision.\n * True when the join is a BatchValues unnest() join and carries pre-spliced\n * parameter arrays in `batchValuesParams`.\n */\nexport function isBatchValuesJoinDecision(\n\td: PlanDecision,\n): d is BatchValuesJoinDecision {\n\treturn isPrecompiledJoinDecision(d) && d.batchValuesParams !== undefined;\n}\n\n/**\n * Simplified PlanReport for the spike\n */\nexport interface SimplifiedPlanReport {\n\treadonly rootTable: string;\n\treadonly decisions: readonly PlanDecision[];\n\treadonly schema?: string;\n\t/** If true, wrap result in SELECT EXISTS(SELECT 1 ...) AS \"exists\" */\n\treadonly existsWrap?: boolean;\n\t/** Row-level lock (FOR UPDATE/SHARE/etc.) */\n\treadonly lock?: import('@dbsp/types').LockIntent;\n\t/**\n\t * When present, the FROM clause is replaced by a pre-compiled RangeFunction node\n\t * (e.g. unnest() AS alias) instead of the root table rangeVar.\n\t * `batchValuesFromParams` holds the parameter arrays to splice into state first.\n\t */\n\treadonly batchValuesFromNode?: unknown;\n\treadonly batchValuesFromParams?: readonly unknown[];\n}\n\n/**\n * Compiled query result\n */\nexport interface CompiledResult {\n\treadonly sql: string;\n\treadonly parameters: readonly unknown[];\n\treadonly ast: Node;\n}\n\n// ============================================================================\n// AST Utilities\n// ============================================================================\n\n/**\n * Walk a PostgreSQL AST Node tree and renumber all ParamRef.number values\n * by adding `offset` to each. Used to merge inner subquery parameters into\n * the outer query's parameter sequence without $N collisions.\n *\n * @param node - Root AST node (any pgsql Node object or array)\n * @param offset - Value to add to every ParamRef.number found\n * @returns A new node tree with renumbered ParamRefs (original is not mutated)\n */\nexport function renumberParamRefsInAst(node: unknown, offset: number): Node {\n\tif (offset === 0) return node as Node;\n\treturn renumberNode(node, offset) as Node;\n}\n\nfunction renumberNode(value: unknown, offset: number): unknown {\n\tif (value === null || value === undefined) return value;\n\tif (Array.isArray(value)) {\n\t\treturn value.map((item) => renumberNode(item, offset));\n\t}\n\tif (typeof value !== 'object') return value;\n\tconst obj = value as Record<string, unknown>;\n\t// ParamRef node: { ParamRef: { number: N } }\n\tif (\n\t\t'ParamRef' in obj &&\n\t\tobj.ParamRef !== null &&\n\t\ttypeof obj.ParamRef === 'object'\n\t) {\n\t\tconst pr = obj.ParamRef as Record<string, unknown>;\n\t\treturn { ParamRef: { ...pr, number: (pr.number as number) + offset } };\n\t}\n\t// Recursively walk all object properties\n\tconst result: Record<string, unknown> = {};\n\tfor (const key of Object.keys(obj)) {\n\t\tresult[key] = renumberNode(obj[key], offset);\n\t}\n\treturn result;\n}\n\n// ============================================================================\n// Compiler\n// ============================================================================\n\nexport interface CompilerOptions {\n\treadonly naming?: NamingPlugin;\n\treadonly schema?: string;\n\t/** Default primary key column name convention (default: 'id') */\n\treadonly defaultPkColumnName?: string;\n\t/** Convention for deriving FK column names: (tableName, pkName) => fkColumnName */\n\treadonly deriveFkColumnName?: FkColumnDerivation;\n\t/** ModelIR for type-aware parameter casting in WHERE clauses */\n\treadonly model?: import('@dbsp/types').ModelIR;\n}\n\n/**\n * Compile a PlanReport to SQL via PostgreSQL AST\n */\nlet includeHandlersInitialized = false;\nfunction ensureIncludeHandlersRegistered(): void {\n\tif (includeHandlersInitialized) return;\n\tincludeHandlersInitialized = true;\n\tregisterAllIncludeHandlers();\n}\n\nlet expressionHandlersInitialized = false;\nfunction ensureExpressionHandlersRegistered(): void {\n\tif (expressionHandlersInitialized) return;\n\texpressionHandlersInitialized = true;\n\tregisterAllExpressionHandlers();\n}\n\nexport class PlanCompiler {\n\tprivate readonly naming: NamingPlugin;\n\tprivate readonly schema: string | undefined;\n\tprivate readonly defaultPk: string;\n\tprivate readonly deriveFk: FkColumnDerivation;\n\tprivate readonly model: import('@dbsp/types').ModelIR | undefined;\n\t/** Mutable state shared with extracted condition/value compilation functions */\n\tprivate state: HandlerCompilerState = {\n\t\tparameters: [],\n\t\tparamIndex: 0,\n\t\tctes: new Map(),\n\t\taliases: new Map(),\n\t\tjoins: [],\n\t};\n\t/** Track root table for EXISTS FK correlation */\n\tprivate currentRootTable = '';\n\t/** Pending JOINs registered by filter/include strategies (flushed in compileSelect) */\n\tprivate pendingJoins: Array<{\n\t\ttype: 'JOIN' | 'LEFT JOIN';\n\t\ttable: string;\n\t\talias?: string;\n\t\ton: Node;\n\t}> = [];\n\t/** Raw JOIN AST nodes from include handlers (e.g., LATERAL) */\n\tprivate rawJoins: Node[] = [];\n\t/** CTE nodes from include handlers (e.g., CTE strategy) */\n\tprivate pendingCtes: Node[] = [];\n\t/**\n\t * Maps joined targetTable → alias for multi-hop FK resolution.\n\t * Populated as join decisions are compiled so later hops can find\n\t * the correct source alias (e.g., 'symbols' → 'callee').\n\t */\n\tprivate joinAliasMap: Map<string, string> = new Map();\n\t/**\n\t * Tracks all join aliases in use for the current query.\n\t * Ensures no two JOINs share the same alias (DOUBLE-ALIAS prevention).\n\t */\n\tprivate usedJoinAliases: Set<string> = new Set();\n\n\tconstructor(options: CompilerOptions = {}) {\n\t\tthis.naming = options.naming ?? identityNaming;\n\t\tthis.schema = options.schema ?? undefined;\n\t\tthis.defaultPk = options.defaultPkColumnName ?? DEFAULT_PK_COLUMN;\n\t\tthis.deriveFk = options.deriveFkColumnName ?? defaultFkDerivation;\n\t\tthis.model = options.model ?? undefined;\n\t}\n\n\t/** Build immutable context for handler-based WHERE compilation */\n\tprivate handlerCtx(): HandlerCompilerContext {\n\t\treturn {\n\t\t\tnaming: this.naming,\n\t\t\trootTable: this.currentRootTable,\n\t\t\tmaxRecursiveDepth: 100,\n\t\t\tdefaultPkColumnName: this.defaultPk,\n\t\t\tderiveFkColumnName: this.deriveFk,\n\t\t\t...(this.schema != null && { schema: this.schema }),\n\t\t\t...(this.model != null && { model: this.model }),\n\t\t} as HandlerCompilerContext;\n\t}\n\n\t/**\n\t * Dispatch a PlanDecision through the unified WHERE handler system.\n\t * Bridges PlanCompiler's state to handler types, calls dispatcher, syncs back.\n\t */\n\tprivate dispatchWhere(\n\t\tdecision: PlanDecision,\n\t\tctxOverrides?: Partial<HandlerCompilerContext>,\n\t): Node {\n\t\tconst dispatcher = createWhereDispatcher();\n\t\tconst mapped = mapToHandlerDecision(\n\t\t\tdecision,\n\t\t\tthis.currentRootTable,\n\t\t\tthis.defaultPk,\n\t\t\tthis.deriveFk,\n\t\t);\n\t\t// Handle IN/NOT IN subquery: remap to inSubquery/notInSubquery\n\t\t// Subquery can be in `decision.subquery` (direct PlanDecision) or\n\t\t// `decision.value` (from plan-decision-extractor which puts it in value)\n\t\tconst sub =\n\t\t\tdecision.subquery ??\n\t\t\t(decision.value &&\n\t\t\ttypeof decision.value === 'object' &&\n\t\t\t'from' in (decision.value as object)\n\t\t\t\t? (decision.value as PlanDecision['subquery'])\n\t\t\t\t: undefined);\n\t\tif (sub && (decision.operator === 'in' || decision.operator === 'notIn')) {\n\t\t\tconst op = decision.operator === 'notIn' ? 'notInSubquery' : 'inSubquery';\n\t\t\t// Extract selectColumn: may be a string or a SelectIntent with fields\n\t\t\tconst rawSelect = sub.select as unknown;\n\t\t\tconst selectColumn =\n\t\t\t\ttypeof rawSelect === 'string'\n\t\t\t\t\t? rawSelect\n\t\t\t\t\t: isSelectWithFields(rawSelect)\n\t\t\t\t\t\t? (rawSelect.fields?.[0] ?? '*')\n\t\t\t\t\t\t: '*';\n\t\t\tconst subConditions = sub.where\n\t\t\t\t? [this.mapInSubqueryCondition(sub.where, sub.from)]\n\t\t\t\t: [];\n\t\t\tconst rawLimit = sub.limit;\n\t\t\tconst rawOrderBy = sub.orderBy;\n\t\t\tconst subDecision = {\n\t\t\t\t...mapped,\n\t\t\t\toperator: op,\n\t\t\t\ttargetTable: sub.from,\n\t\t\t\tselectColumn,\n\t\t\t\tconditions: subConditions,\n\t\t\t\t...(rawLimit != null && { limit: rawLimit }),\n\t\t\t\t...(rawOrderBy && {\n\t\t\t\t\torderBy: rawOrderBy.map((o) => ({\n\t\t\t\t\t\tcolumn: o.field,\n\t\t\t\t\t\tdirection: (o.direction?.toUpperCase() ?? 'ASC') as 'ASC' | 'DESC',\n\t\t\t\t\t})),\n\t\t\t\t}),\n\t\t\t} as HandlerDecision;\n\t\t\tconst ctx = ctxOverrides\n\t\t\t\t? { ...this.handlerCtx(), ...ctxOverrides }\n\t\t\t\t: this.handlerCtx();\n\t\t\treturn dispatcher(subDecision, ctx, this.state);\n\t\t}\n\t\tconst ctx = ctxOverrides\n\t\t\t? { ...this.handlerCtx(), ...ctxOverrides }\n\t\t\t: this.handlerCtx();\n\t\treturn dispatcher(mapped, ctx, this.state);\n\t}\n\n\t/**\n\t * Recursively convert a PlanDecision (potentially with nested in+subquery)\n\t * into a HandlerDecision suitable for the WHERE dispatcher.\n\t *\n\t * When a PlanDecision has operator='in'/'notIn' with a subquery object,\n\t * mapToHandlerDecision loses the subquery because HandlerDecision has no\n\t * `subquery` field. This method detects that pattern and converts it to the\n\t * inSubquery/notInSubquery form that buildScalarSubquery expects.\n\t *\n\t * Called recursively so 2+ levels of nested IN subqueries all work.\n\t */\n\tprivate mapInSubqueryCondition(\n\t\tpd: PlanDecision,\n\t\trootTable: string,\n\t): HandlerDecision {\n\t\tconst sub = pd.subquery as\n\t\t\t| (PlanDecision['subquery'] & { where?: PlanDecision })\n\t\t\t| undefined;\n\t\tif (sub && (pd.operator === 'in' || pd.operator === 'notIn')) {\n\t\t\tconst op = pd.operator === 'notIn' ? 'notInSubquery' : 'inSubquery';\n\t\t\tconst rawSelect = sub.select as unknown;\n\t\t\tconst selectColumn =\n\t\t\t\ttypeof rawSelect === 'string'\n\t\t\t\t\t? rawSelect\n\t\t\t\t\t: isSelectWithFields(rawSelect)\n\t\t\t\t\t\t? (rawSelect.fields?.[0] ?? '*')\n\t\t\t\t\t\t: '*';\n\t\t\t// Recursively apply: the inner subquery's WHERE may itself be\n\t\t\t// another in+subquery (the NESTED-INSUBQUERY case)\n\t\t\tconst subConditions: HandlerDecision[] = sub.where\n\t\t\t\t? [this.mapInSubqueryCondition(sub.where, sub.from)]\n\t\t\t\t: [];\n\t\t\tconst rawLimit = sub.limit;\n\t\t\tconst rawOrderBy = sub.orderBy;\n\t\t\treturn {\n\t\t\t\t...mapToHandlerDecision(pd, rootTable, this.defaultPk, this.deriveFk),\n\t\t\t\toperator: op,\n\t\t\t\ttargetTable: sub.from,\n\t\t\t\tselectColumn,\n\t\t\t\tconditions: subConditions,\n\t\t\t\t...(rawLimit != null && { limit: rawLimit }),\n\t\t\t\t...(rawOrderBy && {\n\t\t\t\t\torderBy: rawOrderBy.map((o) => ({\n\t\t\t\t\t\tcolumn: o.field,\n\t\t\t\t\t\tdirection: (o.direction?.toUpperCase() ?? 'ASC') as 'ASC' | 'DESC',\n\t\t\t\t\t})),\n\t\t\t\t}),\n\t\t\t} as HandlerDecision;\n\t\t}\n\t\t// Non-subquery case: plain mapToHandlerDecision suffices\n\t\treturn mapToHandlerDecision(pd, rootTable, this.defaultPk, this.deriveFk);\n\t}\n\n\t/**\n\t * Bridge PlanDecision to handler Decision and dispatch to include handler.\n\t * Returns targets and optional pending joins to apply.\n\t */\n\tprivate compileIncludeViaHandler(\n\t\tdecision: PlanDecision,\n\t\tplan: SimplifiedPlanReport,\n\t): {\n\t\ttargets?: Node[];\n\t\trawJoin?: Node;\n\t\tadditionalJoins?: Node[];\n\t\tcte?: Node;\n\t} {\n\t\tensureIncludeHandlersRegistered();\n\n\t\tconst strategy = decision.choice as\n\t\t\t| 'json_agg'\n\t\t\t| 'join'\n\t\t\t| 'lateral'\n\t\t\t| 'cte'\n\t\t\t| 'subquery'\n\t\t\t| undefined;\n\t\tif (!strategy)\n\t\t\tthrow new Error(\n\t\t\t\t`Include decision missing strategy choice: ${JSON.stringify(decision)}`,\n\t\t\t);\n\n\t\t// Bridge PlanDecision -> handler Decision via explicit mapper\n\t\t// (mapper handles subquery → json_agg mapping internally)\n\t\tconst handlerDecision = mapToHandlerDecision(\n\t\t\tdecision,\n\t\t\tplan.rootTable,\n\t\t\tthis.defaultPk,\n\t\t\tthis.deriveFk,\n\t\t);\n\n\t\tconst handler = getIncludeHandler(\n\t\t\thandlerDecision.strategy as 'json_agg' | 'join' | 'lateral' | 'cte',\n\t\t);\n\n\t\t// Pre-compile filter conditions for the handler (e.g., EXISTS propagation).\n\t\t// INCLUDE-WHERE-SCOPE: skip for 'join' strategy — its conditions are folded\n\t\t// into the root WHERE clause in compileSelect() instead. Pre-compiling here\n\t\t// would double-consume parameter slots without producing usable SQL.\n\t\tif (\n\t\t\tstrategy !== 'join' &&\n\t\t\tdecision.conditions &&\n\t\t\t(decision.conditions as PlanDecision[]).length > 0\n\t\t) {\n\t\t\tconst innerAlias = '__t__';\n\t\t\tconst condNodes = (decision.conditions as PlanDecision[]).map((c) => {\n\t\t\t\t// Rewrite condition table references to use the inner alias\n\t\t\t\tconst rewritten = { ...c, table: innerAlias };\n\t\t\t\treturn this.dispatchWhere(rewritten, { currentAlias: innerAlias });\n\t\t\t});\n\t\t\tconst combined =\n\t\t\t\tcondNodes.length === 1 ? condNodes[0]! : andExpr(...condNodes);\n\t\t\t// Inject pre-compiled filter for the json_agg handler to read.\n\t\t\t// Property is readonly on Decision; the compiler is the sole writer.\n\t\t\t(\n\t\t\t\thandlerDecision as { _compiledFilterWhere?: Node }\n\t\t\t)._compiledFilterWhere = combined;\n\t\t}\n\n\t\t// Bridge compiler context for include handler.\n\t\t// For multi-hop flat joins the sourceTable differs from the root table —\n\t\t// resolve the alias of that intermediate table from the registry so the\n\t\t// ON clause references the right prefix (e.g., callee.file_id, not calls.file_id).\n\t\tconst sourceAlias =\n\t\t\tdecision.sourceTable && decision.sourceTable !== plan.rootTable\n\t\t\t\t? (this.joinAliasMap.get(decision.sourceTable) ?? decision.sourceTable)\n\t\t\t\t: plan.rootTable;\n\t\tconst ctx = {\n\t\t\t...this.handlerCtx(),\n\t\t\tcurrentAlias: sourceAlias,\n\t\t} as HandlerCompilerContext;\n\n\t\tconst handlerState: HandlerCompilerState = {\n\t\t\tparameters: this.state.parameters,\n\t\t\tparamIndex: this.state.paramIndex,\n\t\t\tctes: new Map(),\n\t\t\taliases: new Map(),\n\t\t\tjoins: [],\n\t\t};\n\n\t\t// Deduplicate join alias before compiling (DOUBLE-ALIAS prevention).\n\t\t// The join handler derives its alias as: relation ?? targetTable.\n\t\t// If two includes resolve to the same alias (e.g., include('def.file') +\n\t\t// include('file') both produce alias 'file'), suffix with _N to disambiguate.\n\t\tlet finalJoinAlias: string | undefined;\n\t\tif (decision.choice === 'join') {\n\t\t\tconst candidateAlias =\n\t\t\t\thandlerDecision.relation ??\n\t\t\t\thandlerDecision.targetTable ??\n\t\t\t\thandlerDecision.relationName;\n\t\t\tif (candidateAlias) {\n\t\t\t\tlet alias = candidateAlias;\n\t\t\t\tlet counter = 1;\n\t\t\t\twhile (this.usedJoinAliases.has(alias)) {\n\t\t\t\t\talias = `${candidateAlias}_${counter++}`;\n\t\t\t\t}\n\t\t\t\tthis.usedJoinAliases.add(alias);\n\t\t\t\tfinalJoinAlias = alias;\n\t\t\t\t// Inject the deduplicated alias so the handler uses it\n\t\t\t\tif (alias !== candidateAlias) {\n\t\t\t\t\t(handlerDecision as { relation?: string }).relation = alias;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst result = handler.compile(handlerDecision, ctx, handlerState);\n\n\t\t// Sync parameters back\n\t\tthis.state.paramIndex = handlerState.paramIndex;\n\n\t\t// Register targetTable → alias for multi-hop FK resolution.\n\t\t// Later join decisions whose sourceTable matches this targetTable\n\t\t// will use the alias (e.g., relationName) as their sourceAlias.\n\t\tif (\n\t\t\tdecision.choice === 'join' &&\n\t\t\tdecision.targetTable &&\n\t\t\t(finalJoinAlias ?? decision.relationName)\n\t\t) {\n\t\t\tthis.joinAliasMap.set(\n\t\t\t\tdecision.targetTable,\n\t\t\t\tfinalJoinAlias ?? decision.relationName!,\n\t\t\t);\n\t\t}\n\n\t\tconst out: {\n\t\t\ttargets?: Node[];\n\t\t\trawJoin?: Node;\n\t\t\tadditionalJoins?: Node[];\n\t\t\tcte?: Node;\n\t\t} = {};\n\t\tif (result.targets) out.targets = result.targets;\n\t\tif (result.join) out.rawJoin = result.join;\n\t\tif (result.lateral) out.rawJoin = result.lateral;\n\t\tif (result.additionalJoins) out.additionalJoins = result.additionalJoins;\n\t\tif (result.cte) out.cte = result.cte;\n\t\treturn out;\n\t}\n\n\t/**\n\t * Compile a simplified plan report to SQL\n\t */\n\tcompile(plan: SimplifiedPlanReport): CompiledResult {\n\t\tthis.state = {\n\t\t\tparameters: [],\n\t\t\tparamIndex: 0,\n\t\t\tctes: new Map(),\n\t\t\taliases: new Map(),\n\t\t\tjoins: [],\n\t\t};\n\t\tthis.currentRootTable = plan.rootTable;\n\t\tthis.pendingJoins = [];\n\t\tthis.rawJoins = [];\n\t\tthis.pendingCtes = [];\n\t\tthis.joinAliasMap = new Map();\n\n\t\t// Determine query type from decisions\n\t\tconst queryType = this.detectQueryType(plan.decisions);\n\n\t\tlet ast: Node;\n\n\t\tswitch (queryType) {\n\t\t\tcase 'select':\n\t\t\t\tast = this.compileSelect(plan);\n\t\t\t\t// Handle existsWrap: SELECT EXISTS(SELECT 1 ...) AS \"exists\"\n\t\t\t\tif (plan.existsWrap) {\n\t\t\t\t\tast = this.wrapSelectInExists(ast);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'insert':\n\t\t\t\tast = this.compileInsert(plan);\n\t\t\t\tbreak;\n\t\t\tcase 'update':\n\t\t\t\tast = this.compileUpdate(plan);\n\t\t\t\tbreak;\n\t\t\tcase 'delete':\n\t\t\t\tast = this.compileDelete(plan);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unsupported query type: ${queryType}`);\n\t\t}\n\n\t\tconst sql = deparseQuoted(ast);\n\n\t\treturn {\n\t\t\tsql,\n\t\t\tparameters: this.state.parameters,\n\t\t\tast,\n\t\t};\n\t}\n\n\tprivate detectQueryType(decisions: readonly PlanDecision[]): string {\n\t\tfor (const decision of decisions) {\n\t\t\tif (decision.type === 'insert') return 'insert';\n\t\t\tif (decision.type === 'update') return 'update';\n\t\t\tif (decision.type === 'delete') return 'delete';\n\t\t}\n\t\treturn 'select';\n\t}\n\n\t// --------------------------------------------------------------------------\n\t// SELECT Compilation\n\t// --------------------------------------------------------------------------\n\n\t/** Build a HandlerCompilerContext for the given plan and optional alias override. */\n\tprivate createHandlerContext(\n\t\tplan: SimplifiedPlanReport,\n\t\tcurrentAlias?: string,\n\t): HandlerCompilerContext {\n\t\treturn {\n\t\t\tnaming: this.naming,\n\t\t\trootTable: plan.rootTable,\n\t\t\tcurrentAlias: currentAlias ?? plan.rootTable,\n\t\t\tmaxRecursiveDepth: 100,\n\t\t\tdefaultPkColumnName: this.defaultPk,\n\t\t\tderiveFkColumnName: this.deriveFk,\n\t\t\t...((plan.schema ?? this.schema)\n\t\t\t\t? { schema: plan.schema ?? this.schema }\n\t\t\t\t: {}),\n\t\t\t...(this.model != null && { model: this.model }),\n\t\t} as HandlerCompilerContext;\n\t}\n\n\t/** Build a fresh HandlerCompilerState sharing the current parameter array. */\n\tprivate createHandlerState(): HandlerCompilerState {\n\t\treturn {\n\t\t\tparameters: this.state.parameters,\n\t\t\tparamIndex: this.state.paramIndex,\n\t\t\tctes: new Map(),\n\t\t\taliases: new Map(),\n\t\t\tjoins: [],\n\t\t};\n\t}\n\n\t/**\n\t * Compile a SELECT-list target via expression handler.\n\t * Wraps the node in a ResTarget and pushes it onto targetList.\n\t */\n\tprivate compileSelectTarget(\n\t\tdecision: PlanDecision,\n\t\tplan: SimplifiedPlanReport,\n\t\ttargetList: Node[],\n\t): void {\n\t\tswitch (decision.type) {\n\t\t\tcase 'select':\n\t\t\t\tif (decision.column === '*') {\n\t\t\t\t\ttargetList.push(starTarget(decision.table, this.naming));\n\t\t\t\t} else if (decision.column) {\n\t\t\t\t\ttargetList.push(\n\t\t\t\t\t\tcolumnTarget(\n\t\t\t\t\t\t\tdecision.column,\n\t\t\t\t\t\t\tdecision.alias,\n\t\t\t\t\t\t\tdecision.table,\n\t\t\t\t\t\t\tthis.naming,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 'selectFunction': {\n\t\t\t\tensureExpressionHandlersRegistered();\n\t\t\t\tconst funcType = decision.function;\n\t\t\t\tif (!funcType) break;\n\t\t\t\tconst handler = getExpressionHandler(funcType);\n\t\t\t\tconst ctx = this.createHandlerContext(\n\t\t\t\t\tplan,\n\t\t\t\t\tdecision.table ?? plan.rootTable,\n\t\t\t\t);\n\t\t\t\tconst state = this.createHandlerState();\n\t\t\t\tconst handlerDecision = mapToHandlerDecision(\n\t\t\t\t\tdecision,\n\t\t\t\t\tplan.rootTable,\n\t\t\t\t\tthis.defaultPk,\n\t\t\t\t\tthis.deriveFk,\n\t\t\t\t);\n\t\t\t\t// Compile FILTER (WHERE ...) clause if present\n\t\t\t\tconst filterNode = compileFilterCondition(\n\t\t\t\t\tdecision.filterCondition,\n\t\t\t\t\tcreateWhereDispatcher(),\n\t\t\t\t\tctx,\n\t\t\t\t\tstate,\n\t\t\t\t);\n\t\t\t\tconst hydratedDecision = filterNode\n\t\t\t\t\t? { ...handlerDecision, filterWhere: filterNode }\n\t\t\t\t\t: handlerDecision;\n\t\t\t\tconst node = handler.compile(hydratedDecision, ctx, state);\n\t\t\t\tthis.state.paramIndex = state.paramIndex;\n\t\t\t\ttargetList.push({\n\t\t\t\t\tResTarget: {\n\t\t\t\t\t\tval: node,\n\t\t\t\t\t\t...(decision.alias\n\t\t\t\t\t\t\t? { name: this.naming.toDatabase(decision.alias) }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 'selectExpression': {\n\t\t\t\tif (decision.expressionType === 'case') {\n\t\t\t\t\tconst caseNode = this.compileCaseExpression(decision);\n\t\t\t\t\tconst alias = decision.alias;\n\t\t\t\t\ttargetList.push({\n\t\t\t\t\t\tResTarget: {\n\t\t\t\t\t\t\tval: caseNode,\n\t\t\t\t\t\t\t...(alias ? { name: this.naming.toDatabase(alias) } : {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 'selectCustomExpression': {\n\t\t\t\tconst exprIntent = decision.expressionIntent as ExpressionIntent;\n\t\t\t\tconst outerThis = this;\n\t\t\t\tconst ctx = {\n\t\t\t\t\t...this.createHandlerContext(plan, plan.rootTable),\n\t\t\t\t\tcompileSubquery(\n\t\t\t\t\t\tquery: import('@dbsp/types').QueryIntent,\n\t\t\t\t\t\tparamOffset: number,\n\t\t\t\t\t): {\n\t\t\t\t\t\tast: import('@pgsql/types').Node;\n\t\t\t\t\t\tparameters: readonly unknown[];\n\t\t\t\t\t} {\n\t\t\t\t\t\t// Compile the inner QueryIntent through a fresh PlanCompiler\n\t\t\t\t\t\t// (same options: naming, schema, defaultPk, deriveFk)\n\t\t\t\t\t\tconst innerCompiler = new PlanCompiler({\n\t\t\t\t\t\t\tnaming: outerThis.naming,\n\t\t\t\t\t\t\t...(outerThis.schema !== undefined && {\n\t\t\t\t\t\t\t\tschema: outerThis.schema,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tdefaultPkColumnName: outerThis.defaultPk,\n\t\t\t\t\t\t\tderiveFkColumnName: outerThis.deriveFk,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tconst innerPlan: SimplifiedPlanReport = {\n\t\t\t\t\t\t\trootTable: query.from,\n\t\t\t\t\t\t\tdecisions: intentToDecisions(query, query.from),\n\t\t\t\t\t\t};\n\t\t\t\t\t\tconst innerResult = innerCompiler.compile(innerPlan);\n\t\t\t\t\t\t// Renumber ParamRef $N in the inner AST by paramOffset so they\n\t\t\t\t\t\t// don't collide with the outer query's already-consumed parameters.\n\t\t\t\t\t\tconst renumbered = renumberParamRefsInAst(\n\t\t\t\t\t\t\tinnerResult.ast,\n\t\t\t\t\t\t\tparamOffset,\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn { ast: renumbered, parameters: innerResult.parameters };\n\t\t\t\t\t},\n\t\t\t\t} as HandlerCompilerContext;\n\t\t\t\tconst state = this.createHandlerState();\n\t\t\t\tconst node = compileExpressionIntent(exprIntent, ctx, state);\n\t\t\t\t// Apply FILTER (WHERE ...) clause for customFn intents (e.g. array_agg FILTER (WHERE ...))\n\t\t\t\t// Compiled at this level to use compileFilterCondition + convertWhereCondition\n\t\t\t\t// without introducing circular deps in custom.ts.\n\t\t\t\tif (\n\t\t\t\t\texprIntent.kind === 'customFn' &&\n\t\t\t\t\t(exprIntent as import('@dbsp/types').CustomFnExpressionIntent).filter\n\t\t\t\t) {\n\t\t\t\t\tconst filterIntent = (\n\t\t\t\t\t\texprIntent as import('@dbsp/types').CustomFnExpressionIntent\n\t\t\t\t\t).filter!;\n\t\t\t\t\tconst filterDecision = convertWhereCondition(\n\t\t\t\t\t\tfilterIntent,\n\t\t\t\t\t\tplan.rootTable,\n\t\t\t\t\t);\n\t\t\t\t\tif (filterDecision) {\n\t\t\t\t\t\tconst filterNode = compileFilterCondition(\n\t\t\t\t\t\t\tfilterDecision,\n\t\t\t\t\t\t\tcreateWhereDispatcher(),\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\tstate,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (filterNode && 'FuncCall' in node) {\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\tnode as { FuncCall: Record<string, unknown> }\n\t\t\t\t\t\t\t).FuncCall.agg_filter = filterNode;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// parameters are shared by reference; only sync paramIndex\n\t\t\t\tthis.state.paramIndex = state.paramIndex;\n\t\t\t\tconst alias = decision.alias || decision.column || undefined;\n\t\t\t\ttargetList.push({\n\t\t\t\t\tResTarget: {\n\t\t\t\t\t\tval: node,\n\t\t\t\t\t\t...(alias ? { name: this.naming.toDatabase(alias) } : {}),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 'selectRelationColumn':\n\t\t\tcase 'selectPseudoColumn':\n\t\t\tcase 'selectArithmetic': {\n\t\t\t\tensureExpressionHandlersRegistered();\n\t\t\t\tconst exprType =\n\t\t\t\t\tdecision.type === 'selectRelationColumn'\n\t\t\t\t\t\t? 'relationColumn'\n\t\t\t\t\t\t: decision.type === 'selectPseudoColumn'\n\t\t\t\t\t\t\t? 'pseudoColumn'\n\t\t\t\t\t\t\t: 'arithmetic';\n\t\t\t\tconst handler = getExpressionHandler(exprType);\n\t\t\t\tconst ctx = this.createHandlerContext(plan, plan.rootTable);\n\t\t\t\tconst state = this.createHandlerState();\n\t\t\t\tconst handlerDecision = mapToHandlerDecision(\n\t\t\t\t\tdecision,\n\t\t\t\t\tplan.rootTable,\n\t\t\t\t\tthis.defaultPk,\n\t\t\t\t\tthis.deriveFk,\n\t\t\t\t);\n\t\t\t\tconst node = handler.compile(handlerDecision, ctx, state);\n\t\t\t\tthis.state.paramIndex = state.paramIndex;\n\t\t\t\ttargetList.push({\n\t\t\t\t\tResTarget: {\n\t\t\t\t\t\tval: node,\n\t\t\t\t\t\t...(decision.alias\n\t\t\t\t\t\t\t? { name: this.naming.toDatabase(decision.alias) }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 'selectWindow': {\n\t\t\t\tconst winFuncName = decision.function;\n\t\t\t\tif (!winFuncName) break;\n\t\t\t\t// Always use genericWindowHandler — avoids aggregate handlers\n\t\t\t\t// (sumHandler, avgHandler) being picked for names like 'sum', 'avg'\n\t\t\t\t// which produce FuncCall WITHOUT OVER clause.\n\t\t\t\tconst winHandler = genericWindowHandler;\n\t\t\t\tconst ctx = this.createHandlerContext(\n\t\t\t\t\tplan,\n\t\t\t\t\tdecision.table ?? plan.rootTable,\n\t\t\t\t);\n\t\t\t\tconst state = this.createHandlerState();\n\t\t\t\tconst winDecision = mapToHandlerDecision(\n\t\t\t\t\tdecision,\n\t\t\t\t\tplan.rootTable,\n\t\t\t\t\tthis.defaultPk,\n\t\t\t\t\tthis.deriveFk,\n\t\t\t\t);\n\t\t\t\tconst winNode = winHandler.compile(winDecision, ctx, state);\n\t\t\t\tthis.state.paramIndex = state.paramIndex;\n\t\t\t\ttargetList.push({\n\t\t\t\t\tResTarget: {\n\t\t\t\t\t\tval: winNode,\n\t\t\t\t\t\t...(decision.alias\n\t\t\t\t\t\t\t? { name: this.naming.toDatabase(decision.alias) }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Compile an includeStrategy decision and register its results.\n\t * Pushes targets onto targetList, raw joins / CTEs onto instance collections.\n\t */\n\tprivate compileIncludeDecision(\n\t\tdecision: PlanDecision,\n\t\tplan: SimplifiedPlanReport,\n\t\ttargetList: Node[],\n\t): void {\n\t\tconst includeResult = this.compileIncludeViaHandler(decision, plan);\n\t\tif (includeResult.targets) {\n\t\t\ttargetList.push(...includeResult.targets);\n\t\t}\n\t\tif (includeResult.rawJoin) {\n\t\t\tthis.rawJoins.push(includeResult.rawJoin);\n\t\t}\n\t\tif (includeResult.additionalJoins) {\n\t\t\tthis.rawJoins.push(...includeResult.additionalJoins);\n\t\t}\n\t\tif (includeResult.cte) {\n\t\t\tthis.pendingCtes.push(includeResult.cte);\n\t\t}\n\t}\n\n\t/**\n\t * Fold a WHERE-family decision into an existing where expression.\n\t * Returns the updated (or new) where node.\n\t */\n\tprivate compileWhereDecision(\n\t\tdecision: PlanDecision,\n\t\tcurrentWhere: Node | undefined,\n\t): Node | undefined {\n\t\tswitch (decision.type) {\n\t\t\tcase 'where': {\n\t\t\t\t// JOIN filter: register INNER JOIN instead of EXISTS subquery\n\t\t\t\tif (\n\t\t\t\t\tdecision.operator === 'exists' &&\n\t\t\t\t\tdecision.choice === 'join' &&\n\t\t\t\t\tdecision.targetTable\n\t\t\t\t) {\n\t\t\t\t\tthis.registerJoinFilter(decision);\n\t\t\t\t\t// Add user conditions (on joined table) to WHERE\n\t\t\t\t\tif (decision.conditions && decision.conditions.length > 0) {\n\t\t\t\t\t\tconst joinTarget = decision.targetTable!;\n\t\t\t\t\t\tconst condNodes = decision.conditions.map((c) =>\n\t\t\t\t\t\t\tthis.dispatchWhere(c as PlanDecision, {\n\t\t\t\t\t\t\t\tcurrentAlias: joinTarget,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst combined =\n\t\t\t\t\t\t\tcondNodes.length === 1 ? condNodes[0]! : andExpr(...condNodes);\n\t\t\t\t\t\treturn currentWhere ? andExpr(currentWhere, combined) : combined;\n\t\t\t\t\t}\n\t\t\t\t\treturn currentWhere;\n\t\t\t\t}\n\t\t\t\tconst whereExpr = this.dispatchWhere(decision);\n\t\t\t\treturn currentWhere ? andExpr(currentWhere, whereExpr) : whereExpr;\n\t\t\t}\n\n\t\t\tcase 'whereAnd':\n\t\t\t\tif (decision.conditions) {\n\t\t\t\t\tconst andConditions = decision.conditions.map((c) =>\n\t\t\t\t\t\tthis.dispatchWhere(c),\n\t\t\t\t\t);\n\t\t\t\t\tconst combined =\n\t\t\t\t\t\tandConditions.length === 1\n\t\t\t\t\t\t\t? andConditions[0]!\n\t\t\t\t\t\t\t: andExpr(...andConditions);\n\t\t\t\t\treturn currentWhere ? andExpr(currentWhere, combined) : combined;\n\t\t\t\t}\n\t\t\t\treturn currentWhere;\n\n\t\t\tcase 'whereOr':\n\t\t\t\tif (decision.conditions) {\n\t\t\t\t\tconst orConditions = decision.conditions.map((c) =>\n\t\t\t\t\t\tthis.dispatchWhere(c),\n\t\t\t\t\t);\n\t\t\t\t\tconst combined =\n\t\t\t\t\t\torConditions.length === 1\n\t\t\t\t\t\t\t? orConditions[0]!\n\t\t\t\t\t\t\t: orExpr(...orConditions);\n\t\t\t\t\treturn currentWhere ? andExpr(currentWhere, combined) : combined;\n\t\t\t\t}\n\t\t\t\treturn currentWhere;\n\n\t\t\tcase 'whereNot':\n\t\t\t\tif (decision.conditions) {\n\t\t\t\t\tconst notConditions = decision.conditions.map((c) =>\n\t\t\t\t\t\tthis.dispatchWhere(c),\n\t\t\t\t\t);\n\t\t\t\t\tconst innerExpr =\n\t\t\t\t\t\tnotConditions.length === 1\n\t\t\t\t\t\t\t? notConditions[0]!\n\t\t\t\t\t\t\t: andExpr(...notConditions);\n\t\t\t\t\tconst negated = notExpr(innerExpr);\n\t\t\t\t\treturn currentWhere ? andExpr(currentWhere, negated) : negated;\n\t\t\t\t}\n\t\t\t\treturn currentWhere;\n\n\t\t\tdefault:\n\t\t\t\treturn currentWhere;\n\t\t}\n\t}\n\n\t/**\n\t * Flush pendingJoins and rawJoins into the FROM clause.\n\t * Mutates the from array in-place.\n\t */\n\tprivate flushPendingJoins(from: Node[], plan: SimplifiedPlanReport): void {\n\t\t// Flush pending JOINs into FROM clause\n\t\tfor (const pj of this.pendingJoins) {\n\t\t\tconst targetRV = rangeVar(\n\t\t\t\tpj.table,\n\t\t\t\tpj.alias,\n\t\t\t\tplan.schema ?? this.schema,\n\t\t\t\tthis.naming,\n\t\t\t);\n\t\t\tconst base =\n\t\t\t\tfrom.length > 0\n\t\t\t\t\t? from[0]!\n\t\t\t\t\t: rangeVar(\n\t\t\t\t\t\t\tplan.rootTable,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tplan.schema ?? this.schema,\n\t\t\t\t\t\t\tthis.naming,\n\t\t\t\t\t\t);\n\t\t\tfrom[0] =\n\t\t\t\tpj.type === 'LEFT JOIN'\n\t\t\t\t\t? leftJoin(base, targetRV, pj.on)\n\t\t\t\t\t: innerJoin(base, targetRV, pj.on);\n\t\t}\n\n\t\t// Flush raw JOIN nodes from include handlers (e.g., LATERAL)\n\t\tfor (const rawJoin of this.rawJoins) {\n\t\t\tconst base =\n\t\t\t\tfrom.length > 0\n\t\t\t\t\t? from[0]!\n\t\t\t\t\t: rangeVar(\n\t\t\t\t\t\t\tplan.rootTable,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tplan.schema ?? this.schema,\n\t\t\t\t\t\t\tthis.naming,\n\t\t\t\t\t\t);\n\t\t\t// Raw joins are pre-built JoinExpr — inject base table as larg\n\t\t\tconst joinExpr = rawJoin as JoinExprNode;\n\t\t\tif (joinExpr.JoinExpr) {\n\t\t\t\tjoinExpr.JoinExpr.larg = base;\n\t\t\t\tfrom[0] = rawJoin;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Build the initial FROM clause array and register batch-values parameters.\n\t * For batch-values queries, the unnest RangeFunction replaces the root rangeVar.\n\t */\n\tprivate compileFromClause(plan: SimplifiedPlanReport): Node[] {\n\t\tif (plan.batchValuesFromNode && plan.batchValuesFromParams) {\n\t\t\tfor (const p of plan.batchValuesFromParams) {\n\t\t\t\tthis.state.parameters.push(p);\n\t\t\t}\n\t\t\tthis.state.paramIndex = this.state.parameters.length;\n\t\t}\n\t\treturn [\n\t\t\tplan.batchValuesFromNode\n\t\t\t\t? (plan.batchValuesFromNode as Node)\n\t\t\t\t: rangeVar(\n\t\t\t\t\t\tplan.rootTable,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tplan.schema ?? this.schema,\n\t\t\t\t\t\tthis.naming,\n\t\t\t\t\t),\n\t\t];\n\t}\n\n\t/**\n\t * Fold WHERE conditions from a join-strategy include decision into the\n\t * accumulated WHERE expression. The join alias is used as currentAlias so\n\t * column refs like `project_id` resolve against the joined table, not root.\n\t */\n\tprivate compileIncludeWhereConditions(\n\t\tdecision: PlanDecision,\n\t\twhere: Node | undefined,\n\t): Node | undefined {\n\t\tif (\n\t\t\tdecision.choice !== 'join' ||\n\t\t\t!decision.conditions ||\n\t\t\t(decision.conditions as PlanDecision[]).length === 0\n\t\t) {\n\t\t\treturn where;\n\t\t}\n\t\tconst joinAlias = decision.relationName as string | undefined;\n\t\tfor (const cond of decision.conditions as PlanDecision[]) {\n\t\t\tconst condExpr = this.dispatchWhere(\n\t\t\t\tcond,\n\t\t\t\tjoinAlias ? { currentAlias: joinAlias } : undefined,\n\t\t\t);\n\t\t\twhere = where ? andExpr(where, condExpr) : condExpr;\n\t\t}\n\t\treturn where;\n\t}\n\n\t/**\n\t * Apply a single join decision to the FROM clause in-place.\n\t * Chains multiple joins by wrapping from[0] as the left-arg each time.\n\t */\n\tprivate compileJoinDecision(\n\t\tdecision: PlanDecision,\n\t\tplan: SimplifiedPlanReport,\n\t\tfrom: Node[],\n\t): void {\n\t\tif (isPrecompiledJoinDecision(decision)) {\n\t\t\t// BatchValues: splice batch params into state BEFORE other query params\n\t\t\t// so that $1, $2, ... in the RangeFunction align with parameters[0], [1], ...\n\t\t\tif (isBatchValuesJoinDecision(decision)) {\n\t\t\t\tfor (const p of decision.batchValuesParams) {\n\t\t\t\t\tthis.state.parameters.push(p);\n\t\t\t\t}\n\t\t\t\tthis.state.paramIndex = this.state.parameters.length;\n\t\t\t}\n\t\t\tconst jRarg = decision.joinRarg;\n\t\t\tconst jOn = decision.joinOnNode;\n\t\t\tfrom[0] =\n\t\t\t\tdecision.joinType === 'left'\n\t\t\t\t\t? leftJoin(from[0] as Node, jRarg, jOn)\n\t\t\t\t\t: innerJoin(from[0] as Node, jRarg, jOn);\n\t\t} else {\n\t\t\t// Relation mode: FK-based join, pass from[0] as larg\n\t\t\tfrom[0] = this.compileJoin(decision, plan, from[0] as Node);\n\t\t}\n\t}\n\n\t/**\n\t * Compile a single orderBy decision into a SortBy AST node.\n\t * Supports both expression-intent and plain column references.\n\t */\n\t/**\n\t * Compile a single orderBy decision into a SortBy AST node.\n\t * Supports both expression-intent and plain column references.\n\t * Returns undefined when neither expressionIntent nor column is present.\n\t */\n\tprivate compileOrderByDecision(\n\t\tdecision: PlanDecision,\n\t\tplan: SimplifiedPlanReport,\n\t): Node | undefined {\n\t\tif (decision.expressionIntent) {\n\t\t\tconst exprCtx = this.createHandlerContext(plan, plan.rootTable);\n\t\t\tconst exprState = this.createHandlerState();\n\t\t\tconst exprNode = compileExpressionIntent(\n\t\t\t\tdecision.expressionIntent as ExpressionIntent,\n\t\t\t\texprCtx,\n\t\t\t\texprState,\n\t\t\t);\n\t\t\t// parameters are shared by reference; only sync paramIndex\n\t\t\tthis.state.paramIndex = exprState.paramIndex;\n\t\t\treturn sortBy(\n\t\t\t\texprNode,\n\t\t\t\tdecision.direction ?? 'ASC',\n\t\t\t\tdecision.nulls ?? 'DEFAULT',\n\t\t\t);\n\t\t}\n\t\tif (decision.column) {\n\t\t\treturn sortBy(\n\t\t\t\tcolumnRef(\n\t\t\t\t\tdecision.column as string,\n\t\t\t\t\tdecision.table,\n\t\t\t\t\tundefined,\n\t\t\t\t\tthis.naming,\n\t\t\t\t),\n\t\t\t\tdecision.direction ?? 'ASC',\n\t\t\t\tdecision.nulls ?? 'DEFAULT',\n\t\t\t);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Compile a single groupBy decision into a ColumnRef AST node.\n\t * Supports dotted 'relation.column' notation for joined tables.\n\t */\n\tprivate compileGroupByDecision(decision: PlanDecision): Node {\n\t\tconst gbCol = decision.column as string;\n\t\tconst gbDot = gbCol.indexOf('.');\n\t\tif (gbDot !== -1) {\n\t\t\treturn columnRef(\n\t\t\t\tgbCol.slice(gbDot + 1),\n\t\t\t\tgbCol.slice(0, gbDot),\n\t\t\t\tundefined,\n\t\t\t\tthis.naming,\n\t\t\t);\n\t\t}\n\t\treturn columnRef(gbCol, decision.table, undefined, this.naming);\n\t}\n\n\t/**\n\t * Assemble the final SelectStmt from all accumulated clause nodes.\n\t * Also handles the default SELECT *, CTEs, and row-level locking.\n\t */\n\tprivate buildSelectStmt(\n\t\ttargetList: Node[],\n\t\tfrom: Node[],\n\t\twhere: Node | undefined,\n\t\torderBy: Node[],\n\t\tgroupBy: Node[],\n\t\thaving: Node | undefined,\n\t\tlimit: Node | undefined,\n\t\toffset: Node | undefined,\n\t\tdistinct: boolean | Node[],\n\t\tplan: SimplifiedPlanReport,\n\t): Node {\n\t\t// Default to SELECT * if no columns specified\n\t\tif (targetList.length === 0) {\n\t\t\ttargetList.push(starTarget(undefined, this.naming));\n\t\t}\n\n\t\t// Build options object, only including defined properties\n\t\tconst options: Parameters<typeof selectStmt>[0] = {\n\t\t\ttargetList,\n\t\t\tfrom,\n\t\t};\n\n\t\tif (where) options.where = where;\n\t\tif (groupBy.length > 0) options.groupBy = groupBy;\n\t\tif (having) options.having = having;\n\t\tif (orderBy.length > 0) options.orderBy = orderBy;\n\t\tif (limit) options.limit = limit;\n\t\tif (offset) options.offset = offset;\n\t\tif (distinct) options.distinct = distinct;\n\t\tif (this.pendingCtes.length > 0) {\n\t\t\toptions.withClause = { ctes: this.pendingCtes, recursive: false };\n\t\t}\n\n\t\t// Row-level locking (E15: FOR UPDATE/SHARE/etc.)\n\t\tif (plan.lock) {\n\t\t\tconst mapped = mapLockToAst(plan.lock);\n\t\t\t// INV-E15-05: When query has JOINs (includes), scope lock to root table\n\t\t\t// to prevent lock amplification on joined tables.\n\t\t\tconst hasJoins = this.rawJoins.length > 0;\n\t\t\toptions.lockingClause = {\n\t\t\t\t...mapped,\n\t\t\t\t...(hasJoins\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tlockedRels: [\n\t\t\t\t\t\t\t\trangeVar(\n\t\t\t\t\t\t\t\t\tplan.rootTable,\n\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\tplan.schema ?? this.schema,\n\t\t\t\t\t\t\t\t\tthis.naming,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t};\n\t\t}\n\n\t\treturn selectStmt(options);\n\t}\n\n\tprivate compileSelect(plan: SimplifiedPlanReport): Node {\n\t\tconst targetList: Node[] = [];\n\t\tconst from = this.compileFromClause(plan);\n\t\tlet where: Node | undefined;\n\t\tconst orderBy: Node[] = [];\n\t\tconst groupBy: Node[] = [];\n\t\tlet having: Node | undefined;\n\t\tlet limit: Node | undefined;\n\t\tlet offset: Node | undefined;\n\t\tlet distinct: boolean | Node[] = false;\n\n\t\tfor (const decision of plan.decisions) {\n\t\t\tswitch (decision.type) {\n\t\t\t\tcase 'select':\n\t\t\t\tcase 'selectFunction':\n\t\t\t\tcase 'selectExpression':\n\t\t\t\tcase 'selectRelationColumn':\n\t\t\t\tcase 'selectPseudoColumn':\n\t\t\t\tcase 'selectArithmetic':\n\t\t\t\tcase 'selectWindow':\n\t\t\t\tcase 'selectCustomExpression':\n\t\t\t\t\tthis.compileSelectTarget(decision, plan, targetList);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'includeStrategy':\n\t\t\t\t\tthis.compileIncludeDecision(decision, plan, targetList);\n\t\t\t\t\twhere = this.compileIncludeWhereConditions(decision, where);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'where':\n\t\t\t\tcase 'whereAnd':\n\t\t\t\tcase 'whereOr':\n\t\t\t\tcase 'whereNot':\n\t\t\t\t\twhere = this.compileWhereDecision(decision, where);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'join':\n\t\t\t\t\tthis.compileJoinDecision(decision, plan, from);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'orderBy': {\n\t\t\t\t\tconst obNode = this.compileOrderByDecision(decision, plan);\n\t\t\t\t\tif (obNode) orderBy.push(obNode);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase 'groupBy':\n\t\t\t\t\tif (decision.column) {\n\t\t\t\t\t\tgroupBy.push(this.compileGroupByDecision(decision));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'having':\n\t\t\t\t\thaving = this.dispatchWhere(decision);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'limit':\n\t\t\t\t\tif (typeof decision.limit === 'number') {\n\t\t\t\t\t\tlimit = integerNode(decision.limit);\n\t\t\t\t\t} else if (decision.limit?.paramIndex !== undefined) {\n\t\t\t\t\t\tlimit = createParamRef(decision.limit.paramIndex);\n\t\t\t\t\t\tthis.state.parameters.push(undefined); // Placeholder\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'offset':\n\t\t\t\t\tif (typeof decision.offset === 'number') {\n\t\t\t\t\t\toffset = integerNode(decision.offset);\n\t\t\t\t\t} else if (decision.offset?.paramIndex !== undefined) {\n\t\t\t\t\t\toffset = createParamRef(decision.offset.paramIndex);\n\t\t\t\t\t\tthis.state.parameters.push(undefined); // Placeholder\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'distinct':\n\t\t\t\t\tdistinct = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'distinctOn':\n\t\t\t\t\tif (decision.columns && decision.columns.length > 0) {\n\t\t\t\t\t\tdistinct = decision.columns.map((col) =>\n\t\t\t\t\t\t\tcolumnRef(col as string, undefined, undefined, this.naming),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tthis.flushPendingJoins(from, plan);\n\t\treturn this.buildSelectStmt(\n\t\t\ttargetList,\n\t\t\tfrom,\n\t\t\twhere,\n\t\t\torderBy,\n\t\t\tgroupBy,\n\t\t\thaving,\n\t\t\tlimit,\n\t\t\toffset,\n\t\t\tdistinct,\n\t\t\tplan,\n\t\t);\n\t}\n\n\t// --------------------------------------------------------------------------\n\t// EXISTS Wrapping\n\t// --------------------------------------------------------------------------\n\n\t/**\n\t * Wrap a SELECT statement in SELECT EXISTS(SELECT 1 ...) AS \"exists\"\n\t *\n\t * This transforms the inner SELECT by:\n\t * 1. Replacing targetList with just `1` (constant)\n\t * 2. Wrapping in SubLink with EXISTS_SUBLINK\n\t * 3. Creating outer SELECT with EXISTS result aliased as \"exists\"\n\t */\n\tprivate wrapSelectInExists(innerAst: Node): Node {\n\t\t// Get the inner SelectStmt and modify its targetList to just `1`\n\t\tconst innerSelectNode = innerAst as SelectStmtNode;\n\t\tif (!innerSelectNode.SelectStmt) {\n\t\t\tthrow new Error('existsWrap requires a SelectStmt');\n\t\t}\n\t\tconst innerSelect = innerSelectNode.SelectStmt;\n\n\t\t// Create inner SELECT with just `1` as target\n\t\tconst modifiedInner: Node = {\n\t\t\tSelectStmt: {\n\t\t\t\t...innerSelect,\n\t\t\t\ttargetList: [\n\t\t\t\t\t{\n\t\t\t\t\t\tResTarget: {\n\t\t\t\t\t\t\tval: { A_Const: { ival: { ival: 1 } } },\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t};\n\n\t\t// Wrap in EXISTS SubLink\n\t\tconst existsExpr: Node = {\n\t\t\tSubLink: {\n\t\t\t\tsubLinkType: 'EXISTS_SUBLINK',\n\t\t\t\tsubselect: modifiedInner,\n\t\t\t},\n\t\t};\n\n\t\t// Create outer SELECT with EXISTS result aliased as \"exists\"\n\t\treturn selectStmt({\n\t\t\ttargetList: [\n\t\t\t\t{\n\t\t\t\t\tResTarget: {\n\t\t\t\t\t\tval: existsExpr,\n\t\t\t\t\t\tname: 'exists',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t\tfrom: [],\n\t\t});\n\t}\n\n\t// --------------------------------------------------------------------------\n\t// CASE Expression Compilation\n\t// --------------------------------------------------------------------------\n\n\tprivate compileCaseExpression(decision: PlanDecision): Node {\n\t\t// CASE decisions carry { when, then } tuples in `conditions` —\n\t\t// structurally different from the base PlanDecision[].\n\t\tconst conditions = decision.conditions as\n\t\t\t| readonly { when: PlanDecision; then: unknown }[]\n\t\t\t| undefined;\n\t\tconst elseValue = decision.value;\n\n\t\tif (!conditions || conditions.length === 0) {\n\t\t\tthrow new Error('CASE requires at least one WHEN condition');\n\t\t}\n\n\t\tconst args: Node[] = conditions.map((cond) => {\n\t\t\tconst whenExpr = this.dispatchWhere(cond.when);\n\t\t\tconst thenResult = this.compileCaseValue(cond.then);\n\n\t\t\treturn {\n\t\t\t\tCaseWhen: {\n\t\t\t\t\texpr: whenExpr,\n\t\t\t\t\tresult: thenResult,\n\t\t\t\t},\n\t\t\t};\n\t\t});\n\n\t\tlet defresult: Node | undefined;\n\t\tif (elseValue !== undefined) {\n\t\t\tdefresult = this.compileCaseValue(elseValue);\n\t\t}\n\n\t\treturn {\n\t\t\tCaseExpr: {\n\t\t\t\targs,\n\t\t\t\t...(defresult ? { defresult } : {}),\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Compile a CASE THEN/ELSE value based on its ExpressionIntent kind.\n\t * Delegates to shared resolveCaseValue with nested CASE support.\n\t */\n\tprivate compileCaseValue(value: unknown): Node {\n\t\treturn resolveCaseValueShared(\n\t\t\tvalue,\n\t\t\tthis.currentRootTable,\n\t\t\tundefined,\n\t\t\tthis.naming,\n\t\t\tthis.state,\n\t\t\t(expr) =>\n\t\t\t\tthis.compileCaseExpression({\n\t\t\t\t\ttype: 'selectExpression',\n\t\t\t\t\texpressionType: 'case',\n\t\t\t\t\tconditions: (\n\t\t\t\t\t\texpr.when as Array<{ condition: unknown; result: unknown }>\n\t\t\t\t\t).map((wc) => ({\n\t\t\t\t\t\twhen: wc.condition as PlanDecision,\n\t\t\t\t\t\t// biome-ignore lint/suspicious/noThenProperty: intentional\n\t\t\t\t\t\tthen: wc.result,\n\t\t\t\t\t})),\n\t\t\t\t\tvalue: expr.else,\n\t\t\t\t\ttable: this.currentRootTable,\n\t\t\t\t} as unknown as PlanDecision),\n\t\t);\n\t}\n\n\t// --------------------------------------------------------------------------\n\t// INSERT Compilation\n\t// --------------------------------------------------------------------------\n\n\tprivate compileInsert(plan: SimplifiedPlanReport): Node {\n\t\tconst columns: string[] = [];\n\t\tconst values: Node[][] = [];\n\t\tconst returning: Node[] = [];\n\n\t\tfor (const decision of plan.decisions) {\n\t\t\tif (decision.type === 'insert') {\n\t\t\t\tif (decision.columns) {\n\t\t\t\t\tcolumns.push(...decision.columns);\n\t\t\t\t}\n\t\t\t\tif (decision.values) {\n\t\t\t\t\tconst row = decision.values.map((v) => compileValue(v, this.state));\n\t\t\t\t\tvalues.push(row);\n\t\t\t\t}\n\t\t\t} else if (decision.type === 'returning') {\n\t\t\t\tif (decision.column === '*') {\n\t\t\t\t\treturning.push(starTarget(undefined, this.naming));\n\t\t\t\t} else if (decision.column) {\n\t\t\t\t\treturning.push(\n\t\t\t\t\t\tcolumnTarget(\n\t\t\t\t\t\t\tdecision.column,\n\t\t\t\t\t\t\tdecision.alias,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tthis.naming,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst insertOptions: Parameters<typeof insertStmt>[0] = {\n\t\t\ttable: plan.rootTable,\n\t\t\tcolumns,\n\t\t\tvalues,\n\t\t\tnaming: this.naming,\n\t\t};\n\n\t\tconst schema = plan.schema ?? this.schema;\n\t\tif (schema) insertOptions.schema = schema;\n\t\tif (returning.length > 0) insertOptions.returning = returning;\n\n\t\treturn insertStmt(insertOptions);\n\t}\n\n\t// --------------------------------------------------------------------------\n\t// UPDATE Compilation\n\t// --------------------------------------------------------------------------\n\n\tprivate compileUpdate(plan: SimplifiedPlanReport): Node {\n\t\tconst set: Array<{ column: string; value: Node }> = [];\n\t\tlet where: Node | undefined;\n\t\tconst returning: Node[] = [];\n\n\t\tfor (const decision of plan.decisions) {\n\t\t\tif (decision.type === 'update') {\n\t\t\t\tif (decision.set) {\n\t\t\t\t\tfor (const s of decision.set) {\n\t\t\t\t\t\tset.push({\n\t\t\t\t\t\t\tcolumn: s.column,\n\t\t\t\t\t\t\tvalue: compileValue(s.value, this.state),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (decision.type === 'where') {\n\t\t\t\tconst whereExpr = this.dispatchWhere(decision);\n\t\t\t\twhere = where ? andExpr(where, whereExpr) : whereExpr;\n\t\t\t} else if (decision.type === 'returning') {\n\t\t\t\tif (decision.column === '*') {\n\t\t\t\t\treturning.push(starTarget(undefined, this.naming));\n\t\t\t\t} else if (decision.column) {\n\t\t\t\t\treturning.push(\n\t\t\t\t\t\tcolumnTarget(\n\t\t\t\t\t\t\tdecision.column,\n\t\t\t\t\t\t\tdecision.alias,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tthis.naming,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst updateOptions: Parameters<typeof updateStmt>[0] = {\n\t\t\ttable: plan.rootTable,\n\t\t\tset,\n\t\t\tnaming: this.naming,\n\t\t};\n\n\t\tconst updateSchema = plan.schema ?? this.schema;\n\t\tif (updateSchema) updateOptions.schema = updateSchema;\n\t\tif (where) updateOptions.where = where;\n\t\tif (returning.length > 0) updateOptions.returning = returning;\n\n\t\treturn updateStmt(updateOptions);\n\t}\n\n\t// --------------------------------------------------------------------------\n\t// DELETE Compilation\n\t// --------------------------------------------------------------------------\n\n\tprivate compileDelete(plan: SimplifiedPlanReport): Node {\n\t\tlet where: Node | undefined;\n\t\tconst returning: Node[] = [];\n\n\t\tfor (const decision of plan.decisions) {\n\t\t\tif (decision.type === 'where') {\n\t\t\t\tconst whereExpr = this.dispatchWhere(decision);\n\t\t\t\twhere = where ? andExpr(where, whereExpr) : whereExpr;\n\t\t\t} else if (decision.type === 'returning') {\n\t\t\t\tif (decision.column === '*') {\n\t\t\t\t\treturning.push(starTarget(undefined, this.naming));\n\t\t\t\t} else if (decision.column) {\n\t\t\t\t\treturning.push(\n\t\t\t\t\t\tcolumnTarget(\n\t\t\t\t\t\t\tdecision.column,\n\t\t\t\t\t\t\tdecision.alias,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tthis.naming,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else if (decision.type === 'delete') {\n\t\t\t\t// Mark as delete query (handled by detectQueryType)\n\t\t\t}\n\t\t}\n\n\t\tconst deleteOptions: Parameters<typeof deleteStmt>[0] = {\n\t\t\ttable: plan.rootTable,\n\t\t\tnaming: this.naming,\n\t\t};\n\n\t\tconst deleteSchema = plan.schema ?? this.schema;\n\t\tif (deleteSchema) deleteOptions.schema = deleteSchema;\n\t\tif (where) deleteOptions.where = where;\n\t\tif (returning.length > 0) deleteOptions.returning = returning;\n\n\t\treturn deleteStmt(deleteOptions);\n\t}\n\n\t// --------------------------------------------------------------------------\n\t// Helpers (condition compilation via handler dispatcher)\n\t// --------------------------------------------------------------------------\n\n\t/**\n\t * Register an INNER JOIN for a belongsTo filter-strategy decision.\n\t * The JOIN replaces the EXISTS subquery when the planner chooses 'join'.\n\t * The ON condition correlates FK → PK (belongsTo: source.FK = target.PK).\n\t */\n\tprivate registerJoinFilter(decision: PlanDecision): void {\n\t\tconst targetTable = decision.targetTable!;\n\t\tconst sourceTable = this.currentRootTable;\n\n\t\t// For belongsTo: FK is on source table, references target PK\n\t\t// e.g., posts.author_id → authors.id\n\t\tconst fkColumn =\n\t\t\tdecision.foreignKey ?? this.deriveFk(targetTable, this.defaultPk);\n\t\tconst onCondition = eqExpr(\n\t\t\tcolumnRef(this.defaultPk, targetTable, undefined, this.naming),\n\t\t\tcolumnRef(fkColumn, sourceTable, undefined, this.naming),\n\t\t);\n\n\t\t// Use relation-based alias for self-referential tables\n\t\tconst alias =\n\t\t\ttargetTable === sourceTable\n\t\t\t\t? (decision.relationName ?? `${targetTable}_join`)\n\t\t\t\t: undefined;\n\n\t\tthis.pendingJoins.push({\n\t\t\ttype: 'JOIN',\n\t\t\ttable: targetTable,\n\t\t\t...(alias && { alias }),\n\t\t\ton: onCondition,\n\t\t});\n\t}\n\n\tprivate compileJoin(\n\t\tdecision: PlanDecision,\n\t\tplan: SimplifiedPlanReport,\n\t\tlarg?: Node,\n\t): Node {\n\t\tconst baseTable =\n\t\t\tlarg ??\n\t\t\trangeVar(\n\t\t\t\tplan.rootTable,\n\t\t\t\tundefined,\n\t\t\t\tplan.schema ?? this.schema,\n\t\t\t\tthis.naming,\n\t\t\t);\n\t\tconst targetTable = rangeVar(\n\t\t\tdecision.targetTable ?? '',\n\t\t\tdecision.alias,\n\t\t\tplan.schema ?? this.schema,\n\t\t\tthis.naming,\n\t\t);\n\n\t\tconst onCondition = eqExpr(\n\t\t\tcolumnRef(\n\t\t\t\trequiredColumn(decision.sourceColumn, 'sourceColumn', 'compileJoin'),\n\t\t\t\tundefined,\n\t\t\t\tundefined,\n\t\t\t\tthis.naming,\n\t\t\t),\n\t\t\tcolumnRef(\n\t\t\t\trequiredColumn(decision.targetColumn, 'targetColumn', 'compileJoin'),\n\t\t\t\tdecision.alias ?? decision.targetTable,\n\t\t\t\tundefined,\n\t\t\t\tthis.naming,\n\t\t\t),\n\t\t);\n\n\t\tif (decision.joinType === 'left') {\n\t\t\treturn leftJoin(baseTable, targetTable, onCondition, decision.alias);\n\t\t}\n\n\t\treturn innerJoin(baseTable, targetTable, onCondition, decision.alias);\n\t}\n}\n\n/**\n * Convenience function to compile a plan\n */\nexport function compilePlan(\n\tplan: SimplifiedPlanReport,\n\toptions?: CompilerOptions,\n): CompiledResult {\n\tconst compiler = new PlanCompiler(options);\n\treturn compiler.compile(plan);\n}\n","/**\n * Internal PostgreSQL AST deparser.\n *\n * Handles all AST node types that dbsp produces (~40 types).\n * Output is intentionally identical to pgsql-deparser (deparseSync) for all\n * nodes the compiler emits.\n *\n * Formatting rules:\n * - Identifiers: double-quoted → \"table\".\"column\"\n * - String literals: single-quoted → 'value'\n * - Parameters: $1, $2, etc.\n * - TypeCast: CAST(arg AS type) form (pgsql-deparser normalizes to CAST)\n * - Operators: spaces around → a + b, a = b\n * - Keywords: UPPERCASE\n * - NULL literal: NULL\n * - Boolean: TRUE / FALSE\n */\n\nimport type {\n\tA_ArrayExpr,\n\tA_Const,\n\tA_Expr,\n\tAlias,\n\tBoolExpr,\n\tCaseExpr,\n\tCaseWhen,\n\tClosePortalStmt,\n\tCoalesceExpr,\n\tColumnRef,\n\tCommonTableExpr,\n\tCTECycleClause,\n\tDeclareCursorStmt,\n\tDefElem,\n\tDeleteStmt,\n\tExplainStmt,\n\tFetchStmt,\n\tFloat,\n\tFuncCall,\n\tIndexElem,\n\tInferClause,\n\tInsertStmt,\n\tInteger,\n\tJoinExpr,\n\tLockingClause,\n\tNode,\n\tNullTest,\n\tOnConflictClause,\n\tParamRef,\n\tString as PgString,\n\tRangeVar,\n\tResTarget,\n\tSelectStmt,\n\tSortBy,\n\tSubLink,\n\tTypeCast,\n\tTypeName,\n\tUpdateStmt,\n\tWindowDef,\n\tWithClause,\n} from '@pgsql/types';\n\n// ---------------------------------------------------------------------------\n// Entry point\n// ---------------------------------------------------------------------------\n\nexport function deparse(node: Node): string {\n\tif (node === null || node === undefined) {\n\t\treturn 'NULL';\n\t}\n\tconst rec = node as Record<string, unknown>;\n\tconst keys = Object.keys(rec);\n\tif (keys.length === 0) return '';\n\tconst key = keys[0]!;\n\tconst inner = rec[key];\n\n\tswitch (key) {\n\t\tcase 'SelectStmt':\n\t\t\treturn deparseSelectStmt(inner as SelectStmt);\n\t\tcase 'InsertStmt':\n\t\t\treturn deparseInsertStmt(inner as InsertStmt);\n\t\tcase 'UpdateStmt':\n\t\t\treturn deparseUpdateStmt(inner as UpdateStmt);\n\t\tcase 'DeleteStmt':\n\t\t\treturn deparseDeleteStmt(inner as DeleteStmt);\n\t\tcase 'ExplainStmt':\n\t\t\treturn deparseExplainStmt(inner as ExplainStmt);\n\t\tcase 'ColumnRef':\n\t\t\treturn deparseColumnRef(inner as ColumnRef);\n\t\tcase 'RangeVar':\n\t\t\treturn deparseRangeVar(inner as RangeVar);\n\t\tcase 'A_Star':\n\t\t\treturn '*';\n\t\tcase 'ResTarget':\n\t\t\treturn deparseResTarget(inner as ResTarget);\n\t\tcase 'A_Expr':\n\t\t\treturn deparseAExpr(inner as A_Expr);\n\t\tcase 'BoolExpr':\n\t\t\treturn deparseBoolExpr(inner as BoolExpr);\n\t\tcase 'FuncCall':\n\t\t\treturn deparseFuncCall(inner as FuncCall);\n\t\tcase 'CoalesceExpr':\n\t\t\treturn deparseCoalesceExpr(inner as CoalesceExpr);\n\t\tcase 'NullIfExpr':\n\t\t\treturn deparseNullIfExpr(inner as { args?: Node[] });\n\t\tcase 'MinMaxExpr':\n\t\t\treturn deparseMinMaxExpr(inner as { op?: string; args?: Node[] });\n\t\tcase 'CaseExpr':\n\t\t\treturn deparseCaseExpr(inner as CaseExpr);\n\t\tcase 'CaseWhen':\n\t\t\treturn deparseCaseWhen(inner as CaseWhen);\n\t\tcase 'TypeCast':\n\t\t\treturn deparseTypeCast(inner as TypeCast);\n\t\tcase 'TypeName':\n\t\t\treturn deparseTypeName(inner as TypeName);\n\t\tcase 'NullTest':\n\t\t\treturn deparseNullTest(inner as NullTest);\n\t\tcase 'SubLink':\n\t\t\treturn deparseSubLink(inner as SubLink);\n\t\tcase 'ParamRef':\n\t\t\treturn deparseParamRef(inner as ParamRef);\n\t\tcase 'A_Const':\n\t\t\treturn deparseAConst(inner as A_Const);\n\t\tcase 'String':\n\t\t\treturn deparseStringNode(inner as PgString);\n\t\tcase 'Integer':\n\t\t\treturn deparseIntegerNode(inner as Integer);\n\t\tcase 'Float':\n\t\t\treturn deparseFloatNode(inner as Float);\n\t\tcase 'JoinExpr':\n\t\t\treturn deparseJoinExpr(inner as JoinExpr);\n\t\tcase 'SortBy':\n\t\t\treturn deparseSortBy(inner as SortBy);\n\t\tcase 'WindowDef':\n\t\t\treturn deparseWindowDef(inner as WindowDef);\n\t\tcase 'CommonTableExpr':\n\t\t\treturn deparseCommonTableExpr(inner as CommonTableExpr);\n\t\tcase 'WithClause':\n\t\t\treturn deparseWithClause(inner as WithClause);\n\t\tcase 'CTECycleClause':\n\t\t\treturn deparseCTECycleClause(inner as CTECycleClause);\n\t\tcase 'OnConflictClause':\n\t\t\treturn deparseOnConflictClause(inner as OnConflictClause);\n\t\tcase 'LockingClause':\n\t\t\treturn deparseLockingClause(inner as LockingClause);\n\t\tcase 'List':\n\t\t\treturn deparseListNode(inner as { items?: Node[] });\n\t\tcase 'Alias':\n\t\t\treturn deparseAlias(inner as Alias);\n\t\tcase 'ClosePortalStmt':\n\t\t\treturn deparseClosePortalStmt(inner as ClosePortalStmt);\n\t\tcase 'Null':\n\t\t\treturn 'NULL';\n\t\tcase 'InferClause':\n\t\t\treturn deparseInferClause(inner as InferClause);\n\t\tcase 'A_ArrayExpr':\n\t\t\treturn deparseArrayExpr(inner as A_ArrayExpr);\n\t\tcase 'DeclareCursorStmt':\n\t\t\treturn deparseDeclareCursorStmt(inner as DeclareCursorStmt);\n\t\tcase 'FetchStmt':\n\t\t\treturn deparseFetchStmt(inner as FetchStmt);\n\t\tcase 'DefElem':\n\t\t\treturn deparseDefElem(inner as DefElem);\n\t\tcase 'IndexElem':\n\t\t\treturn deparseIndexElem(inner as IndexElem);\n\t\tcase 'RangeFunction':\n\t\t\treturn deparseRangeFunction(inner as Record<string, unknown>);\n\t\tcase 'NamedArgExpr': {\n\t\t\tconst nae = inner as { arg: Node; name: string };\n\t\t\treturn `${nae.name} => ${deparse(nae.arg)}`;\n\t\t}\n\t\tcase 'RawSQL': {\n\t\t\t// Custom node: verbatim SQL passthrough (used by raw() escape hatch)\n\t\t\treturn (inner as { sql: string }).sql;\n\t\t}\n\t\tcase 'RangeSubselect':\n\t\t\treturn deparseRangeSubselect(inner as Record<string, unknown>);\n\t\tdefault:\n\t\t\tthrow new Error(`deparse: unsupported AST node type: ${key}`);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n// PostgreSQL reserved words that must be double-quoted when used as identifiers.\n// This is the minimal set needed for identifiers the dbsp compiler emits.\n// Note: 'excluded' is intentionally omitted — it's unquoted in UPSERT SET context.\nconst PG_RESERVED = new Set([\n\t'all',\n\t'analyse',\n\t'analyze',\n\t'and',\n\t'any',\n\t'array',\n\t'as',\n\t'asc',\n\t'asymmetric',\n\t'both',\n\t'case',\n\t'cast',\n\t'check',\n\t'collate',\n\t'column',\n\t'constraint',\n\t'create',\n\t'cross',\n\t'current_catalog',\n\t'current_date',\n\t'current_role',\n\t'current_schema',\n\t'current_time',\n\t'current_timestamp',\n\t'current_user',\n\t'default',\n\t'deferrable',\n\t'desc',\n\t'distinct',\n\t'do',\n\t'else',\n\t'end',\n\t'except',\n\t'false',\n\t'fetch',\n\t'for',\n\t'foreign',\n\t'freeze',\n\t'from',\n\t'full',\n\t'grant',\n\t'group',\n\t'having',\n\t'ilike',\n\t'in',\n\t'initially',\n\t'inner',\n\t'intersect',\n\t'into',\n\t'is',\n\t'isnull',\n\t'join',\n\t'lateral',\n\t'leading',\n\t'left',\n\t'like',\n\t'limit',\n\t'localtime',\n\t'localtimestamp',\n\t'natural',\n\t'not',\n\t'notnull',\n\t'null',\n\t'offset',\n\t'on',\n\t'only',\n\t'or',\n\t'order',\n\t'outer',\n\t'overlaps',\n\t'placing',\n\t'primary',\n\t'references',\n\t'returning',\n\t'right',\n\t'select',\n\t'session_user',\n\t'similar',\n\t'some',\n\t'symmetric',\n\t'system_user',\n\t'table',\n\t'timestamp',\n\t'tablesample',\n\t'then',\n\t'to',\n\t'trailing',\n\t'true',\n\t'union',\n\t'unique',\n\t'user',\n\t'using',\n\t'variadic',\n\t'verbose',\n\t'when',\n\t'where',\n\t'window',\n\t'with',\n\t// Non-reserved but used as output column alias by dbsp compiler\n\t'exists',\n\t// SQL standard function keywords that pgsql-deparser quotes in FuncCall context\n\t'coalesce',\n]);\n\nfunction quoteIdent(name: string): string {\n\t// Quote when needed: uppercase, spaces, special chars, or reserved words.\n\tif (/^[a-z_][a-z0-9_]*$/.test(name) && !PG_RESERVED.has(name)) {\n\t\treturn name;\n\t}\n\treturn `\"${name.replace(/\"/g, '\"\"')}\"`;\n}\n\nfunction quoteString(value: string): string {\n\treturn `'${value.replace(/'/g, \"''\")}'`;\n}\n\nfunction nodeToStr(n: Node): string {\n\treturn deparse(n);\n}\n\nfunction strNodeVal(n: Node): string {\n\tconst r = n as Record<string, unknown>;\n\tconst k = Object.keys(r)[0]!;\n\tif (k === 'String') {\n\t\treturn ((r[k] as Record<string, unknown>).sval as string | undefined) ?? '';\n\t}\n\treturn '';\n}\n\n// ---------------------------------------------------------------------------\n// Leaf nodes\n// ---------------------------------------------------------------------------\n\nfunction deparseStringNode(node: PgString): string {\n\t// String nodes are used as identifiers — double-quote them\n\treturn quoteIdent(node.sval ?? '');\n}\n\nfunction deparseIntegerNode(node: Integer): string {\n\treturn String(node.ival ?? 0);\n}\n\nfunction deparseFloatNode(node: Float): string {\n\treturn node.fval ?? '';\n}\n\n// ---------------------------------------------------------------------------\n// A_Const (literal constant)\n// ---------------------------------------------------------------------------\n\nfunction deparseAConst(node: A_Const): string {\n\tif ('isnull' in node && (node as Record<string, unknown>).isnull) {\n\t\treturn 'NULL';\n\t}\n\tconst rec = node as Record<string, unknown>;\n\t// integer: { ival: { ival: N } } or { ival: N }\n\tif ('ival' in rec && rec.ival !== undefined) {\n\t\tconst iv = rec.ival as Record<string, unknown> | number;\n\t\treturn String(typeof iv === 'object' ? (iv.ival as number) : iv);\n\t}\n\t// float: { fval: { fval: \"N\" } } or { fval: \"N\" }\n\tif ('fval' in rec && rec.fval !== undefined) {\n\t\tconst fv = rec.fval as Record<string, unknown> | string;\n\t\treturn typeof fv === 'object' ? String(fv.fval ?? '') : fv;\n\t}\n\t// boolean: { boolval: { boolval: bool } } or { boolval: bool }\n\tif ('boolval' in rec && rec.boolval !== undefined) {\n\t\tconst bv = rec.boolval as Record<string, unknown> | boolean;\n\t\tconst val = typeof bv === 'object' ? (bv.boolval as boolean) : bv;\n\t\treturn val ? 'true' : 'false';\n\t}\n\t// string: { sval: { sval: \"...\" } } or { sval: \"...\" }\n\tif ('sval' in rec && rec.sval !== undefined) {\n\t\tconst sv = rec.sval as Record<string, unknown> | string;\n\t\tconst s = typeof sv === 'object' ? String(sv.sval ?? '') : sv;\n\t\treturn quoteString(s);\n\t}\n\treturn 'NULL';\n}\n\n// ---------------------------------------------------------------------------\n// ParamRef\n// ---------------------------------------------------------------------------\n\nfunction deparseParamRef(node: ParamRef): string {\n\treturn `$${node.number}`;\n}\n\n// ---------------------------------------------------------------------------\n// ColumnRef\n// ---------------------------------------------------------------------------\n\nfunction deparseColumnRef(node: ColumnRef): string {\n\tconst fields = node.fields ?? [];\n\tconst parts = fields.map((f) => {\n\t\tconst r = f as Record<string, unknown>;\n\t\tconst k = Object.keys(r)[0]!;\n\t\tif (k === 'A_Star') return '*';\n\t\t// String node → identifier\n\t\tconst inner = r[k] as Record<string, unknown>;\n\t\treturn quoteIdent(String(inner.sval ?? ''));\n\t});\n\treturn parts.join('.');\n}\n\n// ---------------------------------------------------------------------------\n// RangeVar\n// ---------------------------------------------------------------------------\n\nfunction deparseRangeVar(node: RangeVar): string {\n\tlet result = '';\n\tif (node.schemaname) {\n\t\tresult += `${quoteIdent(node.schemaname)}.`;\n\t}\n\tresult += quoteIdent(node.relname ?? '');\n\tif (node.alias) {\n\t\tresult += ` AS ${quoteIdent(node.alias.aliasname ?? '')}`;\n\t}\n\treturn result;\n}\n\n// ---------------------------------------------------------------------------\n// Alias\n// ---------------------------------------------------------------------------\n\nfunction deparseAlias(node: Alias): string {\n\treturn quoteIdent(node.aliasname ?? '');\n}\n\n// ---------------------------------------------------------------------------\n// ResTarget\n// ---------------------------------------------------------------------------\n\nfunction deparseResTarget(node: ResTarget): string {\n\tif (node.val) {\n\t\tconst val = deparse(node.val);\n\t\tif (node.name) {\n\t\t\treturn `${val} AS ${quoteIdent(node.name)}`;\n\t\t}\n\t\treturn val;\n\t}\n\tif (node.name) {\n\t\treturn quoteIdent(node.name);\n\t}\n\treturn '';\n}\n\n// ---------------------------------------------------------------------------\n// A_Expr\n// ---------------------------------------------------------------------------\n\nfunction getOpName(node: A_Expr): string {\n\tif (!node.name || node.name.length === 0) return '';\n\treturn strNodeVal(node.name[0]!);\n}\n\nfunction deparseAExpr(node: A_Expr): string {\n\tconst kind = node.kind;\n\tconst op = getOpName(node);\n\n\tif (kind === 'AEXPR_OP') {\n\t\t// Parenthesize nested A_Expr operands to preserve operator precedence.\n\t\t// Custom operators have unknown precedence — wrap nested binary\n\t\t// expressions to guarantee correct SQL semantics.\n\t\tconst leftRaw = node.lexpr ? deparse(node.lexpr) : '';\n\t\tconst rightRaw = node.rexpr ? deparse(node.rexpr) : '';\n\t\tconst left =\n\t\t\tnode.lexpr && 'A_Expr' in node.lexpr ? `(${leftRaw})` : leftRaw;\n\t\tconst right =\n\t\t\tnode.rexpr && 'A_Expr' in node.rexpr ? `(${rightRaw})` : rightRaw;\n\t\tif (!left) {\n\t\t\treturn `${op} ${right}`;\n\t\t}\n\t\treturn `${left} ${op} ${right}`;\n\t}\n\n\tif (kind === 'AEXPR_OP_ANY') {\n\t\tconst left = node.lexpr ? deparse(node.lexpr) : '';\n\t\tconst right = node.rexpr ? deparse(node.rexpr) : '';\n\t\treturn `${left} ${op} ANY (${right})`;\n\t}\n\n\tif (kind === 'AEXPR_OP_ALL') {\n\t\tconst left = node.lexpr ? deparse(node.lexpr) : '';\n\t\tconst right = node.rexpr ? deparse(node.rexpr) : '';\n\t\treturn `${left} ${op} ALL (${right})`;\n\t}\n\n\tif (kind === 'AEXPR_BETWEEN' || kind === 'AEXPR_NOT_BETWEEN') {\n\t\tconst left = node.lexpr ? deparse(node.lexpr) : '';\n\t\tconst listRec = node.rexpr as Record<string, unknown>;\n\t\tconst listInner = listRec.List as { items: Node[] } | undefined;\n\t\tconst items = listInner?.items ?? [];\n\t\tconst low = items[0] ? deparse(items[0]) : '';\n\t\tconst high = items[1] ? deparse(items[1]) : '';\n\t\tconst betweenOp = kind === 'AEXPR_BETWEEN' ? 'BETWEEN' : 'NOT BETWEEN';\n\t\treturn `${left} ${betweenOp} ${low} AND ${high}`;\n\t}\n\n\tif (kind === 'AEXPR_LIKE') {\n\t\tconst left = node.lexpr ? deparse(node.lexpr) : '';\n\t\tconst right = node.rexpr ? deparse(node.rexpr) : '';\n\t\tconst base =\n\t\t\top === '!~~' ? `${left} NOT LIKE ${right}` : `${left} LIKE ${right}`;\n\t\tconst escapeNode = (node as unknown as Record<string, unknown>).escape as\n\t\t\t| import('@pgsql/types').Node\n\t\t\t| undefined;\n\t\tif (escapeNode) {\n\t\t\treturn `${base} ESCAPE ${deparse(escapeNode)}`;\n\t\t}\n\t\treturn base;\n\t}\n\n\tif (kind === 'AEXPR_ILIKE') {\n\t\tconst left = node.lexpr ? deparse(node.lexpr) : '';\n\t\tconst right = node.rexpr ? deparse(node.rexpr) : '';\n\t\treturn op === '!~~*'\n\t\t\t? `${left} NOT ILIKE ${right}`\n\t\t\t: `${left} ILIKE ${right}`;\n\t}\n\n\tif (kind === 'AEXPR_IN') {\n\t\tconst left = node.lexpr ? deparse(node.lexpr) : '';\n\t\tconst right = node.rexpr ? deparse(node.rexpr) : '';\n\t\t// Wrap List in parentheses for proper IN (...) syntax\n\t\tconst rightWrapped =\n\t\t\tnode.rexpr && 'List' in node.rexpr ? `(${right})` : right;\n\t\treturn op === '<>'\n\t\t\t? `${left} NOT IN ${rightWrapped}`\n\t\t\t: `${left} IN ${rightWrapped}`;\n\t}\n\n\tif (kind === 'AEXPR_NULLIF') {\n\t\tconst left = node.lexpr ? deparse(node.lexpr) : '';\n\t\tconst right = node.rexpr ? deparse(node.rexpr) : '';\n\t\treturn `NULLIF(${left}, ${right})`;\n\t}\n\n\t// Fallback\n\tconst left = node.lexpr ? deparse(node.lexpr) : '';\n\tconst right = node.rexpr ? deparse(node.rexpr) : '';\n\tif (!left) return `${op} ${right}`;\n\treturn `${left} ${op} ${right}`;\n}\n\n// ---------------------------------------------------------------------------\n// BoolExpr\n// ---------------------------------------------------------------------------\n\nfunction deparseBoolExpr(node: BoolExpr): string {\n\tconst args = node.args ?? [];\n\n\tif (node.boolop === 'NOT_EXPR') {\n\t\tconst arg = args[0] ? deparse(args[0]) : '';\n\t\treturn `NOT (${arg})`;\n\t}\n\n\tconst sep = node.boolop === 'AND_EXPR' ? ' AND ' : ' OR ';\n\tconst parts = args.map((arg) => {\n\t\t// When building AND, wrap OR children in parens to enforce precedence.\n\t\t// Without this, \"A OR B AND C\" would be emitted instead of \"(A OR B) AND C\".\n\t\tif (\n\t\t\tnode.boolop === 'AND_EXPR' &&\n\t\t\t'BoolExpr' in arg &&\n\t\t\t(arg as { BoolExpr: { boolop: string } }).BoolExpr.boolop === 'OR_EXPR'\n\t\t) {\n\t\t\treturn `(${nodeToStr(arg)})`;\n\t\t}\n\t\treturn nodeToStr(arg);\n\t});\n\treturn parts.join(sep);\n}\n\n// ---------------------------------------------------------------------------\n// FuncCall\n// ---------------------------------------------------------------------------\n\nfunction deparseFuncCall(node: FuncCall): string {\n\tconst nameParts = (node.funcname ?? []).map((n) => {\n\t\tconst r = n as Record<string, unknown>;\n\t\tconst k = Object.keys(r)[0]!;\n\t\tif (k === 'String') {\n\t\t\treturn quoteIdent(String((r[k] as Record<string, unknown>).sval ?? ''));\n\t\t}\n\t\treturn deparse(n);\n\t});\n\tconst name = nameParts.join('.');\n\n\tconst overClause = node.over\n\t\t? ` OVER (${deparseWindowDef(node.over as WindowDef)})`\n\t\t: '';\n\n\tlet argStr: string;\n\tif (node.agg_star) {\n\t\targStr = '*';\n\t} else {\n\t\tconst args = node.args ?? [];\n\t\tconst distinct = node.agg_distinct ? 'DISTINCT ' : '';\n\t\tconst argParts = args.map(nodeToStr);\n\n\t\tlet orderByClause = '';\n\t\tif (node.agg_order && node.agg_order.length > 0) {\n\t\t\torderByClause = ` ORDER BY ${node.agg_order.map(nodeToStr).join(', ')}`;\n\t\t}\n\n\t\targStr = `${distinct}${argParts.join(', ')}${orderByClause}`;\n\t}\n\n\tlet filterClause = '';\n\tif (node.agg_filter) {\n\t\tfilterClause = ` FILTER (WHERE ${deparse(node.agg_filter)})`;\n\t}\n\n\treturn `${name}(${argStr})${filterClause}${overClause}`;\n}\n\n// ---------------------------------------------------------------------------\n// CoalesceExpr\n// ---------------------------------------------------------------------------\n\nfunction deparseCoalesceExpr(node: CoalesceExpr): string {\n\tconst args = (node.args ?? []).map(nodeToStr);\n\treturn `COALESCE(${args.join(', ')})`;\n}\n\nfunction deparseNullIfExpr(node: { args?: Node[] }): string {\n\tconst args = node.args ?? [];\n\tif (args.length !== 2) {\n\t\tthrow new Error(\n\t\t\t`NullIfExpr requires exactly 2 arguments, got ${args.length}`,\n\t\t);\n\t}\n\treturn `NULLIF(${deparse(args[0]!)}, ${deparse(args[1]!)})`;\n}\n\nfunction deparseMinMaxExpr(node: { op?: string; args?: Node[] }): string {\n\tconst args = (node.args ?? []).map(nodeToStr);\n\tconst fn = node.op === 'IS_GREATEST' ? 'GREATEST' : 'LEAST';\n\treturn `${fn}(${args.join(', ')})`;\n}\n\n// ---------------------------------------------------------------------------\n// CaseExpr / CaseWhen\n// ---------------------------------------------------------------------------\n\nfunction deparseCaseExpr(node: CaseExpr): string {\n\tconst parts: string[] = ['CASE'];\n\tif (node.arg) parts.push(deparse(node.arg));\n\tfor (const w of node.args ?? []) {\n\t\tparts.push(deparse(w));\n\t}\n\tif (node.defresult) parts.push(`ELSE ${deparse(node.defresult)}`);\n\tparts.push('END');\n\treturn parts.join(' ');\n}\n\nfunction deparseCaseWhen(node: CaseWhen): string {\n\tconst expr = node.expr ? deparse(node.expr) : '';\n\tconst result = node.result ? deparse(node.result) : '';\n\treturn `WHEN ${expr} THEN ${result}`;\n}\n\n// ---------------------------------------------------------------------------\n// TypeCast — always CAST(arg AS type) form\n// ---------------------------------------------------------------------------\n\nfunction deparseTypeCast(node: TypeCast): string {\n\tconst arg = node.arg ? deparse(node.arg) : '';\n\tconst typeName = node.typeName ? deparseTypeName(node.typeName) : '';\n\t// Use :: shorthand for A_Const (string/int/bool literals) — matches pgsql-deparser\n\tif (node.arg && 'A_Const' in (node.arg as Record<string, unknown>)) {\n\t\treturn `${arg}::${typeName}`;\n\t}\n\treturn `CAST(${arg} AS ${typeName})`;\n}\n\nfunction deparseTypeName(node: TypeName): string {\n\tconst names = (node.names ?? [])\n\t\t.map((n) => {\n\t\t\tconst r = n as Record<string, unknown>;\n\t\t\tconst k = Object.keys(r)[0]!;\n\t\t\tif (k === 'String') {\n\t\t\t\tconst sval = String((r[k] as Record<string, unknown>).sval ?? '');\n\t\t\t\tif (sval === 'pg_catalog') return null;\n\t\t\t\treturn sval;\n\t\t\t}\n\t\t\treturn deparse(n);\n\t\t})\n\t\t.filter((v): v is string => v !== null && v !== undefined);\n\n\tlet typeName = names.join('.');\n\n\tif (node.arrayBounds && node.arrayBounds.length > 0) {\n\t\ttypeName += '[]';\n\t}\n\n\treturn typeName;\n}\n\n// ---------------------------------------------------------------------------\n// NullTest\n// ---------------------------------------------------------------------------\n\nfunction deparseNullTest(node: NullTest): string {\n\tconst arg = node.arg ? deparse(node.arg) : '';\n\tif (node.nulltesttype === 'IS_NULL') {\n\t\treturn `${arg} IS NULL`;\n\t}\n\treturn `${arg} IS NOT NULL`;\n}\n\n// ---------------------------------------------------------------------------\n// SubLink\n// ---------------------------------------------------------------------------\n\nfunction deparseSubLink(node: SubLink): string {\n\tconst subquery = node.subselect ? deparse(node.subselect) : '';\n\n\tif (node.subLinkType === 'EXISTS_SUBLINK') {\n\t\treturn `EXISTS (${subquery})`;\n\t}\n\n\tif (node.subLinkType === 'ANY_SUBLINK') {\n\t\tif (node.testexpr && node.operName && node.operName.length > 0) {\n\t\t\tconst testExpr = deparse(node.testexpr);\n\t\t\tconst op = strNodeVal(node.operName[0]!);\n\t\t\treturn `${testExpr} ${op} ANY (${subquery})`;\n\t\t}\n\t\treturn `ANY (${subquery})`;\n\t}\n\n\tif (node.subLinkType === 'ALL_SUBLINK') {\n\t\tif (node.testexpr && node.operName && node.operName.length > 0) {\n\t\t\tconst testExpr = deparse(node.testexpr);\n\t\t\tconst op = strNodeVal(node.operName[0]!);\n\t\t\treturn `${testExpr} ${op} ALL (${subquery})`;\n\t\t}\n\t\treturn `ALL (${subquery})`;\n\t}\n\n\t// EXPR_SUBLINK — scalar subquery in expression context\n\treturn `(${subquery})`;\n}\n\n// ---------------------------------------------------------------------------\n// JoinExpr\n// ---------------------------------------------------------------------------\n\nconst JOIN_TYPE_MAP: Record<string, string> = {\n\tJOIN_INNER: 'JOIN',\n\tJOIN_LEFT: 'LEFT JOIN',\n\tJOIN_FULL: 'FULL JOIN',\n\tJOIN_RIGHT: 'RIGHT JOIN',\n\tJOIN_SEMI: 'SEMI JOIN',\n\tJOIN_ANTI: 'ANTI JOIN',\n};\n\nfunction deparseJoinExpr(node: JoinExpr): string {\n\tconst left = node.larg ? deparse(node.larg) : '';\n\tconst joinType = node.jointype\n\t\t? (JOIN_TYPE_MAP[node.jointype] ?? 'JOIN')\n\t\t: 'JOIN';\n\tconst right = node.rarg ? deparse(node.rarg) : '';\n\n\tlet result = `${left} ${joinType} ${right}`;\n\n\tif (node.quals) {\n\t\tresult += ` ON ${deparse(node.quals)}`;\n\t}\n\n\tif (node.alias) {\n\t\t// When a JoinExpr has an outer alias, wrap the whole join in parens\n\t\tresult = `(${result}) ${quoteIdent(node.alias.aliasname ?? '')}`;\n\t}\n\n\treturn result;\n}\n\n// ---------------------------------------------------------------------------\n// SortBy\n// ---------------------------------------------------------------------------\n\nfunction deparseSortBy(node: SortBy): string {\n\tlet result = node.node ? deparse(node.node) : '';\n\n\tif (node.sortby_dir === 'SORTBY_ASC') {\n\t\tresult += ' ASC';\n\t} else if (node.sortby_dir === 'SORTBY_DESC') {\n\t\tresult += ' DESC';\n\t}\n\n\tif (node.sortby_nulls === 'SORTBY_NULLS_FIRST') {\n\t\tresult += ' NULLS FIRST';\n\t} else if (node.sortby_nulls === 'SORTBY_NULLS_LAST') {\n\t\tresult += ' NULLS LAST';\n\t}\n\n\treturn result;\n}\n\n// ---------------------------------------------------------------------------\n// WindowDef\n// ---------------------------------------------------------------------------\n\n// PostgreSQL frameOptions bitmask constants (from parsenodes.h, PostgreSQL 17)\n// Only emit a frame clause when FRAMEOPTION_NONDEFAULT is set.\nconst FRAMEOPTION_NONDEFAULT = 0x00001;\nconst FRAMEOPTION_RANGE = 0x00002;\nconst FRAMEOPTION_ROWS = 0x00004;\nconst FRAMEOPTION_GROUPS = 0x00008;\nconst FRAMEOPTION_BETWEEN = 0x00010;\nconst FRAMEOPTION_START_UNBOUNDED_PRECEDING = 0x00020;\nconst FRAMEOPTION_END_UNBOUNDED_PRECEDING = 0x00040;\nconst FRAMEOPTION_START_UNBOUNDED_FOLLOWING = 0x00080;\nconst FRAMEOPTION_END_UNBOUNDED_FOLLOWING = 0x00100;\nconst FRAMEOPTION_START_CURRENT_ROW = 0x00200;\nconst FRAMEOPTION_END_CURRENT_ROW = 0x00400;\n\nfunction deparseFrameOptions(frameOptions: number): string {\n\t// Only emit a frame clause when the NONDEFAULT bit is set.\n\t// Implicit default frames (e.g. from row_number()) do not have this bit and\n\t// pgsql-deparser omits them — we do the same.\n\tif (!(frameOptions & FRAMEOPTION_NONDEFAULT)) {\n\t\treturn '';\n\t}\n\n\tconst parts: string[] = [];\n\n\tif (frameOptions & FRAMEOPTION_RANGE) {\n\t\tparts.push('RANGE');\n\t} else if (frameOptions & FRAMEOPTION_ROWS) {\n\t\tparts.push('ROWS');\n\t} else if (frameOptions & FRAMEOPTION_GROUPS) {\n\t\tparts.push('GROUPS');\n\t}\n\n\tif (frameOptions & FRAMEOPTION_BETWEEN) {\n\t\tparts.push('BETWEEN');\n\t}\n\n\tif (frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) {\n\t\tparts.push('UNBOUNDED PRECEDING');\n\t} else if (frameOptions & FRAMEOPTION_START_CURRENT_ROW) {\n\t\tparts.push('CURRENT ROW');\n\t} else if (frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) {\n\t\tparts.push('UNBOUNDED FOLLOWING');\n\t}\n\n\tif (frameOptions & FRAMEOPTION_BETWEEN) {\n\t\tparts.push('AND');\n\n\t\tif (frameOptions & FRAMEOPTION_END_CURRENT_ROW) {\n\t\t\tparts.push('CURRENT ROW');\n\t\t} else if (frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) {\n\t\t\tparts.push('UNBOUNDED FOLLOWING');\n\t\t} else if (frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING) {\n\t\t\tparts.push('UNBOUNDED PRECEDING');\n\t\t}\n\t}\n\n\treturn parts.join(' ');\n}\n\nfunction deparseWindowDef(node: WindowDef): string {\n\tconst parts: string[] = [];\n\n\tif (node.partitionClause && node.partitionClause.length > 0) {\n\t\tparts.push(\n\t\t\t`PARTITION BY ${node.partitionClause.map(nodeToStr).join(', ')}`,\n\t\t);\n\t}\n\n\tif (node.orderClause && node.orderClause.length > 0) {\n\t\tparts.push(`ORDER BY ${node.orderClause.map(nodeToStr).join(', ')}`);\n\t}\n\n\tif (node.frameOptions !== undefined && node.frameOptions !== 0) {\n\t\tconst frame = deparseFrameOptions(node.frameOptions);\n\t\tif (frame) parts.push(frame);\n\t}\n\n\treturn parts.join(' ');\n}\n\n// ---------------------------------------------------------------------------\n// CTEs\n// ---------------------------------------------------------------------------\n\nfunction deparseCommonTableExpr(node: CommonTableExpr): string {\n\tconst rec = node as unknown as Record<string, unknown>;\n\tconst cteName = String(rec.ctename ?? '');\n\tconst ctequery = rec.ctequery as Node | undefined;\n\tconst cteCols = rec.cte_cols as Node[] | undefined;\n\tconst cycleClause = rec.cycle_clause as CTECycleClause | undefined;\n\n\tlet result = `${quoteIdent(cteName)} AS `;\n\n\tif (cteCols && cteCols.length > 0) {\n\t\tconst cols = cteCols.map((c) => {\n\t\t\tconst r = c as Record<string, unknown>;\n\t\t\tconst k = Object.keys(r)[0]!;\n\t\t\tif (k === 'String') {\n\t\t\t\treturn quoteIdent(String((r[k] as Record<string, unknown>).sval ?? ''));\n\t\t\t}\n\t\t\treturn deparse(c);\n\t\t});\n\t\tresult = `${quoteIdent(cteName)}(${cols.join(', ')}) AS `;\n\t}\n\n\tresult += `(${ctequery ? deparse(ctequery) : ''})`;\n\n\tif (cycleClause) {\n\t\tresult += ` ${deparseCTECycleClause(cycleClause)}`;\n\t}\n\n\treturn result;\n}\n\nfunction deparseWithClause(node: WithClause): string {\n\tconst recursive = node.recursive ? 'WITH RECURSIVE ' : 'WITH ';\n\tconst ctes = (node.ctes ?? []).map(nodeToStr).join(', ');\n\treturn `${recursive}${ctes}`;\n}\n\nfunction deparseCTECycleClause(node: CTECycleClause): string {\n\tconst rec = node as unknown as Record<string, unknown>;\n\tconst colList = (rec.cycle_col_list ?? []) as Node[];\n\tconst markColumn = String(rec.cycle_mark_column ?? '');\n\tconst pathColumn = String(rec.cycle_path_column ?? '');\n\n\tconst cols = colList\n\t\t.map((c) => {\n\t\t\tconst r = c as Record<string, unknown>;\n\t\t\tconst k = Object.keys(r)[0]!;\n\t\t\tif (k === 'String') {\n\t\t\t\treturn quoteIdent(String((r[k] as Record<string, unknown>).sval ?? ''));\n\t\t\t}\n\t\t\treturn deparse(c);\n\t\t})\n\t\t.join(', ');\n\n\treturn `CYCLE ${cols} SET ${quoteIdent(markColumn)} USING ${quoteIdent(pathColumn)}`;\n}\n\n// ---------------------------------------------------------------------------\n// SelectStmt\n// ---------------------------------------------------------------------------\n\nfunction deparseSelectStmt(node: SelectStmt): string {\n\tconst rec = node as unknown as Record<string, unknown>;\n\tconst op = rec.op as string | undefined;\n\n\t// UNION / INTERSECT / EXCEPT\n\tif (op && op !== 'SETOP_NONE') {\n\t\tconst larg = rec.larg as SelectStmt | undefined;\n\t\tconst rarg = rec.rarg as SelectStmt | undefined;\n\t\tconst all = rec.all as boolean | undefined;\n\t\tconst left = larg ? deparseSelectStmt(larg) : '';\n\t\tconst right = rarg ? deparseSelectStmt(rarg) : '';\n\t\tlet setOp: string;\n\t\tswitch (op) {\n\t\t\tcase 'SETOP_UNION':\n\t\t\t\tsetOp = all ? 'UNION ALL' : 'UNION';\n\t\t\t\tbreak;\n\t\t\tcase 'SETOP_INTERSECT':\n\t\t\t\tsetOp = all ? 'INTERSECT ALL' : 'INTERSECT';\n\t\t\t\tbreak;\n\t\t\tcase 'SETOP_EXCEPT':\n\t\t\t\tsetOp = all ? 'EXCEPT ALL' : 'EXCEPT';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tsetOp = op;\n\t\t}\n\t\treturn `${left} ${setOp} ${right}`;\n\t}\n\n\t// VALUES clause\n\tconst valuesLists = rec.valuesLists as Node[] | undefined;\n\tif (valuesLists && valuesLists.length > 0) {\n\t\tconst rows = valuesLists.map((row) => {\n\t\t\tconst rowRec = row as Record<string, unknown>;\n\t\t\tconst items = (rowRec.List as { items: Node[] } | undefined)?.items ?? [];\n\t\t\treturn `(${items.map(nodeToStr).join(', ')})`;\n\t\t});\n\t\treturn `VALUES ${rows.join(', ')}`;\n\t}\n\n\tconst parts: string[] = [];\n\n\t// WITH clause\n\tconst withClause = rec.withClause as WithClause | undefined;\n\tif (withClause) {\n\t\tparts.push(deparseWithClause(withClause));\n\t}\n\n\t// SELECT [DISTINCT]\n\tconst distinctClause = rec.distinctClause as Node[] | undefined;\n\tlet selectKeyword = 'SELECT';\n\tif (distinctClause !== undefined) {\n\t\tif (Array.isArray(distinctClause) && distinctClause.length > 0) {\n\t\t\tconst cols = distinctClause.map(nodeToStr).join(', ');\n\t\t\tselectKeyword = `SELECT DISTINCT ON (${cols})`;\n\t\t} else {\n\t\t\tselectKeyword = 'SELECT DISTINCT';\n\t\t}\n\t}\n\tparts.push(selectKeyword);\n\n\t// Target list\n\tconst targetList = node.targetList ?? [];\n\tif (targetList.length > 0) {\n\t\tparts.push(targetList.map(nodeToStr).join(', '));\n\t}\n\n\t// FROM clause\n\tconst fromClause = node.fromClause ?? [];\n\tif (fromClause.length > 0) {\n\t\tparts.push(`FROM ${fromClause.map(nodeToStr).join(', ')}`);\n\t}\n\n\t// WHERE\n\tif (node.whereClause) {\n\t\tparts.push(`WHERE ${deparse(node.whereClause)}`);\n\t}\n\n\t// GROUP BY\n\tconst groupClause = node.groupClause ?? [];\n\tif (groupClause.length > 0) {\n\t\tparts.push(`GROUP BY ${groupClause.map(nodeToStr).join(', ')}`);\n\t}\n\n\t// HAVING\n\tif (node.havingClause) {\n\t\tparts.push(`HAVING ${deparse(node.havingClause)}`);\n\t}\n\n\t// ORDER BY\n\tconst sortClause = node.sortClause ?? [];\n\tif (sortClause.length > 0) {\n\t\tparts.push(`ORDER BY ${sortClause.map(nodeToStr).join(', ')}`);\n\t}\n\n\t// LIMIT\n\tif (node.limitCount) {\n\t\tparts.push(`LIMIT ${deparse(node.limitCount)}`);\n\t}\n\n\t// OFFSET\n\tif (node.limitOffset) {\n\t\tparts.push(`OFFSET ${deparse(node.limitOffset)}`);\n\t}\n\n\t// FOR UPDATE / SHARE locking clause\n\tconst lockingClause = node.lockingClause ?? [];\n\tfor (const lc of lockingClause) {\n\t\tparts.push(deparse(lc));\n\t}\n\n\treturn parts.join(' ');\n}\n\n// ---------------------------------------------------------------------------\n// InsertStmt\n// ---------------------------------------------------------------------------\n\nfunction deparseInsertStmt(node: InsertStmt): string {\n\tconst parts: string[] = ['INSERT INTO'];\n\n\tif (node.relation) {\n\t\tparts.push(deparseRangeVar(node.relation));\n\t}\n\n\tif (node.cols && node.cols.length > 0) {\n\t\tconst cols = node.cols.map((c) => {\n\t\t\tconst r = c as Record<string, unknown>;\n\t\t\t// Format 1: { ResTarget: { name: \"col\" } } (ast-helpers.ts)\n\t\t\tif ('ResTarget' in r) {\n\t\t\t\tconst rt = r.ResTarget as ResTarget | undefined;\n\t\t\t\treturn quoteIdent(rt?.name ?? '');\n\t\t\t}\n\t\t\t// Format 2: { String: { sval: \"col\" } } (upsert.ts)\n\t\t\tif ('String' in r) {\n\t\t\t\tconst s = r.String as Record<string, unknown> | undefined;\n\t\t\t\treturn quoteIdent(String(s?.sval ?? ''));\n\t\t\t}\n\t\t\treturn deparse(c);\n\t\t});\n\t\tparts.push(`(${cols.join(', ')})`);\n\t}\n\n\tif (node.override && node.override !== 'OVERRIDING_NOT_SET') {\n\t\tif (node.override === 'OVERRIDING_SYSTEM_VALUE') {\n\t\t\tparts.push('OVERRIDING SYSTEM VALUE');\n\t\t} else if (node.override === 'OVERRIDING_USER_VALUE') {\n\t\t\tparts.push('OVERRIDING USER VALUE');\n\t\t}\n\t}\n\n\tif (node.selectStmt) {\n\t\tparts.push(deparse(node.selectStmt));\n\t}\n\n\tif (node.onConflictClause) {\n\t\tparts.push(`ON CONFLICT ${deparseOnConflictClause(node.onConflictClause)}`);\n\t}\n\n\tconst returningList = node.returningList ?? [];\n\tif (returningList.length > 0) {\n\t\tparts.push(`RETURNING ${returningList.map(nodeToStr).join(', ')}`);\n\t}\n\n\treturn parts.join(' ');\n}\n\n// ---------------------------------------------------------------------------\n// UpdateStmt\n// ---------------------------------------------------------------------------\n\nfunction deparseUpdateStmt(node: UpdateStmt): string {\n\tconst parts: string[] = ['UPDATE'];\n\n\tif (node.relation) {\n\t\tparts.push(deparseRangeVar(node.relation));\n\t}\n\n\tconst setItems = (node.targetList ?? []).map((t) => {\n\t\tconst rt = (t as Record<string, unknown>).ResTarget as\n\t\t\t| ResTarget\n\t\t\t| undefined;\n\t\tconst name = rt?.name ?? '';\n\t\tconst val = rt?.val ? deparse(rt.val) : '';\n\t\treturn `${quoteIdent(name)} = ${val}`;\n\t});\n\tparts.push(`SET ${setItems.join(',')}`);\n\n\tconst fromClause = node.fromClause ?? [];\n\tif (fromClause.length > 0) {\n\t\tparts.push(`FROM ${fromClause.map(nodeToStr).join(', ')}`);\n\t}\n\n\tif (node.whereClause) {\n\t\tparts.push(`WHERE ${deparse(node.whereClause)}`);\n\t}\n\n\tconst returningList = node.returningList ?? [];\n\tif (returningList.length > 0) {\n\t\tparts.push(`RETURNING ${returningList.map(nodeToStr).join(', ')}`);\n\t}\n\n\treturn parts.join(' ');\n}\n\n// ---------------------------------------------------------------------------\n// DeleteStmt\n// ---------------------------------------------------------------------------\n\nfunction deparseDeleteStmt(node: DeleteStmt): string {\n\tconst parts: string[] = ['DELETE FROM'];\n\n\tif (node.relation) {\n\t\tparts.push(deparseRangeVar(node.relation));\n\t}\n\n\tconst usingClause = (node as unknown as Record<string, unknown>)\n\t\t.usingClause as Node[] | undefined;\n\tif (usingClause && usingClause.length > 0) {\n\t\tparts.push(`USING ${usingClause.map(nodeToStr).join(', ')}`);\n\t}\n\n\tif (node.whereClause) {\n\t\tparts.push(`WHERE ${deparse(node.whereClause)}`);\n\t}\n\n\tconst returningList = node.returningList ?? [];\n\tif (returningList.length > 0) {\n\t\tparts.push(`RETURNING ${returningList.map(nodeToStr).join(', ')}`);\n\t}\n\n\treturn parts.join(' ');\n}\n\n// ---------------------------------------------------------------------------\n// OnConflictClause\n// ---------------------------------------------------------------------------\n\nfunction deparseOnConflictClause(node: OnConflictClause): string {\n\tconst parts: string[] = [];\n\n\tif (node.infer) {\n\t\tparts.push(deparseInferClause(node.infer));\n\t}\n\n\tif (node.action === 'ONCONFLICT_NOTHING') {\n\t\tparts.push('DO NOTHING');\n\t} else if (node.action === 'ONCONFLICT_UPDATE') {\n\t\tconst setItems = (node.targetList ?? []).map((t) => {\n\t\t\tconst rt = (t as Record<string, unknown>).ResTarget as\n\t\t\t\t| ResTarget\n\t\t\t\t| undefined;\n\t\t\tconst name = rt?.name ?? '';\n\t\t\tconst val = rt?.val ? deparse(rt.val) : '';\n\t\t\treturn `${quoteIdent(name)} = ${val}`;\n\t\t});\n\t\tparts.push(`DO UPDATE SET ${setItems.join(', ')}`);\n\n\t\tif (node.whereClause) {\n\t\t\tparts.push(`WHERE ${deparse(node.whereClause)}`);\n\t\t}\n\t}\n\n\treturn parts.join(' ');\n}\n\n// ---------------------------------------------------------------------------\n// InferClause\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\nfunction deparseInferClause(node: InferClause): string {\n\tif (node.conname) {\n\t\treturn `ON CONSTRAINT ${quoteIdent(node.conname)}`;\n\t}\n\tconst indexElems = node.indexElems ?? [];\n\tlet result = '';\n\tif (indexElems.length > 0) {\n\t\tconst cols = indexElems.map((e) => {\n\t\t\tconst ie = (e as Record<string, unknown>).IndexElem as\n\t\t\t\t| IndexElem\n\t\t\t\t| undefined;\n\t\t\treturn ie ? deparseIndexElem(ie) : deparse(e);\n\t\t});\n\t\tresult = `(${cols.join(', ')})`;\n\t}\n\t// Partial-index predicate for ON CONFLICT: emit WHERE <expr> after the column list.\n\t// e.g. ON CONFLICT (col) WHERE active = true DO UPDATE ...\n\tif (node.whereClause) {\n\t\tconst where = deparse(node.whereClause as Node);\n\t\tresult = result ? `${result} WHERE ${where}` : `WHERE ${where}`;\n\t}\n\treturn result;\n}\n\n// ---------------------------------------------------------------------------\n// IndexElem\n// ---------------------------------------------------------------------------\n\nfunction deparseIndexElem(node: IndexElem): string {\n\tif (node.name) {\n\t\treturn quoteIdent(node.name);\n\t}\n\tif (node.expr) {\n\t\treturn deparse(node.expr);\n\t}\n\treturn '';\n}\n\n// ---------------------------------------------------------------------------\n// RangeFunction (e.g. unnest(...) [WITH ORDINALITY] AS alias(col1, col2))\n// ---------------------------------------------------------------------------\n\nfunction deparseRangeFunction(node: Record<string, unknown>): string {\n\tconst functions = (node.functions ?? []) as Node[];\n\tconst ordinality = node.ordinality as boolean | undefined;\n\tconst alias = node.alias as Record<string, unknown> | undefined;\n\n\t// Each element in `functions` is a List node with [funcCall, defList?]\n\tconst funcParts = functions.map((f) => {\n\t\tconst fRec = f as Record<string, unknown>;\n\t\tif ('List' in fRec) {\n\t\t\tconst items = (fRec.List as Record<string, unknown>).items as\n\t\t\t\t| Node[]\n\t\t\t\t| undefined;\n\t\t\t// First item is the function call, rest are def elements\n\t\t\tconst funcNode = items?.[0];\n\t\t\treturn funcNode ? deparse(funcNode) : '';\n\t\t}\n\t\treturn deparse(f);\n\t});\n\n\tlet result = funcParts.join(', ');\n\n\tif (ordinality) {\n\t\tresult += ' WITH ORDINALITY';\n\t}\n\n\tif (alias) {\n\t\tconst aliasname = String(alias.aliasname ?? '');\n\t\tresult += ` AS ${quoteIdent(aliasname)}`;\n\n\t\tconst colnames = (alias.colnames ?? []) as Node[];\n\t\tif (colnames.length > 0) {\n\t\t\tconst cols = colnames.map((c) => {\n\t\t\t\tconst cr = c as Record<string, unknown>;\n\t\t\t\tif ('String' in cr) {\n\t\t\t\t\treturn String((cr.String as Record<string, unknown>).sval ?? '');\n\t\t\t\t}\n\t\t\t\treturn deparse(c);\n\t\t\t});\n\t\t\tresult += `(${cols.join(', ')})`;\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// ---------------------------------------------------------------------------\n// RangeSubselect (e.g. LATERAL (SELECT ...) AS alias)\n// ---------------------------------------------------------------------------\n\nfunction deparseRangeSubselect(node: Record<string, unknown>): string {\n\tconst lateral = node.lateral as boolean | undefined;\n\tconst subquery = node.subquery as Node | undefined;\n\tconst alias = node.alias as Record<string, unknown> | undefined;\n\n\tconst prefix = lateral ? 'LATERAL ' : '';\n\tconst subStr = subquery ? deparse(subquery) : '';\n\tlet result = `${prefix}(${subStr})`;\n\n\tif (alias) {\n\t\tconst aliasname = String(alias.aliasname ?? '');\n\t\tresult += ` AS ${quoteIdent(aliasname)}`;\n\t}\n\n\treturn result;\n}\n\n// ---------------------------------------------------------------------------\n// LockingClause\n// ---------------------------------------------------------------------------\n\nconst LOCK_STRENGTH_MAP: Record<string, string> = {\n\tLCS_NONE: '',\n\tLCS_FORKEYSHARE: 'FOR KEY SHARE',\n\tLCS_FORSHARE: 'FOR SHARE',\n\tLCS_FORNOKEYUPDATE: 'FOR NO KEY UPDATE',\n\tLCS_FORUPDATE: 'FOR UPDATE',\n};\n\nconst WAIT_POLICY_MAP: Record<string, string> = {\n\tLockWaitBlock: '',\n\tLockWaitSkip: 'SKIP LOCKED',\n\tLockWaitError: 'NOWAIT',\n};\n\nfunction deparseLockingClause(node: LockingClause): string {\n\tconst parts: string[] = [];\n\n\tconst strength = node.strength\n\t\t? (LOCK_STRENGTH_MAP[node.strength] ?? '')\n\t\t: '';\n\tif (strength) parts.push(strength);\n\n\tconst lockedRels = node.lockedRels ?? [];\n\tif (lockedRels.length > 0) {\n\t\tconst tables = lockedRels.map(nodeToStr).join(', ');\n\t\tparts.push(`OF ${tables}`);\n\t}\n\n\tconst waitPolicy = node.waitPolicy\n\t\t? (WAIT_POLICY_MAP[node.waitPolicy] ?? '')\n\t\t: '';\n\tif (waitPolicy) parts.push(waitPolicy);\n\n\treturn parts.join(' ');\n}\n\n// ---------------------------------------------------------------------------\n// ExplainStmt\n// ---------------------------------------------------------------------------\n\nfunction deparseExplainStmt(node: ExplainStmt): string {\n\tconst parts: string[] = ['EXPLAIN'];\n\n\tconst opts = node.options ?? [];\n\tif (opts.length > 0) {\n\t\tconst optStr = opts.map(nodeToStr).join(', ');\n\t\tparts.push(`(${optStr})`);\n\t}\n\n\tif (node.query) {\n\t\tparts.push(deparse(node.query));\n\t}\n\n\treturn parts.join(' ');\n}\n\n// ---------------------------------------------------------------------------\n// DefElem (used in EXPLAIN options)\n// ---------------------------------------------------------------------------\n\nfunction deparseDefElem(node: DefElem): string {\n\tconst rec = node as unknown as Record<string, unknown>;\n\tconst defname = String(rec.defname ?? '');\n\tconst name = defname.toUpperCase();\n\tconst arg = rec.arg as Node | undefined;\n\n\tif (arg) {\n\t\tconst argRec = arg as Record<string, unknown>;\n\t\tconst argKey = Object.keys(argRec)[0]!;\n\t\tif (argKey === 'String') {\n\t\t\tconst sval = String(\n\t\t\t\t(argRec[argKey] as Record<string, unknown>).sval ?? '',\n\t\t\t);\n\t\t\treturn `${name} ${sval.toUpperCase()}`;\n\t\t}\n\t\treturn `${name} ${deparse(arg)}`;\n\t}\n\treturn name;\n}\n\n// ---------------------------------------------------------------------------\n// ClosePortalStmt\n// ---------------------------------------------------------------------------\n\nfunction deparseClosePortalStmt(node: ClosePortalStmt): string {\n\tconst rec = node as unknown as Record<string, unknown>;\n\tconst portalname = rec.portalname as string | undefined;\n\tif (portalname) {\n\t\treturn `CLOSE ${quoteIdent(portalname)}`;\n\t}\n\treturn 'CLOSE ALL';\n}\n\n// ---------------------------------------------------------------------------\n// List (used in BETWEEN rexpr etc.)\n// ---------------------------------------------------------------------------\n\nfunction deparseListNode(node: { items?: Node[] }): string {\n\treturn (node.items ?? []).map(nodeToStr).join(', ');\n}\n\n// ---------------------------------------------------------------------------\n// A_ArrayExpr (ARRAY[...])\n// ---------------------------------------------------------------------------\n\nfunction deparseArrayExpr(node: A_ArrayExpr): string {\n\tconst elements = (node.elements ?? []).map(nodeToStr);\n\treturn `ARRAY[${elements.join(', ')}]`;\n}\n\n// ---------------------------------------------------------------------------\n// DeclareCursorStmt\n// ---------------------------------------------------------------------------\n\nfunction deparseDeclareCursorStmt(node: DeclareCursorStmt): string {\n\tconst rec = node as unknown as Record<string, unknown>;\n\tconst portalname = String(rec.portalname ?? '');\n\tconst query = rec.query as Node | undefined;\n\tconst opts = (rec.options as number | undefined) ?? 0;\n\n\tconst parts: string[] = ['DECLARE', quoteIdent(portalname)];\n\n\tif (opts & 0x0001) parts.push('BINARY');\n\tif (opts & 0x0002) parts.push('SCROLL');\n\tif (opts & 0x0004) parts.push('NO SCROLL');\n\n\tparts.push('CURSOR');\n\n\tif (opts & 0x0010) parts.push('WITH HOLD');\n\n\tparts.push('FOR');\n\tif (query) parts.push(deparse(query));\n\n\treturn parts.join(' ');\n}\n\n// ---------------------------------------------------------------------------\n// FetchStmt\n// ---------------------------------------------------------------------------\n\nconst FETCH_DIR_MAP: Record<string, string> = {\n\tFETCH_FORWARD: 'FORWARD',\n\tFETCH_BACKWARD: 'BACKWARD',\n\tFETCH_ABSOLUTE: 'ABSOLUTE',\n\tFETCH_RELATIVE: 'RELATIVE',\n};\n\nfunction deparseFetchStmt(node: FetchStmt): string {\n\tconst rec = node as unknown as Record<string, unknown>;\n\tconst direction = String(rec.direction ?? '');\n\tconst howMany = rec.howMany;\n\tconst portalname = String(rec.portalname ?? '');\n\n\t// PostgreSQL uses LONG_MAX (9223372036854775807) as a sentinel for \"ALL\".\n\t// The pgsql-deparser library stores this as the float64 approximation 9223372036854776000.\n\t// Mirror the same sentinel check so the internal deparser matches the external one.\n\tconst isAll = howMany === 9223372036854776000;\n\n\tconst parts: string[] = ['FETCH'];\n\tconst dir = FETCH_DIR_MAP[direction] ?? direction;\n\n\tswitch (direction) {\n\t\tcase 'FETCH_FORWARD':\n\t\t\tif (isAll) {\n\t\t\t\tparts.push('FORWARD', 'ALL');\n\t\t\t} else if (howMany !== undefined && howMany !== null) {\n\t\t\t\tparts.push(`${dir} ${String(howMany)}`);\n\t\t\t} else {\n\t\t\t\tparts.push(dir);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 'FETCH_BACKWARD':\n\t\t\tif (isAll) {\n\t\t\t\tparts.push('BACKWARD', 'ALL');\n\t\t\t} else if (howMany !== undefined && howMany !== null) {\n\t\t\t\tparts.push(`${dir} ${String(howMany)}`);\n\t\t\t} else {\n\t\t\t\tparts.push(dir);\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tif (howMany !== undefined && howMany !== null) {\n\t\t\t\tparts.push(`${dir} ${String(howMany)}`);\n\t\t\t} else {\n\t\t\t\tparts.push(dir);\n\t\t\t}\n\t}\n\n\tparts.push(`FROM ${quoteIdent(portalname)}`);\n\n\treturn parts.join(' ');\n}\n","/**\n * Deparse AST to SQL string.\n * Uses the internal deparser for production; pgsql-deparser stays in devDeps\n * for comparison tests only.\n */\nimport type { Node } from '@pgsql/types';\nimport { deparse } from './pgsql-deparser.js';\n\nexport function deparseQuoted(ast: Node): string {\n\treturn deparse(ast);\n}\n","/**\n * Intent to Decisions Converter\n *\n * Converts core's QueryIntent into Decision[] format for the pgsql compiler.\n * This bridges the gap between the planner output and SQL compilation.\n */\n\nimport type {\n\tOrderByIntent,\n\tQueryIntent,\n\tSelectIntent,\n\tWhereIntent,\n} from '@dbsp/types';\nimport { isSubqueryRef } from '@dbsp/types';\nimport type { Mutable } from '@dbsp/types/internal';\nimport type { PlanDecision } from './compiler.js';\nimport type { RangeValue } from './handlers/types.js';\nimport { EXPRESSION_HANDLERS } from './select-expression-handlers.js';\n\n// ============================================================================\n// Main Converter\n// ============================================================================\n\n/**\n * Convert a QueryIntent into Decision[] for the pgsql compiler.\n *\n * @param intent - The QueryIntent from core's planner\n * @param rootTable - The root table name (from plan.rootTable)\n * @returns Array of decisions the compiler can process\n */\nexport function intentToDecisions(\n\tintent: QueryIntent,\n\trootTable: string,\n): PlanDecision[] {\n\tconst decisions: PlanDecision[] = [];\n\n\t// 1. SELECT clause\n\tif (intent.select) {\n\t\tdecisions.push(...convertSelect(intent.select, rootTable));\n\t} else {\n\t\t// Default to SELECT *\n\t\tdecisions.push({ type: 'select', column: '*', table: rootTable });\n\t}\n\n\t// 2. WHERE clause\n\tif (intent.where) {\n\t\tdecisions.push(...convertWhere(intent.where, rootTable));\n\t}\n\n\t// 3. ORDER BY clause\n\tif (intent.orderBy && intent.orderBy.length > 0) {\n\t\tfor (const order of intent.orderBy) {\n\t\t\tdecisions.push(convertOrderBy(order, rootTable));\n\t\t}\n\t}\n\n\t// 4. GROUP BY clause\n\tif (intent.groupBy && intent.groupBy.length > 0) {\n\t\tfor (const col of intent.groupBy) {\n\t\t\tdecisions.push({ type: 'groupBy', column: col, table: rootTable });\n\t\t}\n\t}\n\n\t// 5. HAVING clause\n\tif (intent.having) {\n\t\tconst havingDecisions = convertWhere(intent.having, rootTable);\n\t\tfor (const d of havingDecisions) {\n\t\t\tdecisions.push({ ...d, type: 'having' });\n\t\t}\n\t}\n\n\t// 6. DISTINCT / DISTINCT ON\n\tif (intent.distinctOn && intent.distinctOn.length > 0) {\n\t\tdecisions.push({ type: 'distinctOn', columns: intent.distinctOn });\n\t} else if (intent.distinct) {\n\t\tdecisions.push({ type: 'distinct' });\n\t}\n\n\t// 7. LIMIT\n\tif (intent.limit !== undefined) {\n\t\tdecisions.push({ type: 'limit', limit: intent.limit });\n\t}\n\n\t// 8. OFFSET\n\tif (intent.offset !== undefined) {\n\t\tdecisions.push({ type: 'offset', offset: intent.offset });\n\t}\n\n\treturn decisions;\n}\n\n// ============================================================================\n// SELECT Conversion\n// ============================================================================\n\n/**\n * Apply a filter condition to a decision if a filter intent is present.\n */\nfunction applyFilterCondition(\n\tdecision: Mutable<PlanDecision>,\n\tfilter: WhereIntent | undefined,\n\trootTable: string,\n): void {\n\tif (filter) {\n\t\tconst filterDecision = convertWhereCondition(filter, rootTable);\n\t\tif (filterDecision) decision.filterCondition = filterDecision;\n\t}\n}\n\nfunction convertSelect(\n\tselect: SelectIntent,\n\trootTable: string,\n): PlanDecision[] {\n\t// Handle different SelectIntent types using discriminator\n\tconst selectType = 'type' in select ? select.type : undefined;\n\n\t// SelectAllIntent: { all: true }\n\tif ('all' in select && select.all === true) {\n\t\treturn [{ type: 'select', column: '*', table: rootTable }];\n\t}\n\n\t// SelectFieldsIntent: { type: 'fields', fields: string[] }\n\tif (selectType === 'fields' && 'fields' in select) {\n\t\treturn (select.fields as readonly string[]).map((field) => ({\n\t\t\ttype: 'select' as const,\n\t\t\tcolumn: field,\n\t\t\ttable: rootTable,\n\t\t}));\n\t}\n\n\t// SelectWithExpressionsIntent: { type: 'expressions', columns: ExpressionIntent[] }\n\tif (selectType === 'expressions' && 'columns' in select) {\n\t\tconst decisions: PlanDecision[] = [];\n\t\tconst columns = select.columns as readonly unknown[];\n\n\t\tfor (const exprUnknown of columns) {\n\t\t\tconst expr = exprUnknown as Record<string, unknown>;\n\t\t\tconst handler = EXPRESSION_HANDLERS[expr.kind as string];\n\t\t\tif (handler) {\n\t\t\t\thandler(\n\t\t\t\t\texpr,\n\t\t\t\t\trootTable,\n\t\t\t\t\tdecisions,\n\t\t\t\t\tapplyFilterCondition,\n\t\t\t\t\tconvertWhereCondition,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// else: unknown kind (e.g., pseudoColumn) — intentional no-op\n\t\t}\n\n\t\treturn decisions;\n\t}\n\n\tif ('aggregates' in select) {\n\t\t// SelectAggregateIntent\n\t\tconst decisions: PlanDecision[] = [];\n\n\t\t// Add non-aggregate fields\n\t\tif (select.fields) {\n\t\t\tfor (const field of select.fields) {\n\t\t\t\tdecisions.push({ type: 'select', column: field, table: rootTable });\n\t\t\t}\n\t\t}\n\n\t\t// Add aggregates\n\t\tfor (const agg of select.aggregates) {\n\t\t\tconst aggDecision: Mutable<PlanDecision> = {\n\t\t\t\ttype: 'selectFunction',\n\t\t\t\tfunction:\n\t\t\t\t\tagg.function === 'count' && agg.field === '*'\n\t\t\t\t\t\t? 'count'\n\t\t\t\t\t\t: agg.function,\n\t\t\t\tcolumn: agg.field ?? '*',\n\t\t\t\ttable: rootTable,\n\t\t\t};\n\t\t\tif (agg.as) {\n\t\t\t\taggDecision.alias = agg.as;\n\t\t\t}\n\t\t\tapplyFilterCondition(aggDecision, agg.filter, rootTable);\n\t\t\tdecisions.push(aggDecision);\n\t\t}\n\n\t\treturn decisions;\n\t}\n\n\t// Default: SELECT *\n\treturn [{ type: 'select', column: '*', table: rootTable }];\n}\n\n// ============================================================================\n// WHERE Conversion\n// ============================================================================\n\n/**\n * Convert a WhereIntent (kind-discriminated union) into PlanDecisions.\n * WhereIntent uses 'kind' as the discriminator field.\n */\nfunction convertWhere(where: WhereIntent, rootTable: string): PlanDecision[] {\n\tconst decision = convertWhereCondition(where, rootTable);\n\treturn decision ? [decision] : [];\n}\n\n/**\n * Convert a single WhereIntent condition to a PlanDecision.\n * Handles the kind-based discriminated union.\n */\n/**\n * Flat view of all possible WhereIntent properties.\n * WhereIntent is a discriminated union — each variant contributes a subset.\n * This interface avoids double casts by exposing every variant's fields as optional.\n */\ninterface FlatWhereFields {\n\treadonly kind: string;\n\treadonly field?: string;\n\treadonly operator?: string;\n\treadonly value?: unknown;\n\treadonly values?: readonly unknown[];\n\treadonly pattern?: string;\n\treadonly caseInsensitive?: boolean;\n\treadonly not?: boolean;\n\treadonly conditions?: readonly WhereIntent[];\n\treadonly condition?: WhereIntent;\n\treadonly relation?: string;\n\treadonly where?: WhereIntent;\n\treadonly mode?: string;\n\treadonly subquery?: QueryIntent;\n\t// Legacy numeric range bounds (not on WhereRangeIntent but produced by NQL)\n\treadonly gte?: unknown;\n\treadonly lte?: unknown;\n\treadonly gt?: unknown;\n\treadonly lt?: unknown;\n\t// JSON-related fields\n\treadonly jsonPath?: readonly string[];\n\treadonly jsonMode?: string;\n\treadonly reversed?: boolean;\n\treadonly key?: string;\n\t// LIKE escape character\n\treadonly escape?: string;\n\t// Custom expression WHERE (kind: 'expression')\n\treadonly expr?: unknown;\n}\n\n// ============================================================================\n// Where condition handlers — one per WhereIntent.kind\n// ============================================================================\n\n/**\n * Recursively walk a WhereIntent looking for a SubqueryRefIntent\n * (`{ kind: 'ref', column }` produced by `outerRef()`). Used to detect\n * correlated subqueries inside rawExists/rawNotExists, which the current\n * pipeline does not support — we throw rather than emit broken SQL.\n */\nfunction containsOuterRef(where: unknown): boolean {\n\tif (!where || typeof where !== 'object') return false;\n\tconst w = where as Record<string, unknown>;\n\tif (isSubqueryRef(w)) return true;\n\tfor (const value of Object.values(w)) {\n\t\tif (Array.isArray(value)) {\n\t\t\tfor (const item of value) {\n\t\t\t\tif (containsOuterRef(item)) return true;\n\t\t\t}\n\t\t} else if (typeof value === 'object' && value !== null) {\n\t\t\tif (containsOuterRef(value)) return true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/** Handle kind: 'comparison' — field OP value */\nfunction convertComparison(\n\tcond: FlatWhereFields,\n\trootTable: string,\n): PlanDecision {\n\tconst rawValue = cond.value;\n\t// Convert SubqueryRefIntent { kind: 'ref', column } to FieldRef so that\n\t// compileValueOrFieldRef() treats it as a column reference, not a parameter.\n\tconst resolvedValue = isSubqueryRef(rawValue)\n\t\t? {\n\t\t\t\tkind: 'fieldRef' as const,\n\t\t\t\tscope: 'outer' as const,\n\t\t\t\tcolumn: (rawValue as { column: string }).column,\n\t\t\t}\n\t\t: rawValue;\n\tconst result: Mutable<PlanDecision> = {\n\t\ttype: 'where',\n\t\tcolumn: cond.field as string,\n\t\toperator: cond.operator as string,\n\t\tvalue: resolvedValue,\n\t\ttable: rootTable,\n\t};\n\tif (cond.jsonPath) result.jsonPath = cond.jsonPath;\n\tif (cond.jsonMode) result.jsonMode = cond.jsonMode as 'json' | 'text';\n\treturn result;\n}\n\n/** Handle kind: 'like' — field LIKE/ILIKE pattern */\nfunction convertLike(cond: FlatWhereFields, rootTable: string): PlanDecision {\n\tconst result: Mutable<PlanDecision> = {\n\t\ttype: 'where',\n\t\tcolumn: cond.field as string,\n\t\toperator: cond.caseInsensitive ? 'ilike' : 'like',\n\t\tvalue: cond.pattern,\n\t\ttable: rootTable,\n\t};\n\tif (cond.escape !== undefined) result.escape = cond.escape;\n\treturn result;\n}\n\n/** Handle kind: 'in' — field IN (values) or field IN (subquery) */\nfunction convertIn(cond: FlatWhereFields, rootTable: string): PlanDecision {\n\tconst rawSubquery = cond.subquery;\n\n\t// When a subquery is present, build the inSubquery Decision shape directly.\n\t// We cannot rely on normalizeToDecision's `case 'in'` branch because that\n\t// function short-circuits via early-return when `column` is already set.\n\tif (rawSubquery) {\n\t\tconst selectField = rawSubquery.select;\n\t\tconst selectColumn: string =\n\t\t\tselectField &&\n\t\t\t'fields' in selectField &&\n\t\t\tArray.isArray(selectField.fields)\n\t\t\t\t? (selectField.fields[0] ?? '*')\n\t\t\t\t: '*';\n\t\tconst subConditions = rawSubquery.where\n\t\t\t? (() => {\n\t\t\t\t\tconst converted = convertWhereCondition(\n\t\t\t\t\t\trawSubquery.where!,\n\t\t\t\t\t\trawSubquery.from,\n\t\t\t\t\t);\n\t\t\t\t\treturn converted ? [converted] : [];\n\t\t\t\t})()\n\t\t\t: [];\n\t\t// Propagate limit and orderBy from QueryIntent (e.g. from NQL `| limit N | order by col`)\n\t\tconst rawLimit = rawSubquery.limit;\n\t\tconst rawOrderBy = rawSubquery.orderBy as\n\t\t\t| readonly { field: string; direction?: string }[]\n\t\t\t| undefined;\n\t\treturn {\n\t\t\ttype: 'where',\n\t\t\tcolumn: cond.field as string,\n\t\t\toperator: cond.not ? 'notInSubquery' : 'inSubquery',\n\t\t\ttargetTable: rawSubquery.from,\n\t\t\tselectColumn,\n\t\t\tconditions: subConditions,\n\t\t\ttable: rootTable,\n\t\t\t...(rawLimit != null && { limit: rawLimit }),\n\t\t\t...(rawOrderBy && {\n\t\t\t\torderBy: rawOrderBy.map((o) => ({\n\t\t\t\t\tcolumn: o.field,\n\t\t\t\t\tdirection: (o.direction?.toUpperCase() ?? 'ASC') as 'ASC' | 'DESC',\n\t\t\t\t})),\n\t\t\t}),\n\t\t} as unknown as PlanDecision;\n\t}\n\n\treturn {\n\t\ttype: 'where',\n\t\tcolumn: cond.field as string,\n\t\toperator: cond.not ? 'notIn' : 'in',\n\t\tvalue: cond.values,\n\t\ttable: rootTable,\n\t};\n}\n\n/** Handle kind: 'null' — IS NULL / IS NOT NULL */\nfunction convertNull(cond: FlatWhereFields, rootTable: string): PlanDecision {\n\treturn {\n\t\ttype: 'where',\n\t\tcolumn: cond.field as string,\n\t\toperator: cond.operator as string,\n\t\ttable: rootTable,\n\t};\n}\n\n/** Handle kind: 'range' — BETWEEN, gte/lte/gt/lt, or PG range operators (@>, <@, &&) */\nfunction convertRange(\n\tcond: FlatWhereFields,\n\trootTable: string,\n): PlanDecision | null {\n\tconst rangeOperator = cond.operator as string | undefined;\n\tconst col = cond.field as string;\n\n\t// PostgreSQL range type operators: @>, <@, &&\n\tif (\n\t\trangeOperator === 'contains' ||\n\t\trangeOperator === 'containedBy' ||\n\t\trangeOperator === 'overlaps'\n\t) {\n\t\treturn {\n\t\t\ttype: 'where',\n\t\t\tcolumn: col,\n\t\t\toperator: rangeOperator,\n\t\t\tvalue: cond.value,\n\t\t\ttable: rootTable,\n\t\t};\n\t}\n\n\t// NQL BETWEEN: { operator: 'between', value: { lower, upper } }\n\tif (rangeOperator === 'between') {\n\t\tconst rangeVal = cond.value as RangeValue;\n\t\treturn {\n\t\t\ttype: 'where',\n\t\t\tcolumn: col,\n\t\t\toperator: 'between',\n\t\t\tvalue: [rangeVal.lower, rangeVal.upper],\n\t\t\ttable: rootTable,\n\t\t};\n\t}\n\n\t// Numeric bounds — convert to BETWEEN or single-side comparison\n\tif (cond.gte !== undefined && cond.lte !== undefined) {\n\t\treturn {\n\t\t\ttype: 'where',\n\t\t\tcolumn: col,\n\t\t\toperator: 'between',\n\t\t\tvalue: [cond.gte, cond.lte],\n\t\t\ttable: rootTable,\n\t\t};\n\t}\n\tif (cond.gte !== undefined) {\n\t\treturn {\n\t\t\ttype: 'where',\n\t\t\tcolumn: col,\n\t\t\toperator: 'gte',\n\t\t\tvalue: cond.gte,\n\t\t\ttable: rootTable,\n\t\t};\n\t}\n\tif (cond.gt !== undefined) {\n\t\treturn {\n\t\t\ttype: 'where',\n\t\t\tcolumn: col,\n\t\t\toperator: 'gt',\n\t\t\tvalue: cond.gt,\n\t\t\ttable: rootTable,\n\t\t};\n\t}\n\tif (cond.lte !== undefined) {\n\t\treturn {\n\t\t\ttype: 'where',\n\t\t\tcolumn: col,\n\t\t\toperator: 'lte',\n\t\t\tvalue: cond.lte,\n\t\t\ttable: rootTable,\n\t\t};\n\t}\n\tif (cond.lt !== undefined) {\n\t\treturn {\n\t\t\ttype: 'where',\n\t\t\tcolumn: col,\n\t\t\toperator: 'lt',\n\t\t\tvalue: cond.lt,\n\t\t\ttable: rootTable,\n\t\t};\n\t}\n\treturn null;\n}\n\n/** Handle kind: 'and' | 'or' — logical group of sub-conditions */\nfunction convertLogicalGroup(\n\tcond: FlatWhereFields,\n\trootTable: string,\n\tdecisionType: 'whereAnd' | 'whereOr',\n): PlanDecision | null {\n\tconst subDecisions: PlanDecision[] = [];\n\tfor (const sub of cond.conditions as WhereIntent[]) {\n\t\tconst subDecision = convertWhereCondition(sub, rootTable);\n\t\tif (subDecision) subDecisions.push(subDecision);\n\t}\n\tif (subDecisions.length === 0) return null;\n\treturn { type: decisionType, conditions: subDecisions };\n}\n\n/** Handle kind: 'not' — NOT (condition) */\nfunction convertNot(\n\tcond: FlatWhereFields,\n\trootTable: string,\n): PlanDecision | null {\n\tconst subDecision = convertWhereCondition(\n\t\tcond.condition as WhereIntent,\n\t\trootTable,\n\t);\n\tif (!subDecision) return null;\n\treturn { type: 'whereNot', conditions: [subDecision] };\n}\n\n/** Handle kind: 'exists' | 'notExists' | 'relationFilter' — correlated EXISTS / NOT EXISTS */\nfunction convertExistsLike(\n\tcond: FlatWhereFields,\n\toperator: 'exists' | 'notExists',\n): PlanDecision {\n\tconst targetTable = cond.relation as string;\n\tconst subDecisions: PlanDecision[] = cond.where\n\t\t? convertWhere(cond.where as WhereIntent, targetTable)\n\t\t: [];\n\tconst base: PlanDecision = { type: 'where', operator, targetTable };\n\treturn subDecisions.length > 0 ? { ...base, conditions: subDecisions } : base;\n}\n\n/** Handle kind: 'subquery' — field OP (SELECT col FROM table WHERE ...) */\nfunction convertSubquery(cond: FlatWhereFields): PlanDecision | null {\n\tconst field = cond.field as string;\n\tconst operator = cond.operator as string;\n\tconst subquery = cond.subquery as QueryIntent | undefined;\n\tif (!subquery || !field) return null;\n\n\tconst targetTable = subquery.from;\n\tlet selectColumn = '*';\n\tlet aggregate: string | undefined;\n\n\tconst select = subquery.select as SelectIntent | undefined;\n\tif (select) {\n\t\tif ('type' in select && select.type === 'aggregate') {\n\t\t\tconst agg = select.aggregates?.[0];\n\t\t\tif (agg) {\n\t\t\t\taggregate = agg.function;\n\t\t\t\tselectColumn = agg.field ?? '*';\n\t\t\t}\n\t\t} else if ('fields' in select && select.fields?.length) {\n\t\t\tselectColumn = select.fields[0]!;\n\t\t}\n\t}\n\n\tconst subConditions: PlanDecision[] = [];\n\tif (subquery.where) {\n\t\tconst innerWhere = convertWhereCondition(\n\t\t\tsubquery.where as WhereIntent,\n\t\t\ttargetTable,\n\t\t);\n\t\tif (innerWhere) subConditions.push(innerWhere);\n\t}\n\n\tconst opMap: Record<string, string> = {\n\t\teq: '=',\n\t\tneq: '!=',\n\t\tgt: '>',\n\t\tgte: '>=',\n\t\tlt: '<',\n\t\tlte: '<=',\n\t};\n\treturn {\n\t\ttype: 'where',\n\t\tcolumn: field,\n\t\toperator: 'scalarSubquery',\n\t\ttargetTable,\n\t\tselectColumn,\n\t\tsubqueryOperator: opMap[operator] ?? '=',\n\t\t...(aggregate && { aggregate }),\n\t\t...(subConditions.length > 0 && { conditions: subConditions }),\n\t};\n}\n\n// ============================================================================\n// Main dispatcher — routes each WhereIntent.kind to its dedicated handler\n// ============================================================================\n\nexport function convertWhereCondition(\n\tcondition: WhereIntent,\n\trootTable: string,\n): PlanDecision | null {\n\tconst cond = condition as FlatWhereFields;\n\n\tswitch (cond.kind) {\n\t\tcase 'comparison':\n\t\t\treturn convertComparison(cond, rootTable);\n\t\tcase 'like':\n\t\t\treturn convertLike(cond, rootTable);\n\t\tcase 'in':\n\t\t\treturn convertIn(cond, rootTable);\n\t\tcase 'null':\n\t\t\treturn convertNull(cond, rootTable);\n\t\tcase 'range':\n\t\t\treturn convertRange(cond, rootTable);\n\t\tcase 'and':\n\t\t\treturn convertLogicalGroup(cond, rootTable, 'whereAnd');\n\t\tcase 'or':\n\t\t\treturn convertLogicalGroup(cond, rootTable, 'whereOr');\n\t\tcase 'not':\n\t\t\treturn convertNot(cond, rootTable);\n\t\tcase 'exists':\n\t\t\treturn convertExistsLike(cond, 'exists');\n\t\tcase 'notExists':\n\t\t\treturn convertExistsLike(cond, 'notExists');\n\t\tcase 'relationFilter': {\n\t\t\tconst mode = (cond.mode as string) || 'some';\n\t\t\treturn convertExistsLike(cond, mode === 'none' ? 'notExists' : 'exists');\n\t\t}\n\t\tcase 'subquery':\n\t\t\treturn convertSubquery(cond);\n\t\tcase 'rawExists':\n\t\tcase 'rawNotExists': {\n\t\t\tconst sub = (cond as unknown as { subquery: QueryIntent | undefined })\n\t\t\t\t.subquery;\n\t\t\tif (!sub) {\n\t\t\t\t// Defensive: malformed intent (rawExists called without a subquery).\n\t\t\t\t// Returning null causes the WHERE filter to be dropped — same as any\n\t\t\t\t// other unrecognized kind. Better to fail loudly so the bug surfaces.\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`${cond.kind}: missing subquery — pass the result of subquery(table).select(...) or a builder with buildIntent()`,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Correlated subqueries (outerRef inside the inner WHERE) are NOT yet\n\t\t\t// supported on the rawExists/rawNotExists path: buildSubqueryFromIntent\n\t\t\t// builds a fresh WhereCompilerCtx with no outerAlias, so SubqueryRefIntent\n\t\t\t// values fall back to being parameterized as $N (an object literal!) which\n\t\t\t// produces wrong SQL at best and a runtime error at worst. Detect this\n\t\t\t// case at decision-time and throw a clear \"not yet supported\" error so\n\t\t\t// callers don't get silently-broken queries.\n\t\t\tif (sub.where && containsOuterRef(sub.where)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`${cond.kind}: correlated subqueries (outerRef inside the inner WHERE) are not yet supported. ` +\n\t\t\t\t\t\t'Workaround: use exists(\"relation\", { where: ... }) when a schema relation exists, or wait for the rawExists correlation pipeline (tracked in TODO).',\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\ttype: 'where',\n\t\t\t\toperator: cond.kind,\n\t\t\t\t// Reuse expressionIntent (already present on PlanDecision) to carry the\n\t\t\t\t// inner QueryIntent; the rawExistsHandler discriminates by operator name.\n\t\t\t\texpressionIntent: sub,\n\t\t\t\ttable: rootTable,\n\t\t\t};\n\t\t}\n\t\tcase 'jsonContains':\n\t\t\treturn {\n\t\t\t\ttype: 'where',\n\t\t\t\tcolumn: cond.field as string,\n\t\t\t\toperator: cond.reversed ? 'jsonContainedBy' : 'jsonContains',\n\t\t\t\tvalue: cond.value,\n\t\t\t\ttable: rootTable,\n\t\t\t};\n\t\tcase 'any':\n\t\t\treturn {\n\t\t\t\ttype: 'where',\n\t\t\t\tcolumn: cond.field as string,\n\t\t\t\toperator: 'any',\n\t\t\t\tvalues: cond.values as readonly unknown[],\n\t\t\t\ttable: rootTable,\n\t\t\t};\n\t\tcase 'jsonExists':\n\t\t\treturn {\n\t\t\t\ttype: 'where',\n\t\t\t\tcolumn: cond.field as string,\n\t\t\t\toperator: 'jsonExists',\n\t\t\t\tvalue: cond.key,\n\t\t\t\ttable: rootTable,\n\t\t\t};\n\t\tcase 'expression':\n\t\t\treturn {\n\t\t\t\ttype: 'where',\n\t\t\t\toperator: 'expression',\n\t\t\t\texpressionIntent: cond.expr,\n\t\t\t\tvalue: cond.value,\n\t\t\t\tsubqueryOperator: cond.operator as string,\n\t\t\t\ttable: rootTable,\n\t\t\t};\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\n// ============================================================================\n// ORDER BY Conversion\n// ============================================================================\n\nfunction convertOrderBy(order: OrderByIntent, rootTable: string): PlanDecision {\n\t// Convert lowercase direction to uppercase\n\tconst direction: 'ASC' | 'DESC' = order.direction === 'desc' ? 'DESC' : 'ASC';\n\n\t// Convert lowercase nulls to uppercase if present\n\tconst nulls: 'FIRST' | 'LAST' | undefined = order.nulls\n\t\t? order.nulls === 'first'\n\t\t\t? 'FIRST'\n\t\t\t: 'LAST'\n\t\t: undefined;\n\n\t// Expression-based ORDER BY (e.g. rawDistance('vector', qv))\n\tif (order.expression) {\n\t\tconst base: PlanDecision = {\n\t\t\ttype: 'orderBy',\n\t\t\texpressionIntent: order.expression,\n\t\t\tdirection,\n\t\t\ttable: rootTable,\n\t\t};\n\t\tif (nulls) {\n\t\t\treturn { ...base, nulls };\n\t\t}\n\t\treturn base;\n\t}\n\n\tconst decision: PlanDecision = {\n\t\ttype: 'orderBy',\n\t\tdirection,\n\t\ttable: rootTable,\n\t\t// field is optional in OrderByIntent after expression extension (exactOptionalPropertyTypes)\n\t\t...(order.field ? { column: order.field } : {}),\n\t};\n\n\t// Only add nulls if defined (exactOptionalPropertyTypes)\n\tif (nulls) {\n\t\treturn { ...decision, nulls };\n\t}\n\n\treturn decision;\n}\n\n// ============================================================================\n// CASE expression helpers\n// ============================================================================\n\n/**\n * Convert a CASE WHEN condition (ExpressionIntent) to a PlanDecision\n * that compileCondition can handle.\n */\n","/**\n * SELECT Expression Handlers\n *\n * Individual handlers for each expression kind in SelectWithExpressionsIntent.\n * Extracted from convertSelect in intent-to-decisions.ts to reduce cyclomatic complexity.\n */\n\nimport type { WhereIntent } from '@dbsp/types';\nimport type { Mutable } from '@dbsp/types/internal';\nimport type { PlanDecision } from './compiler.js';\nimport type { WindowOver } from './handlers/types.js';\n\n// ============================================================================\n// Handler Type\n// ============================================================================\n\n/**\n * Handler for a single SELECT expression kind.\n * Pushes zero or more decisions into the provided array.\n */\nexport type SelectExpressionHandler = (\n\texpr: Record<string, unknown>,\n\trootTable: string,\n\tdecisions: PlanDecision[],\n\tapplyFilter: (\n\t\tdecision: Mutable<PlanDecision>,\n\t\tfilter: WhereIntent | undefined,\n\t\ttable: string,\n\t) => void,\n\tconvertCondition: (\n\t\tcondition: WhereIntent,\n\t\ttable: string,\n\t) => PlanDecision | null,\n) => void;\n\n// ============================================================================\n// Individual Handlers\n// ============================================================================\n\n/**\n * column / columnAlias — both produce a 'select' decision.\n * - column: uses `expr.as` for alias\n * - columnAlias: uses `expr.alias` for alias\n */\nexport function handleColumnExpression(\n\texpr: Record<string, unknown>,\n\trootTable: string,\n\tdecisions: PlanDecision[],\n): void {\n\tconst decision: Mutable<PlanDecision> = {\n\t\ttype: 'select',\n\t\tcolumn: expr.column as string,\n\t\ttable: rootTable,\n\t};\n\t// 'column' kind uses `as`; 'columnAlias' kind uses `alias`\n\tconst alias = (expr.as ?? expr.alias) as string | undefined;\n\tif (alias) decision.alias = alias;\n\tdecisions.push(decision);\n}\n\n/**\n * aggregate — count(*), countDistinct, or generic aggregate function.\n */\nexport function handleAggregateExpression(\n\texpr: Record<string, unknown>,\n\trootTable: string,\n\tdecisions: PlanDecision[],\n\tapplyFilter: (\n\t\tdecision: Mutable<PlanDecision>,\n\t\tfilter: WhereIntent | undefined,\n\t\ttable: string,\n\t) => void,\n): void {\n\tconst aggFunc = expr.function as string;\n\tconst aggField = expr.field as string | undefined;\n\tconst aggAs = expr.as as string | undefined;\n\tconst aggDistinct = expr.distinct as boolean | undefined;\n\tconst aggFilter = expr.filter as WhereIntent | undefined;\n\n\tif (aggFunc === 'count' && !aggField) {\n\t\tconst decision: Mutable<PlanDecision> = {\n\t\t\ttype: 'selectFunction',\n\t\t\tfunction: 'count',\n\t\t\tcolumn: '*',\n\t\t\ttable: rootTable,\n\t\t};\n\t\tif (aggAs) decision.alias = aggAs;\n\t\tapplyFilter(decision, aggFilter, rootTable);\n\t\tdecisions.push(decision);\n\t} else if (aggFunc === 'count' && aggDistinct && aggField) {\n\t\tconst decision: Mutable<PlanDecision> = {\n\t\t\ttype: 'selectFunction',\n\t\t\tfunction: 'countDistinct',\n\t\t\tcolumn: aggField,\n\t\t\ttable: rootTable,\n\t\t};\n\t\tif (aggAs) decision.alias = aggAs;\n\t\tapplyFilter(decision, aggFilter, rootTable);\n\t\tdecisions.push(decision);\n\t} else {\n\t\tconst decision: Mutable<PlanDecision> = {\n\t\t\ttype: 'selectFunction',\n\t\t\tfunction: aggFunc,\n\t\t\ttable: rootTable,\n\t\t};\n\t\tif (aggField) decision.column = aggField;\n\t\tif (aggAs) decision.alias = aggAs;\n\t\tapplyFilter(decision, aggFilter, rootTable);\n\t\tdecisions.push(decision);\n\t}\n}\n\n/**\n * coalesce — COALESCE(field1, field2, ...) [AS alias]\n */\nexport function handleCoalesceExpression(\n\texpr: Record<string, unknown>,\n\trootTable: string,\n\tdecisions: PlanDecision[],\n): void {\n\tconst decision: Mutable<PlanDecision> = {\n\t\ttype: 'selectFunction',\n\t\tfunction: 'coalesce',\n\t\targs: expr.fields as string[],\n\t\ttable: rootTable,\n\t};\n\tif (expr.as) decision.alias = expr.as as string;\n\tdecisions.push(decision);\n}\n\n/**\n * raw — raw SQL snippet wrapped in a selectFunction decision.\n */\nexport function handleRawExpression(\n\texpr: Record<string, unknown>,\n\trootTable: string,\n\tdecisions: PlanDecision[],\n): void {\n\tconst decision: Mutable<PlanDecision> = {\n\t\ttype: 'selectFunction',\n\t\tfunction: 'raw',\n\t\targs: [expr.sql as string],\n\t\ttable: rootTable,\n\t};\n\tif (expr.as) decision.alias = expr.as as string;\n\tdecisions.push(decision);\n}\n\n/**\n * window — window function with OVER (PARTITION BY … ORDER BY …).\n */\nexport function handleWindowExpression(\n\texpr: Record<string, unknown>,\n\trootTable: string,\n\tdecisions: PlanDecision[],\n): void {\n\tconst windowFunc = expr.function as string;\n\tconst windowAlias = expr.alias as string;\n\tconst windowField = expr.field as string | undefined;\n\tconst over = expr.over as WindowOver;\n\n\tconst decision: Mutable<PlanDecision> = {\n\t\ttype: 'selectWindow',\n\t\tfunction: windowFunc,\n\t\talias: windowAlias,\n\t\ttable: rootTable,\n\t};\n\tif (windowField) decision.field = windowField;\n\tif (over.partitionBy) decision.partitionBy = over.partitionBy;\n\tif (over.orderBy) decision.orderBy = over.orderBy;\n\tconst windowOffset = expr.offset as number | undefined;\n\tconst windowDefault = expr.defaultValue as unknown;\n\tif (windowOffset !== undefined) decision.args = [windowOffset];\n\tif (windowDefault !== undefined) decision.value = windowDefault;\n\tdecisions.push(decision);\n}\n\n/**\n * case — CASE WHEN … THEN … ELSE … END [AS alias]\n */\nexport function handleCaseExpression(\n\texpr: Record<string, unknown>,\n\trootTable: string,\n\tdecisions: PlanDecision[],\n\t_applyFilter: (\n\t\tdecision: Mutable<PlanDecision>,\n\t\tfilter: WhereIntent | undefined,\n\t\ttable: string,\n\t) => void,\n\tconvertCondition: (\n\t\tcondition: WhereIntent,\n\t\ttable: string,\n\t) => PlanDecision | null,\n): void {\n\tconst whenClauses = expr.when as Array<{\n\t\tcondition: WhereIntent;\n\t\tresult: Record<string, unknown>;\n\t}>;\n\tconst conditions = whenClauses.map((wc) => ({\n\t\twhen: convertCondition(wc.condition, rootTable),\n\t\t// biome-ignore lint/suspicious/noThenProperty: intentional reserved word in decision object\n\t\tthen: wc.result,\n\t}));\n\n\t// CASE decisions carry { when, then } tuples in `conditions` —\n\t// structurally different from PlanDecision[]. The compiler and\n\t// case handler both expect this shape at runtime.\n\tconst decision: Mutable<PlanDecision> = {\n\t\ttype: 'selectExpression',\n\t\texpressionType: 'case',\n\t\ttable: rootTable,\n\t};\n\t// Assign conditions separately: the runtime type is { when, then }[]\n\t// but PlanDecision declares conditions as PlanDecision[].\n\t(decision as Record<string, unknown>).conditions = conditions;\n\tif (expr.else) {\n\t\tdecision.value = expr.else;\n\t}\n\tif (expr.as) decision.alias = expr.as as string;\n\tdecisions.push(decision);\n}\n\n/**\n * relationColumn — SELECT relation.column AS alias\n */\nexport function handleRelationColumnExpression(\n\texpr: Record<string, unknown>,\n\trootTable: string,\n\tdecisions: PlanDecision[],\n): void {\n\tconst decision: Mutable<PlanDecision> = {\n\t\ttype: 'selectRelationColumn',\n\t\trelation: expr.relation as string,\n\t\tcolumn: (expr.column ?? '*') as string,\n\t\ttable: rootTable,\n\t};\n\tif (expr.as) decision.alias = expr.as as string;\n\tdecisions.push(decision);\n}\n\n/**\n * arithmetic — SELECT left op right AS alias\n */\nexport function handleArithmeticExpression(\n\texpr: Record<string, unknown>,\n\trootTable: string,\n\tdecisions: PlanDecision[],\n): void {\n\tconst decision: Mutable<PlanDecision> = {\n\t\ttype: 'selectArithmetic',\n\t\toperator: expr.operator as string,\n\t\targs: [expr.left, expr.right],\n\t\ttable: rootTable,\n\t};\n\tif (expr.as) decision.alias = expr.as as string;\n\tdecisions.push(decision);\n}\n\n/**\n * jsonExtract — col->'key' or col->>'key'\n */\nexport function handleJsonExtractExpression(\n\texpr: Record<string, unknown>,\n\trootTable: string,\n\tdecisions: PlanDecision[],\n): void {\n\tconst decision: Mutable<PlanDecision> = {\n\t\ttype: 'selectFunction',\n\t\tfunction: 'jsonExtract',\n\t\tcolumn: expr.field as string,\n\t\targs: expr.path as string[],\n\t\ttable: rootTable,\n\t};\n\tif (expr.mode) decision.jsonMode = expr.mode as 'json' | 'text';\n\tif (expr.as) decision.alias = expr.as as string;\n\tdecisions.push(decision);\n}\n\n/**\n * jsonPathExtract — col#>'{a,b}' or col#>>'{a,b}'\n */\nexport function handleJsonPathExtractExpression(\n\texpr: Record<string, unknown>,\n\trootTable: string,\n\tdecisions: PlanDecision[],\n): void {\n\tconst decision: Mutable<PlanDecision> = {\n\t\ttype: 'selectFunction',\n\t\tfunction: 'jsonPathExtract',\n\t\tcolumn: expr.field as string,\n\t\targs: [expr.path as string],\n\t\ttable: rootTable,\n\t};\n\tif (expr.mode) decision.jsonMode = expr.mode as 'json' | 'text';\n\tif (expr.as) decision.alias = expr.as as string;\n\tdecisions.push(decision);\n}\n\n/**\n * customOp / customFn / ref / param / cast / unary — custom expression in SELECT.\n * The expression intent is stored as-is in a 'selectCustomExpression' decision.\n * Compilation is deferred to compileExpressionIntent in compiler.ts.\n */\nexport function handleCustomExpressionSelect(\n\texpr: Record<string, unknown>,\n\trootTable: string,\n\tdecisions: PlanDecision[],\n): void {\n\tconst decision: Mutable<PlanDecision> = {\n\t\ttype: 'selectCustomExpression',\n\t\texpressionIntent: expr,\n\t\ttable: rootTable,\n\t};\n\tconst alias = expr.as as string | undefined;\n\tif (alias) decision.alias = alias;\n\tdecisions.push(decision);\n}\n\n// ============================================================================\n// Dispatch Map\n// ============================================================================\n\n/**\n * Maps each expression kind to its handler.\n * pseudoColumn is an intentional no-op — planner hints, not SQL.\n */\nexport const EXPRESSION_HANDLERS: Record<string, SelectExpressionHandler> = {\n\tcolumn: (expr, rootTable, decisions) =>\n\t\thandleColumnExpression(expr, rootTable, decisions),\n\tcolumnAlias: (expr, rootTable, decisions) =>\n\t\thandleColumnExpression(expr, rootTable, decisions),\n\taggregate: (expr, rootTable, decisions, applyFilter) =>\n\t\thandleAggregateExpression(expr, rootTable, decisions, applyFilter),\n\tcoalesce: (expr, rootTable, decisions) =>\n\t\thandleCoalesceExpression(expr, rootTable, decisions),\n\traw: (expr, rootTable, decisions) =>\n\t\thandleRawExpression(expr, rootTable, decisions),\n\twindow: (expr, rootTable, decisions) =>\n\t\thandleWindowExpression(expr, rootTable, decisions),\n\tcase: (expr, rootTable, decisions, applyFilter, convertCondition) =>\n\t\thandleCaseExpression(\n\t\t\texpr,\n\t\t\trootTable,\n\t\t\tdecisions,\n\t\t\tapplyFilter,\n\t\t\tconvertCondition,\n\t\t),\n\trelationColumn: (expr, rootTable, decisions) =>\n\t\thandleRelationColumnExpression(expr, rootTable, decisions),\n\t// pseudoColumn: intentional no-op — planner hints, not SQL\n\tarithmetic: (expr, rootTable, decisions) =>\n\t\thandleArithmeticExpression(expr, rootTable, decisions),\n\tjsonExtract: (expr, rootTable, decisions) =>\n\t\thandleJsonExtractExpression(expr, rootTable, decisions),\n\tjsonPathExtract: (expr, rootTable, decisions) =>\n\t\thandleJsonPathExtractExpression(expr, rootTable, decisions),\n\t// Custom expression types — produce 'selectCustomExpression' decisions\n\tliteral: (expr, rootTable, decisions) =>\n\t\thandleCustomExpressionSelect(expr, rootTable, decisions),\n\tcustomOp: (expr, rootTable, decisions) =>\n\t\thandleCustomExpressionSelect(expr, rootTable, decisions),\n\tcustomFn: (expr, rootTable, decisions) =>\n\t\thandleCustomExpressionSelect(expr, rootTable, decisions),\n\tref: (expr, rootTable, decisions) =>\n\t\thandleCustomExpressionSelect(expr, rootTable, decisions),\n\tparam: (expr, rootTable, decisions) =>\n\t\thandleCustomExpressionSelect(expr, rootTable, decisions),\n\tcast: (expr, rootTable, decisions) =>\n\t\thandleCustomExpressionSelect(expr, rootTable, decisions),\n\tunary: (expr, rootTable, decisions) =>\n\t\thandleCustomExpressionSelect(expr, rootTable, decisions),\n};\n","/**\n * DDL Generator - Generates PostgreSQL DDL statements from ModelIR\n *\n * Generates SQL strings directly for better compatibility and control.\n * Two-pass strategy handles circular FK dependencies.\n *\n * @module ddl/ddl-generator\n */\n\nimport type {\n\tColumnIR,\n\tDialectCapabilities,\n\tForeignKeyIR,\n\tIndexIR,\n\tModelIR,\n\tPolicyIR,\n\tTableIR,\n} from '@dbsp/types';\nimport { identityNaming, type NamingPlugin } from '../naming-plugin.js';\nimport { validateIdentifier, validateSqlExpression } from '../validate.js';\nimport { generateCommentsPhase } from './phases/comments.js';\nimport { generateConstraintsPhase } from './phases/constraints.js';\nimport { generateDropStatementsPhase } from './phases/drop-statements.js';\nimport { generateEnumTypesPhase } from './phases/enum-types.js';\nimport { generateExtensionsPhase } from './phases/extensions.js';\nimport { generateIndexesPhase } from './phases/indexes.js';\nimport { generateRlsPhase } from './phases/rls.js';\nimport { generateSequencesPhase } from './phases/sequences.js';\nimport { generateTablesPhase } from './phases/tables.js';\nimport type { PhaseContext } from './phases/types.js';\nimport {\n\tformatSqlDefault,\n\tquoteCollation,\n\tquoteRoleName,\n\tvalidateIndexMethod,\n} from './phases/utils.js';\nimport { mapColumnType, mapOnDeleteAction } from './type-mapping.js';\n\n// ============================================================================\n// Options\n// ============================================================================\n\nexport interface GenerateDDLOptions {\n\t/** Include DROP TABLE IF EXISTS statements before CREATE TABLE */\n\treadonly includeDropStatements?: boolean;\n\t/** Database schema name (e.g., 'public', 'tenant_123') */\n\treadonly schemaName?: string;\n\t/**\n\t * Automatically create indexes on foreign key columns.\n\t * FK columns are frequently used in JOINs, so indexing is a best practice.\n\t * @default true\n\t */\n\treadonly fkAutoIndex?: boolean;\n\t/** Naming plugin for identifier transformation */\n\treadonly naming?: NamingPlugin;\n\t/** Dialect capabilities — DDL passes for unsupported features will be skipped */\n\treadonly dialectCapabilities?: DialectCapabilities;\n}\n\n// ============================================================================\n// Main DDL Generation\n// ============================================================================\n\n/**\n * Generate DDL statements from a ModelIR schema.\n *\n * Uses a two-pass approach to handle circular FK dependencies:\n * 1. CREATE TABLE (without FK constraints)\n * 2. ALTER TABLE ADD CONSTRAINT for foreign keys\n * 3. CREATE INDEX (explicit + auto-generated for FKs)\n *\n * @param schema - The ModelIR schema to generate DDL from\n * @param options - Optional configuration\n * @returns Array of DDL statements in dependency order\n */\nexport function generateDDL(\n\tschema: ModelIR,\n\toptions: GenerateDDLOptions = {},\n): string[] {\n\tconst {\n\t\tincludeDropStatements = false,\n\t\tschemaName,\n\t\tfkAutoIndex = true,\n\t\tnaming = identityNaming,\n\t\tdialectCapabilities: caps,\n\t} = options;\n\n\tconst tables = Array.from(schema.tables.values());\n\n\tconst ctx: PhaseContext = {\n\t\tschema,\n\t\ttables,\n\t\tschemaName,\n\t\tnaming,\n\t\tcaps,\n\t\tfkAutoIndex,\n\t\tincludeDropStatements,\n\t};\n\n\treturn [\n\t\t...generateExtensionsPhase(ctx), // PASS -1: CREATE EXTENSION\n\t\t...generateSequencesPhase(ctx), // PASS -0.5: CREATE SEQUENCE\n\t\t...generateDropStatementsPhase(ctx), // PASS 0: DROP TABLE (optional)\n\t\t...generateEnumTypesPhase(ctx), // PASS 0.5: CREATE TYPE ... AS ENUM\n\t\t...generateTablesPhase(ctx), // PASS 1: CREATE TABLE\n\t\t...generateConstraintsPhase(ctx), // PASS 2 + 2.5: FK + CHECK constraints\n\t\t...generateIndexesPhase(ctx), // PASS 3: CREATE INDEX\n\t\t...generateRlsPhase(ctx), // PASS 3.5: RLS + policies\n\t\t...generateCommentsPhase(ctx), // PASS 4: COMMENT ON\n\t];\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Quote an identifier (table name, column name, etc.)\n */\n/**\n * Quote an identifier (table name, column name, etc.) for use in DDL.\n *\n * @security Validates the identifier via validateIdentifier() before quoting.\n * Escapes embedded double-quotes by doubling them as defense-in-depth.\n * Only call this with identifiers that have been validated upstream (table names,\n * column names, policy names). Do NOT call with raw user input without validation.\n */\nfunction quoteIdentifier(name: string): string {\n\tvalidateIdentifier(name, 'alias');\n\t// Defense-in-depth: escape any embedded double-quotes by doubling them.\n\treturn `\"${name.replace(/\"/g, '\"\"')}\"`;\n}\n\n/**\n * Qualify a table name with optional schema.\n */\nfunction qualifyTable(\n\ttableName: string,\n\tschemaName: string | undefined,\n\tnaming: NamingPlugin,\n): string {\n\tconst table = quoteIdentifier(naming.toDatabase(tableName));\n\tif (schemaName) {\n\t\treturn `${quoteIdentifier(naming.toDatabase(schemaName))}.${table}`;\n\t}\n\treturn table;\n}\n\n// ============================================================================\n// DROP TABLE\n// ============================================================================\n\nexport function generateDropTable(\n\ttableName: string,\n\tschemaName: string | undefined,\n\tnaming: NamingPlugin,\n): string {\n\tconst qualifiedTable = qualifyTable(tableName, schemaName, naming);\n\treturn `DROP TABLE IF EXISTS ${qualifiedTable} CASCADE;`;\n}\n\n// ============================================================================\n// CREATE TABLE\n// ============================================================================\n\nexport function generateCreateTable(\n\ttable: TableIR,\n\tschemaName: string | undefined,\n\tnaming: NamingPlugin,\n): string {\n\tconst qualifiedTable = qualifyTable(table.name, schemaName, naming);\n\tconst elements: string[] = [];\n\n\t// Add columns\n\tfor (const col of table.columns) {\n\t\telements.push(generateColumnDef(col, naming));\n\t}\n\n\t// Add primary key constraint (omit if no PK defined)\n\tif (table.primaryKey !== undefined) {\n\t\t// Normalize primaryKey: typed as string | readonly string[], but\n\t\t// introspected models may pass { columns: string[] } — extract columns defensively.\n\t\tconst rawPk = table.primaryKey as unknown;\n\t\tlet pkColumns: readonly string[];\n\t\tif (\n\t\t\trawPk !== null &&\n\t\t\ttypeof rawPk === 'object' &&\n\t\t\t'columns' in rawPk &&\n\t\t\tArray.isArray((rawPk as { columns: unknown }).columns)\n\t\t) {\n\t\t\tpkColumns = (rawPk as { columns: string[] }).columns;\n\t\t} else if (Array.isArray(rawPk)) {\n\t\t\tpkColumns = rawPk as readonly string[];\n\t\t} else {\n\t\t\tpkColumns = [rawPk as string];\n\t\t}\n\t\tconst pkCols = pkColumns\n\t\t\t.map((col) => quoteIdentifier(naming.toDatabase(col)))\n\t\t\t.join(', ');\n\t\tconst pkName = quoteIdentifier(`pk_${table.name}`);\n\t\telements.push(`CONSTRAINT ${pkName} PRIMARY KEY (${pkCols})`);\n\t}\n\n\tconst elementsStr = elements.map((el) => ` ${el}`).join(',\\n');\n\tlet sql = `CREATE TABLE ${qualifiedTable} (\\n${elementsStr}\\n)`;\n\tif (table.partition) {\n\t\tconst partCols = table.partition.columns\n\t\t\t.map((col) => quoteIdentifier(naming.toDatabase(col)))\n\t\t\t.join(', ');\n\t\tsql += ` PARTITION BY ${table.partition.strategy} (${partCols})`;\n\t}\n\tsql += ';';\n\treturn sql;\n}\n\n/**\n * Generate a column definition string.\n */\nfunction generateColumnDef(col: ColumnIR, naming: NamingPlugin): string {\n\tconst parts: string[] = [];\n\n\t// Column name and type\n\tparts.push(quoteIdentifier(naming.toDatabase(col.name)));\n\tparts.push(mapColumnType(col));\n\n\t// NOT NULL constraint (SERIAL/BIGSERIAL imply NOT NULL)\n\tif (!col.nullable && !col.autoIncrement) {\n\t\tparts.push('NOT NULL');\n\t}\n\n\t// DEFAULT constraint\n\tif (col.default !== undefined) {\n\t\tparts.push(`DEFAULT ${formatDefaultValue(col.default)}`);\n\t}\n\n\t// UNIQUE constraint\n\tif (col.unique) {\n\t\tparts.push('UNIQUE');\n\t}\n\n\t// COLLATE (must come after type)\n\t// S-2: validate collation name before quoting — uses quoteCollation which\n\t// accepts locale strings like `en_US.utf8`, `en-US-x-icu`, `C.UTF-8`\n\t// that contain dots/hyphens rejected by the standard identifier validator.\n\tif (col.collation) {\n\t\tparts.push(`COLLATE ${quoteCollation(col.collation)}`);\n\t}\n\n\t// GENERATED AS IDENTITY\n\tif (col.identity) {\n\t\tconst gen = col.identity === 'always' ? 'ALWAYS' : 'BY DEFAULT';\n\t\tparts.push(`GENERATED ${gen} AS IDENTITY`);\n\t}\n\n\treturn parts.join(' ');\n}\n\n/**\n * Format a default value for SQL.\n */\n/**\n * Format a default value for SQL.\n *\n * @security The `{ sql: string }` escape hatch is validated via validateSqlExpression()\n * before interpolation to prevent injection of multi-statement or comment-bearing strings.\n */\n// M-6: formatDefaultValue is now a thin alias for the shared formatSqlDefault from phases/utils.\n// The duplicate implementations have been consolidated.\n// The doc-comment security note is on formatSqlDefault in packages/adapter-pgsql/src/ddl/phases/utils.ts.\nfunction formatDefaultValue(value: unknown): string {\n\treturn formatSqlDefault(value, 'ddl-generator default');\n}\n\n// ============================================================================\n// ALTER TABLE (Foreign Keys)\n// ============================================================================\n\nexport function generateAlterTableAddFK(\n\ttableName: string,\n\tfk: ForeignKeyIR,\n\tschemaName: string | undefined,\n\tnaming: NamingPlugin,\n): string {\n\tconst qualifiedTable = qualifyTable(tableName, schemaName, naming);\n\tconst constraintName = quoteIdentifier(\n\t\t`fk_${tableName}_${fk.columns.join('_')}`,\n\t);\n\n\t// Local columns\n\tconst fkCols = fk.columns\n\t\t.map((col) => quoteIdentifier(naming.toDatabase(col)))\n\t\t.join(', ');\n\n\t// Referenced table and columns (must also be schema-qualified to match the target table's schema)\n\tconst refTable = qualifyTable(fk.references.table, schemaName, naming);\n\tconst refCols = fk.references.columns\n\t\t.map((col) => quoteIdentifier(naming.toDatabase(col)))\n\t\t.join(', ');\n\n\t// ON DELETE / ON UPDATE / DEFERRABLE actions\n\tconst onDelete = fk.onDelete\n\t\t? ` ON DELETE ${mapOnDeleteAction(fk.onDelete)}`\n\t\t: '';\n\tconst onUpdate = fk.onUpdate\n\t\t? ` ON UPDATE ${mapOnDeleteAction(fk.onUpdate)}`\n\t\t: '';\n\tconst deferred = fk.deferred ? ' DEFERRABLE INITIALLY DEFERRED' : '';\n\tconst notValid = fk.notValid ? ' NOT VALID' : '';\n\n\treturn `ALTER TABLE ${qualifiedTable} ADD CONSTRAINT ${constraintName} FOREIGN KEY (${fkCols}) REFERENCES ${refTable} (${refCols})${onDelete}${onUpdate}${deferred}${notValid};`;\n}\n\n// ============================================================================\n// CREATE INDEX\n// ============================================================================\n\nexport function generateCreateIndex(\n\ttableName: string,\n\tidx: IndexIR,\n\tschemaName: string | undefined,\n\tnaming: NamingPlugin,\n): string {\n\tconst indexName = quoteIdentifier(\n\t\tidx.name ?? `idx_${tableName}_${idx.columns.join('_')}`,\n\t);\n\tconst qualifiedTable = qualifyTable(tableName, schemaName, naming);\n\tconst unique = idx.unique ? 'UNIQUE ' : '';\n\t// S-2: validate index method against allowlist before interpolation into unquoted USING clause\n\tif (idx.method) validateIndexMethod(idx.method, 'index method');\n\tconst method = idx.method ? ` USING ${idx.method}` : '';\n\n\t// Build column list: expressions first (validated), then named columns with optional opclass\n\t// S-1: validate each expression and opclass before interpolation\n\tconst colParts: string[] = [];\n\tif (idx.expressions && idx.expressions.length > 0) {\n\t\tfor (const expr of idx.expressions) {\n\t\t\tvalidateSqlExpression(expr, 'index expression');\n\t\t\tcolParts.push(expr);\n\t\t}\n\t}\n\tfor (const col of idx.columns) {\n\t\tconst opclass = idx.opclass?.[col] ?? '';\n\t\tif (opclass) validateIdentifier(opclass, 'alias');\n\t\tcolParts.push(\n\t\t\t`${quoteIdentifier(naming.toDatabase(col))}${opclass ? ` ${opclass}` : ''}`,\n\t\t);\n\t}\n\tconst cols = colParts.join(', ');\n\n\tconst include =\n\t\tidx.include && idx.include.length > 0\n\t\t\t? ` INCLUDE (${idx.include.map((c) => quoteIdentifier(naming.toDatabase(c))).join(', ')})`\n\t\t\t: '';\n\n\t// S-1: validate WITH storage parameter keys before interpolation\n\tconst withParams =\n\t\tidx.with && Object.keys(idx.with).length > 0\n\t\t\t? ` WITH (${Object.entries(idx.with)\n\t\t\t\t\t.map(([k, v]) => {\n\t\t\t\t\t\tvalidateIdentifier(k, 'alias');\n\t\t\t\t\t\treturn `${k} = ${v}`;\n\t\t\t\t\t})\n\t\t\t\t\t.join(', ')})`\n\t\t\t: '';\n\n\t// S-1: validate WHERE predicate expression before interpolation\n\tif (idx.where) validateSqlExpression(idx.where, 'index WHERE predicate');\n\tconst where = idx.where ? ` WHERE ${idx.where}` : '';\n\n\treturn `CREATE ${unique}INDEX ${indexName} ON ${qualifiedTable}${method} (${cols})${include}${withParams}${where};`;\n}\n\n// ============================================================================\n// generateCreatePolicy\n// ============================================================================\n\n/**\n * Generate a CREATE POLICY statement.\n */\nexport function generateCreatePolicy(\n\ttableName: string,\n\tpolicy: PolicyIR,\n\tschemaName: string | undefined,\n\tnaming: NamingPlugin,\n): string {\n\tconst qualifiedTable = qualifyTable(tableName, schemaName, naming);\n\tconst policyName = quoteIdentifier(policy.name);\n\tconst forClause =\n\t\tpolicy.command && policy.command !== 'ALL'\n\t\t\t? ` FOR ${policy.command}`\n\t\t\t: ' FOR ALL';\n\tconst asClause =\n\t\tpolicy.permissive === false ? ' AS RESTRICTIVE' : ' AS PERMISSIVE';\n\t// M-4: role names use quoteRoleName() (allows spaces/hyphens, blocks injection vectors)\n\t// rather than quoteIdentifier() (which only allows \\w$ characters).\n\tconst toClause =\n\t\tpolicy.roles && policy.roles.length > 0\n\t\t\t? ` TO ${policy.roles.map((r) => quoteRoleName(r)).join(', ')}`\n\t\t\t: '';\n\tif (policy.using) {\n\t\tvalidateSqlExpression(policy.using, 'policy USING expression');\n\t}\n\tif (policy.withCheck) {\n\t\tvalidateSqlExpression(policy.withCheck, 'policy WITH CHECK expression');\n\t}\n\tconst usingClause = policy.using ? ` USING (${policy.using})` : '';\n\tconst withCheckClause = policy.withCheck\n\t\t? ` WITH CHECK (${policy.withCheck})`\n\t\t: '';\n\treturn `CREATE POLICY ${policyName} ON ${qualifiedTable}${forClause}${asClause}${toClause}${usingClause}${withCheckClause};`;\n}\n","/**\n * Shared types for DDL generation phases.\n *\n * Each phase receives a PhaseContext containing the full set of\n * generation options resolved from GenerateDDLOptions.\n *\n * @module ddl/phases/types\n */\n\nimport type { DialectCapabilities, ModelIR, TableIR } from '@dbsp/types';\nimport type { NamingPlugin } from '../../naming-plugin.js';\n\n/**\n * Resolved context passed to every DDL generation phase.\n * Contains all options from GenerateDDLOptions plus the resolved tables array.\n */\nexport type PhaseContext = {\n\treadonly schema: ModelIR;\n\treadonly tables: TableIR[];\n\treadonly schemaName: string | undefined;\n\treadonly naming: NamingPlugin;\n\treadonly caps: DialectCapabilities | undefined;\n\treadonly fkAutoIndex: boolean;\n\treadonly includeDropStatements: boolean;\n};\n\n/**\n * Check whether a DDL feature is supported given DialectCapabilities.\n *\n * - `undefined` caps: no capability restriction → feature is on by default.\n * - `false`: capability explicitly disabled → feature is skipped.\n * - `true`: capability explicitly enabled → feature is included.\n */\nexport function sup(\n\tcaps: DialectCapabilities | undefined,\n\tflag: boolean | undefined,\n): boolean {\n\treturn !caps || flag === true;\n}\n","/**\n * Shared DDL phase utilities.\n *\n * Centralises identifier quoting with mandatory validation so every phase\n * funnels through `validateIdentifier()` before emitting DDL.\n *\n * @module ddl/phases/utils\n */\n\nimport {\n\tvalidateCollationName,\n\tvalidateExtensionName,\n\tvalidateIdentifier,\n\tvalidateSqlExpression,\n} from '../../validate.js';\nimport type { PhaseContext } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Index method validation\n// ---------------------------------------------------------------------------\n\n/**\n * Valid PostgreSQL index access methods.\n * Used by validateIndexMethod() to reject unknown / injection-bearing strings.\n */\nexport const VALID_INDEX_METHODS = new Set([\n\t'btree',\n\t'hash',\n\t'gist',\n\t'gin',\n\t'brin',\n\t'spgist',\n\t'hnsw',\n\t'ivfflat',\n\t'bm25',\n\t'bloom',\n]);\n\n/**\n * Validate a PostgreSQL index access method (USING clause).\n *\n * Method names are emitted unquoted into DDL (`USING btree`, `USING hnsw`),\n * so an allowlist is the only safe approach — regex-based checks cannot\n * guard all injection vectors for unquoted keywords.\n *\n * @security Allowlist — rejects anything not in VALID_INDEX_METHODS.\n * @param method Raw method name from IndexIR (e.g. `'btree'`, `'hnsw'`)\n * @param context Human-readable context for error messages\n * @throws Error when the method is not in the allowlist\n */\nexport function validateIndexMethod(\n\tmethod: string,\n\tcontext = 'index method',\n): void {\n\tif (!VALID_INDEX_METHODS.has(method)) {\n\t\tthrow new Error(\n\t\t\t`Invalid ${context}: \"${method}\". Must be one of: ${[...VALID_INDEX_METHODS].join(', ')}`,\n\t\t);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Enum label validation (shared by migration-sql.ts and enum-types.ts)\n// ---------------------------------------------------------------------------\n\n/**\n * Validate an enum label (single-quoted string value in CREATE TYPE ... AS ENUM,\n * ADD VALUE, or AFTER clause).\n *\n * Enum labels may be any printable string but must not contain NUL bytes or\n * control characters, which PostgreSQL silently truncates or rejects at the\n * protocol level.\n *\n * @param value The enum label to validate\n * @param context Human-readable context label for error messages\n * @throws Error if the label contains forbidden characters\n */\nexport function validateEnumLabel(value: string, context = 'enum label'): void {\n\t// Reject NUL bytes — PostgreSQL truncates strings at the first NUL silently\n\tif (/\\x00/.test(value)) {\n\t\tthrow new Error(\n\t\t\t`Invalid ${context}: contains NUL byte (\\\\x00) which would be silently truncated by PostgreSQL`,\n\t\t);\n\t}\n\t// Reject control characters that have no valid use in enum labels\n\tif (/[\\x01-\\x1f\\x7f]/.test(value)) {\n\t\tthrow new Error(\n\t\t\t`Invalid ${context}: contains control characters (only printable characters allowed)`,\n\t\t);\n\t}\n}\n\n/**\n * Quote a PostgreSQL identifier for use in DDL statements.\n *\n * @security Always calls `validateIdentifier()` before quoting.\n * Escapes embedded double-quotes by doubling them as defense-in-depth.\n * Throws `InvalidIdentifierError` for identifiers that contain control\n * characters, injection vectors, or other forbidden patterns.\n *\n * @param name Raw identifier (table name, schema name, column name, …)\n * @param type Identifier type used for error context; one of\n * `'table' | 'column' | 'schema' | 'alias'` — defaults to `'alias'`\n * @returns Double-quoted identifier safe for DDL emission\n */\nexport function quoteIdent(\n\tname: string,\n\ttype: 'table' | 'column' | 'schema' | 'alias' = 'alias',\n): string {\n\tvalidateIdentifier(name, type);\n\treturn `\"${name.replace(/\"/g, '\"\"')}\"`;\n}\n\n/**\n * Quote a PostgreSQL extension name for use in CREATE EXTENSION DDL statements.\n *\n * Extension names allow hyphens and dots (e.g. `uuid-ossp`, `postgis-raster`)\n * which standard identifiers do not. This function calls `validateExtensionName()`\n * for injection-safety, then wraps the name in double-quotes so PostgreSQL\n * accepts hyphenated names without error.\n *\n * @security Always calls `validateExtensionName()` before quoting.\n * @param name Raw extension name (e.g. `uuid-ossp`)\n * @returns Double-quoted name safe for DDL emission (e.g. `\"uuid-ossp\"`)\n */\nexport function quoteExtensionName(name: string): string {\n\tvalidateExtensionName(name, 'extension');\n\t// No need to escape double-quotes inside — validateExtensionName rejects them.\n\treturn `\"${name}\"`;\n}\n\n/**\n * Quote a PostgreSQL collation name for use in DDL statements\n * (e.g. `COLLATE \"en_US.utf8\"`, `COLLATE \"en-US-x-icu\"`).\n *\n * Collation names differ from standard identifiers: they can contain dots\n * and hyphens to represent OS locale strings and ICU locale identifiers.\n * This function calls `validateCollationName()` for injection-safety, then\n * wraps the name in double-quotes for safe DDL emission.\n *\n * @security Always calls `validateCollationName()` before quoting.\n * @param name Raw collation name (e.g. `en_US.utf8`, `C.UTF-8`)\n * @returns Double-quoted collation name safe for DDL emission (e.g. `\"en_US.utf8\"`)\n */\nexport function quoteCollation(name: string): string {\n\tvalidateCollationName(name, 'collation');\n\t// No need to escape double-quotes inside — validateCollationName rejects them.\n\treturn `\"${name}\"`;\n}\n\n/**\n * Quote a PostgreSQL role name for use in DDL statements (e.g. CREATE POLICY ... TO).\n *\n * Role names may contain spaces and other characters not allowed in standard\n * identifiers (e.g. `\"app admin\"`, `\"read-only\"`), but must not contain\n * injection vectors such as semicolons, comment markers, or backslashes.\n *\n * @security Validates via validateSqlExpression() (blocks `;`, `--`, `/*`, `$$`, `\\`)\n * and rejects embedded double-quotes, NUL bytes, control characters, and names\n * exceeding PostgreSQL's NAMEDATALEN limit (63 bytes). Wraps the name in\n * double-quotes for safe DDL emission.\n *\n * @param name Raw role name (e.g. `app admin`)\n * @returns Double-quoted role name safe for DDL emission (e.g. `\"app admin\"`)\n */\nexport function quoteRoleName(name: string): string {\n\tif (!name) {\n\t\tthrow new Error('quoteRoleName: role name must not be empty');\n\t}\n\t// Reject embedded double-quotes — no legitimate role name needs them inside\n\tif (name.includes('\"')) {\n\t\tthrow new Error(\n\t\t\t`quoteRoleName: role name \"${name}\" must not contain double-quote characters`,\n\t\t);\n\t}\n\t// Reject NUL bytes — PostgreSQL silently truncates at the first NUL\n\tif (/\\x00/.test(name)) {\n\t\tthrow new Error(\n\t\t\t`quoteRoleName: role name contains NUL byte (\\\\x00) which would be silently truncated by PostgreSQL`,\n\t\t);\n\t}\n\t// Reject other control characters (0x01-0x1F, 0x7F)\n\tif (/[\\x01-\\x1f\\x7f]/.test(name)) {\n\t\tthrow new Error(\n\t\t\t`quoteRoleName: role name contains control characters (only printable characters allowed)`,\n\t\t);\n\t}\n\t// Enforce PostgreSQL NAMEDATALEN: identifiers are truncated at 63 bytes.\n\t// We count bytes (not JS chars) because PostgreSQL uses strlen() semantics.\n\tconst byteLength = Buffer.byteLength(name, 'utf8');\n\tif (byteLength > 63) {\n\t\tthrow new Error(\n\t\t\t`quoteRoleName: role name exceeds PostgreSQL NAMEDATALEN limit of 63 bytes (got ${byteLength} bytes): \"${name}\"`,\n\t\t);\n\t}\n\t// Block injection vectors (semicolons, comments, dollar-quotes, backslash)\n\tvalidateSqlExpression(name, 'role name');\n\treturn `\"${name}\"`;\n}\n\n/**\n * Qualify a table name with an optional schema prefix.\n * Both the schema and table names are validated + quoted via `quoteIdent`.\n *\n * @param tableName Unqualified table name (pre-naming-plugin)\n * @param schemaName Optional schema name\n * @param naming NamingPlugin from PhaseContext\n * @returns `\"schema\".\"table\"` or `\"table\"` if no schema\n */\nexport function qualifyTableIdent(\n\ttableName: string,\n\tschemaName: string | undefined,\n\tnaming: PhaseContext['naming'],\n): string {\n\tconst table = quoteIdent(naming.toDatabase(tableName), 'table');\n\tif (schemaName) {\n\t\treturn `${quoteIdent(naming.toDatabase(schemaName), 'schema')}.${table}`;\n\t}\n\treturn table;\n}\n\n/**\n * Format a default value for safe SQL emission.\n *\n * Handles the following value types:\n * - `null` → `NULL`\n * - `{ sql: string }` → raw SQL expression (validated via validateSqlExpression)\n * - `string` ending with `()` → emitted unquoted as a bare function call (e.g. `now()`)\n * - `string` (other) → single-quoted literal with `'` escaped as `''` (e.g. `'hello''world'`)\n * - `number` → numeric literal\n * - `boolean` → `true` / `false`\n * - other → single-quoted string representation\n *\n * @security The `{ sql }` escape hatch is validated via validateSqlExpression()\n * before interpolation to prevent injection of multi-statement or comment-bearing strings.\n *\n * @param value The default value from ModelIR\n * @param context Human-readable label for error messages\n * @returns SQL-safe default clause fragment (without `DEFAULT` keyword)\n */\nexport function formatSqlDefault(\n\tvalue: unknown,\n\tcontext = 'column default',\n): string {\n\tif (value === null || value === undefined) return 'NULL';\n\n\t// { sql: string } escape hatch — emit verbatim after validation\n\tif (typeof value === 'object' && 'sql' in (value as object)) {\n\t\tconst rawSql = (value as Record<string, unknown>).sql;\n\t\tif (typeof rawSql !== 'string') {\n\t\t\tthrow new Error(\n\t\t\t\t`formatSqlDefault({ sql }): expected string, got ${typeof rawSql}`,\n\t\t\t);\n\t\t}\n\t\tvalidateSqlExpression(rawSql, context);\n\t\treturn rawSql;\n\t}\n\n\t// Function-like expressions (e.g. 'now()') — validate then emit unquoted\n\tif (typeof value === 'string') {\n\t\tif (value.endsWith('()')) {\n\t\t\tvalidateSqlExpression(value, context);\n\t\t\treturn value;\n\t\t}\n\t\treturn `'${value.replace(/'/g, \"''\")}'`;\n\t}\n\n\tif (typeof value === 'number') return String(value);\n\tif (typeof value === 'boolean') return value ? 'true' : 'false';\n\n\t// Fallback: single-quoted string representation\n\treturn `'${String(value).replace(/'/g, \"''\")}'`;\n}\n","/**\n * DDL Phase: Comments\n *\n * Generates COMMENT ON TABLE and COMMENT ON COLUMN statements.\n * Guarded by the supportsDDLComments capability flag.\n *\n * @module ddl/phases/comments\n */\n\nimport { type PhaseContext, sup } from './types.js';\nimport {\n\tqualifyTableIdent as qualifyTable,\n\tquoteIdent as quoteId,\n} from './utils.js';\n\n/**\n * Generate COMMENT ON TABLE and COMMENT ON COLUMN statements.\n *\n * @param ctx - Phase context\n * @returns Array of DDL statements (empty if comments are unsupported by the dialect)\n */\nexport function generateCommentsPhase(ctx: PhaseContext): string[] {\n\tconst { tables, schemaName, naming, caps } = ctx;\n\tif (!sup(caps, caps?.supportsDDLComments)) {\n\t\treturn [];\n\t}\n\tconst statements: string[] = [];\n\tfor (const table of tables) {\n\t\tif (table.comment) {\n\t\t\tconst qualifiedTable = qualifyTable(table.name, schemaName, naming);\n\t\t\tstatements.push(\n\t\t\t\t`COMMENT ON TABLE ${qualifiedTable} IS '${table.comment.replace(/'/g, \"''\")}';`,\n\t\t\t);\n\t\t}\n\t\tfor (const col of table.columns) {\n\t\t\tif (col.comment) {\n\t\t\t\tconst qualifiedTable = qualifyTable(table.name, schemaName, naming);\n\t\t\t\tstatements.push(\n\t\t\t\t\t`COMMENT ON COLUMN ${qualifiedTable}.${quoteId(naming.toDatabase(col.name))} IS '${col.comment.replace(/'/g, \"''\")}';`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\treturn statements;\n}\n","/**\n * DDL Phase: Constraints\n *\n * Generates ALTER TABLE ADD CONSTRAINT statements for:\n * 1. Foreign keys (always included — no capability flag, FKs are core SQL)\n * 2. Check constraints (guarded by supportsDDLCheckConstraints)\n *\n * Runs after CREATE TABLE to handle circular FK dependencies.\n *\n * @module ddl/phases/constraints\n */\n\nimport { validateSqlExpression } from '../../validate.js';\nimport { generateAlterTableAddFK } from '../ddl-generator.js';\nimport { type PhaseContext, sup } from './types.js';\nimport {\n\tqualifyTableIdent as qualifyTable,\n\tquoteIdent as quoteId,\n} from './utils.js';\n\n/**\n * Generate ALTER TABLE ADD CONSTRAINT statements for foreign keys and check constraints.\n *\n * @param ctx - Phase context\n * @returns Array of DDL statements\n */\nexport function generateConstraintsPhase(ctx: PhaseContext): string[] {\n\tconst { tables, schemaName, naming, caps } = ctx;\n\tconst statements: string[] = [];\n\n\t// FK constraints (two-pass approach: tables first, then FKs to handle circularity)\n\tfor (const table of tables) {\n\t\tfor (const fk of table.foreignKeys) {\n\t\t\tstatements.push(\n\t\t\t\tgenerateAlterTableAddFK(table.name, fk, schemaName, naming),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Check constraints\n\tif (sup(caps, caps?.supportsDDLCheckConstraints)) {\n\t\tfor (const table of tables) {\n\t\t\tfor (const check of table.checkConstraints ?? []) {\n\t\t\t\tconst qualifiedTable = qualifyTable(table.name, schemaName, naming);\n\t\t\t\tconst constraintName = quoteId(check.name);\n\t\t\t\tvalidateSqlExpression(check.expression, 'check constraint expression');\n\t\t\t\tstatements.push(\n\t\t\t\t\t`ALTER TABLE ${qualifiedTable} ADD CONSTRAINT ${constraintName} ${check.expression};`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn statements;\n}\n","/**\n * DDL Phase: Drop Statements\n *\n * Generates DROP TABLE IF EXISTS ... CASCADE statements.\n * Only emitted when includeDropStatements=true.\n * Tables are dropped in reverse order to handle FK dependencies.\n *\n * @module ddl/phases/drop-statements\n */\n\nimport { generateDropTable } from '../ddl-generator.js';\nimport type { PhaseContext } from './types.js';\n\n/**\n * Generate DROP TABLE statements for all tables in reverse dependency order.\n *\n * @param ctx - Phase context\n * @returns Array of DDL statements (empty if includeDropStatements is false)\n */\nexport function generateDropStatementsPhase(ctx: PhaseContext): string[] {\n\tconst { tables, schemaName, naming, includeDropStatements } = ctx;\n\tif (!includeDropStatements) {\n\t\treturn [];\n\t}\n\tconst statements: string[] = [];\n\tfor (const table of [...tables].reverse()) {\n\t\tstatements.push(generateDropTable(table.name, schemaName, naming));\n\t}\n\tstatements.push(''); // Empty line separator\n\treturn statements;\n}\n","/**\n * DDL Phase: Enum Types\n *\n * Generates CREATE TYPE ... AS ENUM statements.\n * Must run before CREATE TABLE (enum types are referenced by column definitions).\n *\n * @module ddl/phases/enum-types\n */\n\nimport { type PhaseContext, sup } from './types.js';\nimport { quoteIdent as quoteId, validateEnumLabel } from './utils.js';\n\n/**\n * Generate CREATE TYPE ... AS ENUM statements for all enum types in the schema.\n *\n * @param ctx - Phase context with schema, schemaName, naming, and capabilities\n * @returns Array of DDL statements, or empty if enum types are unsupported / absent\n */\nexport function generateEnumTypesPhase(ctx: PhaseContext): string[] {\n\tconst { schema, schemaName, naming, caps } = ctx;\n\tif (!schema.enums || !sup(caps, caps?.supportsDDLEnumTypes)) {\n\t\treturn [];\n\t}\n\tconst statements: string[] = [];\n\tfor (const [, enumDef] of schema.enums) {\n\t\tconst enumName = schemaName\n\t\t\t? `${quoteId(naming.toDatabase(schemaName), 'schema')}.${quoteId(enumDef.name, 'table')}`\n\t\t\t: quoteId(enumDef.name, 'table');\n\t\t// M-3: validate each enum value against NUL/control-char injection before emission\n\t\tconst values = enumDef.values\n\t\t\t.map((v) => {\n\t\t\t\tvalidateEnumLabel(v, 'enum value');\n\t\t\t\treturn `'${v.replace(/'/g, \"''\")}'`;\n\t\t\t})\n\t\t\t.join(', ');\n\t\tstatements.push(`CREATE TYPE ${enumName} AS ENUM (${values});`);\n\t}\n\treturn statements;\n}\n","/**\n * DDL Phase: Extensions\n *\n * Generates CREATE EXTENSION IF NOT EXISTS statements.\n * Must run first (before tables and sequences).\n *\n * @module ddl/phases/extensions\n */\n\nimport { type PhaseContext, sup } from './types.js';\nimport { quoteExtensionName } from './utils.js';\n\n/**\n * Generate CREATE EXTENSION statements for all extensions in the schema.\n *\n * @param ctx - Phase context with schema and capabilities\n * @returns Array of DDL statements, or empty if extensions are unsupported / absent\n */\nexport function generateExtensionsPhase(ctx: PhaseContext): string[] {\n\tconst { schema, caps } = ctx;\n\tif (!schema.extensions || !sup(caps, caps?.supportsDDLExtensions)) {\n\t\treturn [];\n\t}\n\treturn schema.extensions.map(\n\t\t(ext) => `CREATE EXTENSION IF NOT EXISTS ${quoteExtensionName(ext)};`,\n\t);\n}\n","/**\n * DDL Phase: Indexes\n *\n * Generates CREATE INDEX statements for:\n * 1. Explicit indexes defined on each table\n * 2. Auto-generated indexes for FK columns (when fkAutoIndex=true)\n *\n * Auto-indexes are only generated for single-column FKs that do not already\n * have an explicit index, following PostgreSQL best practices for JOIN performance.\n *\n * @module ddl/phases/indexes\n */\n\nimport type { IndexIR } from '@dbsp/types';\nimport { generateCreateIndex } from '../ddl-generator.js';\nimport type { PhaseContext } from './types.js';\n\n/**\n * Generate CREATE INDEX statements for all tables.\n *\n * @param ctx - Phase context\n * @returns Array of DDL statements\n */\nexport function generateIndexesPhase(ctx: PhaseContext): string[] {\n\tconst { tables, schemaName, naming, fkAutoIndex } = ctx;\n\tconst statements: string[] = [];\n\n\tfor (const table of tables) {\n\t\t// Collect explicit index column names to avoid duplicating FK auto-indexes\n\t\tconst explicitIndexColumns = new Set(\n\t\t\ttable.indexes.flatMap((idx) =>\n\t\t\t\tidx.columns.length === 1 ? idx.columns : [],\n\t\t\t),\n\t\t);\n\n\t\t// Explicit indexes\n\t\tfor (const idx of table.indexes) {\n\t\t\tstatements.push(generateCreateIndex(table.name, idx, schemaName, naming));\n\t\t}\n\n\t\t// Auto-generate indexes for single-column FK columns without an explicit index\n\t\tif (fkAutoIndex) {\n\t\t\tfor (const fk of table.foreignKeys) {\n\t\t\t\tconst fkCol = fk.columns[0];\n\t\t\t\tif (\n\t\t\t\t\tfk.columns.length === 1 &&\n\t\t\t\t\tfkCol &&\n\t\t\t\t\t!explicitIndexColumns.has(fkCol)\n\t\t\t\t) {\n\t\t\t\t\tconst autoIdx: IndexIR = {\n\t\t\t\t\t\tname: `idx_${table.name}_${fkCol}`,\n\t\t\t\t\t\tcolumns: [fkCol],\n\t\t\t\t\t\tunique: false,\n\t\t\t\t\t};\n\t\t\t\t\tstatements.push(\n\t\t\t\t\t\tgenerateCreateIndex(table.name, autoIdx, schemaName, naming),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn statements;\n}\n","/**\n * DDL Phase: Row Level Security (RLS)\n *\n * Generates:\n * 1. ALTER TABLE ... ENABLE ROW LEVEL SECURITY (when rlsEnabled=true on table)\n * 2. CREATE POLICY statements for each policy on the table\n *\n * Guarded by the supportsDDLRowLevelSecurity capability flag.\n *\n * @module ddl/phases/rls\n */\n\nimport { generateCreatePolicy } from '../ddl-generator.js';\nimport { type PhaseContext, sup } from './types.js';\nimport { qualifyTableIdent as qualifyTable } from './utils.js';\n\n/**\n * Generate ENABLE ROW LEVEL SECURITY and CREATE POLICY statements.\n *\n * @param ctx - Phase context\n * @returns Array of DDL statements (empty if RLS is unsupported by the dialect)\n */\nexport function generateRlsPhase(ctx: PhaseContext): string[] {\n\tconst { tables, schemaName, naming, caps } = ctx;\n\tif (!sup(caps, caps?.supportsDDLRowLevelSecurity)) {\n\t\treturn [];\n\t}\n\tconst statements: string[] = [];\n\tfor (const table of tables) {\n\t\tif (table.rlsEnabled) {\n\t\t\tconst qualifiedTable = qualifyTable(table.name, schemaName, naming);\n\t\t\tstatements.push(\n\t\t\t\t`ALTER TABLE ${qualifiedTable} ENABLE ROW LEVEL SECURITY;`,\n\t\t\t);\n\t\t}\n\t\tfor (const policy of table.policies ?? []) {\n\t\t\tstatements.push(\n\t\t\t\tgenerateCreatePolicy(table.name, policy, schemaName, naming),\n\t\t\t);\n\t\t}\n\t}\n\treturn statements;\n}\n","/**\n * Migration SQL Generator (DDL-PROV Block 1)\n *\n * Generates ordered SQL statements from a SchemaDiff.\n * Statements are topologically sorted: DROP constraints → DROP objects → CREATE objects → ADD constraints.\n *\n * @module migration-sql\n */\n\nimport type {\n\tCheckConstraintIR,\n\tColumnIR,\n\tDialectCapabilities,\n\tEnumIR,\n\tForeignKeyIR,\n\tIndexIR,\n\tPolicyIR,\n\tSequenceIR,\n\tTableIR,\n} from '@dbsp/types';\nimport { validateIdentifier, validateSqlExpression } from '../validate.js';\nimport {\n\tformatSqlDefault,\n\tquoteCollation,\n\tquoteExtensionName,\n\tquoteIdent,\n\tquoteRoleName,\n\tvalidateEnumLabel,\n\tvalidateIndexMethod,\n} from './phases/utils.js';\nimport type { SchemaChange, SchemaDiff } from './schema-diff.js';\nimport { mapColumnType, mapOnDeleteAction } from './type-mapping.js';\n\n// ── Helpers ─────────────────────────────────────────────────────\n\n// NOTE: quoteIdent (imported from phases/utils) validates + double-quotes identifiers.\n// The former local q() had no validation (bare `\"${name}\"`). All callers now use quoteIdent.\n\n// =============================================================================\n// retro-audit M-5 (SchemaChange.meta discriminated union) — DEFERRED\n//\n// The ~56 `change.meta?.x as ForeignKeyIR / as IndexIR / as ColumnIR` casts\n// below remain untyped by design. A full discriminated union covering all ~25\n// ChangeKind values is too large in scope for this PR and was explicitly listed\n// as deferrable in the audit brief.\n//\n// Tracked in TODO.md: \"[adapter-pgsql] M-5 SchemaChangeMeta discriminated union\".\n//\n// Until that follow-up lands, every NEW SchemaChange producer MUST verify the\n// meta shape at the call site rather than relying on downstream casts.\n// =============================================================================\n\n/** Schema-qualify a table name: \"schema\".\"table\" or just \"table\". */\nfunction qualifyTable(table: string, schemaName?: string): string {\n\treturn schemaName\n\t\t? `${quoteIdent(schemaName, 'schema')}.${quoteIdent(table, 'table')}`\n\t\t: quoteIdent(table, 'table');\n}\n\n// validateEnumLabel is imported from './phases/utils.js' (shared with enum-types.ts)\n\n/** PK constraint name convention. */\nfunction pkName(table: string): string {\n\treturn `pk_${table}`;\n}\n\n/** FK constraint name convention. */\nfunction fkName(table: string, columns: readonly string[]): string {\n\treturn `fk_${table}_${columns.join('_')}`;\n}\n\n/** Index name convention (custom name takes priority). */\nfunction idxName(\n\ttable: string,\n\tcolumns: readonly string[],\n\tcustomName?: string,\n): string {\n\treturn customName ?? `idx_${table}_${columns.join('_')}`;\n}\n\n/** Build a CREATE POLICY SQL statement from a PolicyIR. */\nfunction buildPolicySQL(\n\ttableName: string,\n\tpolicy: PolicyIR,\n\tschemaName?: string,\n): string {\n\tconst policyName = quoteIdent(policy.name, 'alias');\n\tconst qt = qualifyTable(tableName, schemaName);\n\tconst forClause =\n\t\tpolicy.command && policy.command !== 'ALL'\n\t\t\t? ` FOR ${policy.command}`\n\t\t\t: ' FOR ALL';\n\tconst asClause =\n\t\tpolicy.permissive === false ? ' AS RESTRICTIVE' : ' AS PERMISSIVE';\n\t// M-4: role names use quoteRoleName() (allows spaces, blocks injection vectors)\n\t// rather than quoteIdent() (which only allows \\w$ characters).\n\tconst toClause =\n\t\tpolicy.roles && policy.roles.length > 0\n\t\t\t? ` TO ${policy.roles.map((r) => quoteRoleName(r)).join(', ')}`\n\t\t\t: '';\n\tif (policy.using) validateSqlExpression(policy.using, 'USING expression');\n\tif (policy.withCheck)\n\t\tvalidateSqlExpression(policy.withCheck, 'WITH CHECK expression');\n\tconst usingClause = policy.using ? ` USING (${policy.using})` : '';\n\tconst withCheckClause = policy.withCheck\n\t\t? ` WITH CHECK (${policy.withCheck})`\n\t\t: '';\n\treturn `CREATE POLICY ${policyName} ON ${qt}${forClause}${asClause}${toClause}${usingClause}${withCheckClause};`;\n}\n\n/**\n * Build a sequence options clause (shared by CREATE SEQUENCE, ALTER SEQUENCE, and their reverses).\n *\n * @param verb - SQL verb: `'CREATE SEQUENCE'` or `'ALTER SEQUENCE'`\n * @param seqName - Already-quoted and schema-qualified sequence name\n * @param seq - Sequence properties to emit\n * @param includeCycleNoCycle - When true, emits `NO CYCLE` for `seq.cycle === false`\n * (needed by ALTER SEQUENCE; CREATE SEQUENCE omits the clause when cycle is false)\n * @returns Full SQL statement ending with `;`\n */\n/**\n * Build a sequence options clause shared by CREATE SEQUENCE, ALTER SEQUENCE, and their reverses.\n *\n * @param verb - SQL verb: `'CREATE SEQUENCE'` or `'ALTER SEQUENCE'`\n * @param seqName - Already-quoted and schema-qualified sequence name\n * @param seq - Sequence properties to emit\n * @param includeCycleNoCycle - When true (ALTER SEQUENCE), emits `NO CYCLE` for `seq.cycle === false`.\n * When false (CREATE SEQUENCE), only emits `CYCLE` when truthy; no `NO CYCLE` clause.\n * @returns Full SQL statement ending with `;`\n */\nexport function buildSequenceClause(\n\tverb: 'CREATE SEQUENCE' | 'ALTER SEQUENCE',\n\tseqName: string,\n\tseq: Pick<\n\t\tSequenceIR,\n\t\t'startWith' | 'incrementBy' | 'minValue' | 'maxValue' | 'cycle'\n\t>,\n\tincludeCycleNoCycle = false,\n): string {\n\tconst parts: string[] = [`${verb} ${seqName}`];\n\tif (seq.startWith !== undefined) parts.push(`START WITH ${seq.startWith}`);\n\tif (seq.incrementBy !== undefined)\n\t\tparts.push(`INCREMENT BY ${seq.incrementBy}`);\n\tif (seq.minValue !== undefined) parts.push(`MINVALUE ${seq.minValue}`);\n\tif (seq.maxValue !== undefined) parts.push(`MAXVALUE ${seq.maxValue}`);\n\tif (includeCycleNoCycle) {\n\t\t// ALTER SEQUENCE: emit CYCLE or NO CYCLE when the flag is defined\n\t\tif (seq.cycle !== undefined) parts.push(seq.cycle ? 'CYCLE' : 'NO CYCLE');\n\t} else {\n\t\t// CREATE SEQUENCE: only emit CYCLE when truthy; silence NO CYCLE\n\t\tif (seq.cycle) parts.push('CYCLE');\n\t}\n\treturn `${parts.join(' ')};`;\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface MigrationSQLOptions {\n\t/** Schema namespace (default: none — unqualified) */\n\treadonly schemaName?: string;\n\t/** Whether to include destructive changes (drops) */\n\treadonly includeDestructive?: boolean;\n\t/** Automatically create indexes on FK columns for new tables (default: true) */\n\treadonly fkAutoIndex?: boolean;\n\t/** Dialect capabilities — migration SQL for unsupported features will be filtered */\n\treadonly dialectCapabilities?: DialectCapabilities;\n}\n\n// ============================================================================\n// Capability Helpers\n// ============================================================================\n\n/** Check if a change kind is supported by the dialect capabilities */\nfunction isChangeSupported(kind: string, caps: DialectCapabilities): boolean {\n\tswitch (kind) {\n\t\tcase 'create_enum':\n\t\tcase 'drop_enum':\n\t\tcase 'alter_enum_add_value':\n\t\t\treturn caps.supportsDDLEnumTypes === true;\n\t\tcase 'create_extension':\n\t\tcase 'drop_extension':\n\t\t\treturn caps.supportsDDLExtensions === true;\n\t\tcase 'create_sequence':\n\t\tcase 'drop_sequence':\n\t\tcase 'alter_sequence':\n\t\t\treturn caps.supportsDDLSequences === true;\n\t\tcase 'add_check_constraint':\n\t\tcase 'drop_check_constraint':\n\t\t\treturn caps.supportsDDLCheckConstraints === true;\n\t\tcase 'add_comment':\n\t\tcase 'drop_comment':\n\t\t\treturn caps.supportsDDLComments === true;\n\t\tcase 'alter_column_collation':\n\t\t\treturn caps.supportsDDLCollation === true;\n\t\tcase 'alter_column_identity':\n\t\t\treturn caps.supportsDDLIdentityColumns === true;\n\t\tcase 'enable_rls':\n\t\tcase 'disable_rls':\n\t\tcase 'create_policy':\n\t\tcase 'drop_policy':\n\t\t\treturn caps.supportsDDLRowLevelSecurity === true;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\n// ============================================================================\n// SQL Generation\n// ============================================================================\n\n/**\n * Generate ordered SQL statements from a SchemaDiff.\n *\n * Topological order:\n * 0. DROP FK/CHECK constraints (must drop before referenced tables)\n * 1. DROP indexes\n * 2. DROP columns\n * 3. DROP primary keys\n * 4. DROP tables, DROP ENUMs\n * 5. CREATE ENUMs (must exist before tables that use them)\n * 6. CREATE tables\n * 7. ADD columns\n * 8. ALTER columns (type, nullable, default)\n * 9. ADD primary keys\n * 10. ADD FK constraints (must add after referenced tables exist)\n * 11. ALTER FK (drop + re-add)\n * 12. CREATE indexes\n * 13. ADD CHECK constraints\n * 14. ALTER ENUM ADD VALUE (must be last — has transaction visibility caveats in PG)\n * 15. COMMENT ON TABLE / COLUMN (very last)\n */\nexport function generateMigrationSQL(\n\tdiff: SchemaDiff,\n\toptions?: MigrationSQLOptions,\n): readonly string[] {\n\tconst schemaName = options?.schemaName;\n\tconst includeDestructive = options?.includeDestructive ?? true;\n\n\t// Filter out destructive changes if not included\n\tconst filteredChanges = includeDestructive\n\t\t? diff.changes\n\t\t: diff.changes.filter((c) => !c.destructive);\n\n\tconst caps = options?.dialectCapabilities;\n\n\t// Filter out changes for unsupported DDL features\n\tconst changes = caps\n\t\t? filteredChanges.filter((c) => isChangeSupported(c.kind, caps))\n\t\t: filteredChanges;\n\n\t// Group changes by phase for topological ordering\n\tconst phases: SchemaChange[][] = [\n\t\t[], // 0: drop FK, drop CHECK\n\t\t[], // 1: drop index\n\t\t[], // 2: drop column\n\t\t[], // 3: drop PK\n\t\t[], // 4: drop table, drop ENUM\n\t\t[], // 5: create ENUM\n\t\t[], // 6: create table\n\t\t[], // 7: add column\n\t\t[], // 8: alter column\n\t\t[], // 9: add PK\n\t\t[], // 10: add FK\n\t\t[], // 11: alter FK (drop + re-add)\n\t\t[], // 12: create index\n\t\t[], // 13: add CHECK constraint\n\t\t[], // 14: alter ENUM add value (must be after CREATE TABLE, outside transaction)\n\t\t[], // 15: COMMENT ON TABLE / COLUMN\n\t\t[], // 16: VALIDATE CONSTRAINT (after FK/CHECK added with NOT VALID)\n\t\t[], // 17: ENABLE/DISABLE ROW LEVEL SECURITY\n\t\t[], // 18: CREATE/DROP POLICY\n\t];\n\n\tfor (const change of changes) {\n\t\tconst phase = getPhase(change.kind);\n\t\tphases[phase]!.push(change);\n\t}\n\n\t// Generate SQL in phase order\n\tconst statements: string[] = [];\n\tfor (const phase of phases) {\n\t\tfor (const change of phase) {\n\t\t\tconst sql = changeToUpSQL(change, schemaName);\n\t\t\tif (sql) statements.push(sql);\n\t\t}\n\t}\n\n\t// FK auto-indexes for new tables (single-column FKs without explicit index)\n\tif (options?.fkAutoIndex !== false) {\n\t\tfor (const change of changes) {\n\t\t\tif (change.kind === 'create_table') {\n\t\t\t\tconst table = change.meta?.table as TableIR | undefined;\n\t\t\t\tif (!table) continue;\n\t\t\t\tconst explicitIndexColumns = new Set(\n\t\t\t\t\ttable.indexes.flatMap((idx) =>\n\t\t\t\t\t\tidx.columns.length === 1 ? idx.columns : [],\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tfor (const fk of table.foreignKeys) {\n\t\t\t\t\tconst fkCol = fk.columns[0];\n\t\t\t\t\tif (\n\t\t\t\t\t\tfk.columns.length === 1 &&\n\t\t\t\t\t\tfkCol &&\n\t\t\t\t\t\t!explicitIndexColumns.has(fkCol)\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst indexName = quoteIdent(idxName(table.name, [fkCol]), 'alias');\n\t\t\t\t\t\tstatements.push(\n\t\t\t\t\t\t\t`CREATE INDEX IF NOT EXISTS ${indexName} ON ${qualifyTable(table.name, schemaName)} (${quoteIdent(fkCol, 'alias')});`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn statements;\n}\n\n// ============================================================================\n// Phase Mapping (Topological Order)\n// ============================================================================\n\nfunction getPhase(kind: SchemaChange['kind']): number {\n\tswitch (kind) {\n\t\tcase 'drop_foreign_key':\n\t\tcase 'drop_check_constraint':\n\t\t\treturn 0;\n\t\tcase 'drop_index':\n\t\t\treturn 1;\n\t\tcase 'drop_column':\n\t\t\treturn 2;\n\t\tcase 'drop_primary_key':\n\t\t\treturn 3;\n\t\tcase 'drop_table':\n\t\tcase 'drop_enum':\n\t\tcase 'drop_extension':\n\t\tcase 'drop_sequence':\n\t\t\treturn 4;\n\t\tcase 'create_enum':\n\t\tcase 'create_extension':\n\t\tcase 'create_sequence':\n\t\t\treturn 5;\n\t\tcase 'alter_sequence':\n\t\t\treturn 8;\n\t\tcase 'create_table':\n\t\t\treturn 6;\n\t\tcase 'add_column':\n\t\t\treturn 7;\n\t\tcase 'alter_column_type':\n\t\tcase 'alter_column_nullable':\n\t\tcase 'alter_column_default':\n\t\tcase 'alter_column_collation':\n\t\tcase 'alter_column_identity':\n\t\t\treturn 8;\n\t\tcase 'add_primary_key':\n\t\t\treturn 9;\n\t\tcase 'add_foreign_key':\n\t\t\treturn 10;\n\t\tcase 'alter_foreign_key':\n\t\t\treturn 11;\n\t\tcase 'create_index':\n\t\t\treturn 12;\n\t\tcase 'add_check_constraint':\n\t\t\treturn 13;\n\t\tcase 'alter_enum_add_value':\n\t\t\treturn 14;\n\t\tcase 'add_comment':\n\t\tcase 'drop_comment':\n\t\t\treturn 15;\n\t\tcase 'validate_constraint':\n\t\t\t// Runs after add_foreign_key / add_check_constraint so the constraint exists\n\t\t\treturn 16;\n\t\tcase 'enable_rls':\n\t\tcase 'disable_rls':\n\t\t\t// After table is created / indexes set up\n\t\t\treturn 17;\n\t\tcase 'create_policy':\n\t\tcase 'drop_policy':\n\t\t\t// After RLS is enabled\n\t\t\treturn 18;\n\t}\n}\n\n// ============================================================================\n// SQL Generators per ChangeKind\n// ============================================================================\n\n// ============================================================================\n// UP SQL Handlers (one function per change kind)\n// ============================================================================\n\nfunction upAddColumn(\n\tchange: SchemaChange,\n\tschemaName?: string,\n): string | undefined {\n\tconst col = change.meta?.column as ColumnIR | undefined;\n\tif (!col) return undefined;\n\tconst typeName = mapColumnType(col);\n\tconst notNull = !col.nullable && !col.autoIncrement ? ' NOT NULL' : '';\n\tconst def =\n\t\tcol.default !== undefined ? ` DEFAULT ${formatDefault(col.default)}` : '';\n\tconst unique = col.unique ? ' UNIQUE' : '';\n\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} ADD COLUMN ${quoteIdent(col.name, 'alias')} ${typeName}${notNull}${def}${unique};`;\n}\n\nfunction upAlterColumnType(change: SchemaChange, schemaName?: string): string {\n\tconst col = change.meta?.column as ColumnIR | undefined;\n\tconst toType = col ? mapColumnType(col) : String(change.meta?.toType);\n\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} ALTER COLUMN ${quoteIdent(change.column!, 'alias')} TYPE ${toType};`;\n}\n\nfunction upAlterColumnNullable(\n\tchange: SchemaChange,\n\tschemaName?: string,\n): string {\n\tconst nullable = change.meta?.nullable as boolean;\n\tconst action = nullable ? 'DROP NOT NULL' : 'SET NOT NULL';\n\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} ALTER COLUMN ${quoteIdent(change.column!, 'alias')} ${action};`;\n}\n\nfunction upAlterColumnDefault(\n\tchange: SchemaChange,\n\tschemaName?: string,\n): string {\n\tconst def = change.meta?.default;\n\tif (def === undefined || def === null) {\n\t\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} ALTER COLUMN ${quoteIdent(change.column!, 'alias')} DROP DEFAULT;`;\n\t}\n\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} ALTER COLUMN ${quoteIdent(change.column!, 'alias')} SET DEFAULT ${formatDefault(def)};`;\n}\n\nfunction upAddPrimaryKey(change: SchemaChange, schemaName?: string): string {\n\tconst columns = change.meta?.columns as string[];\n\tconst pkCols = columns.map((n) => quoteIdent(n, 'alias')).join(', ');\n\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} ADD CONSTRAINT ${quoteIdent(pkName(change.table), 'alias')} PRIMARY KEY (${pkCols});`;\n}\n\nfunction upDropForeignKey(\n\tchange: SchemaChange,\n\tschemaName?: string,\n): string | undefined {\n\tconst fk = change.meta?.fk as ForeignKeyIR;\n\tif (!fk) return undefined;\n\tconst constraintName = quoteIdent(fkName(change.table, fk.columns), 'alias');\n\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} DROP CONSTRAINT IF EXISTS ${constraintName};`;\n}\n\nfunction upAlterForeignKey(\n\tchange: SchemaChange,\n\tschemaName?: string,\n): string | undefined {\n\t// Drop + re-add with new onDelete\n\tconst fk = change.meta?.fk as ForeignKeyIR;\n\tif (!fk) return undefined;\n\tconst constraintName = quoteIdent(fkName(change.table, fk.columns), 'alias');\n\tconst drop = `ALTER TABLE ${qualifyTable(change.table, schemaName)} DROP CONSTRAINT IF EXISTS ${constraintName};`;\n\tconst add = generateAddFKSQL(change.table, fk, schemaName);\n\treturn `${drop}\\n${add}`;\n}\n\nfunction upCreateIndex(\n\tchange: SchemaChange,\n\tschemaName?: string,\n): string | undefined {\n\tconst idx = change.meta?.index as IndexIR;\n\tif (!idx) return undefined;\n\tconst indexName = quoteIdent(\n\t\tidxName(change.table, idx.columns, idx.name),\n\t\t'alias',\n\t);\n\tconst unique = idx.unique ? 'UNIQUE ' : '';\n\t// S-1: validate index method against allowlist before interpolation into unquoted USING clause\n\tif (idx.method) validateIndexMethod(idx.method, 'index method');\n\tconst method = idx.method ? ` USING ${idx.method}` : '';\n\n\t// Build column list: expressions first (validated), then named columns with optional opclass\n\t// S-1: validate each expression and opclass before interpolation\n\tconst colParts: string[] = [\n\t\t...(idx.expressions ?? []).map((expr) => {\n\t\t\tvalidateSqlExpression(expr, 'index expression');\n\t\t\treturn expr;\n\t\t}),\n\t\t...idx.columns.map((col) => {\n\t\t\tconst opclass = idx.opclass?.[col] ?? '';\n\t\t\tif (opclass) validateIdentifier(opclass, 'alias');\n\t\t\treturn `${quoteIdent(col, 'alias')}${opclass ? ` ${opclass}` : ''}`;\n\t\t}),\n\t];\n\tconst cols = colParts.join(', ');\n\n\tconst include =\n\t\tidx.include && idx.include.length > 0\n\t\t\t? ` INCLUDE (${idx.include.map((n) => quoteIdent(n, 'alias')).join(', ')})`\n\t\t\t: '';\n\n\t// S-1: validate WITH storage parameter keys (values are numeric literals from IR)\n\tconst withParams =\n\t\tidx.with && Object.keys(idx.with).length > 0\n\t\t\t? ` WITH (${Object.entries(idx.with)\n\t\t\t\t\t.map(([k, v]) => {\n\t\t\t\t\t\tvalidateIdentifier(k, 'alias');\n\t\t\t\t\t\treturn `${k} = ${v}`;\n\t\t\t\t\t})\n\t\t\t\t\t.join(', ')})`\n\t\t\t: '';\n\n\t// S-1: validate WHERE predicate expression before interpolation\n\tif (idx.where) validateSqlExpression(idx.where, 'index WHERE predicate');\n\tconst where = idx.where ? ` WHERE ${idx.where}` : '';\n\n\treturn `CREATE ${unique}INDEX IF NOT EXISTS ${indexName} ON ${qualifyTable(change.table, schemaName)}${method} (${cols})${include}${withParams}${where};`;\n}\n\nfunction upDropIndex(\n\tchange: SchemaChange,\n\tschemaName?: string,\n): string | undefined {\n\tconst idx = change.meta?.index as IndexIR;\n\tif (!idx) return undefined;\n\tconst indexName = quoteIdent(\n\t\tidxName(change.table, idx.columns, idx.name),\n\t\t'alias',\n\t);\n\tconst schemaPrefix = schemaName ? `${quoteIdent(schemaName, 'alias')}.` : '';\n\treturn `DROP INDEX IF EXISTS ${schemaPrefix}${indexName};`;\n}\n\nfunction upAddCheckConstraint(\n\tchange: SchemaChange,\n\tschemaName?: string,\n): string | undefined {\n\tconst check = change.meta?.check as CheckConstraintIR;\n\tif (!check) return undefined;\n\tconst notValid = check.notValid ? ' NOT VALID' : '';\n\tvalidateSqlExpression(\n\t\tcheck.expression,\n\t\t'migration check constraint expression',\n\t);\n\treturn (\n\t\t'DO $$ BEGIN ALTER TABLE ' +\n\t\tqualifyTable(change.table, schemaName) +\n\t\t' ADD CONSTRAINT ' +\n\t\tquoteIdent(check.name, 'alias') +\n\t\t' ' +\n\t\tcheck.expression +\n\t\tnotValid +\n\t\t'; EXCEPTION WHEN duplicate_object THEN NULL; END $$;'\n\t);\n}\n\nfunction upValidateConstraint(\n\tchange: SchemaChange,\n\tschemaName?: string,\n): string | undefined {\n\tconst fk = change.meta?.fk as ForeignKeyIR | undefined;\n\tconst check = change.meta?.check as CheckConstraintIR | undefined;\n\tconst constraintName = fk\n\t\t? quoteIdent(fkName(change.table, fk.columns), 'alias')\n\t\t: check\n\t\t\t? quoteIdent(check.name, 'alias')\n\t\t\t: undefined;\n\tif (!constraintName) return undefined;\n\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} VALIDATE CONSTRAINT ${constraintName};`;\n}\n\nfunction upCreateEnum(\n\tchange: SchemaChange,\n\tschemaName?: string,\n): string | undefined {\n\tconst enumDef = change.meta?.enum as EnumIR;\n\tif (!enumDef) return undefined;\n\tconst enumName = schemaName\n\t\t? `${quoteIdent(schemaName, 'alias')}.${quoteIdent(enumDef.name, 'alias')}`\n\t\t: quoteIdent(enumDef.name, 'alias');\n\t// M-2: validate each enum value against NUL/control-char injection before emission\n\tconst values = enumDef.values\n\t\t.map((v) => {\n\t\t\tvalidateEnumLabel(v, 'enum value');\n\t\t\treturn `'${v.replace(/'/g, \"''\")}'`;\n\t\t})\n\t\t.join(', ');\n\treturn `CREATE TYPE ${enumName} AS ENUM (${values});`;\n}\n\nfunction upAlterEnumAddValue(\n\tchange: SchemaChange,\n\tschemaName?: string,\n): string | undefined {\n\tconst enumDef = change.meta?.enum as EnumIR;\n\tconst value = change.meta?.value as string;\n\tconst after = change.meta?.after as string | undefined;\n\tif (!enumDef || !value) return undefined;\n\t// M-2: enum name validated via quoteIdent; enum labels validated against control-char injection\n\tconst enumName = schemaName\n\t\t? `${quoteIdent(schemaName, 'schema')}.${quoteIdent(enumDef.name, 'table')}`\n\t\t: quoteIdent(enumDef.name, 'table');\n\tvalidateEnumLabel(value, 'enum value');\n\tif (after !== undefined) validateEnumLabel(after, 'enum AFTER position');\n\tconst escaped = value.replace(/'/g, \"''\");\n\tconst position = after ? ` AFTER '${after.replace(/'/g, \"''\")}'` : '';\n\treturn `ALTER TYPE ${enumName} ADD VALUE IF NOT EXISTS '${escaped}'${position};`;\n}\n\nfunction upDropEnum(\n\tchange: SchemaChange,\n\tschemaName?: string,\n): string | undefined {\n\tconst enumDef = change.meta?.enum as EnumIR;\n\tif (!enumDef) return undefined;\n\tconst enumName = schemaName\n\t\t? `${quoteIdent(schemaName, 'alias')}.${quoteIdent(enumDef.name, 'alias')}`\n\t\t: quoteIdent(enumDef.name, 'alias');\n\t// Before dropping the type, cast any referencing columns to text\n\t// to prevent \"cannot drop type: still referenced\" errors.\n\tconst refs = change.meta?.referencingColumns as\n\t\t| Array<{ table: string; column: string }>\n\t\t| undefined;\n\tconst alterStatements =\n\t\trefs && refs.length > 0\n\t\t\t? refs.map(\n\t\t\t\t\t(ref) =>\n\t\t\t\t\t\t`ALTER TABLE ${qualifyTable(ref.table, schemaName)} ALTER COLUMN ${quoteIdent(ref.column, 'alias')} TYPE text;`,\n\t\t\t\t)\n\t\t\t: [];\n\treturn [...alterStatements, `DROP TYPE IF EXISTS ${enumName} CASCADE;`].join(\n\t\t'\\n',\n\t);\n}\n\nfunction upAlterColumnCollation(\n\tchange: SchemaChange,\n\tschemaName?: string,\n): string | undefined {\n\tconst col = change.meta?.column as ColumnIR;\n\tif (!col) return undefined;\n\t// S-2: validate collation name before quoting — uses quoteCollation which\n\t// accepts locale strings like `en_US.utf8`, `en-US-x-icu`, `C.UTF-8`\n\t// that contain dots/hyphens rejected by the standard identifier validator.\n\tconst collation = col.collation\n\t\t? ` COLLATE ${quoteCollation(col.collation)}`\n\t\t: '';\n\tconst typeName = mapColumnType(col);\n\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} ALTER COLUMN ${quoteIdent(change.column!, 'alias')} TYPE ${typeName}${collation};`;\n}\n\nfunction upAlterColumnIdentity(\n\tchange: SchemaChange,\n\tschemaName?: string,\n): string | undefined {\n\tconst col = change.meta?.column as ColumnIR;\n\tconst prevIdentity = change.meta?.previousIdentity as string | undefined;\n\tif (!col) return undefined;\n\tconst table = qualifyTable(change.table, schemaName);\n\tconst column = quoteIdent(change.column!, 'alias');\n\tif (!col.identity && prevIdentity) {\n\t\treturn `ALTER TABLE ${table} ALTER COLUMN ${column} DROP IDENTITY IF EXISTS;`;\n\t}\n\tif (col.identity && !prevIdentity) {\n\t\tconst gen = col.identity === 'always' ? 'ALWAYS' : 'BY DEFAULT';\n\t\treturn `ALTER TABLE ${table} ALTER COLUMN ${column} ADD GENERATED ${gen} AS IDENTITY;`;\n\t}\n\t// Change from one identity type to another\n\tconst gen = col.identity === 'always' ? 'ALWAYS' : 'BY DEFAULT';\n\treturn `ALTER TABLE ${table} ALTER COLUMN ${column} SET GENERATED ${gen};`;\n}\n\nfunction upAddComment(change: SchemaChange, schemaName?: string): string {\n\tconst comment = change.meta?.comment as string;\n\tconst target = change.meta?.target as string;\n\tconst escaped = comment.replace(/'/g, \"''\");\n\tif (target === 'table') {\n\t\treturn `COMMENT ON TABLE ${qualifyTable(change.table, schemaName)} IS '${escaped}';`;\n\t}\n\treturn `COMMENT ON COLUMN ${qualifyTable(change.table, schemaName)}.${quoteIdent(change.column!, 'alias')} IS '${escaped}';`;\n}\n\nfunction upSequenceName(\n\tschemaName: string | undefined,\n\tseq: SequenceIR,\n): string {\n\treturn schemaName\n\t\t? `${quoteIdent(schemaName, 'alias')}.${quoteIdent(seq.name, 'alias')}`\n\t\t: quoteIdent(seq.name, 'alias');\n}\n\n// ============================================================================\n// SQL Generators per ChangeKind\n// ============================================================================\n\nfunction changeToUpSQL(\n\tchange: SchemaChange,\n\tschemaName?: string,\n): string | undefined {\n\tswitch (change.kind) {\n\t\tcase 'create_table': {\n\t\t\tconst table = change.meta?.table as TableIR | undefined;\n\t\t\treturn table ? generateCreateTableSQL(table, schemaName) : undefined;\n\t\t}\n\t\tcase 'drop_table':\n\t\t\treturn `DROP TABLE IF EXISTS ${qualifyTable(change.table, schemaName)} CASCADE;`;\n\t\tcase 'add_column':\n\t\t\treturn upAddColumn(change, schemaName);\n\t\tcase 'drop_column':\n\t\t\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} DROP COLUMN ${quoteIdent(change.column!, 'alias')} CASCADE;`;\n\t\tcase 'alter_column_type':\n\t\t\treturn upAlterColumnType(change, schemaName);\n\t\tcase 'alter_column_nullable':\n\t\t\treturn upAlterColumnNullable(change, schemaName);\n\t\tcase 'alter_column_default':\n\t\t\treturn upAlterColumnDefault(change, schemaName);\n\t\tcase 'add_primary_key':\n\t\t\treturn upAddPrimaryKey(change, schemaName);\n\t\tcase 'drop_primary_key':\n\t\t\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} DROP CONSTRAINT IF EXISTS ${quoteIdent(pkName(change.table), 'alias')} CASCADE;`;\n\t\tcase 'add_foreign_key': {\n\t\t\tconst fk = change.meta?.fk as ForeignKeyIR;\n\t\t\treturn fk ? generateAddFKSQL(change.table, fk, schemaName) : undefined;\n\t\t}\n\t\tcase 'drop_foreign_key':\n\t\t\treturn upDropForeignKey(change, schemaName);\n\t\tcase 'alter_foreign_key':\n\t\t\treturn upAlterForeignKey(change, schemaName);\n\t\tcase 'create_index':\n\t\t\treturn upCreateIndex(change, schemaName);\n\t\tcase 'drop_index':\n\t\t\treturn upDropIndex(change, schemaName);\n\t\tcase 'add_check_constraint':\n\t\t\treturn upAddCheckConstraint(change, schemaName);\n\t\tcase 'validate_constraint':\n\t\t\treturn upValidateConstraint(change, schemaName);\n\t\tcase 'drop_check_constraint': {\n\t\t\tconst check = change.meta?.check as CheckConstraintIR;\n\t\t\treturn check\n\t\t\t\t? `ALTER TABLE ${qualifyTable(change.table, schemaName)} DROP CONSTRAINT IF EXISTS ${quoteIdent(check.name, 'alias')};`\n\t\t\t\t: undefined;\n\t\t}\n\t\tcase 'create_enum':\n\t\t\treturn upCreateEnum(change, schemaName);\n\t\tcase 'alter_enum_add_value':\n\t\t\treturn upAlterEnumAddValue(change, schemaName);\n\t\tcase 'drop_enum':\n\t\t\treturn upDropEnum(change, schemaName);\n\t\tcase 'alter_column_collation':\n\t\t\treturn upAlterColumnCollation(change, schemaName);\n\t\tcase 'alter_column_identity':\n\t\t\treturn upAlterColumnIdentity(change, schemaName);\n\t\tcase 'add_comment':\n\t\t\treturn upAddComment(change, schemaName);\n\t\tcase 'drop_comment': {\n\t\t\tconst target = change.meta?.target as string;\n\t\t\tif (target === 'table') {\n\t\t\t\treturn `COMMENT ON TABLE ${qualifyTable(change.table, schemaName)} IS NULL;`;\n\t\t\t}\n\t\t\treturn `COMMENT ON COLUMN ${qualifyTable(change.table, schemaName)}.${quoteIdent(change.column!, 'alias')} IS NULL;`;\n\t\t}\n\t\tcase 'create_extension': {\n\t\t\tconst ext = change.meta?.extension as string;\n\t\t\tif (ext == null) return undefined;\n\t\t\treturn `CREATE EXTENSION IF NOT EXISTS ${quoteExtensionName(ext)};`;\n\t\t}\n\t\tcase 'drop_extension': {\n\t\t\tconst ext = change.meta?.extension as string;\n\t\t\tif (ext == null) return undefined;\n\t\t\treturn `DROP EXTENSION IF EXISTS ${quoteExtensionName(ext)} CASCADE;`;\n\t\t}\n\t\tcase 'create_sequence': {\n\t\t\tconst seq = change.meta?.sequence as SequenceIR;\n\t\t\treturn seq\n\t\t\t\t? buildSequenceClause(\n\t\t\t\t\t\t'CREATE SEQUENCE',\n\t\t\t\t\t\tupSequenceName(schemaName, seq),\n\t\t\t\t\t\tseq,\n\t\t\t\t\t)\n\t\t\t\t: undefined;\n\t\t}\n\t\tcase 'alter_sequence': {\n\t\t\tconst seq = change.meta?.sequence as SequenceIR;\n\t\t\treturn seq\n\t\t\t\t? buildSequenceClause(\n\t\t\t\t\t\t'ALTER SEQUENCE',\n\t\t\t\t\t\tupSequenceName(schemaName, seq),\n\t\t\t\t\t\tseq,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t)\n\t\t\t\t: undefined;\n\t\t}\n\t\tcase 'drop_sequence': {\n\t\t\tconst seq = change.meta?.sequence as SequenceIR;\n\t\t\treturn seq\n\t\t\t\t? `DROP SEQUENCE IF EXISTS ${upSequenceName(schemaName, seq)} CASCADE;`\n\t\t\t\t: undefined;\n\t\t}\n\t\tcase 'enable_rls':\n\t\t\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} ENABLE ROW LEVEL SECURITY;`;\n\t\tcase 'disable_rls':\n\t\t\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} DISABLE ROW LEVEL SECURITY;`;\n\t\tcase 'create_policy': {\n\t\t\tconst policy = change.meta?.policy as PolicyIR;\n\t\t\treturn policy\n\t\t\t\t? buildPolicySQL(change.table, policy, schemaName)\n\t\t\t\t: undefined;\n\t\t}\n\t\tcase 'drop_policy': {\n\t\t\tconst policy = change.meta?.policy as PolicyIR;\n\t\t\treturn policy\n\t\t\t\t? `DROP POLICY IF EXISTS ${quoteIdent(policy.name, 'alias')} ON ${qualifyTable(change.table, schemaName)};`\n\t\t\t\t: undefined;\n\t\t}\n\t}\n}\n\n// ============================================================================\n// DOWN SQL Generators per ChangeKind\n// ============================================================================\n\nfunction changeToDownSQL(\n\tchange: SchemaChange,\n\tschemaName?: string,\n): string | undefined {\n\tswitch (change.kind) {\n\t\tcase 'create_table':\n\t\t\treturn `DROP TABLE IF EXISTS ${qualifyTable(change.table, schemaName)} CASCADE;`;\n\n\t\tcase 'drop_table':\n\t\t\treturn `-- WARNING: Cannot reverse drop_table \"${change.table}\" -- table data was lost`;\n\n\t\tcase 'add_column':\n\t\t\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} DROP COLUMN ${quoteIdent(change.column!, 'alias')} CASCADE;`;\n\n\t\tcase 'drop_column':\n\t\t\treturn `-- WARNING: Cannot reverse drop_column \"${change.table}\".\"${change.column}\" -- column data was lost`;\n\n\t\tcase 'alter_column_type': {\n\t\t\tconst fromType = change.meta?.fromType as string | undefined;\n\t\t\tif (!fromType) {\n\t\t\t\treturn `-- WARNING: Cannot reverse alter_column_type \"${change.table}\".\"${change.column}\" -- missing migration metadata`;\n\t\t\t}\n\t\t\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} ALTER COLUMN ${quoteIdent(change.column!, 'alias')} TYPE ${fromType};`;\n\t\t}\n\n\t\tcase 'alter_column_nullable': {\n\t\t\tconst oldNullable = change.meta?.oldNullable as boolean | undefined;\n\t\t\tif (oldNullable === undefined) {\n\t\t\t\treturn `-- WARNING: Cannot reverse alter_column_nullable \"${change.table}\".\"${change.column}\" -- missing migration metadata`;\n\t\t\t}\n\t\t\t// Reverse: restore old nullable state\n\t\t\tconst action = oldNullable ? 'DROP NOT NULL' : 'SET NOT NULL';\n\t\t\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} ALTER COLUMN ${quoteIdent(change.column!, 'alias')} ${action};`;\n\t\t}\n\n\t\tcase 'alter_column_default': {\n\t\t\tconst oldDefault = change.meta?.oldDefault;\n\t\t\tif (oldDefault === undefined) {\n\t\t\t\treturn `-- WARNING: Cannot reverse alter_column_default \"${change.table}\".\"${change.column}\" -- missing migration metadata`;\n\t\t\t}\n\t\t\tif (oldDefault === null) {\n\t\t\t\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} ALTER COLUMN ${quoteIdent(change.column!, 'alias')} DROP DEFAULT;`;\n\t\t\t}\n\t\t\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} ALTER COLUMN ${quoteIdent(change.column!, 'alias')} SET DEFAULT ${formatDefault(oldDefault)};`;\n\t\t}\n\n\t\tcase 'add_primary_key': {\n\t\t\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} DROP CONSTRAINT IF EXISTS ${quoteIdent(pkName(change.table), 'alias')} CASCADE;`;\n\t\t}\n\n\t\tcase 'drop_primary_key':\n\t\t\treturn `-- WARNING: Cannot reverse drop_primary_key \"${change.table}\" -- columns unknown`;\n\n\t\tcase 'add_foreign_key': {\n\t\t\tconst fk = change.meta?.fk as ForeignKeyIR | undefined;\n\t\t\tif (!fk) return undefined;\n\t\t\tconst constraintName = quoteIdent(\n\t\t\t\tfkName(change.table, fk.columns),\n\t\t\t\t'alias',\n\t\t\t);\n\t\t\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} DROP CONSTRAINT IF EXISTS ${constraintName} CASCADE;`;\n\t\t}\n\n\t\tcase 'drop_foreign_key':\n\t\t\treturn `-- WARNING: Cannot reverse drop_foreign_key \"${change.table}\" -- FK definition was lost`;\n\n\t\tcase 'alter_foreign_key': {\n\t\t\tconst oldFk = change.meta?.oldFk as ForeignKeyIR | undefined;\n\t\t\tif (!oldFk) {\n\t\t\t\treturn `-- WARNING: Cannot reverse alter_foreign_key \"${change.table}\" -- missing migration metadata`;\n\t\t\t}\n\t\t\tconst fk = change.meta?.fk as ForeignKeyIR;\n\t\t\tconst constraintName = quoteIdent(\n\t\t\t\tfkName(change.table, fk.columns),\n\t\t\t\t'alias',\n\t\t\t);\n\t\t\tconst drop = `ALTER TABLE ${qualifyTable(change.table, schemaName)} DROP CONSTRAINT IF EXISTS ${constraintName};`;\n\t\t\tconst add = generateAddFKSQL(change.table, oldFk, schemaName);\n\t\t\treturn `${drop}\\n${add}`;\n\t\t}\n\n\t\tcase 'create_index': {\n\t\t\tconst idx = change.meta?.index as IndexIR | undefined;\n\t\t\tif (!idx) return undefined;\n\t\t\tconst indexName = quoteIdent(\n\t\t\t\tidxName(change.table, idx.columns, idx.name),\n\t\t\t\t'alias',\n\t\t\t);\n\t\t\tconst schemaPrefix = schemaName\n\t\t\t\t? `${quoteIdent(schemaName, 'alias')}.`\n\t\t\t\t: '';\n\t\t\treturn `DROP INDEX IF EXISTS ${schemaPrefix}${indexName};`;\n\t\t}\n\n\t\tcase 'drop_index':\n\t\t\treturn `-- WARNING: Cannot reverse drop_index \"${change.table}\" -- index definition was lost`;\n\n\t\tcase 'add_check_constraint': {\n\t\t\tconst check = change.meta?.check as CheckConstraintIR | undefined;\n\t\t\tif (!check) return undefined;\n\t\t\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} DROP CONSTRAINT IF EXISTS ${quoteIdent(check.name, 'alias')};`;\n\t\t}\n\n\t\tcase 'drop_check_constraint': {\n\t\t\tconst check = change.meta?.check as CheckConstraintIR | undefined;\n\t\t\tif (!check) return undefined;\n\t\t\tvalidateSqlExpression(\n\t\t\t\tcheck.expression,\n\t\t\t\t'migration check constraint (down)',\n\t\t\t);\n\t\t\treturn (\n\t\t\t\t'DO $$ BEGIN ALTER TABLE ' +\n\t\t\t\tqualifyTable(change.table, schemaName) +\n\t\t\t\t' ADD CONSTRAINT ' +\n\t\t\t\tquoteIdent(check.name, 'alias') +\n\t\t\t\t' ' +\n\t\t\t\tcheck.expression +\n\t\t\t\t'; EXCEPTION WHEN duplicate_object THEN NULL; END $$;'\n\t\t\t);\n\t\t}\n\n\t\tcase 'create_enum': {\n\t\t\t// DOWN: drop the type that was created\n\t\t\tconst enumDef = change.meta?.enum as EnumIR | undefined;\n\t\t\tif (!enumDef) return undefined;\n\t\t\tconst enumName = schemaName\n\t\t\t\t? `${quoteIdent(schemaName, 'alias')}.${quoteIdent(enumDef.name, 'alias')}`\n\t\t\t\t: quoteIdent(enumDef.name, 'alias');\n\t\t\treturn `DROP TYPE IF EXISTS ${enumName} CASCADE;`;\n\t\t}\n\n\t\tcase 'drop_enum': {\n\t\t\t// DOWN: recreate the type that was dropped\n\t\t\tconst enumDef = change.meta?.enum as EnumIR | undefined;\n\t\t\tif (!enumDef) return undefined;\n\t\t\tconst enumName = schemaName\n\t\t\t\t? `${quoteIdent(schemaName, 'alias')}.${quoteIdent(enumDef.name, 'alias')}`\n\t\t\t\t: quoteIdent(enumDef.name, 'alias');\n\t\t\tconst values = enumDef.values\n\t\t\t\t.map((v) => `'${v.replace(/'/g, \"''\")}'`)\n\t\t\t\t.join(', ');\n\t\t\treturn `CREATE TYPE ${enumName} AS ENUM (${values});`;\n\t\t}\n\n\t\tcase 'alter_enum_add_value':\n\t\t\t// DOWN: ALTER TYPE ADD VALUE cannot be reversed in PostgreSQL\n\t\t\treturn `-- ALTER TYPE ADD VALUE cannot be reversed in PostgreSQL`;\n\n\t\tcase 'alter_column_collation': {\n\t\t\t// DOWN: restore previous collation — stored in db state, not in meta; emit warning\n\t\t\treturn `-- WARNING: Cannot reverse alter_column_collation \"${change.table}\".\"${change.column}\" -- previous collation unknown`;\n\t\t}\n\n\t\tcase 'alter_column_identity': {\n\t\t\tconst col = change.meta?.column as ColumnIR | undefined;\n\t\t\tconst prevIdentity = change.meta?.previousIdentity as string | undefined;\n\t\t\tif (!col) return undefined;\n\t\t\tconst table = qualifyTable(change.table, schemaName);\n\t\t\tconst column = quoteIdent(change.column!, 'alias');\n\t\t\t// Reverse: restore previous identity state\n\t\t\tif (prevIdentity && !col.identity) {\n\t\t\t\t// Was identity, now not → re-add identity\n\t\t\t\tconst gen = prevIdentity === 'always' ? 'ALWAYS' : 'BY DEFAULT';\n\t\t\t\treturn `ALTER TABLE ${table} ALTER COLUMN ${column} ADD GENERATED ${gen} AS IDENTITY;`;\n\t\t\t}\n\t\t\tif (!prevIdentity && col.identity) {\n\t\t\t\t// Was not identity, now is → drop identity\n\t\t\t\treturn `ALTER TABLE ${table} ALTER COLUMN ${column} DROP IDENTITY IF EXISTS;`;\n\t\t\t}\n\t\t\t// Change between types → restore previous\n\t\t\tconst gen = prevIdentity === 'always' ? 'ALWAYS' : 'BY DEFAULT';\n\t\t\treturn `ALTER TABLE ${table} ALTER COLUMN ${column} SET GENERATED ${gen};`;\n\t\t}\n\n\t\tcase 'add_comment': {\n\t\t\t// DOWN: remove the comment that was added\n\t\t\tconst target = change.meta?.target as string;\n\t\t\tif (target === 'table') {\n\t\t\t\treturn `COMMENT ON TABLE ${qualifyTable(change.table, schemaName)} IS NULL;`;\n\t\t\t}\n\t\t\treturn `COMMENT ON COLUMN ${qualifyTable(change.table, schemaName)}.${quoteIdent(change.column!, 'alias')} IS NULL;`;\n\t\t}\n\n\t\tcase 'drop_comment': {\n\t\t\t// DOWN: cannot restore comment — value was lost\n\t\t\treturn `-- WARNING: Cannot reverse drop_comment \"${change.table}\"${change.column ? `.\"${change.column}\"` : ''} -- comment text was lost`;\n\t\t}\n\n\t\tcase 'create_extension': {\n\t\t\t// DOWN: drop the extension that was created\n\t\t\tconst ext = change.meta?.extension as string;\n\t\t\tif (ext == null) return undefined;\n\t\t\treturn `DROP EXTENSION IF EXISTS ${quoteExtensionName(ext)} CASCADE;`;\n\t\t}\n\n\t\tcase 'drop_extension': {\n\t\t\t// DOWN: recreate the extension that was dropped\n\t\t\tconst ext = change.meta?.extension as string;\n\t\t\tif (ext == null) return undefined;\n\t\t\treturn `CREATE EXTENSION IF NOT EXISTS ${quoteExtensionName(ext)};`;\n\t\t}\n\n\t\tcase 'create_sequence': {\n\t\t\t// DOWN: drop the sequence that was created\n\t\t\tconst seq = change.meta?.sequence as SequenceIR;\n\t\t\tif (!seq) return undefined;\n\t\t\tconst seqName = schemaName\n\t\t\t\t? `${quoteIdent(schemaName, 'alias')}.${quoteIdent(seq.name, 'alias')}`\n\t\t\t\t: quoteIdent(seq.name, 'alias');\n\t\t\treturn `DROP SEQUENCE IF EXISTS ${seqName} CASCADE;`;\n\t\t}\n\n\t\tcase 'alter_sequence': {\n\t\t\t// DOWN: restore previous sequence state\n\t\t\tconst prevSeq = change.meta?.previousSequence as SequenceIR | undefined;\n\t\t\tif (!prevSeq) {\n\t\t\t\treturn `-- WARNING: Cannot reverse alter_sequence \"${change.table}\" -- missing migration metadata`;\n\t\t\t}\n\t\t\tconst seqName = schemaName\n\t\t\t\t? `${quoteIdent(schemaName, 'alias')}.${quoteIdent(prevSeq.name, 'alias')}`\n\t\t\t\t: quoteIdent(prevSeq.name, 'alias');\n\t\t\treturn buildSequenceClause('ALTER SEQUENCE', seqName, prevSeq, true);\n\t\t}\n\n\t\tcase 'drop_sequence': {\n\t\t\t// DOWN: recreate the sequence that was dropped\n\t\t\tconst seq = change.meta?.sequence as SequenceIR;\n\t\t\tif (!seq) return undefined;\n\t\t\tconst seqName = schemaName\n\t\t\t\t? `${quoteIdent(schemaName, 'alias')}.${quoteIdent(seq.name, 'alias')}`\n\t\t\t\t: quoteIdent(seq.name, 'alias');\n\t\t\treturn buildSequenceClause('CREATE SEQUENCE', seqName, seq);\n\t\t}\n\n\t\tcase 'validate_constraint':\n\t\t\t// DOWN: VALIDATE CONSTRAINT cannot be reversed in PostgreSQL\n\t\t\treturn `-- VALIDATE CONSTRAINT cannot be reversed in PostgreSQL (table: \"${change.table}\")`;\n\n\t\tcase 'enable_rls':\n\t\t\t// DOWN: reverse enable → disable\n\t\t\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} DISABLE ROW LEVEL SECURITY;`;\n\n\t\tcase 'disable_rls':\n\t\t\t// DOWN: reverse disable → enable\n\t\t\treturn `ALTER TABLE ${qualifyTable(change.table, schemaName)} ENABLE ROW LEVEL SECURITY;`;\n\n\t\tcase 'create_policy': {\n\t\t\t// DOWN: drop the policy that was created\n\t\t\tconst policy = change.meta?.policy as PolicyIR;\n\t\t\tif (!policy) return undefined;\n\t\t\treturn `DROP POLICY IF EXISTS ${quoteIdent(policy.name, 'alias')} ON ${qualifyTable(change.table, schemaName)};`;\n\t\t}\n\n\t\tcase 'drop_policy': {\n\t\t\t// DOWN: recreate the policy that was dropped\n\t\t\tconst policy = change.meta?.policy as PolicyIR;\n\t\t\tif (!policy) return undefined;\n\t\t\treturn buildPolicySQL(change.table, policy, schemaName);\n\t\t}\n\t}\n}\n\n// ============================================================================\n// Down Migration SQL Generation\n// ============================================================================\n\n/**\n * Generate ordered DOWN SQL statements from a SchemaDiff.\n *\n * Reverses the topological order used in UP migrations:\n * phases run in descending order (11, 10, 9, ..., 0).\n *\n * Irreversible changes (drops that lose data) produce SQL WARNING comments.\n */\nexport function generateDownSQL(\n\tdiff: SchemaDiff,\n\toptions?: MigrationSQLOptions,\n): readonly string[] {\n\tconst schemaName = options?.schemaName;\n\tconst includeDestructive = options?.includeDestructive ?? true;\n\n\t// Filter out destructive changes if not included\n\tconst changes = includeDestructive\n\t\t? diff.changes\n\t\t: diff.changes.filter((c) => !c.destructive);\n\n\t// Group changes by phase for topological ordering\n\tconst phases: SchemaChange[][] = [\n\t\t[], // 0: drop FK, drop CHECK\n\t\t[], // 1: drop index\n\t\t[], // 2: drop column\n\t\t[], // 3: drop PK\n\t\t[], // 4: drop table, drop ENUM\n\t\t[], // 5: create ENUM\n\t\t[], // 6: create table\n\t\t[], // 7: add column\n\t\t[], // 8: alter column\n\t\t[], // 9: add PK\n\t\t[], // 10: add FK\n\t\t[], // 11: alter FK (drop + re-add)\n\t\t[], // 12: create index\n\t\t[], // 13: add CHECK constraint\n\t\t[], // 14: alter ENUM add value\n\t\t[], // 15: comments\n\t\t[], // 16: VALIDATE CONSTRAINT\n\t\t[], // 17: ENABLE/DISABLE ROW LEVEL SECURITY\n\t\t[], // 18: CREATE/DROP POLICY\n\t];\n\n\tfor (const change of changes) {\n\t\tconst phase = getPhase(change.kind);\n\t\tphases[phase]!.push(change);\n\t}\n\n\t// Generate SQL in REVERSE phase order (index → FK → PK → alter → column → table)\n\tconst statements: string[] = [];\n\tfor (let i = phases.length - 1; i >= 0; i--) {\n\t\tfor (const change of phases[i]!) {\n\t\t\tconst sql = changeToDownSQL(change, schemaName);\n\t\t\tif (sql) statements.push(sql);\n\t\t}\n\t}\n\n\treturn statements;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction generateCreateTableSQL(table: TableIR, schemaName?: string): string {\n\tconst qualTable = qualifyTable(table.name, schemaName);\n\n\tconst elements: string[] = [];\n\n\t// Columns\n\tfor (const col of table.columns) {\n\t\tconst parts: string[] = [quoteIdent(col.name, 'alias'), mapColumnType(col)];\n\t\tif (!col.nullable && !col.autoIncrement) parts.push('NOT NULL');\n\t\tif (col.default !== undefined)\n\t\t\tparts.push(`DEFAULT ${formatDefault(col.default)}`);\n\t\tif (col.unique) parts.push('UNIQUE');\n\t\t// S-2: validate collation name before quoting — uses quoteCollation which\n\t\t// accepts locale strings like `en_US.utf8`, `en-US-x-icu`, `C.UTF-8`\n\t\t// that contain dots/hyphens rejected by the standard identifier validator.\n\t\tif (col.collation) parts.push(`COLLATE ${quoteCollation(col.collation)}`);\n\t\tif (col.identity) {\n\t\t\tconst gen = col.identity === 'always' ? 'ALWAYS' : 'BY DEFAULT';\n\t\t\tparts.push(`GENERATED ${gen} AS IDENTITY`);\n\t\t}\n\t\telements.push(parts.join(' '));\n\t}\n\n\t// Primary key\n\tif (table.primaryKey !== undefined) {\n\t\tconst pkCols = (\n\t\t\tArray.isArray(table.primaryKey) ? table.primaryKey : [table.primaryKey]\n\t\t)\n\t\t\t.map((n) => quoteIdent(n, 'alias'))\n\t\t\t.join(', ');\n\t\telements.push(\n\t\t\t`CONSTRAINT ${quoteIdent(pkName(table.name), 'alias')} PRIMARY KEY (${pkCols})`,\n\t\t);\n\t}\n\n\tconst body = elements.map((el) => ` ${el}`).join(',\\n');\n\tlet sql = `CREATE TABLE ${qualTable} (\\n${body}\\n)`;\n\tif (table.partition) {\n\t\tconst partCols = table.partition.columns\n\t\t\t.map((n) => quoteIdent(n, 'alias'))\n\t\t\t.join(', ');\n\t\tsql += ` PARTITION BY ${table.partition.strategy} (${partCols})`;\n\t}\n\tsql += ';';\n\treturn sql;\n}\n\nfunction generateAddFKSQL(\n\ttableName: string,\n\tfk: ForeignKeyIR,\n\tschemaName?: string,\n): string {\n\tconst qualTable = qualifyTable(tableName, schemaName);\n\tconst constraintName = quoteIdent(fkName(tableName, fk.columns), 'alias');\n\tconst fkCols = fk.columns.map((n) => quoteIdent(n, 'alias')).join(', ');\n\t// Referenced table must also be schema-qualified to resolve within the same schema\n\tconst refTable = qualifyTable(fk.references.table, schemaName);\n\tconst refCols = fk.references.columns\n\t\t.map((n) => quoteIdent(n, 'alias'))\n\t\t.join(', ');\n\tconst onDelete = fk.onDelete\n\t\t? ` ON DELETE ${mapOnDeleteAction(fk.onDelete)}`\n\t\t: '';\n\tconst onUpdate = fk.onUpdate\n\t\t? ` ON UPDATE ${mapOnDeleteAction(fk.onUpdate)}`\n\t\t: '';\n\tconst deferred = fk.deferred ? ' DEFERRABLE INITIALLY DEFERRED' : '';\n\tconst notValid = fk.notValid ? ' NOT VALID' : '';\n\treturn `ALTER TABLE ${qualTable} ADD CONSTRAINT ${constraintName} FOREIGN KEY (${fkCols}) REFERENCES ${refTable} (${refCols})${onDelete}${onUpdate}${deferred}${notValid};`;\n}\n\n// M-6: formatDefault is now a thin alias for the shared formatSqlDefault from phases/utils.\n// The duplicate implementations in migration-sql.ts, table-operations.ts, and ddl-generator.ts\n// have been consolidated. See formatSqlDefault in packages/adapter-pgsql/src/ddl/phases/utils.ts.\nfunction formatDefault(value: unknown): string {\n\treturn formatSqlDefault(value, 'migration-sql default');\n}\n","/**\n * Type Mapping - Maps ModelIR ColumnType to PostgreSQL data types\n *\n * Supports both manual schemas and introspected schemas (preserving originalDbType).\n * Handles auto-increment via SERIAL/BIGSERIAL types.\n *\n * @module ddl/type-mapping\n */\n\nimport type { ColumnIR, ColumnType } from '@dbsp/types';\nimport { validateDbTypeName } from '../validate.js';\n\n/**\n * Map ColumnType to PostgreSQL data type string.\n *\n * Uses originalDbType if available (from introspection), otherwise\n * falls back to reasonable PostgreSQL defaults.\n *\n * @param col - Column definition from ModelIR\n * @returns PostgreSQL type string (e.g., 'VARCHAR(255)', 'SERIAL', 'JSONB')\n */\nexport function mapColumnType(col: ColumnIR): string {\n\t// Prefer original DB type if available (preserves precision/scale)\n\tif (col.originalDbType) {\n\t\treturn validateDbTypeName(col.originalDbType.toUpperCase()).toUpperCase();\n\t}\n\n\t// Auto-increment columns use SERIAL/BIGSERIAL\n\tif (col.autoIncrement) {\n\t\treturn col.type === 'bigint' ? 'BIGSERIAL' : 'SERIAL';\n\t}\n\n\t// Standard type mapping\n\treturn mapBaseType(col.type);\n}\n\n/**\n * Map base ColumnType to PostgreSQL type (without auto-increment handling).\n */\nfunction mapBaseType(type: ColumnType): string {\n\tswitch (type) {\n\t\tcase 'string':\n\t\t\treturn 'VARCHAR(255)';\n\t\tcase 'text':\n\t\t\treturn 'TEXT';\n\t\tcase 'number':\n\t\tcase 'integer':\n\t\t\treturn 'INTEGER';\n\t\tcase 'bigint':\n\t\t\treturn 'BIGINT';\n\t\tcase 'decimal':\n\t\t\treturn 'NUMERIC';\n\t\tcase 'boolean':\n\t\t\treturn 'BOOLEAN';\n\t\tcase 'date':\n\t\t\treturn 'DATE';\n\t\tcase 'time':\n\t\t\treturn 'TIME';\n\t\tcase 'datetime':\n\t\tcase 'timestamp':\n\t\t\treturn 'TIMESTAMPTZ';\n\t\tcase 'json':\n\t\tcase 'jsonb':\n\t\t\treturn 'JSONB';\n\t\tcase 'uuid':\n\t\t\treturn 'UUID';\n\t\t// PostgreSQL-specific range types\n\t\tcase 'daterange':\n\t\t\treturn 'DATERANGE';\n\t\tcase 'tsrange':\n\t\t\treturn 'TSRANGE';\n\t\tcase 'tstzrange':\n\t\t\treturn 'TSTZRANGE';\n\t\tcase 'int4range':\n\t\t\treturn 'INT4RANGE';\n\t\tcase 'int8range':\n\t\t\treturn 'INT8RANGE';\n\t\tcase 'numrange':\n\t\t\treturn 'NUMRANGE';\n\t\tdefault:\n\t\t\t// Fallback for unknown types\n\t\t\treturn 'TEXT';\n\t}\n}\n\n/**\n * Map OnDeleteAction to PostgreSQL syntax.\n */\nexport function mapOnDeleteAction(action?: string): string {\n\tswitch (action) {\n\t\tcase 'CASCADE':\n\t\t\treturn 'CASCADE';\n\t\tcase 'SET NULL':\n\t\t\treturn 'SET NULL';\n\t\tcase 'SET DEFAULT':\n\t\t\treturn 'SET DEFAULT';\n\t\tcase 'RESTRICT':\n\t\t\treturn 'RESTRICT';\n\t\tdefault:\n\t\t\treturn 'NO ACTION';\n\t}\n}\n","/**\n * DDL Phase: Sequences\n *\n * Generates CREATE SEQUENCE statements.\n * Must run before CREATE TABLE (tables may reference sequences).\n *\n * @module ddl/phases/sequences\n */\n\nimport { buildSequenceClause } from '../migration-sql.js';\nimport { type PhaseContext, sup } from './types.js';\nimport { quoteIdent as quoteId } from './utils.js';\n\n/**\n * Generate CREATE SEQUENCE statements for all sequences in the schema.\n *\n * @param ctx - Phase context with schema, schemaName, naming, and capabilities\n * @returns Array of DDL statements, or empty if sequences are unsupported / absent\n */\nexport function generateSequencesPhase(ctx: PhaseContext): string[] {\n\tconst { schema, schemaName, naming, caps } = ctx;\n\tif (!schema.sequences || !sup(caps, caps?.supportsDDLSequences)) {\n\t\treturn [];\n\t}\n\tconst statements: string[] = [];\n\tfor (const [, seq] of schema.sequences) {\n\t\tconst seqName = schemaName\n\t\t\t? `${quoteId(naming.toDatabase(schemaName), 'schema')}.${quoteId(seq.name, 'table')}`\n\t\t\t: quoteId(seq.name, 'table');\n\t\tstatements.push(buildSequenceClause('CREATE SEQUENCE', seqName, seq));\n\t}\n\treturn statements;\n}\n","/**\n * DDL Phase: Tables\n *\n * Generates CREATE TABLE statements (without FK constraints).\n * FKs are handled separately in the constraints phase to allow circular references.\n *\n * @module ddl/phases/tables\n */\n\nimport { generateCreateTable } from '../ddl-generator.js';\nimport type { PhaseContext } from './types.js';\n\n/**\n * Generate CREATE TABLE statements for all tables in the schema.\n * Column definitions are included inline; foreign key constraints are excluded\n * (added later by the constraints phase).\n *\n * @param ctx - Phase context\n * @returns Array of DDL statements, one per table\n */\nexport function generateTablesPhase(ctx: PhaseContext): string[] {\n\tconst { tables, schemaName, naming } = ctx;\n\treturn tables.map((table) => generateCreateTable(table, schemaName, naming));\n}\n","/**\n * Migration File Format v2 — UP + DOWN sections.\n *\n * File format:\n * <UP statements>;\n * -- DOWN\n * <DOWN statements>;\n *\n * The separator `-- DOWN` must be on its own line (SC-25).\n *\n * @module ddl/migration-file\n */\n\nimport type { MigrationSQLOptions } from './migration-sql.js';\nimport { generateDownSQL, generateMigrationSQL } from './migration-sql.js';\nimport type { SchemaDiff } from './schema-diff.js';\n\n/**\n * Result of parsing a migration file's UP/DOWN sections.\n */\nexport interface ParsedMigrationFile {\n\treadonly upStatements: readonly string[];\n\treadonly downStatements: readonly string[];\n\treadonly hasDown: boolean;\n}\n\n/**\n * Generate a migration file content with UP and DOWN sections.\n */\nexport function generateMigrationFile(\n\tdiff: SchemaDiff,\n\toptions?: MigrationSQLOptions & { name?: string },\n): string {\n\tconst upStatements = generateMigrationSQL(diff, options);\n\tconst downStatements = generateDownSQL(diff, options);\n\n\tconst header = options?.name\n\t\t? `-- Migration: ${options.name}\\n-- Generated by: dbsp migrate dev\\n-- Date: ${new Date().toISOString()}\\n\\n`\n\t\t: '';\n\n\tconst upSection =\n\t\tupStatements.length > 0 ? `${upStatements.join(';\\n\\n')};\\n` : '';\n\tconst downSection =\n\t\tdownStatements.length > 0 ? `${downStatements.join(';\\n\\n')};\\n` : '';\n\n\treturn `${header}${upSection}\\n-- DOWN\\n\\n${downSection}`;\n}\n\n/**\n * Parse a migration file into UP and DOWN sections.\n * Separator: `^\\s*-- DOWN\\s*$` (strict regex, own line only — SC-25)\n */\nexport function parseMigrationFile(content: string): ParsedMigrationFile {\n\t// Strict regex: -- DOWN must be on its own line\n\tconst separatorRegex = /^\\s*-- DOWN\\s*$/m;\n\tconst match = separatorRegex.exec(content);\n\n\tif (!match) {\n\t\t// No DOWN section — legacy v1 file\n\t\treturn {\n\t\t\tupStatements: splitStatements(content),\n\t\t\tdownStatements: [],\n\t\t\thasDown: false,\n\t\t};\n\t}\n\n\tconst upContent = content.slice(0, match.index);\n\tconst downContent = content.slice(match.index + match[0].length);\n\n\treturn {\n\t\tupStatements: splitStatements(upContent),\n\t\tdownStatements: splitStatements(downContent),\n\t\thasDown: true,\n\t};\n}\n\n/**\n * Check if SQL statements contain destructive operations.\n * Destructive: DROP TABLE, DROP COLUMN, lossy ALTER COLUMN TYPE\n */\nexport function isDestructiveDown(downStatements: readonly string[]): boolean {\n\tconst destructivePatterns = [\n\t\t/DROP\\s+TABLE/i,\n\t\t/DROP\\s+COLUMN/i,\n\t\t/ALTER\\s+COLUMN\\s+\\S+\\s+TYPE/i, // lossy type change\n\t];\n\n\treturn downStatements.some((stmt) =>\n\t\tdestructivePatterns.some((pattern) => pattern.test(stmt)),\n\t);\n}\n\n/**\n * Split SQL content into individual statements by semicolons.\n * Filters out empty strings. Preserves WARNING comments.\n */\nfunction splitStatements(content: string): string[] {\n\treturn content\n\t\t.split(/;\\s*\\n/)\n\t\t.map((s) => s.trim())\n\t\t.filter((s) => s.length > 0);\n}\n","/**\n * Migration Tracker — `_dbsp_migrations` table CRUD.\n *\n * Manages the tracking table that records which migrations\n * have been applied to a database.\n */\n\nimport type { Pool, PoolClient } from 'pg';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface MigrationRecord {\n\t/** Migration filename (e.g., \"0001_create_users.sql\") */\n\treadonly name: string;\n\t/** SHA-256 checksum of the migration file content */\n\treadonly checksum: string;\n\t/** When the migration was applied */\n\treadonly appliedAt: Date;\n\t/** Schema version at time of this migration */\n\treadonly schemaVersion: number;\n\t/** Whether this migration contains destructive changes */\n\treadonly destructive: boolean;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst MIGRATIONS_TABLE = '_dbsp_migrations';\n\nconst CREATE_TABLE_SQL = `\nCREATE TABLE IF NOT EXISTS \"${MIGRATIONS_TABLE}\" (\n \"id\" serial PRIMARY KEY,\n \"name\" varchar(255) NOT NULL UNIQUE,\n \"checksum\" varchar(64) NOT NULL,\n \"applied_at\" timestamptz NOT NULL DEFAULT now(),\n \"schema_version\" integer NOT NULL DEFAULT 0,\n \"destructive\" boolean NOT NULL DEFAULT false\n)`;\n\n// ============================================================================\n// Advisory Lock\n// ============================================================================\n\n/**\n * Acquire a session-level advisory lock for migration operations.\n *\n * @deprecated Use {@link withMigrationLock} instead — pool.query may release\n * the connection (and the lock) before the migration completes.\n */\nexport async function acquireMigrationLock(pool: Pool): Promise<void> {\n\tawait pool.query(`SELECT pg_advisory_lock(hashtext('dbsp_migrate'))`);\n}\n\n/**\n * Release the session-level advisory lock for migration operations.\n *\n * @deprecated Use {@link withMigrationLock} instead.\n */\nexport async function releaseMigrationLock(pool: Pool): Promise<void> {\n\tawait pool.query(`SELECT pg_advisory_unlock(hashtext('dbsp_migrate'))`);\n}\n\n/**\n * Execute a callback under an advisory lock using a dedicated client.\n * The lock is held for the duration of the callback.\n * The client is released (and lock freed) after the callback completes.\n */\nexport async function withMigrationLock<T>(\n\tpool: Pool,\n\tfn: (client: PoolClient) => Promise<T>,\n): Promise<T> {\n\tconst client = await pool.connect();\n\ttry {\n\t\tawait client.query(`SELECT pg_advisory_lock(hashtext('dbsp_migrate'))`);\n\t\treturn await fn(client);\n\t} finally {\n\t\tawait client\n\t\t\t.query(`SELECT pg_advisory_unlock(hashtext('dbsp_migrate'))`)\n\t\t\t.catch(() => {\n\t\t\t\t/* unlock failure is non-fatal — lock freed on client.release() */\n\t\t\t});\n\t\tclient.release();\n\t}\n}\n\n// ============================================================================\n// Table Management\n// ============================================================================\n\n/**\n * Ensure the migrations tracking table exists.\n * Auto-migrates existing tables that lack `schema_version`/`destructive` columns,\n * and backfills `schema_version` by `applied_at` order for rows still at 0.\n */\nexport async function ensureMigrationsTable(pool: Pool): Promise<void> {\n\tawait pool.query(CREATE_TABLE_SQL);\n\n\t// Auto-migrate: add schema_version column if missing\n\tawait pool.query(`\n ALTER TABLE \"${MIGRATIONS_TABLE}\"\n ADD COLUMN IF NOT EXISTS \"schema_version\" integer NOT NULL DEFAULT 0\n `);\n\n\t// Auto-migrate: add destructive column if missing\n\tawait pool.query(`\n ALTER TABLE \"${MIGRATIONS_TABLE}\"\n ADD COLUMN IF NOT EXISTS \"destructive\" boolean NOT NULL DEFAULT false\n `);\n\n\t// Backfill schema_version for existing rows that still have default 0.\n\t// Uses ROW_NUMBER() OVER (ORDER BY applied_at) to assign sequential versions.\n\tawait pool.query(`\n UPDATE \"${MIGRATIONS_TABLE}\"\n SET \"schema_version\" = sub.rn\n FROM (\n SELECT \"id\", ROW_NUMBER() OVER (ORDER BY \"applied_at\") AS rn\n FROM \"${MIGRATIONS_TABLE}\"\n WHERE \"schema_version\" = 0\n ) sub\n WHERE \"${MIGRATIONS_TABLE}\".\"id\" = sub.\"id\"\n `);\n}\n\n// ============================================================================\n// CRUD Operations\n// ============================================================================\n\n/**\n * Get all applied migrations, ordered by name.\n */\nexport async function getAppliedMigrations(\n\tpool: Pool,\n): Promise<readonly MigrationRecord[]> {\n\tconst result = await pool.query<{\n\t\tname: string;\n\t\tchecksum: string;\n\t\tapplied_at: Date;\n\t\tschema_version: number;\n\t\tdestructive: boolean;\n\t}>(\n\t\t`SELECT \"name\", \"checksum\", \"applied_at\", \"schema_version\", \"destructive\" FROM \"${MIGRATIONS_TABLE}\" ORDER BY \"name\"`,\n\t);\n\n\treturn result.rows.map((row) => ({\n\t\tname: row.name,\n\t\tchecksum: row.checksum,\n\t\tappliedAt: row.applied_at,\n\t\tschemaVersion: row.schema_version,\n\t\tdestructive: row.destructive,\n\t}));\n}\n\n/**\n * Record a migration as applied.\n */\nexport async function recordMigration(\n\tpool: Pool,\n\tname: string,\n\tchecksum: string,\n\tschemaVersion: number,\n\tdestructive: boolean,\n): Promise<void> {\n\tawait pool.query(\n\t\t`INSERT INTO \"${MIGRATIONS_TABLE}\" (\"name\", \"checksum\", \"schema_version\", \"destructive\") VALUES ($1, $2, $3, $4)`,\n\t\t[name, checksum, schemaVersion, destructive],\n\t);\n}\n\n/**\n * Check if a specific migration has been applied.\n */\nexport async function isMigrationApplied(\n\tpool: Pool,\n\tname: string,\n): Promise<boolean> {\n\tconst result = await pool.query<{ count: string }>(\n\t\t`SELECT count(*) as count FROM \"${MIGRATIONS_TABLE}\" WHERE \"name\" = $1`,\n\t\t[name],\n\t);\n\tconst row = result.rows[0];\n\treturn row !== undefined && Number.parseInt(row.count, 10) > 0;\n}\n\n/**\n * Get the next schema version number (max + 1, or 1 if no migrations).\n */\nexport async function getNextSchemaVersion(pool: Pool): Promise<number> {\n\tconst result = await pool.query<{ max_version: number | null }>(\n\t\t`SELECT MAX(\"schema_version\") as max_version FROM \"${MIGRATIONS_TABLE}\"`,\n\t);\n\tconst maxVersion = result.rows[0]?.max_version ?? 0;\n\treturn maxVersion + 1;\n}\n\n/**\n * Remove a migration record (for rollback).\n */\nexport async function removeMigrationRecord(\n\tpool: Pool,\n\tname: string,\n): Promise<void> {\n\tawait pool.query(`DELETE FROM \"${MIGRATIONS_TABLE}\" WHERE \"name\" = $1`, [\n\t\tname,\n\t]);\n}\n","/**\n * Schema Comparison Engine (DDL-PROV Block 1)\n *\n * Compares two ModelIRs (schema definition vs database state)\n * and produces a structured diff of changes needed.\n *\n * @module schema-diff\n */\n\nimport type {\n\tColumnIR,\n\tDbCasing,\n\tDialectCapabilities,\n\tEnumIR,\n\tForeignKeyIR,\n\tIndexIR,\n\tModelIR,\n\tPartitionIR,\n\tPolicyIR,\n\tSequenceIR,\n\tTableIR,\n} from '@dbsp/types';\nimport {\n\tgetNamingPluginForDbCasing,\n\ttype NamingPlugin,\n} from '../naming-plugin.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ChangeKind =\n\t// Tables\n\t| 'create_table'\n\t| 'drop_table'\n\t// Columns\n\t| 'add_column'\n\t| 'drop_column'\n\t| 'alter_column_type'\n\t| 'alter_column_nullable'\n\t| 'alter_column_default'\n\t// Constraints\n\t| 'add_primary_key'\n\t| 'drop_primary_key'\n\t| 'add_foreign_key'\n\t| 'drop_foreign_key'\n\t| 'alter_foreign_key'\n\t| 'validate_constraint'\n\t// Indexes\n\t| 'create_index'\n\t| 'drop_index'\n\t// CHECK constraints\n\t| 'add_check_constraint'\n\t| 'drop_check_constraint'\n\t// ENUM types\n\t| 'create_enum'\n\t| 'alter_enum_add_value'\n\t| 'drop_enum'\n\t// Column enhancements\n\t| 'alter_column_collation'\n\t| 'alter_column_identity'\n\t// Comments\n\t| 'add_comment'\n\t| 'drop_comment'\n\t// Extensions\n\t| 'create_extension'\n\t| 'drop_extension'\n\t// Sequences\n\t| 'create_sequence'\n\t| 'alter_sequence'\n\t| 'drop_sequence'\n\t// Row-Level Security\n\t| 'enable_rls'\n\t| 'disable_rls'\n\t| 'create_policy'\n\t| 'drop_policy';\n\nexport interface SchemaChange {\n\treadonly kind: ChangeKind;\n\treadonly table: string;\n\treadonly column?: string;\n\treadonly destructive: boolean;\n\treadonly details: string;\n\t/** Additional metadata for SQL generation */\n\treadonly meta?: Readonly<Record<string, unknown>>;\n}\n\nexport interface DiffSummary {\n\treadonly tables: { readonly added: number; readonly dropped: number };\n\treadonly columns: {\n\t\treadonly added: number;\n\t\treadonly dropped: number;\n\t\treadonly altered: number;\n\t};\n\treadonly indexes: { readonly added: number; readonly dropped: number };\n\treadonly constraints: {\n\t\treadonly added: number;\n\t\treadonly dropped: number;\n\t\treadonly altered: number;\n\t};\n}\n\nexport interface SchemaDiff {\n\treadonly changes: readonly SchemaChange[];\n\treadonly hasDestructive: boolean;\n\treadonly summary: DiffSummary;\n}\n\n// ============================================================================\n// Options\n// ============================================================================\n\nexport interface CompareSchemataOptions {\n\t/**\n\t * Database naming convention.\n\t * When set, schema model names (camelCase) are converted to DB format\n\t * (e.g. snake_case) before comparison with the introspected model.\n\t */\n\tdbCasing?: DbCasing;\n\t/** Dialect capabilities — comparisons for unsupported features will be skipped */\n\treadonly dialectCapabilities?: DialectCapabilities;\n}\n\n// ============================================================================\n// Comparison Engine\n// ============================================================================\n\n/**\n * Compare two ModelIRs and produce a structured diff.\n *\n * @param schema - The desired schema (from definition)\n * @param db - The current database state (from introspection)\n * @param options - Optional comparison settings (e.g. dbCasing)\n * @returns SchemaDiff with all changes needed to bring DB in sync with schema\n */\nexport function compareSchemata(\n\tschema: ModelIR,\n\tdb: ModelIR,\n\toptions?: CompareSchemataOptions,\n): SchemaDiff {\n\tconst changes: SchemaChange[] = [];\n\n\tconst plugin =\n\t\toptions?.dbCasing !== undefined\n\t\t\t? getNamingPluginForDbCasing(options.dbCasing)\n\t\t\t: undefined;\n\tconst schemaTables = plugin\n\t\t? normalizeTableMap(schema.tables, plugin)\n\t\t: new Map(schema.tables);\n\tconst dbTables = new Map(db.tables);\n\n\tconst caps = options?.dialectCapabilities;\n\t// Helper: feature is supported if no caps provided (backward compat) OR flag is true\n\t/**\n\t * Check whether a DDL feature is supported.\n\t *\n\t * - `undefined`: capability flag not set → feature is on by default (no caps = all features).\n\t * - `false`: capability explicitly disabled → feature is skipped.\n\t * - `true`: capability explicitly enabled → feature is included.\n\t */\n\tconst sup = (flag: boolean | undefined) => !caps || flag === true;\n\n\t// 0. Compare ENUM types (schema-level, before tables)\n\tif (sup(caps?.supportsDDLEnumTypes)) {\n\t\tcompareEnums(schema, db, changes);\n\t}\n\n\t// 0a. Compare extensions (schema-level)\n\tif (sup(caps?.supportsDDLExtensions)) {\n\t\tcompareExtensions(schema, db, changes);\n\t}\n\n\t// 0b. Compare sequences (schema-level, before tables)\n\tif (sup(caps?.supportsDDLSequences)) {\n\t\tcompareSequences(schema, db, changes);\n\t}\n\n\t// 1. Tables that exist in schema but not in DB → create_table\n\tfor (const [name, schemaTable] of schemaTables) {\n\t\tif (!dbTables.has(name)) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'create_table',\n\t\t\t\ttable: name,\n\t\t\t\tdestructive: false,\n\t\t\t\tdetails: `Create table \"${name}\" with ${schemaTable.columns.length} columns`,\n\t\t\t\tmeta: { table: schemaTable },\n\t\t\t});\n\t\t\t// Emit FK constraints for new table (phase 9, after CREATE TABLE phase 5)\n\t\t\tfor (const fk of schemaTable.foreignKeys) {\n\t\t\t\tchanges.push({\n\t\t\t\t\tkind: 'add_foreign_key',\n\t\t\t\t\ttable: name,\n\t\t\t\t\tdestructive: false,\n\t\t\t\t\tdetails: `Add FK (${fk.columns.join(', ')}) → ${fk.references.table}(${fk.references.columns.join(', ')})`,\n\t\t\t\t\tmeta: { fk },\n\t\t\t\t});\n\t\t\t}\n\t\t\t// Emit indexes for new table (phase 11, after FK phase 9)\n\t\t\tfor (const idx of schemaTable.indexes) {\n\t\t\t\tchanges.push({\n\t\t\t\t\tkind: 'create_index',\n\t\t\t\t\ttable: name,\n\t\t\t\t\tdestructive: false,\n\t\t\t\t\tdetails: `Create ${idx.unique ? 'unique ' : ''}index on (${idx.columns.join(', ')})`,\n\t\t\t\t\tmeta: { index: idx },\n\t\t\t\t});\n\t\t\t}\n\t\t\t// Emit CHECK constraints for new table (phase 12, after indexes)\n\t\t\tif (sup(caps?.supportsDDLCheckConstraints)) {\n\t\t\t\tfor (const check of schemaTable.checkConstraints ?? []) {\n\t\t\t\t\tchanges.push({\n\t\t\t\t\t\tkind: 'add_check_constraint',\n\t\t\t\t\t\ttable: name,\n\t\t\t\t\t\tdestructive: false,\n\t\t\t\t\t\tdetails: `Add CHECK constraint \"${check.name}\" ${check.expression}`,\n\t\t\t\t\t\tmeta: { check },\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Emit RLS enable + policies for new table (after table creation)\n\t\t\tif (sup(caps?.supportsDDLRowLevelSecurity)) {\n\t\t\t\tif (schemaTable.rlsEnabled) {\n\t\t\t\t\tchanges.push({\n\t\t\t\t\t\tkind: 'enable_rls',\n\t\t\t\t\t\ttable: name,\n\t\t\t\t\t\tdestructive: false,\n\t\t\t\t\t\tdetails: `Enable RLS on table \"${name}\"`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tfor (const policy of schemaTable.policies ?? []) {\n\t\t\t\t\tchanges.push({\n\t\t\t\t\t\tkind: 'create_policy',\n\t\t\t\t\t\ttable: name,\n\t\t\t\t\t\tdestructive: false,\n\t\t\t\t\t\tdetails: `Create policy \"${policy.name}\" on \"${name}\"`,\n\t\t\t\t\t\tmeta: { policy },\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Table exists in both → compare columns, constraints, indexes\n\t\tconst dbTable = dbTables.get(name)!;\n\t\tcompareColumns(schemaTable, dbTable, changes);\n\t\tcomparePrimaryKeys(schemaTable, dbTable, changes);\n\t\tcompareForeignKeys(schemaTable, dbTable, changes);\n\t\tcompareIndexes(schemaTable, dbTable, changes);\n\t\tif (sup(caps?.supportsDDLCheckConstraints)) {\n\t\t\tcompareCheckConstraints(schemaTable, dbTable, changes);\n\t\t}\n\t\tif (sup(caps?.supportsDDLComments)) {\n\t\t\tcompareComments(schemaTable, dbTable, changes);\n\t\t}\n\t\tcomparePartitions(schemaTable, dbTable, changes);\n\t\tif (sup(caps?.supportsDDLRowLevelSecurity)) {\n\t\t\tcomparePolicies(schemaTable, dbTable, changes);\n\t\t}\n\t}\n\n\t// 2. Tables that exist in DB but not in schema → drop_table\n\tfor (const [name] of dbTables) {\n\t\tif (!schemaTables.has(name)) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'drop_table',\n\t\t\t\ttable: name,\n\t\t\t\tdestructive: true,\n\t\t\t\tdetails: `Drop table \"${name}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn {\n\t\tchanges,\n\t\thasDestructive: changes.some((c) => c.destructive),\n\t\tsummary: buildSummary(changes),\n\t};\n}\n\n// ============================================================================\n// Name Normalization (camelCase → DB format)\n// ============================================================================\n\n/**\n * Convert all identifiers in a table map from model format to database format.\n * This allows comparing a schema definition (camelCase) against an introspected\n * database (snake_case) without false positives.\n */\nfunction normalizeTableMap(\n\ttables: ReadonlyMap<string, TableIR>,\n\tplugin: NamingPlugin,\n): Map<string, TableIR> {\n\tconst result = new Map<string, TableIR>();\n\tfor (const [_key, table] of tables) {\n\t\tconst dbName = plugin.toDatabase(table.name);\n\t\tresult.set(dbName, normalizeTable(table, plugin));\n\t}\n\treturn result;\n}\n\nfunction normalizeTable(table: TableIR, plugin: NamingPlugin): TableIR {\n\tconst dbName = plugin.toDatabase(table.name);\n\tconst toDb = (name: string) => plugin.toDatabase(name);\n\n\treturn {\n\t\tname: dbName,\n\t\tcolumns: table.columns.map((col) => ({\n\t\t\t...col,\n\t\t\tname: toDb(col.name),\n\t\t})),\n\t\t...(table.primaryKey !== undefined && {\n\t\t\tprimaryKey:\n\t\t\t\ttypeof table.primaryKey === 'string'\n\t\t\t\t\t? toDb(table.primaryKey)\n\t\t\t\t\t: table.primaryKey.map(toDb),\n\t\t}),\n\t\tforeignKeys: table.foreignKeys.map((fk) => ({\n\t\t\t...fk,\n\t\t\tcolumns: fk.columns.map(toDb),\n\t\t\treferences: {\n\t\t\t\ttable: toDb(fk.references.table),\n\t\t\t\tcolumns: fk.references.columns.map(toDb),\n\t\t\t},\n\t\t})),\n\t\tindexes: table.indexes.map((idx) => ({\n\t\t\t...idx,\n\t\t\tcolumns: idx.columns.map(toDb),\n\t\t})),\n\t\t...(table.partition\n\t\t\t? {\n\t\t\t\t\tpartition: {\n\t\t\t\t\t\tstrategy: table.partition.strategy,\n\t\t\t\t\t\tcolumns: table.partition.columns.map(toDb),\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t};\n}\n\n// ============================================================================\n// Column Comparison\n// ============================================================================\n\nfunction compareColumns(\n\tschema: TableIR,\n\tdb: TableIR,\n\tchanges: SchemaChange[],\n): void {\n\tconst schemaColMap = new Map(schema.columns.map((c) => [c.name, c]));\n\tconst dbColMap = new Map(db.columns.map((c) => [c.name, c]));\n\n\t// Columns in schema but not in DB → add_column\n\tfor (const [name, schemaCol] of schemaColMap) {\n\t\tif (!dbColMap.has(name)) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'add_column',\n\t\t\t\ttable: schema.name,\n\t\t\t\tcolumn: name,\n\t\t\t\tdestructive: false,\n\t\t\t\tdetails: `Add column \"${name}\" (${schemaCol.type}${schemaCol.nullable ? '' : ' NOT NULL'})`,\n\t\t\t\tmeta: { column: schemaCol },\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Column exists in both → compare type, nullable, default\n\t\tconst dbCol = dbColMap.get(name)!;\n\t\tcompareColumnDetails(schema.name, schemaCol, dbCol, changes);\n\t}\n\n\t// Columns in DB but not in schema → drop_column\n\tfor (const [name] of dbColMap) {\n\t\tif (!schemaColMap.has(name)) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'drop_column',\n\t\t\t\ttable: schema.name,\n\t\t\t\tcolumn: name,\n\t\t\t\tdestructive: true,\n\t\t\t\tdetails: `Drop column \"${name}\"`,\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction compareColumnDetails(\n\ttableName: string,\n\tschema: ColumnIR,\n\tdb: ColumnIR,\n\tchanges: SchemaChange[],\n): void {\n\t// Type change — prefer originalDbType when both sides carry it (e.g. vector(768) → vector(1024))\n\tconst schemaDbType = schema.originalDbType?.toLowerCase();\n\tconst dbDbType = db.originalDbType?.toLowerCase();\n\n\tif (schemaDbType && dbDbType && schemaDbType !== dbDbType) {\n\t\t// Both have originalDbType and they differ → precision/type change\n\t\tchanges.push({\n\t\t\tkind: 'alter_column_type',\n\t\t\ttable: tableName,\n\t\t\tcolumn: schema.name,\n\t\t\tdestructive: true,\n\t\t\tdetails: `Change type of \"${schema.name}\" from ${db.originalDbType} to ${schema.originalDbType}`,\n\t\t\tmeta: {\n\t\t\t\tfromType: db.originalDbType,\n\t\t\t\ttoType: schema.originalDbType,\n\t\t\t\tcolumn: schema,\n\t\t\t},\n\t\t});\n\t} else if (!areTypesEquivalent(schema.type, db.type)) {\n\t\t// Fall back to base type comparison (original behavior)\n\t\tchanges.push({\n\t\t\tkind: 'alter_column_type',\n\t\t\ttable: tableName,\n\t\t\tcolumn: schema.name,\n\t\t\tdestructive: true,\n\t\t\tdetails: `Change type of \"${schema.name}\" from ${db.type} to ${schema.type}`,\n\t\t\tmeta: { fromType: db.type, toType: schema.type, column: schema },\n\t\t});\n\t}\n\n\t// Nullable change\n\tif (schema.nullable !== db.nullable) {\n\t\tchanges.push({\n\t\t\tkind: 'alter_column_nullable',\n\t\t\ttable: tableName,\n\t\t\tcolumn: schema.name,\n\t\t\tdestructive: false,\n\t\t\tdetails: `Change nullable of \"${schema.name}\" from ${db.nullable} to ${schema.nullable}`,\n\t\t\tmeta: { nullable: schema.nullable, oldNullable: db.nullable },\n\t\t});\n\t}\n\n\t// Default change — compare normalized string representations\n\tconst schemaDefault = normalizeDefault(schema.default);\n\tconst dbDefault = normalizeDefault(db.default);\n\tif (schemaDefault !== dbDefault) {\n\t\tchanges.push({\n\t\t\tkind: 'alter_column_default',\n\t\t\ttable: tableName,\n\t\t\tcolumn: schema.name,\n\t\t\tdestructive: false,\n\t\t\tdetails: `Change default of \"${schema.name}\" from ${dbDefault ?? 'none'} to ${schemaDefault ?? 'none'}`,\n\t\t\tmeta: { default: schema.default, oldDefault: db.default },\n\t\t});\n\t}\n\n\t// Collation change\n\tif ((schema.collation ?? null) !== (db.collation ?? null)) {\n\t\tchanges.push({\n\t\t\tkind: 'alter_column_collation',\n\t\t\ttable: tableName,\n\t\t\tcolumn: schema.name,\n\t\t\tdestructive: false,\n\t\t\tdetails: `Change collation of \"${schema.name}\" to ${schema.collation ?? 'default'}`,\n\t\t\tmeta: { column: schema },\n\t\t});\n\t}\n\n\t// Identity change\n\tif ((schema.identity ?? null) !== (db.identity ?? null)) {\n\t\tchanges.push({\n\t\t\tkind: 'alter_column_identity',\n\t\t\ttable: tableName,\n\t\t\tcolumn: schema.name,\n\t\t\tdestructive: false,\n\t\t\tdetails: `Change identity of \"${schema.name}\" to ${schema.identity ?? 'none'}`,\n\t\t\tmeta: { column: schema, previousIdentity: db.identity },\n\t\t});\n\t}\n}\n\n// ============================================================================\n// Type Equivalence\n// ============================================================================\n\n/**\n * Type equivalence classes — groups of ColumnTypes that map to the same\n * PostgreSQL data type and should not trigger alter_column_type.\n *\n * - timestamp/datetime → both are TIMESTAMPTZ\n *\n * Note: number/integer are NOT equivalent because `number` can represent\n * NUMERIC(precision,scale) via originalDbType, which differs from INTEGER.\n */\nconst TYPE_EQUIVALENCE: ReadonlyMap<string, string> = new Map([\n\t['timestamp', 'timestamptz'],\n\t['datetime', 'timestamptz'],\n]);\n\nfunction areTypesEquivalent(a: string, b: string): boolean {\n\tif (a === b) return true;\n\tconst canonA = TYPE_EQUIVALENCE.get(a);\n\tconst canonB = TYPE_EQUIVALENCE.get(b);\n\treturn canonA !== undefined && canonA === canonB;\n}\n\n// ============================================================================\n// Default Normalization\n// ============================================================================\n\n/**\n * Normalize default values for comparison.\n *\n * PostgreSQL introspection returns defaults with type casts and quoting:\n * 'deploy'::character varying → deploy\n * ''::text → (empty string)\n * 42::integer → 42\n * gen_random_uuid() → gen_random_uuid()\n * now() → now()\n */\nfunction normalizeDefault(value: unknown): string | undefined {\n\tif (value === undefined || value === null) return undefined;\n\n\tlet str: string;\n\tif (typeof value === 'object' && value !== null && 'sql' in value) {\n\t\tconst rawSql = (value as Record<string, unknown>).sql;\n\t\tif (typeof rawSql !== 'string') {\n\t\t\tthrow new Error(\n\t\t\t\t`normalizeDefault({ sql }): expected string, got ${typeof rawSql}`,\n\t\t\t);\n\t\t}\n\t\tstr = rawSql;\n\t} else {\n\t\tstr = String(value);\n\t}\n\n\t// Strip PostgreSQL type casts: 'value'::type → value\n\t// Handles: 'deploy'::character varying, ''::text, '{}'::text[]\n\tstr = str.replace(/^'(.*)'::[\\w\\s[\\]]+$/, '$1');\n\n\t// Also strip unquoted casts: 42::integer → 42\n\t// But NOT function calls like gen_random_uuid()\n\tif (!str.includes('(')) {\n\t\tstr = str.replace(/^(.+?)::[\\w\\s[\\]]+$/, '$1');\n\t}\n\n\treturn str;\n}\n\n// ============================================================================\n// Primary Key Comparison\n// ============================================================================\n\nfunction comparePrimaryKeys(\n\tschema: TableIR,\n\tdb: TableIR,\n\tchanges: SchemaChange[],\n): void {\n\tconst schemaPK = normalizePK(schema.primaryKey);\n\tconst dbPK = normalizePK(db.primaryKey);\n\n\tconst sameKeys =\n\t\tschemaPK.length === dbPK.length &&\n\t\tschemaPK.every((col, i) => col === dbPK[i]);\n\n\tif (sameKeys) return;\n\n\t// PK in schema but not in DB → add\n\tif (schemaPK.length > 0 && dbPK.length === 0) {\n\t\tchanges.push({\n\t\t\tkind: 'add_primary_key',\n\t\t\ttable: schema.name,\n\t\t\tdestructive: false,\n\t\t\tdetails: `Add primary key (${schemaPK.join(', ')})`,\n\t\t\tmeta: { columns: schemaPK },\n\t\t});\n\t\treturn;\n\t}\n\n\t// PK in DB but not in schema → drop\n\tif (schemaPK.length === 0 && dbPK.length > 0) {\n\t\tchanges.push({\n\t\t\tkind: 'drop_primary_key',\n\t\t\ttable: schema.name,\n\t\t\tdestructive: true,\n\t\t\tdetails: `Drop primary key (${dbPK.join(', ')})`,\n\t\t});\n\t\treturn;\n\t}\n\n\t// PK differs → drop + add\n\tchanges.push({\n\t\tkind: 'drop_primary_key',\n\t\ttable: schema.name,\n\t\tdestructive: true,\n\t\tdetails: `Drop primary key (${dbPK.join(', ')})`,\n\t});\n\tchanges.push({\n\t\tkind: 'add_primary_key',\n\t\ttable: schema.name,\n\t\tdestructive: false,\n\t\tdetails: `Add primary key (${schemaPK.join(', ')})`,\n\t\tmeta: { columns: schemaPK },\n\t});\n}\n\nfunction normalizePK(pk: string | readonly string[] | undefined): string[] {\n\tif (!pk) return [];\n\tif (typeof pk === 'string') return [pk];\n\treturn Array.from(pk);\n}\n\n// ============================================================================\n// Foreign Key Comparison\n// ============================================================================\n\nfunction compareForeignKeys(\n\tschema: TableIR,\n\tdb: TableIR,\n\tchanges: SchemaChange[],\n): void {\n\tconst schemaFKs = schema.foreignKeys;\n\tconst dbFKs = db.foreignKeys;\n\n\t// Build a key for each FK: \"localCols→targetTable(targetCols)\"\n\tconst schemaFKMap = new Map(schemaFKs.map((fk) => [fkKey(fk), fk]));\n\tconst dbFKMap = new Map(dbFKs.map((fk) => [fkKey(fk), fk]));\n\n\t// FKs in schema but not in DB → add\n\tfor (const [key, fk] of schemaFKMap) {\n\t\tif (!dbFKMap.has(key)) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'add_foreign_key',\n\t\t\t\ttable: schema.name,\n\t\t\t\tdestructive: false,\n\t\t\t\tdetails: `Add FK (${fk.columns.join(', ')}) → ${fk.references.table}(${fk.references.columns.join(', ')})`,\n\t\t\t\tmeta: { fk },\n\t\t\t});\n\t\t} else {\n\t\t\t// FK exists in both — check onDelete, onUpdate, deferred, and notValid\n\t\t\tconst dbFK = dbFKMap.get(key)!;\n\t\t\tconst schemaOnDelete = fk.onDelete ?? 'NO ACTION';\n\t\t\tconst dbOnDelete = dbFK.onDelete ?? 'NO ACTION';\n\t\t\tconst schemaOnUpdate = fk.onUpdate ?? 'NO ACTION';\n\t\t\tconst dbOnUpdate = dbFK.onUpdate ?? 'NO ACTION';\n\t\t\tconst schemaDeferred = fk.deferred ?? false;\n\t\t\tconst dbDeferred = dbFK.deferred ?? false;\n\t\t\tif (\n\t\t\t\tschemaOnDelete !== dbOnDelete ||\n\t\t\t\tschemaOnUpdate !== dbOnUpdate ||\n\t\t\t\tschemaDeferred !== dbDeferred\n\t\t\t) {\n\t\t\t\tchanges.push({\n\t\t\t\t\tkind: 'alter_foreign_key',\n\t\t\t\t\ttable: schema.name,\n\t\t\t\t\tdestructive: false,\n\t\t\t\t\tdetails: `Alter FK (${fk.columns.join(', ')}) — onDelete/onUpdate/deferred changed`,\n\t\t\t\t\tmeta: { fk, previousOnDelete: dbOnDelete, oldFk: dbFK },\n\t\t\t\t});\n\t\t\t}\n\t\t\t// notValid: true in DB but false/undefined in schema → emit validate_constraint\n\t\t\tconst dbNotValid = dbFK.notValid ?? false;\n\t\t\tconst schemaNotValid = fk.notValid ?? false;\n\t\t\tif (dbNotValid && !schemaNotValid) {\n\t\t\t\tchanges.push({\n\t\t\t\t\tkind: 'validate_constraint',\n\t\t\t\t\ttable: schema.name,\n\t\t\t\t\tdestructive: false,\n\t\t\t\t\tdetails: `Validate FK constraint on (${fk.columns.join(', ')})`,\n\t\t\t\t\tmeta: { fk },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// FKs in DB but not in schema → drop\n\tfor (const [key, fk] of dbFKMap) {\n\t\tif (!schemaFKMap.has(key)) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'drop_foreign_key',\n\t\t\t\ttable: schema.name,\n\t\t\t\tdestructive: true,\n\t\t\t\tdetails: `Drop FK (${fk.columns.join(', ')}) → ${fk.references.table}(${fk.references.columns.join(', ')})`,\n\t\t\t\tmeta: { fk },\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction fkKey(fk: ForeignKeyIR): string {\n\treturn `${fk.columns.join(',')}→${fk.references.table}(${fk.references.columns.join(',')})`;\n}\n\n// ============================================================================\n// Index Comparison\n// ============================================================================\n\nfunction compareIndexes(\n\tschema: TableIR,\n\tdb: TableIR,\n\tchanges: SchemaChange[],\n): void {\n\t// Build the set of FK auto-index keys.\n\t// generateDDL (fkAutoIndex=true default) creates an index for every single-column FK that\n\t// does not already have an explicit index. These indexes are managed automatically — they\n\t// should never trigger create_index or drop_index diffs.\n\tconst explicitIndexCols = new Set(\n\t\tschema.indexes.flatMap((idx) =>\n\t\t\tidx.columns.length === 1 ? idx.columns : [],\n\t\t),\n\t);\n\tconst autoFkIndexKeys = new Set(\n\t\tschema.foreignKeys\n\t\t\t.filter(\n\t\t\t\t(fk) =>\n\t\t\t\t\tfk.columns.length === 1 &&\n\t\t\t\t\tfk.columns[0] !== undefined &&\n\t\t\t\t\t!explicitIndexCols.has(fk.columns[0]),\n\t\t\t)\n\t\t\t.map((fk) =>\n\t\t\t\tindexKey({\n\t\t\t\t\tcolumns: fk.columns,\n\t\t\t\t\tunique: false,\n\t\t\t\t}),\n\t\t\t),\n\t);\n\n\t// Index identity: columns + unique flag (name is cosmetic)\n\tconst schemaIdxMap = new Map(\n\t\tschema.indexes.map((idx) => [indexKey(idx), idx]),\n\t);\n\tconst dbIdxMap = new Map(db.indexes.map((idx) => [indexKey(idx), idx]));\n\n\t// Explicit indexes in schema but not in DB → create\n\tfor (const [key, idx] of schemaIdxMap) {\n\t\tif (!dbIdxMap.has(key)) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'create_index',\n\t\t\t\ttable: schema.name,\n\t\t\t\tdestructive: false,\n\t\t\t\tdetails: `Create ${idx.unique ? 'unique ' : ''}index on (${idx.columns.join(', ')})`,\n\t\t\t\tmeta: { index: idx },\n\t\t\t});\n\t\t}\n\t}\n\n\t// Auto-unique index keys: col.unique=true generates an implicit UNIQUE index in the DB,\n\t// but this does not appear in ModelIR's indexes[] array. These are auto-managed and must\n\t// never trigger a drop_index diff.\n\tconst autoUniqueIndexKeys = new Set(\n\t\tschema.columns\n\t\t\t.filter((col) => col.unique === true)\n\t\t\t.map((col) =>\n\t\t\t\tindexKey({\n\t\t\t\t\tcolumns: [col.name],\n\t\t\t\t\tunique: true,\n\t\t\t\t}),\n\t\t\t),\n\t);\n\n\t// Indexes in DB but not in schema → drop (skip auto-FK and auto-unique indexes — they are auto-managed)\n\tfor (const [key, idx] of dbIdxMap) {\n\t\tif (\n\t\t\t!schemaIdxMap.has(key) &&\n\t\t\t!autoFkIndexKeys.has(key) &&\n\t\t\t!autoUniqueIndexKeys.has(key)\n\t\t) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'drop_index',\n\t\t\t\ttable: schema.name,\n\t\t\t\tdestructive: false,\n\t\t\t\tdetails: `Drop index ${idx.name ?? `on (${idx.columns.join(', ')})`}`,\n\t\t\t\tmeta: { index: idx },\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction indexKey(idx: IndexIR): string {\n\tconst parts = [\n\t\tidx.columns.join(','),\n\t\tidx.unique ? 'unique' : 'nonunique',\n\t\tidx.method ?? 'btree',\n\t\tidx.where ?? '',\n\t\t(idx.expressions ?? []).join(','),\n\t\tidx.opclass\n\t\t\t? Object.entries(idx.opclass)\n\t\t\t\t\t.sort()\n\t\t\t\t\t.map(([k, v]) => `${k}=${v}`)\n\t\t\t\t\t.join(',')\n\t\t\t: '',\n\t\tidx.with\n\t\t\t? Object.entries(idx.with)\n\t\t\t\t\t.sort()\n\t\t\t\t\t.map(([k, v]) => `${k}=${v}`)\n\t\t\t\t\t.join(',')\n\t\t\t: '',\n\t];\n\treturn parts.join(':');\n}\n\n// ============================================================================\n// Summary Builder\n// ============================================================================\n\n// ============================================================================\n// compareCheckConstraints\n// ============================================================================\n// ============================================================================\n// Comments\n// ============================================================================\n\nfunction compareComments(\n\tschema: TableIR,\n\tdb: TableIR,\n\tchanges: SchemaChange[],\n): void {\n\t// Table-level comment\n\tif ((schema.comment ?? null) !== (db.comment ?? null)) {\n\t\tif (schema.comment) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'add_comment',\n\t\t\t\ttable: schema.name,\n\t\t\t\tdestructive: false,\n\t\t\t\tdetails: `Set comment on table \"${schema.name}\"`,\n\t\t\t\tmeta: { comment: schema.comment, target: 'table' },\n\t\t\t});\n\t\t} else {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'drop_comment',\n\t\t\t\ttable: schema.name,\n\t\t\t\tdestructive: false,\n\t\t\t\tdetails: `Remove comment from table \"${schema.name}\"`,\n\t\t\t\tmeta: { target: 'table' },\n\t\t\t});\n\t\t}\n\t}\n\n\t// Column-level comments\n\tfor (const schemaCol of schema.columns) {\n\t\tconst dbCol = db.columns.find((c) => c.name === schemaCol.name);\n\t\tif (!dbCol) continue;\n\t\tif ((schemaCol.comment ?? null) !== (dbCol.comment ?? null)) {\n\t\t\tif (schemaCol.comment) {\n\t\t\t\tchanges.push({\n\t\t\t\t\tkind: 'add_comment',\n\t\t\t\t\ttable: schema.name,\n\t\t\t\t\tcolumn: schemaCol.name,\n\t\t\t\t\tdestructive: false,\n\t\t\t\t\tdetails: `Set comment on \"${schema.name}\".\"${schemaCol.name}\"`,\n\t\t\t\t\tmeta: { comment: schemaCol.comment, target: 'column' },\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tchanges.push({\n\t\t\t\t\tkind: 'drop_comment',\n\t\t\t\t\ttable: schema.name,\n\t\t\t\t\tcolumn: schemaCol.name,\n\t\t\t\t\tdestructive: false,\n\t\t\t\t\tdetails: `Remove comment from \"${schema.name}\".\"${schemaCol.name}\"`,\n\t\t\t\t\tmeta: { target: 'column' },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n\n// ============================================================================\n// Partition Diff\n// ============================================================================\n\n/**\n * Compare partition configs between schema and DB.\n * PostgreSQL does not support ALTER TABLE ... SET PARTITION STRATEGY.\n * Any mismatch (add, remove, or change) requires DROP + CREATE.\n * We emit a destructive drop_table change with isPartitionChange=true as a marker.\n */\nfunction comparePartitions(\n\tschema: TableIR,\n\tdb: TableIR,\n\tchanges: SchemaChange[],\n): void {\n\tconst sp = schema.partition as PartitionIR | undefined;\n\tconst dp = db.partition as PartitionIR | undefined;\n\n\tif (!sp && !dp) return; // Neither has partition — nothing to do\n\n\tif (sp && dp) {\n\t\t// Both have partition — check if config matches\n\t\tconst sameStrategy = sp.strategy === dp.strategy;\n\t\tconst sameCols = sp.columns.join(',') === dp.columns.join(',');\n\t\tif (!sameStrategy || !sameCols) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'drop_table',\n\t\t\t\ttable: schema.name,\n\t\t\t\tdestructive: true,\n\t\t\t\tdetails: `Cannot alter partition strategy of \"${schema.name}\" (${dp.strategy} → ${sp.strategy}). Requires DROP + CREATE (data migration needed).`,\n\t\t\t\tmeta: { isPartitionChange: true },\n\t\t\t});\n\t\t}\n\t\t// Same config → no change needed\n\t} else if (sp && !dp) {\n\t\t// Adding partition to non-partitioned table\n\t\tchanges.push({\n\t\t\tkind: 'drop_table',\n\t\t\ttable: schema.name,\n\t\t\tdestructive: true,\n\t\t\tdetails: `Cannot add partition to existing table \"${schema.name}\". Requires DROP + CREATE (data migration needed).`,\n\t\t\tmeta: { isPartitionChange: true },\n\t\t});\n\t} else {\n\t\t// Removing partition from partitioned table\n\t\tchanges.push({\n\t\t\tkind: 'drop_table',\n\t\t\ttable: schema.name,\n\t\t\tdestructive: true,\n\t\t\tdetails: `Cannot remove partition from existing table \"${schema.name}\". Requires DROP + CREATE (data migration needed).`,\n\t\t\tmeta: { isPartitionChange: true },\n\t\t});\n\t}\n}\n\nfunction compareCheckConstraints(\n\tschema: TableIR,\n\tdb: TableIR,\n\tchanges: SchemaChange[],\n): void {\n\tconst schemaChecks = schema.checkConstraints ?? [];\n\tconst dbChecks = db.checkConstraints ?? [];\n\n\t// Build map by constraint name\n\tconst schemaMap = new Map(schemaChecks.map((c) => [c.name, c]));\n\tconst dbMap = new Map(dbChecks.map((c) => [c.name, c]));\n\n\t// In schema but not in DB → add\n\tfor (const [name, check] of schemaMap) {\n\t\tif (!dbMap.has(name)) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'add_check_constraint',\n\t\t\t\ttable: schema.name,\n\t\t\t\tdestructive: false,\n\t\t\t\tdetails: `Add CHECK constraint \"${name}\" ${check.expression}`,\n\t\t\t\tmeta: { check },\n\t\t\t});\n\t\t} else {\n\t\t\t// Both have it — compare expression and notValid\n\t\t\tconst dbCheck = dbMap.get(name)!;\n\t\t\tif (check.expression !== dbCheck.expression) {\n\t\t\t\t// Expression changed → drop + re-add\n\t\t\t\tchanges.push({\n\t\t\t\t\tkind: 'drop_check_constraint',\n\t\t\t\t\ttable: schema.name,\n\t\t\t\t\tdestructive: true,\n\t\t\t\t\tdetails: `Drop CHECK constraint \"${name}\" (expression changed)`,\n\t\t\t\t\tmeta: { check: dbCheck },\n\t\t\t\t});\n\t\t\t\tchanges.push({\n\t\t\t\t\tkind: 'add_check_constraint',\n\t\t\t\t\ttable: schema.name,\n\t\t\t\t\tdestructive: false,\n\t\t\t\t\tdetails: `Add CHECK constraint \"${name}\" ${check.expression}`,\n\t\t\t\t\tmeta: { check },\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// notValid: true in DB but false/undefined in schema → emit validate_constraint\n\t\t\t\tconst dbNotValid = dbCheck.notValid ?? false;\n\t\t\t\tconst schemaNotValid = check.notValid ?? false;\n\t\t\t\tif (dbNotValid && !schemaNotValid) {\n\t\t\t\t\tchanges.push({\n\t\t\t\t\t\tkind: 'validate_constraint',\n\t\t\t\t\t\ttable: schema.name,\n\t\t\t\t\t\tdestructive: false,\n\t\t\t\t\t\tdetails: `Validate CHECK constraint \"${name}\"`,\n\t\t\t\t\t\tmeta: { check },\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// In DB but not in schema → drop\n\tfor (const [name, check] of dbMap) {\n\t\tif (!schemaMap.has(name)) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'drop_check_constraint',\n\t\t\t\ttable: schema.name,\n\t\t\t\tdestructive: true,\n\t\t\t\tdetails: `Drop CHECK constraint \"${name}\"`,\n\t\t\t\tmeta: { check },\n\t\t\t});\n\t\t}\n\t}\n}\n\n// ============================================================================\n// ENUM comparison (schema-level, not table-level)\n// ============================================================================\n\nfunction compareEnums(\n\tschema: ModelIR,\n\tdb: ModelIR,\n\tchanges: SchemaChange[],\n): void {\n\tconst schemaEnums = schema.enums ?? new Map<string, EnumIR>();\n\tconst dbEnums = db.enums ?? new Map<string, EnumIR>();\n\n\t// Enums in schema but not in DB → create\n\tfor (const [name, enumDef] of schemaEnums) {\n\t\tif (!dbEnums.has(name)) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'create_enum',\n\t\t\t\ttable: '',\n\t\t\t\tdestructive: false,\n\t\t\t\tdetails: `Create enum \"${name}\" with values (${enumDef.values.join(', ')})`,\n\t\t\t\tmeta: { enum: enumDef },\n\t\t\t});\n\t\t} else {\n\t\t\t// Exists in both → check for new values\n\t\t\tconst dbEnum = dbEnums.get(name)!;\n\t\t\t// Find values in schema that are not in DB → add\n\t\t\tfor (let i = 0; i < enumDef.values.length; i++) {\n\t\t\t\tconst val = enumDef.values[i]!;\n\t\t\t\tif (!dbEnum.values.includes(val)) {\n\t\t\t\t\tconst prevVal = i > 0 ? enumDef.values[i - 1] : undefined;\n\t\t\t\t\tchanges.push({\n\t\t\t\t\t\tkind: 'alter_enum_add_value',\n\t\t\t\t\t\ttable: '',\n\t\t\t\t\t\tdestructive: false,\n\t\t\t\t\t\tdetails: `Add value '${val}' to enum \"${name}\"${prevVal ? ` after '${prevVal}'` : ''}`,\n\t\t\t\t\t\tmeta: { enum: enumDef, value: val, after: prevVal },\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Values in DB but not in schema → PG limitation, flag as error\n\t\t\tfor (const val of dbEnum.values) {\n\t\t\t\tif (!enumDef.values.includes(val)) {\n\t\t\t\t\tchanges.push({\n\t\t\t\t\t\tkind: 'drop_enum',\n\t\t\t\t\t\ttable: '',\n\t\t\t\t\t\tdestructive: true,\n\t\t\t\t\t\tdetails: `Cannot remove value '${val}' from enum \"${name}\" — PostgreSQL limitation. Requires DROP TYPE + CREATE TYPE (data migration needed).`,\n\t\t\t\t\t\tmeta: { enum: dbEnum, removedValue: val, isValueRemoval: true },\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Enums in DB but not in schema → drop\n\tfor (const [name, enumDef] of dbEnums) {\n\t\tif (!schemaEnums.has(name)) {\n\t\t\t// Scan DB tables for columns still referencing this enum type.\n\t\t\t// These must be cast to text before the DROP TYPE can succeed.\n\t\t\tconst referencingColumns: Array<{ table: string; column: string }> = [];\n\t\t\tfor (const [tableName, tableIR] of db.tables) {\n\t\t\t\tfor (const col of tableIR.columns) {\n\t\t\t\t\tif (col.originalDbType === name) {\n\t\t\t\t\t\treferencingColumns.push({ table: tableName, column: col.name });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tchanges.push({\n\t\t\t\tkind: 'drop_enum',\n\t\t\t\ttable: '',\n\t\t\t\tdestructive: true,\n\t\t\t\tdetails: `Drop enum \"${name}\"`,\n\t\t\t\tmeta: { enum: enumDef, referencingColumns },\n\t\t\t});\n\t\t}\n\t}\n}\n\n// ============================================================================\n// Extension Diff\n// ============================================================================\n\nfunction compareExtensions(\n\tschema: ModelIR,\n\tdb: ModelIR,\n\tchanges: SchemaChange[],\n): void {\n\tconst schemaExts = new Set(schema.extensions ?? []);\n\tconst dbExts = new Set(db.extensions ?? []);\n\n\tfor (const ext of schemaExts) {\n\t\tif (!dbExts.has(ext)) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'create_extension',\n\t\t\t\ttable: '',\n\t\t\t\tdestructive: false,\n\t\t\t\tdetails: `Create extension \"${ext}\"`,\n\t\t\t\tmeta: { extension: ext },\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const ext of dbExts) {\n\t\tif (!schemaExts.has(ext)) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'drop_extension',\n\t\t\t\ttable: '',\n\t\t\t\tdestructive: true,\n\t\t\t\tdetails: `Drop extension \"${ext}\"`,\n\t\t\t\tmeta: { extension: ext },\n\t\t\t});\n\t\t}\n\t}\n}\n\n// ============================================================================\n// Sequence Diff\n// ============================================================================\n\nfunction compareSequences(\n\tschema: ModelIR,\n\tdb: ModelIR,\n\tchanges: SchemaChange[],\n): void {\n\tconst schemaSeqs = schema.sequences ?? new Map<string, SequenceIR>();\n\tconst dbSeqs = db.sequences ?? new Map<string, SequenceIR>();\n\n\t// Sequences in schema but not in DB → create\n\tfor (const [name, seq] of schemaSeqs) {\n\t\tif (!dbSeqs.has(name)) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'create_sequence',\n\t\t\t\ttable: '',\n\t\t\t\tdestructive: false,\n\t\t\t\tdetails: `Create sequence \"${name}\"`,\n\t\t\t\tmeta: { sequence: seq },\n\t\t\t});\n\t\t} else {\n\t\t\tconst dbSeq = dbSeqs.get(name)!;\n\t\t\t// Compare relevant properties\n\t\t\tif (\n\t\t\t\tseq.startWith !== dbSeq.startWith ||\n\t\t\t\tseq.incrementBy !== dbSeq.incrementBy ||\n\t\t\t\tseq.minValue !== dbSeq.minValue ||\n\t\t\t\tseq.maxValue !== dbSeq.maxValue ||\n\t\t\t\tseq.cycle !== dbSeq.cycle\n\t\t\t) {\n\t\t\t\tchanges.push({\n\t\t\t\t\tkind: 'alter_sequence',\n\t\t\t\t\ttable: '',\n\t\t\t\t\tdestructive: false,\n\t\t\t\t\tdetails: `Alter sequence \"${name}\"`,\n\t\t\t\t\tmeta: { sequence: seq, previousSequence: dbSeq },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// Sequences in DB but not in schema → drop\n\tfor (const [name, seq] of dbSeqs) {\n\t\tif (!schemaSeqs.has(name)) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'drop_sequence',\n\t\t\t\ttable: '',\n\t\t\t\tdestructive: true,\n\t\t\t\tdetails: `Drop sequence \"${name}\"`,\n\t\t\t\tmeta: { sequence: seq },\n\t\t\t});\n\t\t}\n\t}\n}\n\n// ============================================================================\n// RLS Policy Comparison\n// ============================================================================\n\nfunction comparePolicies(\n\tschema: TableIR,\n\tdb: TableIR,\n\tchanges: SchemaChange[],\n): void {\n\tconst schemaRlsEnabled = schema.rlsEnabled ?? false;\n\tconst dbRlsEnabled = db.rlsEnabled ?? false;\n\n\t// RLS enabled state changed\n\tif (schemaRlsEnabled && !dbRlsEnabled) {\n\t\tchanges.push({\n\t\t\tkind: 'enable_rls',\n\t\t\ttable: schema.name,\n\t\t\tdestructive: false,\n\t\t\tdetails: `Enable RLS on table \"${schema.name}\"`,\n\t\t});\n\t} else if (!schemaRlsEnabled && dbRlsEnabled) {\n\t\tchanges.push({\n\t\t\tkind: 'disable_rls',\n\t\t\ttable: schema.name,\n\t\t\tdestructive: false,\n\t\t\tdetails: `Disable RLS on table \"${schema.name}\"`,\n\t\t});\n\t}\n\n\tconst schemaPolicies = schema.policies ?? [];\n\tconst dbPolicies = db.policies ?? [];\n\n\tconst schemaMap = new Map<string, PolicyIR>(\n\t\tschemaPolicies.map((p) => [p.name, p]),\n\t);\n\tconst dbMap = new Map<string, PolicyIR>(dbPolicies.map((p) => [p.name, p]));\n\n\t// In schema but not in DB → create\n\tfor (const [name, policy] of schemaMap) {\n\t\tif (!dbMap.has(name)) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'create_policy',\n\t\t\t\ttable: schema.name,\n\t\t\t\tdestructive: false,\n\t\t\t\tdetails: `Create policy \"${name}\" on \"${schema.name}\"`,\n\t\t\t\tmeta: { policy },\n\t\t\t});\n\t\t} else {\n\t\t\t// Policy exists in both — compare all fields; if changed → drop + recreate\n\t\t\tconst dbPolicy = dbMap.get(name)!;\n\t\t\tconst changed =\n\t\t\t\tpolicy.command !== dbPolicy.command ||\n\t\t\t\tpolicy.using !== dbPolicy.using ||\n\t\t\t\tpolicy.withCheck !== dbPolicy.withCheck ||\n\t\t\t\tpolicy.permissive !== dbPolicy.permissive ||\n\t\t\t\tJSON.stringify(policy.roles ?? []) !==\n\t\t\t\t\tJSON.stringify(dbPolicy.roles ?? []);\n\t\t\tif (changed) {\n\t\t\t\tchanges.push({\n\t\t\t\t\tkind: 'drop_policy',\n\t\t\t\t\ttable: schema.name,\n\t\t\t\t\tdestructive: false,\n\t\t\t\t\tdetails: `Drop policy \"${name}\" on \"${schema.name}\" (changed)`,\n\t\t\t\t\tmeta: { policy: dbPolicy },\n\t\t\t\t});\n\t\t\t\tchanges.push({\n\t\t\t\t\tkind: 'create_policy',\n\t\t\t\t\ttable: schema.name,\n\t\t\t\t\tdestructive: false,\n\t\t\t\t\tdetails: `Create policy \"${name}\" on \"${schema.name}\"`,\n\t\t\t\t\tmeta: { policy },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// In DB but not in schema → drop\n\tfor (const [name, policy] of dbMap) {\n\t\tif (!schemaMap.has(name)) {\n\t\t\tchanges.push({\n\t\t\t\tkind: 'drop_policy',\n\t\t\t\ttable: schema.name,\n\t\t\t\tdestructive: false,\n\t\t\t\tdetails: `Drop policy \"${name}\" on \"${schema.name}\"`,\n\t\t\t\tmeta: { policy },\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction buildSummary(changes: readonly SchemaChange[]): DiffSummary {\n\tconst tables = { added: 0, dropped: 0 };\n\tconst columns = { added: 0, dropped: 0, altered: 0 };\n\tconst indexes = { added: 0, dropped: 0 };\n\tconst constraints = { added: 0, dropped: 0, altered: 0 };\n\n\tfor (const c of changes) {\n\t\tswitch (c.kind) {\n\t\t\tcase 'create_table':\n\t\t\t\ttables.added++;\n\t\t\t\tbreak;\n\t\t\tcase 'drop_table':\n\t\t\t\ttables.dropped++;\n\t\t\t\tbreak;\n\t\t\tcase 'add_column':\n\t\t\t\tcolumns.added++;\n\t\t\t\tbreak;\n\t\t\tcase 'drop_column':\n\t\t\t\tcolumns.dropped++;\n\t\t\t\tbreak;\n\t\t\tcase 'alter_column_type':\n\t\t\tcase 'alter_column_nullable':\n\t\t\tcase 'alter_column_default':\n\t\t\t\tcolumns.altered++;\n\t\t\t\tbreak;\n\t\t\tcase 'add_primary_key':\n\t\t\tcase 'add_foreign_key':\n\t\t\tcase 'add_check_constraint':\n\t\t\t\tconstraints.added++;\n\t\t\t\tbreak;\n\t\t\tcase 'drop_primary_key':\n\t\t\tcase 'drop_foreign_key':\n\t\t\tcase 'drop_check_constraint':\n\t\t\t\tconstraints.dropped++;\n\t\t\t\tbreak;\n\t\t\tcase 'alter_foreign_key':\n\t\t\t\tconstraints.altered++;\n\t\t\t\tbreak;\n\t\t\tcase 'create_index':\n\t\t\t\tindexes.added++;\n\t\t\t\tbreak;\n\t\t\tcase 'drop_index':\n\t\t\t\tindexes.dropped++;\n\t\t\t\tbreak;\n\t\t\tcase 'create_enum':\n\t\t\tcase 'alter_enum_add_value':\n\t\t\tcase 'drop_enum':\n\t\t\t\t// ENUM changes are schema-level; not counted in table/column/index summaries\n\t\t\t\tbreak;\n\t\t\tcase 'alter_column_collation':\n\t\t\tcase 'alter_column_identity':\n\t\t\t\tcolumns.altered++;\n\t\t\t\tbreak;\n\t\t\tcase 'add_comment':\n\t\t\tcase 'drop_comment':\n\t\t\tcase 'create_extension':\n\t\t\tcase 'drop_extension':\n\t\t\tcase 'create_sequence':\n\t\t\tcase 'alter_sequence':\n\t\t\tcase 'drop_sequence':\n\t\t\tcase 'enable_rls':\n\t\t\tcase 'disable_rls':\n\t\t\tcase 'create_policy':\n\t\t\tcase 'drop_policy':\n\t\t\t\t// Schema-level or metadata changes; not counted in table/column/index/constraint summaries\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn { tables, columns, indexes, constraints };\n}\n","/**\n * EXPLAIN Statement Compiler\n *\n * Generates PostgreSQL EXPLAIN statements with various options.\n * Supports:\n * - ANALYZE (execute and show actual run times)\n * - FORMAT (text, json, xml, yaml)\n * - VERBOSE, COSTS, BUFFERS, TIMING, SETTINGS\n */\n\nimport type { Node } from '@pgsql/types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Output format for EXPLAIN results.\n */\nexport type ExplainFormat = 'text' | 'json' | 'xml' | 'yaml';\n\n/**\n * Options for EXPLAIN statement.\n */\nexport interface ExplainOptions {\n\t/** Execute the query and show actual run times */\n\tanalyze?: boolean;\n\t/** Show more detailed output */\n\tverbose?: boolean;\n\t/** Show cost estimates (default: true) */\n\tcosts?: boolean;\n\t/** Show buffer usage (requires analyze) */\n\tbuffers?: boolean;\n\t/** Show actual timing (requires analyze) */\n\ttiming?: boolean;\n\t/** Show non-default settings */\n\tsettings?: boolean;\n\t/** Output format */\n\tformat?: ExplainFormat;\n}\n\n// ============================================================================\n// EXPLAIN Builder\n// ============================================================================\n\n/**\n * Build an EXPLAIN statement wrapping a query.\n *\n * @param query - The query to explain (SelectStmt, InsertStmt, etc.)\n * @param options - EXPLAIN options\n * @returns ExplainStmt AST node\n *\n * @example\n * ```typescript\n * const selectAst = { SelectStmt: { ... } };\n * const explainAst = buildExplain(selectAst, { analyze: true, format: 'json' });\n * // Produces: EXPLAIN (ANALYZE, FORMAT JSON) SELECT ...\n * ```\n */\nexport function buildExplain(query: Node, options: ExplainOptions = {}): Node {\n\tconst defElems: Node[] = [];\n\n\t// Add options in standard order\n\tif (options.analyze !== undefined) {\n\t\tdefElems.push(buildDefElem('analyze', options.analyze));\n\t}\n\n\tif (options.verbose !== undefined) {\n\t\tdefElems.push(buildDefElem('verbose', options.verbose));\n\t}\n\n\tif (options.costs !== undefined) {\n\t\tdefElems.push(buildDefElem('costs', options.costs));\n\t}\n\n\tif (options.buffers !== undefined) {\n\t\tdefElems.push(buildDefElem('buffers', options.buffers));\n\t}\n\n\tif (options.timing !== undefined) {\n\t\tdefElems.push(buildDefElem('timing', options.timing));\n\t}\n\n\tif (options.settings !== undefined) {\n\t\tdefElems.push(buildDefElem('settings', options.settings));\n\t}\n\n\tif (options.format) {\n\t\tdefElems.push(buildDefElem('format', options.format));\n\t}\n\n\tconst explainStmt: { query: Node; options?: Node[] } = { query };\n\tif (defElems.length > 0) {\n\t\texplainStmt.options = defElems;\n\t}\n\n\treturn { ExplainStmt: explainStmt };\n}\n\n/**\n * Build EXPLAIN ANALYZE with JSON format (common pattern).\n *\n * @param query - The query to explain\n * @returns ExplainStmt with ANALYZE and JSON format\n */\nexport function buildExplainAnalyzeJson(query: Node): Node {\n\treturn buildExplain(query, {\n\t\tanalyze: true,\n\t\tformat: 'json',\n\t});\n}\n\n/**\n * Build simple EXPLAIN (plan only, no execution).\n *\n * @param query - The query to explain\n * @returns ExplainStmt with default options\n */\nexport function buildExplainPlan(query: Node): Node {\n\treturn buildExplain(query);\n}\n\n/**\n * Build verbose EXPLAIN with costs and buffers.\n *\n * @param query - The query to explain\n * @returns ExplainStmt with verbose options\n */\nexport function buildExplainVerbose(query: Node): Node {\n\treturn buildExplain(query, {\n\t\tanalyze: true,\n\t\tverbose: true,\n\t\tbuffers: true,\n\t\ttiming: true,\n\t});\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Build a DefElem node for EXPLAIN options.\n *\n * @param name - Option name (analyze, verbose, format, etc.)\n * @param value - Option value (boolean or string)\n * @returns DefElem AST node\n */\nfunction buildDefElem(name: string, value: boolean | string): Node {\n\tlet arg: Node | undefined;\n\n\tif (typeof value === 'boolean') {\n\t\t// Boolean options: ANALYZE TRUE/FALSE\n\t\targ = {\n\t\t\tString: {\n\t\t\t\tsval: value ? 'true' : 'false',\n\t\t\t},\n\t\t};\n\t} else {\n\t\t// String options: FORMAT json\n\t\targ = {\n\t\t\tString: {\n\t\t\t\tsval: value,\n\t\t\t},\n\t\t};\n\t}\n\n\treturn {\n\t\tDefElem: {\n\t\t\tdefname: name,\n\t\t\targ,\n\t\t\tdefaction: 'DEFELEM_UNSPEC',\n\t\t},\n\t};\n}\n\n/**\n * Parse EXPLAIN JSON output to get execution statistics.\n *\n * @param jsonOutput - The JSON string from EXPLAIN (ANALYZE, FORMAT JSON)\n * @returns Parsed plan with execution statistics\n */\nexport function parseExplainJson(jsonOutput: string): ExplainPlan[] {\n\ttry {\n\t\tconst parsed = JSON.parse(jsonOutput);\n\t\treturn Array.isArray(parsed) ? parsed : [parsed];\n\t} catch {\n\t\tthrow new Error('Failed to parse EXPLAIN JSON output');\n\t}\n}\n\n/**\n * Parsed EXPLAIN plan structure (simplified).\n */\nexport interface ExplainPlan {\n\tPlan: {\n\t\t'Node Type': string;\n\t\t'Relation Name'?: string;\n\t\tAlias?: string;\n\t\t'Startup Cost'?: number;\n\t\t'Total Cost'?: number;\n\t\t'Plan Rows'?: number;\n\t\t'Plan Width'?: number;\n\t\t'Actual Startup Time'?: number;\n\t\t'Actual Total Time'?: number;\n\t\t'Actual Rows'?: number;\n\t\t'Actual Loops'?: number;\n\t\tPlans?: ExplainPlan['Plan'][];\n\t};\n\t'Planning Time'?: number;\n\t'Execution Time'?: number;\n\tTriggers?: unknown[];\n}\n\n/**\n * Extract total execution time from EXPLAIN ANALYZE JSON output.\n *\n * @param plans - Parsed EXPLAIN plans\n * @returns Total execution time in milliseconds\n */\nexport function getTotalExecutionTime(plans: ExplainPlan[]): number {\n\tif (plans.length === 0) return 0;\n\n\tconst plan = plans[0]!;\n\tconst planning = plan['Planning Time'] ?? 0;\n\tconst execution = plan['Execution Time'] ?? 0;\n\n\treturn planning + execution;\n}\n\n/**\n * Extract row counts from EXPLAIN ANALYZE JSON output.\n *\n * @param plans - Parsed EXPLAIN plans\n * @returns Object with estimated and actual row counts\n */\nexport function getRowEstimates(plans: ExplainPlan[]): {\n\testimated: number;\n\tactual: number;\n} {\n\tif (plans.length === 0) return { estimated: 0, actual: 0 };\n\n\tconst rootPlan = plans[0]?.Plan;\n\tif (!rootPlan) return { estimated: 0, actual: 0 };\n\n\treturn {\n\t\testimated: rootPlan['Plan Rows'] ?? 0,\n\t\tactual: rootPlan['Actual Rows'] ?? 0,\n\t};\n}\n","/**\n * ParadeDB Extension Wrappers\n *\n * Type-safe query builders for ParadeDB BM25 full-text search.\n * All functions return ExpressionRef instances that can be used in:\n * - SELECT: .column(score('id').as('score'))\n * - WHERE: .where(bm25Search('symbols', query, { name: 3.0, doc: 1.0 }))\n * - ORDER BY: .orderBy(score('id'), 'desc')\n *\n * @remarks\n * ParadeDB functions accept both named and positional arguments.\n * This module uses named args via namedArg() for parse(), which produces:\n * paradedb.parse(field => 'field_name', query_string => $1)\n * Named parameter syntax is supported via the NamedArgExpressionIntent (EXT-NAMED-PARAMS).\n */\n\nimport {\n\tarray,\n\tExpressionRef,\n\texprRef,\n\tfn,\n\tliteral,\n\tnamedArg,\n\top,\n\tparam,\n} from '@dbsp/core';\n\n/**\n * BM25 relevance score for a row.\n *\n * Use in SELECT and ORDER BY to retrieve and sort by full-text relevance.\n * Requires a BM25 index on the table.\n *\n * @param keyField - The key field of the BM25 index (typically the primary key, e.g. 'id')\n * @returns ExpressionRef that compiles to: paradedb.score(\"keyField\")\n *\n * @example\n * orm.select('symbols').column(score('id').as('score')).orderBy(score('id'), 'desc')\n * // → paradedb.score(\"id\") AS \"score\"\n */\nexport function score(keyField: string): ExpressionRef {\n\treturn fn('paradedb.score', exprRef(keyField));\n}\n\n/**\n * Parse a single-field BM25 query expression.\n *\n * Compiles to: paradedb.parse(field => 'field_name', query_string => $N)\n *\n * @param field - Column name to search in (must be indexed in the BM25 index)\n * @param query - Query string value (will be bound as a parameter)\n * @returns ExpressionRef for use with boost() or booleanSearch()\n *\n * @example\n * parse('name', 'hello world')\n * // → paradedb.parse(field => 'name', query_string => $1)\n */\nexport function parse(\n\tfield: string,\n\tquery: ExpressionRef | unknown,\n): ExpressionRef {\n\t// If query is already an ExpressionRef, pass it directly so fn() unwraps .intent.\n\t// Otherwise, wrap it in param() so it becomes a bound $N parameter.\n\tconst queryExpr: ExpressionRef =\n\t\tquery instanceof ExpressionRef ? query : param(query);\n\treturn fn(\n\t\t'paradedb.parse',\n\t\tnamedArg('field', literal(field)),\n\t\tnamedArg('query_string', queryExpr),\n\t);\n}\n\n/**\n * Apply a boost multiplier to a BM25 sub-expression.\n *\n * Compiles to: paradedb.boost(factor, expr)\n *\n * @param factor - Boost multiplier (e.g. 3.0 for 3x weight)\n * @param expr - Expression to boost (typically a parse() call)\n * @returns ExpressionRef for use with booleanSearch()\n *\n * @example\n * boost(3.0, parse('name', 'hello'))\n * // → paradedb.boost(3.0, paradedb.parse('name', $1))\n */\nexport function boost(factor: number, expr: ExpressionRef): ExpressionRef {\n\treturn fn('paradedb.boost', literal(factor), expr);\n}\n\n/**\n * Combine multiple BM25 sub-expressions with boolean OR logic.\n *\n * Compiles to: paradedb.boolean(expr1, expr2, ...)\n *\n * @param exprs - One or more sub-expressions (typically boost() calls)\n * @returns ExpressionRef for use on the right side of the @@@ operator\n *\n * @example\n * booleanSearch([boost(3.0, parse('name', q)), boost(1.0, parse('doc', q))])\n * // → paradedb.boolean(paradedb.boost(3.0, ...), paradedb.boost(1.0, ...))\n */\n/**\n * Combine multiple BM25 sub-expressions with boolean OR logic.\n *\n * Compiles to: paradedb.boolean(should => ARRAY[expr1, expr2, ...])\n *\n * @param exprs - One or more sub-expressions (typically boost() calls)\n * @returns ExpressionRef for use on the right side of the @@@ operator\n *\n * @example\n * booleanSearch([boost(3.0, parse('name', q)), boost(1.0, parse('doc', q))])\n * // → paradedb.boolean(should => ARRAY[paradedb.boost(3.0, ...), paradedb.boost(1.0, ...)])\n */\nexport function booleanSearch(exprs: ExpressionRef[]): ExpressionRef {\n\treturn fn('paradedb.boolean', namedArg('should', array(...exprs)));\n}\n\n/**\n * Full BM25 multi-field search with per-field boost weights.\n *\n * Produces: table @@@ paradedb.boolean(boost1, boost2, ...)\n *\n * Each field in `fieldBoosts` generates a `paradedb.boost(weight, paradedb.parse(field, $N))`\n * sub-expression. The same query string is used for all fields (single parameter binding).\n *\n * @param table - Table alias for the left side of the @@@ operator\n * @param query - Query string (bound as a single $N parameter, shared across all fields)\n * @param fieldBoosts - Map of column name → boost weight\n * @returns ExpressionRef for use in .where()\n *\n * @example\n * bm25Search('s', searchTerm, {\n * name_searchable: 3.0,\n * name: 1.0,\n * signature: 1.5,\n * doc_searchable: 1.0,\n * })\n * // → s @@@ paradedb.boolean(\n * // paradedb.boost(3.0, paradedb.parse('name_searchable', $1)),\n * // paradedb.boost(1.0, paradedb.parse('name', $1)),\n * // paradedb.boost(1.5, paradedb.parse('signature', $1)),\n * // paradedb.boost(1.0, paradedb.parse('doc_searchable', $1))\n * // )\n *\n * @remarks\n * The query parameter is shared: all parse() calls reference the same $N slot.\n * If you need different query strings per field, compose parse()/boost()/booleanSearch() manually.\n *\n * @remarks\n * ParadeDB's boolean() function accepts both positional args and the named\n * `should => ARRAY[...]` syntax. This wrapper uses positional args.\n * Named parameter syntax is deferred to EXT-NAMED-PARAMS.\n */\nexport function bm25Search(\n\ttable: string,\n\tquery: unknown,\n\tfieldBoosts: Record<string, number>,\n): ExpressionRef {\n\tconst queryParam = param(query);\n\tconst boostExprs = Object.entries(fieldBoosts).map(([field, weight]) =>\n\t\tboost(weight, fn('paradedb.parse', literal(field), queryParam)),\n\t);\n\tconst booleanExpr = booleanSearch(boostExprs);\n\treturn op('@@@', exprRef(table), booleanExpr);\n}\n","/**\n * PostgreSQL built-in function helpers.\n *\n * Thin wrappers around core expression primitives for common PostgreSQL functions.\n * Same pattern as pgvector.ts and paradedb.ts.\n */\nimport { type ExpressionRef, fn, literal } from '@dbsp/core';\n\n/**\n * Generate a series of values: generate_series(start, stop[, step])\n *\n * Returns a set of values from start to stop (inclusive), with an optional step.\n * Commonly used with CTE for batch operations.\n *\n * @example generateSeries(1, 100) → generate_series(1, 100)\n * @example generateSeries(0, 50, 5) → generate_series(0, 50, 5)\n */\nexport function generateSeries(\n\tstart: number,\n\tstop: number,\n\tstep?: number,\n): ExpressionRef {\n\tconst args: ExpressionRef[] = [literal(start), literal(stop)];\n\tif (step !== undefined) {\n\t\targs.push(literal(step));\n\t}\n\treturn fn('generate_series', ...args);\n}\n\n/**\n * Get next value from a sequence: nextval('sequence_name')\n *\n * @example nextval('order_id_seq') → nextval('order_id_seq')\n */\nexport function nextval(sequenceName: string): ExpressionRef {\n\treturn fn('nextval', literal(sequenceName));\n}\n","/**\n * pgvector Extension Wrappers\n *\n * Type-safe query builders for pgvector distance operators.\n * All functions return ExpressionRef instances that can be used in:\n * - SELECT: .column(cosineDistance('vector', qv).as('score'))\n * - WHERE: .where(cosineDistance('vector', qv).gte(0.5))\n * - ORDER BY: .orderBy(rawDistance('vector', qv), 'asc')\n */\n\nimport {\n\tcast,\n\ttype ExpressionRef,\n\texprRef,\n\tfn,\n\tliteral,\n\top,\n\tparam,\n} from '@dbsp/core';\n\n/**\n * Cosine similarity: 1 - (col <=> vector)\n *\n * Score in [0, 1], higher = more similar.\n * Use in SELECT to get a similarity score.\n *\n * @example\n * orm.select('embeddings').column(cosineDistance('vector', qv).as('score'))\n */\nexport function cosineDistance(\n\tcolumn: string,\n\tvector: number[],\n): ExpressionRef {\n\treturn op(\n\t\t'-',\n\t\tliteral(1),\n\t\top('<=>', exprRef(column), cast(param(vector), 'vector')),\n\t);\n}\n\n/**\n * Raw cosine distance: col <=> vector\n *\n * Lower = closer. Index-friendly — use in ORDER BY for ANN search.\n * Do NOT use in SELECT as a similarity score (lower = closer is counterintuitive).\n *\n * @example\n * orm.select('embeddings').orderBy(rawDistance('vector', qv), 'asc')\n */\nexport function rawDistance(column: string, vector: number[]): ExpressionRef {\n\treturn op('<=>', exprRef(column), cast(param(vector), 'vector'));\n}\n\n/**\n * L2 (Euclidean) distance: col <-> vector\n *\n * @example\n * orm.select('embeddings').orderBy(l2Distance('vector', qv), 'asc')\n */\nexport function l2Distance(column: string, vector: number[]): ExpressionRef {\n\treturn op('<->', exprRef(column), cast(param(vector), 'vector'));\n}\n\n/**\n * Inner product distance: col <#> vector (negative inner product)\n *\n * For maximum inner product search: ORDER BY innerProduct('vector', qv) ASC.\n *\n * @example\n * orm.select('embeddings').orderBy(innerProduct('vector', qv), 'asc')\n */\nexport function innerProduct(column: string, vector: number[]): ExpressionRef {\n\treturn op('<#>', exprRef(column), cast(param(vector), 'vector'));\n}\n\n/**\n * Get the number of dimensions of a vector column: vector_dims(col)\n *\n * Returns an integer — the dimension count of the stored vector.\n * Useful for sanity-checking that embeddings match the expected model dimension.\n *\n * @example\n * orm.from(embeddings).columns([vectorDims('vector').as('dim')]).first()\n * // → SELECT vector_dims(\"t0\".\"vector\") AS \"dim\" FROM \"embeddings\" AS \"t0\"\n */\nexport function vectorDims(column: string): ExpressionRef {\n\treturn fn('vector_dims', exprRef(column));\n}\n","/**\n * PostgreSQL Schema Introspection (ADAPTER-006)\n *\n * Queries information_schema/pg_catalog to build ModelIR\n * from an existing database. Supports:\n * - Table/column/PK discovery\n * - FK → bidirectional relation inference\n * - Hierarchy detection (adjacency + edge-table)\n * - Include/exclude filtering\n *\n * @module introspection\n */\n\nimport { ModelIRImpl } from '@dbsp/core';\nimport type {\n\tCheckConstraintIR,\n\tColumnIR,\n\tColumnType,\n\tEnumIR,\n\tForeignKeyIR,\n\tHierarchyIR,\n\tIndexIR,\n\tModelIR,\n\tOnDeleteAction,\n\tPartitionIR,\n\tPolicyIR,\n\tRelationIR,\n\tRelationType,\n\tSequenceIR,\n\tTableIR,\n} from '@dbsp/types';\nimport type { Pool } from 'pg';\nimport { DEFAULT_PK_COLUMN } from './assert-field.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Options for database introspection */\nexport interface IntrospectionOptions {\n\t/** Tables to exclude (glob patterns: * matches any chars) */\n\treadonly exclude?: readonly string[];\n\t/** Tables to include (default: all). Applied before exclude. */\n\treadonly include?: readonly string[];\n\t/** Schema name to introspect (default: 'public') */\n\treadonly schema?: string;\n}\n\n/** Hierarchy pattern detected during introspection */\n/**\n * Hierarchy pattern detected during introspection.\n * Alias of {@link HierarchyIR} from \\@dbsp/types — kept here for\n * public-API backwards compatibility (re-exported from \\@dbsp/adapter-pgsql).\n */\nexport type DetectedHierarchy = HierarchyIR;\n\n/** Extended ModelIR with hierarchy metadata */\nexport interface IntrospectedModelIR extends ModelIR {\n\treadonly hierarchies: readonly DetectedHierarchy[];\n\treadonly introspectedAt: Date;\n\treadonly warnings: readonly string[];\n}\n\n// ============================================================================\n// Raw query result types\n// ============================================================================\n\ninterface RawColumn {\n\ttable_name: string;\n\tcolumn_name: string;\n\tdata_type: string;\n\tudt_name: string;\n\tis_nullable: string;\n\tcolumn_default: string | null;\n\tcollation_name: string | null;\n\tis_identity: string;\n\tidentity_generation: string | null;\n}\n\ninterface RawPrimaryKey {\n\ttable_name: string;\n\tcolumn_name: string;\n}\n\ninterface RawForeignKey {\n\tconstraint_name: string;\n\tsource_table: string;\n\tsource_column: string;\n\ttarget_table: string;\n\ttarget_column: string;\n\tdelete_rule: string;\n\tupdate_rule: string;\n\tis_deferrable: string;\n\tinitially_deferred: string;\n}\n\ninterface RawIndex {\n\tindex_name: string;\n\ttable_name: string;\n\tcolumns: string[];\n\tinclude_columns: string[] | null;\n\texpressions_text: string | null;\n\topclass_names: string[] | null;\n\topclass_cols: string[] | null;\n\tis_unique: boolean;\n\tmethod: string;\n\tpredicate: string | null;\n\treloptions: string[] | null;\n}\n\ninterface RawPartition {\n\ttable_name: string;\n\tstrategy: string;\n\tcolumns: string[];\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Parse the comma-separated expression list returned by pg_get_expr(indexprs, ...).\n *\n * PostgreSQL serialises multiple expression index entries as a comma-separated\n * string, e.g. `\"lower(email), (score * 2)\"`. A naive split on \",\" would break\n * on expressions that contain commas inside parentheses (e.g. function calls with\n * multiple arguments), so we track parenthesis depth.\n */\nfunction parseExpressionsList(raw: string): readonly string[] {\n\tconst results: string[] = [];\n\tlet depth = 0;\n\tlet start = 0;\n\tfor (let i = 0; i < raw.length; i++) {\n\t\tconst ch = raw[i];\n\t\tif (ch === '(') {\n\t\t\tdepth++;\n\t\t} else if (ch === ')') {\n\t\t\tdepth--;\n\t\t} else if (ch === ',' && depth === 0) {\n\t\t\tconst expr = raw.slice(start, i).trim();\n\t\t\tif (expr) results.push(expr);\n\t\t\tstart = i + 1;\n\t\t}\n\t}\n\tconst last = raw.slice(start).trim();\n\tif (last) results.push(last);\n\treturn results;\n}\n\n// ============================================================================\n// Block 1: Core Introspection (tables, columns, PKs)\n// ============================================================================\n\n/**\n * Introspect a PostgreSQL database and return a ModelIR.\n *\n * @param pool - pg.Pool connection\n * @param options - Introspection options (schema, include/exclude)\n * @returns IntrospectedModelIR with tables, relations, and hierarchy metadata\n *\n * @example\n * ```typescript\n * const model = await introspect(pool);\n * const orm = createOrm({ model, adapter: createPgsqlAdapter(pool) });\n * ```\n */\n\n// ============================================================================\n// Catalog query helpers\n// ============================================================================\n\n/** All raw results returned by a single parallel catalog fetch */\ninterface CatalogResults {\n\tcolumns: RawColumn[];\n\tpks: RawPrimaryKey[];\n\tfks: RawForeignKey[];\n\tindexes: RawIndex[];\n\tenums: Array<{ name: string; values: string[] }>;\n\tcomments: Array<{\n\t\ttable_name: string;\n\t\tcolumn_name: string | null;\n\t\tcomment: string;\n\t}>;\n\tchecks: Array<{ name: string; expression: string; raw_table: string }>;\n\tpartitions: RawPartition[];\n\textensions: Array<{ name: string }>;\n\tsequences: Array<{\n\t\tname: string;\n\t\tstart_value: string;\n\t\tincrement_by: string;\n\t\tmin_value: string;\n\t\tmax_value: string;\n\t\tcycle: boolean;\n\t}>;\n\trls: Array<{ table_name: string; rls_enabled: boolean }>;\n\tpolicies: Array<{\n\t\ttable_name: string;\n\t\tpolicy_name: string;\n\t\tcmd: string;\n\t\troles: string[];\n\t\tpermissive: boolean;\n\t\tusing_expr: string | null;\n\t\twith_check_expr: string | null;\n\t}>;\n}\n\n/**\n * Run all 12 catalog queries in parallel.\n * Order matches the coverage test mock sequence: columns, pks, fks, indexes,\n * enums, comments, checks, partitions, extensions (no schema param), sequences,\n * rls state, policies.\n */\nasync function queryAllCatalogs(\n\tpool: Pool,\n\tschema: string,\n): Promise<CatalogResults> {\n\tconst [\n\t\tcolumnsResult,\n\t\tpksResult,\n\t\tfksResult,\n\t\tindexesResult,\n\t\tenumsResult,\n\t\tcommentsResult,\n\t\tchecksResult,\n\t\tpartitionsResult,\n\t\textensionsResult,\n\t\tsequencesResult,\n\t\trlsResult,\n\t\tpoliciesResult,\n\t] = await Promise.all([\n\t\t// 1. Columns (including identity and collation)\n\t\tpool.query<RawColumn>(\n\t\t\t`SELECT table_name, column_name, data_type, udt_name, is_nullable, column_default,\n\t\t\t collation_name, is_identity, identity_generation\n\t\t\t FROM information_schema.columns\n\t\t\t WHERE table_schema = $1\n\t\t\t ORDER BY table_name, ordinal_position`,\n\t\t\t[schema],\n\t\t),\n\t\t// 2. Primary keys\n\t\tpool.query<RawPrimaryKey>(\n\t\t\t`SELECT tc.table_name, kcu.column_name\n\t\t\t FROM information_schema.table_constraints tc\n\t\t\t JOIN information_schema.key_column_usage kcu\n\t\t\t ON tc.constraint_name = kcu.constraint_name\n\t\t\t AND tc.table_schema = kcu.table_schema\n\t\t\t WHERE tc.constraint_type = 'PRIMARY KEY'\n\t\t\t AND tc.table_schema = $1\n\t\t\t ORDER BY tc.table_name, kcu.ordinal_position`,\n\t\t\t[schema],\n\t\t),\n\t\t// 3. Foreign keys\n\t\tpool.query<RawForeignKey>(\n\t\t\t`SELECT\n\t\t\t tc.constraint_name,\n\t\t\t kcu.table_name AS source_table,\n\t\t\t kcu.column_name AS source_column,\n\t\t\t ccu.table_name AS target_table,\n\t\t\t ccu.column_name AS target_column,\n\t\t\t rc.delete_rule,\n\t\t\t rc.update_rule,\n\t\t\t tc.is_deferrable,\n\t\t\t tc.initially_deferred\n\t\t\t FROM information_schema.table_constraints tc\n\t\t\t JOIN information_schema.key_column_usage kcu\n\t\t\t ON tc.constraint_name = kcu.constraint_name\n\t\t\t AND tc.table_schema = kcu.table_schema\n\t\t\t JOIN information_schema.constraint_column_usage ccu\n\t\t\t ON ccu.constraint_name = tc.constraint_name\n\t\t\t AND ccu.table_schema = tc.table_schema\n\t\t\t JOIN information_schema.referential_constraints rc\n\t\t\t ON rc.constraint_name = tc.constraint_name\n\t\t\t AND rc.constraint_schema = tc.table_schema\n\t\t\t WHERE tc.constraint_type = 'FOREIGN KEY'\n\t\t\t AND tc.table_schema = $1\n\t\t\t ORDER BY tc.constraint_name, kcu.ordinal_position`,\n\t\t\t[schema],\n\t\t),\n\t\t// 4. Indexes (excluding PK-backing indexes and unique-constraint-backing indexes).\n\t\t// Unique constraints created via col.unique / UNIQUE keyword in DDL produce an implicit\n\t\t// backing index that is NOT a user-defined index — it is tracked via col.unique on the\n\t\t// ColumnIR instead. Including it here would cause spurious drop_index diffs on roundtrip.\n\t\t// Enhanced to capture:\n\t\t// - INCLUDE columns (PG11+): indkey positions > indnkeyatts\n\t\t// - Expression index entries: attnum = 0 in indkey → pg_get_expr(indexprs)\n\t\t// - Per-column operator classes: pg_opclass join on indclass, non-default only\n\t\tpool.query<RawIndex>(\n\t\t\t`SELECT\n\t\t\t i.relname AS index_name,\n\t\t\t t.relname AS table_name,\n\t\t\t -- Key columns (attnum != 0 means real column, within key positions)\n\t\t\t array_agg(a.attname ORDER BY k.n)\n\t\t\t FILTER (WHERE k.n <= ix.indnkeyatts AND k.attnum != 0) AS columns,\n\t\t\t -- INCLUDE columns (positions after indnkeyatts)\n\t\t\t array_agg(a_inc.attname ORDER BY k.n)\n\t\t\t FILTER (WHERE k.n > ix.indnkeyatts) AS include_columns,\n\t\t\t -- Full expression string for expression indexes (NULL if none)\n\t\t\t pg_get_expr(ix.indexprs, ix.indrelid, false) AS expressions_text,\n\t\t\t -- Non-default opclass names (parallel arrays with opclass_cols)\n\t\t\t array_agg(oc.opcname ORDER BY k.n)\n\t\t\t FILTER (WHERE k.n <= ix.indnkeyatts AND k.attnum != 0\n\t\t\t AND NOT oc.opcdefault) AS opclass_names,\n\t\t\t array_agg(a.attname ORDER BY k.n)\n\t\t\t FILTER (WHERE k.n <= ix.indnkeyatts AND k.attnum != 0\n\t\t\t AND NOT oc.opcdefault) AS opclass_cols,\n\t\t\t ix.indisunique AS is_unique,\n\t\t\t am.amname AS method,\n\t\t\t pg_get_expr(ix.indpred, ix.indrelid, false) AS predicate,\n\t\t\t i.reloptions AS reloptions\n\t\t\t FROM pg_index ix\n\t\t\t JOIN pg_class i ON i.oid = ix.indexrelid\n\t\t\t JOIN pg_class t ON t.oid = ix.indrelid\n\t\t\t JOIN pg_namespace n ON n.oid = t.relnamespace\n\t\t\t JOIN pg_am am ON am.oid = i.relam\n\t\t\t -- Unnest all indkey entries (key + INCLUDE positions)\n\t\t\t CROSS JOIN LATERAL unnest(ix.indkey) WITH ORDINALITY AS k(attnum, n)\n\t\t\t -- Real column (key positions, attnum != 0)\n\t\t\t LEFT JOIN pg_attribute a\n\t\t\t ON a.attrelid = t.oid AND a.attnum = k.attnum AND k.attnum != 0\n\t\t\t -- INCLUDE column (positions past indnkeyatts)\n\t\t\t LEFT JOIN pg_attribute a_inc\n\t\t\t ON a_inc.attrelid = t.oid AND a_inc.attnum = k.attnum AND k.n > ix.indnkeyatts\n\t\t\t -- Operator class for key columns (indclass is oidvector, cast to oid[])\n\t\t\t LEFT JOIN pg_opclass oc\n\t\t\t ON oc.oid = (ix.indclass::oid[])[k.n - 1]\n\t\t\t AND k.n <= ix.indnkeyatts AND k.attnum != 0\n\t\t\t WHERE n.nspname = $1\n\t\t\t AND NOT ix.indisprimary\n\t\t\t AND NOT EXISTS (\n\t\t\t SELECT 1 FROM pg_constraint c\n\t\t\t WHERE c.conindid = i.oid\n\t\t\t AND c.contype = 'u'\n\t\t\t )\n\t\t\t GROUP BY i.relname, t.relname, ix.indisunique, am.amname,\n\t\t\t ix.indpred, ix.indrelid, ix.indexprs, i.reloptions\n\t\t\t ORDER BY t.relname, i.relname`,\n\t\t\t[schema],\n\t\t),\n\t\t// 5. ENUM types\n\t\tpool.query<{ name: string; values: string[] }>(\n\t\t\t`SELECT\n\t\t\t t.typname AS name,\n\t\t\t array_agg(e.enumlabel ORDER BY e.enumsortorder) AS values\n\t\t\t FROM pg_type t\n\t\t\t JOIN pg_enum e ON e.enumtypid = t.oid\n\t\t\t JOIN pg_namespace n ON n.oid = t.typnamespace\n\t\t\t WHERE t.typtype = 'e'\n\t\t\t AND n.nspname = $1\n\t\t\t GROUP BY t.typname`,\n\t\t\t[schema],\n\t\t),\n\t\t// 6. Comments (table and column level) from pg_description\n\t\tpool.query<{\n\t\t\ttable_name: string;\n\t\t\tcolumn_name: string | null;\n\t\t\tcomment: string;\n\t\t}>(\n\t\t\t`SELECT\n\t\t\t c.relname AS table_name,\n\t\t\t a.attname AS column_name,\n\t\t\t d.description AS comment\n\t\t\t FROM pg_description d\n\t\t\t JOIN pg_class c ON c.oid = d.objoid\n\t\t\t JOIN pg_namespace n ON n.oid = c.relnamespace\n\t\t\t LEFT JOIN pg_attribute a ON a.attrelid = d.objoid AND a.attnum = d.objsubid\n\t\t\t WHERE n.nspname = $1\n\t\t\t AND d.objsubid >= 0`,\n\t\t\t[schema],\n\t\t),\n\t\t// 7. CHECK constraints\n\t\tpool.query<{\n\t\t\tname: string;\n\t\t\texpression: string;\n\t\t\traw_table: string;\n\t\t}>(\n\t\t\t`SELECT\n\t\t\t c.conname AS name,\n\t\t\t pg_get_constraintdef(c.oid, false) AS expression,\n\t\t\t c.conrelid::regclass::text AS raw_table\n\t\t\t FROM pg_constraint c\n\t\t\t JOIN pg_namespace n ON n.oid = c.connamespace\n\t\t\t WHERE c.contype = 'c'\n\t\t\t AND n.nspname = $1`,\n\t\t\t[schema],\n\t\t),\n\t\t// 8. Partition configurations\n\t\tpool.query<RawPartition>(\n\t\t\t`SELECT\n\t\t\t c.relname AS table_name,\n\t\t\t p.partstrat AS strategy,\n\t\t\t array_agg(a.attname ORDER BY pk.n) AS columns\n\t\t\t FROM pg_partitioned_table p\n\t\t\t JOIN pg_class c ON c.oid = p.partrelid\n\t\t\t JOIN pg_namespace n ON n.oid = c.relnamespace\n\t\t\t JOIN LATERAL unnest(p.partattrs) WITH ORDINALITY AS pk(attnum, n) ON true\n\t\t\t JOIN pg_attribute a ON a.attrelid = p.partrelid AND a.attnum = pk.attnum\n\t\t\t WHERE n.nspname = $1\n\t\t\t GROUP BY c.relname, p.partstrat`,\n\t\t\t[schema],\n\t\t),\n\t\t// 9. Installed extensions (no schema param — queries globally; skip plpgsql)\n\t\tpool.query<{ name: string }>(\n\t\t\t`SELECT extname AS name\n\t\t\t FROM pg_extension\n\t\t\t WHERE extname != 'plpgsql'`,\n\t\t),\n\t\t// 10. Sequences not backed by SERIAL\n\t\tpool.query<{\n\t\t\tname: string;\n\t\t\tstart_value: string;\n\t\t\tincrement_by: string;\n\t\t\tmin_value: string;\n\t\t\tmax_value: string;\n\t\t\tcycle: boolean;\n\t\t}>(\n\t\t\t`SELECT s.sequencename AS name, s.start_value, s.increment_by, s.min_value, s.max_value, s.cycle\n\t\t\t FROM pg_sequences s\n\t\t\t LEFT JOIN pg_class c ON c.relname = s.sequencename AND c.relkind = 'S'\n\t\t\t AND c.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = s.schemaname)\n\t\t\t LEFT JOIN pg_depend d ON d.objid = c.oid AND d.deptype = 'a'\n\t\t\t WHERE s.schemaname = $1\n\t\t\t AND d.objid IS NULL`,\n\t\t\t[schema],\n\t\t),\n\t\t// 11. RLS enabled state per table\n\t\tpool.query<{ table_name: string; rls_enabled: boolean }>(\n\t\t\t`SELECT c.relname AS table_name, c.relrowsecurity AS rls_enabled\n\t\t\t FROM pg_class c\n\t\t\t JOIN pg_namespace n ON n.oid = c.relnamespace\n\t\t\t WHERE n.nspname = $1\n\t\t\t AND c.relkind = 'r'`,\n\t\t\t[schema],\n\t\t),\n\t\t// 12. Row-Level Security policies\n\t\tpool.query<{\n\t\t\ttable_name: string;\n\t\t\tpolicy_name: string;\n\t\t\tcmd: string;\n\t\t\troles: string[];\n\t\t\tpermissive: boolean;\n\t\t\tusing_expr: string | null;\n\t\t\twith_check_expr: string | null;\n\t\t}>(\n\t\t\t`SELECT\n\t\t\t c.relname AS table_name,\n\t\t\t p.polname AS policy_name,\n\t\t\t p.polcmd AS cmd,\n\t\t\t ARRAY(SELECT rolname FROM pg_roles WHERE oid = ANY(p.polroles)) AS roles,\n\t\t\t p.polpermissive AS permissive,\n\t\t\t pg_get_expr(p.polqual, p.polrelid) AS using_expr,\n\t\t\t pg_get_expr(p.polwithcheck, p.polrelid) AS with_check_expr\n\t\t\t FROM pg_policy p\n\t\t\t JOIN pg_class c ON c.oid = p.polrelid\n\t\t\t JOIN pg_namespace n ON n.oid = c.relnamespace\n\t\t\t WHERE n.nspname = $1`,\n\t\t\t[schema],\n\t\t),\n\t]);\n\n\treturn {\n\t\tcolumns: columnsResult.rows,\n\t\tpks: pksResult.rows,\n\t\tfks: fksResult.rows,\n\t\tindexes: indexesResult.rows,\n\t\tenums: enumsResult.rows,\n\t\tcomments: commentsResult.rows,\n\t\tchecks: checksResult.rows,\n\t\tpartitions: partitionsResult.rows,\n\t\textensions: extensionsResult.rows,\n\t\tsequences: sequencesResult.rows,\n\t\trls: rlsResult.rows,\n\t\tpolicies: policiesResult.rows,\n\t};\n}\n\n/** Build a Map<tableName, PartitionIR> from raw partition rows. */\nfunction buildPartitionMap(rows: RawPartition[]): Map<string, PartitionIR> {\n\tconst strategyMap: Record<string, 'RANGE' | 'LIST' | 'HASH'> = {\n\t\tr: 'RANGE',\n\t\tl: 'LIST',\n\t\th: 'HASH',\n\t};\n\tconst result = new Map<string, PartitionIR>();\n\tfor (const row of rows) {\n\t\tconst strategy = strategyMap[row.strategy];\n\t\tif (!strategy) continue; // Unknown strategy — skip\n\t\tconst columns: string[] = Array.isArray(row.columns)\n\t\t\t? row.columns\n\t\t\t: String(row.columns)\n\t\t\t\t\t.replace(/^\\{|}$/g, '')\n\t\t\t\t\t.split(',')\n\t\t\t\t\t.filter(Boolean);\n\t\tresult.set(row.table_name, { strategy, columns });\n\t}\n\treturn result;\n}\n\n/** Build a Map<tableName, CheckConstraintIR[]> from raw check rows. */\nfunction buildCheckMap(\n\trows: Array<{ name: string; expression: string; raw_table: string }>,\n): Map<string, CheckConstraintIR[]> {\n\tconst result = new Map<string, CheckConstraintIR[]>();\n\tfor (const ck of rows) {\n\t\tconst tableName = ck.raw_table.replace(/^\".*\"\\.|^.*\\./u, '');\n\t\tconst checkIR: CheckConstraintIR = {\n\t\t\tname: ck.name,\n\t\t\texpression: ck.expression,\n\t\t};\n\t\tconst existing = result.get(tableName);\n\t\tif (existing) {\n\t\t\texisting.push(checkIR);\n\t\t} else {\n\t\t\tresult.set(tableName, [checkIR]);\n\t\t}\n\t}\n\treturn result;\n}\n\n/** Build a Map<tableName, IndexIR[]> from raw index rows. */\nfunction buildIndexMap(rows: RawIndex[]): Map<string, IndexIR[]> {\n\tconst result = new Map<string, IndexIR[]>();\n\tfor (const idx of rows) {\n\t\tconst columns: string[] = Array.isArray(idx.columns)\n\t\t\t? idx.columns\n\t\t\t: String(idx.columns)\n\t\t\t\t\t.replace(/^\\{|}$/g, '')\n\t\t\t\t\t.split(',')\n\t\t\t\t\t.filter(Boolean);\n\n\t\t// Parse reloptions array (e.g. ['m=16', 'ef_construction=200']) into a Record\n\t\tlet withParams: Record<string, string> | undefined;\n\t\tif (Array.isArray(idx.reloptions) && idx.reloptions.length > 0) {\n\t\t\twithParams = {};\n\t\t\tfor (const opt of idx.reloptions) {\n\t\t\t\tconst eqIdx = opt.indexOf('=');\n\t\t\t\tif (eqIdx !== -1) {\n\t\t\t\t\twithParams[opt.slice(0, eqIdx)] = opt.slice(eqIdx + 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst indexIR: IndexIR = {\n\t\t\tname: idx.index_name,\n\t\t\tcolumns,\n\t\t\t...(idx.is_unique ? { unique: true } : {}),\n\t\t\t// Only store method when it's not the default 'btree'\n\t\t\t...(idx.method && idx.method !== 'btree' ? { method: idx.method } : {}),\n\t\t\t...(idx.predicate ? { where: idx.predicate } : {}),\n\t\t\t...(withParams && Object.keys(withParams).length > 0\n\t\t\t\t? { with: withParams }\n\t\t\t\t: {}),\n\t\t\t// INCLUDE columns (PG11+)\n\t\t\t...(Array.isArray(idx.include_columns) && idx.include_columns.length > 0\n\t\t\t\t? { include: idx.include_columns as readonly string[] }\n\t\t\t\t: {}),\n\t\t\t// Expression index entries — parse comma-separated pg_get_expr output\n\t\t\t...(idx.expressions_text\n\t\t\t\t? { expressions: parseExpressionsList(idx.expressions_text) }\n\t\t\t\t: {}),\n\t\t\t// Per-column operator class overrides (non-default only)\n\t\t\t...(Array.isArray(idx.opclass_cols) &&\n\t\t\tidx.opclass_cols.length > 0 &&\n\t\t\tArray.isArray(idx.opclass_names) &&\n\t\t\tidx.opclass_names.length > 0\n\t\t\t\t? {\n\t\t\t\t\t\topclass: Object.fromEntries(\n\t\t\t\t\t\t\tidx.opclass_cols.map((col, i) => [col, idx.opclass_names![i]!]),\n\t\t\t\t\t\t) as Record<string, string>,\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t};\n\t\tconst existing = result.get(idx.table_name);\n\t\tif (existing) {\n\t\t\texisting.push(indexIR);\n\t\t} else {\n\t\t\tresult.set(idx.table_name, [indexIR]);\n\t\t}\n\t}\n\treturn result;\n}\n\n/** Build a Map<tableName, RawColumn[]> from raw column rows. */\nfunction buildColumnMap(rows: RawColumn[]): Map<string, RawColumn[]> {\n\tconst result = new Map<string, RawColumn[]>();\n\tfor (const col of rows) {\n\t\tconst existing = result.get(col.table_name);\n\t\tif (existing) {\n\t\t\texisting.push(col);\n\t\t} else {\n\t\t\tresult.set(col.table_name, [col]);\n\t\t}\n\t}\n\treturn result;\n}\n\n/** Build a Map<tableName, pkColumns[]> from raw PK rows. */\nfunction buildPKMap(rows: RawPrimaryKey[]): Map<string, string[]> {\n\tconst result = new Map<string, string[]>();\n\tfor (const pk of rows) {\n\t\tconst existing = result.get(pk.table_name);\n\t\tif (existing) {\n\t\t\texisting.push(pk.column_name);\n\t\t} else {\n\t\t\tresult.set(pk.table_name, [pk.column_name]);\n\t\t}\n\t}\n\treturn result;\n}\n\n/** FK entry used internally for relation/hierarchy inference. */\ninterface FKEntry {\n\tsource: string;\n\ttarget: string;\n\tcols: string[];\n\trefs: string[];\n\tdeleteRule: string;\n\tupdateRule: string;\n\tdeferred: boolean;\n}\n\n/** Build a Map<constraintName, FKEntry> from raw FK rows. */\nfunction buildFKMap(rows: RawForeignKey[]): Map<string, FKEntry> {\n\tconst result = new Map<string, FKEntry>();\n\tfor (const fk of rows) {\n\t\tconst existing = result.get(fk.constraint_name);\n\t\tif (existing) {\n\t\t\texisting.cols.push(fk.source_column);\n\t\t\texisting.refs.push(fk.target_column);\n\t\t} else {\n\t\t\tresult.set(fk.constraint_name, {\n\t\t\t\tsource: fk.source_table,\n\t\t\t\ttarget: fk.target_table,\n\t\t\t\tcols: [fk.source_column],\n\t\t\t\trefs: [fk.target_column],\n\t\t\t\tdeleteRule: fk.delete_rule,\n\t\t\t\tupdateRule: fk.update_rule,\n\t\t\t\tdeferred: fk.is_deferrable === 'YES' && fk.initially_deferred === 'YES',\n\t\t\t});\n\t\t}\n\t}\n\treturn result;\n}\n\n/** Build a Map<enumName, EnumIR> from raw enum rows. */\nfunction buildEnumMap(\n\trows: Array<{ name: string; values: string[] }>,\n): Map<string, EnumIR> {\n\tconst result = new Map<string, EnumIR>();\n\tfor (const row of rows) {\n\t\tconst values: string[] = Array.isArray(row.values)\n\t\t\t? row.values\n\t\t\t: String(row.values)\n\t\t\t\t\t.replace(/^\\{|}$/g, '')\n\t\t\t\t\t.split(',')\n\t\t\t\t\t.filter(Boolean);\n\t\tresult.set(row.name, { name: row.name, values });\n\t}\n\treturn result;\n}\n\n/** Build table-level and column-level comment maps from raw pg_description rows. */\nfunction buildCommentMaps(\n\trows: Array<{\n\t\ttable_name: string;\n\t\tcolumn_name: string | null;\n\t\tcomment: string;\n\t}>,\n): {\n\ttableComments: Map<string, string>;\n\tcolumnComments: Map<string, string>;\n} {\n\tconst tableComments = new Map<string, string>();\n\tconst columnComments = new Map<string, string>(); // key: \"table.column\"\n\tfor (const row of rows) {\n\t\tif (row.column_name === null) {\n\t\t\t// objsubid = 0 → table comment\n\t\t\ttableComments.set(row.table_name, row.comment);\n\t\t} else {\n\t\t\tcolumnComments.set(`${row.table_name}.${row.column_name}`, row.comment);\n\t\t}\n\t}\n\treturn { tableComments, columnComments };\n}\n\n/** Build RLS enabled map and policies map from raw RLS rows. */\nfunction buildRLSMaps(\n\trlsRows: Array<{ table_name: string; rls_enabled: boolean }>,\n\tpoliciesRows: Array<{\n\t\ttable_name: string;\n\t\tpolicy_name: string;\n\t\tcmd: string;\n\t\troles: string[];\n\t\tpermissive: boolean;\n\t\tusing_expr: string | null;\n\t\twith_check_expr: string | null;\n\t}>,\n): {\n\ttableRlsEnabled: Map<string, boolean>;\n\ttablePolicies: Map<string, PolicyIR[]>;\n} {\n\tconst tableRlsEnabled = new Map<string, boolean>();\n\tfor (const row of rlsRows) {\n\t\ttableRlsEnabled.set(row.table_name, row.rls_enabled);\n\t}\n\n\tconst tablePolicies = new Map<string, PolicyIR[]>();\n\tconst cmdMap: Record<string, PolicyIR['command']> = {\n\t\tr: 'SELECT',\n\t\ta: 'INSERT',\n\t\tw: 'UPDATE',\n\t\td: 'DELETE',\n\t\t'*': 'ALL',\n\t};\n\tfor (const row of policiesRows) {\n\t\tconst command = cmdMap[row.cmd] ?? 'ALL';\n\t\tconst policyIR: PolicyIR = {\n\t\t\tname: row.policy_name,\n\t\t\tcommand,\n\t\t\t...(Array.isArray(row.roles) && row.roles.length > 0\n\t\t\t\t? { roles: row.roles as readonly string[] }\n\t\t\t\t: {}),\n\t\t\t...(!row.permissive ? { permissive: false } : {}),\n\t\t\t...(row.using_expr ? { using: row.using_expr } : {}),\n\t\t\t...(row.with_check_expr ? { withCheck: row.with_check_expr } : {}),\n\t\t};\n\t\tconst existing = tablePolicies.get(row.table_name);\n\t\tif (existing) {\n\t\t\texisting.push(policyIR);\n\t\t} else {\n\t\t\ttablePolicies.set(row.table_name, [policyIR]);\n\t\t}\n\t}\n\treturn { tableRlsEnabled, tablePolicies };\n}\n\n/** Context bag passed to buildTableIR. */\ninterface TableIRContext {\n\ttableColumns: Map<string, RawColumn[]>;\n\ttablePKs: Map<string, string[]>;\n\tfksByConstraint: Map<string, FKEntry>;\n\ttableIndexes: Map<string, IndexIR[]>;\n\ttableChecks: Map<string, CheckConstraintIR[]>;\n\ttableComments: Map<string, string>;\n\tcolumnComments: Map<string, string>;\n\ttablePartitions: Map<string, PartitionIR>;\n\ttableRlsEnabled: Map<string, boolean>;\n\ttablePolicies: Map<string, PolicyIR[]>;\n\ttableNames: string[];\n\twarnings: string[];\n}\n\n/** Build a single TableIR from all pre-grouped maps. */\nfunction buildTableIR(tableName: string, ctx: TableIRContext): TableIR {\n\tconst rawCols = ctx.tableColumns.get(tableName) ?? [];\n\tconst pkCols = ctx.tablePKs.get(tableName);\n\n\tconst columns: ColumnIR[] = rawCols.map((col) => {\n\t\t// Map identity_generation: 'ALWAYS' → 'always', 'BY DEFAULT' → 'byDefault'\n\t\tconst identity =\n\t\t\tcol.is_identity === 'YES' && col.identity_generation\n\t\t\t\t? col.identity_generation === 'ALWAYS'\n\t\t\t\t\t? ('always' as const)\n\t\t\t\t\t: ('byDefault' as const)\n\t\t\t\t: undefined;\n\n\t\t// Collation: skip null and the PostgreSQL default collation name\n\t\tconst collation =\n\t\t\tcol.collation_name && col.collation_name !== 'default'\n\t\t\t\t? col.collation_name\n\t\t\t\t: undefined;\n\n\t\tconst colComment =\n\t\t\tctx.columnComments.get(`${tableName}.${col.column_name}`) ?? undefined;\n\n\t\treturn {\n\t\t\tname: col.column_name,\n\t\t\ttype: mapPgType(col.data_type, col.udt_name),\n\t\t\tnullable: col.is_nullable === 'YES',\n\t\t\t// Wrap raw column_default string in { sql } so formatDefaultValue emits\n\t\t\t// it verbatim (e.g. CURRENT_TIMESTAMP, nextval('seq'::regclass)) instead\n\t\t\t// of quoting it as a string literal.\n\t\t\t...(col.column_default != null\n\t\t\t\t? { default: { sql: col.column_default } }\n\t\t\t\t: {}),\n\t\t\toriginalDbType: col.udt_name,\n\t\t\t...(collation ? { collation } : {}),\n\t\t\t...(identity ? { identity } : {}),\n\t\t\t...(colComment ? { comment: colComment } : {}),\n\t\t};\n\t});\n\n\t// Build FK list for this table\n\tconst foreignKeys: ForeignKeyIR[] = [];\n\tfor (const [, fk] of ctx.fksByConstraint) {\n\t\tif (fk.source !== tableName) continue;\n\t\t// Only include FK if target table is in our filtered set\n\t\tif (!ctx.tableNames.includes(fk.target)) continue;\n\t\tconst onDelete = mapDeleteRule(fk.deleteRule);\n\t\tconst onUpdate = mapDeleteRule(fk.updateRule);\n\t\tforeignKeys.push({\n\t\t\tcolumns: fk.cols,\n\t\t\treferences: { table: fk.target, columns: fk.refs },\n\t\t\t...(onDelete !== 'NO ACTION' ? { onDelete } : {}),\n\t\t\t...(onUpdate !== 'NO ACTION' ? { onUpdate } : {}),\n\t\t\t...(fk.deferred ? { deferred: true } : {}),\n\t\t});\n\t}\n\n\tif (!pkCols) {\n\t\tctx.warnings.push(`Table \"${tableName}\" has no primary key`);\n\t}\n\n\tconst checks = ctx.tableChecks.get(tableName);\n\tconst tableComment = ctx.tableComments.get(tableName);\n\tconst partitionConfig = ctx.tablePartitions.get(tableName);\n\tconst rlsEnabled = ctx.tableRlsEnabled.get(tableName) ?? false;\n\tconst policies = ctx.tablePolicies.get(tableName);\n\n\treturn {\n\t\tname: tableName,\n\t\tcolumns,\n\t\t...(pkCols\n\t\t\t? { primaryKey: pkCols.length === 1 ? pkCols[0]! : pkCols }\n\t\t\t: {}),\n\t\tforeignKeys,\n\t\tindexes: ctx.tableIndexes.get(tableName) ?? [],\n\t\t...(checks && checks.length > 0 ? { checkConstraints: checks } : {}),\n\t\t...(tableComment ? { comment: tableComment } : {}),\n\t\t...(partitionConfig ? { partition: partitionConfig } : {}),\n\t\t...(rlsEnabled ? { rlsEnabled: true } : {}),\n\t\t...(policies && policies.length > 0 ? { policies } : {}),\n\t};\n}\n\n/** Build a Map<seqName, SequenceIR> from raw sequence rows. */\nfunction buildSequenceMap(\n\trows: Array<{\n\t\tname: string;\n\t\tstart_value: string;\n\t\tincrement_by: string;\n\t\tmin_value: string;\n\t\tmax_value: string;\n\t\tcycle: boolean;\n\t}>,\n): Map<string, SequenceIR> {\n\tconst result = new Map<string, SequenceIR>();\n\tfor (const row of rows) {\n\t\tresult.set(row.name, {\n\t\t\tname: row.name,\n\t\t\tstartWith: Number(row.start_value),\n\t\t\tincrementBy: Number(row.increment_by),\n\t\t\tminValue: Number(row.min_value),\n\t\t\tmaxValue: Number(row.max_value),\n\t\t\tcycle: row.cycle,\n\t\t});\n\t}\n\treturn result;\n}\n\nexport async function introspect(\n\tpool: Pool,\n\toptions?: IntrospectionOptions,\n): Promise<IntrospectedModelIR> {\n\tconst schema = options?.schema ?? 'public';\n\tconst warnings: string[] = [];\n\n\tconst raw = await queryAllCatalogs(pool, schema);\n\n\tconst tablePartitions = buildPartitionMap(raw.partitions);\n\tconst tableChecks = buildCheckMap(raw.checks);\n\tconst tableIndexes = buildIndexMap(raw.indexes);\n\tconst tableColumns = buildColumnMap(raw.columns);\n\tconst tablePKs = buildPKMap(raw.pks);\n\tconst fksByConstraint = buildFKMap(raw.fks);\n\tconst enumMap = buildEnumMap(raw.enums);\n\tconst { tableComments, columnComments } = buildCommentMaps(raw.comments);\n\tconst { tableRlsEnabled, tablePolicies } = buildRLSMaps(\n\t\traw.rls,\n\t\traw.policies,\n\t);\n\n\t// Apply include/exclude filters\n\tlet tableNames = Array.from(tableColumns.keys());\n\ttableNames = filterTables(tableNames, options);\n\n\t// Build TableIR map\n\tconst tables = new Map<string, TableIR>();\n\tfor (const tableName of tableNames) {\n\t\tconst table = buildTableIR(tableName, {\n\t\t\ttableColumns,\n\t\t\ttablePKs,\n\t\t\tfksByConstraint,\n\t\t\ttableIndexes,\n\t\t\ttableChecks,\n\t\t\ttableComments,\n\t\t\tcolumnComments,\n\t\t\ttablePartitions,\n\t\t\ttableRlsEnabled,\n\t\t\ttablePolicies,\n\t\t\ttableNames,\n\t\t\twarnings,\n\t\t});\n\t\ttables.set(tableName, table);\n\t}\n\n\tconst extensions: string[] = raw.extensions.map((r) => r.name);\n\tconst sequenceMap = buildSequenceMap(raw.sequences);\n\tconst relations = inferRelations(fksByConstraint, tableNames);\n\tconst hierarchies = detectHierarchies(tables, fksByConstraint, tableNames);\n\n\tconst modelIR = new ModelIRImpl(\n\t\ttables,\n\t\trelations,\n\t\tenumMap,\n\t\textensions,\n\t\tsequenceMap,\n\t);\n\n\treturn Object.assign(modelIR, {\n\t\thierarchies,\n\t\tintrospectedAt: new Date(),\n\t\twarnings,\n\t}) as IntrospectedModelIR;\n}\n\n// ============================================================================\n// Block 2: Relation Inference\n// ============================================================================\n\n/**\n * Infer bidirectional relations from FK constraints.\n * Each FK produces: belongsTo (source → target) + hasMany (target → source).\n */\nfunction inferRelations(\n\tfksByConstraint: Map<string, FKEntry>,\n\tfilteredTables: string[],\n): Map<string, RelationIR> {\n\tconst relations = new Map<string, RelationIR>();\n\tconst filteredSet = new Set(filteredTables);\n\n\tfor (const [, fk] of fksByConstraint) {\n\t\tif (!filteredSet.has(fk.source) || !filteredSet.has(fk.target)) continue;\n\n\t\t// Derive relation name from FK column\n\t\t// author_id → author (belongsTo)\n\t\t// category_id → category (belongsTo)\n\t\tconst belongsToName = deriveRelationName(fk.cols[0]!, fk.target);\n\t\tconst fkCol = fk.cols.length === 1 ? fk.cols[0]! : fk.cols;\n\n\t\t// belongsTo: source (FK owner) → target\n\t\tconst belongsToKey = `${fk.source}.${belongsToName}`;\n\t\tif (!relations.has(belongsToKey)) {\n\t\t\trelations.set(belongsToKey, {\n\t\t\t\tname: belongsToName,\n\t\t\t\ttype: 'belongsTo' as RelationType,\n\t\t\t\tsource: fk.source,\n\t\t\t\ttarget: fk.target,\n\t\t\t\tforeignKey: fkCol,\n\t\t\t\tcardinality: 'one',\n\t\t\t\toptionality: 'optional',\n\t\t\t\tincludeStrategy: 'auto',\n\t\t\t\tfilterStrategy: 'auto',\n\t\t\t\tjoinDefault: 'auto',\n\t\t\t});\n\t\t}\n\n\t\t// hasMany: target → source (FK owner)\n\t\t// users.posts (users hasMany posts)\n\t\tconst hasManyName = fk.source; // Use source table name for hasMany\n\t\tconst hasManyKey = `${fk.target}.${hasManyName}`;\n\t\tif (!relations.has(hasManyKey)) {\n\t\t\trelations.set(hasManyKey, {\n\t\t\t\tname: hasManyName,\n\t\t\t\ttype: 'hasMany' as RelationType,\n\t\t\t\tsource: fk.target,\n\t\t\t\ttarget: fk.source,\n\t\t\t\tforeignKey: fkCol,\n\t\t\t\tcardinality: 'many',\n\t\t\t\toptionality: 'optional',\n\t\t\t\tincludeStrategy: 'auto',\n\t\t\t\tfilterStrategy: 'auto',\n\t\t\t\tjoinDefault: 'auto',\n\t\t\t});\n\t\t}\n\t}\n\n\treturn relations;\n}\n\n/**\n * Derive a relation name from a FK column name.\n * - author_id → author\n * - category_id → category\n * - parent_id → parent\n * - If no _id suffix, use target table (singular)\n */\nfunction deriveRelationName(fkColumn: string, _targetTable: string): string {\n\tif (fkColumn.endsWith('_id')) {\n\t\treturn fkColumn.slice(0, -3);\n\t}\n\tif (fkColumn.endsWith('Id')) {\n\t\treturn fkColumn.slice(0, -2);\n\t}\n\treturn fkColumn;\n}\n\n// ============================================================================\n// Block 3: Hierarchy Detection\n// ============================================================================\n\n/**\n * Detect hierarchy patterns:\n * - Adjacency: self-referential FK (table.parent_id → table.id)\n * - Edge-table: table with 2+ FKs to same target\n */\nfunction detectHierarchies(\n\ttables: Map<string, TableIR>,\n\tfksByConstraint: Map<string, FKEntry>,\n\tfilteredTables: string[],\n): DetectedHierarchy[] {\n\tconst hierarchies: DetectedHierarchy[] = [];\n\tconst filteredSet = new Set(filteredTables);\n\n\t// Track FKs by (source, target) for edge-table detection\n\tconst fksBySourceTarget = new Map<\n\t\tstring,\n\t\tArray<{ cols: string[]; refs: string[] }>\n\t>();\n\n\tfor (const [, fk] of fksByConstraint) {\n\t\tif (!filteredSet.has(fk.source) || !filteredSet.has(fk.target)) continue;\n\n\t\t// Adjacency: self-referential FK\n\t\tif (fk.source === fk.target && fk.cols.length === 1) {\n\t\t\tconst table = tables.get(fk.source);\n\t\t\tconst pk = table?.primaryKey;\n\t\t\tconst nodeIdColumn =\n\t\t\t\ttypeof pk === 'string' ? pk : (pk?.[0] ?? DEFAULT_PK_COLUMN);\n\n\t\t\thierarchies.push({\n\t\t\t\ttype: 'adjacency',\n\t\t\t\tnodeTable: fk.source,\n\t\t\t\tparentColumn: fk.cols[0]!,\n\t\t\t\tnodeIdColumn,\n\t\t\t});\n\t\t}\n\n\t\t// Track for edge-table detection\n\t\tconst key = `${fk.source}→${fk.target}`;\n\t\tconst existing = fksBySourceTarget.get(key);\n\t\tif (existing) {\n\t\t\texisting.push({ cols: fk.cols, refs: fk.refs });\n\t\t} else {\n\t\t\tfksBySourceTarget.set(key, [{ cols: fk.cols, refs: fk.refs }]);\n\t\t}\n\t}\n\n\t// Edge-table: table with 2+ FKs to same target (non-self-referential)\n\tfor (const [key, fks] of fksBySourceTarget) {\n\t\tif (fks.length < 2) continue;\n\t\tconst [source, target] = key.split('→');\n\t\tif (!source || !target) continue;\n\t\tif (source === target) continue; // Exclude self-referential (already handled as adjacency)\n\n\t\tconst nodeTable = tables.get(target);\n\t\tconst nodeIdColumn =\n\t\t\ttypeof nodeTable?.primaryKey === 'string'\n\t\t\t\t? nodeTable.primaryKey\n\t\t\t\t: (nodeTable?.primaryKey?.[0] ?? DEFAULT_PK_COLUMN);\n\n\t\thierarchies.push({\n\t\t\ttype: 'edge-table',\n\t\t\tnodeTable: target,\n\t\t\tedgeTable: source,\n\t\t\tparentColumn: fks[0]!.cols[0]!,\n\t\t\tchildColumn: fks[1]!.cols[0]!,\n\t\t\tnodeIdColumn,\n\t\t});\n\t}\n\n\treturn hierarchies;\n}\n\n// ============================================================================\n// Block 4: Helpers\n// ============================================================================\n\n/** Map PostgreSQL data type to ColumnType */\nfunction mapPgType(dataType: string, udtName: string): ColumnType {\n\t// Check UDT name first (more specific)\n\tswitch (udtName) {\n\t\tcase 'uuid':\n\t\t\treturn 'uuid';\n\t\tcase 'jsonb':\n\t\t\treturn 'jsonb';\n\t\tcase 'json':\n\t\t\treturn 'json';\n\t\tcase 'int4range':\n\t\t\treturn 'int4range';\n\t\tcase 'int8range':\n\t\t\treturn 'int8range';\n\t\tcase 'numrange':\n\t\t\treturn 'numrange';\n\t\tcase 'daterange':\n\t\t\treturn 'daterange';\n\t\tcase 'tsrange':\n\t\t\treturn 'tsrange';\n\t\tcase 'tstzrange':\n\t\t\treturn 'tstzrange';\n\t}\n\n\t// Fallback to data_type\n\tswitch (dataType) {\n\t\tcase 'integer':\n\t\tcase 'smallint':\n\t\t\treturn 'integer';\n\t\tcase 'bigint':\n\t\t\treturn 'bigint';\n\t\tcase 'numeric':\n\t\tcase 'decimal':\n\t\tcase 'real':\n\t\tcase 'double precision':\n\t\t\treturn 'decimal';\n\t\tcase 'boolean':\n\t\t\treturn 'boolean';\n\t\tcase 'character varying':\n\t\tcase 'character':\n\t\tcase 'varchar':\n\t\tcase 'char':\n\t\t\treturn 'string';\n\t\tcase 'text':\n\t\t\treturn 'text';\n\t\tcase 'date':\n\t\t\treturn 'date';\n\t\tcase 'time without time zone':\n\t\tcase 'time with time zone':\n\t\t\treturn 'time';\n\t\tcase 'timestamp without time zone':\n\t\t\treturn 'timestamp';\n\t\tcase 'timestamp with time zone':\n\t\t\treturn 'datetime';\n\t\tcase 'json':\n\t\t\treturn 'json';\n\t\tcase 'jsonb':\n\t\t\treturn 'jsonb';\n\t\tcase 'uuid':\n\t\t\treturn 'uuid';\n\t\tdefault:\n\t\t\treturn 'string'; // Safe fallback\n\t}\n}\n\n/** Map PostgreSQL delete rule to OnDeleteAction */\nfunction mapDeleteRule(rule: string): OnDeleteAction {\n\tswitch (rule) {\n\t\tcase 'CASCADE':\n\t\t\treturn 'CASCADE';\n\t\tcase 'SET NULL':\n\t\t\treturn 'SET NULL';\n\t\tcase 'SET DEFAULT':\n\t\t\treturn 'SET DEFAULT';\n\t\tcase 'RESTRICT':\n\t\t\treturn 'RESTRICT';\n\t\tdefault:\n\t\t\treturn 'NO ACTION';\n\t}\n}\n\n/**\n * Filter table names by include/exclude options.\n * Include is applied first, then exclude.\n * Patterns support * for wildcard matching.\n */\nfunction filterTables(\n\ttableNames: string[],\n\toptions?: IntrospectionOptions,\n): string[] {\n\tlet result = tableNames;\n\n\tif (options?.include?.length) {\n\t\tresult = result.filter((name) =>\n\t\t\toptions.include!.some((pattern) => matchGlob(pattern, name)),\n\t\t);\n\t}\n\n\tif (options?.exclude?.length) {\n\t\tresult = result.filter(\n\t\t\t(name) => !options.exclude!.some((pattern) => matchGlob(pattern, name)),\n\t\t);\n\t}\n\n\treturn result;\n}\n\n/** Simple glob matching (supports * wildcard) */\nfunction matchGlob(pattern: string, value: string): boolean {\n\tif (!pattern.includes('*')) return pattern === value;\n\tconst regex = new RegExp(\n\t\t`^${pattern.replace(/\\*/g, '.*').replace(/\\?/g, '.')}$`,\n\t);\n\treturn regex.test(value);\n}\n","/**\n * Mutation Compiler\n *\n * Compiles INSERT, UPDATE, and DELETE statements from plan decisions.\n * Supports:\n * - INSERT with values/from subquery\n * - INSERT with RETURNING\n * - UPDATE with SET and WHERE\n * - DELETE with WHERE\n * - RETURNING clause for all mutations\n */\n\nimport { isSqlRaw } from '@dbsp/core';\nimport type { Node } from '@pgsql/types';\nimport {\n\tcolumnRef,\n\ttype DeleteOptions,\n\tdeleteStmt,\n\tfuncCall,\n\ttype InsertOptions,\n\tinsertStmt,\n\tresTarget,\n\ttype UpdateOptions,\n\tupdateStmt,\n} from '../ast-helpers.js';\nimport {\n\tinferPgArrayType,\n\tparseRawExpression,\n\tstripArraySuffix,\n\ttransposeToColumnArrays,\n\tvalidateBatchCardinality,\n} from '../compiler-utils.js';\nimport { createWhereDispatcher } from '../handlers/index.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n\tInsertStmtNode,\n} from '../handlers/types.js';\nimport { createTypeCastParamRef } from '../param-ref.js';\n\n// ============================================================================\n// Shared Helpers\n// ============================================================================\n\n/**\n * Build RETURNING clause AST nodes from column names.\n * Shared across INSERT, UPDATE, DELETE, UPSERT, and INSERT FROM.\n */\nexport function buildReturningList(\n\tcolumns: readonly string[] | undefined,\n\ttableRef: string,\n\tctx: CompilerContext,\n): Node[] | undefined {\n\tif (!columns || columns.length === 0) return undefined;\n\tconst { naming } = ctx;\n\treturn columns.map((col) =>\n\t\tresTarget(\n\t\t\tcolumnRef(col, tableRef, ctx.schema, naming),\n\t\t\tnaming.toDatabase(col),\n\t\t),\n\t);\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Configuration for INSERT compilation\n */\nexport interface InsertConfig {\n\t/** Table to insert into */\n\ttable: string;\n\t/** Columns to insert */\n\tcolumns: string[];\n\t/** Values for each column (array of rows) */\n\tvalues: unknown[][];\n\t/** Columns to return (RETURNING clause) */\n\treturning?: string[];\n\t/** Subquery for INSERT ... SELECT */\n\tselectQuery?: Node;\n\t/** Column database types for type-cast emission (e.g. range types) */\n\tcolumnTypes?: Record<string, string>;\n}\n\n/**\n * Configuration for UPDATE compilation\n */\nexport interface UpdateConfig {\n\t/** Table to update */\n\ttable: string;\n\t/** Column-value pairs to set */\n\tset: { column: string; value: unknown }[];\n\t/** WHERE conditions */\n\twhere?: Decision[];\n\t/** Columns to return (RETURNING clause) */\n\treturning?: string[];\n\t/** Column database types for type-cast emission (e.g. range types) */\n\tcolumnTypes?: Record<string, string>;\n}\n\n/**\n * Configuration for DELETE compilation\n */\nexport interface DeleteConfig {\n\t/** Table to delete from */\n\ttable: string;\n\t/** WHERE conditions */\n\twhere?: Decision[];\n\t/** Columns to return (RETURNING clause) */\n\treturning?: string[];\n}\n\n/**\n * Configuration for INSERT FROM SELECT compilation\n */\nexport interface InsertFromConfig {\n\t/** Target table to insert into */\n\ttargetTable: string;\n\t/** Source table to select from */\n\tsourceTable: string;\n\t/** Columns to insert (same names in target and source) */\n\tcolumns?: string[];\n\t/** WHERE conditions for source query */\n\twhere?: Decision[];\n\t/** LIMIT for source query */\n\tlimit?: number;\n\t/** Columns to return (RETURNING clause) */\n\treturning?: string[];\n}\n\nexport interface UpsertFromConfig {\n\t/** Target table to upsert into */\n\ttargetTable: string;\n\t/** Source table to select from */\n\tsourceTable: string;\n\t/** Conflict target columns for ON CONFLICT */\n\tconflictColumns: string[];\n\t/** Columns to insert (same names in target and source) */\n\tcolumns?: string[];\n\t/** WHERE conditions for source query */\n\twhere?: Decision[];\n\t/** LIMIT for source query */\n\tlimit?: number;\n\t/** Columns to return (RETURNING clause) */\n\treturning?: string[];\n}\n\n// ============================================================================\n// Compilers\n// ============================================================================\n\n/**\n * Compile an INSERT statement from configuration.\n */\nexport function compileInsert(\n\tconfig: InsertConfig,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): Node {\n\tconst naming = ctx.naming;\n\tconst dbTable = naming.toDatabase(config.table);\n\tconst dbColumns = config.columns.map((c) => naming.toDatabase(c));\n\n\t// Build VALUES as Node[][] (each row is Node[])\n\tconst columnTypes = config.columnTypes;\n\tconst columns = config.columns;\n\tconst valuesRows: Node[][] = config.values.map((row) =>\n\t\trow.map((val, i) => {\n\t\t\tconst colName = columns[i];\n\t\t\tconst dbType = colName ? columnTypes?.[colName] : undefined;\n\t\t\treturn valueToNode(val, state, dbType);\n\t\t}),\n\t);\n\n\t// Build RETURNING clause if specified\n\tconst returningList = buildReturningList(config.returning, dbTable, ctx);\n\n\t// Build INSERT statement using helper\n\t// Use spread to conditionally include optional properties (exactOptionalPropertyTypes)\n\tconst options: InsertOptions = {\n\t\ttable: config.table,\n\t\tcolumns: dbColumns,\n\t\tvalues: valuesRows,\n\t\tnaming,\n\t};\n\tif (ctx.schema) options.schema = ctx.schema;\n\tif (returningList) options.returning = returningList;\n\n\treturn insertStmt(options);\n}\n\n/**\n * Compile an INSERT statement using the unnest strategy for large batches.\n *\n * Generates:\n * INSERT INTO \"table\" (\"col1\", \"col2\")\n * SELECT unnest($1::int4[]), unnest($2::text[])\n * [RETURNING ...]\n *\n * This avoids the PostgreSQL 65535 parameter limit that VALUES clauses hit\n * at ~5000 rows with 12 columns. Uses N parameters regardless of row count.\n */\n/**\n * Compile an INSERT statement using the unnest strategy for large batches.\n *\n * Generates:\n * INSERT INTO \"table\" (\"col1\", \"col2\")\n * SELECT unnest($1::int4[]), unnest($2::text[])\n * [RETURNING ...]\n *\n * This avoids the PostgreSQL 65535 parameter limit that VALUES clauses hit\n * at ~5000 rows with 12 columns. Uses N parameters regardless of row count.\n */\nexport function compileUnnestInsert(\n\tconfig: InsertConfig,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): Node {\n\tconst naming = ctx.naming;\n\tconst dbTable = naming.toDatabase(config.table);\n\tconst { columns, values, columnTypes } = config;\n\n\t// Validate cardinality before any SQL generation (INV-02)\n\tvalidateBatchCardinality(columns, values);\n\n\t// Transpose row-major → column-major\n\tconst columnArrays = transposeToColumnArrays(columns, values);\n\n\t// Build SELECT target list: unnest($N::type[]) AS \"col\"\n\tconst targetList: Node[] = columns.map((col, i) => {\n\t\t// columnArrays[i] is always defined (transposeToColumnArrays maps over columns),\n\t\t// but TypeScript doesn't know that — use a safe fallback.\n\t\tconst colArray: unknown[] = columnArrays[i] ?? [];\n\n\t\t// Find a non-null sample value for runtime type fallback\n\t\tconst sampleValue = colArray.find((v) => v !== null && v !== undefined);\n\n\t\t// Strip the trailing [] to get base type (inferPgArrayType returns e.g. \"int4[]\")\n\t\tconst pgArrayType = inferPgArrayType(col, columnTypes, sampleValue);\n\t\tconst pgBaseType = stripArraySuffix(pgArrayType);\n\n\t\t// Add array parameter and get its 1-based index\n\t\tstate.parameters.push(colArray);\n\t\tstate.paramIndex++;\n\t\tconst paramIdx = state.paramIndex;\n\n\t\t// Build: unnest($N::base_type[])\n\t\tconst typeCasted = createTypeCastParamRef(paramIdx, pgBaseType, true);\n\t\tconst unnestCall = funcCall('unnest', [typeCasted]);\n\n\t\t// ResTarget with column alias: unnest(...) AS \"colname\"\n\t\treturn {\n\t\t\tResTarget: {\n\t\t\t\tname: naming.toDatabase(col),\n\t\t\t\tval: unnestCall,\n\t\t\t},\n\t\t};\n\t});\n\n\t// Build the SELECT statement for INSERT ... SELECT (no op field = SETOP_NONE by default)\n\tconst selectQuery: Node = {\n\t\tSelectStmt: {\n\t\t\ttargetList,\n\t\t},\n\t};\n\n\t// Build RETURNING clause if specified\n\tconst returningList = buildReturningList(config.returning, dbTable, ctx);\n\n\t// Build INSERT INTO \"table\" (\"col1\", \"col2\") <selectQuery>\n\tconst options: InsertOptions = {\n\t\ttable: config.table,\n\t\tcolumns: columns.map((c) => naming.toDatabase(c)),\n\t\tselectQuery,\n\t\tnaming,\n\t};\n\tif (ctx.schema) options.schema = ctx.schema;\n\tif (returningList) options.returning = returningList;\n\n\treturn insertStmt(options);\n}\n\n/**\n * Compile an UPDATE statement from configuration.\n */\nexport function compileUpdate(\n\tconfig: UpdateConfig,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): Node {\n\tconst naming = ctx.naming;\n\tconst tableAlias = config.table;\n\n\t// Build SET clause - convert unknown values to Node.\n\t// Raw SQL expressions (SqlRawExpression) are parsed directly into AST nodes;\n\t// all other values become parameterized $N references.\n\tconst columnTypes = config.columnTypes;\n\tconst setClause: Array<{ column: string; value: Node }> = config.set.map(\n\t\t({ column, value }) => ({\n\t\t\tcolumn: naming.toDatabase(column),\n\t\t\tvalue: isSqlRaw(value)\n\t\t\t\t? parseRawExpression(value.sql)\n\t\t\t\t: valueToNode(value, state, columnTypes?.[column]),\n\t\t}),\n\t);\n\n\t// Build WHERE clause if present\n\tlet whereClause: Node | undefined;\n\tif (config.where && config.where.length > 0) {\n\t\tconst dispatch = createWhereDispatcher();\n\t\tconst subCtx = { ...ctx, currentAlias: tableAlias };\n\n\t\tif (config.where.length === 1) {\n\t\t\twhereClause = dispatch(config.where[0]!, subCtx, state);\n\t\t} else {\n\t\t\tconst conditions = config.where.map((cond) =>\n\t\t\t\tdispatch(cond, subCtx, state),\n\t\t\t);\n\t\t\twhereClause = {\n\t\t\t\tBoolExpr: {\n\t\t\t\t\tboolop: 'AND_EXPR',\n\t\t\t\t\targs: conditions,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\t// Build RETURNING clause if specified\n\tconst returningList = buildReturningList(config.returning, tableAlias, ctx);\n\n\t// Build UPDATE statement (exactOptionalPropertyTypes compatible)\n\tconst options: UpdateOptions = {\n\t\ttable: config.table,\n\t\tset: setClause,\n\t\tnaming,\n\t};\n\tif (ctx.schema) options.schema = ctx.schema;\n\tif (whereClause) options.where = whereClause;\n\tif (returningList) options.returning = returningList;\n\n\treturn updateStmt(options);\n}\n\n/**\n * Compile a DELETE statement from configuration.\n */\n\n/**\n * Configuration for batch UPDATE via unnest (BATCH-001).\n */\nexport interface BatchUpdateConfig {\n\t/** Target table name */\n\ttable: string;\n\t/** Column(s) used to join for WHERE clause */\n\tmatchColumns: string[];\n\t/** All columns (match + update), extracted from updates[0] */\n\tallColumns: string[];\n\t/** Column-major arrays: [[match_vals...], [update_vals...], ...] */\n\tcolumnArrays: unknown[][];\n\t/** Optional scalar SET assignments applied to all rows */\n\tscalarSet?: { column: string; value: unknown }[];\n\t/** Columns to return (RETURNING clause) */\n\treturning?: string[];\n\t/** Column database types for type-cast emission */\n\tcolumnTypes?: Record<string, string>;\n\t/** Optional extra WHERE guard appended as AND after match conditions */\n\twhereGuard?: Node;\n}\n\n/**\n * Compile a batch UPDATE statement using the unnest FROM strategy (BATCH-001).\n *\n * Generates:\n * UPDATE \"table\" SET \"update_col\" = t.\"update_col\" [, \"scalar_col\" = $N]\n * FROM unnest(CAST($1 AS type[]), CAST($2 AS type[])) AS t(\"match_col\", \"update_col\")\n * WHERE \"table\".\"match_col\" = t.\"match_col\"\n * [RETURNING ...]\n */\nexport function compileUnnestUpdate(\n\tconfig: BatchUpdateConfig,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): Node {\n\tconst naming = ctx.naming;\n\tconst { table, matchColumns, allColumns, columnArrays, columnTypes } = config;\n\tconst dbTable = naming.toDatabase(table);\n\tconst updateColumns = allColumns.filter((c) => !matchColumns.includes(c));\n\n\t// Build unnest arguments: CAST($N AS type[]) for each column\n\tconst unnestArgs: Node[] = allColumns.map((col, i) => {\n\t\tconst colArray: unknown[] = columnArrays[i] ?? [];\n\t\tconst sampleValue = colArray.find((v) => v !== null && v !== undefined);\n\t\tconst pgArrayType = inferPgArrayType(col, columnTypes, sampleValue);\n\t\t// pgArrayType is already \"type[]\"; strip [] to get base type for createTypeCastParamRef\n\t\tconst pgBaseType = stripArraySuffix(pgArrayType);\n\n\t\tstate.parameters.push(colArray);\n\t\tstate.paramIndex++;\n\t\tconst paramIdx = state.paramIndex;\n\n\t\treturn createTypeCastParamRef(paramIdx, pgBaseType, true);\n\t});\n\n\t// Build: FROM unnest(CAST($1 AS int4[]), ...) AS t(\"col1\", \"col2\", ...)\n\tconst unnestCall = funcCall('unnest', unnestArgs);\n\tconst rangeFunction: Node = {\n\t\tRangeFunction: {\n\t\t\tfunctions: [{ List: { items: [unnestCall] } }],\n\t\t\talias: {\n\t\t\t\taliasname: 't',\n\t\t\t\tcolnames: allColumns.map((c) => ({\n\t\t\t\t\tString: { sval: naming.toDatabase(c) },\n\t\t\t\t})),\n\t\t\t},\n\t\t},\n\t};\n\n\t// Build SET clause: update cols = t.\"col\", scalar cols = $N\n\tconst setClause: Array<{ column: string; value: Node }> = [\n\t\t// Array-sourced update columns: \"col\" = t.\"col\"\n\t\t...updateColumns.map((col) => ({\n\t\t\tcolumn: naming.toDatabase(col),\n\t\t\tvalue: columnRef(col, 't', undefined, naming),\n\t\t})),\n\t\t// Scalar SET from scalarSet (e.g. .set({ confidence: 0.85 }))\n\t\t...(config.scalarSet ?? []).map(({ column, value }) => ({\n\t\t\tcolumn: naming.toDatabase(column),\n\t\t\tvalue: valueToNode(value, state, columnTypes?.[column]),\n\t\t})),\n\t];\n\n\t// Build WHERE: \"table\".\"match_col\" = t.\"match_col\" [AND ...]\n\tconst matchConditions: Node[] = matchColumns.map((col) => ({\n\t\tA_Expr: {\n\t\t\tkind: 'AEXPR_OP',\n\t\t\tname: [{ String: { sval: '=' } }],\n\t\t\tlexpr: columnRef(col, dbTable, undefined, naming),\n\t\t\trexpr: columnRef(col, 't', undefined, naming),\n\t\t},\n\t}));\n\n\tconst matchWhere: Node =\n\t\tmatchConditions.length === 1\n\t\t\t? matchConditions[0]!\n\t\t\t: {\n\t\t\t\t\tBoolExpr: {\n\t\t\t\t\t\tboolop: 'AND_EXPR',\n\t\t\t\t\t\targs: matchConditions,\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t// Append optional whereGuard as AND <extra> after the batch match condition\n\tconst whereClause: Node = config.whereGuard\n\t\t? {\n\t\t\t\tBoolExpr: {\n\t\t\t\t\tboolop: 'AND_EXPR',\n\t\t\t\t\targs: [matchWhere, config.whereGuard],\n\t\t\t\t},\n\t\t\t}\n\t\t: matchWhere;\n\n\t// Build RETURNING clause if specified\n\tconst returningList = buildReturningList(config.returning, dbTable, ctx);\n\n\t// Build UPDATE statement\n\tconst options: UpdateOptions = {\n\t\ttable,\n\t\tset: setClause,\n\t\tnaming,\n\t\tfrom: [rangeFunction],\n\t\twhere: whereClause,\n\t};\n\tif (ctx.schema) options.schema = ctx.schema;\n\tif (returningList) options.returning = returningList;\n\n\treturn updateStmt(options);\n}\n\nexport function compileDelete(\n\tconfig: DeleteConfig,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): Node {\n\tconst naming = ctx.naming;\n\tconst tableAlias = config.table;\n\n\t// Build WHERE clause if present\n\tlet whereClause: Node | undefined;\n\tif (config.where && config.where.length > 0) {\n\t\tconst dispatch = createWhereDispatcher();\n\t\tconst subCtx = { ...ctx, currentAlias: tableAlias };\n\n\t\tif (config.where.length === 1) {\n\t\t\twhereClause = dispatch(config.where[0]!, subCtx, state);\n\t\t} else {\n\t\t\tconst conditions = config.where.map((cond) =>\n\t\t\t\tdispatch(cond, subCtx, state),\n\t\t\t);\n\t\t\twhereClause = {\n\t\t\t\tBoolExpr: {\n\t\t\t\t\tboolop: 'AND_EXPR',\n\t\t\t\t\targs: conditions,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\t// Build RETURNING clause if specified\n\tconst returningList = buildReturningList(config.returning, tableAlias, ctx);\n\n\t// Build DELETE statement (exactOptionalPropertyTypes compatible)\n\tconst options: DeleteOptions = {\n\t\ttable: config.table,\n\t\tnaming,\n\t};\n\tif (ctx.schema) options.schema = ctx.schema;\n\tif (whereClause) options.where = whereClause;\n\tif (returningList) options.returning = returningList;\n\n\treturn deleteStmt(options);\n}\n\n/**\n * Compile an INSERT FROM SELECT statement from configuration.\n * INSERT INTO target (cols) SELECT cols FROM source WHERE ... LIMIT ... RETURNING ...\n */\nexport function compileInsertFrom(\n\tconfig: InsertFromConfig,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): Node {\n\tconst naming = ctx.naming;\n\tconst _dbTargetTable = naming.toDatabase(config.targetTable);\n\tconst dbSourceTable = naming.toDatabase(config.sourceTable);\n\tconst sourceAlias = config.sourceTable;\n\n\t// Build column list\n\tconst dbColumns = config.columns?.map((c) => naming.toDatabase(c));\n\n\t// Build SELECT target list\n\tlet targetList: Node[];\n\tif (config.columns && config.columns.length > 0) {\n\t\ttargetList = config.columns.map((col) =>\n\t\t\tresTarget(\n\t\t\t\tcolumnRef(col, sourceAlias, ctx.schema, naming),\n\t\t\t\tnaming.toDatabase(col),\n\t\t\t),\n\t\t);\n\t} else {\n\t\t// SELECT *\n\t\ttargetList = [\n\t\t\t{\n\t\t\t\tResTarget: {\n\t\t\t\t\tval: { ColumnRef: { fields: [{ A_Star: {} }] } },\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\t}\n\n\t// Build WHERE clause for source query if present\n\tlet whereClause: Node | undefined;\n\tif (config.where && config.where.length > 0) {\n\t\tconst dispatch = createWhereDispatcher();\n\t\tconst subCtx = { ...ctx, currentAlias: sourceAlias };\n\n\t\tif (config.where.length === 1) {\n\t\t\twhereClause = dispatch(config.where[0]!, subCtx, state);\n\t\t} else {\n\t\t\tconst conditions = config.where.map((cond) =>\n\t\t\t\tdispatch(cond, subCtx, state),\n\t\t\t);\n\t\t\twhereClause = {\n\t\t\t\tBoolExpr: {\n\t\t\t\t\tboolop: 'AND_EXPR',\n\t\t\t\t\targs: conditions,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\t// Build LIMIT clause if specified\n\tlet limitCount: Node | undefined;\n\tif (config.limit !== undefined) {\n\t\tlimitCount = { A_Const: { ival: { ival: config.limit } } };\n\t}\n\n\t// Build the SELECT query\n\tconst sourceRelation: {\n\t\tschemaname?: string;\n\t\trelname: string;\n\t\tinh: boolean;\n\t\trelpersistence: string;\n\t\talias?: { aliasname: string };\n\t} = {\n\t\trelname: dbSourceTable,\n\t\tinh: true,\n\t\trelpersistence: 'p',\n\t};\n\tif (ctx.schema) {\n\t\tsourceRelation.schemaname = naming.toDatabase(ctx.schema);\n\t}\n\n\tconst selectQuery: Node = {\n\t\tSelectStmt: {\n\t\t\ttargetList,\n\t\t\tfromClause: [{ RangeVar: sourceRelation }],\n\t\t\t...(whereClause && { whereClause }),\n\t\t\t...(limitCount && { limitCount }),\n\t\t},\n\t};\n\n\t// Build RETURNING clause for INSERT if specified\n\tconst returningList = buildReturningList(\n\t\tconfig.returning,\n\t\tconfig.targetTable,\n\t\tctx,\n\t);\n\n\t// Build INSERT statement with SELECT query\n\t// Note: dbTargetTable is computed but table in options uses logical name\n\t// as insertStmt applies naming internally\n\tconst options: InsertOptions = {\n\t\ttable: config.targetTable,\n\t\tselectQuery,\n\t\tnaming,\n\t};\n\tif (dbColumns) options.columns = dbColumns;\n\tif (ctx.schema) options.schema = ctx.schema;\n\tif (returningList) options.returning = returningList;\n\n\treturn insertStmt(options);\n}\n\n/**\n * Compile an UPSERT FROM statement (INSERT ... SELECT ... ON CONFLICT DO UPDATE).\n *\n * Produces: INSERT INTO target SELECT ... FROM source ON CONFLICT (cols) DO UPDATE SET col = EXCLUDED.col\n */\nexport function compileUpsertFrom(\n\tconfig: UpsertFromConfig,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): Node {\n\tconst naming = ctx.naming;\n\tconst dbSourceTable = naming.toDatabase(config.sourceTable);\n\tconst sourceAlias = config.sourceTable;\n\n\t// Build column list\n\tconst dbColumns = config.columns?.map((c) => naming.toDatabase(c));\n\n\t// Build SELECT target list\n\tlet targetList: Node[];\n\tif (config.columns && config.columns.length > 0) {\n\t\ttargetList = config.columns.map((col) =>\n\t\t\tresTarget(\n\t\t\t\tcolumnRef(col, sourceAlias, ctx.schema, naming),\n\t\t\t\tnaming.toDatabase(col),\n\t\t\t),\n\t\t);\n\t} else {\n\t\t// SELECT *\n\t\ttargetList = [\n\t\t\t{\n\t\t\t\tResTarget: {\n\t\t\t\t\tval: { ColumnRef: { fields: [{ A_Star: {} }] } },\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\t}\n\n\t// Build WHERE clause for source query if present\n\tlet whereClause: Node | undefined;\n\tif (config.where && config.where.length > 0) {\n\t\tconst dispatch = createWhereDispatcher();\n\t\tconst subCtx = { ...ctx, currentAlias: sourceAlias };\n\n\t\tif (config.where.length === 1) {\n\t\t\twhereClause = dispatch(config.where[0]!, subCtx, state);\n\t\t} else {\n\t\t\tconst conditions = config.where.map((cond) =>\n\t\t\t\tdispatch(cond, subCtx, state),\n\t\t\t);\n\t\t\twhereClause = {\n\t\t\t\tBoolExpr: {\n\t\t\t\t\tboolop: 'AND_EXPR',\n\t\t\t\t\targs: conditions,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t}\n\n\t// Build LIMIT clause if specified\n\tlet limitCount: Node | undefined;\n\tif (config.limit !== undefined) {\n\t\tlimitCount = { A_Const: { ival: { ival: config.limit } } };\n\t}\n\n\t// Build the SELECT query\n\tconst sourceRelation: {\n\t\tschemaname?: string;\n\t\trelname: string;\n\t\tinh: boolean;\n\t\trelpersistence: string;\n\t\talias?: { aliasname: string };\n\t} = {\n\t\trelname: dbSourceTable,\n\t\tinh: true,\n\t\trelpersistence: 'p',\n\t};\n\tif (ctx.schema) {\n\t\tsourceRelation.schemaname = naming.toDatabase(ctx.schema);\n\t}\n\n\tconst selectQuery: Node = {\n\t\tSelectStmt: {\n\t\t\ttargetList,\n\t\t\tfromClause: [{ RangeVar: sourceRelation }],\n\t\t\t...(whereClause && { whereClause }),\n\t\t\t...(limitCount && { limitCount }),\n\t\t},\n\t};\n\n\t// Build RETURNING clause\n\tconst returningList = buildReturningList(\n\t\tconfig.returning,\n\t\tconfig.targetTable,\n\t\tctx,\n\t);\n\n\t// Build ON CONFLICT clause: DO UPDATE SET col = EXCLUDED.col for non-conflict columns\n\tconst conflictInfer = {\n\t\tindexElems: config.conflictColumns.map((col) => ({\n\t\t\tIndexElem: {\n\t\t\t\tname: naming.toDatabase(col),\n\t\t\t},\n\t\t})),\n\t};\n\n\t// Determine update columns: all source columns minus conflict columns\n\tconst updateColumns = config.columns\n\t\t? config.columns.filter((c) => !config.conflictColumns.includes(c))\n\t\t: [];\n\n\tconst onConflictTargetList: Node[] = updateColumns.map((col) => {\n\t\tconst dbCol = naming.toDatabase(col);\n\t\treturn {\n\t\t\tResTarget: {\n\t\t\t\tname: dbCol,\n\t\t\t\tval: {\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: 'excluded' } },\n\t\t\t\t\t\t\t{ String: { sval: dbCol } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t});\n\n\t// Build INSERT statement with SELECT query + ON CONFLICT\n\tconst options: InsertOptions = {\n\t\ttable: config.targetTable,\n\t\tselectQuery,\n\t\tnaming,\n\t};\n\tif (dbColumns) options.columns = dbColumns;\n\tif (ctx.schema) options.schema = ctx.schema;\n\tif (returningList) options.returning = returningList;\n\n\t// Get base InsertStmt and add onConflictClause manually\n\tconst node = insertStmt(options);\n\tconst insertNode = (node as InsertStmtNode).InsertStmt;\n\tinsertNode.onConflictClause = {\n\t\taction: 'ONCONFLICT_UPDATE',\n\t\tinfer: conflictInfer,\n\t\t...(onConflictTargetList.length > 0 && {\n\t\t\ttargetList: onConflictTargetList,\n\t\t}),\n\t};\n\n\treturn node;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Convert a JavaScript value to an AST node.\n * Uses parameters for actual values.\n */\n/** PostgreSQL range types that require explicit type-cast on parameter binding */\nexport const RANGE_TYPES = new Set([\n\t'daterange',\n\t'tsrange',\n\t'tstzrange',\n\t'int4range',\n\t'int8range',\n\t'numrange',\n]);\n\nfunction valueToNode(\n\tvalue: unknown,\n\tstate: CompilerState,\n\tdbType?: string,\n): Node {\n\tif (value === null || value === undefined) {\n\t\treturn { A_Const: { isnull: true } };\n\t}\n\n\t// Add to parameters and return a ParamRef\n\tstate.parameters.push(value);\n\tstate.paramIndex++;\n\n\t// Range types require explicit cast ($N::int4range) for PostgreSQL to parse the literal\n\tif (dbType && RANGE_TYPES.has(dbType)) {\n\t\treturn createTypeCastParamRef(state.paramIndex, dbType);\n\t}\n\n\treturn {\n\t\tParamRef: {\n\t\t\tnumber: state.paramIndex,\n\t\t},\n\t};\n}\n\n/**\n * Compile a mutation decision to AST.\n * Determines mutation type from decision.type and delegates.\n */\nexport function compileMutation(\n\tdecision: Decision,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): Node {\n\tconst type = decision.type;\n\tconst table = decision.table ?? ctx.rootTable;\n\n\tswitch (type) {\n\t\tcase 'insert': {\n\t\t\tconst insertConfig: InsertConfig = {\n\t\t\t\ttable,\n\t\t\t\tcolumns: decision.columns ? [...decision.columns] : [],\n\t\t\t\tvalues: decision.values ? [[...decision.values] as unknown[]] : [],\n\t\t\t};\n\t\t\tif (decision.columns) insertConfig.returning = [...decision.columns];\n\t\t\treturn compileInsert(insertConfig, ctx, state);\n\t\t}\n\n\t\tcase 'update': {\n\t\t\tconst updateConfig: UpdateConfig = {\n\t\t\t\ttable,\n\t\t\t\tset: decision.set ? [...decision.set] : [],\n\t\t\t};\n\t\t\tif (decision.conditions) updateConfig.where = [...decision.conditions];\n\t\t\tif (decision.columns) updateConfig.returning = [...decision.columns];\n\t\t\treturn compileUpdate(updateConfig, ctx, state);\n\t\t}\n\n\t\tcase 'delete': {\n\t\t\tconst deleteConfig: DeleteConfig = {\n\t\t\t\ttable,\n\t\t\t};\n\t\t\tif (decision.conditions) deleteConfig.where = [...decision.conditions];\n\t\t\tif (decision.columns) deleteConfig.returning = [...decision.columns];\n\t\t\treturn compileDelete(deleteConfig, ctx, state);\n\t\t}\n\n\t\tdefault:\n\t\t\tthrow new Error(`Unknown mutation type: ${type}`);\n\t}\n}\n","/**\n * Upsert (INSERT ... ON CONFLICT) Compiler\n *\n * Compiles UPSERT statements with ON CONFLICT handling.\n * Supports:\n * - ON CONFLICT DO NOTHING\n * - ON CONFLICT DO UPDATE SET ...\n * - Conflict target (columns or constraint name)\n * - WHERE clause for conflict resolution\n */\n\nimport type { InferClause, Node, OnConflictClause } from '@pgsql/types';\nimport { columnRef, funcCall } from '../ast-helpers.js';\nimport {\n\tinferPgArrayType,\n\tparseRawExpression,\n\tstripArraySuffix,\n\ttransposeToColumnArrays,\n\tvalidateBatchCardinality,\n} from '../compiler-utils.js';\nimport { createWhereDispatcher } from '../handlers/index.js';\nimport type {\n\tCompilerContext,\n\tCompilerState,\n\tDecision,\n} from '../handlers/types.js';\nimport { createTypeCastParamRef } from '../param-ref.js';\nimport { buildReturningList } from './mutation-compiler.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Conflict resolution strategy\n */\nexport type ConflictAction = 'nothing' | 'update';\n\n/**\n * Conflict target specification\n */\nexport interface ConflictTarget {\n\t/** Column names that form the unique constraint */\n\tcolumns?: string[];\n\t/** Named constraint */\n\tconstraint?: string;\n\t/** WHERE clause for partial index */\n\twhere?: Decision[];\n}\n\n/**\n * Configuration for UPSERT compilation\n */\nexport interface UpsertConfig {\n\t/** Table to upsert into */\n\ttable: string;\n\t/** Columns to insert */\n\tcolumns: string[];\n\t/** Values for each column (array of rows) */\n\tvalues: unknown[][];\n\t/** Conflict target (unique columns or constraint) */\n\tconflictTarget: ConflictTarget;\n\t/** What to do on conflict */\n\tconflictAction: ConflictAction;\n\t/** Columns to update on conflict (for 'update' action) */\n\tupdateColumns?: string[];\n\t/** Use EXCLUDED.column for update values (default: true) */\n\tuseExcluded?: boolean;\n\t/** Columns to return (RETURNING clause) */\n\treturning?: string[];\n\t/** Optional column type hints for unnest casting (schema-driven) */\n\tcolumnTypes?: Record<string, string>;\n\t/**\n\t * Raw SQL expressions for specific update columns.\n\t * These are injected verbatim into the ON CONFLICT DO UPDATE SET clause.\n\t * Keys are logical column names (before naming plugin), values are raw SQL fragments.\n\t *\n\t * @warning SECURITY: fragments are inserted without parameterization.\n\t * Only use with hardcoded expressions. Never with user input.\n\t *\n\t * @example { last_parsed: 'now()', count: 'excluded.count + 1' }\n\t */\n\tupdateExpressions?: Record<string, string>;\n}\n\n// ============================================================================\n// ON CONFLICT Builder\n// ============================================================================\n\n/**\n * Build ON CONFLICT clause for INSERT statement.\n */\nexport function buildOnConflictClause(\n\tconfig: UpsertConfig,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): OnConflictClause {\n\tconst naming = ctx.naming;\n\tconst action = config.conflictAction;\n\n\t// Build conflict target\n\tlet infer: InferClause | undefined;\n\tif (\n\t\tconfig.conflictTarget.columns &&\n\t\tconfig.conflictTarget.columns.length > 0\n\t) {\n\t\t// Conflict on columns\n\t\tinfer = {\n\t\t\tindexElems: config.conflictTarget.columns.map((col) => ({\n\t\t\t\tIndexElem: {\n\t\t\t\t\tname: naming.toDatabase(col),\n\t\t\t\t},\n\t\t\t})),\n\t\t};\n\n\t\t// Partial-index conflict: ON CONFLICT (col) WHERE predicate\n\t\tif (config.conflictTarget.where && config.conflictTarget.where.length > 0) {\n\t\t\tconst dispatch = createWhereDispatcher();\n\t\t\tconst conditions = config.conflictTarget.where;\n\t\t\tlet whereClause: Node;\n\t\t\tif (conditions.length === 1) {\n\t\t\t\twhereClause = dispatch(conditions[0]!, ctx, state);\n\t\t\t} else {\n\t\t\t\tconst nodes = conditions.map((c) => dispatch(c, ctx, state));\n\t\t\t\twhereClause = {\n\t\t\t\t\tBoolExpr: { boolop: 'AND_EXPR', args: nodes },\n\t\t\t\t} as unknown as Node;\n\t\t\t}\n\t\t\tinfer.whereClause = whereClause;\n\t\t}\n\t} else if (config.conflictTarget.constraint) {\n\t\t// Conflict on named constraint\n\t\tinfer = {\n\t\t\tconname: naming.toDatabase(config.conflictTarget.constraint),\n\t\t};\n\t}\n\n\t// DO NOTHING case\n\tif (action === 'nothing') {\n\t\treturn {\n\t\t\taction: 'ONCONFLICT_NOTHING',\n\t\t\t...(infer && { infer }),\n\t\t};\n\t}\n\n\t// DO UPDATE SET case\n\tconst updateColumns = config.updateColumns ?? config.columns;\n\tconst useExcluded = config.useExcluded ?? true;\n\n\tconst targetList: Node[] = updateColumns.map((col) => {\n\t\tconst dbCol = naming.toDatabase(col);\n\n\t\t// Raw SQL expression: emit the parsed AST node verbatim\n\t\tconst rawExpr = config.updateExpressions?.[col];\n\t\tif (rawExpr !== undefined) {\n\t\t\treturn {\n\t\t\t\tResTarget: {\n\t\t\t\t\tname: dbCol,\n\t\t\t\t\tval: parseRawExpression(rawExpr),\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tResTarget: {\n\t\t\t\tname: dbCol,\n\t\t\t\tval: useExcluded\n\t\t\t\t\t? // Use EXCLUDED.column (the value that would have been inserted)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t{ String: { sval: 'excluded' } },\n\t\t\t\t\t\t\t\t\t{ String: { sval: dbCol } },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t: // Use parameter placeholder\n\t\t\t\t\t\tvalueToParam(state),\n\t\t\t},\n\t\t};\n\t});\n\n\treturn {\n\t\taction: 'ONCONFLICT_UPDATE',\n\t\t...(infer && { infer }),\n\t\ttargetList,\n\t};\n}\n\n/**\n * Compile a complete UPSERT statement.\n */\nexport function compileUpsert(\n\tconfig: UpsertConfig,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): Node {\n\tconst naming = ctx.naming;\n\tconst dbTable = naming.toDatabase(config.table);\n\tconst dbColumns = config.columns.map((c) => naming.toDatabase(c));\n\n\t// Build column names\n\tconst cols = dbColumns.map((c) => ({ String: { sval: c } }));\n\n\t// Build VALUES lists\n\tconst valuesList: Node[] = config.values.map((row) => ({\n\t\tList: {\n\t\t\titems: row.map((val) => valueToParam(state, val)),\n\t\t},\n\t}));\n\n\t// Build ON CONFLICT clause\n\tconst onConflict = buildOnConflictClause(config, ctx, state);\n\n\t// Build RETURNING clause if specified\n\tconst returningList = buildReturningList(config.returning, dbTable, ctx);\n\n\t// Build INSERT statement with ON CONFLICT\n\treturn {\n\t\tInsertStmt: {\n\t\t\trelation: {\n\t\t\t\trelname: dbTable,\n\t\t\t\t...(ctx.schema && { schemaname: ctx.schema }),\n\t\t\t\tinh: true,\n\t\t\t\trelpersistence: 'p',\n\t\t\t},\n\t\t\tcols,\n\t\t\tselectStmt: {\n\t\t\t\tSelectStmt: {\n\t\t\t\t\tvaluesLists: valuesList,\n\t\t\t\t},\n\t\t\t},\n\t\t\tonConflictClause: onConflict,\n\t\t\t...(returningList && { returningList }),\n\t\t\toverride: 'OVERRIDING_NOT_SET',\n\t\t},\n\t};\n}\n\n/**\n * Compile a UPSERT statement using the unnest strategy for large batches.\n *\n * Generates:\n * INSERT INTO \"table\" (\"col1\", \"col2\")\n * SELECT unnest($1::type[]), unnest($2::type[])\n * ON CONFLICT (\"conflict_col\") DO UPDATE SET \"col2\" = EXCLUDED.\"col2\"\n * [RETURNING ...]\n *\n * This avoids the PostgreSQL 65535 parameter limit. Uses N parameters\n * (one per column) regardless of row count.\n */\nexport function compileUnnestUpsert(\n\tconfig: UpsertConfig,\n\tctx: CompilerContext,\n\tstate: CompilerState,\n): Node {\n\tconst naming = ctx.naming;\n\tconst dbTable = naming.toDatabase(config.table);\n\tconst { columns, values, columnTypes } = config;\n\n\t// Validate cardinality before any SQL generation (INV-02)\n\tvalidateBatchCardinality(columns, values);\n\n\t// Transpose row-major → column-major\n\tconst columnArrays = transposeToColumnArrays(columns, values);\n\n\t// Build SELECT target list: unnest($N::type[]) AS \"col\"\n\tconst targetList: Node[] = columns.map((col, i) => {\n\t\tconst colArray: unknown[] = columnArrays[i] ?? [];\n\n\t\t// Find a non-null sample value for runtime type fallback\n\t\tconst sampleValue = colArray.find((v) => v !== null && v !== undefined);\n\n\t\t// Strip trailing [] to get base type\n\t\tconst pgArrayType = inferPgArrayType(col, columnTypes, sampleValue);\n\t\tconst pgBaseType = stripArraySuffix(pgArrayType);\n\n\t\t// Add array parameter and get its 1-based index\n\t\tstate.parameters.push(colArray);\n\t\tstate.paramIndex++;\n\t\tconst paramIdx = state.paramIndex;\n\n\t\t// Build: unnest($N::base_type[])\n\t\tconst typeCasted = createTypeCastParamRef(paramIdx, pgBaseType, true);\n\t\tconst unnestCall = funcCall('unnest', [typeCasted]);\n\n\t\t// ResTarget with column alias: unnest(...) AS \"colname\"\n\t\treturn {\n\t\t\tResTarget: {\n\t\t\t\tname: naming.toDatabase(col),\n\t\t\t\tval: unnestCall,\n\t\t\t},\n\t\t};\n\t});\n\n\t// Build the SELECT statement for INSERT ... SELECT\n\tconst selectQuery: Node = {\n\t\tSelectStmt: {\n\t\t\ttargetList,\n\t\t},\n\t};\n\n\t// Build ON CONFLICT clause (same as VALUES path)\n\tconst onConflict = buildOnConflictClause(config, ctx, state);\n\n\t// Build RETURNING clause if specified\n\tconst returningList = buildReturningList(config.returning, dbTable, ctx);\n\n\t// Build INSERT INTO \"table\" (\"col1\", \"col2\") <selectQuery> ON CONFLICT ...\n\treturn {\n\t\tInsertStmt: {\n\t\t\trelation: {\n\t\t\t\trelname: dbTable,\n\t\t\t\t...(ctx.schema && { schemaname: ctx.schema }),\n\t\t\t\tinh: true,\n\t\t\t\trelpersistence: 'p',\n\t\t\t},\n\t\t\tcols: columns.map((c) => ({\n\t\t\t\tResTarget: { name: naming.toDatabase(c) },\n\t\t\t})),\n\t\t\tselectStmt: selectQuery,\n\t\t\tonConflictClause: onConflict,\n\t\t\t...(returningList && { returningList }),\n\t\t\toverride: 'OVERRIDING_NOT_SET',\n\t\t},\n\t};\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Convert value to a parameter reference.\n */\nfunction valueToParam(state: CompilerState, value?: unknown): Node {\n\tif (value !== undefined) {\n\t\tstate.parameters.push(value);\n\t}\n\tstate.paramIndex++;\n\n\treturn {\n\t\tParamRef: {\n\t\t\tnumber: state.paramIndex,\n\t\t},\n\t};\n}\n\n/**\n * Build EXCLUDED.column reference.\n * EXCLUDED is a special table alias in ON CONFLICT ... DO UPDATE\n * that refers to the row that would have been inserted.\n */\nexport function excludedRef(\n\tcolumn: string,\n\tnaming: { toDatabase: (s: string) => string },\n): Node {\n\treturn {\n\t\tColumnRef: {\n\t\t\tfields: [\n\t\t\t\t{ String: { sval: 'excluded' } },\n\t\t\t\t{ String: { sval: naming.toDatabase(column) } },\n\t\t\t],\n\t\t},\n\t};\n}\n\n/**\n * Build conditional update using COALESCE.\n *\n * Produces: COALESCE(EXCLUDED.col, table.col)\n * This keeps existing value if new value is NULL.\n */\nexport function conditionalUpdate(\n\tcolumn: string,\n\ttable: string,\n\tctx: CompilerContext,\n): Node {\n\tconst naming = ctx.naming;\n\tconst _dbCol = naming.toDatabase(column);\n\tconst dbTable = naming.toDatabase(table);\n\n\treturn {\n\t\tFuncCall: {\n\t\t\tfuncname: [{ String: { sval: 'coalesce' } }],\n\t\t\targs: [\n\t\t\t\texcludedRef(column, naming),\n\t\t\t\tcolumnRef(column, dbTable, ctx.schema, naming),\n\t\t\t],\n\t\t},\n\t};\n}\n","/**\n * @module naming\n * Utilities for resolving database names to logical model names.\n *\n * The ModelIR.getTable() method expects logical (camelCase) names,\n * but the adapter often works with database (snake_case) names.\n * This module bridges that gap.\n */\n\nimport type { DbCasing, ModelIR } from '@dbsp/types';\nimport { getNamingPluginForDbCasing } from './naming-plugin.js';\n\n/**\n * Resolve a database table name to the corresponding logical model name.\n *\n * Converts the DB name using the naming convention, then looks it up in the model.\n * Falls back to exact match if conversion doesn't find a match.\n *\n * @param model - The model IR to search in\n * @param dbName - Database table name (e.g. \"post_comments\")\n * @param convention - Naming convention used by the adapter\n * @returns The logical table name if found, undefined otherwise\n *\n * @example\n * ```typescript\n * // With camelCase convention:\n * resolveLogicalName(model, \"post_comments\", \"camelCase\") // → \"postComments\"\n * resolveLogicalName(model, \"posts\", \"camelCase\") // → \"posts\"\n * resolveLogicalName(model, \"unknown\", \"camelCase\") // → undefined\n * ```\n */\nexport function resolveLogicalName(\n\tmodel: ModelIR,\n\tdbName: string,\n\tcasing: DbCasing,\n): string | undefined {\n\tconst plugin = getNamingPluginForDbCasing(casing);\n\tconst logicalName = plugin.toModel(dbName);\n\n\t// Try converted name first\n\tif (model.getTable(logicalName)) {\n\t\treturn logicalName;\n\t}\n\n\t// Fallback: exact match (handles identity/preserve cases)\n\tif (logicalName !== dbName && model.getTable(dbName)) {\n\t\treturn dbName;\n\t}\n\n\treturn undefined;\n}\n","/**\n * PgsqlAdapter - Implements the Adapter interface for PostgreSQL using native pg driver.\n *\n * This adapter wraps a pg Pool instance and provides the unified\n * adapter interface for the db-semantic-planner ORM.\n *\n * @module pgsql-adapter\n */\n\nimport type {\n\tAlterColumnOptions,\n\tCreateIndexOptions,\n\tDropIndexOptions,\n\tIndexInfo,\n\tTruncateOptions,\n\tVacuumOptions,\n} from '@dbsp/core';\nimport { POSTGRESQL_CAPABILITIES, plan as planFn } from '@dbsp/core';\nimport type {\n\tAdapter,\n\tAdapterCapabilities,\n\tAdapterLogger,\n\tAdapterStreamOptions,\n\tBatchUpdateIntent,\n\tCompiledQuery,\n\tCompileOnlyAdapter,\n\tCompileOptions,\n\tCompileResultWithIncludes,\n\tCteQueryIntent,\n\tDbCasing,\n\tDeleteIntent,\n\tDialectCapabilities,\n\tDump,\n\tDumpMeta,\n\tExpressionIntent,\n\tInsertFromIntent,\n\tInsertIntent,\n\tModelIR,\n\tPlanReport,\n\tRecursivePlanReport,\n\tSetOperationIntent,\n\tSubqueryIncludeInfo,\n\tUpdateIntent,\n\tUpsertFromIntent,\n\tUpsertIntent,\n} from '@dbsp/types';\nimport type { Pool, PoolClient } from 'pg';\nimport type { AdapterCompilerDeps } from './adapter-compiler-deps.js';\nimport { compileSubqueryInclude as compileSubqueryIncludeImpl } from './adapter-compiler-includes.js';\nimport {\n\tcompileBatchUpdate as compileBatchUpdateImpl,\n\tcompileDelete as compileDeleteImpl,\n\tcompileInsertFrom as compileInsertFromImpl,\n\tcompileInsert as compileInsertImpl,\n\tcompileUpdate as compileUpdateImpl,\n\tcompileUpsertFrom as compileUpsertFromImpl,\n\tcompileUpsert as compileUpsertImpl,\n} from './adapter-compiler-mutations.js';\nimport {\n\tcompileCteQuery as compileCteQueryImpl,\n\tcompileRecursive as compileRecursiveImpl,\n} from './adapter-compiler-recursive.js';\nimport {\n\tcompileSelect,\n\tcompileWithIncludes as compileWithIncludesImpl,\n} from './adapter-compiler-select.js';\nimport {\n\tDEFAULT_PK_COLUMN,\n\tdefaultFkDerivation,\n\ttype FkColumnDerivation,\n} from './assert-field.js';\nimport { selectStmt } from './ast-helpers.js';\nimport { PlanCompiler, renumberParamRefsInAst } from './compiler.js';\nimport {\n\ttype GenerateDDLOptions,\n\tgenerateDDL as generateDDLStatements,\n} from './ddl/index.js';\nimport {\n\tgenerateCreateIndexSQL,\n\tgenerateDropIndexSQL,\n} from './ddl/index-operations.js';\nimport {\n\tgenerateAlterColumnSQL,\n\tgenerateTruncateSQL,\n\tgenerateVacuumSQL,\n} from './ddl/table-operations.js';\nimport { deparseQuoted } from './deparse.js';\nimport { compileExpressionIntent } from './handlers/expression/custom.js';\nimport { createCompilerState } from './handlers/types.js';\nimport { intentToDecisions } from './intent-to-decisions.js';\nimport {\n\ttype IntrospectedModelIR,\n\ttype IntrospectionOptions,\n\tintrospect as introspectDb,\n} from './introspection.js';\nimport {\n\tgetNamingPluginForDbCasing,\n\ttype NamingPlugin,\n} from './naming-plugin.js';\nimport {\n\tcompileSetOperation as compileSetOperationImpl,\n\tcreateLeafCompileFn,\n} from './set-operation.js';\nimport { generateCursorName } from './streaming/cursor.js';\nimport { validateIdentifier } from './validate.js';\n\n// ============================================================================\n// Internal types\n// ============================================================================\n\ntype CompileSubqueryResult = {\n\tast: import('@pgsql/types').Node;\n\tparameters: readonly unknown[];\n};\n// ============================================================================\n// Options\n// ============================================================================\n\n/**\n * Options for PgsqlAdapter.\n */\nexport interface PgsqlAdapterOptions {\n\t/** Schema name for multi-tenant queries */\n\treadonly schemaName?: string;\n\t/**\n\t * DB column casing convention (intuitive semantics).\n\t * - `'snake_case'`: DB columns are snake_case → transform to camelCase for JS\n\t * - `'camelCase'`: DB columns are camelCase → no transformation\n\t * - `'preserve'`: No transformation\n\t */\n\treadonly dbCasing?: DbCasing;\n\t/** Optional model for WHERE compilation */\n\treadonly model?: ModelIR;\n\t/** Optional logger for debug/error messages */\n\treadonly logger?: AdapterLogger;\n\t/** Default primary key column name for convention fallbacks (default: 'id') */\n\treadonly defaultPkColumnName?: string;\n\t/** Convention for deriving FK column names: (tableName, pkName) => fkColumnName */\n\treadonly deriveFkColumnName?: FkColumnDerivation;\n}\n\n// ============================================================================\n// PgsqlAdapter\n// ============================================================================\n\n/**\n * Adapter implementation for PostgreSQL using native pg driver.\n *\n * @typeParam DB - Database schema type\n *\n * @example\n * ```typescript\n * import { Pool } from 'pg';\n * import { createPgsqlAdapter } from '@dbsp/adapter-pgsql';\n *\n * const pool = new Pool({ connectionString: process.env.DATABASE_URL });\n * const adapter = createPgsqlAdapter(pool);\n * const orm = createOrm({ model, adapter });\n * ```\n */\nexport class PgsqlAdapter<DB = unknown> implements Adapter<DB> {\n\tprivate readonly pool: Pool | undefined;\n\tprivate readonly client: PoolClient | undefined;\n\tprivate readonly schemaName: string | undefined;\n\tprivate readonly _dbCasing: DbCasing;\n\tprivate readonly naming: NamingPlugin;\n\tprivate readonly model: ModelIR | undefined;\n\tprivate readonly logger: AdapterLogger | undefined;\n\tprivate readonly _capabilities: AdapterCapabilities;\n\tprivate readonly defaultPk: string;\n\tprivate readonly deriveFk: FkColumnDerivation;\n\n\t/**\n\t * Create a new PgsqlAdapter.\n\t *\n\t * @param pool - pg.Pool instance, PoolClient (transactions), or undefined (compile-only mode)\n\t * @param options - Optional configuration\n\t */\n\tconstructor(\n\t\tpool?: Pool | PoolClient | undefined,\n\t\toptions?: PgsqlAdapterOptions,\n\t) {\n\t\tif (pool != null) {\n\t\t\t// Detect if this is a PoolClient (transaction context)\n\t\t\tif ('release' in pool && typeof pool.release === 'function') {\n\t\t\t\tthis.client = pool as PoolClient;\n\t\t\t\t// For clients, we need to get the pool reference\n\t\t\t\t// This is a limitation - we'll use the client directly\n\t\t\t\tthis.pool = pool as unknown as Pool;\n\t\t\t} else {\n\t\t\t\tthis.pool = pool as Pool;\n\t\t\t\tthis.client = undefined;\n\t\t\t}\n\t\t} else {\n\t\t\t// Compile-only mode — no pool/client\n\t\t\tthis.pool = undefined;\n\t\t\tthis.client = undefined;\n\t\t}\n\n\t\tthis.schemaName = options?.schemaName;\n\t\tthis._dbCasing = options?.dbCasing ?? 'preserve';\n\t\tthis.naming = getNamingPluginForDbCasing(this._dbCasing);\n\t\tthis.model = options?.model;\n\t\tthis.logger = options?.logger;\n\t\tthis.defaultPk = options?.defaultPkColumnName ?? DEFAULT_PK_COLUMN;\n\t\tthis.deriveFk = options?.deriveFkColumnName ?? defaultFkDerivation;\n\n\t\t// PostgreSQL capabilities — streaming requires a connection\n\t\tthis._capabilities = {\n\t\t\tsupportsReturning: true,\n\t\t\tsupportsSchemas: true,\n\t\t\tsupportsStreaming: pool != null,\n\t\t\tsupportsRecursiveCTE: true,\n\t\t\tsupportsWindowFunctions: true,\n\t\t\tsupportsArrayType: true,\n\t\t};\n\t}\n\n\t/**\n\t * Shared compilation dependencies — built lazily from adapter fields.\n\t * Passed to compiler sub-modules instead of `this`.\n\t */\n\n\t/**\n\t * Return a new PgsqlAdapterOptions that merges current config with overrides.\n\t * Ensures that all configuration fields (logger, defaultPkColumnName,\n\t * deriveFkColumnName, etc.) are propagated to scoped/transactional adapters.\n\t */\n\tprivate cloneOptions(\n\t\toverrides: Partial<PgsqlAdapterOptions>,\n\t): PgsqlAdapterOptions {\n\t\treturn {\n\t\t\t...(this.schemaName !== undefined && { schemaName: this.schemaName }),\n\t\t\t...(this._dbCasing !== undefined && { dbCasing: this._dbCasing }),\n\t\t\t...(this.model !== undefined && { model: this.model }),\n\t\t\t...(this.logger !== undefined && { logger: this.logger }),\n\t\t\tdefaultPkColumnName: this.defaultPk,\n\t\t\tderiveFkColumnName: this.deriveFk,\n\t\t\t...overrides,\n\t\t};\n\t}\n\n\tprivate buildCompileDeps(options?: CompileOptions): AdapterCompilerDeps {\n\t\t// Validate schemaName from CompileOptions before use — prevents SQL injection\n\t\t// via direct callers of adapter.compile(). Empty string is treated as \"no\n\t\t// override\" (falls through to this.schemaName via ||), so we skip it here;\n\t\t// the empty-string → fallback behaviour is covered by existing tests.\n\t\tif (options?.schemaName) {\n\t\t\tvalidateIdentifier(options.schemaName, 'schema');\n\t\t}\n\t\treturn {\n\t\t\tnaming: this.naming,\n\t\t\t// `||` (not `??`): empty string is treated as \"no override\" and falls back to this.schemaName (which may be a configured schema or undefined)\n\t\t\tschemaName: options?.schemaName || this.schemaName,\n\t\t\tmodel: options?.model ?? this.model,\n\t\t\tdefaultPk: this.defaultPk,\n\t\t\tderiveFk: this.deriveFk,\n\t\t};\n\t}\n\n\t/**\n\t * Returns the pool/client executor, or throws if in compile-only mode.\n\t */\n\tprivate requireConnection(): Pool | PoolClient {\n\t\tconst executor = this.client ?? this.pool;\n\t\tif (!executor) {\n\t\t\tthrow new Error(\n\t\t\t\t'PgsqlAdapter is in compile-only mode (no database connection). ' +\n\t\t\t\t\t'Use createPgsqlAdapter(pool) for a full adapter with execution capabilities.',\n\t\t\t);\n\t\t}\n\t\treturn executor;\n\t}\n\n\t/** Adapter capabilities for feature detection */\n\tget capabilities(): AdapterCapabilities {\n\t\treturn this._capabilities;\n\t}\n\n\t/** PostgreSQL dialect capabilities for planner strategy selection */\n\tget dialectCapabilities(): DialectCapabilities {\n\t\treturn POSTGRESQL_CAPABILITIES;\n\t}\n\n\t/**\n\t * DB column casing convention used by this adapter.\n\t */\n\tget dbCasing(): DbCasing {\n\t\treturn this._dbCasing;\n\t}\n\n\t/**\n\t * Get the underlying pg Pool instance.\n\t */\n\tgetPoolInstance(): Pool {\n\t\treturn this.requireConnection() as Pool;\n\t}\n\n\t// =========================================================================\n\t// CompilingAdapter Methods\n\t// =========================================================================\n\n\t/**\n\t * Compile a plan to executable SQL.\n\t */\n\tcompile<T = unknown>(\n\t\tplan: PlanReport,\n\t\toptions?: CompileOptions,\n\t): CompiledQuery<T> {\n\t\treturn compileSelect<T>(plan, options, this.buildCompileDeps(options));\n\t}\n\n\t/**\n\t * Compile a plan with includes, returning subquery include metadata (DX-033).\n\t */\n\tcompileWithIncludes<T = unknown>(\n\t\tplan: PlanReport,\n\t\toptions?: CompileOptions,\n\t): CompileResultWithIncludes<T> {\n\t\treturn compileWithIncludesImpl<T>(\n\t\t\tplan,\n\t\t\toptions,\n\t\t\tthis.buildCompileDeps(options),\n\t\t);\n\t}\n\n\t/**\n\t * Compile a subquery include query for given parent IDs (DX-033).\n\t * Generates: SELECT * FROM targetTable WHERE foreignKey IN ($1, $2, ...)\n\t *\n\t * @param info - Subquery include metadata\n\t * @param parentIds - Parent record IDs to fetch related records for\n\t * @param options - Compile options\n\t * @returns Compiled query for fetching related records\n\t */\n\tcompileSubqueryInclude(\n\t\tinfo: SubqueryIncludeInfo,\n\t\tparentIds: readonly unknown[],\n\t\toptions?: CompileOptions,\n\t): CompiledQuery {\n\t\treturn compileSubqueryIncludeImpl(\n\t\t\tinfo,\n\t\t\tparentIds,\n\t\t\toptions,\n\t\t\tthis.buildCompileDeps(options),\n\t\t);\n\t}\n\n\t/**\n\t * Compile a FROM-less SELECT expression to SQL.\n\t *\n\t * Produces: SELECT <expr>\n\t * Example: SELECT nextval('my_seq')\n\t *\n\t * @param expr - ExpressionIntent to evaluate\n\t * @returns Compiled SQL and parameters\n\t */\n\tcompileSelectExpression(expr: ExpressionIntent): CompiledQuery {\n\t\tconst naming = this.naming;\n\t\tconst schemaName = this.schemaName;\n\t\tconst state = createCompilerState();\n\t\tconst ctx = {\n\t\t\tnaming,\n\t\t\t...(schemaName !== undefined && { schema: schemaName }),\n\t\t\trootTable: '',\n\t\t\tmaxRecursiveDepth: 100,\n\t\t\t// Wire compileSubquery so that SubqueryExpressionIntent nested inside\n\t\t\t// expr (e.g. op('+', subquery(...).asExpr(), literal(1))) compiles\n\t\t\t// correctly via a fresh inner PlanCompiler (same pattern as PlanCompiler\n\t\t\t// case 'selectCustomExpression').\n\t\t\tcompileSubquery(\n\t\t\t\tquery: import('@dbsp/types').QueryIntent,\n\t\t\t\tparamOffset: number,\n\t\t\t): CompileSubqueryResult {\n\t\t\t\tconst innerCompiler = new PlanCompiler({\n\t\t\t\t\tnaming,\n\t\t\t\t\t...(schemaName !== undefined && { schema: schemaName }),\n\t\t\t\t});\n\t\t\t\tconst innerPlan = {\n\t\t\t\t\trootTable: query.from,\n\t\t\t\t\tdecisions: intentToDecisions(query, query.from),\n\t\t\t\t};\n\t\t\t\tconst innerResult = innerCompiler.compile(innerPlan);\n\t\t\t\tconst renumbered = renumberParamRefsInAst(innerResult.ast, paramOffset);\n\t\t\t\treturn { ast: renumbered, parameters: innerResult.parameters };\n\t\t\t},\n\t\t};\n\t\tconst node = compileExpressionIntent(expr, ctx, state);\n\t\tconst ast = selectStmt({\n\t\t\ttargetList: [{ ResTarget: { val: node } }],\n\t\t});\n\t\tconst sql = deparseQuoted(ast);\n\t\treturn { sql, parameters: state.parameters };\n\t}\n\n\t/**\n\t * Compile an insert intent to executable SQL.\n\t *\n\t * Strategy switch (per CompileOptions):\n\t * - rows <= batchThreshold (default 50): VALUES ($1,$2),($3,$4),...\n\t * - rows > batchThreshold OR batchThreshold === 0: SELECT unnest($1::type[]),...\n\t */\n\tcompileInsert(intent: InsertIntent, options?: CompileOptions): CompiledQuery {\n\t\treturn compileInsertImpl(intent, options, this.buildCompileDeps(options));\n\t}\n\n\t/**\n\t * Compile an insert-from intent to executable SQL (NQL-ALIGN).\n\t * INSERT INTO target (cols) SELECT cols FROM source WHERE ... LIMIT ... RETURNING ...\n\t */\n\tcompileInsertFrom(\n\t\tintent: InsertFromIntent,\n\t\toptions?: CompileOptions,\n\t): CompiledQuery {\n\t\treturn compileInsertFromImpl(\n\t\t\tintent,\n\t\t\toptions,\n\t\t\tthis.buildCompileDeps(options),\n\t\t);\n\t}\n\n\t/**\n\t * Compile an update intent to executable SQL.\n\t */\n\tcompileUpdate(intent: UpdateIntent, options?: CompileOptions): CompiledQuery {\n\t\treturn compileUpdateImpl(intent, options, this.buildCompileDeps(options));\n\t}\n\n\t/**\n\t * Compile a batch update intent to executable SQL using unnest FROM strategy (BATCH-001).\n\t *\n\t * Generates:\n\t * UPDATE \"table\" SET \"update_col\" = t.\"update_col\" [, \"scalar_col\" = $N]\n\t * FROM unnest(CAST($1 AS type[]), CAST($2 AS type[])) AS t(\"match_col\", \"update_col\")\n\t * WHERE \"table\".\"match_col\" = t.\"match_col\"\n\t * [RETURNING ...]\n\t */\n\tcompileBatchUpdate(\n\t\tintent: BatchUpdateIntent,\n\t\toptions?: CompileOptions,\n\t): CompiledQuery {\n\t\treturn compileBatchUpdateImpl(\n\t\t\tintent,\n\t\t\toptions,\n\t\t\tthis.buildCompileDeps(options),\n\t\t);\n\t}\n\n\t/**\n\t * Compile a delete intent to executable SQL.\n\t */\n\tcompileDelete(intent: DeleteIntent, options?: CompileOptions): CompiledQuery {\n\t\treturn compileDeleteImpl(intent, options, this.buildCompileDeps(options));\n\t}\n\n\t/**\n\t * Compile an upsert intent to executable SQL (DX-026).\n\t */\n\tcompileUpsert(intent: UpsertIntent, options?: CompileOptions): CompiledQuery {\n\t\treturn compileUpsertImpl(intent, options, this.buildCompileDeps(options));\n\t}\n\n\t/**\n\t * Compile an upsert-from intent to executable SQL (NQL-BIND).\n\t * INSERT INTO target SELECT ... FROM source ON CONFLICT (cols) DO UPDATE SET ...\n\t */\n\tcompileUpsertFrom(\n\t\tintent: UpsertFromIntent,\n\t\toptions?: CompileOptions,\n\t): CompiledQuery {\n\t\treturn compileUpsertFromImpl(\n\t\t\tintent,\n\t\t\toptions,\n\t\t\tthis.buildCompileDeps(options),\n\t\t);\n\t}\n\n\t/**\n\t * Compile a recursive CTE plan to executable SQL.\n\t * Supports adjacency-list and edge-table traversal modes.\n\t */\n\tcompileRecursive(\n\t\treport: RecursivePlanReport,\n\t\tmodel: ModelIR,\n\t\toptions?: CompileOptions,\n\t): CompiledQuery {\n\t\treturn compileRecursiveImpl(\n\t\t\treport,\n\t\t\tmodel,\n\t\t\toptions,\n\t\t\tthis.buildCompileDeps(options),\n\t\t);\n\t}\n\n\t/**\n\t * Compile a CTE query backed by unnest() arrays (BATCH-001 Block 5).\n\t *\n\t * Strategy: compile CTE nodes to SQL fragments, compile outer query\n\t * independently (parameters starting at $1), then renumber outer params\n\t * to start after CTE params and prepend WITH clause.\n\t */\n\tcompileCteQuery(\n\t\tintent: CteQueryIntent,\n\t\toptions?: CompileOptions,\n\t): CompiledQuery {\n\t\treturn compileCteQueryImpl(intent, options, this.buildCompileDeps(options));\n\t}\n\n\t/**\n\t * Compile a set operation (UNION / INTERSECT / EXCEPT) to SQL.\n\t */\n\tcompileSetOperation(\n\t\tintent: SetOperationIntent,\n\t\tmodel: ModelIR,\n\t\t_options?: CompileOptions,\n\t): CompiledQuery {\n\t\tconst compileFn = createLeafCompileFn(this, model, planFn);\n\t\tconst result = compileSetOperationImpl(intent, compileFn);\n\t\treturn {\n\t\t\tsql: result.sql,\n\t\t\tparameters: result.parameters,\n\t\t};\n\t}\n\n\t/**\n\t * Create a dump for observability.\n\t */\n\tcreateDump(plan: PlanReport, query: CompiledQuery, meta?: DumpMeta): Dump {\n\t\treturn {\n\t\t\tplan,\n\t\t\tsql: query.sql,\n\t\t\tparams: query.parameters,\n\t\t\tmeta: {\n\t\t\t\t...(this.schemaName !== undefined && { schema: this.schemaName }),\n\t\t\t\tcompiledAt: new Date(),\n\t\t\t\t...meta,\n\t\t\t},\n\t\t};\n\t}\n\n\t// =========================================================================\n\t// ExecutingAdapter Methods\n\t// =========================================================================\n\n\t/**\n\t * Execute a query and return all results.\n\t * Results are transformed to use model naming convention (e.g., snake_case → camelCase)\n\t */\n\tasync execute<T>(query: CompiledQuery<T>): Promise<T[]> {\n\t\tconst executor = this.requireConnection();\n\t\tconst result = await executor.query(query.sql, [...query.parameters]);\n\t\treturn this.transformResultRows(result.rows) as T[];\n\t}\n\n\t/**\n\t * Transform result rows from database naming to model naming convention.\n\t * For CamelCaseNamingPlugin: price_cents → priceCents\n\t */\n\tprivate transformResultRows(\n\t\trows: Record<string, unknown>[],\n\t): Record<string, unknown>[] {\n\t\treturn rows.map((row) => {\n\t\t\tconst transformed: Record<string, unknown> = {};\n\t\t\tfor (const [key, value] of Object.entries(row)) {\n\t\t\t\t// Use toModel to convert database column name to model column name\n\t\t\t\tconst modelKey = this.naming.toModel(key);\n\t\t\t\ttransformed[modelKey] = value;\n\t\t\t}\n\t\t\treturn transformed;\n\t\t});\n\t}\n\n\t/**\n\t * Execute a query and return the first result or null.\n\t */\n\tasync executeOne<T>(query: CompiledQuery<T>): Promise<T | null> {\n\t\tconst results = await this.execute<T>(query);\n\t\treturn results[0] ?? null;\n\t}\n\n\t/**\n\t * Execute a query and return the first result or throw.\n\t */\n\tasync executeOneOrThrow<T>(query: CompiledQuery<T>): Promise<T> {\n\t\tconst result = await this.executeOne<T>(query);\n\t\tif (result === null) {\n\t\t\tthrow new Error('No results found');\n\t\t}\n\t\treturn result;\n\t}\n\n\t// =========================================================================\n\t// StreamingAdapter Methods\n\t// =========================================================================\n\n\t/**\n\t * Stream query results as an async iterable iterator.\n\t * Uses PostgreSQL cursors for efficient streaming.\n\t *\n\t * Note: The cursor must be used within a transaction. If not already\n\t * in a transaction, this method wraps the streaming in one.\n\t *\n\t * @param query - Compiled query to stream\n\t * @param options - Stream options (chunkSize)\n\t * @returns AsyncIterableIterator that yields rows one by one\n\t */\n\tstream<T>(\n\t\tquery: CompiledQuery<T>,\n\t\toptions?: AdapterStreamOptions,\n\t): AsyncIterableIterator<T> {\n\t\tconst chunkSize = options?.chunkSize ?? 100;\n\t\tconst adapter = this;\n\n\t\t// Use a wrapper to create the async generator\n\t\tasync function* streamGenerator(): AsyncIterableIterator<T> {\n\t\t\t// If already in transaction (has client), use it directly\n\t\t\tif (adapter.client) {\n\t\t\t\tyield* adapter.streamWithClient<T>(adapter.client, query, chunkSize);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Otherwise, acquire a client and create a transaction\n\t\t\tconst pool = adapter.requireConnection() as Pool;\n\t\t\tconst client = await pool.connect();\n\t\t\tlet committed = false;\n\t\t\ttry {\n\t\t\t\tawait client.query('BEGIN');\n\t\t\t\tyield* adapter.streamWithClient<T>(client, query, chunkSize);\n\t\t\t\tawait client.query('COMMIT');\n\t\t\t\tcommitted = true;\n\t\t\t} catch (error) {\n\t\t\t\tawait client.query('ROLLBACK');\n\t\t\t\tthrow error;\n\t\t\t} finally {\n\t\t\t\t// On early break, yield* returns without reaching COMMIT.\n\t\t\t\t// ROLLBACK the open transaction to avoid leaking it to the pool.\n\t\t\t\tif (!committed) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait client.query('ROLLBACK');\n\t\t\t\t\t} catch (rollbackErr) {\n\t\t\t\t\t\t// Rollback errors during cleanup are non-actionable;\n\t\t\t\t\t\t// the connection returns to the pool regardless.\n\t\t\t\t\t\tadapter.logger?.debug?.(\n\t\t\t\t\t\t\t'Rollback failed during cleanup',\n\t\t\t\t\t\t\trollbackErr,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tclient.release();\n\t\t\t}\n\t\t}\n\n\t\treturn streamGenerator();\n\t}\n\n\t/**\n\t * Internal: Stream with an existing client using cursors.\n\t */\n\tprivate async *streamWithClient<T>(\n\t\tclient: PoolClient,\n\t\tquery: CompiledQuery<T>,\n\t\tchunkSize: number,\n\t): AsyncIterableIterator<T> {\n\t\t// Generate unique cursor name\n\t\tconst cursorName = generateCursorName();\n\n\t\t// Declare cursor\n\t\tawait client.query(\n\t\t\t`DECLARE ${cursorName} NO SCROLL CURSOR FOR ${query.sql}`,\n\t\t\tquery.parameters as unknown[],\n\t\t);\n\n\t\ttry {\n\t\t\t// Fetch in batches\n\t\t\twhile (true) {\n\t\t\t\tconst result = await client.query(\n\t\t\t\t\t`FETCH FORWARD ${chunkSize} FROM ${cursorName}`,\n\t\t\t\t);\n\n\t\t\t\tif (result.rows.length === 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tfor (const row of result.rows) {\n\t\t\t\t\tyield row as T;\n\t\t\t\t}\n\n\t\t\t\t// If we got fewer rows than batch size, we're done\n\t\t\t\tif (result.rows.length < chunkSize) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\t// Always close the cursor\n\t\t\tawait client.query(`CLOSE ${cursorName}`);\n\t\t}\n\t}\n\n\t// =========================================================================\n\t// IntrospectingAdapter Methods\n\t// =========================================================================\n\n\t/**\n\t * Introspect the database schema and return a ModelIR.\n\t *\n\t * @param options - Optional introspection options (schema, include/exclude filters)\n\t * @returns IntrospectedModelIR with tables, relations, and hierarchy metadata\n\t *\n\t * @example\n\t * ```typescript\n\t * const model = await adapter.introspect();\n\t * const model = await adapter.introspect({ schema: 'tenant_1' });\n\t * const model = await adapter.introspect({ exclude: ['_prisma*'] });\n\t * ```\n\t */\n\tasync introspect(\n\t\toptions?: IntrospectionOptions,\n\t): Promise<IntrospectedModelIR> {\n\t\tif (!this.pool) {\n\t\t\tthrow new Error(\n\t\t\t\t'Cannot introspect without a database connection (compile-only adapter)',\n\t\t\t);\n\t\t}\n\t\treturn introspectDb(this.pool, options);\n\t}\n\n\t// =========================================================================\n\t// TransactionalAdapter Methods\n\t// =========================================================================\n\n\t/**\n\t * Execute a callback within a database transaction.\n\t */\n\tasync transaction<T>(fn: (adapter: Adapter<DB>) => Promise<T>): Promise<T> {\n\t\t// If already in a transaction (this.client exists), reuse it\n\t\tif (this.client) {\n\t\t\treturn fn(this);\n\t\t}\n\n\t\t// Otherwise, acquire a client and start transaction\n\t\tconst pool = this.requireConnection() as Pool;\n\t\tconst client = await pool.connect();\n\t\ttry {\n\t\t\tawait client.query('BEGIN');\n\n\t\t\t// Create transaction-scoped adapter preserving all configuration\n\t\t\tconst txOptions: PgsqlAdapterOptions = this.cloneOptions({});\n\t\t\tconst txAdapter = new PgsqlAdapter<DB>(client, txOptions);\n\n\t\t\tconst result = await fn(txAdapter);\n\n\t\t\tawait client.query('COMMIT');\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\tawait client.query('ROLLBACK');\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tclient.release();\n\t\t}\n\t}\n\n\t/**\n\t * Create a schema-scoped adapter for multi-tenant queries.\n\t */\n\twithSchema(schemaName: string): Adapter<DB> {\n\t\t// Validate schema name\n\t\tvalidateIdentifier(schemaName, 'schema');\n\n\t\t// Create new adapter preserving all configuration, only overriding schemaName\n\t\tconst options: PgsqlAdapterOptions = this.cloneOptions({ schemaName });\n\t\treturn new PgsqlAdapter<DB>(this.client ?? this.pool ?? undefined, options);\n\t}\n\n\t// =========================================================================\n\t// RawSqlAdapter Methods\n\t// =========================================================================\n\n\t/**\n\t * Execute raw SQL directly.\n\t *\n\t * ⚠️ WARNING: Use parameter placeholders ($1, $2, etc.) for all values.\n\t */\n\tasync executeRaw<T = unknown>(\n\t\tsql: string,\n\t\tparameters: readonly unknown[] = [],\n\t): Promise<T[]> {\n\t\tconst executor = this.requireConnection();\n\t\tconst result = await executor.query(sql, [...parameters]);\n\t\treturn result.rows as T[];\n\t}\n\n\t// =========================================================================\n\t// DDLGeneratingAdapter Methods\n\t// =========================================================================\n\n\t/**\n\t * Generate DDL statements from a ModelIR schema.\n\t *\n\t * Uses PostgreSQL AST nodes and pgsql-deparser for consistent SQL generation.\n\t * Applies the naming plugin for identifier transformation.\n\t *\n\t * @param schema - The ModelIR schema to generate DDL from\n\t * @param overrideOptions - Optional overrides for DDL generation (e.g., includeDropStatements)\n\t * @returns Array of DDL statements in dependency order\n\t */\n\tgenerateDDL(\n\t\tschema: ModelIR,\n\t\toverrideOptions?: Partial<GenerateDDLOptions>,\n\t): string[] {\n\t\tconst options: GenerateDDLOptions = {\n\t\t\t...(this.schemaName ? { schemaName: this.schemaName } : {}),\n\t\t\tnaming: this.naming,\n\t\t\t...overrideOptions,\n\t\t};\n\t\treturn generateDDLStatements(schema, options);\n\t}\n\n\t/**\n\t * Execute a DDL statement directly (e.g. TRUNCATE, VACUUM, ALTER TABLE, CREATE INDEX).\n\t *\n\t * @throws Error if called on a compile-only adapter (no pool)\n\t * @since DDL-TABLE-001\n\t */\n\tasync executeDDL(sql: string): Promise<void> {\n\t\tif (!this.pool) {\n\t\t\tthrow new Error('Cannot execute DDL on compile-only adapter');\n\t\t}\n\t\tawait this.pool.query(sql);\n\t}\n\n\t/**\n\t * Whether this adapter instance is scoped inside a transaction.\n\t * Guards unsafe DDL operations (VACUUM, CREATE INDEX CONCURRENTLY).\n\t *\n\t * @since DDL-TABLE-001\n\t */\n\tget inTransaction(): boolean {\n\t\treturn this.client !== undefined;\n\t}\n\n\t/**\n\t * List all indexes on a table by querying pg_indexes.\n\t *\n\t * @param table - Table name\n\t * @param schema - Schema name (defaults to adapter schema or 'public')\n\t */\n\tasync listIndexes(\n\t\ttable: string,\n\t\tschema?: string,\n\t\toptions?: { namePattern?: string },\n\t): Promise<IndexInfo[]> {\n\t\tconst executor = this.requireConnection();\n\t\tconst schemaName = schema ?? this.schemaName ?? 'public';\n\t\tconst params: unknown[] = [table, schemaName];\n\t\tlet sql =\n\t\t\t'SELECT indexname, indexdef FROM pg_indexes WHERE tablename = $1 AND schemaname = $2';\n\t\tif (options?.namePattern) {\n\t\t\tsql += ' AND indexname LIKE $3';\n\t\t\tparams.push(options.namePattern);\n\t\t}\n\t\tsql += ' ORDER BY indexname';\n\t\tconst result = await executor.query<{\n\t\t\tindexname: string;\n\t\t\tindexdef: string;\n\t\t}>(sql, params);\n\t\treturn result.rows.map((row) => {\n\t\t\tconst def = row.indexdef;\n\t\t\tconst unique = /\\bCREATE UNIQUE INDEX\\b/i.test(def);\n\t\t\tconst methodMatch = /\\bUSING\\s+(\\w+)/i.exec(def);\n\t\t\tconst method = methodMatch?.[1] ?? 'btree';\n\t\t\treturn { name: row.indexname, definition: def, unique, method };\n\t\t});\n\t}\n\n\t/**\n\t * Check whether an index with the given name exists on a table.\n\t *\n\t * @param name - Index name\n\t * @param table - Table name\n\t * @param schema - Schema name (defaults to adapter schema or 'public')\n\t */\n\tasync indexExists(\n\t\tname: string,\n\t\ttable: string,\n\t\tschema?: string,\n\t): Promise<boolean> {\n\t\tconst executor = this.requireConnection();\n\t\tconst schemaName = schema ?? this.schemaName ?? 'public';\n\t\tconst result = await executor.query<{ exists: boolean }>(\n\t\t\t'SELECT EXISTS (SELECT 1 FROM pg_indexes WHERE indexname = $1 AND tablename = $2 AND schemaname = $3) AS exists',\n\t\t\t[name, table, schemaName],\n\t\t);\n\t\treturn result.rows[0]?.exists ?? false;\n\t}\n\n\t/**\n\t * Return the total storage size of a table in bytes.\n\t *\n\t * @param table - Table name\n\t * @param schema - Schema name (defaults to adapter schema or 'public')\n\t */\n\t/**\n\t * Return the total storage size of a table in bytes (includes indexes and TOAST).\n\t *\n\t * The table name is a SQL identifier — it is double-quoted, not parameterized,\n\t * because PostgreSQL does not allow parameterized table names in FROM clauses.\n\t *\n\t * @param table - Table name\n\t * @param schema - Schema name (defaults to adapter schema or 'public')\n\t */\n\tasync storageSize(table: string, schema?: string): Promise<number> {\n\t\tconst executor = this.requireConnection();\n\t\tconst schemaName = schema ?? this.schemaName ?? 'public';\n\t\t// Build a double-quoted, schema-qualified identifier string.\n\t\t// Double any embedded double-quotes to prevent injection.\n\t\tconst qualified = `\"${schemaName.replace(/\"/g, '\"\"')}\".\"${table.replace(/\"/g, '\"\"')}\"`;\n\t\tconst result = await executor.query<{ size: string }>(\n\t\t\t`SELECT pg_total_relation_size($1::regclass)::bigint AS size`,\n\t\t\t[qualified],\n\t\t);\n\t\treturn Number(result.rows[0]?.size ?? 0);\n\t}\n\n\t/**\n\t * Generate SQL for TRUNCATE TABLE.\n\t * Implements TableDDLGeneratorAdapter.generateTruncate.\n\t */\n\tgenerateTruncate(\n\t\ttable: string,\n\t\tschema?: string,\n\t\toptions?: TruncateOptions,\n\t): string {\n\t\treturn generateTruncateSQL(table, schema ?? this.schemaName, options);\n\t}\n\n\t/**\n\t * Generate SQL for VACUUM.\n\t * Implements TableDDLGeneratorAdapter.generateVacuum.\n\t */\n\tgenerateVacuum(\n\t\ttable: string,\n\t\tschema?: string,\n\t\toptions?: VacuumOptions,\n\t): string {\n\t\treturn generateVacuumSQL(table, schema ?? this.schemaName, options);\n\t}\n\n\t/**\n\t * Generate SQL for ALTER TABLE ... ALTER COLUMN.\n\t * Implements TableDDLGeneratorAdapter.generateAlterColumn.\n\t */\n\tgenerateAlterColumn(\n\t\ttable: string,\n\t\tcolumn: string,\n\t\toptions: AlterColumnOptions,\n\t\tschema?: string,\n\t): string {\n\t\treturn generateAlterColumnSQL(\n\t\t\ttable,\n\t\t\tcolumn,\n\t\t\toptions,\n\t\t\tschema ?? this.schemaName,\n\t\t);\n\t}\n\n\t/**\n\t * Generate SQL for CREATE INDEX.\n\t * Implements TableDDLGeneratorAdapter.generateCreateIndex.\n\t */\n\tgenerateCreateIndex(\n\t\ttable: string,\n\t\toptions: CreateIndexOptions,\n\t\tschema?: string,\n\t): string {\n\t\treturn generateCreateIndexSQL(table, options, schema ?? this.schemaName);\n\t}\n\n\t/**\n\t * Generate SQL for DROP INDEX.\n\t * Implements TableDDLGeneratorAdapter.generateDropIndex.\n\t */\n\tgenerateDropIndex(name: string, options?: DropIndexOptions): string {\n\t\treturn generateDropIndexSQL(name, options);\n\t}\n\n\t// =========================================================================\n\t// Validation\n\t// =========================================================================\n\n\t/**\n\t * Validate an identifier (table name, column name, schema name).\n\t */\n\tvalidateIdentifier(value: string, type: string): void {\n\t\t// Cast to expected type union\n\t\tconst identifierType = type as 'table' | 'column' | 'schema' | 'alias';\n\t\tvalidateIdentifier(value, identifierType);\n\t}\n}\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\n/**\n * Create a PgsqlAdapter from a pg Pool instance.\n *\n * @param pool - pg Pool instance\n * @param options - Optional configuration\n * @returns A new PgsqlAdapter instance\n *\n * @example\n * ```typescript\n * import { Pool } from 'pg';\n * import { createPgsqlAdapter } from '@dbsp/adapter-pgsql';\n *\n * const pool = new Pool({ connectionString: process.env.DATABASE_URL });\n * const adapter = createPgsqlAdapter(pool);\n *\n * // With naming convention\n * const adapter = createPgsqlAdapter(pool, { dbCasing: 'snake_case' });\n * ```\n */\nexport function createPgsqlAdapter<DB = unknown>(\n\tpool: Pool,\n\toptions?: PgsqlAdapterOptions,\n): PgsqlAdapter<DB> {\n\treturn new PgsqlAdapter<DB>(pool, options);\n}\n\n/**\n * Creates a compile-only PgsqlAdapter for SQL generation without a database connection.\n *\n * All compilation methods (compile, compileInsert, etc.), createDump(), and generateDDL()\n * work normally. Execution methods (execute, stream, transaction, etc.) throw an error.\n *\n * @example\n * ```typescript\n * import { createPgsqlCompileOnlyAdapter } from '@dbsp/adapter-pgsql';\n * import { createOrm } from '@dbsp/core';\n *\n * const adapter = createPgsqlCompileOnlyAdapter();\n * const orm = createOrm({ model, adapter });\n * const dump = await orm.select('users').dump();\n * console.log(dump.sql);\n * ```\n */\nexport function createPgsqlCompileOnlyAdapter<DB = unknown>(\n\toptions?: PgsqlAdapterOptions,\n): CompileOnlyAdapter {\n\t// The `unknown` intermediate cast is required because TypeScript treats\n\t// `?: never` properties as non-overlapping with the concrete methods on\n\t// PgsqlAdapter<DB>. CompileOnlyAdapter uses `?: never` to exclude execution\n\t// methods at compile time; at runtime those methods throw ExecutionError\n\t// when no Pool is provided. The cast is intentional and safe.\n\treturn new PgsqlAdapter<DB>(\n\t\tundefined,\n\t\toptions,\n\t) as unknown as CompileOnlyAdapter;\n}\n","/**\n * Subquery-include compilation: compileSubqueryInclude + M:N variant.\n * Extracted from PgsqlAdapter.compileSubqueryInclude() and\n * PgsqlAdapter.compileSubqueryIncludeManyToMany().\n *\n * @internal\n */\n\nimport type {\n\tCompiledQuery,\n\tCompileOptions,\n\tSubqueryIncludeInfo,\n} from '@dbsp/types';\nimport type { Node } from '@pgsql/types';\nimport type { AdapterCompilerDeps } from './adapter-compiler-deps.js';\nimport { innerJoin, rangeVar } from './ast-helpers.js';\nimport { deparseQuoted } from './deparse.js';\nimport { createCompilerState } from './handlers/index.js';\n\n// ============================================================================\n// compileSubqueryInclude\n// ============================================================================\n\n/**\n * Compile a subquery include query for given parent IDs (DX-033).\n * Generates: SELECT * FROM targetTable WHERE foreignKey IN ($1, $2, ...)\n * Extracted body of PgsqlAdapter.compileSubqueryInclude().\n */\nexport function compileSubqueryInclude(\n\tinfo: SubqueryIncludeInfo,\n\tparentIds: readonly unknown[],\n\t_options: CompileOptions | undefined,\n\tdeps: AdapterCompilerDeps,\n): CompiledQuery {\n\t// schemaName precedence (options > adapter ctor) is resolved in PgsqlAdapter.buildCompileDeps; deps.schemaName is authoritative here\n\tconst schemaName = deps.schemaName;\n\tconst state = createCompilerState();\n\n\t// Handle empty parent IDs - return query that returns no results\n\tif (parentIds.length === 0) {\n\t\tconst tableName = schemaName\n\t\t\t? `\"${deps.naming.toDatabase(schemaName)}\".\"${deps.naming.toDatabase(info.targetTable)}\"`\n\t\t\t: `\"${deps.naming.toDatabase(info.targetTable)}\"`;\n\n\t\treturn {\n\t\t\tsql: `SELECT * FROM ${tableName} WHERE FALSE`,\n\t\t\tparameters: [],\n\t\t};\n\t}\n\n\t// Determine FK column(s)\n\tconst fkColumns = Array.isArray(info.foreignKey)\n\t\t? info.foreignKey\n\t\t: [info.foreignKey];\n\n\t// For M:N relations with junction table\n\tif (info.through && info.throughSourceKey && info.throughTargetKey) {\n\t\treturn compileSubqueryIncludeManyToMany(\n\t\t\tinfo,\n\t\t\tparentIds,\n\t\t\tschemaName,\n\t\t\tstate,\n\t\t\tdeps,\n\t\t);\n\t}\n\n\t// Build SELECT target list\n\tconst targetList = [\n\t\t{ ResTarget: { val: { ColumnRef: { fields: [{ A_Star: {} }] } } } },\n\t];\n\n\t// Build FROM clause\n\tconst fromClause = [\n\t\t{\n\t\t\tRangeVar: {\n\t\t\t\trelname: deps.naming.toDatabase(info.targetTable),\n\t\t\t\tinh: true,\n\t\t\t\trelpersistence: 'p',\n\t\t\t\t...(schemaName && {\n\t\t\t\t\tschemaname: deps.naming.toDatabase(schemaName),\n\t\t\t\t}),\n\t\t\t},\n\t\t},\n\t];\n\n\t// Build WHERE clause: foreignKey IN ($1, $2, ...)\n\tlet whereClause: Node;\n\n\tif (fkColumns.length === 1) {\n\t\t// Single column FK: column IN ($1, $2, ...)\n\t\tconst paramRefs = parentIds.map((id) => {\n\t\t\tstate.parameters.push(id);\n\t\t\tstate.paramIndex++;\n\t\t\treturn { ParamRef: { number: state.paramIndex } };\n\t\t});\n\n\t\twhereClause = {\n\t\t\tA_Expr: {\n\t\t\t\tkind: 'AEXPR_IN',\n\t\t\t\tname: [{ String: { sval: '=' } }],\n\t\t\t\tlexpr: {\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: deps.naming.toDatabase(fkColumns[0]!) } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\trexpr: { List: { items: paramRefs } },\n\t\t\t},\n\t\t};\n\t} else {\n\t\t// Composite FK: (col1, col2) IN (($1, $2), ($3, $4), ...)\n\t\t// For simplicity, use OR of ANDs\n\t\tconst conditions = parentIds.map((id) => {\n\t\t\tconst idValues = id as unknown[];\n\t\t\tconst colConditions = fkColumns.map((col, idx) => {\n\t\t\t\tstate.parameters.push(idValues[idx]);\n\t\t\t\tstate.paramIndex++;\n\t\t\t\treturn {\n\t\t\t\t\tA_Expr: {\n\t\t\t\t\t\tkind: 'AEXPR_OP',\n\t\t\t\t\t\tname: [{ String: { sval: '=' } }],\n\t\t\t\t\t\tlexpr: {\n\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\tfields: [{ String: { sval: deps.naming.toDatabase(col) } }],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\trexpr: { ParamRef: { number: state.paramIndex } },\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t});\n\n\t\t\treturn colConditions.length === 1\n\t\t\t\t? colConditions[0]\n\t\t\t\t: { BoolExpr: { boolop: 'AND_EXPR', args: colConditions } };\n\t\t});\n\n\t\twhereClause =\n\t\t\tconditions.length === 1\n\t\t\t\t? (conditions[0] as Node)\n\t\t\t\t: { BoolExpr: { boolop: 'OR_EXPR', args: conditions as Node[] } };\n\t}\n\n\t// Build SELECT statement\n\tconst selectAst: Node = {\n\t\tSelectStmt: {\n\t\t\ttargetList,\n\t\t\tfromClause,\n\t\t\twhereClause,\n\t\t},\n\t};\n\n\tconst sql = deparseQuoted(selectAst);\n\n\treturn {\n\t\tsql,\n\t\tparameters: state.parameters,\n\t};\n}\n\n// ============================================================================\n// compileSubqueryIncludeManyToMany (internal)\n// ============================================================================\n\n/**\n * Compile M:N subquery include with junction table.\n * Extracted body of PgsqlAdapter.compileSubqueryIncludeManyToMany().\n */\nfunction compileSubqueryIncludeManyToMany(\n\tinfo: SubqueryIncludeInfo,\n\tparentIds: readonly unknown[],\n\tschemaName: string | undefined,\n\tstate: ReturnType<typeof createCompilerState>,\n\tdeps: AdapterCompilerDeps,\n): CompiledQuery {\n\t// M:N: SELECT t.* FROM target t\n\t// JOIN junction j ON t.pk = j.throughTargetKey\n\t// WHERE j.throughSourceKey IN ($1, $2, ...)\n\n\tconst targetAlias = 't';\n\tconst junctionAlias = 'j';\n\n\tconst throughTable = info.through!;\n\tconst throughSourceKey = info.throughSourceKey!;\n\tconst throughTargetKey = info.throughTargetKey!;\n\n\t// Determine target PK (usually 'id', but could be from sourceKey)\n\tconst targetPk = Array.isArray(info.sourceKey)\n\t\t? info.sourceKey[0]!\n\t\t: info.sourceKey;\n\n\t// Build param refs for parent IDs\n\tconst paramRefs = parentIds.map((id) => {\n\t\tstate.parameters.push(id);\n\t\tstate.paramIndex++;\n\t\treturn { ParamRef: { number: state.paramIndex } };\n\t});\n\n\t// Build WHERE clause: j.throughSourceKey IN (...)\n\tconst whereClause: Node = {\n\t\tA_Expr: {\n\t\t\tkind: 'AEXPR_IN',\n\t\t\tname: [{ String: { sval: '=' } }],\n\t\t\tlexpr: {\n\t\t\t\tColumnRef: {\n\t\t\t\t\tfields: [\n\t\t\t\t\t\t{ String: { sval: junctionAlias } },\n\t\t\t\t\t\t{ String: { sval: deps.naming.toDatabase(throughSourceKey) } },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\trexpr: { List: { items: paramRefs } },\n\t\t},\n\t};\n\n\t// Build JOIN condition: t.pk = j.throughTargetKey\n\tconst joinQuals: Node = {\n\t\tA_Expr: {\n\t\t\tkind: 'AEXPR_OP',\n\t\t\tname: [{ String: { sval: '=' } }],\n\t\t\tlexpr: {\n\t\t\t\tColumnRef: {\n\t\t\t\t\tfields: [\n\t\t\t\t\t\t{ String: { sval: targetAlias } },\n\t\t\t\t\t\t{ String: { sval: deps.naming.toDatabase(targetPk) } },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\trexpr: {\n\t\t\t\tColumnRef: {\n\t\t\t\t\tfields: [\n\t\t\t\t\t\t{ String: { sval: junctionAlias } },\n\t\t\t\t\t\t{ String: { sval: deps.naming.toDatabase(throughTargetKey) } },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t};\n\n\t// Build FROM clause with JOIN using helper functions\n\tconst targetRangeVar = rangeVar(\n\t\tinfo.targetTable,\n\t\ttargetAlias,\n\t\tschemaName,\n\t\tdeps.naming,\n\t);\n\n\tconst junctionRangeVar = rangeVar(\n\t\tthroughTable,\n\t\tjunctionAlias,\n\t\tschemaName,\n\t\tdeps.naming,\n\t);\n\n\t// Use innerJoin helper for proper typing\n\tconst joinNode = innerJoin(targetRangeVar, junctionRangeVar, joinQuals);\n\tconst fromClause = [joinNode];\n\n\t// Build SELECT t.*\n\tconst targetList = [\n\t\t{\n\t\t\tResTarget: {\n\t\t\t\tval: {\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [{ String: { sval: targetAlias } }, { A_Star: {} }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t];\n\n\tconst selectAst: Node = {\n\t\tSelectStmt: {\n\t\t\ttargetList,\n\t\t\tfromClause,\n\t\t\twhereClause,\n\t\t},\n\t};\n\n\tconst sql = deparseQuoted(selectAst);\n\n\treturn {\n\t\tsql,\n\t\tparameters: state.parameters,\n\t};\n}\n","/**\n * Mutation compilation: INSERT, UPDATE, DELETE, UPSERT.\n * Extracted from PgsqlAdapter.compileInsert/Update/Delete/Upsert/etc.\n *\n * @internal\n */\n\nimport { InvalidOperationError, isSqlRaw } from '@dbsp/core';\nimport type {\n\tBatchUpdateIntent,\n\tCompiledQuery,\n\tCompileOptions,\n\tDeleteIntent,\n\tInsertFromIntent,\n\tInsertIntent,\n\tUpdateIntent,\n\tUpsertFromIntent,\n\tUpsertIntent,\n\tWhereIntent,\n} from '@dbsp/types';\nimport type { AdapterCompilerDeps } from './adapter-compiler-deps.js';\nimport {\n\tbuildSubqueryFromIntent,\n\tcompileWhereIntent,\n\ttype WhereCompilerCtx,\n} from './compile-where.js';\nimport {\n\ttransposeToColumnArrays,\n\tvalidateBatchCardinality,\n} from './compiler-utils.js';\nimport { deparseQuoted } from './deparse.js';\nimport {\n\ttype CompilerContext,\n\tcreateCompilerState,\n\ttype Decision,\n} from './handlers/index.js';\nimport {\n\ttype BatchUpdateConfig,\n\tcompileDelete as compileDeleteMutation,\n\tcompileInsertFrom as compileInsertFromMutation,\n\tcompileInsert as compileInsertMutation,\n\tcompileUnnestInsert as compileUnnestInsertMutation,\n\tcompileUnnestUpdate as compileUnnestUpdateMutation,\n\tcompileUnnestUpsert as compileUnnestUpsertMutation,\n\tcompileUpdate as compileUpdateMutation,\n\tcompileUpsertFrom as compileUpsertFromMutation,\n\tcompileUpsert as compileUpsertMutation,\n\ttype DeleteConfig,\n\ttype InsertConfig,\n\ttype InsertFromConfig,\n\ttype UpdateConfig,\n\ttype UpsertConfig,\n\ttype UpsertFromConfig,\n} from './mutations/index.js';\n\n// ============================================================================\n// Internal helpers\n// ============================================================================\n\n/**\n * Bridge a WhereIntent into a Decision for mutation config.\n * The WHERE dispatcher's `normalizeToDecision` handles the actual\n * `kind`/`field` → `type`/`column`/`operator` conversion at runtime.\n */\nfunction whereIntentAsDecision(where: WhereIntent): Decision {\n\treturn where as never as Decision;\n}\n\n/**\n * Resolve relation metadata for an exists/notExists WHERE condition.\n *\n * `notExists('symbol')` carries `relation: 'symbol'` (the logical relation name).\n * The mutation path bypasses the planner, so `normalizeToDecision` sets\n * `targetTable: relation` — using 'symbol' as the table name instead of 'symbols'.\n *\n * This helper looks up `sourceTable.relation` in ModelIR and returns:\n * - `targetTable`: real DB table name (e.g. 'symbols' for relation 'symbol')\n * - `sourceColumn`: FK column on the root table for `belongsTo` (e.g. 'symbol_id')\n * - `targetColumn`: PK on the target table (always 'id' for standard schemas)\n *\n * Falls back gracefully when ModelIR is unavailable or relation not found.\n */\nfunction resolveExistsRelation(\n\tsourceTable: string,\n\trelation: string,\n\tmodel: import('@dbsp/types').ModelIR | undefined,\n): { targetTable: string; sourceColumn?: string; targetColumn?: string } {\n\tif (!model) return { targetTable: relation };\n\tconst rel = model.getRelation(`${sourceTable}.${relation}`);\n\tif (!rel) return { targetTable: relation };\n\tconst targetTable = rel.target;\n\t// For belongsTo: FK is on the source table (e.g. embeddings.symbol_id → symbols.id)\n\tif (rel.type === 'belongsTo') {\n\t\tconst fk =\n\t\t\ttypeof rel.foreignKey === 'string' ? rel.foreignKey : rel.foreignKey?.[0];\n\t\treturn {\n\t\t\ttargetTable,\n\t\t\t...(fk !== undefined && { sourceColumn: fk }),\n\t\t\ttargetColumn: 'id',\n\t\t};\n\t}\n\t// For hasMany/hasOne: FK is on the target table (e.g. symbols.file_id → files.id)\n\treturn { targetTable };\n}\n\n/**\n * Enrich an exists/notExists WhereIntent with the resolved `targetTable`,\n * `sourceColumn`, and `targetColumn` so that `buildExistsSubquery` correlates\n * the subquery using the correct FK columns instead of convention-based defaults.\n */\nfunction resolveExistsIntent(\n\twhere: WhereIntent,\n\tsourceTable: string,\n\tdeps: AdapterCompilerDeps,\n): WhereIntent {\n\tconst w = where as unknown as Record<string, unknown>;\n\tconst kind = w.kind as string | undefined;\n\n\t// Recursively walk and/or/not branches so nested exists/notExists are enriched\n\tif (kind === 'and' || kind === 'or') {\n\t\tconst conditions = w.conditions as WhereIntent[] | undefined;\n\t\tif (!conditions) return where;\n\t\tconst enriched = conditions.map((c) =>\n\t\t\tresolveExistsIntent(c, sourceTable, deps),\n\t\t);\n\t\tconst changed = enriched.some((c, i) => c !== conditions[i]);\n\t\treturn changed\n\t\t\t? ({ ...w, conditions: enriched } as unknown as WhereIntent)\n\t\t\t: where;\n\t}\n\tif (kind === 'not') {\n\t\tconst condition = w.condition as WhereIntent | undefined;\n\t\tif (!condition) return where;\n\t\tconst enriched = resolveExistsIntent(condition, sourceTable, deps);\n\t\treturn enriched !== condition\n\t\t\t? ({ ...w, condition: enriched } as unknown as WhereIntent)\n\t\t\t: where;\n\t}\n\n\t// Only enrich exists/notExists at this level\n\tif (kind !== 'exists' && kind !== 'notExists') return where;\n\tconst relation = w.relation as string;\n\tconst resolved = resolveExistsRelation(sourceTable, relation, deps.model);\n\t// Only enrich if we resolved to a different name (avoid mutation when model absent)\n\tif (resolved.targetTable === relation && !resolved.sourceColumn) return where;\n\treturn {\n\t\t...w,\n\t\ttargetTable: resolved.targetTable,\n\t\t...(resolved.sourceColumn !== undefined && {\n\t\t\tsourceColumn: resolved.sourceColumn,\n\t\t}),\n\t\t...(resolved.targetColumn !== undefined && {\n\t\t\ttargetColumn: resolved.targetColumn,\n\t\t}),\n\t} as unknown as WhereIntent;\n}\n\n/**\n * Build a column-type map for a table, covering all typed columns so that\n * `inferPgArrayType` can produce schema-driven array casts (e.g. int4[], bool[]).\n * Prefers `originalDbType` when set (preserves precision info from introspection).\n * Returns undefined if no columns found (or model unavailable).\n */\nfunction getColumnTypes(\n\ttableName: string,\n\tcolumns: string[],\n\tdeps: AdapterCompilerDeps,\n): Record<string, string> | undefined {\n\tif (!deps.model) return undefined;\n\tconst table = deps.model.getTable(tableName);\n\tif (!table) return undefined;\n\tlet result: Record<string, string> | undefined;\n\tfor (const col of columns) {\n\t\tconst columnIR = table.columns.find((c) => c.name === col);\n\t\tif (columnIR) {\n\t\t\tresult ??= {};\n\t\t\t// Prefer originalDbType (preserves introspection precision) over ColumnType\n\t\t\tresult[col] = columnIR.originalDbType ?? columnIR.type;\n\t\t}\n\t}\n\treturn result;\n}\n\n// ============================================================================\n// compileInsert\n// ============================================================================\n\n/**\n * Compile an insert intent to executable SQL.\n *\n * Strategy switch (per CompileOptions):\n * - rows <= batchThreshold (default 50): VALUES ($1,$2),($3,$4),...\n * - rows > batchThreshold OR batchThreshold === 0: SELECT unnest($1::type[]),...\n *\n * Extracted body of PgsqlAdapter.compileInsert().\n */\nexport function compileInsert(\n\tintent: InsertIntent,\n\toptions: CompileOptions | undefined,\n\tdeps: AdapterCompilerDeps,\n): CompiledQuery {\n\t// schemaName precedence (options > adapter ctor) is resolved in PgsqlAdapter.buildCompileDeps; deps.schemaName is authoritative here\n\tconst schemaName = deps.schemaName;\n\n\tconst ctx: CompilerContext = {\n\t\tnaming: deps.naming,\n\t\trootTable: intent.table,\n\t\t...(schemaName !== undefined && { schema: schemaName }),\n\t\tmaxRecursiveDepth: 100,\n\t};\n\tconst state = createCompilerState();\n\n\tconst firstRow = intent.values?.[0] ?? {};\n\tconst columns = Object.keys(firstRow);\n\tconst values = (intent.values ?? []).map((row) =>\n\t\tcolumns.map((col) => row[col]),\n\t);\n\n\tconst columnTypes = getColumnTypes(intent.table, columns, deps);\n\n\tconst config: InsertConfig = {\n\t\ttable: intent.table,\n\t\tcolumns,\n\t\tvalues,\n\t\t...(intent.returning && { returning: [...intent.returning] }),\n\t\t...(columnTypes && { columnTypes }),\n\t};\n\n\t// maxBatchSize guard (INV-07)\n\tconst maxBatchSize = options?.maxBatchSize;\n\tif (maxBatchSize !== undefined && values.length > maxBatchSize) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'insert',\n\t\t\t`Batch size ${values.length} exceeds maxBatchSize ${maxBatchSize}`,\n\t\t);\n\t}\n\n\t// Strategy switch: unnest for large batches, VALUES for small (INV-03)\n\tconst batchThreshold = options?.batchThreshold ?? 50;\n\tconst useUnnest =\n\t\tvalues.length > 0 &&\n\t\t(batchThreshold === 0 || values.length > batchThreshold);\n\n\tconst ast = useUnnest\n\t\t? compileUnnestInsertMutation(config, ctx, state)\n\t\t: compileInsertMutation(config, ctx, state);\n\tconst sql = deparseQuoted(ast);\n\n\treturn {\n\t\tsql,\n\t\tparameters: state.parameters,\n\t};\n}\n\n// ============================================================================\n// compileInsertFrom\n// ============================================================================\n\n/**\n * Compile an insert-from intent to executable SQL (NQL-ALIGN).\n * INSERT INTO target (cols) SELECT cols FROM source WHERE ... LIMIT ... RETURNING ...\n * Extracted body of PgsqlAdapter.compileInsertFrom().\n */\nexport function compileInsertFrom(\n\tintent: InsertFromIntent,\n\t_options: CompileOptions | undefined,\n\tdeps: AdapterCompilerDeps,\n): CompiledQuery {\n\t// schemaName precedence (options > adapter ctor) is resolved in PgsqlAdapter.buildCompileDeps; deps.schemaName is authoritative here\n\tconst schemaName = deps.schemaName;\n\n\tconst ctx: CompilerContext = {\n\t\tnaming: deps.naming,\n\t\trootTable: intent.source,\n\t\t...(schemaName !== undefined && { schema: schemaName }),\n\t\tmaxRecursiveDepth: 100,\n\t};\n\tconst state = createCompilerState();\n\n\tconst config: InsertFromConfig = {\n\t\ttargetTable: intent.table,\n\t\tsourceTable: intent.source,\n\t\t...(intent.columns && { columns: [...intent.columns] }),\n\t\t...(intent.where && { where: [whereIntentAsDecision(intent.where)] }),\n\t\t...(intent.limit !== undefined && { limit: intent.limit }),\n\t\t...(intent.returning && { returning: [...intent.returning] }),\n\t};\n\n\tconst ast = compileInsertFromMutation(config, ctx, state);\n\tconst sql = deparseQuoted(ast);\n\n\treturn {\n\t\tsql,\n\t\tparameters: state.parameters,\n\t};\n}\n\n// ============================================================================\n// compileUpdate\n// ============================================================================\n\n/**\n * Compile an update intent to executable SQL.\n * Extracted body of PgsqlAdapter.compileUpdate().\n */\nexport function compileUpdate(\n\tintent: UpdateIntent,\n\t_options: CompileOptions | undefined,\n\tdeps: AdapterCompilerDeps,\n): CompiledQuery {\n\t// schemaName precedence (options > adapter ctor) is resolved in PgsqlAdapter.buildCompileDeps; deps.schemaName is authoritative here\n\tconst schemaName = deps.schemaName;\n\n\tconst ctx: CompilerContext = {\n\t\tnaming: deps.naming,\n\t\trootTable: intent.table,\n\t\t...(schemaName !== undefined && { schema: schemaName }),\n\t\tmaxRecursiveDepth: 100,\n\t};\n\tconst state = createCompilerState();\n\n\tconst setColumns = Object.keys(intent.set ?? {});\n\tconst columnTypes = getColumnTypes(intent.table, setColumns, deps);\n\n\tconst config: UpdateConfig = {\n\t\ttable: intent.table,\n\t\tset: Object.entries(intent.set ?? {}).map(([column, value]) => ({\n\t\t\tcolumn,\n\t\t\tvalue,\n\t\t})),\n\t\t...(intent.where && { where: [whereIntentAsDecision(intent.where)] }),\n\t\t...(intent.returning && { returning: [...intent.returning] }),\n\t\t...(columnTypes && { columnTypes }),\n\t};\n\n\tconst ast = compileUpdateMutation(config, ctx, state);\n\tconst sql = deparseQuoted(ast);\n\n\treturn {\n\t\tsql,\n\t\tparameters: state.parameters,\n\t};\n}\n\n// ============================================================================\n// compileBatchUpdate\n// ============================================================================\n\n/**\n * Compile a batch update intent to executable SQL using unnest FROM strategy (BATCH-001).\n *\n * Generates:\n * UPDATE \"table\" SET \"update_col\" = t.\"update_col\" [, \"scalar_col\" = $N]\n * FROM unnest(CAST($1 AS type[]), CAST($2 AS type[])) AS t(\"match_col\", \"update_col\")\n * WHERE \"table\".\"match_col\" = t.\"match_col\"\n * [RETURNING ...]\n *\n * Extracted body of PgsqlAdapter.compileBatchUpdate().\n */\nexport function compileBatchUpdate(\n\tintent: BatchUpdateIntent,\n\t_options: CompileOptions | undefined,\n\tdeps: AdapterCompilerDeps,\n): CompiledQuery {\n\t// schemaName precedence (options > adapter ctor) is resolved in PgsqlAdapter.buildCompileDeps; deps.schemaName is authoritative here\n\tconst schemaName = deps.schemaName;\n\n\tconst ctx: CompilerContext = {\n\t\tnaming: deps.naming,\n\t\trootTable: intent.table,\n\t\t...(schemaName !== undefined && { schema: schemaName }),\n\t\tmaxRecursiveDepth: 100,\n\t};\n\tconst state = createCompilerState();\n\n\tif (intent.updates.length === 0) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'update',\n\t\t\t'batchSet requires at least one row',\n\t\t);\n\t}\n\n\t// Extract all columns from the first row\n\tconst allColumns = Object.keys(intent.updates[0]!);\n\tconst matchColumns = [...intent.matchColumns];\n\n\t// Validate that all match columns appear in the data\n\tfor (const mc of matchColumns) {\n\t\tif (!allColumns.includes(mc)) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'update',\n\t\t\t\t`Match column \"${mc}\" not found in update data. Each row must include the match column(s).`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// Build row-major values matrix and validate cardinality\n\tconst values = intent.updates.map((row) => allColumns.map((col) => row[col]));\n\tvalidateBatchCardinality(allColumns, values);\n\n\t// Transpose to column-major arrays\n\tconst columnArrays = transposeToColumnArrays(allColumns, values);\n\n\t// Get column types for type inference\n\tconst columnTypes = getColumnTypes(intent.table, allColumns, deps);\n\n\t// Build scalar SET entries from scalarSet\n\tconst scalarSet = intent.scalarSet\n\t\t? Object.entries(intent.scalarSet).map(([column, value]) => ({\n\t\t\t\tcolumn,\n\t\t\t\tvalue,\n\t\t\t}))\n\t\t: undefined;\n\n\t// Compile optional WHERE guard (e.g., AND EXISTS(...))\n\t// The guard uses the shared `state` so $N numbering continues from unnest params.\n\tlet whereGuard: import('@pgsql/types').Node | undefined;\n\tif (intent.where) {\n\t\tconst whereCtx: WhereCompilerCtx = {\n\t\t\trootTable: intent.table,\n\t\t\taliases: new Map<string, string>(),\n\t\t\tparamState: state,\n\t\t\tnaming: deps.naming,\n\t\t\t...(schemaName !== undefined && { schemaName }),\n\t\t\t...(deps.model !== undefined && { model: deps.model }),\n\t\t\tcompileSubquery: (sqIntent, paramOffset) =>\n\t\t\t\tbuildSubqueryFromIntent(sqIntent, paramOffset, deps.naming, schemaName),\n\t\t};\n\t\twhereGuard = compileWhereIntent(intent.where, whereCtx);\n\t}\n\n\tconst config: BatchUpdateConfig = {\n\t\ttable: intent.table,\n\t\tmatchColumns,\n\t\tallColumns,\n\t\tcolumnArrays,\n\t\t...(scalarSet && { scalarSet }),\n\t\t...(intent.returning && { returning: [...intent.returning] }),\n\t\t...(columnTypes && { columnTypes }),\n\t\t...(whereGuard !== undefined && { whereGuard }),\n\t};\n\n\tconst ast = compileUnnestUpdateMutation(config, ctx, state);\n\tconst sql = deparseQuoted(ast);\n\n\treturn {\n\t\tsql,\n\t\tparameters: state.parameters,\n\t};\n}\n\n// ============================================================================\n// compileDelete\n// ============================================================================\n\n/**\n * Compile a delete intent to executable SQL.\n * Extracted body of PgsqlAdapter.compileDelete().\n */\nexport function compileDelete(\n\tintent: DeleteIntent,\n\toptions: CompileOptions | undefined,\n\tdeps: AdapterCompilerDeps,\n): CompiledQuery {\n\t// schemaName precedence (options > adapter ctor) is resolved in PgsqlAdapter.buildCompileDeps; deps.schemaName is authoritative here\n\tconst schemaName = deps.schemaName;\n\n\tconst resolvedModel = options?.model ?? deps.model;\n\tconst ctx: CompilerContext = {\n\t\tnaming: deps.naming,\n\t\trootTable: intent.table,\n\t\t...(schemaName !== undefined && { schema: schemaName }),\n\t\tmaxRecursiveDepth: 100,\n\t\t...(resolvedModel !== undefined && { model: resolvedModel }),\n\t};\n\tconst state = createCompilerState();\n\n\t// Resolve exists/notExists relation name → real table name before compiling.\n\t// The mutation path bypasses the planner, so we must resolve targetTable here.\n\tconst resolvedWhere = intent.where\n\t\t? resolveExistsIntent(intent.where, intent.table, deps)\n\t\t: undefined;\n\n\tconst config: DeleteConfig = {\n\t\ttable: intent.table,\n\t\t...(resolvedWhere && { where: [whereIntentAsDecision(resolvedWhere)] }),\n\t\t...(intent.returning && { returning: [...intent.returning] }),\n\t};\n\n\tconst ast = compileDeleteMutation(config, ctx, state);\n\tconst sql = deparseQuoted(ast);\n\n\treturn {\n\t\tsql,\n\t\tparameters: state.parameters,\n\t};\n}\n\n// ============================================================================\n// compileUpsert\n// ============================================================================\n\n/**\n * Compile an upsert intent to executable SQL (DX-026).\n * Extracted body of PgsqlAdapter.compileUpsert().\n */\nexport function compileUpsert(\n\tintent: UpsertIntent,\n\toptions: CompileOptions | undefined,\n\tdeps: AdapterCompilerDeps,\n): CompiledQuery {\n\t// schemaName precedence (options > adapter ctor) is resolved in PgsqlAdapter.buildCompileDeps; deps.schemaName is authoritative here\n\tconst schemaName = deps.schemaName;\n\n\tconst ctx: CompilerContext = {\n\t\tnaming: deps.naming,\n\t\trootTable: intent.table,\n\t\t...(schemaName !== undefined && { schema: schemaName }),\n\t\tmaxRecursiveDepth: 100,\n\t};\n\tconst state = createCompilerState();\n\n\tconst firstRow = intent.values?.[0] ?? {};\n\n\t// Separate raw SQL expressions from scalar set values.\n\t// Raw expressions are emitted verbatim in ON CONFLICT DO UPDATE SET —\n\t// they must NOT be merged into INSERT VALUES rows (they are not values).\n\t// Scalar set values are merged so EXCLUDED.column picks them up.\n\tconst rawExprs: Record<string, string> = {};\n\tconst scalarSet: Record<string, unknown> = {};\n\tif (intent.action.type === 'doUpdate' && intent.action.set) {\n\t\tfor (const [key, val] of Object.entries(intent.action.set)) {\n\t\t\tif (isSqlRaw(val)) {\n\t\t\t\trawExprs[key] = val.sql;\n\t\t\t} else {\n\t\t\t\tscalarSet[key] = val;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Merge only scalar set values into INSERT VALUES rows so EXCLUDED.column\n\t// references resolve correctly.\n\tconst hasScalarSet = Object.keys(scalarSet).length > 0;\n\tconst mergedFirstRow = hasScalarSet\n\t\t? { ...firstRow, ...scalarSet }\n\t\t: firstRow;\n\n\tconst columns = Object.keys(mergedFirstRow);\n\tconst values = (intent.values ?? []).map((row) => {\n\t\tconst mergedRow = hasScalarSet ? { ...row, ...scalarSet } : row;\n\t\treturn columns.map((col) => mergedRow[col]);\n\t});\n\n\t// Build conflict target\n\tconst conflictTarget: {\n\t\tcolumns?: string[];\n\t\tconstraint?: string;\n\t} = {};\n\n\tif ('columns' in intent.onConflict) {\n\t\tconflictTarget.columns = [...intent.onConflict.columns];\n\t} else if ('constraint' in intent.onConflict) {\n\t\tconflictTarget.constraint = intent.onConflict.constraint;\n\t}\n\n\t// Build conflict action\n\tconst conflictAction: 'nothing' | 'update' =\n\t\tintent.action.type === 'doNothing' ? 'nothing' : 'update';\n\n\t// Determine update columns.\n\t// All columns in intent.action.set are update columns (both scalar and raw).\n\t// Scalar ones use EXCLUDED.column, raw ones use the parsed SQL expression.\n\tlet updateColumns: string[] | undefined;\n\tif (intent.action.type === 'doUpdate') {\n\t\tif (intent.action.set) {\n\t\t\t// All keys in set become update columns (raw + scalar combined)\n\t\t\tupdateColumns = Object.keys(intent.action.set);\n\t\t} else {\n\t\t\t// Default: update all non-conflict columns\n\t\t\tconst conflictCols =\n\t\t\t\t'columns' in intent.onConflict ? intent.onConflict.columns : [];\n\t\t\tupdateColumns = columns.filter((col) => !conflictCols.includes(col));\n\t\t}\n\t}\n\n\tconst columnTypes = getColumnTypes(intent.table, columns, deps);\n\tconst hasRawExprs = Object.keys(rawExprs).length > 0;\n\n\tconst config: UpsertConfig = {\n\t\ttable: intent.table,\n\t\tcolumns,\n\t\tvalues,\n\t\tconflictTarget,\n\t\tconflictAction,\n\t\t...(updateColumns && { updateColumns }),\n\t\t...(intent.returning && { returning: [...intent.returning] }),\n\t\t...(columnTypes && { columnTypes }),\n\t\t...(hasRawExprs && { updateExpressions: rawExprs }),\n\t};\n\n\t// maxBatchSize guard (INV-07)\n\tconst maxBatchSize = options?.maxBatchSize;\n\tif (maxBatchSize !== undefined && values.length > maxBatchSize) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'upsert',\n\t\t\t`Batch size ${values.length} exceeds maxBatchSize ${maxBatchSize}`,\n\t\t);\n\t}\n\n\t// Strategy switch: unnest for large batches, VALUES for small (INV-03)\n\tconst batchThreshold = options?.batchThreshold ?? 50;\n\tconst useUnnest =\n\t\tvalues.length > 0 &&\n\t\t(batchThreshold === 0 || values.length > batchThreshold);\n\n\tconst ast = useUnnest\n\t\t? compileUnnestUpsertMutation(config, ctx, state)\n\t\t: compileUpsertMutation(config, ctx, state);\n\tconst sql = deparseQuoted(ast);\n\n\treturn {\n\t\tsql,\n\t\tparameters: state.parameters,\n\t};\n}\n\n// ============================================================================\n// compileUpsertFrom\n// ============================================================================\n\n/**\n * Compile an upsert-from intent to executable SQL (NQL-BIND).\n * INSERT INTO target SELECT ... FROM source ON CONFLICT (cols) DO UPDATE SET ...\n * Extracted body of PgsqlAdapter.compileUpsertFrom().\n */\nexport function compileUpsertFrom(\n\tintent: UpsertFromIntent,\n\toptions: CompileOptions | undefined,\n\tdeps: AdapterCompilerDeps,\n): CompiledQuery {\n\t// schemaName precedence (options > adapter ctor) is resolved in PgsqlAdapter.buildCompileDeps; deps.schemaName is authoritative here\n\tconst schemaName = deps.schemaName;\n\n\tconst ctx: CompilerContext = {\n\t\tnaming: deps.naming,\n\t\trootTable: intent.source,\n\t\t...(schemaName !== undefined && { schema: schemaName }),\n\t\tmaxRecursiveDepth: 100,\n\t};\n\tconst state = createCompilerState();\n\n\t// Derive columns from model if not explicitly specified (needed for ON CONFLICT SET)\n\tlet columns: string[] | undefined;\n\tif (intent.columns) {\n\t\tcolumns = [...intent.columns];\n\t} else if (options?.model) {\n\t\tconst targetTable = options.model.getTable(intent.table);\n\t\tif (targetTable) {\n\t\t\tcolumns = targetTable.columns.map((c) => c.name);\n\t\t}\n\t}\n\n\tconst config: UpsertFromConfig = {\n\t\ttargetTable: intent.table,\n\t\tsourceTable: intent.source,\n\t\tconflictColumns: [...intent.conflictColumns],\n\t\t...(columns && { columns }),\n\t\t...(intent.where && { where: [whereIntentAsDecision(intent.where)] }),\n\t\t...(intent.limit !== undefined && { limit: intent.limit }),\n\t\t...(intent.returning && { returning: [...intent.returning] }),\n\t};\n\n\tconst ast = compileUpsertFromMutation(config, ctx, state);\n\tconst sql = deparseQuoted(ast);\n\n\treturn {\n\t\tsql,\n\t\tparameters: state.parameters,\n\t};\n}\n","/**\n * SELECT compilation: converts PlanReport to CompiledQuery.\n * Extracted from PgsqlAdapter.compile() and PgsqlAdapter.compileWithIncludes().\n *\n * @internal\n */\n\nimport type {\n\tCompiledQuery,\n\tCompileOptions,\n\tCompileResultWithIncludes,\n\tJoinIntent,\n\tPlanReport,\n\tSubqueryIncludeInfo,\n} from '@dbsp/types';\nimport type { Mutable } from '@dbsp/types/internal';\nimport type { Node } from '@pgsql/types';\nimport type { AdapterCompilerDeps } from './adapter-compiler-deps.js';\nimport { defaultFkDerivation } from './assert-field.js';\nimport { funcCall, rangeVar } from './ast-helpers.js';\nimport { compileWhereIntent, type WhereCompilerCtx } from './compile-where.js';\nimport {\n\ttype CompilerOptions,\n\tcompilePlan,\n\ttype PlanDecision,\n\ttype SimplifiedPlanReport,\n} from './compiler.js';\nimport { inferPgArrayType, stripArraySuffix } from './compiler-utils.js';\nimport { createCompilerState } from './handlers/types.js';\nimport { intentToDecisions } from './intent-to-decisions.js';\nimport { createTypeCastParamRef } from './param-ref.js';\nimport {\n\tconvertDottedFieldsToExists,\n\tderiveForeignKey,\n\textractAllIncludeDecisions,\n\textractExistsDecisions,\n\tsynthesizeMissingJoinDecisions,\n} from './plan-decision-extractor.js';\n\n// ============================================================================\n// Internal: legacy bridge\n// ============================================================================\n\n/**\n * Bridge core's PlanDecision[] (observability format) to adapter's PlanDecision[].\n * Used only in the legacy/test path where mock plans carry adapter-format decisions\n * inside a core PlanReport. At runtime the data is already in adapter format.\n */\n/**\n * Recursively strip exists/notExists decisions from a decision tree.\n * Handles top-level decisions and those nested inside whereAnd/whereOr/whereNot.\n * Returns null when the decision itself should be removed.\n * Containers (whereAnd/whereOr/whereNot) that become empty after stripping are also removed.\n */\nfunction stripExistsFromDecision(d: PlanDecision): PlanDecision | null {\n\tif (\n\t\td.type === 'where' &&\n\t\t(d.operator === 'exists' || d.operator === 'notExists')\n\t) {\n\t\treturn null;\n\t}\n\tif (\n\t\t(d.type === 'whereAnd' || d.type === 'whereOr' || d.type === 'whereNot') &&\n\t\td.conditions\n\t) {\n\t\tconst stripped = (d.conditions as PlanDecision[])\n\t\t\t.map(stripExistsFromDecision)\n\t\t\t.filter((c): c is PlanDecision => c !== null);\n\t\tif (stripped.length === 0) return null;\n\t\treturn { ...d, conditions: stripped };\n\t}\n\treturn d;\n}\n\nexport function bridgeLegacyDecisions(\n\tdecisions: readonly unknown[],\n): SimplifiedPlanReport['decisions'] {\n\treturn decisions as SimplifiedPlanReport['decisions'];\n}\n\n/**\n * Compile JoinIntent[] from a QueryIntent into PlanDecision[] of type 'join'.\n *\n * Two modes:\n * - Relation mode (no `on`): FK auto-resolved from model, like `include` but flat (no hydration).\n * - Table mode (`on` present): Explicit ON condition compiled via compileWhereIntent().\n *\n * The resulting decisions are appended to `allDecisions` before `compilePlan()`.\n */\n\n// ============================================================================\n// Batch Values RangeFunction builder (shared by JOIN and FROM cases)\n// ============================================================================\n\ntype BatchValuesRangeFnResult = {\n\trangeFunction: Node;\n\tparams: unknown[];\n};\n\n/**\n * Build a `unnest($1::type[], ...) AS alias(col1, col2 [, ord])` RangeFunction node\n * from a BatchValuesJoinPayload.\n *\n * The returned `params` array contains the column data arrays in order; they must\n * be spliced into CompilerState.parameters BEFORE other query params so that the\n * $N refs in the AST node match the right positions.\n *\n * @param bv - The batch values payload (columns, data, types, alias, ordinality).\n * @param startParamIndex - The 1-based index for the first ParamRef ($N).\n * Pass 1 when the batch params are first; pass current paramIndex+1 otherwise.\n */\nfunction buildBatchValuesRangeFn(\n\tbv: import('@dbsp/types').BatchValuesJoinPayload,\n\tstartParamIndex: number,\n\taliasOverride?: string,\n): BatchValuesRangeFnResult {\n\tconst params: unknown[] = [];\n\tlet paramIdx = startParamIndex - 1;\n\tconst effectiveAlias = aliasOverride ?? bv.alias;\n\n\tconst unnestArgs: Node[] = bv.columns.map((col, i) => {\n\t\tconst colArray: unknown[] = (bv.data[i] as unknown[]) ?? [];\n\t\tconst sampleValue = colArray.find((v) => v !== null && v !== undefined);\n\t\tconst colTypes: Record<string, string> = {};\n\t\tif (bv.types[i]) colTypes[col] = bv.types[i] as string;\n\t\tconst pgArrayType = inferPgArrayType(col, colTypes, sampleValue);\n\t\tconst pgBaseType = stripArraySuffix(pgArrayType);\n\n\t\tparams.push(colArray);\n\t\tparamIdx++;\n\t\treturn createTypeCastParamRef(paramIdx, pgBaseType, true);\n\t});\n\n\tconst unnestCall = funcCall('unnest', unnestArgs);\n\tconst colnames = [...bv.columns, ...(bv.ordinality ? ['ord'] : [])].map(\n\t\t(c) => ({ String: { sval: c } }),\n\t);\n\n\tconst rangeFunction: Node = {\n\t\tRangeFunction: {\n\t\t\tfunctions: [{ List: { items: [unnestCall] } }],\n\t\t\tordinality: bv.ordinality,\n\t\t\talias: { aliasname: effectiveAlias, colnames },\n\t\t},\n\t};\n\n\treturn { rangeFunction, params };\n}\n\nfunction compileJoinIntents(\n\tjoins: readonly JoinIntent[],\n\trootTable: string,\n\tschemaName: string | undefined,\n\tdeps: AdapterCompilerDeps,\n): PlanDecision[] {\n\tif (joins.length === 0) return [];\n\n\tconst model = deps.model;\n\tconst naming = deps.naming;\n\tconst deriveFk = deps.deriveFk ?? defaultFkDerivation;\n\tconst defaultPk = deps.defaultPk;\n\tconst results: PlanDecision[] = [];\n\n\tfor (const intent of joins) {\n\t\tif (intent.relation !== undefined) {\n\t\t\t// ── Relation mode: resolve FK from model ──────────────────────────\n\t\t\t// If no model available, we can't resolve the FK — skip with warning.\n\t\t\tif (!model) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`join('${intent.relation}'): relation-mode join requires a model for FK resolution.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst relationsFromRoot = model.getRelationsFrom(rootTable);\n\t\t\t// Match only by relation name for FK resolution.\n\t\t\t// The alias is only used for the output JOIN alias — using it for FK lookup\n\t\t\t// would allow `.join('callee', { as: 'caller' })` to resolve against the\n\t\t\t// wrong relation when 'caller' happens to be another relation name.\n\t\t\tconst rel = relationsFromRoot.find((r) => r.name === intent.relation);\n\n\t\t\tif (!rel) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`join('${intent.relation}'): relation not found on table '${rootTable}'. ` +\n\t\t\t\t\t\t`Available: ${relationsFromRoot.map((r) => r.name).join(', ')}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Derive FK direction from relation type\n\t\t\t// - belongsTo: FK is on the source (root) table → sourceColumn=FK, targetColumn=PK\n\t\t\t// - hasMany/hasOne: FK is on the target table → sourceColumn=PK, targetColumn=FK\n\t\t\tconst isBelongsTo = rel.type === 'belongsTo';\n\t\t\tconst rawFk = rel.foreignKey\n\t\t\t\t? Array.isArray(rel.foreignKey)\n\t\t\t\t\t? rel.foreignKey[0]!\n\t\t\t\t\t: rel.foreignKey\n\t\t\t\t: deriveFk(isBelongsTo ? rootTable : rel.target, defaultPk);\n\n\t\t\tconst sourceColumn = isBelongsTo ? rawFk : defaultPk;\n\t\t\tconst targetColumn = isBelongsTo ? defaultPk : rawFk;\n\t\t\tconst alias = intent.alias ?? intent.relation;\n\n\t\t\tresults.push({\n\t\t\t\ttype: 'join',\n\t\t\t\ttargetTable: rel.target,\n\t\t\t\talias,\n\t\t\t\tsourceColumn,\n\t\t\t\ttargetColumn,\n\t\t\t\tjoinType: intent.type,\n\t\t\t});\n\t\t} else if (intent.batchValues !== undefined) {\n\t\t\t// ── BatchValues mode: unnest($N::type[], ...) AS alias(col1, col2) ──\n\t\t\t// Compiles a batch-values join: the rarg is a RangeFunction wrapping\n\t\t\t// unnest() instead of a plain RangeVar.\n\t\t\t// Params are $1, $2, ... (1-indexed); compiler.ts splices them first.\n\t\t\tconst bv = intent.batchValues;\n\t\t\tconst alias = intent.alias ?? bv.alias;\n\n\t\t\tconst { rangeFunction, params: bvParams } = buildBatchValuesRangeFn(\n\t\t\t\tbv,\n\t\t\t\t1,\n\t\t\t\talias,\n\t\t\t);\n\n\t\t\t// Compile the ON condition.\n\t\t\t// We use a minimal param state with paramIndex already advanced past bvParams\n\t\t\t// so that any ON condition params (rare for batch joins) get correct indices.\n\t\t\t// The ON params start at bvParams.length + 1 (1-indexed).\n\t\t\tconst bvOnParamState = createCompilerState();\n\t\t\tbvOnParamState.paramIndex = bvParams.length;\n\n\t\t\tconst bvCtx: WhereCompilerCtx = {\n\t\t\t\trootTable,\n\t\t\t\taliases: new Map<string, string>(),\n\t\t\t\tparamState: bvOnParamState,\n\t\t\t\tnaming,\n\t\t\t\touterTable: alias,\n\t\t\t\t...(schemaName !== undefined && { schemaName }),\n\t\t\t\t...(model !== undefined && { model }),\n\t\t\t\tcompileSubquery: () => {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t'Subquery in BatchValues JOIN ON condition is not supported.',\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst onNode: Node = compileWhereIntent(intent.on, bvCtx);\n\n\t\t\t// Combine bv unnest params + any ON condition params into batchValuesParams.\n\t\t\t// compiler.ts splices all of these BEFORE other query params so that $1/$2/...\n\t\t\t// in the RangeFunction and ON condition align with parameters[0], [1], ...\n\t\t\tconst allBvParams: unknown[] = [\n\t\t\t\t...bvParams,\n\t\t\t\t...bvOnParamState.parameters,\n\t\t\t];\n\n\t\t\tresults.push({\n\t\t\t\ttype: 'join',\n\t\t\t\ttargetTable: alias,\n\t\t\t\talias,\n\t\t\t\tjoinType: intent.type,\n\t\t\t\tjoinRarg: rangeFunction,\n\t\t\t\tjoinOnNode: onNode,\n\t\t\t\t// batchValuesParams are spliced into this.state.parameters BEFORE\n\t\t\t\t// other params in compiler.ts, so $1/$2/... refs align correctly.\n\t\t\t\tbatchValuesParams: allBvParams,\n\t\t\t});\n\t\t} else {\n\t\t\t// ── Table mode: explicit ON condition ─────────────────────────────\n\t\t\t// Compile the ON WhereIntent to an AST Node via compileWhereIntent.\n\t\t\t// ON conditions for joins are typically column-to-column comparisons\n\t\t\t// (no $N parameters), so a fresh param state is safe.\n\t\t\tconst paramState = createCompilerState();\n\n\t\t\tconst tableAlias = intent.alias ?? intent.table;\n\n\t\t\t// Pre-populate aliases so ref(\"rootTable.col\") and similar expressions\n\t\t\t// resolve the correct table qualifier when the alias differs from the\n\t\t\t// base table name.\n\t\t\tconst tableAliasMap = new Map<string, string>();\n\t\t\ttableAliasMap.set(rootTable, rootTable);\n\t\t\tif (tableAlias !== rootTable) {\n\t\t\t\ttableAliasMap.set(tableAlias, intent.table);\n\t\t\t}\n\n\t\t\tconst ctx: WhereCompilerCtx = {\n\t\t\t\trootTable,\n\t\t\t\taliases: tableAliasMap,\n\t\t\t\tparamState,\n\t\t\t\tnaming,\n\t\t\t\t// outerTable = tableAlias so FieldRef(scope:'outer') resolves to the\n\t\t\t\t// joined alias (e.g. 'e2' in self-join ON conditions).\n\t\t\t\touterTable: tableAlias,\n\t\t\t\t...(schemaName !== undefined && { schemaName }),\n\t\t\t\t...(model !== undefined && { model }),\n\t\t\t\tcompileSubquery: () => {\n\t\t\t\t\tthrow new Error('Subquery in JOIN ON condition is not supported.');\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst onNode: Node = compileWhereIntent(intent.on, ctx);\n\n\t\t\t// Store rarg + onNode separately — the 'join' case in compiler.ts wraps\n\t\t\t// from[0] as larg so multiple .join() calls chain correctly.\n\t\t\tconst joinedRangeVar = rangeVar(\n\t\t\t\tintent.table,\n\t\t\t\ttableAlias,\n\t\t\t\tschemaName,\n\t\t\t\tnaming,\n\t\t\t);\n\n\t\t\tresults.push({\n\t\t\t\ttype: 'join',\n\t\t\t\ttargetTable: intent.table,\n\t\t\t\talias: tableAlias,\n\t\t\t\tjoinType: intent.type,\n\t\t\t\tjoinRarg: joinedRangeVar,\n\t\t\t\tjoinOnNode: onNode,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn results;\n}\n\n// ============================================================================\n// Phase helpers — extracted from compileSelect for CC reduction\n// ============================================================================\n\n/**\n * Propagate filter conditions from EXISTS decisions to matching includeStrategy decisions.\n * When a relation is both filtered (EXISTS) and included, the filter appears in both\n * the EXISTS subquery AND the include subquery.\n */\nfunction propagateExistsConditions(\n\tincludeDecisions: readonly PlanDecision[],\n\texistsDecisions: readonly PlanDecision[],\n): PlanDecision[] {\n\treturn includeDecisions.map((jd) => {\n\t\tif (jd.type !== 'includeStrategy' || !jd.relationName) return jd;\n\n\t\tconst matchingExists = existsDecisions.find(\n\t\t\t(ed) =>\n\t\t\t\ted.type === 'where' &&\n\t\t\t\t(ed.operator === 'exists' || ed.operator === 'notExists') &&\n\t\t\t\t(ed.relationName === jd.relationName ||\n\t\t\t\t\ted.targetTable === jd.targetTable) &&\n\t\t\t\ted.conditions &&\n\t\t\t\t(ed.conditions as PlanDecision[]).length > 0,\n\t\t);\n\n\t\tif (matchingExists?.conditions) {\n\t\t\treturn { ...jd, conditions: matchingExists.conditions };\n\t\t}\n\t\treturn jd;\n\t});\n}\n\n/**\n * Strip auto-selected columns from join includeStrategy decisions when the query\n * uses aggregation, DISTINCT, GROUP BY, or explicit column selection.\n *\n * In all four cases the JOIN itself is kept (for filtering / INNER JOIN semantics)\n * but its auto-hydration columns would produce invalid SQL — they are cleared.\n * Explicitly requested columns (via relationColumn()) are re-injected later by\n * injectAndValidateRelationColumns().\n *\n * Mutates `decisions` in place (same pattern as the original code).\n */\nfunction stripJoinColumnsForAggregation(\n\tdecisions: PlanDecision[],\n\tintent: NonNullable<PlanReport['intent']>,\n): void {\n\t// INCLUDE-COUNT: aggregate-only query (COUNT(*), no GROUP BY fields)\n\tconst isAggregateOnly =\n\t\tintent.select &&\n\t\t'type' in intent.select &&\n\t\tintent.select.type === 'aggregate' &&\n\t\t!(\n\t\t\t'fields' in intent.select &&\n\t\t\t(intent.select as { fields?: unknown }).fields\n\t\t);\n\n\t// DISTINCT-VECTOR: SELECT DISTINCT — vector cols have no equality operator\n\tconst isDistinct = intent.distinct === true;\n\n\t// GROUP-BY-JOIN: GROUP BY — non-aggregate cols must appear in GROUP BY\n\tconst hasGroupBy = intent.groupBy && intent.groupBy.length > 0;\n\n\t// EXPLICIT-COLUMNS: .columns([...]) — user declared exactly what they want\n\tconst hasExplicitColumns =\n\t\tintent.select &&\n\t\t'type' in intent.select &&\n\t\tintent.select.type === 'expressions';\n\n\tif (isAggregateOnly || isDistinct || hasGroupBy || hasExplicitColumns) {\n\t\tfor (const d of decisions) {\n\t\t\tif (d.type === 'includeStrategy' && d.choice === 'join') {\n\t\t\t\t(d as Mutable<PlanDecision>).columns = [];\n\t\t\t}\n\t\t}\n\t}\n}\n\ntype RelationColumnEntry = { col: string; alias?: string };\n\n/**\n * Collect specific columns per relation from selectRelationColumn decisions.\n *\n * Key: full relation path (e.g. 'callee' for 1-hop, 'callee.file' for 2-hop).\n * This lets relationColumn('callee.file', 'path', 'fp') target the leaf\n * includeStrategy decision rather than the 1st-hop one.\n */\nfunction buildRelationColumnsMap(\n\tdecisions: PlanDecision[],\n\tincludedRelations: Set<string>,\n): Map<string, RelationColumnEntry[]> {\n\tconst map = new Map<string, RelationColumnEntry[]>();\n\n\tfor (const d of decisions) {\n\t\tif (!(d.type === 'selectRelationColumn' && d.relation && d.column))\n\t\t\tcontinue;\n\n\t\tconst col = d.column as string;\n\t\tconst alias = d.alias as string | undefined;\n\t\tconst fullRelation = d.relation as string;\n\t\tconst rootRelation = fullRelation.split('.')[0] ?? '';\n\t\tif (!includedRelations.has(rootRelation)) continue;\n\n\t\t// Use full path as map key so 'callee.file' is stored separately\n\t\t// from 'callee' — avoids injecting 2-hop columns into 1-hop includes.\n\t\tconst mapKey = fullRelation;\n\t\tif (col === '*') {\n\t\t\t// Wildcard: select all columns from relation (no aliases)\n\t\t\tmap.set(mapKey, [{ col: '*' }]);\n\t\t\tcontinue;\n\t\t}\n\t\tconst existing = map.get(mapKey);\n\t\tif (existing) {\n\t\t\tif (existing.length === 1 && existing[0]?.col === '*') continue; // wildcard already set\n\t\t\tif (!existing.some((e) => e.col === col)) {\n\t\t\t\texisting.push({ col, ...(alias !== undefined && { alias }) });\n\t\t\t}\n\t\t} else {\n\t\t\tmap.set(mapKey, [{ col, ...(alias !== undefined && { alias }) }]);\n\t\t}\n\t}\n\n\treturn map;\n}\n\n/**\n * Find the map key for a given includeStrategy relationName.\n * Exact match first (1-hop); then suffix match '.relationName' (2-hop+).\n */\nfunction findRelationMapKey(\n\tmap: Map<string, RelationColumnEntry[]>,\n\trelationName: string,\n): string | undefined {\n\tif (map.has(relationName)) return relationName;\n\tconst suffix = `.${relationName}`;\n\tfor (const key of map.keys()) {\n\t\tif (key.endsWith(suffix)) return key;\n\t}\n\treturn undefined;\n}\n\n/**\n * Inject user-specified columns from relationColumnsMap into matching\n * includeStrategy decisions, then validate them against the model schema.\n */\nfunction injectAndValidateRelationColumns(\n\tenrichedUnifiedDecisions: PlanDecision[],\n\trelationColumnsMap: Map<string, RelationColumnEntry[]>,\n\tmodel: import('@dbsp/types').ModelIR | undefined,\n): void {\n\tif (relationColumnsMap.size === 0) return;\n\n\t// Inject collected columns and aliases into matching includeStrategy decisions\n\tfor (const d of enrichedUnifiedDecisions) {\n\t\tif (d.type === 'includeStrategy' && d.relationName) {\n\t\t\tconst mapKey = findRelationMapKey(\n\t\t\t\trelationColumnsMap,\n\t\t\t\td.relationName as string,\n\t\t\t);\n\t\t\tconst entries = mapKey ? relationColumnsMap.get(mapKey) : undefined;\n\t\t\tif (entries) {\n\t\t\t\tconst mut = d as Mutable<PlanDecision>;\n\t\t\t\t// columns: plain string array (preserves existing contract)\n\t\t\t\tmut.columns = entries.map((e) => e.col);\n\t\t\t\t// columnAliases: map col -> user alias (only non-trivial aliases)\n\t\t\t\tconst aliasMap: Record<string, string> = {};\n\t\t\t\tfor (const { col, alias } of entries) {\n\t\t\t\t\tif (alias) aliasMap[col] = alias;\n\t\t\t\t}\n\t\t\t\tif (Object.keys(aliasMap).length > 0) {\n\t\t\t\t\tmut.columnAliases = aliasMap;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Validate injected columns exist in target table schema\n\tif (!model) return;\n\tfor (const d of enrichedUnifiedDecisions) {\n\t\tif (\n\t\t\td.type === 'includeStrategy' &&\n\t\t\td.columns &&\n\t\t\td.targetTable &&\n\t\t\t!(\n\t\t\t\t(d.columns as string[]).length === 1 &&\n\t\t\t\t(d.columns as string[])[0] === '*'\n\t\t\t)\n\t\t) {\n\t\t\tconst targetTable = model.getTable(d.targetTable as string);\n\t\t\tif (targetTable) {\n\t\t\t\tconst validColumnNames = new Set(\n\t\t\t\t\ttargetTable.columns.map((c) => c.name),\n\t\t\t\t);\n\t\t\t\tconst invalid = (d.columns as string[]).filter(\n\t\t\t\t\t(c) => !validColumnNames.has(c),\n\t\t\t\t);\n\t\t\t\tif (invalid.length > 0) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unknown column(s) ${invalid.map((c) => `'${c}'`).join(', ')} ` +\n\t\t\t\t\t\t\t`in relation '${d.relationName}' (table '${d.targetTable}'). ` +\n\t\t\t\t\t\t\t`Available: ${[...validColumnNames].join(', ')}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Enrich range operator decisions with `dataType` from the model.\n * PostgreSQL requires explicit type casts for range parameters (contains/containedBy/overlaps).\n * Mutates `allDecisions` in place.\n */\nfunction enrichRangeDecisions(\n\tallDecisions: PlanDecision[],\n\tmodel: import('@dbsp/types').ModelIR | undefined,\n\trootTable: string,\n): void {\n\tif (!model) return;\n\tfor (let i = 0; i < allDecisions.length; i++) {\n\t\tconst d = allDecisions[i];\n\t\tif (\n\t\t\td &&\n\t\t\td.type === 'where' &&\n\t\t\t(d.operator === 'contains' ||\n\t\t\t\td.operator === 'containedBy' ||\n\t\t\t\td.operator === 'overlaps')\n\t\t) {\n\t\t\tconst tableName = d.table || rootTable;\n\t\t\tconst table = model.getTable(tableName);\n\t\t\tif (table) {\n\t\t\t\tconst col = table.columns.find((c) => c.name === d.column);\n\t\t\t\tif (col?.type.endsWith('range')) {\n\t\t\t\t\tallDecisions[i] = { ...d, dataType: col.type } as typeof d;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Assemble the SimplifiedPlanReport from the compiled decisions and plan metadata.\n * Handles BatchValues FROM source construction and optional fields (existsWrap, lock, schema).\n */\nfunction buildSimplifiedPlanReport(\n\tplan: PlanReport,\n\tallDecisions: PlanDecision[],\n\tschemaName: string | undefined,\n): SimplifiedPlanReport {\n\t// BatchValues FROM source: the FROM clause is an unnest() table function.\n\t// Build the RangeFunction and record params separately so compiler.ts can\n\t// inject them at the front of the parameter list.\n\tconst bvFromSource = plan.intent?.batchValuesSource;\n\tconst batchValuesFromFields = bvFromSource\n\t\t? (() => {\n\t\t\t\tconst { rangeFunction, params } = buildBatchValuesRangeFn(\n\t\t\t\t\tbvFromSource,\n\t\t\t\t\t1,\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tbatchValuesFromNode: rangeFunction,\n\t\t\t\t\tbatchValuesFromParams: params,\n\t\t\t\t};\n\t\t\t})()\n\t\t: {};\n\n\treturn {\n\t\trootTable: plan.rootTable,\n\t\tdecisions: allDecisions,\n\t\t...(schemaName ? { schema: schemaName } : {}),\n\t\t...(plan.intent?.existsWrap ? { existsWrap: true } : {}),\n\t\t...(plan.intent?.lock ? { lock: plan.intent.lock } : {}),\n\t\t...batchValuesFromFields,\n\t};\n}\n\n// ============================================================================\n// compile (SELECT)\n// ============================================================================\n\n/**\n * Compile a PlanReport to a parameterised SELECT query.\n * Extracted body of PgsqlAdapter.compile().\n */\nexport function compileSelect<T = unknown>(\n\tplan: PlanReport,\n\toptions: CompileOptions | undefined,\n\tdeps: AdapterCompilerDeps,\n): CompiledQuery<T> {\n\t// schemaName precedence (options > adapter ctor) is resolved in PgsqlAdapter.buildCompileDeps; deps.schemaName is authoritative here\n\tconst schemaName = deps.schemaName;\n\n\tconst resolvedModelForCompiler = options?.model ?? deps.model;\n\tconst compilerOptions: CompilerOptions = {\n\t\tnaming: deps.naming,\n\t\t...(schemaName && { schema: schemaName }),\n\t\tdefaultPkColumnName: deps.defaultPk,\n\t\tderiveFkColumnName: deps.deriveFk,\n\t\t...(resolvedModelForCompiler != null && {\n\t\t\tmodel: resolvedModelForCompiler,\n\t\t}),\n\t};\n\n\t// Convert PlanReport (core) → SimplifiedPlanReport (pgsql compiler)\n\t// The core's plan.decisions contain observability data, not SQL instructions.\n\t// The actual query structure is in plan.intent (QueryIntent).\n\t// Note: For unit tests with mock plans (no intent), fall back to plan.decisions directly.\n\tlet simplifiedPlan: SimplifiedPlanReport;\n\n\tif (plan.intent) {\n\t\t// Real usage: convert intent to decisions\n\t\tlet decisions = intentToDecisions(plan.intent, plan.rootTable);\n\n\t\t// Strip exists/notExists decisions from intentToDecisions — they use the\n\t\t// relation name as targetTable (unresolved). extractExistsDecisions (below)\n\t\t// provides the correct decisions with the actual table name from the planner.\n\t\t// Must recurse into whereAnd/whereOr/whereNot to catch nested occurrences\n\t\t// (e.g. notExists inside and() produces a whereAnd containing a notExists).\n\t\tdecisions = decisions\n\t\t\t.map(stripExistsFromDecision)\n\t\t\t.filter((d): d is PlanDecision => d !== null);\n\n\t\t// Convert dotted-field comparisons (e.g., \"parent.name\") to EXISTS subqueries\n\t\t// NQL compiles relation-path filters as plain comparisons with dotted field names\n\t\tconst resolvedModel = options?.model ?? deps.model;\n\t\tif (resolvedModel) {\n\t\t\tdecisions = convertDottedFieldsToExists(\n\t\t\t\tdecisions,\n\t\t\t\tplan.rootTable,\n\t\t\t\tresolvedModel,\n\t\t\t);\n\t\t}\n\n\t\t// Add correct EXISTS decisions from planner's filter-strategy decisions\n\t\t// (they have the actual target table in context.target)\n\t\tconst existsDecisions = extractExistsDecisions(plan, options?.model);\n\n\t\t// Phase 3: Extract ALL include decisions (json_agg, join, lateral, cte, subquery)\n\t\tconst unifiedIncludeDecisions = extractAllIncludeDecisions(\n\t\t\tplan,\n\t\t\tdeps.defaultPk,\n\t\t\tdeps.deriveFk,\n\t\t);\n\n\t\t// Synthesize join decisions for intent-based includes the planner couldn't resolve\n\t\t// (e.g. camelCase alias 'enclosingSymbol' for model relation 'enclosing_symbol').\n\t\tconst coveredByPlanner = new Set(\n\t\t\tunifiedIncludeDecisions\n\t\t\t\t.filter((d) => d.type === 'includeStrategy')\n\t\t\t\t.map((d) => d.relationName as string)\n\t\t\t\t.filter(Boolean),\n\t\t);\n\t\tconst synthesizedModel = options?.model ?? deps.model;\n\t\tconst synthesizedJoins = synthesizedModel\n\t\t\t? synthesizeMissingJoinDecisions(\n\t\t\t\t\tplan,\n\t\t\t\t\tcoveredByPlanner,\n\t\t\t\t\tsynthesizedModel,\n\t\t\t\t\tdeps.defaultPk,\n\t\t\t\t\tdeps.deriveFk,\n\t\t\t\t)\n\t\t\t: [];\n\t\tconst allUnifiedIncludeDecisions =\n\t\t\tsynthesizedJoins.length > 0\n\t\t\t\t? [...unifiedIncludeDecisions, ...synthesizedJoins]\n\t\t\t\t: unifiedIncludeDecisions;\n\n\t\t// Propagate filter conditions from EXISTS to matching include decisions.\n\t\t// When a relation is both filtered and included, the filter appears in both\n\t\t// the EXISTS subquery AND the include subquery.\n\t\tconst enrichedUnifiedDecisions = propagateExistsConditions(\n\t\t\tallUnifiedIncludeDecisions,\n\t\t\texistsDecisions,\n\t\t);\n\n\t\t// Strip auto-selected columns from join includes when aggregation, DISTINCT,\n\t\t// GROUP BY, or explicit column selection is active. Keeps the JOIN for\n\t\t// filtering/inner join semantics but prevents invalid SELECT column lists.\n\t\tstripJoinColumnsForAggregation(enrichedUnifiedDecisions, plan.intent);\n\n\t\t// Deduplicate: remove selectRelationColumn decisions for relations\n\t\t// already covered by an include strategy.\n\t\t// Include handlers (json_agg, lateral, CTE, join) already compile the\n\t\t// relation's columns — emitting both would produce duplicate columns.\n\t\t// Standalone relation expressions (no matching include) are kept.\n\t\t// Note: selectPseudoColumn (recursive traversals like manager.name)\n\t\t// are never covered by includes — they always compile independently.\n\t\tconst includedRelations = new Set(\n\t\t\tenrichedUnifiedDecisions\n\t\t\t\t.filter((d) => d.type === 'includeStrategy')\n\t\t\t\t.map((d) => d.relationName as string)\n\t\t\t\t.filter(Boolean),\n\t\t);\n\n\t\tif (includedRelations.size > 0) {\n\t\t\t// Collect specific columns from selectRelationColumn decisions and inject\n\t\t\t// them into matching includeStrategy decisions, then validate against schema.\n\t\t\tconst relationColumnsMap = buildRelationColumnsMap(\n\t\t\t\tdecisions,\n\t\t\t\tincludedRelations,\n\t\t\t);\n\t\t\tinjectAndValidateRelationColumns(\n\t\t\t\tenrichedUnifiedDecisions,\n\t\t\t\trelationColumnsMap,\n\t\t\t\toptions?.model ?? deps.model,\n\t\t\t);\n\t\t}\n\n\t\tconst deduplicatedDecisions =\n\t\t\tincludedRelations.size > 0\n\t\t\t\t? decisions.filter((d) => {\n\t\t\t\t\t\tif (d.type === 'selectRelationColumn' && d.relation) {\n\t\t\t\t\t\t\t// relation may be a dotted path (e.g. \"userRoles.role.permissions\")\n\t\t\t\t\t\t\t// — check if the root segment is covered by an include\n\t\t\t\t\t\t\tconst rel = d.relation as string;\n\t\t\t\t\t\t\tconst rootRelation = rel.split('.')[0] ?? rel;\n\t\t\t\t\t\t\tif (includedRelations.has(rootRelation)) {\n\t\t\t\t\t\t\t\treturn false; // covered by include strategy\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t})\n\t\t\t\t: decisions;\n\n\t\t// Compile explicit JoinIntent[] from plan.intent.joins into 'join' decisions.\n\t\t// These are non-hydrating SQL JOINs (flat result, no relation columns added).\n\t\tconst joinIntentDecisions =\n\t\t\tplan.intent?.joins && (plan.intent.joins as JoinIntent[]).length > 0\n\t\t\t\t? compileJoinIntents(\n\t\t\t\t\t\tplan.intent.joins as JoinIntent[],\n\t\t\t\t\t\tplan.rootTable,\n\t\t\t\t\t\tschemaName,\n\t\t\t\t\t\tdeps,\n\t\t\t\t\t)\n\t\t\t\t: [];\n\n\t\tconst allDecisions = [\n\t\t\t...deduplicatedDecisions,\n\t\t\t...existsDecisions,\n\t\t\t...enrichedUnifiedDecisions,\n\t\t\t...joinIntentDecisions,\n\t\t];\n\n\t\t// Enrich range operator decisions with dataType from model\n\t\t// (PostgreSQL requires explicit type casts for range parameters).\n\t\t// Use deps.model as fallback so ORM queries through deps also get enriched.\n\t\tconst rangeModel = options?.model ?? deps.model;\n\t\tenrichRangeDecisions(allDecisions, rangeModel, plan.rootTable);\n\n\t\tsimplifiedPlan = buildSimplifiedPlanReport(plan, allDecisions, schemaName);\n\t} else {\n\t\t// Unit test with mock data: use decisions directly (legacy format).\n\t\t// Tests supply adapter-format PlanDecisions inside a core PlanReport,\n\t\t// so the runtime data is already in the right shape — bridge the type gap.\n\t\tsimplifiedPlan = {\n\t\t\trootTable: plan.rootTable,\n\t\t\tdecisions: bridgeLegacyDecisions(plan.decisions),\n\t\t\t...(schemaName ? { schema: schemaName } : {}),\n\t\t};\n\t}\n\n\tconst result = compilePlan(simplifiedPlan, compilerOptions);\n\n\treturn {\n\t\tsql: result.sql,\n\t\tparameters: result.parameters,\n\t};\n}\n\nexport function compileWithIncludes<T = unknown>(\n\tplan: PlanReport,\n\toptions: CompileOptions | undefined,\n\tdeps: AdapterCompilerDeps,\n): CompileResultWithIncludes<T> {\n\tconst main = compileSelect<T>(plan, options, deps);\n\n\t// Extract subquery include info from planner decisions.\n\t// Decisions with choice === 'subquery' need separate execution:\n\t// mapToHandlerDecision lowers them to json_agg at the SQL level so the main\n\t// query compiles, but hydrateJsonAggIncludes only processes decisions whose\n\t// planner choice is 'json_agg'. When the user sets defaultIncludeStrategy:\n\t// 'subquery', planner decisions carry choice === 'subquery', so hydration\n\t// must happen via the subquery path (separate query + hydrateIncludes).\n\tconst subqueryIncludes: SubqueryIncludeInfo[] = [];\n\n\tfor (const d of plan.decisions) {\n\t\tif (d.type !== 'include-strategy' || d.choice !== 'subquery') continue;\n\n\t\tconst ctx = d.context;\n\t\tif (!ctx.target) continue;\n\n\t\tconst relationName = ctx.includeAlias ?? ctx.relation;\n\t\tif (!relationName) continue;\n\n\t\t// Derive FK using shared helper\n\t\tconst rawFk =\n\t\t\tderiveForeignKey(ctx, deps.deriveFk, deps.defaultPk) ?? deps.defaultPk;\n\t\tconst fk = Array.isArray(rawFk) ? rawFk[0]! : rawFk;\n\n\t\t// For subquery include, we need:\n\t\t// - sourceKey: column on the parent result to extract IDs from\n\t\t// - foreignKey: column on the target table to match via WHERE ... IN\n\t\t//\n\t\t// belongsTo (posts → author): FK=authorId is on source.\n\t\t// Extract authorId from parents → SELECT * FROM authors WHERE id IN (...)\n\t\t// sourceKey=authorId, foreignKey=id (target PK)\n\t\t//\n\t\t// hasMany (authors → posts): FK=authorId is on target.\n\t\t// Extract id from parents → SELECT * FROM posts WHERE author_id IN (...)\n\t\t// sourceKey=id, foreignKey=authorId (target FK)\n\t\tconst isBelongsTo = ctx.relationType === 'belongsTo';\n\t\tconst sourceKey = isBelongsTo ? fk : 'id';\n\t\tconst targetFk = isBelongsTo ? 'id' : fk;\n\n\t\t// Find matching include intent for select/where passthrough\n\t\tconst includeIntent = (\n\t\t\tplan.intent?.include as Array<Record<string, unknown>> | undefined\n\t\t)?.find(\n\t\t\t(i) => i.relation === relationName || i.relation === ctx.includeAlias,\n\t\t);\n\n\t\tconst entry: Mutable<SubqueryIncludeInfo> = {\n\t\t\trelationName,\n\t\t\ttargetTable: ctx.target,\n\t\t\tforeignKey: targetFk,\n\t\t\tsourceKey,\n\t\t\tsourceTable: ctx.sourceTable ?? plan.rootTable,\n\t\t};\n\t\tif (typeof ctx.relationType === 'string') {\n\t\t\tentry.relationType = ctx.relationType;\n\t\t}\n\t\tif (includeIntent?.select != null) {\n\t\t\tentry.select = includeIntent.select as NonNullable<\n\t\t\t\tSubqueryIncludeInfo['select']\n\t\t\t>;\n\t\t}\n\t\tif (includeIntent?.where != null) {\n\t\t\tentry.where = includeIntent.where as NonNullable<\n\t\t\t\tSubqueryIncludeInfo['where']\n\t\t\t>;\n\t\t}\n\t\tsubqueryIncludes.push(entry);\n\t}\n\n\treturn { main, subqueryIncludes };\n}\n","/**\n * Plan Decision Extractor\n *\n * Extracted from PgsqlAdapter — converts PlanReport decisions into\n * PlanDecision arrays for the compiler. Handles EXISTS, LEFT JOIN,\n * JSON_AGG, and dotted-field → EXISTS conversion.\n *\n * All functions are stateless pure functions operating on PlanReport data.\n */\n\nimport type { ModelIR, PlanReport } from '@dbsp/types';\nimport { isSubqueryRef } from '@dbsp/types';\nimport type { Node } from '@pgsql/types';\nimport {\n\tDEFAULT_PK_COLUMN,\n\tdefaultFkDerivation,\n\ttype FkColumnDerivation,\n} from './assert-field.js';\nimport type { PlanDecision, SimplifiedPlanReport } from './compiler.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ntype ExistsIntent = {\n\tkind: 'exists' | 'notExists' | 'relationFilter';\n\trelation: string | readonly string[];\n\twhere?: unknown;\n\tmode?: 'some' | 'none' | 'every';\n};\n\ntype ResolvedRelation = {\n\ttarget: string;\n\tforeignKey: string | undefined;\n\trelationType: 'belongsTo' | 'hasMany' | 'hasOne' | undefined;\n};\n\n// ============================================================================\n// Pure Helpers\n// ============================================================================\n\n/**\n * Recursively find all exists/notExists/relationFilter intents in a where tree.\n */\nexport function findExistsIntents(where: unknown): ExistsIntent[] {\n\tif (!where || typeof where !== 'object') return [];\n\tconst w = where as Record<string, unknown>;\n\tif (\n\t\tw.kind === 'exists' ||\n\t\tw.kind === 'notExists' ||\n\t\tw.kind === 'relationFilter'\n\t) {\n\t\treturn [w as ExistsIntent];\n\t}\n\tconst results: ExistsIntent[] = [];\n\tif (w.conditions && Array.isArray(w.conditions)) {\n\t\tfor (const c of w.conditions) {\n\t\t\tresults.push(...findExistsIntents(c));\n\t\t}\n\t}\n\tif (w.condition) {\n\t\tresults.push(...findExistsIntents(w.condition));\n\t}\n\treturn results;\n}\n\n/**\n * Resolve a named relation from the ModelIR, returning target table, FK, and type.\n */\nexport function resolveRelation(\n\tmodel: ModelIR,\n\tsourceTable: string,\n\trelationName: string,\n): ResolvedRelation | undefined {\n\tconst rel = model.getRelation(`${sourceTable}.${relationName}`);\n\tif (!rel) return undefined;\n\tconst foreignKey =\n\t\ttypeof rel.foreignKey === 'string' ? rel.foreignKey : rel.foreignKey?.[0];\n\tconst relationType = rel.type as\n\t\t| 'belongsTo'\n\t\t| 'hasMany'\n\t\t| 'hasOne'\n\t\t| undefined;\n\treturn { target: rel.target, foreignKey, relationType };\n}\n\n/**\n * Resolve include alias from planner context (relation ?? includeAlias).\n */\nexport function resolveIncludeAlias(context: {\n\tincludeAlias?: string;\n\trelation?: string;\n}): string | undefined {\n\treturn context.relation ?? context.includeAlias;\n}\n\n/**\n * Resolve an include intent by following the intentPath through the nested include tree.\n * intentPath is e.g. \"include[0]\" or \"include[0].include[0]\" for deeply nested includes.\n * Falls back to flat search by relation name if intentPath is not available.\n */\nfunction resolveIncludeByPath(\n\tincludes:\n\t\t| Array<{\n\t\t\t\trelation: string;\n\t\t\t\tlimit?: number;\n\t\t\t\tselect?: unknown;\n\t\t\t\twhere?: unknown;\n\t\t\t\tinclude?: unknown[];\n\t\t }>\n\t\t| undefined,\n\tintentPath: string | undefined,\n\trelationName: string,\n):\n\t| { relation: string; limit?: number; select?: unknown; where?: unknown }\n\t| undefined {\n\tif (!includes) return undefined;\n\n\t// Try intentPath-based traversal first\n\tif (intentPath) {\n\t\t// Parse path segments like \"include[0].include[1]\"\n\t\tconst indexPattern = /include\\[(\\d+)\\]/g;\n\t\tlet current: unknown[] = includes;\n\t\tlet resolved: { relation: string; limit?: number } | undefined;\n\t\tlet execResult = indexPattern.exec(intentPath);\n\n\t\twhile (execResult !== null) {\n\t\t\tconst idx = parseInt(execResult[1]!, 10);\n\t\t\tconst item = current[idx] as\n\t\t\t\t| { relation: string; limit?: number; include?: unknown[] }\n\t\t\t\t| undefined;\n\t\t\tif (!item) break;\n\t\t\tresolved = item;\n\t\t\tcurrent = (item.include as unknown[]) ?? [];\n\t\t\texecResult = indexPattern.exec(intentPath);\n\t\t}\n\t\tif (resolved) return resolved;\n\t}\n\n\t// Fallback: flat search by relation name (top-level only)\n\treturn includes.find((i) => i.relation === relationName);\n}\n\n/**\n * Derive foreign key from planner decision context.\n * Uses explicit FK if available, otherwise derives from table name\n * using the configurable FK derivation convention.\n */\nexport function deriveForeignKey(\n\tcontext: {\n\t\tforeignKey?: string | readonly string[];\n\t\tsourceFK?: string | readonly string[];\n\t\trelationType?: string;\n\t\ttarget?: string;\n\t\tsourceTable?: string;\n\t},\n\tderiveFk: FkColumnDerivation = defaultFkDerivation,\n\tdefaultPk: string = DEFAULT_PK_COLUMN,\n): string | readonly string[] | undefined {\n\tconst fk = context.foreignKey ?? context.sourceFK;\n\tif (fk) return fk;\n\tif (!context.relationType) return undefined;\n\tif (context.relationType === 'belongsTo') {\n\t\treturn context.target ? deriveFk(context.target, defaultPk) : undefined;\n\t}\n\treturn context.sourceTable\n\t\t? deriveFk(context.sourceTable, defaultPk)\n\t\t: undefined;\n}\n\n/**\n * Map comparison operator names to SQL operator strings.\n */\nexport function mapComparisonOperator(op: string): string {\n\tconst map: Record<string, string> = {\n\t\teq: '=',\n\t\tneq: '!=',\n\t\tgt: '>',\n\t\tgte: '>=',\n\t\tlt: '<',\n\t\tlte: '<=',\n\t\tlike: 'LIKE',\n\t\tilike: 'ILIKE',\n\t\tisDistinctFrom: 'IS DISTINCT FROM',\n\t};\n\treturn map[op] ?? '=';\n}\n\n/**\n * Convert a literal JS value to a PostgreSQL AST constant node.\n */\nexport function valueToNode(value: unknown): Node {\n\tif (typeof value === 'string') {\n\t\treturn { A_Const: { sval: { sval: value } } };\n\t}\n\tif (typeof value === 'number') {\n\t\tif (Number.isInteger(value)) {\n\t\t\treturn { A_Const: { ival: { ival: value } } };\n\t\t}\n\t\treturn { A_Const: { fval: { fval: String(value) } } };\n\t}\n\tif (typeof value === 'boolean') {\n\t\treturn { A_Const: { boolval: { boolval: value } } };\n\t}\n\tif (value === null) {\n\t\treturn { A_Const: { isnull: true } };\n\t}\n\t// Fallback: string representation\n\treturn { A_Const: { sval: { sval: String(value) } } };\n}\n\n// ============================================================================\n// Where → Decision Conversion\n// ============================================================================\n\n/**\n * Convert a where clause AST (from intent) to PlanDecision[].\n * Handles comparison, and, or, not.\n */\nexport function convertWhereToDecisions(\n\twhere: unknown,\n\ttable: string,\n): PlanDecision[] {\n\tif (!where || typeof where !== 'object') return [];\n\tconst w = where as Record<string, unknown>;\n\n\tswitch (w.kind) {\n\t\tcase 'comparison': {\n\t\t\t// Convert SubqueryRefIntent { kind: 'ref', column } to FieldRef { kind: 'fieldRef', scope: 'outer', column }\n\t\t\t// so that compileValueOrFieldRef() treats it as a column reference, not a parameter.\n\t\t\tconst rawValue = w.value;\n\t\t\tconst resolvedValue = isSubqueryRef(rawValue)\n\t\t\t\t? {\n\t\t\t\t\t\tkind: 'fieldRef' as const,\n\t\t\t\t\t\tscope: 'outer' as const,\n\t\t\t\t\t\tcolumn: (rawValue as { column: string }).column,\n\t\t\t\t\t}\n\t\t\t\t: rawValue;\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'where',\n\t\t\t\t\tcolumn: w.field as string,\n\t\t\t\t\toperator: w.operator as string,\n\t\t\t\t\tvalue: resolvedValue,\n\t\t\t\t\ttable,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t\tcase 'like':\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'where',\n\t\t\t\t\tcolumn: w.field as string,\n\t\t\t\t\toperator: 'like',\n\t\t\t\t\tvalue: w.pattern,\n\t\t\t\t\ttable,\n\t\t\t\t},\n\t\t\t];\n\t\tcase 'in':\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'where',\n\t\t\t\t\tcolumn: w.field as string,\n\t\t\t\t\toperator: 'in',\n\t\t\t\t\tvalue: w.values ?? w.subquery,\n\t\t\t\t\ttable,\n\t\t\t\t},\n\t\t\t];\n\t\tcase 'range':\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'where',\n\t\t\t\t\tcolumn: w.field as string,\n\t\t\t\t\toperator: (w.operator as string) ?? 'between',\n\t\t\t\t\tvalue: w.value,\n\t\t\t\t\ttable,\n\t\t\t\t},\n\t\t\t];\n\t\tcase 'null':\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'where',\n\t\t\t\t\tcolumn: w.field as string,\n\t\t\t\t\toperator: w.operator as string,\n\t\t\t\t\tvalue: null,\n\t\t\t\t\ttable,\n\t\t\t\t},\n\t\t\t];\n\t\tcase 'and': {\n\t\t\tconst conditions = w.conditions as unknown[];\n\t\t\tconst subDecisions = conditions.flatMap((c) =>\n\t\t\t\tconvertWhereToDecisions(c, table),\n\t\t\t);\n\t\t\tif (subDecisions.length === 0) return [];\n\t\t\tif (subDecisions.length === 1) return subDecisions;\n\t\t\treturn [{ type: 'whereAnd', conditions: subDecisions }];\n\t\t}\n\t\tcase 'or': {\n\t\t\tconst conditions = w.conditions as unknown[];\n\t\t\tconst subDecisions = conditions.flatMap((c) =>\n\t\t\t\tconvertWhereToDecisions(c, table),\n\t\t\t);\n\t\t\tif (subDecisions.length === 0) return [];\n\t\t\tif (subDecisions.length === 1) return subDecisions;\n\t\t\treturn [{ type: 'whereOr', conditions: subDecisions }];\n\t\t}\n\t\tcase 'not': {\n\t\t\tconst subDecisions = convertWhereToDecisions(w.condition, table);\n\t\t\tif (subDecisions.length === 0) return [];\n\t\t\treturn [{ type: 'whereNot', conditions: subDecisions }];\n\t\t}\n\t\t// Custom expression: { kind: 'expression', expr, operator, value }\n\t\t// Produced by ExpressionRef.eq(), .neq(), .gt(), etc.\n\t\t// e.g. op('~', ref('path'), param(regex)).eq(true)\n\t\tcase 'expression':\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'where',\n\t\t\t\t\toperator: 'expression',\n\t\t\t\t\texpressionIntent: w.expr,\n\t\t\t\t\tvalue: w.value,\n\t\t\t\t\tsubqueryOperator: w.operator as string,\n\t\t\t\t\ttable,\n\t\t\t\t},\n\t\t\t];\n\t\tdefault:\n\t\t\treturn [];\n\t}\n}\n\n// ============================================================================\n// Decision Extractors\n// ============================================================================\n\n/**\n * Convert dotted field references (e.g., \"author.name\") to EXISTS subquery decisions.\n */\nexport function convertDottedFieldsToExists(\n\tdecisions: PlanDecision[],\n\trootTable: string,\n\tmodel: ModelIR,\n): PlanDecision[] {\n\treturn decisions.map((d) => {\n\t\t// Recurse into compound conditions\n\t\tif (\n\t\t\t(d.type === 'whereAnd' ||\n\t\t\t\td.type === 'whereOr' ||\n\t\t\t\td.type === 'whereNot') &&\n\t\t\td.conditions\n\t\t) {\n\t\t\treturn {\n\t\t\t\t...d,\n\t\t\t\tconditions: convertDottedFieldsToExists(\n\t\t\t\t\td.conditions as PlanDecision[],\n\t\t\t\t\trootTable,\n\t\t\t\t\tmodel,\n\t\t\t\t),\n\t\t\t};\n\t\t}\n\n\t\t// Only handle 'where' comparisons with dotted column\n\t\tif (\n\t\t\td.type !== 'where' ||\n\t\t\t!d.column ||\n\t\t\ttypeof d.column !== 'string' ||\n\t\t\t!d.column.includes('.')\n\t\t)\n\t\t\treturn d;\n\n\t\t// Split: \"parent.name\" → [\"parent\", \"name\"]\n\t\tconst dotIndex = d.column.indexOf('.');\n\t\tconst relationName = d.column.substring(0, dotIndex);\n\t\tconst targetColumn = d.column.substring(dotIndex + 1);\n\n\t\t// Resolve relation from model\n\t\tconst resolved = resolveRelation(model, rootTable, relationName);\n\t\tif (!resolved) return d; // No matching relation — leave as-is\n\n\t\treturn {\n\t\t\ttype: 'where',\n\t\t\toperator: 'exists',\n\t\t\ttargetTable: resolved.target,\n\t\t\trelationName,\n\t\t\t...(resolved.foreignKey && { foreignKey: resolved.foreignKey }),\n\t\t\t...(resolved.relationType && { relationType: resolved.relationType }),\n\t\t\tconditions: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'where',\n\t\t\t\t\tcolumn: targetColumn,\n\t\t\t\t\toperator: d.operator,\n\t\t\t\t\tvalue: d.value,\n\t\t\t\t\ttable: resolved.target,\n\t\t\t\t},\n\t\t\t],\n\t\t} as PlanDecision;\n\t});\n}\n\n/**\n * Extract EXISTS/NOT EXISTS subquery decisions from filter-strategy plan decisions.\n */\nexport function extractExistsDecisions(\n\tplan: PlanReport,\n\tmodel?: ModelIR,\n): SimplifiedPlanReport['decisions'] {\n\t// Find filter-strategy decisions with choice: 'exists', 'notExists', or 'join'\n\tconst filterDecisions = plan.decisions.filter(\n\t\t(d) =>\n\t\t\td.type === 'filter-strategy' &&\n\t\t\t(d.choice === 'exists' ||\n\t\t\t\td.choice === 'notExists' ||\n\t\t\t\td.choice === 'join'),\n\t);\n\n\tif (filterDecisions.length === 0) {\n\t\treturn [];\n\t}\n\n\t// Find all exists intents from the plan's where clause\n\t// Clone the array so we can consume (splice) matches without mutating the plan.\n\tconst existsIntents = plan.intent?.where\n\t\t? findExistsIntents(plan.intent.where)\n\t\t: [];\n\n\t// Convert to where decisions for the compiler\n\tconst results: PlanDecision[] = [];\n\n\tfor (const d of filterDecisions) {\n\t\tconst context = d.context;\n\t\t// Skip if target table is not defined\n\t\tif (!context.target) continue;\n\n\t\t// Find the matching intent to get nested conditions\n\t\t// Match by relation name or target table (planner may normalize relation names)\n\t\t// Note: relationFilter intents from NQL have relation as string[] (e.g., ['posts'])\n\t\t// We consume (splice) each matched intent so that duplicate exists() on the same\n\t\t// relation each get their own unique intent — prevents param duplication.\n\t\tconst matchIdx = existsIntents.findIndex((i) => {\n\t\t\tconst rel =\n\t\t\t\tArray.isArray(i.relation) && i.relation.length > 0\n\t\t\t\t\t? i.relation[0]\n\t\t\t\t\t: typeof i.relation === 'string'\n\t\t\t\t\t\t? i.relation\n\t\t\t\t\t\t: undefined;\n\t\t\treturn (\n\t\t\t\trel === context.relation ||\n\t\t\t\trel === context.target ||\n\t\t\t\trel === context.includeAlias\n\t\t\t);\n\t\t});\n\t\tconst matchingIntent = matchIdx >= 0 ? existsIntents[matchIdx] : undefined;\n\t\tif (matchIdx >= 0) existsIntents.splice(matchIdx, 1);\n\n\t\t// Build nested conditions with correct target table\n\t\tlet conditions: PlanDecision[] | undefined;\n\t\tif (matchingIntent?.where) {\n\t\t\t// Convert nested where using the CORRECT target table\n\t\t\tconst nestedDecisions = convertWhereToDecisions(\n\t\t\t\tmatchingIntent.where,\n\t\t\t\tcontext.target,\n\t\t\t);\n\t\t\tif (nestedDecisions.length > 0) {\n\t\t\t\tconditions = nestedDecisions;\n\t\t\t}\n\t\t}\n\n\t\t// Resolve FK from model relation if available\n\t\tconst foreignKey =\n\t\t\tmodel && context.relation\n\t\t\t\t? resolveRelation(\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tcontext.sourceTable || plan.rootTable,\n\t\t\t\t\t\tcontext.relation,\n\t\t\t\t\t)?.foreignKey\n\t\t\t\t: undefined;\n\n\t\t// Determine operator from intent kind and mode\n\t\t// - exists → exists\n\t\t// - notExists → notExists\n\t\t// - relationFilter + mode='none' → notExists\n\t\t// - relationFilter + mode='every' → every (special NOT EXISTS with inverted conditions)\n\t\t// - relationFilter + mode='some' (default) → exists\n\t\tlet operator: string = 'exists';\n\t\tif (matchingIntent?.kind === 'notExists') {\n\t\t\toperator = 'notExists';\n\t\t} else if (matchingIntent?.kind === 'relationFilter') {\n\t\t\tconst mode = (matchingIntent as ExistsIntent).mode ?? 'some';\n\t\t\tif (mode === 'none') operator = 'notExists';\n\t\t\telse if (mode === 'every') operator = 'every';\n\t\t}\n\n\t\t// Extract include declarations from the matching intent (JOIN inside subquery).\n\t\t// Convert the intent's include map to a Decision[] for the EXISTS handler.\n\t\tconst includeIntent = (\n\t\t\tmatchingIntent as Record<string, unknown> | undefined\n\t\t)?.include as Record<string, { join?: 'inner' | 'left' }> | undefined;\n\t\tconst includeDecisions: PlanDecision[] | undefined = includeIntent\n\t\t\t? Object.entries(includeIntent).map(([rel, opts]) => ({\n\t\t\t\t\ttype: 'existsInclude',\n\t\t\t\t\trelation: rel,\n\t\t\t\t\tjoinType: opts.join ?? 'inner',\n\t\t\t\t}))\n\t\t\t: undefined;\n\n\t\tconst decision: PlanDecision = {\n\t\t\ttype: 'where',\n\t\t\toperator,\n\t\t\ttargetTable: context.target,\n\t\t\t...(foreignKey && { foreignKey }),\n\t\t\t...(conditions && { conditions }),\n\t\t\t// Propagate planner's filter strategy choice to compiler\n\t\t\t...(d.choice === 'join' && { choice: 'join' }),\n\t\t\t// Pass relation name for alias (self-referential tables)\n\t\t\t...(context.relation && { relationName: context.relation }),\n\t\t\t// Pass include declarations (JOIN inside the EXISTS subquery)\n\t\t\t...(includeDecisions && { include: includeDecisions }),\n\t\t};\n\t\tresults.push(decision);\n\t}\n\n\treturn results;\n}\n\n/**\n * Extract ALL include decisions from include-strategy plan decisions.\n * Produces decisions with type 'includeStrategy' for all strategies:\n * - json_agg, subquery → tree-structured with children (like extractJsonAggDecisions)\n * - join → flat decisions with columns (like extractLeftJoinIncludeDecisions)\n * - lateral → tree-structured with children\n * - cte → flat decisions\n *\n * Each decision carries its `choice` field for the compiler to dispatch via handlers.\n */\nexport function extractAllIncludeDecisions(\n\tplan: PlanReport,\n\tdefaultPk: string = DEFAULT_PK_COLUMN,\n\tderiveFk: FkColumnDerivation = defaultFkDerivation,\n): SimplifiedPlanReport['decisions'] {\n\tconst includeDecisions = plan.decisions.filter(\n\t\t(d) => d.type === 'include-strategy',\n\t);\n\n\tif (includeDecisions.length === 0) return [];\n\n\t// Separate by strategy group\n\tconst treeStrategies = new Set(['json_agg', 'subquery', 'lateral']);\n\tconst treeDecisions: (PlanDecision & { intentPath?: string })[] = [];\n\tconst flatDecisions: PlanDecision[] = [];\n\n\tfor (const d of includeDecisions) {\n\t\tconst choice = d.choice as string;\n\t\tif (treeStrategies.has(choice)) {\n\t\t\t// Convert to tree-compatible decision (json_agg / lateral / subquery)\n\t\t\tconst converted = toIncludeDecision(d, choice, plan, defaultPk, deriveFk);\n\t\t\tif (converted) treeDecisions.push(converted);\n\t\t} else if (choice === 'join') {\n\t\t\t// Convert to flat join decision\n\t\t\tconst converted = toJoinIncludeDecision(d, plan, defaultPk, deriveFk);\n\t\t\tif (converted) flatDecisions.push(converted);\n\t\t} else if (choice === 'cte') {\n\t\t\t// CTE: produces WITH clause + LEFT JOIN to CTE\n\t\t\tconst converted = toIncludeDecision(d, choice, plan, defaultPk, deriveFk);\n\t\t\tif (converted) flatDecisions.push(converted);\n\t\t}\n\t}\n\n\t// Build tree for json_agg / lateral / subquery (using intentPath)\n\tconst builtTree = buildIncludeTree(treeDecisions);\n\n\treturn [...builtTree, ...flatDecisions];\n}\n\n/**\n * Convert a planner include-strategy decision to an includeStrategy decision.\n */\nfunction toIncludeDecision(\n\td: PlanReport['decisions'][number],\n\tchoice: string,\n\tplan: PlanReport,\n\tdefaultPk: string = DEFAULT_PK_COLUMN,\n\tderiveFk: FkColumnDerivation = defaultFkDerivation,\n): (PlanDecision & { intentPath?: string }) | undefined {\n\tconst context = d.context;\n\tconst relationName = resolveIncludeAlias(context);\n\tif (!context.target || !relationName) return undefined;\n\n\tconst foreignKey =\n\t\tderiveForeignKey(context, deriveFk, defaultPk) ?? defaultPk;\n\tconst relationType = context.relationType as\n\t\t| 'belongsTo'\n\t\t| 'hasMany'\n\t\t| 'hasOne'\n\t\t| undefined;\n\n\t// Map subquery to json_agg — PostgreSQL always supports json_agg,\n\t// so the subquery strategy is implemented via json_agg correlated subquery\n\tconst effectiveChoice = choice === 'subquery' ? 'json_agg' : choice;\n\n\t// Extract per-include limit from the original intent using intentPath\n\t// intentPath is e.g. \"include[0]\" or \"include[0].include[0]\" for nested\n\tconst includeIntent = resolveIncludeByPath(\n\t\tplan.intent?.include as\n\t\t\t| Array<{\n\t\t\t\t\trelation: string;\n\t\t\t\t\tlimit?: number;\n\t\t\t\t\tselect?: unknown;\n\t\t\t\t\twhere?: unknown;\n\t\t\t\t\tinclude?: unknown[];\n\t\t\t }>\n\t\t\t| undefined,\n\t\tcontext.intentPath,\n\t\trelationName,\n\t);\n\tconst limit = includeIntent?.limit;\n\n\treturn {\n\t\ttype: 'includeStrategy',\n\t\tchoice: effectiveChoice,\n\t\trelationName,\n\t\ttargetTable: context.target,\n\t\t...(context.sourceTable && { sourceTable: context.sourceTable }),\n\t\t...(relationType && { relationType }),\n\t\tforeignKey: Array.isArray(foreignKey) ? foreignKey[0] : foreignKey,\n\t\tparentKey: defaultPk,\n\t\t...(context.intentPath && { intentPath: context.intentPath }),\n\t\t...(limit != null && { limit }),\n\t};\n}\n\n/**\n * Convert a planner include-strategy decision with choice 'join' to an includeStrategy decision.\n */\nfunction toJoinIncludeDecision(\n\td: PlanReport['decisions'][number],\n\tplan: PlanReport,\n\tdefaultPk: string = DEFAULT_PK_COLUMN,\n\tderiveFk: FkColumnDerivation = defaultFkDerivation,\n): PlanDecision | undefined {\n\tconst context = d.context;\n\tconst relationName = context.relation ?? context.includeAlias;\n\tif (!context.target || !relationName) return undefined;\n\n\t// Find matching include intent to get column list and where conditions.\n\t// For 2-hop includes (intentPath: 'include[0].include[0]'), resolveIncludeByPath\n\t// traverses the nested include tree — a flat find() only reaches the top level and\n\t// would miss nested include intents that carry their own { where } conditions.\n\tconst intentPath = (context as unknown as Record<string, unknown>)\n\t\t?.intentPath as string | undefined;\n\tconst includeIntent = resolveIncludeByPath(\n\t\tplan.intent?.include as\n\t\t\t| Array<{\n\t\t\t\t\trelation: string;\n\t\t\t\t\tselect?: { type: string; fields?: readonly string[] };\n\t\t\t\t\twhere?: unknown;\n\t\t\t\t\tinclude?: unknown[];\n\t\t\t }>\n\t\t\t| undefined,\n\t\tintentPath,\n\t\trelationName as string,\n\t) as\n\t\t| {\n\t\t\t\trelation: string;\n\t\t\t\tselect?: { type: string; fields?: readonly string[] };\n\t\t\t\twhere?: unknown;\n\t\t }\n\t\t| undefined;\n\n\tlet columns: string[] = [defaultPk];\n\tif (includeIntent?.select?.type === 'fields' && includeIntent.select.fields) {\n\t\tconst fields = includeIntent.select.fields.filter((f) => f !== defaultPk);\n\t\tcolumns = [defaultPk, ...fields];\n\t}\n\n\tconst foreignKey =\n\t\tderiveForeignKey(context, deriveFk, defaultPk) ?? defaultPk;\n\tconst relationType = context.relationType as\n\t\t| 'belongsTo'\n\t\t| 'hasMany'\n\t\t| 'hasOne'\n\t\t| undefined;\n\n\t// Extract WHERE conditions from include intent.\n\t// When include({ join: 'inner', where: ... }) is used, the WHERE conditions\n\t// must be applied to the root query's WHERE clause (scoped to the joined\n\t// table's alias = relationName) to actually filter the root rows.\n\tlet conditions: PlanDecision[] | undefined;\n\tif (includeIntent?.where) {\n\t\tconst converted = convertWhereToDecisions(\n\t\t\tincludeIntent.where,\n\t\t\trelationName as string,\n\t\t);\n\t\tif (converted.length > 0) {\n\t\t\tconditions = converted;\n\t\t}\n\t}\n\n\t// Forward joinType from the planner decision so the join handler produces\n\t// the correct JOIN type (INNER vs LEFT).\n\tconst joinType = (d as unknown as Record<string, unknown>).joinType as\n\t\t| 'inner'\n\t\t| 'left'\n\t\t| undefined;\n\n\treturn {\n\t\ttype: 'includeStrategy',\n\t\tchoice: 'join',\n\t\trelationName,\n\t\ttargetTable: context.target,\n\t\t...(context.sourceTable && { sourceTable: context.sourceTable }),\n\t\t...(relationType && { relationType }),\n\t\tforeignKey: Array.isArray(foreignKey) ? foreignKey[0] : foreignKey,\n\t\tparentKey: defaultPk,\n\t\tcolumns,\n\t\t...(joinType && { joinType }),\n\t\t...(conditions && { conditions }),\n\t};\n}\n\n// ============================================================================\n// Relation alias resolution: snake_case ⇔ camelCase\n// ============================================================================\n\n/**\n * Convert a snake_case identifier to camelCase.\n * e.g. 'enclosing_symbol' → 'enclosingSymbol'\n */\nfunction snakeToCamel(s: string): string {\n\treturn s.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase());\n}\n\n/**\n * Synthesize join includeStrategy decisions for intent-based includes that the planner\n * failed to emit decisions for (e.g. when the include alias is camelCase but the model\n * relation is snake_case: `include('enclosingSymbol')` while model has `enclosing_symbol`).\n *\n * This is an adapter-level fallback: when the planner's `disambiguateRelation` cannot\n * match the camelCase alias to a registered relation, no `include-strategy` decision is\n * emitted. The adapter detects the gap and synthesizes the join decision directly from\n * the model by scanning `getRelationsFrom(sourceTable)` and matching\n * `snakeToCamel(rel.name) === alias`.\n *\n * Only synthesizes decisions for `{ join: 'inner' | 'left' }` includes that are not\n * already covered by an existing includeStrategy decision.\n */\nexport function synthesizeMissingJoinDecisions(\n\tplan: PlanReport,\n\tcoveredRelations: ReadonlySet<string>,\n\tmodel: ModelIR,\n\tdefaultPk: string = DEFAULT_PK_COLUMN,\n\tderiveFk: FkColumnDerivation = defaultFkDerivation,\n): SimplifiedPlanReport['decisions'] {\n\tconst includes = plan.intent?.include as\n\t\t| Array<{\n\t\t\t\trelation: string;\n\t\t\t\tjoin?: 'inner' | 'left';\n\t\t\t\tselect?: { type: string; fields?: readonly string[] };\n\t\t\t\twhere?: unknown;\n\t\t }>\n\t\t| undefined;\n\n\tif (!includes || includes.length === 0) return [];\n\n\tconst sourceTable = plan.rootTable;\n\tconst relationsFromSource = model.getRelationsFrom(sourceTable);\n\n\tconst synthesized: PlanDecision[] = [];\n\n\tfor (const inc of includes) {\n\t\tconst alias = inc.relation;\n\n\t\t// Only synthesize for explicit join: 'inner'|'left' includes\n\t\tif (inc.join !== 'inner' && inc.join !== 'left') continue;\n\n\t\t// Already covered by a planner-emitted decision\n\t\tif (coveredRelations.has(alias)) continue;\n\n\t\t// Try to find the relation in the model by:\n\t\t// 1. Direct name match (alias === rel.name)\n\t\t// 2. camelCase conversion (snakeToCamel(rel.name) === alias)\n\t\tconst rel = relationsFromSource.find(\n\t\t\t(r) => r.name === alias || snakeToCamel(r.name) === alias,\n\t\t);\n\t\tif (!rel) continue;\n\n\t\t// Derive FK from RelationIR\n\t\tconst rawFk = rel.foreignKey\n\t\t\t? Array.isArray(rel.foreignKey)\n\t\t\t\t? rel.foreignKey[0]\n\t\t\t\t: rel.foreignKey\n\t\t\t: deriveFk(\n\t\t\t\t\trel.type === 'belongsTo' ? rel.target : sourceTable,\n\t\t\t\t\tdefaultPk,\n\t\t\t\t);\n\n\t\t// Build column list (PK always included for NULL-detection)\n\t\tlet columns: string[] = [defaultPk];\n\t\tif (inc.select?.type === 'fields' && inc.select.fields) {\n\t\t\tconst extraFields = inc.select.fields.filter((f) => f !== defaultPk);\n\t\t\tcolumns = [defaultPk, ...extraFields];\n\t\t}\n\n\t\t// Build WHERE conditions from include intent\n\t\tlet conditions: PlanDecision[] | undefined;\n\t\tif (inc.where) {\n\t\t\tconst converted = convertWhereToDecisions(inc.where, alias);\n\t\t\tif (converted.length > 0) conditions = converted;\n\t\t}\n\n\t\tsynthesized.push({\n\t\t\ttype: 'includeStrategy',\n\t\t\tchoice: 'join',\n\t\t\trelationName: alias,\n\t\t\ttargetTable: rel.target,\n\t\t\tsourceTable,\n\t\t\t...(rel.type && {\n\t\t\t\trelationType: rel.type as 'belongsTo' | 'hasMany' | 'hasOne',\n\t\t\t}),\n\t\t\tforeignKey: Array.isArray(rawFk) ? rawFk[0] : rawFk,\n\t\t\tparentKey: defaultPk,\n\t\t\tcolumns,\n\t\t\tjoinType: inc.join,\n\t\t\t...(conditions && { conditions }),\n\t\t});\n\t}\n\n\treturn synthesized;\n}\n\n/**\n * Build tree structure from flat include decisions using intentPath.\n * Groups children under their parents for nested json_agg / lateral compilation.\n */\nfunction buildIncludeTree(\n\tallDecisions: (PlanDecision & { intentPath?: string })[],\n): PlanDecision[] {\n\tconst decisionsByPath = new Map<\n\t\tstring,\n\t\tPlanDecision & { intentPath?: string }\n\t>();\n\tfor (const d of allDecisions) {\n\t\tif (d.intentPath) decisionsByPath.set(d.intentPath, d);\n\t}\n\n\tfunction parentPath(path: string): string | undefined {\n\t\tconst lastDot = path.lastIndexOf('.include[');\n\t\treturn lastDot > 0 ? path.substring(0, lastDot) : undefined;\n\t}\n\n\tconst childrenMap = new Map<string, PlanDecision[]>();\n\tconst rootDecisions: PlanDecision[] = [];\n\n\tfor (const d of allDecisions) {\n\t\tconst pp = d.intentPath ? parentPath(d.intentPath) : undefined;\n\t\tif (pp && decisionsByPath.has(pp)) {\n\t\t\tconst siblings = childrenMap.get(pp) ?? [];\n\t\t\tsiblings.push(d);\n\t\t\tchildrenMap.set(pp, siblings);\n\t\t} else {\n\t\t\trootDecisions.push(d);\n\t\t}\n\t}\n\n\tfunction attachChildren(decision: PlanDecision): PlanDecision {\n\t\tconst path = decision.intentPath;\n\t\tconst children = path ? childrenMap.get(path) : undefined;\n\t\tif (!children || children.length === 0) return decision;\n\t\treturn {\n\t\t\t...decision,\n\t\t\tchildren: children.map(attachChildren),\n\t\t};\n\t}\n\n\treturn rootDecisions.map(attachChildren);\n}\n\n/**\n * Convert a planner include-strategy decision to a selectJsonAgg decision.\n */\nfunction toJsonAggDecision(\n\td: PlanReport['decisions'][number],\n\tdefaultPk: string = DEFAULT_PK_COLUMN,\n\tderiveFk: FkColumnDerivation = defaultFkDerivation,\n): PlanDecision | undefined {\n\tconst context = d.context;\n\tconst relationName = resolveIncludeAlias(context);\n\tif (!context.target || !relationName) return undefined;\n\n\tconst foreignKey =\n\t\tderiveForeignKey(context, deriveFk, defaultPk) ?? defaultPk;\n\tconst relationType = context.relationType as\n\t\t| 'belongsTo'\n\t\t| 'hasMany'\n\t\t| 'hasOne'\n\t\t| undefined;\n\n\treturn {\n\t\ttype: 'selectJsonAgg',\n\t\trelationName,\n\t\ttargetTable: context.target,\n\t\t...(context.sourceTable && { sourceTable: context.sourceTable }),\n\t\t...(relationType && { relationType }),\n\t\tforeignKey: Array.isArray(foreignKey) ? foreignKey[0] : foreignKey,\n\t\tparentKey: defaultPk,\n\t\t...(context.intentPath && { intentPath: context.intentPath }),\n\t};\n}\n\n/**\n * Extract JSON_AGG include decisions from include-strategy plan decisions.\n * Builds a tree structure for nested includes so the compiler can generate\n * nested json_agg subqueries (e.g., users → userRoles → role → ...).\n */\nexport function extractJsonAggDecisions(\n\tplan: PlanReport,\n\tdefaultPk: string = DEFAULT_PK_COLUMN,\n\tderiveFk: FkColumnDerivation = defaultFkDerivation,\n): SimplifiedPlanReport['decisions'] {\n\t// Find include-strategy decisions with choice: 'json_agg'\n\tconst jsonAggIncludeDecisions = plan.decisions.filter(\n\t\t(d) => d.type === 'include-strategy' && d.choice === 'json_agg',\n\t);\n\n\tif (jsonAggIncludeDecisions.length === 0) {\n\t\treturn [];\n\t}\n\n\t// Convert all to flat decisions with intentPath\n\tconst allDecisions: (PlanDecision & { intentPath?: string })[] = [];\n\tfor (const d of jsonAggIncludeDecisions) {\n\t\tconst decision = toJsonAggDecision(d, defaultPk, deriveFk);\n\t\tif (decision) allDecisions.push(decision);\n\t}\n\n\t// Build tree: group children under their parent using intentPath\n\t// Root level: intentPath matches /^include\\[\\d+\\]$/\n\t// Nested: intentPath matches /^include\\[\\d+\\](\\.include\\[\\d+\\])+$/\n\tconst decisionsByPath = new Map<string, PlanDecision>();\n\tfor (const d of allDecisions) {\n\t\tif (d.intentPath) decisionsByPath.set(d.intentPath, d);\n\t}\n\n\t// Find parent intentPath by removing the last .include[N] segment\n\tfunction parentPath(path: string): string | undefined {\n\t\tconst lastDot = path.lastIndexOf('.include[');\n\t\treturn lastDot > 0 ? path.substring(0, lastDot) : undefined;\n\t}\n\n\t// Collect children for each decision\n\tconst childrenMap = new Map<string, PlanDecision[]>();\n\tconst rootDecisions: PlanDecision[] = [];\n\n\tfor (const d of allDecisions) {\n\t\tconst pp = d.intentPath ? parentPath(d.intentPath) : undefined;\n\t\tif (pp && decisionsByPath.has(pp)) {\n\t\t\t// This is a nested include — attach to parent\n\t\t\tconst siblings = childrenMap.get(pp) ?? [];\n\t\t\tsiblings.push(d);\n\t\t\tchildrenMap.set(pp, siblings);\n\t\t} else {\n\t\t\t// Root-level include\n\t\t\trootDecisions.push(d);\n\t\t}\n\t}\n\n\t// Recursively attach children to build tree\n\tfunction attachChildren(decision: PlanDecision): PlanDecision {\n\t\tconst path = decision.intentPath;\n\t\tconst children = path ? childrenMap.get(path) : undefined;\n\t\tif (!children || children.length === 0) return decision;\n\t\treturn {\n\t\t\t...decision,\n\t\t\tchildren: children.map(attachChildren),\n\t\t};\n\t}\n\n\treturn rootDecisions.map(attachChildren);\n}\n\n/**\n * Extract LEFT JOIN include decisions from include-strategy plan decisions.\n */\nexport function extractLeftJoinIncludeDecisions(\n\tplan: PlanReport,\n\tdefaultPk: string = DEFAULT_PK_COLUMN,\n\tderiveFk: FkColumnDerivation = defaultFkDerivation,\n): SimplifiedPlanReport['decisions'] {\n\t// Find include-strategy decisions with choice: 'join' (to-one only)\n\tconst joinIncludeDecisions = plan.decisions.filter(\n\t\t(d) => d.type === 'include-strategy' && d.choice === 'join',\n\t);\n\n\tif (joinIncludeDecisions.length === 0) {\n\t\treturn [];\n\t}\n\n\tconst results: PlanDecision[] = [];\n\n\tfor (const d of joinIncludeDecisions) {\n\t\tconst context = d.context;\n\t\tconst relationName = context.relation ?? context.includeAlias;\n\t\tif (!context.target || !relationName) continue;\n\n\t\t// Find matching include intent to get column list\n\t\tconst includeIntent = (\n\t\t\tplan.intent?.include as\n\t\t\t\t| Array<{\n\t\t\t\t\t\trelation: string;\n\t\t\t\t\t\tselect?: { type: string; fields?: readonly string[] };\n\t\t\t\t }>\n\t\t\t\t| undefined\n\t\t)?.find(\n\t\t\t(i) => i.relation === relationName || i.relation === context.relation,\n\t\t);\n\n\t\t// Extract columns from include intent's select\n\t\t// PK is always included for NULL-detection (missing relation)\n\t\tlet columns: string[] = [defaultPk];\n\t\tif (\n\t\t\tincludeIntent?.select?.type === 'fields' &&\n\t\t\tincludeIntent.select.fields\n\t\t) {\n\t\t\tconst fields = includeIntent.select.fields.filter((f) => f !== defaultPk);\n\t\t\tcolumns = [defaultPk, ...fields];\n\t\t}\n\n\t\tconst foreignKey =\n\t\t\tderiveForeignKey(context, deriveFk, defaultPk) ?? defaultPk;\n\t\tconst relationType = context.relationType as\n\t\t\t| 'belongsTo'\n\t\t\t| 'hasMany'\n\t\t\t| 'hasOne'\n\t\t\t| undefined;\n\n\t\tresults.push({\n\t\t\ttype: 'selectLeftJoinInclude',\n\t\t\trelationName,\n\t\t\ttargetTable: context.target,\n\t\t\t...(relationType && { relationType }),\n\t\t\tforeignKey: Array.isArray(foreignKey) ? foreignKey[0] : foreignKey,\n\t\t\tparentKey: defaultPk,\n\t\t\tcolumns,\n\t\t});\n\t}\n\n\treturn results;\n}\n","/**\n * Recursive CTE and unnest-CTE compilation.\n * Extracted from PgsqlAdapter.compileRecursive(), compileCteQuery(),\n * buildUnnestCte(), and buildRecursiveAnchorWhere().\n *\n * @internal\n */\n\nimport type {\n\tCompiledQuery,\n\tCompileOptions,\n\tCteQueryIntent,\n\tModelIR,\n\tPlanReport,\n\tQueryIntent,\n\tRawCteIntent,\n\tRecursivePlanReport,\n\tSimpleCteIntent,\n\tUnnestCteIntent,\n} from '@dbsp/types';\nimport type { Node, SelectStmt } from '@pgsql/types';\nimport type { AdapterCompilerDeps } from './adapter-compiler-deps.js';\nimport { compileSelect } from './adapter-compiler-select.js';\nimport {\n\tbinaryExpr,\n\tcolumnRef,\n\tfuncCall,\n\tintegerNode,\n\tstringNode,\n} from './ast-helpers.js';\nimport { inferPgArrayType, stripArraySuffix } from './compiler-utils.js';\nimport { deparseQuoted } from './deparse.js';\nimport type { CompilerContext } from './handlers/index.js';\nimport { createCompilerState } from './handlers/index.js';\nimport { createTypeCastParamRef } from './param-ref.js';\nimport {\n\tmapComparisonOperator,\n\tvalueToNode,\n} from './plan-decision-extractor.js';\nimport {\n\tbuildRecursiveCte,\n\ttype RecursiveCteConfig,\n} from './recursive/index.js';\n\n// ============================================================================\n// compileRecursive\n// ============================================================================\n\n/**\n * Compile a recursive CTE plan to executable SQL.\n * Supports adjacency-list and edge-table traversal modes.\n * Extracted body of PgsqlAdapter.compileRecursive().\n */\nexport function compileRecursive(\n\treport: RecursivePlanReport,\n\t_model: ModelIR,\n\t_options: CompileOptions | undefined,\n\tdeps: AdapterCompilerDeps,\n): CompiledQuery {\n\t// schemaName precedence (options > adapter ctor) is resolved in PgsqlAdapter.buildCompileDeps; deps.schemaName is authoritative here\n\tconst schemaName = deps.schemaName;\n\tconst intent = report.intent;\n\tconst traversal = intent.traversal;\n\n\tconst trackPath = intent.track?.path !== undefined;\n\tconst trackDepth = intent.track?.depth !== undefined;\n\n\tlet config: RecursiveCteConfig;\n\n\tif (traversal.kind === 'edge-table') {\n\t\tconst table = traversal.nodeTable;\n\t\tconst pkColumn = traversal.nodeId;\n\t\tconst ctx: CompilerContext = {\n\t\t\tnaming: deps.naming,\n\t\t\trootTable: table,\n\t\t\t...(schemaName !== undefined && { schema: schemaName }),\n\t\t\tmaxRecursiveDepth: intent.maxDepth,\n\t\t};\n\n\t\t// Get columns to select\n\t\tconst startSelect = intent.start.select ?? [];\n\t\tconst nodeIdColumn =\n\t\t\tintent.start.nodeIdExpr.kind === 'column'\n\t\t\t\t? intent.start.nodeIdExpr.name\n\t\t\t\t: pkColumn;\n\t\tconst selectColumns = Array.from(new Set([nodeIdColumn, ...startSelect]));\n\n\t\t// Edge-table traversal: join through a junction table\n\t\tconst edgeFrom =\n\t\t\ttraversal.direction === 'in' ? traversal.edgeTo : traversal.edgeFrom;\n\t\tconst edgeTo =\n\t\t\ttraversal.direction === 'in' ? traversal.edgeFrom : traversal.edgeTo;\n\n\t\t// Build anchor WHERE from intent.start.where\n\t\tconst anchorWhere = intent.start.where\n\t\t\t? buildRecursiveAnchorWhere(intent.start.where, '__n', deps)\n\t\t\t: undefined;\n\n\t\tconst base: RecursiveCteConfig = {\n\t\t\tcteAlias: intent.cteName,\n\t\t\ttable,\n\t\t\tpkColumn,\n\t\t\tfkColumn: '', // unused in edge-table mode\n\t\t\touterAlias: 't0',\n\t\t\tisAncestors: false,\n\t\t\tmaxDepth: intent.maxDepth,\n\t\t\tselectColumns,\n\t\t\ttrackPath,\n\t\t\tusePg14Cycle: false,\n\t\t\tedgeTable: traversal.edgeTable,\n\t\t\tedgeFrom,\n\t\t\tedgeTo,\n\t\t\tctx,\n\t\t};\n\n\t\t// Add optional properties only when defined\n\t\tif (traversal.direction === 'both') {\n\t\t\tbase.bidirectionalStrategy =\n\t\t\t\ttraversal.edgeStorageHint === 'directed-only' ? 'union-all' : 'union';\n\t\t}\n\t\tif (anchorWhere) {\n\t\t\tbase.anchorWhere = anchorWhere;\n\t\t}\n\n\t\tconfig = base;\n\t} else if (traversal.kind === 'adjacency') {\n\t\tconst table = traversal.nodeTable;\n\t\tconst pkColumn = traversal.nodeId;\n\t\tconst ctx: CompilerContext = {\n\t\t\tnaming: deps.naming,\n\t\t\trootTable: table,\n\t\t\t...(schemaName !== undefined && { schema: schemaName }),\n\t\t\tmaxRecursiveDepth: intent.maxDepth,\n\t\t};\n\n\t\tconst startSelect = intent.start.select ?? [];\n\t\tconst nodeIdColumn =\n\t\t\tintent.start.nodeIdExpr.kind === 'column'\n\t\t\t\t? intent.start.nodeIdExpr.name\n\t\t\t\t: pkColumn;\n\t\tconst selectColumns = Array.from(new Set([nodeIdColumn, ...startSelect]));\n\n\t\t// Adjacency-list traversal: self-referencing FK\n\t\tconfig = {\n\t\t\tcteAlias: intent.cteName,\n\t\t\ttable,\n\t\t\tpkColumn,\n\t\t\tfkColumn: traversal.parentId,\n\t\t\touterAlias: 't0',\n\t\t\tisAncestors: traversal.direction === 'ancestors',\n\t\t\tmaxDepth: intent.maxDepth,\n\t\t\tselectColumns,\n\t\t\ttrackPath,\n\t\t\tusePg14Cycle: false,\n\t\t\tctx,\n\t\t};\n\t} else {\n\t\t// Exhaustive check: only 'custom' remains, which is reserved for P2\n\t\tconst _exhaustive: 'custom' = traversal.kind;\n\t\tthrow new Error(\n\t\t\t`PgsqlAdapter.compileRecursive: Unsupported traversal kind '${_exhaustive}'`,\n\t\t);\n\t}\n\n\t// Build the recursive CTE\n\tconst { cte, extraCtes } = buildRecursiveCte(config);\n\n\t// Build final target list (include __depth and __path when tracked)\n\tconst finalTargets: Node[] = config.selectColumns.map((col: string) => ({\n\t\tResTarget: {\n\t\t\tval: {\n\t\t\t\tColumnRef: {\n\t\t\t\t\tfields: [\n\t\t\t\t\t\t{ String: { sval: config.cteAlias } },\n\t\t\t\t\t\t{ String: { sval: deps.naming.toDatabase(col) } },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\tname: deps.naming.toDatabase(col),\n\t\t},\n\t}));\n\n\tif (trackDepth) {\n\t\tconst depthAlias = intent.track?.depth?.as ?? '__depth';\n\t\tfinalTargets.push({\n\t\t\tResTarget: {\n\t\t\t\tval: {\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: config.cteAlias } },\n\t\t\t\t\t\t\t{ String: { sval: '__depth' } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tname: depthAlias,\n\t\t\t},\n\t\t});\n\t}\n\n\tif (trackPath) {\n\t\tconst pathAlias = intent.track?.path?.as ?? '__path';\n\t\tfinalTargets.push({\n\t\t\tResTarget: {\n\t\t\t\tval: {\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: config.cteAlias } },\n\t\t\t\t\t\t\t{ String: { sval: '__path' } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tname: pathAlias,\n\t\t\t},\n\t\t});\n\t}\n\n\t// Assemble all CTEs (extra CTEs like __edges_bidir go first)\n\tconst ctes: Node[] = [];\n\tif (extraCtes) {\n\t\tctes.push(...extraCtes);\n\t}\n\tctes.push(cte);\n\n\t// Build the final SELECT that uses the CTE\n\tconst selectStmt: SelectStmt = {\n\t\ttargetList: finalTargets,\n\t\tfromClause: [\n\t\t\t{\n\t\t\t\tRangeVar: {\n\t\t\t\t\trelname: config.cteAlias,\n\t\t\t\t\tinh: true,\n\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\twithClause: {\n\t\t\tctes,\n\t\t\trecursive: true,\n\t\t},\n\t};\n\n\t// Deparse AST to SQL\n\tconst sql = deparseQuoted({ SelectStmt: selectStmt });\n\n\treturn {\n\t\tsql,\n\t\tparameters: [],\n\t};\n}\n\n// ============================================================================\n// compileCteQuery\n// ============================================================================\n\n/**\n * Compile a CTE query backed by unnest() arrays (BATCH-001 Block 5).\n *\n * Strategy: compile CTE nodes to SQL fragments, compile outer query\n * independently (parameters starting at $1), then renumber outer params\n * to start after CTE params and prepend WITH clause.\n *\n * Extracted body of PgsqlAdapter.compileCteQuery().\n */\nexport function compileCteQuery(\n\tintent: CteQueryIntent,\n\t_options: CompileOptions | undefined,\n\tdeps: AdapterCompilerDeps,\n): CompiledQuery {\n\t// schemaName precedence (options > adapter ctor) is resolved in PgsqlAdapter.buildCompileDeps; deps.schemaName is authoritative here\n\tconst schemaName = deps.schemaName;\n\tconst state = createCompilerState();\n\n\t// All parameters accumulated from all CTEs (in declaration order)\n\tconst allCteParams: unknown[] = [];\n\n\t// 1. Build CTE SQL fragments, accumulating parameters\n\tconst cteSqlFragments: string[] = [];\n\tlet isRecursive = false;\n\n\tfor (const cte of intent.ctes) {\n\t\tif (cte.kind === 'unnestCte') {\n\t\t\t// Unnest-backed CTE: builds an AST node, deparses it\n\t\t\tconst node = buildUnnestCte(cte, state, deps);\n\t\t\tallCteParams.push(...state.parameters.slice(allCteParams.length));\n\t\t\tcteSqlFragments.push(deparseQuoted(node));\n\t\t} else if (cte.kind === 'rawCte') {\n\t\t\t// Raw WITH RECURSIVE CTE: compile base + step independently\n\t\t\tisRecursive = true;\n\t\t\tconst { sql: cteSql, params: cteParams } = buildRawCte(\n\t\t\t\tcte,\n\t\t\t\tschemaName,\n\t\t\t\tdeps,\n\t\t\t);\n\t\t\tallCteParams.push(...cteParams);\n\t\t\tcteSqlFragments.push(cteSql);\n\t\t} else if (cte.kind === 'simpleCte') {\n\t\t\t// Simple named subquery CTE: compile inner query, wrap in ctename AS (...)\n\t\t\tconst innerCte = cte as SimpleCteIntent;\n\t\t\tconst innerPlanReport: PlanReport = {\n\t\t\t\trootTable: innerCte.query.from,\n\t\t\t\tdecisions: [],\n\t\t\t\twarnings: [],\n\t\t\t\tctes: [],\n\t\t\t\tintent: innerCte.query,\n\t\t\t\tmetadata: {\n\t\t\t\t\tplanningTimeMs: 0,\n\t\t\t\t\trelationsAnalyzed: 0,\n\t\t\t\t\tisAmbiguous: false,\n\t\t\t\t},\n\t\t\t};\n\t\t\tconst innerCompileOptions: CompileOptions =\n\t\t\t\tschemaName !== undefined ? { schemaName } : {};\n\t\t\tconst innerCompiled = compileSelect(\n\t\t\t\tinnerPlanReport,\n\t\t\t\tinnerCompileOptions,\n\t\t\t\tdeps,\n\t\t\t);\n\t\t\t// Renumber inner params to follow all previously accumulated CTE params\n\t\t\tconst currentParamOffset = allCteParams.length;\n\t\t\tconst renumberedInnerSql =\n\t\t\t\tcurrentParamOffset > 0\n\t\t\t\t\t? innerCompiled.sql.replace(\n\t\t\t\t\t\t\t/\\$([0-9]+)/g,\n\t\t\t\t\t\t\t(_: string, n: string) =>\n\t\t\t\t\t\t\t\t`$${parseInt(n, 10) + currentParamOffset}`,\n\t\t\t\t\t\t)\n\t\t\t\t\t: innerCompiled.sql;\n\t\t\tallCteParams.push(...innerCompiled.parameters);\n\t\t\tcteSqlFragments.push(`\"${innerCte.name}\" AS (${renumberedInnerSql})`);\n\t\t} else {\n\t\t\tconst kind = (cte as { kind: string }).kind;\n\t\t\tthrow new Error(\n\t\t\t\t`PgsqlAdapter.compileCteQuery: Unsupported CTE kind '${kind}'`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// 2. Compile outer query independently ($1, $2, ... relative to outer)\n\tconst outerCompileOptions: CompileOptions =\n\t\tschemaName !== undefined ? { schemaName } : {};\n\tconst outerPlanReport: PlanReport = {\n\t\trootTable: intent.query.from,\n\t\tdecisions: [],\n\t\twarnings: [],\n\t\tctes: [],\n\t\tintent: intent.query,\n\t\tmetadata: {\n\t\t\tplanningTimeMs: 0,\n\t\t\trelationsAnalyzed: 0,\n\t\t\tisAmbiguous: false,\n\t\t},\n\t};\n\tconst outerCompiled = compileSelect(\n\t\touterPlanReport,\n\t\touterCompileOptions,\n\t\tdeps,\n\t);\n\n\t// 3. Renumber outer SQL parameters to follow all CTE parameters.\n\t// Safety: the deparser always emits user values as $N parameters, never as inline string\n\t// literals — so the /\\$([0-9]+)/ regex cannot match user data embedded in quoted strings.\n\tconst cteParamCount = allCteParams.length;\n\tconst renumberedOuterSql =\n\t\tcteParamCount > 0\n\t\t\t? outerCompiled.sql.replace(\n\t\t\t\t\t/\\$([0-9]+)/g,\n\t\t\t\t\t(_: string, n: string) => `$${parseInt(n, 10) + cteParamCount}`,\n\t\t\t\t)\n\t\t\t: outerCompiled.sql;\n\n\t// 4. Build WITH [RECURSIVE] clause\n\tconst withClause = cteSqlFragments.join(', ');\n\tconst withKeyword = isRecursive ? 'WITH RECURSIVE' : 'WITH';\n\n\tconst sql =\n\t\twithClause.length > 0\n\t\t\t? `${withKeyword} ${withClause} ${renumberedOuterSql}`\n\t\t\t: renumberedOuterSql;\n\n\treturn {\n\t\tsql,\n\t\tparameters: [...allCteParams, ...outerCompiled.parameters],\n\t};\n}\n\n// ============================================================================\n// buildUnnestCte (internal)\n// ============================================================================\n\n/**\n * Build a CommonTableExpr AST node for an unnest-backed CTE.\n * Produces: CommonTableExpr { ctename: 'name', ctequery: SelectStmt {...} }\n * Extracted body of PgsqlAdapter.buildUnnestCte().\n */\nfunction buildUnnestCte(\n\tcte: UnnestCteIntent,\n\tstate: ReturnType<typeof createCompilerState>,\n\tdeps: AdapterCompilerDeps,\n): Node {\n\tconst columns = Object.keys(cte.columns);\n\tconst hasIndex = cte.indexColumn !== undefined;\n\tconst indexCol = cte.indexColumn ?? 'ordinality';\n\n\t// Build unnest arguments: CAST($N AS type[]) for each column\n\tconst unnestArgs: Node[] = columns.map((col) => {\n\t\tconst colArray = cte.columns[col] as unknown[];\n\t\tconst sampleValue = colArray.find((v) => v !== null && v !== undefined);\n\t\tconst pgArrayType = inferPgArrayType(col, undefined, sampleValue);\n\t\tconst pgBaseType = stripArraySuffix(pgArrayType);\n\n\t\tstate.parameters.push(colArray);\n\t\tstate.paramIndex++;\n\t\treturn createTypeCastParamRef(state.paramIndex, pgBaseType, true);\n\t});\n\n\t// All column alias names: col1, col2, ...[, ordinality]\n\tconst allAliasNames = [\n\t\t...columns.map((c) => deps.naming.toDatabase(c)),\n\t\t...(hasIndex ? ['ordinality'] : []),\n\t];\n\n\t// FROM unnest(args...) [WITH ORDINALITY] AS t(\"col1\", \"col2\"[, ordinality])\n\tconst rangeFunc: Node = {\n\t\tRangeFunction: {\n\t\t\tordinality: hasIndex,\n\t\t\tfunctions: [{ List: { items: [funcCall('unnest', unnestArgs)] } }],\n\t\t\talias: {\n\t\t\t\taliasname: 't',\n\t\t\t\tcolnames: allAliasNames.map((n) => stringNode(n)),\n\t\t\t},\n\t\t},\n\t};\n\n\t// SELECT targets: t.\"col1\", t.\"col2\"[, (t.ordinality - 1) AS \"idx\"]\n\tconst targets: Node[] = columns.map((col) => ({\n\t\tResTarget: {\n\t\t\tval: columnRef(col, 't', undefined, deps.naming),\n\t\t\tname: deps.naming.toDatabase(col),\n\t\t},\n\t}));\n\tif (hasIndex) {\n\t\ttargets.push({\n\t\t\tResTarget: {\n\t\t\t\tval: binaryExpr('-', columnRef('ordinality', 't'), integerNode(1)),\n\t\t\t\tname: indexCol,\n\t\t\t},\n\t\t});\n\t}\n\n\tconst cteSelectStmt: SelectStmt = {\n\t\ttargetList: targets,\n\t\tfromClause: [rangeFunc],\n\t};\n\n\treturn {\n\t\tCommonTableExpr: {\n\t\t\tctename: cte.name,\n\t\t\tctequery: { SelectStmt: cteSelectStmt },\n\t\t},\n\t};\n}\n\n/**\n * Build a \"name AS (base UNION [ALL] step)\" SQL fragment for a raw recursive CTE.\n *\n * Strategy:\n * 1. Compile base QueryIntent independently → base SQL + base params\n * 2. Compile step QueryIntent independently → step SQL + step params ($1-relative)\n * 3. Renumber step params to follow base params\n * 4. Return: `\"name\" AS (baseSql UNION [ALL] renumberedStepSql)` + all params\n *\n * The outer query params are renumbered separately by compileCteQuery().\n */\nfunction buildRawCte(\n\tcte: RawCteIntent,\n\tschemaName: string | undefined,\n\tdeps: AdapterCompilerDeps,\n): { sql: string; params: readonly unknown[] } {\n\tconst compileOptions: CompileOptions =\n\t\tschemaName !== undefined ? { schemaName } : {};\n\n\t// Compile base (anchor) query\n\tconst basePlanReport: PlanReport = {\n\t\trootTable: cte.base.from,\n\t\tdecisions: [],\n\t\twarnings: [],\n\t\tctes: [],\n\t\tintent: cte.base as QueryIntent,\n\t\tmetadata: { planningTimeMs: 0, relationsAnalyzed: 0, isAmbiguous: false },\n\t};\n\tconst baseCompiled = compileSelect(basePlanReport, compileOptions, deps);\n\n\t// Compile step (recursive) query\n\tconst stepPlanReport: PlanReport = {\n\t\trootTable: cte.step.from,\n\t\tdecisions: [],\n\t\twarnings: [],\n\t\tctes: [],\n\t\tintent: cte.step as QueryIntent,\n\t\tmetadata: { planningTimeMs: 0, relationsAnalyzed: 0, isAmbiguous: false },\n\t};\n\tconst stepCompiled = compileSelect(stepPlanReport, compileOptions, deps);\n\n\t// Renumber step params to follow base params.\n\t// Safety: the deparser always emits user values as $N parameters, never as inline string\n\t// literals — so the /\\$([0-9]+)/ regex cannot match user data embedded in quoted strings.\n\t// This would only be a risk if the deparser inlined literals like 'Price: $10', which it\n\t// does not do. The regex is therefore safe against the SQL it compiles from AST.\n\tconst baseParamCount = baseCompiled.parameters.length;\n\tconst renumberedStepSql =\n\t\tbaseParamCount > 0\n\t\t\t? stepCompiled.sql.replace(\n\t\t\t\t\t/\\$([0-9]+)/g,\n\t\t\t\t\t(_: string, n: string) => `$${parseInt(n, 10) + baseParamCount}`,\n\t\t\t\t)\n\t\t\t: stepCompiled.sql;\n\n\t// Inject depth guard: WHERE \"depthColumn\" < $N (or AND-ed with existing WHERE)\n\tconst allParams: unknown[] = [\n\t\t...baseCompiled.parameters,\n\t\t...stepCompiled.parameters,\n\t];\n\tlet finalStepSql = renumberedStepSql;\n\tif (cte.maxDepth !== undefined) {\n\t\tconst depthCol = `\"${(cte.depthColumn ?? 'depth').replace(/\"/g, '\"\"')}\"`;\n\t\tconst depthParamIndex = allParams.length + 1; // next $N\n\t\tallParams.push(cte.maxDepth);\n\t\t// Detect whether the step SQL already has a WHERE clause\n\t\tconst hasWhere = /\\bWHERE\\b/i.test(finalStepSql);\n\t\tfinalStepSql = hasWhere\n\t\t\t? `${finalStepSql} AND ${depthCol} < $${depthParamIndex}`\n\t\t\t: `${finalStepSql} WHERE ${depthCol} < $${depthParamIndex}`;\n\t}\n\n\tconst setOp = cte.unionAll ? 'UNION ALL' : 'UNION';\n\tconst cteName = `\"${cte.name.replace(/\"/g, '\"\"')}\"`;\n\tconst cteSql = `${cteName} AS (${baseCompiled.sql} ${setOp} ${finalStepSql})`;\n\n\treturn {\n\t\tsql: cteSql,\n\t\tparams: allParams,\n\t};\n}\n\n// ============================================================================\n// buildRecursiveAnchorWhere (internal)\n// ============================================================================\n\n/**\n * Build an anchor WHERE clause AST node from a WhereIntent.\n * Used for edge-table recursive CTE anchor queries.\n * Extracted body of PgsqlAdapter.buildRecursiveAnchorWhere().\n */\nfunction buildRecursiveAnchorWhere(\n\twhere: unknown,\n\ttableAlias: string,\n\tdeps: AdapterCompilerDeps,\n): Node {\n\tif (!where || typeof where !== 'object') {\n\t\treturn { A_Const: { boolval: { boolval: true } } };\n\t}\n\tconst w = where as Record<string, unknown>;\n\n\tswitch (w.kind) {\n\t\tcase 'comparison': {\n\t\t\tconst dbCol = deps.naming.toDatabase(w.field as string);\n\t\t\tconst left: Node = {\n\t\t\t\tColumnRef: {\n\t\t\t\t\tfields: [\n\t\t\t\t\t\t{ String: { sval: tableAlias } },\n\t\t\t\t\t\t{ String: { sval: dbCol } },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t};\n\t\t\tconst op = mapComparisonOperator(w.operator as string);\n\t\t\tconst right: Node = valueToNode(w.value);\n\t\t\treturn {\n\t\t\t\tA_Expr: {\n\t\t\t\t\tkind: 'AEXPR_OP',\n\t\t\t\t\tname: [{ String: { sval: op } }],\n\t\t\t\t\tlexpr: left,\n\t\t\t\t\trexpr: right,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tcase 'and': {\n\t\t\tconst conditions = (w.conditions as unknown[]).map((c) =>\n\t\t\t\tbuildRecursiveAnchorWhere(c, tableAlias, deps),\n\t\t\t);\n\t\t\tif (conditions.length === 1) return conditions[0]!;\n\t\t\treturn { BoolExpr: { boolop: 'AND_EXPR', args: conditions } };\n\t\t}\n\t\tcase 'or': {\n\t\t\tconst conditions = (w.conditions as unknown[]).map((c) =>\n\t\t\t\tbuildRecursiveAnchorWhere(c, tableAlias, deps),\n\t\t\t);\n\t\t\tif (conditions.length === 1) return conditions[0]!;\n\t\t\treturn { BoolExpr: { boolop: 'OR_EXPR', args: conditions } };\n\t\t}\n\t\tdefault:\n\t\t\treturn { A_Const: { boolval: { boolval: true } } };\n\t}\n}\n","/**\n * WITH RECURSIVE CTE Compiler\n *\n * Compiles recursive CTEs for hierarchical data traversal.\n * Supports:\n * - Upward traversal (ancestors, parent chain)\n * - Downward traversal (descendants, children tree)\n * - Path tracking\n * - Cycle detection\n * - Depth limiting\n */\n\nimport type { CommonTableExpr, Node, SelectStmt } from '@pgsql/types';\nimport {\n\tbinaryExpr,\n\tcoalesce,\n\teqExpr,\n\tfuncCall,\n\tintegerNode,\n\tstringNode,\n\ttypeCast,\n} from '../ast-helpers.js';\nimport type { CompilerContext } from '../handlers/types.js';\nimport {\n\tbuildCycleDetection,\n\tbuildPg14CycleClause,\n} from './cycle-detection.js';\nimport { appendPathColumn, buildPathColumn } from './path-tracking.js';\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\n/**\n * Configuration for recursive CTE compilation\n */\nexport interface RecursiveCteConfig {\n\t/** Unique CTE name (e.g., '__rc_0') */\n\tcteAlias: string;\n\t/** Table to traverse */\n\ttable: string;\n\t/** Primary key column */\n\tpkColumn: string;\n\t/** Foreign key column for self-reference (adjacency mode only) */\n\tfkColumn: string;\n\t/** Outer query alias to correlate with */\n\touterAlias: string;\n\t/** true = traverse up (ancestors), false = traverse down (descendants) */\n\tisAncestors: boolean;\n\t/** Maximum recursion depth (default: 100) */\n\tmaxDepth: number;\n\t/** Column(s) to select from each row */\n\tselectColumns: string[];\n\t/** Whether to track traversal path */\n\ttrackPath?: boolean;\n\t/** Whether to use PG14+ CYCLE clause (vs __visited array) */\n\tusePg14Cycle?: boolean;\n\t/** Compiler context */\n\tctx: CompilerContext;\n\n\t// Edge-table mode (optional — when set, uses edge-table traversal)\n\t/** Edge table name (e.g., \"role_edges\") */\n\tedgeTable?: string;\n\t/** Source column in edge table (e.g., \"parent_role_id\") */\n\tedgeFrom?: string;\n\t/** Target column in edge table (e.g., \"child_role_id\") */\n\tedgeTo?: string;\n\t/** Bidirectional strategy: 'union' (safe, dedup) or 'union-all' (no dedup) */\n\tbidirectionalStrategy?: 'union' | 'union-all';\n\n\t// Anchor filter (for edge-table mode — WHERE on anchor node)\n\t/** Anchor WHERE clause node (pre-built AST) */\n\tanchorWhere?: Node;\n}\n\n// ============================================================================\n// CTE Builder\n// ============================================================================\n\n/**\n * Build a complete WITH RECURSIVE CTE for hierarchical traversal.\n *\n * Structure:\n * ```sql\n * WITH RECURSIVE cteAlias AS (\n * -- Anchor: entry point(s)\n * SELECT cols, 1 AS __depth, ARRAY[pk] AS __visited [, ARRAY[pk::text] AS __path]\n * FROM table t\n * WHERE t.pk = outer.fk (ancestors) OR t.fk = outer.pk (descendants)\n *\n * UNION ALL\n *\n * -- Recursive step\n * SELECT cols, __depth + 1, __visited || pk [, __path || pk::text]\n * FROM cteAlias\n * INNER JOIN table t ON ...\n * WHERE __depth < maxDepth AND pk <> ALL(__visited)\n * )\n * [CYCLE pk SET is_cycle USING path] -- PG14+ only\n * SELECT ... FROM cteAlias\n * ```\n */\nexport function buildRecursiveCte(config: RecursiveCteConfig): {\n\tcte: Node;\n\tcteSelect: Node;\n\t/** Additional CTEs needed (e.g., __edges_bidir for bidirectional) */\n\textraCtes?: Node[];\n} {\n\t// Delegate to edge-table builder if edge-table mode\n\tif (config.edgeTable) {\n\t\treturn buildEdgeTableRecursiveCte(config);\n\t}\n\n\tconst {\n\t\tcteAlias,\n\t\ttable,\n\t\tpkColumn,\n\t\tfkColumn,\n\t\touterAlias,\n\t\tisAncestors,\n\t\tmaxDepth,\n\t\tselectColumns,\n\t\ttrackPath = false,\n\t\tusePg14Cycle = false,\n\t\tctx,\n\t} = config;\n\n\tconst naming = ctx.naming;\n\tconst dbTable = naming.toDatabase(table);\n\tconst dbPk = naming.toDatabase(pkColumn);\n\tconst dbFk = naming.toDatabase(fkColumn);\n\tconst dbOuter = naming.toDatabase(outerAlias);\n\tconst innerAlias = '__n';\n\n\t// Build anchor target list\n\tconst anchorTargets: Node[] = buildTargetList(\n\t\tselectColumns,\n\t\tinnerAlias,\n\t\tctx,\n\t\t{ isAnchor: true, trackPath, pkColumn: dbPk, usePg14Cycle },\n\t);\n\n\t// Build anchor WHERE clause\n\tconst anchorWhere = buildAnchorWhere(\n\t\tinnerAlias,\n\t\tdbOuter,\n\t\tdbPk,\n\t\tdbFk,\n\t\tisAncestors,\n\t);\n\n\t// Build anchor SELECT\n\tconst anchorSelect: SelectStmt = {\n\t\ttargetList: anchorTargets,\n\t\tfromClause: [\n\t\t\t{\n\t\t\t\tRangeVar: {\n\t\t\t\t\trelname: dbTable,\n\t\t\t\t\t...(ctx.schema && { schemaname: ctx.schema }),\n\t\t\t\t\tinh: true,\n\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t\talias: { aliasname: innerAlias },\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\twhereClause: anchorWhere,\n\t};\n\n\t// Build recursive target list\n\tconst recursiveTargets: Node[] = buildTargetList(\n\t\tselectColumns,\n\t\tinnerAlias,\n\t\tctx,\n\t\t{ isAnchor: false, trackPath, pkColumn: dbPk, cteAlias, usePg14Cycle },\n\t);\n\n\t// Build recursive WHERE clause (depth limit + cycle detection)\n\tconst recursiveWhere = buildRecursiveWhere(\n\t\tcteAlias,\n\t\tinnerAlias,\n\t\tdbPk,\n\t\tmaxDepth,\n\t\tusePg14Cycle,\n\t);\n\n\t// Build recursive JOIN condition\n\tconst recursiveJoin = buildRecursiveJoin(\n\t\tcteAlias,\n\t\tinnerAlias,\n\t\tdbTable,\n\t\tdbPk,\n\t\tdbFk,\n\t\tisAncestors,\n\t\tctx,\n\t);\n\n\t// Build recursive SELECT\n\tconst recursiveSelect: SelectStmt = {\n\t\ttargetList: recursiveTargets,\n\t\tfromClause: [\n\t\t\t{\n\t\t\t\tRangeVar: {\n\t\t\t\t\trelname: cteAlias,\n\t\t\t\t\tinh: true,\n\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t},\n\t\t\t},\n\t\t\trecursiveJoin,\n\t\t],\n\t\twhereClause: recursiveWhere,\n\t};\n\n\t// Build UNION ALL\n\tconst unionSelect: Node = {\n\t\tSelectStmt: {\n\t\t\top: 'SETOP_UNION',\n\t\t\tall: true,\n\t\t\tlarg: anchorSelect,\n\t\t\trarg: recursiveSelect,\n\t\t},\n\t};\n\n\t// Build CTE\n\tconst cte: CommonTableExpr = {\n\t\tctename: cteAlias,\n\t\tctequery: unionSelect,\n\t\tcterecursive: true,\n\t};\n\n\t// Attach PG14 CYCLE clause if enabled\n\tif (usePg14Cycle) {\n\t\tconst cycleNode = buildPg14CycleClause(dbPk);\n\t\tif (cycleNode && 'CTECycleClause' in cycleNode) {\n\t\t\tcte.cycle_clause = cycleNode.CTECycleClause;\n\t\t}\n\t}\n\n\treturn {\n\t\tcte: { CommonTableExpr: cte },\n\t\tcteSelect: unionSelect,\n\t};\n}\n\n// ============================================================================\n// Target List Builders\n// ============================================================================\n\n/**\n * Build the target list for anchor or recursive SELECT\n */\nfunction buildTargetList(\n\tcolumns: string[],\n\talias: string,\n\tctx: CompilerContext,\n\toptions: {\n\t\tisAnchor: boolean;\n\t\ttrackPath: boolean;\n\t\tpkColumn: string;\n\t\tcteAlias?: string;\n\t\tusePg14Cycle?: boolean;\n\t},\n): Node[] {\n\tconst targets: Node[] = [];\n\n\t// Add requested columns\n\tfor (const col of columns) {\n\t\tconst dbCol = ctx.naming.toDatabase(col);\n\t\ttargets.push({\n\t\t\tResTarget: {\n\t\t\t\tval: {\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [{ String: { sval: alias } }, { String: { sval: dbCol } }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tname: dbCol,\n\t\t\t},\n\t\t});\n\t}\n\n\t// Add __depth\n\tif (options.isAnchor) {\n\t\ttargets.push({\n\t\t\tResTarget: {\n\t\t\t\tval: integerNode(1),\n\t\t\t\tname: '__depth',\n\t\t\t},\n\t\t});\n\t} else if (options.cteAlias) {\n\t\ttargets.push({\n\t\t\tResTarget: {\n\t\t\t\tval: binaryExpr(\n\t\t\t\t\t'+',\n\t\t\t\t\t{\n\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t{ String: { sval: options.cteAlias } },\n\t\t\t\t\t\t\t\t{ String: { sval: '__depth' } },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tintegerNode(1),\n\t\t\t\t),\n\t\t\t\tname: '__depth',\n\t\t\t},\n\t\t});\n\t}\n\n\t// Add __visited for cycle detection (skipped when using PG14 CYCLE clause)\n\tif (!options.usePg14Cycle) {\n\t\ttargets.push(\n\t\t\tbuildCycleDetection(\n\t\t\t\talias,\n\t\t\t\toptions.pkColumn,\n\t\t\t\toptions.isAnchor,\n\t\t\t\toptions.cteAlias,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Add __path if tracking\n\tif (options.trackPath) {\n\t\tif (options.isAnchor) {\n\t\t\ttargets.push(buildPathColumn(alias, options.pkColumn));\n\t\t} else if (options.cteAlias) {\n\t\t\ttargets.push(appendPathColumn(options.cteAlias, alias, options.pkColumn));\n\t\t}\n\t}\n\n\treturn targets;\n}\n\n// ============================================================================\n// WHERE Clause Builders\n// ============================================================================\n\n/**\n * Build anchor WHERE clause\n */\nfunction buildAnchorWhere(\n\tinnerAlias: string,\n\touterAlias: string,\n\tpkColumn: string,\n\tfkColumn: string,\n\tisAncestors: boolean,\n): Node {\n\tif (isAncestors) {\n\t\t// Ancestors: inner.pk = outer.fk (start from parent)\n\t\treturn eqExpr(\n\t\t\t{\n\t\t\t\tColumnRef: {\n\t\t\t\t\tfields: [\n\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t{ String: { sval: pkColumn } },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tColumnRef: {\n\t\t\t\t\tfields: [\n\t\t\t\t\t\t{ String: { sval: outerAlias } },\n\t\t\t\t\t\t{ String: { sval: fkColumn } },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t} else {\n\t\t// Descendants: inner.fk = outer.pk (start from children)\n\t\treturn eqExpr(\n\t\t\t{\n\t\t\t\tColumnRef: {\n\t\t\t\t\tfields: [\n\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t{ String: { sval: fkColumn } },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tColumnRef: {\n\t\t\t\t\tfields: [\n\t\t\t\t\t\t{ String: { sval: outerAlias } },\n\t\t\t\t\t\t{ String: { sval: pkColumn } },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}\n}\n\n/**\n * Build recursive WHERE clause with depth limit and cycle check\n */\nfunction buildRecursiveWhere(\n\tcteAlias: string,\n\tinnerAlias: string,\n\tpkColumn: string,\n\tmaxDepth: number,\n\tusePg14Cycle: boolean,\n): Node {\n\tconst conditions: Node[] = [\n\t\t// __depth < maxDepth\n\t\tbinaryExpr(\n\t\t\t'<',\n\t\t\t{\n\t\t\t\tColumnRef: {\n\t\t\t\t\tfields: [\n\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t{ String: { sval: '__depth' } },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\tintegerNode(maxDepth),\n\t\t),\n\t];\n\n\t// Add cycle check unless using PG14 CYCLE clause\n\tif (!usePg14Cycle) {\n\t\tconditions.push({\n\t\t\tA_Expr: {\n\t\t\t\tkind: 'AEXPR_OP_ALL',\n\t\t\t\tname: [{ String: { sval: '<>' } }],\n\t\t\t\tlexpr: {\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t\t{ String: { sval: pkColumn } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\trexpr: {\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t\t{ String: { sval: '__visited' } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\t}\n\n\treturn {\n\t\tBoolExpr: {\n\t\t\tboolop: 'AND_EXPR',\n\t\t\targs: conditions,\n\t\t},\n\t};\n}\n\n// ============================================================================\n// JOIN Builder\n// ============================================================================\n\n/**\n * Build the JOIN for recursive step\n */\nfunction buildRecursiveJoin(\n\tcteAlias: string,\n\tinnerAlias: string,\n\tdbTable: string,\n\tpkColumn: string,\n\tfkColumn: string,\n\tisAncestors: boolean,\n\tctx: CompilerContext,\n): Node {\n\tconst joinCondition = isAncestors\n\t\t? // Ancestors: inner.pk = cte.fk (traverse up)\n\t\t\teqExpr(\n\t\t\t\t{\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t\t{ String: { sval: pkColumn } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t\t{ String: { sval: fkColumn } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t)\n\t\t: // Descendants: inner.fk = cte.pk (traverse down)\n\t\t\teqExpr(\n\t\t\t\t{\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t\t{ String: { sval: fkColumn } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t\t{ String: { sval: pkColumn } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\treturn {\n\t\tJoinExpr: {\n\t\t\tjointype: 'JOIN_INNER',\n\t\t\tlarg: {\n\t\t\t\tRangeVar: {\n\t\t\t\t\trelname: cteAlias,\n\t\t\t\t\tinh: true,\n\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t},\n\t\t\t},\n\t\t\trarg: {\n\t\t\t\tRangeVar: {\n\t\t\t\t\trelname: dbTable,\n\t\t\t\t\t...(ctx.schema && { schemaname: ctx.schema }),\n\t\t\t\t\tinh: true,\n\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t\talias: { aliasname: innerAlias },\n\t\t\t\t},\n\t\t\t},\n\t\t\tquals: joinCondition,\n\t\t},\n\t};\n}\n\n// ============================================================================\n// Edge-Table CTE Builder\n// ============================================================================\n\n/**\n * Build a recursive CTE that traverses through an edge (junction) table.\n *\n * Edge-table (direction: out):\n * ```sql\n * WITH RECURSIVE cte AS (\n * SELECT n.cols, 1 AS __depth, ARRAY[n.id] AS __visited\n * FROM nodeTable n WHERE <anchor>\n * UNION ALL\n * SELECT n.cols, __depth+1, __visited || n.id\n * FROM cte\n * INNER JOIN edgeTable e ON e.edgeFrom = cte.id\n * INNER JOIN nodeTable n ON n.id = e.edgeTo\n * WHERE __depth < maxDepth AND n.id <> ALL(__visited)\n * )\n * ```\n *\n * Bidirectional (direction: both) prepends a `__edges_bidir` CTE:\n * ```sql\n * WITH RECURSIVE\n * __edges_bidir AS (\n * SELECT edgeFrom AS from_id, edgeTo AS to_id FROM edgeTable\n * UNION [ALL]\n * SELECT edgeTo AS from_id, edgeFrom AS to_id FROM edgeTable\n * ),\n * cte AS (... INNER JOIN __edges_bidir e ON e.from_id = cte.id ...)\n * ```\n */\nfunction buildEdgeTableRecursiveCte(config: RecursiveCteConfig): {\n\tcte: Node;\n\tcteSelect: Node;\n\textraCtes?: Node[];\n} {\n\tconst {\n\t\tcteAlias,\n\t\ttable,\n\t\tpkColumn,\n\t\tedgeTable,\n\t\tedgeFrom,\n\t\tedgeTo,\n\t\tmaxDepth,\n\t\tselectColumns,\n\t\ttrackPath = false,\n\t\tusePg14Cycle = false,\n\t\tbidirectionalStrategy,\n\t\tanchorWhere: externalAnchorWhere,\n\t\tctx,\n\t} = config;\n\n\tif (!edgeTable || !edgeFrom || !edgeTo) {\n\t\tthrow new Error(\n\t\t\t'edgeTable, edgeFrom, and edgeTo are required for edge-table traversal',\n\t\t);\n\t}\n\n\tconst naming = ctx.naming;\n\tconst dbTable = naming.toDatabase(table);\n\tconst dbPk = naming.toDatabase(pkColumn);\n\tconst dbEdgeTable = naming.toDatabase(edgeTable);\n\tconst dbEdgeFrom = naming.toDatabase(edgeFrom);\n\tconst dbEdgeTo = naming.toDatabase(edgeTo);\n\tconst innerAlias = '__n';\n\tconst edgeAlias = '__e';\n\tconst isBidirectional = bidirectionalStrategy !== undefined;\n\tconst bidirCteAlias = '__edges_bidir';\n\n\t// ── Anchor SELECT ───────────────────────────────────────────────────────\n\n\tconst anchorTargets: Node[] = buildTargetList(\n\t\tselectColumns,\n\t\tinnerAlias,\n\t\tctx,\n\t\t{ isAnchor: true, trackPath, pkColumn: dbPk, usePg14Cycle },\n\t);\n\n\t// Anchor WHERE: use external filter (from intent.start.where compilation)\n\t// or fall back to a trivial TRUE (should not happen in practice)\n\tconst anchorWhere: Node = externalAnchorWhere ?? {\n\t\tA_Const: { boolval: { boolval: true } },\n\t};\n\n\tconst anchorSelect: SelectStmt = {\n\t\ttargetList: anchorTargets,\n\t\tfromClause: [\n\t\t\t{\n\t\t\t\tRangeVar: {\n\t\t\t\t\trelname: dbTable,\n\t\t\t\t\t...(ctx.schema && { schemaname: ctx.schema }),\n\t\t\t\t\tinh: true,\n\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t\talias: { aliasname: innerAlias },\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\twhereClause: anchorWhere,\n\t};\n\n\t// ── Recursive SELECT ────────────────────────────────────────────────────\n\n\tconst recursiveTargets: Node[] = buildTargetList(\n\t\tselectColumns,\n\t\tinnerAlias,\n\t\tctx,\n\t\t{ isAnchor: false, trackPath, pkColumn: dbPk, cteAlias, usePg14Cycle },\n\t);\n\n\tconst recursiveWhere = buildRecursiveWhere(\n\t\tcteAlias,\n\t\tinnerAlias,\n\t\tdbPk,\n\t\tmaxDepth,\n\t\tusePg14Cycle,\n\t);\n\n\t// FROM cte JOIN edge ON edge.from = cte.pk JOIN node ON node.pk = edge.to\n\tconst edgeJoinSource = isBidirectional ? bidirCteAlias : dbEdgeTable;\n\tconst edgeJoinFromCol = isBidirectional ? 'from_id' : dbEdgeFrom;\n\tconst edgeJoinToCol = isBidirectional ? 'to_id' : dbEdgeTo;\n\n\t// Build: cte JOIN edgeTable e ON e.edgeFrom = cte.pk\n\tconst cteToEdgeJoin: Node = {\n\t\tJoinExpr: {\n\t\t\tjointype: 'JOIN_INNER',\n\t\t\tlarg: {\n\t\t\t\tRangeVar: {\n\t\t\t\t\trelname: cteAlias,\n\t\t\t\t\tinh: true,\n\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t},\n\t\t\t},\n\t\t\trarg: {\n\t\t\t\tRangeVar: {\n\t\t\t\t\trelname: edgeJoinSource,\n\t\t\t\t\t...(!isBidirectional && ctx.schema && { schemaname: ctx.schema }),\n\t\t\t\t\tinh: true,\n\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t\talias: { aliasname: edgeAlias },\n\t\t\t\t},\n\t\t\t},\n\t\t\tquals: eqExpr(\n\t\t\t\t{\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: edgeAlias } },\n\t\t\t\t\t\t\t{ String: { sval: edgeJoinFromCol } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t\t{ String: { sval: dbPk } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t),\n\t\t},\n\t};\n\n\t// Build: (cte JOIN edge) JOIN nodeTable n ON n.pk = e.edgeTo\n\tconst fullRecursiveJoin: Node = {\n\t\tJoinExpr: {\n\t\t\tjointype: 'JOIN_INNER',\n\t\t\tlarg: cteToEdgeJoin,\n\t\t\trarg: {\n\t\t\t\tRangeVar: {\n\t\t\t\t\trelname: dbTable,\n\t\t\t\t\t...(ctx.schema && { schemaname: ctx.schema }),\n\t\t\t\t\tinh: true,\n\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t\talias: { aliasname: innerAlias },\n\t\t\t\t},\n\t\t\t},\n\t\t\tquals: eqExpr(\n\t\t\t\t{\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t\t{ String: { sval: dbPk } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: edgeAlias } },\n\t\t\t\t\t\t\t{ String: { sval: edgeJoinToCol } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t),\n\t\t},\n\t};\n\n\tconst recursiveSelect: SelectStmt = {\n\t\ttargetList: recursiveTargets,\n\t\tfromClause: [fullRecursiveJoin],\n\t\twhereClause: recursiveWhere,\n\t};\n\n\t// ── UNION ALL ───────────────────────────────────────────────────────────\n\n\tconst unionSelect: Node = {\n\t\tSelectStmt: {\n\t\t\top: 'SETOP_UNION',\n\t\t\tall: true,\n\t\t\tlarg: anchorSelect,\n\t\t\trarg: recursiveSelect,\n\t\t},\n\t};\n\n\tconst cte: CommonTableExpr = {\n\t\tctename: cteAlias,\n\t\tctequery: unionSelect,\n\t\tcterecursive: true,\n\t};\n\n\t// Attach PG14 CYCLE clause if enabled\n\tif (usePg14Cycle) {\n\t\tconst cycleNode = buildPg14CycleClause(dbPk);\n\t\tif (cycleNode && 'CTECycleClause' in cycleNode) {\n\t\t\tcte.cycle_clause = cycleNode.CTECycleClause;\n\t\t}\n\t}\n\n\t// ── Bidirectional __edges_bidir CTE ─────────────────────────────────────\n\n\tconst extraCtes: Node[] = [];\n\n\tif (isBidirectional) {\n\t\tconst useUnionAll = bidirectionalStrategy === 'union-all';\n\n\t\t// SELECT edgeFrom AS from_id, edgeTo AS to_id FROM edgeTable\n\t\tconst forwardSelect: SelectStmt = {\n\t\t\ttargetList: [\n\t\t\t\t{\n\t\t\t\t\tResTarget: {\n\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\tfields: [{ String: { sval: dbEdgeFrom } }],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tname: 'from_id',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tResTarget: {\n\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\tfields: [{ String: { sval: dbEdgeTo } }],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tname: 'to_id',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t\tfromClause: [\n\t\t\t\t{\n\t\t\t\t\tRangeVar: {\n\t\t\t\t\t\trelname: dbEdgeTable,\n\t\t\t\t\t\t...(ctx.schema && { schemaname: ctx.schema }),\n\t\t\t\t\t\tinh: true,\n\t\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\n\t\t// SELECT edgeTo AS from_id, edgeFrom AS to_id FROM edgeTable (reversed)\n\t\tconst reverseSelect: SelectStmt = {\n\t\t\ttargetList: [\n\t\t\t\t{\n\t\t\t\t\tResTarget: {\n\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\tfields: [{ String: { sval: dbEdgeTo } }],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tname: 'from_id',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tResTarget: {\n\t\t\t\t\t\tval: {\n\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\tfields: [{ String: { sval: dbEdgeFrom } }],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tname: 'to_id',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t\tfromClause: [\n\t\t\t\t{\n\t\t\t\t\tRangeVar: {\n\t\t\t\t\t\trelname: dbEdgeTable,\n\t\t\t\t\t\t...(ctx.schema && { schemaname: ctx.schema }),\n\t\t\t\t\t\tinh: true,\n\t\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\n\t\tconst bidirUnion: Node = {\n\t\t\tSelectStmt: {\n\t\t\t\top: 'SETOP_UNION',\n\t\t\t\tall: useUnionAll,\n\t\t\t\tlarg: forwardSelect,\n\t\t\t\trarg: reverseSelect,\n\t\t\t},\n\t\t};\n\n\t\tconst bidirCte: CommonTableExpr = {\n\t\t\tctename: bidirCteAlias,\n\t\t\tctequery: bidirUnion,\n\t\t\tcterecursive: false,\n\t\t};\n\n\t\textraCtes.push({ CommonTableExpr: bidirCte });\n\t}\n\n\tconst result: { cte: Node; cteSelect: Node; extraCtes?: Node[] } = {\n\t\tcte: { CommonTableExpr: cte },\n\t\tcteSelect: unionSelect,\n\t};\n\tif (extraCtes.length > 0) {\n\t\tresult.extraCtes = extraCtes;\n\t}\n\treturn result;\n}\n\n// ============================================================================\n// Scalar Subquery Builder\n// ============================================================================\n\n/**\n * Build a scalar subquery that wraps a recursive CTE.\n *\n * Produces:\n * ```sql\n * (WITH RECURSIVE cteAlias AS (...)\n * SELECT COALESCE(json_agg(col ORDER BY __depth), '[]'::json)\n * FROM cteAlias)\n * ```\n */\nexport function buildRecursiveScalarSubquery(\n\tconfig: RecursiveCteConfig,\n\taggregateColumn: string,\n): Node {\n\tconst { cte } = buildRecursiveCte(config);\n\tconst cteAlias = config.cteAlias;\n\tconst dbCol = config.ctx.naming.toDatabase(aggregateColumn);\n\n\t// Build final SELECT with json_agg\n\tconst finalSelect: SelectStmt = {\n\t\ttargetList: [\n\t\t\t{\n\t\t\t\tResTarget: {\n\t\t\t\t\tval: coalesce(\n\t\t\t\t\t\tfuncCall('json_agg', [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t\t\t\t\t{ String: { sval: dbCol } },\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]),\n\t\t\t\t\t\ttypeCast(stringNode('[]'), 'json'),\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\tfromClause: [\n\t\t\t{\n\t\t\t\tRangeVar: {\n\t\t\t\t\trelname: cteAlias,\n\t\t\t\t\tinh: true,\n\t\t\t\t\trelpersistence: 'p',\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\twithClause: {\n\t\t\tctes: [cte],\n\t\t\trecursive: true,\n\t\t},\n\t};\n\n\treturn {\n\t\tSubLink: {\n\t\t\tsubLinkType: 'EXPR_SUBLINK',\n\t\t\tsubselect: { SelectStmt: finalSelect },\n\t\t},\n\t};\n}\n","/**\n * Cycle Detection for Recursive CTEs\n *\n * Implements cycle detection strategies:\n * 1. __visited array approach (works on all PostgreSQL versions)\n * 2. PG14+ CYCLE clause (cleaner, but requires PG14+)\n *\n * The __visited array stores all visited PKs and checks for duplicates\n * using the `<> ALL(array)` operator.\n */\n\nimport type { CTECycleClause, Node } from '@pgsql/types';\nimport { binaryExpr } from '../ast-helpers.js';\n\n/**\n * Build __visited column for anchor or recursive SELECT.\n *\n * Anchor: ARRAY[pk] AS __visited\n * Recursive: __visited || pk AS __visited\n */\nexport function buildCycleDetection(\n\talias: string,\n\tpkColumn: string,\n\tisAnchor: boolean,\n\tcteAlias?: string,\n): Node {\n\tif (isAnchor) {\n\t\t// ARRAY[pk] AS __visited\n\t\treturn {\n\t\t\tResTarget: {\n\t\t\t\tval: {\n\t\t\t\t\tA_ArrayExpr: {\n\t\t\t\t\t\telements: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t\t{ String: { sval: alias } },\n\t\t\t\t\t\t\t\t\t\t{ String: { sval: pkColumn } },\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tname: '__visited',\n\t\t\t},\n\t\t};\n\t}\n\n\t// Recursive: __visited || pk\n\tif (!cteAlias) {\n\t\tthrow new Error('cteAlias required for recursive cycle detection');\n\t}\n\n\treturn {\n\t\tResTarget: {\n\t\t\tval: binaryExpr(\n\t\t\t\t'||',\n\t\t\t\t{\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t\t{ String: { sval: '__visited' } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: alias } },\n\t\t\t\t\t\t\t{ String: { sval: pkColumn } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t),\n\t\t\tname: '__visited',\n\t\t},\n\t};\n}\n\n/**\n * Build cycle check condition for WHERE clause.\n *\n * Produces: pk <> ALL(__visited)\n */\nexport function buildCycleCheck(\n\tinnerAlias: string,\n\tcteAlias: string,\n\tpkColumn: string,\n): Node {\n\treturn {\n\t\tA_Expr: {\n\t\t\tkind: 'AEXPR_OP_ALL',\n\t\t\tname: [{ String: { sval: '<>' } }],\n\t\t\tlexpr: {\n\t\t\t\tColumnRef: {\n\t\t\t\t\tfields: [\n\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t{ String: { sval: pkColumn } },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\trexpr: {\n\t\t\t\tColumnRef: {\n\t\t\t\t\tfields: [\n\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t{ String: { sval: '__visited' } },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t};\n}\n\n/**\n * Build PG14+ CYCLE clause.\n *\n * PG14 introduced the CYCLE clause for recursive CTEs:\n * ```sql\n * WITH RECURSIVE cte AS (...)\n * CYCLE pk SET is_cycle USING path\n * SELECT ... FROM cte WHERE NOT is_cycle\n * ```\n *\n * Note: This returns metadata about the cycle clause, but the actual\n * implementation depends on how @pgsql/types represents it.\n * Currently returns null if not supported.\n */\nexport function buildPg14CycleClause(\n\tpkColumn: string,\n\tcycleColumn = 'is_cycle',\n\tpathColumn = '__cycle_path',\n): Node | null {\n\t// CTECycleClause is available in @pgsql/types ≥ 17.x.\n\t// Produces: CYCLE {pkColumn} SET {cycleColumn} USING {pathColumn}\n\tconst cycleClause: CTECycleClause = {\n\t\tcycle_col_list: [{ String: { sval: pkColumn } }],\n\t\tcycle_mark_column: cycleColumn,\n\t\tcycle_path_column: pathColumn,\n\t};\n\n\treturn { CTECycleClause: cycleClause };\n}\n\n/**\n * Check if PG14 CYCLE clause is available.\n *\n * This can be used to determine which cycle detection strategy to use.\n */\nexport function isPg14CycleSupported(): boolean {\n\t// CTECycleClause is available in @pgsql/types ≥ 17.x, which we have.\n\t// The CYCLE clause is supported by PostgreSQL ≥ 14.\n\t// Callers should pass `usePg14Cycle: true` in RecursiveCteConfig\n\t// when targeting PG14+ servers.\n\treturn true;\n}\n\n/**\n * Build WHERE condition to filter out cyclic rows when using PG14 CYCLE clause.\n *\n * Produces: NOT is_cycle\n */\nexport function buildCycleFilter(cycleColumn = 'is_cycle'): Node {\n\treturn {\n\t\tBoolExpr: {\n\t\t\tboolop: 'NOT_EXPR',\n\t\t\targs: [\n\t\t\t\t{\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [{ String: { sval: cycleColumn } }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t};\n}\n","/**\n * Path Tracking for Recursive CTEs\n *\n * Builds and appends path arrays for hierarchical traversals.\n * The path array contains text representations of PKs visited during traversal.\n *\n * Example output column:\n * - Anchor: ARRAY[pk::text] AS __path\n * - Recursive: __path || pk::text AS __path\n */\n\nimport type { Node } from '@pgsql/types';\nimport { binaryExpr, typeCast } from '../ast-helpers.js';\n\n/**\n * Build initial path column for anchor SELECT.\n *\n * Produces: ARRAY[pk::text] AS __path\n */\nexport function buildPathColumn(alias: string, pkColumn: string): Node {\n\treturn {\n\t\tResTarget: {\n\t\t\tval: {\n\t\t\t\tA_ArrayExpr: {\n\t\t\t\t\telements: [\n\t\t\t\t\t\ttypeCast(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t\t{ String: { sval: alias } },\n\t\t\t\t\t\t\t\t\t\t{ String: { sval: pkColumn } },\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t'text',\n\t\t\t\t\t\t),\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\tname: '__path',\n\t\t},\n\t};\n}\n\n/**\n * Build appended path column for recursive SELECT.\n *\n * Produces: __path || pk::text AS __path\n */\nexport function appendPathColumn(\n\tcteAlias: string,\n\tinnerAlias: string,\n\tpkColumn: string,\n): Node {\n\treturn {\n\t\tResTarget: {\n\t\t\tval: binaryExpr(\n\t\t\t\t'||',\n\t\t\t\t{\n\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t\t{ String: { sval: '__path' } },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\ttypeCast(\n\t\t\t\t\t{\n\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t{ String: { sval: innerAlias } },\n\t\t\t\t\t\t\t\t{ String: { sval: pkColumn } },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t'text',\n\t\t\t\t),\n\t\t\t),\n\t\t\tname: '__path',\n\t\t},\n\t};\n}\n\n/**\n * Build path as JSON array for more complex scenarios.\n *\n * Produces: json_agg(pk::text ORDER BY __depth) OVER () AS __json_path\n */\nexport function buildJsonPathColumn(\n\talias: string,\n\tpkColumn: string,\n\tdepthColumn = '__depth',\n): Node {\n\treturn {\n\t\tResTarget: {\n\t\t\tval: {\n\t\t\t\tFuncCall: {\n\t\t\t\t\tfuncname: [{ String: { sval: 'json_agg' } }],\n\t\t\t\t\targs: [\n\t\t\t\t\t\ttypeCast(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t\t{ String: { sval: alias } },\n\t\t\t\t\t\t\t\t\t\t{ String: { sval: pkColumn } },\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t'text',\n\t\t\t\t\t\t),\n\t\t\t\t\t],\n\t\t\t\t\tagg_order: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tSortBy: {\n\t\t\t\t\t\t\t\tnode: {\n\t\t\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t\t\t{ String: { sval: alias } },\n\t\t\t\t\t\t\t\t\t\t\t{ String: { sval: depthColumn } },\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tsortby_dir: 'SORTBY_ASC',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\t// Empty OVER () clause for window function\n\t\t\t\t\tover: {},\n\t\t\t\t},\n\t\t\t},\n\t\t\tname: '__json_path',\n\t\t},\n\t};\n}\n\n/**\n * Build path string using array_to_string.\n *\n * Produces: array_to_string(__path, '/') AS __path_string\n */\nexport function buildPathString(cteAlias: string, separator = '/'): Node {\n\treturn {\n\t\tResTarget: {\n\t\t\tval: {\n\t\t\t\tFuncCall: {\n\t\t\t\t\tfuncname: [{ String: { sval: 'array_to_string' } }],\n\t\t\t\t\targs: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tColumnRef: {\n\t\t\t\t\t\t\t\tfields: [\n\t\t\t\t\t\t\t\t\t{ String: { sval: cteAlias } },\n\t\t\t\t\t\t\t\t\t{ String: { sval: '__path' } },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tA_Const: {\n\t\t\t\t\t\t\t\tsval: { sval: separator },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t\tname: '__path_string',\n\t\t},\n\t};\n}\n","/**\n * Index-level DDL SQL generators for PostgreSQL.\n *\n * Generates SQL for CREATE INDEX and DROP INDEX.\n * All identifiers are quoted via quoteIdentifier().\n *\n * @module ddl/index-operations\n */\n\nimport type {\n\tCreateIndexOptions,\n\tDropIndexOptions,\n\tIndexColumnDef,\n} from '@dbsp/core';\nimport { validateIdentifier, validateSqlExpression } from '../validate.js';\nimport { quoteIdent, validateIndexMethod } from './phases/utils.js';\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n// S-2: Use quoteIdent from phases/utils (validates + double-quotes) instead of the former\n// local quoteIdentifier (which had no validation). qualifyTable wraps quoteIdent for schema-qualifying.\n\nfunction quoteIdentifier(name: string): string {\n\treturn quoteIdent(name, 'alias');\n}\n\nfunction qualifyTable(table: string, schema?: string): string {\n\treturn schema\n\t\t? `${quoteIdent(schema, 'schema')}.${quoteIdent(table, 'table')}`\n\t\t: quoteIdent(table, 'table');\n}\n\n// ---------------------------------------------------------------------------\n// CREATE INDEX\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a CREATE INDEX statement.\n *\n * Supports all PostgreSQL index options:\n * - UNIQUE, CONCURRENTLY, IF NOT EXISTS\n * - USING method (btree, hash, gist, gin, brin, hnsw, ivfflat, bm25)\n * - Per-column opclass (via opclass map or expression.opclass)\n * - INCLUDE clause for covering indexes\n * - WITH storage parameters (e.g. m, ef_construction for HNSW)\n * - WHERE partial index predicate (raw SQL escape hatch)\n *\n * @example\n * generateCreateIndexSQL('embeddings', { name: 'idx_model', columns: ['model'] })\n * // → 'CREATE INDEX \"idx_model\" ON \"embeddings\" (\"model\")'\n *\n * generateCreateIndexSQL('embeddings', {\n * name: 'idx_vec', columns: ['vector'], method: 'hnsw',\n * opclass: { vector: 'vector_cosine_ops' }, with: { m: 16, ef_construction: 64 }\n * })\n * // → 'CREATE INDEX \"idx_vec\" ON \"embeddings\" USING hnsw (\"vector\" vector_cosine_ops) WITH (m = 16, ef_construction = 64)'\n *\n * @param table - Table name\n * @param options - Index creation options\n * @param schema - Optional schema name for the table\n *\n * @security index name and column names are identifier-quoted.\n * `where` (S-1) and expression columns (S-1) are validated via validateSqlExpression()\n * before interpolation. WITH parameter keys are validated via validateIdentifier().\n */\nexport function generateCreateIndexSQL(\n\ttable: string,\n\toptions: CreateIndexOptions,\n\tschema?: string,\n): string {\n\t// Validate method if provided\n\tif (options.method !== undefined) {\n\t\tvalidateIndexMethod(options.method, 'index method');\n\t}\n\n\tconst parts: string[] = ['CREATE'];\n\n\tif (options.unique) parts.push('UNIQUE');\n\tparts.push('INDEX');\n\tif (options.concurrently) parts.push('CONCURRENTLY');\n\tif (options.ifNotExists) parts.push('IF NOT EXISTS');\n\n\tparts.push(quoteIdentifier(options.name));\n\tparts.push(`ON ${qualifyTable(table, schema)}`);\n\n\tif (options.method) {\n\t\tparts.push(`USING ${options.method}`);\n\t}\n\n\t// Build column list\n\tconst colParts: string[] = [];\n\tfor (const col of options.columns) {\n\t\tcolParts.push(buildColumnPart(col, options.opclass));\n\t}\n\tparts.push(`(${colParts.join(', ')})`);\n\n\t// INCLUDE clause\n\tif (options.include && options.include.length > 0) {\n\t\tconst includeCols = options.include\n\t\t\t.map((c) => quoteIdentifier(c))\n\t\t\t.join(', ');\n\t\tparts.push(`INCLUDE (${includeCols})`);\n\t}\n\n\t// WITH storage parameters — S-1: validate keys via validateIdentifier (consistent with other paths)\n\tif (options.with && Object.keys(options.with).length > 0) {\n\t\tconst withParams = Object.entries(options.with)\n\t\t\t.map(([k, v]) => {\n\t\t\t\tvalidateIdentifier(k, 'alias');\n\t\t\t\treturn `${k} = ${v}`;\n\t\t\t})\n\t\t\t.join(', ');\n\t\tparts.push(`WITH (${withParams})`);\n\t}\n\n\t// WHERE partial index predicate — S-1: validate before interpolation\n\tif (options.where) {\n\t\tvalidateSqlExpression(options.where, 'index WHERE predicate');\n\t\tparts.push(`WHERE ${options.where}`);\n\t}\n\n\treturn parts.join(' ');\n}\n\n/**\n * Build a single column part in the index column list.\n * Handles both string columns (with optional opclass from the opclass map)\n * and expression column defs ({ expression, opclass? }).\n */\nfunction buildColumnPart(\n\tcol: IndexColumnDef,\n\topclassMap?: Record<string, string>,\n): string {\n\tif (typeof col === 'string') {\n\t\t// Named column — quote it, then append opclass from the map if present\n\t\tconst quoted = quoteIdentifier(col);\n\t\tconst opclass = opclassMap?.[col];\n\t\t// S-1: validate opclass name before interpolation\n\t\tif (opclass) validateIdentifier(opclass, 'alias');\n\t\treturn opclass ? `${quoted} ${opclass}` : quoted;\n\t}\n\t// Expression column — validate expression before interpolation (S-1)\n\tvalidateSqlExpression(col.expression, 'index expression');\n\tconst opclass = col.opclass;\n\t// S-1: validate expression opclass name before interpolation\n\tif (opclass) validateIdentifier(opclass, 'alias');\n\treturn opclass ? `${col.expression} ${opclass}` : col.expression;\n}\n\n// ---------------------------------------------------------------------------\n// DROP INDEX\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a DROP INDEX statement.\n *\n * @example\n * generateDropIndexSQL('idx_vec', { ifExists: true })\n * // → 'DROP INDEX IF EXISTS \"idx_vec\"'\n *\n * generateDropIndexSQL('idx_vec', { cascade: true })\n * // → 'DROP INDEX \"idx_vec\" CASCADE'\n *\n * generateDropIndexSQL('idx_vec', { ifExists: true, schema: 'tenant_42' })\n * // → 'DROP INDEX IF EXISTS \"tenant_42\".\"idx_vec\"'\n *\n * @param name - Index name\n * @param options - Optional DROP INDEX modifiers\n */\nexport function generateDropIndexSQL(\n\tname: string,\n\toptions?: DropIndexOptions,\n): string {\n\tconst parts: string[] = ['DROP INDEX'];\n\n\tif (options?.concurrently) parts.push('CONCURRENTLY');\n\tif (options?.ifExists) parts.push('IF EXISTS');\n\n\t// Schema-qualified index name (for global orm.ddl.dropIndex)\n\tif (options?.schema) {\n\t\tparts.push(`${quoteIdentifier(options.schema)}.${quoteIdentifier(name)}`);\n\t} else {\n\t\tparts.push(quoteIdentifier(name));\n\t}\n\n\tif (options?.cascade) parts.push('CASCADE');\n\n\treturn parts.join(' ');\n}\n","/**\n * Table-level DDL SQL generators for PostgreSQL.\n *\n * @module ddl/table-operations\n */\n\nimport type {\n\tAlterColumnOptions,\n\tTruncateOptions,\n\tVacuumOptions,\n} from '@dbsp/core';\nimport { validateDbTypeName } from '../validate.js';\nimport { formatSqlDefault, quoteIdent } from './phases/utils.js';\n\n// S-2: quoteIdentifier now delegates to quoteIdent (validates + double-quotes).\n// The former local helper was bare `\"${name}\"` with no validation.\nfunction quoteIdentifier(name: string): string {\n\treturn quoteIdent(name, 'alias');\n}\n\nfunction qualifyTable(table: string, schema?: string): string {\n\treturn schema\n\t\t? `${quoteIdent(schema, 'schema')}.${quoteIdent(table, 'table')}`\n\t\t: quoteIdent(table, 'table');\n}\n\nexport function generateTruncateSQL(\n\ttable: string,\n\tschema?: string,\n\toptions?: TruncateOptions,\n): string {\n\tconst target = qualifyTable(table, schema);\n\tconst parts: string[] = [`TRUNCATE ${target}`];\n\tif (options?.restartIdentity) parts.push('RESTART IDENTITY');\n\tif (options?.cascade) parts.push('CASCADE');\n\treturn parts.join(' ');\n}\n\nexport function generateVacuumSQL(\n\ttable: string,\n\t_schema?: string,\n\toptions?: VacuumOptions,\n): string {\n\tconst modifiers: string[] = [];\n\tif (options?.full) modifiers.push('FULL');\n\tif (options?.analyze) modifiers.push('ANALYZE');\n\tconst modifier = modifiers.length > 0 ? ` ${modifiers.join(' ')}` : '';\n\treturn `VACUUM${modifier} ${quoteIdentifier(table)}`;\n}\n\n// M-6: formatDefault is now a thin alias for the shared formatSqlDefault from phases/utils.\n// The duplicate implementations have been consolidated.\nfunction formatDefault(value: unknown): string {\n\treturn formatSqlDefault(value, 'table-operations default');\n}\n\nexport function generateAlterColumnSQL(\n\ttable: string,\n\tcolumn: string,\n\toptions: AlterColumnOptions,\n\tschema?: string,\n): string {\n\tconst target = qualifyTable(table, schema);\n\tconst quotedCol = quoteIdentifier(column);\n\tconst prefix = `ALTER TABLE ${target} ALTER COLUMN ${quotedCol}`;\n\tconst statements: string[] = [];\n\tif (options.type !== undefined) {\n\t\tconst safeType = validateDbTypeName(options.type);\n\t\tconst using = options.using !== undefined ? ` USING ${options.using}` : '';\n\t\tstatements.push(`${prefix} TYPE ${safeType}${using}`);\n\t}\n\tif (options.setNotNull === true) {\n\t\tstatements.push(`${prefix} SET NOT NULL`);\n\t} else if (options.setNotNull === false) {\n\t\tstatements.push(`${prefix} DROP NOT NULL`);\n\t}\n\tif (options.setDefault !== undefined) {\n\t\tstatements.push(\n\t\t\t`${prefix} SET DEFAULT ${formatDefault(options.setDefault)}`,\n\t\t);\n\t}\n\tif (options.dropDefault === true) {\n\t\tstatements.push(`${prefix} DROP DEFAULT`);\n\t}\n\tif (statements.length === 0) {\n\t\tthrow new Error(\n\t\t\t'generateAlterColumnSQL: at least one option must be specified',\n\t\t);\n\t}\n\treturn statements.join(';\\n');\n}\n","/**\n * Set operation compiler (UNION / INTERSECT / EXCEPT)\n *\n * Recursively compiles a SetOperationIntent tree into a single SQL string\n * with correctly renumbered positional parameters ($1, $2, ...).\n */\n\nimport type { ModelIR } from '@dbsp/core';\nimport type {\n\tDialectCapabilities,\n\tPlanReport,\n\tQueryIntent,\n\tSetOperationIntent,\n} from '@dbsp/types';\n\n/**\n * Compiled SQL with positional parameters.\n */\nexport interface SetOperationResult {\n\treadonly sql: string;\n\treadonly parameters: readonly unknown[];\n}\n\n/**\n * Function that compiles a single QueryIntent leaf to SQL + parameters.\n * Provided by the caller to decouple from adapter internals.\n */\nexport type LeafCompileFn = (query: QueryIntent) => {\n\tsql: string;\n\tparameters: readonly unknown[];\n};\n\n/**\n * Re-number positional parameter placeholders ($1, $2, ...) in a SQL string\n * by adding `offset` to each index.\n *\n * @example\n * renumberParams('SELECT * FROM t WHERE a = $1 AND b = $2', 3)\n * // → 'SELECT * FROM t WHERE a = $4 AND b = $5'\n */\nfunction renumberParams(sql: string, offset: number): string {\n\tif (offset === 0) return sql;\n\treturn sql.replace(/\\$(\\d+)/g, (_match, num) => {\n\t\treturn `$${Number.parseInt(num, 10) + offset}`;\n\t});\n}\n\n/**\n * Recursively compile a SetOperationIntent to SQL with merged parameters.\n *\n * Each leaf QueryIntent is compiled via `compileFn`. When merging left and\n * right branches, the right side's `$N` placeholders are renumbered so they\n * don't collide with the left side's parameters.\n *\n * @param intent - The set operation intent (recursive tree)\n * @param compileFn - Compiles a single QueryIntent to SQL + params\n * @returns Combined SQL string and merged parameter array\n *\n * @example\n * ```typescript\n * const result = compileSetOperation(setOpIntent, (query) => {\n * const planReport = plan(query, model, { dialectCapabilities });\n * return adapter.compile(planReport, { model });\n * });\n * console.log(result.sql); // (SELECT ...) UNION (SELECT ...)\n * console.log(result.parameters); // [...leftParams, ...rightParams]\n * ```\n */\nexport function compileSetOperation(\n\tintent: SetOperationIntent,\n\tcompileFn: LeafCompileFn,\n): SetOperationResult {\n\t// Compile left side (always a QueryIntent)\n\tconst left = compileLeafOrBranch(intent.left, compileFn);\n\n\t// Compile right side (QueryIntent or nested SetOperationIntent)\n\tconst right = compileLeafOrBranch(intent.right, compileFn);\n\n\t// Renumber right-side parameters to avoid $N collisions\n\tconst rightSQL = renumberParams(right.sql, left.parameters.length);\n\n\t// Build the set operation keyword\n\tconst opKeyword = intent.op.toUpperCase() + (intent.all ? ' ALL' : '');\n\n\treturn {\n\t\tsql: `(${left.sql}) ${opKeyword} (${rightSQL})`,\n\t\tparameters: [...left.parameters, ...right.parameters],\n\t};\n}\n\n/**\n * Compile either a leaf QueryIntent or a nested SetOperationIntent branch.\n */\nfunction compileLeafOrBranch(\n\tintent: QueryIntent | SetOperationIntent,\n\tcompileFn: LeafCompileFn,\n): SetOperationResult {\n\tif ('kind' in intent && intent.kind === 'setOperation') {\n\t\treturn compileSetOperation(intent as SetOperationIntent, compileFn);\n\t}\n\tconst result = compileFn(intent as QueryIntent);\n\treturn { sql: result.sql, parameters: result.parameters };\n}\n\n/**\n * Create a leaf compile function from adapter + model + capabilities.\n *\n * Convenience factory for the common case where you have a PgsqlAdapter\n * and need a compileFn for `compileSetOperation`.\n *\n * @param adapter - Adapter with compile() and dialectCapabilities\n * @param model - ModelIR schema\n * @param planFn - The plan() function from @dbsp/core\n */\nexport function createLeafCompileFn(\n\tadapter: {\n\t\tcompile(\n\t\t\tplan: PlanReport,\n\t\t\toptions: { model: ModelIR },\n\t\t): { sql: string; parameters: readonly unknown[] };\n\t\tdialectCapabilities: DialectCapabilities;\n\t},\n\tmodel: ModelIR,\n\tplanFn: (\n\t\tintent: QueryIntent,\n\t\tmodel: ModelIR,\n\t\toptions: { dialectCapabilities: DialectCapabilities },\n\t) => PlanReport,\n): LeafCompileFn {\n\treturn (query: QueryIntent) => {\n\t\tconst planReport = planFn(query, model, {\n\t\t\tdialectCapabilities: adapter.dialectCapabilities,\n\t\t});\n\t\treturn adapter.compile(planReport, { model });\n\t};\n}\n","/**\n * Cursor-Based Streaming Support\n *\n * Generates PostgreSQL cursor statements for streaming large result sets.\n * Supports:\n * - DECLARE CURSOR\n * - FETCH (forward, backward, all)\n * - CLOSE CURSOR\n *\n * Note: This generates AST nodes for cursor operations.\n * Actual cursor execution requires a transaction context.\n */\n\nimport type { Node, FetchDirection as PgsqlFetchDirection } from '@pgsql/types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Cursor scroll options.\n */\nexport type CursorScrollOption = 'scroll' | 'no_scroll';\n\n/**\n * Cursor hold option (whether cursor survives transaction commit).\n */\nexport type CursorHoldOption = 'with_hold' | 'without_hold';\n\n/**\n * Fetch direction for cursor.\n */\nexport type FetchDirection =\n\t| 'next'\n\t| 'prior'\n\t| 'first'\n\t| 'last'\n\t| 'absolute'\n\t| 'relative'\n\t| 'forward'\n\t| 'backward'\n\t| 'forward_all'\n\t| 'backward_all';\n\n/**\n * Options for DECLARE CURSOR.\n */\nexport interface CursorOptions {\n\t/** Cursor name */\n\tname: string;\n\t/** The query to execute */\n\tquery: Node;\n\t/** Scroll option (default: no_scroll) */\n\tscroll?: CursorScrollOption;\n\t/** Hold option (default: without_hold) */\n\thold?: CursorHoldOption;\n\t/** Binary output (rarely used) */\n\tbinary?: boolean;\n}\n\n/**\n * Options for FETCH.\n */\nexport interface FetchOptions {\n\t/** Cursor name */\n\tcursorName: string;\n\t/** Fetch direction */\n\tdirection?: FetchDirection;\n\t/** Number of rows to fetch (for forward/backward) */\n\tcount?: number;\n}\n\n// ============================================================================\n// Cursor Builders\n// ============================================================================\n\n/**\n * Build a DECLARE CURSOR statement.\n *\n * @param options - Cursor declaration options\n * @returns DeclareCursorStmt AST node\n *\n * @example\n * ```typescript\n * const selectAst = { SelectStmt: { ... } };\n * const cursorAst = buildDeclareCursor({\n * name: 'my_cursor',\n * query: selectAst,\n * scroll: 'no_scroll',\n * hold: 'without_hold'\n * });\n * // Produces: DECLARE my_cursor NO SCROLL CURSOR WITHOUT HOLD FOR SELECT ...\n * ```\n */\nexport function buildDeclareCursor(options: CursorOptions): Node {\n\tlet cursorOptions = 0;\n\n\t// Set options bitmask based on PostgreSQL constants\n\tif (options.binary) {\n\t\tcursorOptions |= 0x0001; // CURSOR_OPT_BINARY\n\t}\n\tif (options.scroll === 'scroll') {\n\t\tcursorOptions |= 0x0002; // CURSOR_OPT_SCROLL\n\t}\n\tif (options.scroll === 'no_scroll') {\n\t\tcursorOptions |= 0x0004; // CURSOR_OPT_NO_SCROLL\n\t}\n\tif (options.hold === 'with_hold') {\n\t\tcursorOptions |= 0x0010; // CURSOR_OPT_HOLD\n\t}\n\n\treturn {\n\t\tDeclareCursorStmt: {\n\t\t\tportalname: options.name,\n\t\t\toptions: cursorOptions,\n\t\t\tquery: options.query,\n\t\t},\n\t};\n}\n\n/**\n * Build a FETCH statement.\n *\n * @param options - Fetch options\n * @returns FetchStmt AST node\n *\n * @example\n * ```typescript\n * const fetchAst = buildFetch({\n * cursorName: 'my_cursor',\n * direction: 'forward',\n * count: 100\n * });\n * // Produces: FETCH FORWARD 100 FROM my_cursor\n * ```\n */\nexport function buildFetch(options: FetchOptions): Node {\n\tconst dir = options.direction ?? 'next';\n\n\t// Calculate direction and howMany based on FetchDirection.\n\t// PostgreSQL semantics: FETCH FORWARD ALL / FETCH BACKWARD ALL fetches all remaining rows.\n\t//\n\t// TYPE HONESTY NOTE: @pgsql/types declares FetchStmt.howMany as `bigint`, but the\n\t// pgsql-deparser performs a strict Number identity check internally:\n\t// if (node.howMany === 9223372036854776000) → emits \"ALL\"\n\t// A real BigInt (e.g. BigInt('9223372036854775807')) does NOT trigger this branch —\n\t// the deparser emits the literal number string instead of \"ALL\". This was verified\n\t// empirically: deparseSync({FetchStmt:{howMany:BigInt('9223372036854775807'),...}})\n\t// → \"FETCH FORWARD 9223372036854775807 c\" (not \"FETCH FORWARD ALL c\").\n\t//\n\t// Therefore the ALL sentinel must be assigned as a Number. We use `number | bigint`\n\t// to document that the variable holds either a real bigint (for counted fetches) or\n\t// a Number sentinel (for ALL). The `as unknown as bigint` cast on the sentinel line\n\t// satisfies the FetchStmt.howMany type while preserving the Number runtime value.\n\t//\n\t// TODO: file upstream issue against pgsql-deparser — FetchStmt.howMany comparison\n\t// should use Number() conversion to support real BigInt ALL sentinels.\n\tlet direction: string;\n\tlet howMany: number | bigint;\n\n\tswitch (dir) {\n\t\tcase 'first':\n\t\t\tdirection = 'FETCH_ABSOLUTE';\n\t\t\thowMany = BigInt(1);\n\t\t\tbreak;\n\t\tcase 'last':\n\t\t\tdirection = 'FETCH_ABSOLUTE';\n\t\t\thowMany = BigInt(-1);\n\t\t\tbreak;\n\t\tcase 'forward_all':\n\t\t\t// FETCH FORWARD ALL — deparser sentinel: Number 9223372036854776000 (float64 ≈ INT64_MAX)\n\t\t\tdirection = 'FETCH_FORWARD';\n\t\t\thowMany = 9223372036854776000 as unknown as bigint;\n\t\t\tbreak;\n\t\tcase 'backward_all':\n\t\t\t// FETCH BACKWARD ALL — deparser sentinel: Number 9223372036854776000 (float64 ≈ INT64_MAX)\n\t\t\tdirection = 'FETCH_BACKWARD';\n\t\t\thowMany = 9223372036854776000 as unknown as bigint;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tdirection = mapFetchDirection(dir);\n\t\t\thowMany = BigInt(options.count ?? 1);\n\t}\n\n\treturn {\n\t\tFetchStmt: {\n\t\t\tdirection: direction as PgsqlFetchDirection,\n\t\t\thowMany,\n\t\t\tportalname: options.cursorName,\n\t\t\tismove: false,\n\t\t},\n\t};\n}\n\n/**\n * Build a CLOSE cursor statement.\n *\n * @param cursorName - Name of cursor to close (or '*' for all)\n * @returns ClosePortalStmt AST node\n */\nexport function buildCloseCursor(cursorName: string): Node {\n\t// CLOSE ALL uses empty string or no portalname\n\tconst stmt: { portalname?: string } = {};\n\tif (cursorName !== '*') {\n\t\tstmt.portalname = cursorName;\n\t}\n\treturn { ClosePortalStmt: stmt };\n}\n\n// ============================================================================\n// Convenience Builders\n// ============================================================================\n\n/**\n * Build FETCH NEXT (single row).\n */\nexport function buildFetchNext(cursorName: string): Node {\n\treturn buildFetch({ cursorName, direction: 'next', count: 1 });\n}\n\n/**\n * Build FETCH FORWARD N (multiple rows).\n */\nexport function buildFetchForward(cursorName: string, count: number): Node {\n\treturn buildFetch({ cursorName, direction: 'forward', count });\n}\n\n/**\n * Build FETCH ALL (remaining rows).\n */\nexport function buildFetchAll(cursorName: string): Node {\n\treturn buildFetch({ cursorName, direction: 'forward_all' });\n}\n\n/**\n * Build FETCH FIRST (move to start and get first row).\n */\nexport function buildFetchFirst(cursorName: string): Node {\n\treturn buildFetch({ cursorName, direction: 'first' });\n}\n\n// ============================================================================\n// Streaming Iterator Pattern\n// ============================================================================\n\n/**\n * Configuration for streaming query execution.\n */\nexport interface StreamConfig {\n\t/** Cursor name prefix (will be appended with unique ID) */\n\tcursorPrefix?: string;\n\t/** Batch size for each fetch (default: 100) */\n\tbatchSize?: number;\n\t/** Whether cursor should survive transaction (default: false) */\n\twithHold?: boolean;\n}\n\n/**\n * Generate a unique cursor name.\n *\n * @param prefix - Cursor name prefix\n * @returns Unique cursor name\n */\nexport function generateCursorName(prefix = '__cursor'): string {\n\tconst timestamp = Date.now().toString(36);\n\tconst random = crypto.randomUUID().substring(0, 8);\n\treturn `${prefix}_${timestamp}_${random}`;\n}\n\n/**\n * Build all statements needed for streaming query execution.\n *\n * @param query - The SELECT query to stream\n * @param config - Streaming configuration\n * @returns Object with cursor name and statement builders\n *\n * @example\n * ```typescript\n * const { cursorName, declare, fetchBatch, close } = buildStreamingStatements(\n * selectAst,\n * { batchSize: 100 }\n * );\n *\n * // In transaction:\n * // 1. Execute declare\n * // 2. Loop: execute fetchBatch, process rows, until empty\n * // 3. Execute close\n * ```\n */\nexport function buildStreamingStatements(\n\tquery: Node,\n\tconfig: StreamConfig = {},\n): {\n\tcursorName: string;\n\tdeclare: Node;\n\tfetchBatch: Node;\n\tfetchAll: Node;\n\tclose: Node;\n} {\n\tconst cursorName = generateCursorName(config.cursorPrefix);\n\tconst batchSize = config.batchSize ?? 100;\n\n\treturn {\n\t\tcursorName,\n\t\tdeclare: buildDeclareCursor({\n\t\t\tname: cursorName,\n\t\t\tquery,\n\t\t\tscroll: 'no_scroll',\n\t\t\thold: config.withHold ? 'with_hold' : 'without_hold',\n\t\t}),\n\t\tfetchBatch: buildFetchForward(cursorName, batchSize),\n\t\tfetchAll: buildFetchAll(cursorName),\n\t\tclose: buildCloseCursor(cursorName),\n\t};\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Map FetchDirection to PostgreSQL enum value.\n */\nfunction mapFetchDirection(direction: FetchDirection): string {\n\tconst mapping: Record<FetchDirection, string> = {\n\t\tnext: 'FETCH_FORWARD',\n\t\tprior: 'FETCH_BACKWARD',\n\t\tfirst: 'FETCH_ABSOLUTE',\n\t\tlast: 'FETCH_ABSOLUTE',\n\t\tabsolute: 'FETCH_ABSOLUTE',\n\t\trelative: 'FETCH_RELATIVE',\n\t\tforward: 'FETCH_FORWARD',\n\t\tbackward: 'FETCH_BACKWARD',\n\t\tforward_all: 'FETCH_FORWARD_ALL',\n\t\tbackward_all: 'FETCH_BACKWARD_ALL',\n\t};\n\n\treturn mapping[direction];\n}\n","/**\n * Redact sensitive values in a query dump's `params` array before logging.\n *\n * Defense-in-depth helper: when application code may have inserted PII as\n * literal parameter values (e.g. an email in a WHERE clause), this replaces\n * any string value matching a configured pattern with the `replacement`\n * placeholder. Non-string values are passed through unchanged.\n */\n\nexport type RedactionPattern = string | RegExp;\n\nexport type RedactionConfig = {\n\t/** Patterns to match against string param values. String = substring (case-insensitive); RegExp = `.test()`. */\n\treadonly patterns: ReadonlyArray<RedactionPattern>;\n\t/** Placeholder substituted for matched values. Default `'[REDACTED]'`. */\n\treadonly replacement?: string;\n};\n\n/**\n * Curated regex set for common PII shapes. Match against the value itself\n * (not the column name), so they detect data shaped like an email / token /\n * credit-card / SSN regardless of which `$N` slot it landed in.\n *\n * @stable Adding entries is non-breaking; removing one is a semver-major change\n * because callers may rely on a specific shape being redacted.\n */\nexport const DEFAULT_REDACTION_PATTERNS: ReadonlyArray<RegExp> = Object.freeze([\n\t/^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/, // email\n\t/^Bearer\\s+[A-Za-z0-9._-]+$/i, // bearer token\n\t/^eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$/, // JWT\n\t/^\\d{3}-\\d{2}-\\d{4}$/, // US SSN\n\t/^\\d(?:[ -]?\\d){12,18}$/, // credit card (13-19 digits, optional spaces/dashes between)\n\t/^sk-[A-Za-z0-9]{20,}$/, // OpenAI-style API key\n]);\n\nconst DEFAULT_REPLACEMENT = '[REDACTED]';\n\n/**\n * Returns a NEW array of params with sensitive string values replaced.\n * The input array is never mutated. Non-string values pass through unchanged.\n */\nexport function redactParams(\n\tparams: readonly unknown[],\n\tconfig: RedactionConfig,\n): readonly unknown[] {\n\tconst replacement = config.replacement ?? DEFAULT_REPLACEMENT;\n\treturn params.map((value) =>\n\t\tmatchesAnyPattern(value, config.patterns) ? replacement : value,\n\t);\n}\n\nfunction matchesAnyPattern(\n\tvalue: unknown,\n\tpatterns: ReadonlyArray<RedactionPattern>,\n): boolean {\n\tif (typeof value !== 'string') return false;\n\tconst lowerValue = value.toLowerCase();\n\tfor (const pattern of patterns) {\n\t\tif (typeof pattern === 'string') {\n\t\t\tif (pattern.length > 0 && lowerValue.includes(pattern.toLowerCase()))\n\t\t\t\treturn true;\n\t\t} else {\n\t\t\tconst re =\n\t\t\t\tpattern.global || pattern.sticky\n\t\t\t\t\t? new RegExp(pattern.source, pattern.flags)\n\t\t\t\t\t: pattern;\n\t\t\tif (re.test(value)) return true;\n\t\t}\n\t}\n\treturn false;\n}\n"],"mappings":"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","names":["typeCast","op","op","OP_MAP","exprRef","joinExpr","joinExpr","joinExpr","resTarget","joinExpr","op","raw","resolveCaseValue","createWhereDispatcher","coalesceExpr","resTarget","init_json","op","resTarget","sortBy","init_json","op","left","right","fn","op","ctx","joinExpr","quoteIdent","quoteIdent","quoteIdent","quoteIdent","quoteIdent","gen","quoteIdent","qualifyTable","pkName","fn","sup","fn","literal","exprRef","fn","literal","op","param","InvalidOperationError","isSqlRaw","compileInsert","InvalidOperationError","compileInsertFrom","compileUpdate","compileDelete","compileUpsert","isSqlRaw","compileUpsertFrom","isSubqueryRef","op","valueToNode","selectStmt","op","valueToNode","quoteIdentifier","quoteIdent","qualifyTable","opclass","quoteIdentifier","quoteIdent","qualifyTable","formatDefault","planFn","compileInsert","compileInsertFrom","compileUpdate","compileDelete","compileUpsert","compileUpsertFrom","fn"]}
|