@prisma-next/adapter-postgres 0.12.0-dev.17 → 0.12.0-dev.3
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/README.md +20 -13
- package/dist/{adapter-Dr2W2Syq.mjs → adapter-H8BiuXdq.mjs} +2 -4
- package/dist/adapter-H8BiuXdq.mjs.map +1 -0
- package/dist/adapter.d.mts +1 -2
- package/dist/adapter.d.mts.map +1 -1
- package/dist/adapter.mjs +1 -1
- package/dist/control.d.mts +3 -20
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +1 -58
- package/dist/control.mjs.map +1 -1
- package/dist/runtime.d.mts +1 -1
- package/dist/runtime.mjs +1 -1
- package/dist/{sql-renderer-DqVeL4hP.mjs → sql-renderer-DlZhVI9B.mjs} +16 -69
- package/dist/sql-renderer-DlZhVI9B.mjs.map +1 -0
- package/package.json +22 -22
- package/src/core/adapter.ts +1 -10
- package/src/core/control-adapter.ts +2 -98
- package/src/core/sql-renderer.ts +18 -54
- package/dist/adapter-Dr2W2Syq.mjs.map +0 -1
- package/dist/sql-renderer-DqVeL4hP.mjs.map +0 -1
- package/src/core/ddl-renderer.ts +0 -73
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-renderer-DlZhVI9B.mjs","names":[],"sources":["../src/core/codec-lookup.ts","../src/core/sql-renderer.ts"],"sourcesContent":["import type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport { extractCodecLookup } from '@prisma-next/framework-components/control';\nimport { postgresCodecRegistry } from '@prisma-next/target-postgres/codecs';\n\n/**\n * Build a {@link CodecLookup} populated with the Postgres-builtin codec definitions only.\n *\n * This is the default lookup used by `createPostgresAdapter()` and `new PostgresControlAdapter()` when called without a stack-derived lookup (e.g. from tests, or one-off scripts that don't compose a full stack).\n *\n * Extension codecs (e.g. `pg/vector@1` from `@prisma-next/extension-pgvector`) are intentionally NOT included here: a bare adapter cannot see extensions. Stack-composed paths (`SqlControlAdapterDescriptor.create(stack)` / `SqlRuntimeAdapterDescriptor.create(stack)`) supply the broader, extension-inclusive lookup at construction time.\n */\nexport function createPostgresBuiltinCodecLookup(): CodecLookup {\n return extractCodecLookup([\n {\n id: 'postgres-builtin-codecs',\n types: { codecTypes: { codecDescriptors: Array.from(postgresCodecRegistry.values()) } },\n },\n ]);\n}\n","import type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport { runtimeError } from '@prisma-next/framework-components/runtime';\nimport {\n type AggregateExpr,\n type AnyExpression,\n type AnyFromSource,\n type AnyParamRef,\n type AnyQueryAst,\n type BinaryExpr,\n type ColumnRef,\n collectOrderedParamRefs,\n type DeleteAst,\n type InsertAst,\n type InsertValue,\n type JoinAst,\n type JoinOnExpr,\n type JsonArrayAggExpr,\n type JsonObjectExpr,\n type ListExpression,\n LiteralExpr,\n type LoweredParam,\n type NullCheckExpr,\n type OperationExpr,\n type OrderByItem,\n type ProjectionItem,\n type RawExpr,\n type RawSqlExpr,\n type SelectAst,\n type SubqueryExpr,\n type UpdateAst,\n type WindowFuncExpr,\n} from '@prisma-next/sql-relational-core/ast';\nimport { escapeLiteral, quoteIdentifier } from '@prisma-next/target-postgres/sql-utils';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { PostgresContract } from './types';\n\n/**\n * Postgres native types whose unknown-OID parameter inference is reliable in arbitrary expression positions. Parameters bound to a codec whose `meta.db.sql.postgres.nativeType` falls in this set are emitted as plain `$N`; everything else (including `json`, `jsonb`, extension types like `vector`, and unknown user types) is emitted as `$N::<nativeType>` so the planner picks an unambiguous overload.\n *\n * `json` / `jsonb` are intentionally excluded despite being Postgres builtins: their operator overloads make context inference unreliable in expression positions (e.g. `$1 -> 'key'` is ambiguous between the two).\n *\n * Spellings match the on-disk `meta.db.sql.postgres.nativeType` values in `@prisma-next/target-postgres`'s codec definitions, not the `udt_name` abbreviations that ADR 205 used as illustrative shorthand. The lookup-based cast policy compares against these strings directly.\n */\nconst POSTGRES_INFERRABLE_NATIVE_TYPES: ReadonlySet<string> = new Set([\n // Numeric\n 'integer',\n 'smallint',\n 'bigint',\n 'real',\n 'double precision',\n 'numeric',\n // Boolean\n 'boolean',\n // Strings\n 'text',\n 'character',\n 'character varying',\n // Temporal\n 'timestamp',\n 'timestamp without time zone',\n 'timestamp with time zone',\n 'time',\n 'timetz',\n 'interval',\n // Bit strings\n 'bit',\n 'bit varying',\n]);\n\nfunction renderTypedParam(\n index: number,\n codecId: string | undefined,\n codecLookup: CodecLookup,\n): string {\n if (codecId === undefined) {\n return `$${index}`;\n }\n const meta = codecLookup.metaFor(codecId);\n const isRegistered =\n codecLookup.get(codecId) !== undefined ||\n meta !== undefined ||\n codecLookup.targetTypesFor(codecId) !== undefined;\n if (!isRegistered) {\n throw new Error(\n `Postgres lowering: ParamRef carries codecId \"${codecId}\" but the ` +\n 'assembled codec lookup has no entry for it. This usually indicates ' +\n 'a missing extension pack in the runtime stack — register the pack ' +\n 'that contributes this codec (e.g. `extensionPacks: [pgvectorRuntime]`), ' +\n 'or use the codec directly from `@prisma-next/target-postgres/codecs` ' +\n \"if it's a builtin.\",\n );\n }\n // The framework `CodecLookup.metaFor` returns the family-agnostic `CodecMeta` whose `db` is `Record<string, unknown>`. The SQL family populates a narrower shape with `db.sql.<dialect>.nativeType: string`; navigate that path defensively and string-check the leaf.\n const dbRecord = meta?.db;\n const sqlBlock = isRecord(dbRecord) ? dbRecord['sql'] : undefined;\n const dialectBlock = isRecord(sqlBlock) ? sqlBlock['postgres'] : undefined;\n const nativeType = isRecord(dialectBlock) ? dialectBlock['nativeType'] : undefined;\n if (typeof nativeType === 'string' && !POSTGRES_INFERRABLE_NATIVE_TYPES.has(nativeType)) {\n return `$${index}::${nativeType}`;\n }\n return `$${index}`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/**\n * Per-render carrier threaded through every helper. Bundles the param-index map (for `$N` numbering) and the assembled-stack `codecLookup` (for cast policy at the `renderTypedParam` chokepoint). Carrying both on a single value keeps helper signatures stable.\n */\ninterface ParamIndexMap {\n readonly indexMap: Map<AnyParamRef, number>;\n readonly codecLookup: CodecLookup;\n}\n\n/**\n * Render a SQL query AST to a Postgres-flavored `{ sql, params }` payload.\n *\n * Shared between the runtime (`PostgresAdapterImpl.lower`) and control (`PostgresControlAdapter.lower`) entrypoints so emit-time and run-time paths produce byte-identical output for the same AST.\n */\nexport function renderLoweredSql(\n ast: AnyQueryAst,\n contract: PostgresContract,\n codecLookup: CodecLookup,\n): { readonly sql: string; readonly params: readonly LoweredParam[] } {\n const orderedRefs = collectOrderedParamRefs(ast);\n const indexMap = new Map<AnyParamRef, number>();\n const params: LoweredParam[] = orderedRefs.map((ref, i) => {\n indexMap.set(ref, i + 1);\n return ref.kind === 'prepared-param-ref'\n ? { kind: 'bind', name: ref.name }\n : { kind: 'literal', value: ref.value };\n });\n const pim: ParamIndexMap = { indexMap, codecLookup };\n\n const node = ast;\n let sql: string;\n switch (node.kind) {\n case 'select':\n sql = renderSelect(node, contract, pim);\n break;\n case 'insert':\n sql = renderInsert(node, contract, pim);\n break;\n case 'update':\n sql = renderUpdate(node, contract, pim);\n break;\n case 'delete':\n sql = renderDelete(node, contract, pim);\n break;\n case 'raw-sql':\n sql = renderRawSql(node, contract, pim);\n break;\n // v8 ignore next 4\n default:\n throw new Error(\n `Unsupported AST node kind: ${(node satisfies never as { kind: string }).kind}`,\n );\n }\n\n return Object.freeze({ sql, params: Object.freeze(params) });\n}\n\nfunction renderLimitOffset(\n keyword: 'LIMIT' | 'OFFSET',\n value: SelectAst['limit'] | SelectAst['offset'],\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n if (value === undefined) return '';\n if (typeof value === 'number') return `${keyword} ${value}`;\n return `${keyword} ${renderExpr(value, contract, pim)}`;\n}\n\nfunction renderSelect(ast: SelectAst, contract: PostgresContract, pim: ParamIndexMap): string {\n const selectClause = `SELECT ${renderDistinctPrefix(ast.distinct, ast.distinctOn, contract, pim)}${renderProjection(\n ast.projection,\n contract,\n pim,\n )}`;\n const fromClause = `FROM ${renderSource(ast.from, contract, pim)}`;\n\n const joinsClause = ast.joins?.length\n ? ast.joins.map((join) => renderJoin(join, contract, pim)).join(' ')\n : '';\n\n const whereClause = ast.where ? `WHERE ${renderWhere(ast.where, contract, pim)}` : '';\n const groupByClause = ast.groupBy?.length\n ? `GROUP BY ${ast.groupBy.map((expr) => renderExpr(expr, contract, pim)).join(', ')}`\n : '';\n const havingClause = ast.having ? `HAVING ${renderWhere(ast.having, contract, pim)}` : '';\n const orderClause = ast.orderBy?.length\n ? `ORDER BY ${ast.orderBy\n .map((order) => {\n const expr = renderExpr(order.expr, contract, pim);\n return `${expr} ${order.dir.toUpperCase()}`;\n })\n .join(', ')}`\n : '';\n const limitClause = renderLimitOffset('LIMIT', ast.limit, contract, pim);\n const offsetClause = renderLimitOffset('OFFSET', ast.offset, contract, pim);\n\n const clauses = [\n selectClause,\n fromClause,\n joinsClause,\n whereClause,\n groupByClause,\n havingClause,\n orderClause,\n limitClause,\n offsetClause,\n ]\n .filter((part) => part.length > 0)\n .join(' ');\n return clauses.trim();\n}\n\nfunction renderProjection(\n projection: ReadonlyArray<ProjectionItem>,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n return projection\n .map((item) => {\n const alias = quoteIdentifier(item.alias);\n if (item.expr.kind === 'literal') {\n return `${renderLiteral(item.expr)} AS ${alias}`;\n }\n return `${renderExpr(item.expr, contract, pim)} AS ${alias}`;\n })\n .join(', ');\n}\n\nfunction renderReturning(\n items: ReadonlyArray<ProjectionItem>,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n return items\n .map((item) => {\n if (item.expr.kind === 'column-ref') {\n const rendered = renderColumn(item.expr);\n return item.expr.column === item.alias\n ? rendered\n : `${rendered} AS ${quoteIdentifier(item.alias)}`;\n }\n if (item.expr.kind === 'literal') {\n return `${renderLiteral(item.expr)} AS ${quoteIdentifier(item.alias)}`;\n }\n return `${renderExpr(item.expr, contract, pim)} AS ${quoteIdentifier(item.alias)}`;\n })\n .join(', ');\n}\n\nfunction renderDistinctPrefix(\n distinct: true | undefined,\n distinctOn: ReadonlyArray<AnyExpression> | undefined,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n if (distinctOn && distinctOn.length > 0) {\n const rendered = distinctOn.map((expr) => renderExpr(expr, contract, pim)).join(', ');\n return `DISTINCT ON (${rendered}) `;\n }\n if (distinct) {\n return 'DISTINCT ';\n }\n return '';\n}\n\nfunction renderSource(\n source: AnyFromSource,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const node = source;\n switch (node.kind) {\n case 'table-source': {\n const table = quoteIdentifier(node.name);\n if (!node.alias) {\n return table;\n }\n return `${table} AS ${quoteIdentifier(node.alias)}`;\n }\n case 'derived-table-source':\n return `(${renderSelect(node.query, contract, pim)}) AS ${quoteIdentifier(node.alias)}`;\n // v8 ignore next 4\n default:\n throw new Error(\n `Unsupported source node kind: ${(node satisfies never as { kind: string }).kind}`,\n );\n }\n}\n\nfunction assertScalarSubquery(query: SelectAst): void {\n if (query.projection.length !== 1) {\n throw new Error('Subquery expressions must project exactly one column');\n }\n}\n\nfunction renderSubqueryExpr(\n expr: SubqueryExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n assertScalarSubquery(expr.query);\n return `(${renderSelect(expr.query, contract, pim)})`;\n}\n\nfunction renderWhere(expr: AnyExpression, contract: PostgresContract, pim: ParamIndexMap): string {\n return renderExpr(expr, contract, pim);\n}\n\nfunction renderNullCheck(\n expr: NullCheckExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const rendered = renderExpr(expr.expr, contract, pim);\n const renderedExpr = isAtomicExpressionKind(expr.expr.kind) ? rendered : `(${rendered})`;\n return expr.isNull ? `${renderedExpr} IS NULL` : `${renderedExpr} IS NOT NULL`;\n}\n\n/**\n * Atomic expression kinds whose rendered SQL is already self-delimited (a column reference, parameter, literal, function call, aggregate, etc.) and therefore does not need surrounding parentheses when used as the left operand of a postfix predicate like `IS NULL` or `IS NOT NULL`, or as either operand of a binary infix operator.\n *\n * Anything not in this set is treated as composite (binary, AND/OR/NOT, EXISTS, nested IS NULL, subqueries, operation templates) and gets wrapped to preserve grouping.\n */\nfunction isAtomicExpressionKind(kind: AnyExpression['kind']): boolean {\n switch (kind) {\n case 'column-ref':\n case 'identifier-ref':\n case 'param-ref':\n case 'prepared-param-ref':\n case 'literal':\n case 'aggregate':\n case 'window-func':\n case 'json-object':\n case 'json-array-agg':\n case 'list':\n return true;\n case 'subquery':\n case 'operation':\n case 'binary':\n case 'and':\n case 'or':\n case 'exists':\n case 'null-check':\n case 'not':\n case 'raw-expr':\n return false;\n }\n}\n\nfunction renderBinary(expr: BinaryExpr, contract: PostgresContract, pim: ParamIndexMap): string {\n if (expr.right.kind === 'list' && expr.right.values.length === 0) {\n if (expr.op === 'in') {\n return 'FALSE';\n }\n if (expr.op === 'notIn') {\n return 'TRUE';\n }\n }\n\n const leftExpr = expr.left;\n const left = renderExpr(leftExpr, contract, pim);\n const leftRendered =\n leftExpr.kind === 'operation' || leftExpr.kind === 'subquery' ? `(${left})` : left;\n\n const rightNode = expr.right;\n let right: string;\n switch (rightNode.kind) {\n case 'list':\n right = renderListLiteral(rightNode, contract, pim);\n break;\n case 'literal':\n right = renderLiteral(rightNode);\n break;\n case 'column-ref':\n right = renderColumn(rightNode);\n break;\n case 'param-ref':\n case 'prepared-param-ref':\n right = renderParamRef(rightNode, pim);\n break;\n default:\n right = renderExpr(rightNode, contract, pim);\n break;\n }\n\n const operatorMap: Record<BinaryExpr['op'], string> = {\n eq: '=',\n neq: '!=',\n gt: '>',\n lt: '<',\n gte: '>=',\n lte: '<=',\n like: 'LIKE',\n in: 'IN',\n notIn: 'NOT IN',\n };\n\n return `${leftRendered} ${operatorMap[expr.op]} ${right}`;\n}\n\nfunction renderListLiteral(\n expr: ListExpression,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n if (expr.values.length === 0) {\n return '(NULL)';\n }\n const values = expr.values\n .map((v) => {\n if (v.kind === 'param-ref' || v.kind === 'prepared-param-ref') {\n return renderParamRef(v, pim);\n }\n if (v.kind === 'literal') return renderLiteral(v);\n return renderExpr(v, contract, pim);\n })\n .join(', ');\n return `(${values})`;\n}\n\nfunction renderColumn(ref: ColumnRef): string {\n if (ref.table === 'excluded') {\n return `excluded.${quoteIdentifier(ref.column)}`;\n }\n return `${quoteIdentifier(ref.table)}.${quoteIdentifier(ref.column)}`;\n}\n\nfunction renderAggregateExpr(\n expr: AggregateExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const fn = expr.fn.toUpperCase();\n if (!expr.expr) {\n return `${fn}(*)`;\n }\n return `${fn}(${renderExpr(expr.expr, contract, pim)})`;\n}\n\nfunction renderWindowFuncExpr(\n expr: WindowFuncExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const fn = expr.fn.toUpperCase();\n const args = expr.args.map((arg) => renderExpr(arg, contract, pim)).join(', ');\n const partitionClause =\n expr.partitionBy && expr.partitionBy.length > 0\n ? `PARTITION BY ${expr.partitionBy.map((e) => renderExpr(e, contract, pim)).join(', ')}`\n : '';\n const orderClause =\n expr.orderBy && expr.orderBy.length > 0\n ? `ORDER BY ${renderOrderByItems(expr.orderBy, contract, pim)}`\n : '';\n const over = [partitionClause, orderClause].filter((part) => part.length > 0).join(' ');\n return `${fn}(${args}) OVER (${over})`;\n}\n\nfunction renderJsonObjectExpr(\n expr: JsonObjectExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const args = expr.entries\n .flatMap((entry): [string, string] => {\n const key = `'${escapeLiteral(entry.key)}'`;\n if (entry.value.kind === 'literal') {\n return [key, renderLiteral(entry.value)];\n }\n return [key, renderExpr(entry.value, contract, pim)];\n })\n .join(', ');\n return `json_build_object(${args})`;\n}\n\nfunction renderOrderByItems(\n items: ReadonlyArray<OrderByItem>,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n return items\n .map((item) => `${renderExpr(item.expr, contract, pim)} ${item.dir.toUpperCase()}`)\n .join(', ');\n}\n\nfunction renderJsonArrayAggExpr(\n expr: JsonArrayAggExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const aggregateOrderBy =\n expr.orderBy && expr.orderBy.length > 0\n ? ` ORDER BY ${renderOrderByItems(expr.orderBy, contract, pim)}`\n : '';\n const aggregated = `json_agg(${renderExpr(expr.expr, contract, pim)}${aggregateOrderBy})`;\n if (expr.onEmpty === 'emptyArray') {\n return `coalesce(${aggregated}, json_build_array())`;\n }\n return aggregated;\n}\n\nfunction renderExpr(expr: AnyExpression, contract: PostgresContract, pim: ParamIndexMap): string {\n const node = expr;\n switch (node.kind) {\n case 'column-ref':\n return renderColumn(node);\n case 'identifier-ref':\n return quoteIdentifier(node.name);\n case 'operation':\n return renderOperation(node, contract, pim);\n case 'subquery':\n return renderSubqueryExpr(node, contract, pim);\n case 'aggregate':\n return renderAggregateExpr(node, contract, pim);\n case 'window-func':\n return renderWindowFuncExpr(node, contract, pim);\n case 'json-object':\n return renderJsonObjectExpr(node, contract, pim);\n case 'json-array-agg':\n return renderJsonArrayAggExpr(node, contract, pim);\n case 'binary':\n return renderBinary(node, contract, pim);\n case 'and':\n if (node.exprs.length === 0) {\n return 'TRUE';\n }\n return `(${node.exprs.map((part) => renderExpr(part, contract, pim)).join(' AND ')})`;\n case 'or':\n if (node.exprs.length === 0) {\n return 'FALSE';\n }\n return `(${node.exprs.map((part) => renderExpr(part, contract, pim)).join(' OR ')})`;\n case 'exists': {\n const notKeyword = node.notExists ? 'NOT ' : '';\n const subquery = renderSelect(node.subquery, contract, pim);\n return `${notKeyword}EXISTS (${subquery})`;\n }\n case 'null-check':\n return renderNullCheck(node, contract, pim);\n case 'not':\n return `NOT (${renderExpr(node.expr, contract, pim)})`;\n case 'param-ref':\n case 'prepared-param-ref':\n return renderParamRef(node, pim);\n case 'literal':\n return renderLiteral(node);\n case 'list':\n return renderListLiteral(node, contract, pim);\n case 'raw-expr':\n return renderRawExpr(node, contract, pim);\n // v8 ignore next 4\n default:\n throw new Error(\n `Unsupported expression node kind: ${(node satisfies never as { kind: string }).kind}`,\n );\n }\n}\n\nfunction renderParamRef(ref: AnyParamRef, pim: ParamIndexMap): string {\n const index = pim.indexMap.get(ref);\n if (index === undefined) {\n throw new Error('ParamRef not found in index map');\n }\n if (ref.kind === 'prepared-param-ref') {\n return renderTypedParam(index, ref.codec.codecId, pim.codecLookup);\n }\n if (ref.codec === undefined) {\n throw runtimeError(\n 'RUNTIME.PARAM_REF_MISSING_CODEC',\n 'Postgres renderer: ParamRef reached lowering without a bound CodecRef. ' +\n 'Every column-bound ParamRef must carry a codec under the AST-bound codec contract. ' +\n 'This usually indicates a builder path that constructed a ParamRef without threading the column codec.',\n { paramIndex: index, ...ifDefined('name', ref.name) },\n );\n }\n return renderTypedParam(index, ref.codec.codecId, pim.codecLookup);\n}\n\nfunction renderLiteral(expr: LiteralExpr): string {\n if (typeof expr.value === 'string') {\n return `'${escapeLiteral(expr.value)}'`;\n }\n if (typeof expr.value === 'number' || typeof expr.value === 'boolean') {\n return String(expr.value);\n }\n if (typeof expr.value === 'bigint') {\n return String(expr.value);\n }\n if (expr.value === null) {\n return 'NULL';\n }\n if (expr.value === undefined) {\n return 'NULL';\n }\n if (expr.value instanceof Date) {\n return `'${escapeLiteral(expr.value.toISOString())}'`;\n }\n if (Array.isArray(expr.value)) {\n return `ARRAY[${expr.value.map((v: unknown) => renderLiteral(new LiteralExpr(v))).join(', ')}]`;\n }\n const json = JSON.stringify(expr.value);\n if (json === undefined) {\n return 'NULL';\n }\n return `'${escapeLiteral(json)}'`;\n}\n\nfunction renderOperation(\n expr: OperationExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const self = renderExpr(expr.self, contract, pim);\n const args = expr.args.map((arg) => {\n return renderExpr(arg, contract, pim);\n });\n\n // Resolve `{{self}}` and `{{argN}}` from the original template in a single pass. Doing this with sequential `String.prototype.replace` calls is unsafe: a substituted fragment can itself contain text that matches a later token (e.g. an arg literal containing the substring `{{arg1}}`), and the next iteration would corrupt it. A single regex callback never re-scans already-substituted output.\n return expr.lowering.template.replace(\n /\\{\\{self\\}\\}|\\{\\{arg(\\d+)\\}\\}/g,\n (token, argIndex: string | undefined) => {\n if (token === '{{self}}') {\n return self;\n }\n const arg = args[Number(argIndex)];\n if (arg === undefined) {\n throw new Error(\n `Operation lowering template for \"${expr.method}\" referenced missing argument {{arg${argIndex}}}; template has ${args.length} arg(s)`,\n );\n }\n return arg;\n },\n );\n}\n\nfunction renderJoin(join: JoinAst, contract: PostgresContract, pim: ParamIndexMap): string {\n const joinType = join.joinType.toUpperCase();\n const lateral = join.lateral ? 'LATERAL ' : '';\n const source = renderSource(join.source, contract, pim);\n const onClause = renderJoinOn(join.on, contract, pim);\n return `${joinType} JOIN ${lateral}${source} ON ${onClause}`;\n}\n\nfunction renderJoinOn(on: JoinOnExpr, contract: PostgresContract, pim: ParamIndexMap): string {\n if (on.kind === 'eq-col-join-on') {\n const left = renderColumn(on.left);\n const right = renderColumn(on.right);\n return `${left} = ${right}`;\n }\n return renderWhere(on, contract, pim);\n}\n\nfunction getInsertColumnOrder(\n rows: ReadonlyArray<Record<string, InsertValue>>,\n contract: PostgresContract,\n tableName: string,\n): string[] {\n const orderedColumns: string[] = [];\n const seenColumns = new Set<string>();\n\n for (const row of rows) {\n for (const column of Object.keys(row)) {\n if (seenColumns.has(column)) {\n continue;\n }\n seenColumns.add(column);\n orderedColumns.push(column);\n }\n }\n\n if (orderedColumns.length > 0) {\n return orderedColumns;\n }\n\n let table: { columns: Record<string, unknown> } | undefined;\n for (const ns of Object.values(contract.storage.namespaces)) {\n // Namespace.tables is Record<string, IRNode> at the interface level;\n // SQL family namespaces hold StorageTable instances which have .columns.\n const found = ns.tables[tableName] as { columns: Record<string, unknown> } | undefined;\n if (found !== undefined) {\n table = found;\n break;\n }\n }\n if (!table) {\n throw new Error(`INSERT target table not found in contract storage: ${tableName}`);\n }\n return Object.keys(table.columns);\n}\n\nfunction renderInsertValue(value: InsertValue | undefined, pim: ParamIndexMap): string {\n if (!value || value.kind === 'default-value') {\n return 'DEFAULT';\n }\n\n switch (value.kind) {\n case 'param-ref':\n case 'prepared-param-ref':\n return renderParamRef(value, pim);\n case 'column-ref':\n return renderColumn(value);\n // v8 ignore next 4\n default:\n throw new Error(\n `Unsupported value node in INSERT: ${(value satisfies never as { kind: string }).kind}`,\n );\n }\n}\n\nfunction renderInsert(ast: InsertAst, contract: PostgresContract, pim: ParamIndexMap): string {\n const table = quoteIdentifier(ast.table.name);\n const rows = ast.rows;\n if (rows.length === 0) {\n throw new Error('INSERT requires at least one row');\n }\n const hasExplicitValues = rows.some((row) => Object.keys(row).length > 0);\n const insertClause = (() => {\n if (!hasExplicitValues) {\n if (rows.length === 1) {\n return `INSERT INTO ${table} DEFAULT VALUES`;\n }\n\n const defaultColumns = getInsertColumnOrder(rows, contract, ast.table.name);\n if (defaultColumns.length === 0) {\n return `INSERT INTO ${table} VALUES ${rows.map(() => '()').join(', ')}`;\n }\n\n const quotedColumns = defaultColumns.map((column) => quoteIdentifier(column));\n const defaultRow = `(${defaultColumns.map(() => 'DEFAULT').join(', ')})`;\n return `INSERT INTO ${table} (${quotedColumns.join(', ')}) VALUES ${rows\n .map(() => defaultRow)\n .join(', ')}`;\n }\n\n const columnOrder = getInsertColumnOrder(rows, contract, ast.table.name);\n const columns = columnOrder.map((column) => quoteIdentifier(column));\n const values = rows\n .map((row) => {\n const renderedRow = columnOrder.map((column) => renderInsertValue(row[column], pim));\n return `(${renderedRow.join(', ')})`;\n })\n .join(', ');\n\n return `INSERT INTO ${table} (${columns.join(', ')}) VALUES ${values}`;\n })();\n const onConflictClause = ast.onConflict\n ? (() => {\n const conflictColumns = ast.onConflict.columns.map((col) => quoteIdentifier(col.column));\n if (conflictColumns.length === 0) {\n throw new Error('INSERT onConflict requires at least one conflict column');\n }\n\n const action = ast.onConflict.action;\n switch (action.kind) {\n case 'do-nothing':\n return ` ON CONFLICT (${conflictColumns.join(', ')}) DO NOTHING`;\n case 'do-update-set': {\n const updateEntries = Object.entries(action.set);\n if (updateEntries.length === 0) {\n throw new Error('INSERT onConflict do-update-set requires at least one assignment');\n }\n const updates = updateEntries.map(([colName, value]) => {\n return `${quoteIdentifier(colName)} = ${renderExpr(value, contract, pim)}`;\n });\n return ` ON CONFLICT (${conflictColumns.join(', ')}) DO UPDATE SET ${updates.join(', ')}`;\n }\n // v8 ignore next 4\n default:\n throw new Error(\n `Unsupported onConflict action: ${(action satisfies never as { kind: string }).kind}`,\n );\n }\n })()\n : '';\n const returningClause = ast.returning?.length\n ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}`\n : '';\n\n return `${insertClause}${onConflictClause}${returningClause}`;\n}\n\nfunction renderUpdate(ast: UpdateAst, contract: PostgresContract, pim: ParamIndexMap): string {\n const table = quoteIdentifier(ast.table.name);\n const setEntries = Object.entries(ast.set);\n if (setEntries.length === 0) {\n throw new Error('UPDATE requires at least one SET assignment');\n }\n const setClauses = setEntries.map(([col, val]) => {\n const column = quoteIdentifier(col);\n return `${column} = ${renderExpr(val, contract, pim)}`;\n });\n\n const whereClause = ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : '';\n const returningClause = ast.returning?.length\n ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}`\n : '';\n\n return `UPDATE ${table} SET ${setClauses.join(', ')}${whereClause}${returningClause}`;\n}\n\nfunction renderDelete(ast: DeleteAst, contract: PostgresContract, pim: ParamIndexMap): string {\n const table = quoteIdentifier(ast.table.name);\n const whereClause = ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : '';\n const returningClause = ast.returning?.length\n ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}`\n : '';\n\n return `DELETE FROM ${table}${whereClause}${returningClause}`;\n}\n\nfunction renderRawSql(ast: RawSqlExpr, contract: PostgresContract, pim: ParamIndexMap): string {\n const out: string[] = [];\n for (let i = 0; i < ast.fragments.length; i++) {\n out.push(ast.fragments[i] ?? '');\n if (i < ast.args.length) {\n const arg = ast.args[i];\n if (arg !== undefined) {\n out.push(renderExpr(arg, contract, pim));\n }\n }\n }\n return out.join('');\n}\n\nfunction renderRawExpr(node: RawExpr, contract: PostgresContract, pim: ParamIndexMap): string {\n return node.parts\n .map((part) => (typeof part === 'string' ? part : renderExpr(part, contract, pim)))\n .join('');\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/adapter-postgres",
|
|
3
|
-
"version": "0.12.0-dev.
|
|
3
|
+
"version": "0.12.0-dev.3",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@prisma-next/contract": "0.12.0-dev.
|
|
9
|
-
"@prisma-next/contract-authoring": "0.12.0-dev.
|
|
10
|
-
"@prisma-next/errors": "0.12.0-dev.
|
|
11
|
-
"@prisma-next/family-sql": "0.12.0-dev.
|
|
12
|
-
"@prisma-next/framework-components": "0.12.0-dev.
|
|
13
|
-
"@prisma-next/ids": "0.12.0-dev.
|
|
14
|
-
"@prisma-next/sql-contract": "0.12.0-dev.
|
|
15
|
-
"@prisma-next/sql-contract-psl": "0.12.0-dev.
|
|
16
|
-
"@prisma-next/sql-contract-ts": "0.12.0-dev.
|
|
17
|
-
"@prisma-next/sql-operations": "0.12.0-dev.
|
|
18
|
-
"@prisma-next/sql-relational-core": "0.12.0-dev.
|
|
19
|
-
"@prisma-next/sql-runtime": "0.12.0-dev.
|
|
20
|
-
"@prisma-next/sql-schema-ir": "0.12.0-dev.
|
|
21
|
-
"@prisma-next/target-postgres": "0.12.0-dev.
|
|
22
|
-
"@prisma-next/utils": "0.12.0-dev.
|
|
8
|
+
"@prisma-next/contract": "0.12.0-dev.3",
|
|
9
|
+
"@prisma-next/contract-authoring": "0.12.0-dev.3",
|
|
10
|
+
"@prisma-next/errors": "0.12.0-dev.3",
|
|
11
|
+
"@prisma-next/family-sql": "0.12.0-dev.3",
|
|
12
|
+
"@prisma-next/framework-components": "0.12.0-dev.3",
|
|
13
|
+
"@prisma-next/ids": "0.12.0-dev.3",
|
|
14
|
+
"@prisma-next/sql-contract": "0.12.0-dev.3",
|
|
15
|
+
"@prisma-next/sql-contract-psl": "0.12.0-dev.3",
|
|
16
|
+
"@prisma-next/sql-contract-ts": "0.12.0-dev.3",
|
|
17
|
+
"@prisma-next/sql-operations": "0.12.0-dev.3",
|
|
18
|
+
"@prisma-next/sql-relational-core": "0.12.0-dev.3",
|
|
19
|
+
"@prisma-next/sql-runtime": "0.12.0-dev.3",
|
|
20
|
+
"@prisma-next/sql-schema-ir": "0.12.0-dev.3",
|
|
21
|
+
"@prisma-next/target-postgres": "0.12.0-dev.3",
|
|
22
|
+
"@prisma-next/utils": "0.12.0-dev.3",
|
|
23
23
|
"arktype": "^2.2.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@prisma-next/cli": "0.12.0-dev.
|
|
27
|
-
"@prisma-next/driver-postgres": "0.12.0-dev.
|
|
28
|
-
"@prisma-next/migration-tools": "0.12.0-dev.
|
|
29
|
-
"@prisma-next/test-utils": "0.12.0-dev.
|
|
30
|
-
"@prisma-next/tsconfig": "0.12.0-dev.
|
|
31
|
-
"@prisma-next/tsdown": "0.12.0-dev.
|
|
26
|
+
"@prisma-next/cli": "0.12.0-dev.3",
|
|
27
|
+
"@prisma-next/driver-postgres": "0.12.0-dev.3",
|
|
28
|
+
"@prisma-next/migration-tools": "0.12.0-dev.3",
|
|
29
|
+
"@prisma-next/test-utils": "0.12.0-dev.3",
|
|
30
|
+
"@prisma-next/tsconfig": "0.12.0-dev.3",
|
|
31
|
+
"@prisma-next/tsdown": "0.12.0-dev.3",
|
|
32
32
|
"pathe": "^2.0.3",
|
|
33
33
|
"tsdown": "0.22.0",
|
|
34
34
|
"typescript": "5.9.3",
|
package/src/core/adapter.ts
CHANGED
|
@@ -9,12 +9,9 @@ import type {
|
|
|
9
9
|
RawSqlLiteral,
|
|
10
10
|
SqlQueryable,
|
|
11
11
|
} from '@prisma-next/sql-relational-core/ast';
|
|
12
|
-
import { isDdlNode } from '@prisma-next/sql-relational-core/ast';
|
|
13
12
|
import type { RawCodecInferer } from '@prisma-next/sql-relational-core/expression';
|
|
14
13
|
import { parseContractMarkerRow } from '@prisma-next/sql-runtime';
|
|
15
|
-
import type { PostgresDdlNode } from '@prisma-next/target-postgres/ddl';
|
|
16
14
|
import { createPostgresBuiltinCodecLookup } from './codec-lookup';
|
|
17
|
-
import { renderLoweredDdl } from './ddl-renderer';
|
|
18
15
|
import { renderLoweredSql } from './sql-renderer';
|
|
19
16
|
import type { PostgresAdapterOptions, PostgresContract, PostgresLoweredStatement } from './types';
|
|
20
17
|
|
|
@@ -55,13 +52,7 @@ class PostgresAdapterImpl
|
|
|
55
52
|
});
|
|
56
53
|
}
|
|
57
54
|
|
|
58
|
-
lower(
|
|
59
|
-
ast: AnyQueryAst | PostgresDdlNode,
|
|
60
|
-
context: LowererContext<PostgresContract>,
|
|
61
|
-
): PostgresLoweredStatement {
|
|
62
|
-
if (isDdlNode(ast)) {
|
|
63
|
-
return renderLoweredDdl(ast);
|
|
64
|
-
}
|
|
55
|
+
lower(ast: AnyQueryAst, context: LowererContext<PostgresContract>): PostgresLoweredStatement {
|
|
65
56
|
return renderLoweredSql(ast, context.contract, this.codecLookup);
|
|
66
57
|
}
|
|
67
58
|
}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
Contract,
|
|
3
|
-
ContractMarkerRecord,
|
|
4
|
-
LedgerEntryRecord,
|
|
5
|
-
} from '@prisma-next/contract/types';
|
|
1
|
+
import type { Contract, ContractMarkerRecord } from '@prisma-next/contract/types';
|
|
6
2
|
import { parseMarkerRowSafely, withMarkerReadErrorHandling } from '@prisma-next/errors/execution';
|
|
7
3
|
import type { SqlControlAdapter } from '@prisma-next/family-sql/control-adapter';
|
|
8
4
|
import { parseContractMarkerRow } from '@prisma-next/family-sql/verify';
|
|
@@ -12,15 +8,12 @@ import {
|
|
|
12
8
|
type ControlDriverInstance,
|
|
13
9
|
} from '@prisma-next/framework-components/control';
|
|
14
10
|
import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
|
|
15
|
-
import { ledgerOriginFromStored } from '@prisma-next/migration-tools/ledger-origin';
|
|
16
11
|
import type { PostgresEnumStorageEntry, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
17
12
|
import type {
|
|
18
13
|
AnyQueryAst,
|
|
19
|
-
DdlNode,
|
|
20
14
|
LoweredStatement,
|
|
21
15
|
LowererContext,
|
|
22
16
|
} from '@prisma-next/sql-relational-core/ast';
|
|
23
|
-
import { isDdlNode } from '@prisma-next/sql-relational-core/ast';
|
|
24
17
|
import type {
|
|
25
18
|
PrimaryKey,
|
|
26
19
|
SqlColumnIR,
|
|
@@ -31,12 +24,6 @@ import type {
|
|
|
31
24
|
SqlTableIR,
|
|
32
25
|
SqlUniqueIR,
|
|
33
26
|
} from '@prisma-next/sql-schema-ir/types';
|
|
34
|
-
import { postgresColumnsCompatible } from '@prisma-next/target-postgres/column-type-compatibility';
|
|
35
|
-
import {
|
|
36
|
-
buildControlTableBootstrapQueries,
|
|
37
|
-
buildSignMarkerBootstrapQueries,
|
|
38
|
-
} from '@prisma-next/target-postgres/contract-free';
|
|
39
|
-
import type { PostgresDdlNode } from '@prisma-next/target-postgres/ddl';
|
|
40
27
|
import { parsePostgresDefault } from '@prisma-next/target-postgres/default-normalizer';
|
|
41
28
|
import {
|
|
42
29
|
createResolveExistingEnumValues,
|
|
@@ -48,7 +35,6 @@ import { normalizeSchemaNativeType } from '@prisma-next/target-postgres/native-t
|
|
|
48
35
|
import { blindCast } from '@prisma-next/utils/casts';
|
|
49
36
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
50
37
|
import { createPostgresBuiltinCodecLookup } from './codec-lookup';
|
|
51
|
-
import { renderLoweredDdl } from './ddl-renderer';
|
|
52
38
|
import {
|
|
53
39
|
introspectPostgresEnumTypes,
|
|
54
40
|
type PostgresEnumStorageTypeAnnotation,
|
|
@@ -57,7 +43,6 @@ import { renderLoweredSql } from './sql-renderer';
|
|
|
57
43
|
import type { PostgresContract } from './types';
|
|
58
44
|
|
|
59
45
|
const POSTGRES_MARKER_TABLE = 'prisma_contract.marker';
|
|
60
|
-
const POSTGRES_LEDGER_TABLE = 'prisma_contract.ledger';
|
|
61
46
|
|
|
62
47
|
/**
|
|
63
48
|
* Postgres control plane adapter for control-plane operations like introspection.
|
|
@@ -93,13 +78,6 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
|
|
|
93
78
|
*/
|
|
94
79
|
readonly normalizeNativeType = normalizeSchemaNativeType;
|
|
95
80
|
|
|
96
|
-
/**
|
|
97
|
-
* Target-supplied compatible-shape relation used under the `external`
|
|
98
|
-
* control policy. Threading the same relation the migration planner/runner
|
|
99
|
-
* use keeps runtime verify and migration verify in agreement.
|
|
100
|
-
*/
|
|
101
|
-
readonly columnsCompatible = postgresColumnsCompatible;
|
|
102
|
-
|
|
103
81
|
/**
|
|
104
82
|
* Bridges native `PostgresEnumStorageEntry` IR walks against the Postgres
|
|
105
83
|
* introspection shape (`schema.annotations.pg.storageTypes`). Lets
|
|
@@ -121,14 +99,6 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
|
|
|
121
99
|
readonly resolveExistingEnumValuesForContract = (contract: Contract<SqlStorage>) =>
|
|
122
100
|
createResolveExistingEnumValues(contract.storage);
|
|
123
101
|
|
|
124
|
-
bootstrapControlTableQueries(): readonly DdlNode[] {
|
|
125
|
-
return buildControlTableBootstrapQueries();
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
bootstrapSignMarkerQueries(): readonly DdlNode[] {
|
|
129
|
-
return buildSignMarkerBootstrapQueries();
|
|
130
|
-
}
|
|
131
|
-
|
|
132
102
|
/**
|
|
133
103
|
* Lower a SQL query AST into a Postgres-flavored `{ sql, params }` payload.
|
|
134
104
|
*
|
|
@@ -137,10 +107,7 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
|
|
|
137
107
|
* and contract. Used at migration plan/emit time (e.g. by `dataTransform`)
|
|
138
108
|
* without instantiating the runtime adapter.
|
|
139
109
|
*/
|
|
140
|
-
lower(ast: AnyQueryAst
|
|
141
|
-
if (isDdlNode(ast)) {
|
|
142
|
-
return renderLoweredDdl(ast);
|
|
143
|
-
}
|
|
110
|
+
lower(ast: AnyQueryAst, context: LowererContext<unknown>): LoweredStatement {
|
|
144
111
|
return renderLoweredSql(ast, context.contract as PostgresContract, this.codecLookup);
|
|
145
112
|
}
|
|
146
113
|
|
|
@@ -269,69 +236,6 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
|
|
|
269
236
|
return rows;
|
|
270
237
|
}
|
|
271
238
|
|
|
272
|
-
/**
|
|
273
|
-
* Reads per-migration ledger rows for `space` from `prisma_contract.ledger`
|
|
274
|
-
* in apply order. Probes `information_schema.tables` first so a fresh
|
|
275
|
-
* database without the ledger table returns `[]` instead of raising
|
|
276
|
-
* "relation does not exist".
|
|
277
|
-
*/
|
|
278
|
-
async readLedger(
|
|
279
|
-
driver: ControlDriverInstance<'sql', 'postgres'>,
|
|
280
|
-
space: string,
|
|
281
|
-
): Promise<readonly LedgerEntryRecord[]> {
|
|
282
|
-
const ledgerContext = { space, markerLocation: POSTGRES_LEDGER_TABLE };
|
|
283
|
-
const exists = await withMarkerReadErrorHandling(
|
|
284
|
-
() =>
|
|
285
|
-
driver.query(
|
|
286
|
-
`select 1
|
|
287
|
-
from information_schema.tables
|
|
288
|
-
where table_schema = $1 and table_name = $2`,
|
|
289
|
-
['prisma_contract', 'ledger'],
|
|
290
|
-
),
|
|
291
|
-
ledgerContext,
|
|
292
|
-
);
|
|
293
|
-
if (exists.rows.length === 0) {
|
|
294
|
-
return [];
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
const result = await withMarkerReadErrorHandling(
|
|
298
|
-
() =>
|
|
299
|
-
driver.query<{
|
|
300
|
-
space: string;
|
|
301
|
-
migration_name: string;
|
|
302
|
-
migration_hash: string;
|
|
303
|
-
origin_core_hash: string | null;
|
|
304
|
-
destination_core_hash: string;
|
|
305
|
-
operations: unknown;
|
|
306
|
-
created_at: Date | string;
|
|
307
|
-
}>(
|
|
308
|
-
`select
|
|
309
|
-
space,
|
|
310
|
-
migration_name,
|
|
311
|
-
migration_hash,
|
|
312
|
-
origin_core_hash,
|
|
313
|
-
destination_core_hash,
|
|
314
|
-
operations,
|
|
315
|
-
created_at
|
|
316
|
-
from prisma_contract.ledger
|
|
317
|
-
where space = $1
|
|
318
|
-
order by id`,
|
|
319
|
-
[space],
|
|
320
|
-
),
|
|
321
|
-
ledgerContext,
|
|
322
|
-
);
|
|
323
|
-
|
|
324
|
-
return result.rows.map((row) => ({
|
|
325
|
-
space: row.space,
|
|
326
|
-
migrationName: row.migration_name,
|
|
327
|
-
migrationHash: row.migration_hash,
|
|
328
|
-
from: ledgerOriginFromStored(row.origin_core_hash),
|
|
329
|
-
to: row.destination_core_hash,
|
|
330
|
-
appliedAt: row.created_at instanceof Date ? row.created_at : new Date(row.created_at),
|
|
331
|
-
operationCount: Array.isArray(row.operations) ? row.operations.length : 0,
|
|
332
|
-
}));
|
|
333
|
-
}
|
|
334
|
-
|
|
335
239
|
/**
|
|
336
240
|
* Introspects a Postgres database schema and returns a raw SqlSchemaIR.
|
|
337
241
|
*
|
package/src/core/sql-renderer.ts
CHANGED
|
@@ -27,7 +27,6 @@ import {
|
|
|
27
27
|
type RawSqlExpr,
|
|
28
28
|
type SelectAst,
|
|
29
29
|
type SubqueryExpr,
|
|
30
|
-
type TableSource,
|
|
31
30
|
type UpdateAst,
|
|
32
31
|
type WindowFuncExpr,
|
|
33
32
|
} from '@prisma-next/sql-relational-core/ast';
|
|
@@ -270,36 +269,6 @@ function renderDistinctPrefix(
|
|
|
270
269
|
return '';
|
|
271
270
|
}
|
|
272
271
|
|
|
273
|
-
function qualifyTableFromNamespaceCoordinate(
|
|
274
|
-
table: Pick<TableSource, 'name' | 'namespaceId'>,
|
|
275
|
-
contract: PostgresContract,
|
|
276
|
-
): string {
|
|
277
|
-
if (table.namespaceId === undefined) {
|
|
278
|
-
return quoteIdentifier(table.name);
|
|
279
|
-
}
|
|
280
|
-
const namespace = contract.storage.namespaces[table.namespaceId];
|
|
281
|
-
if (namespace === undefined) {
|
|
282
|
-
throw new Error(
|
|
283
|
-
`Table "${table.name}" references namespace "${table.namespaceId}" which is not present as a Postgres schema on the contract`,
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
const qualifyTable = namespace.qualifyTable;
|
|
287
|
-
if (qualifyTable === undefined) {
|
|
288
|
-
throw new Error(
|
|
289
|
-
`Table "${table.name}" references namespace "${table.namespaceId}" which is not materialised as a Postgres schema on the contract`,
|
|
290
|
-
);
|
|
291
|
-
}
|
|
292
|
-
return qualifyTable.call(namespace, table.name);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
function renderTableSource(source: TableSource, contract: PostgresContract): string {
|
|
296
|
-
const qualified = qualifyTableFromNamespaceCoordinate(source, contract);
|
|
297
|
-
if (!source.alias) {
|
|
298
|
-
return qualified;
|
|
299
|
-
}
|
|
300
|
-
return `${qualified} AS ${quoteIdentifier(source.alias)}`;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
272
|
function renderSource(
|
|
304
273
|
source: AnyFromSource,
|
|
305
274
|
contract: PostgresContract,
|
|
@@ -307,8 +276,13 @@ function renderSource(
|
|
|
307
276
|
): string {
|
|
308
277
|
const node = source;
|
|
309
278
|
switch (node.kind) {
|
|
310
|
-
case 'table-source':
|
|
311
|
-
|
|
279
|
+
case 'table-source': {
|
|
280
|
+
const table = quoteIdentifier(node.name);
|
|
281
|
+
if (!node.alias) {
|
|
282
|
+
return table;
|
|
283
|
+
}
|
|
284
|
+
return `${table} AS ${quoteIdentifier(node.alias)}`;
|
|
285
|
+
}
|
|
312
286
|
case 'derived-table-source':
|
|
313
287
|
return `(${renderSelect(node.query, contract, pim)}) AS ${quoteIdentifier(node.alias)}`;
|
|
314
288
|
// v8 ignore next 4
|
|
@@ -685,9 +659,8 @@ function renderJoinOn(on: JoinOnExpr, contract: PostgresContract, pim: ParamInde
|
|
|
685
659
|
function getInsertColumnOrder(
|
|
686
660
|
rows: ReadonlyArray<Record<string, InsertValue>>,
|
|
687
661
|
contract: PostgresContract,
|
|
688
|
-
|
|
662
|
+
tableName: string,
|
|
689
663
|
): string[] {
|
|
690
|
-
const tableName = tableRef.name;
|
|
691
664
|
const orderedColumns: string[] = [];
|
|
692
665
|
const seenColumns = new Set<string>();
|
|
693
666
|
|
|
@@ -706,22 +679,13 @@ function getInsertColumnOrder(
|
|
|
706
679
|
}
|
|
707
680
|
|
|
708
681
|
let table: { columns: Record<string, unknown> } | undefined;
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
682
|
+
for (const ns of Object.values(contract.storage.namespaces)) {
|
|
683
|
+
// Namespace.tables is Record<string, IRNode> at the interface level;
|
|
684
|
+
// SQL family namespaces hold StorageTable instances which have .columns.
|
|
685
|
+
const found = ns.tables[tableName] as { columns: Record<string, unknown> } | undefined;
|
|
712
686
|
if (found !== undefined) {
|
|
713
687
|
table = found;
|
|
714
|
-
|
|
715
|
-
}
|
|
716
|
-
if (table === undefined) {
|
|
717
|
-
for (const ns of Object.values(contract.storage.namespaces)) {
|
|
718
|
-
// Namespace.tables is Record<string, IRNode> at the interface level;
|
|
719
|
-
// SQL family namespaces hold StorageTable instances which have .columns.
|
|
720
|
-
const found = ns.tables[tableName] as { columns: Record<string, unknown> } | undefined;
|
|
721
|
-
if (found !== undefined) {
|
|
722
|
-
table = found;
|
|
723
|
-
break;
|
|
724
|
-
}
|
|
688
|
+
break;
|
|
725
689
|
}
|
|
726
690
|
}
|
|
727
691
|
if (!table) {
|
|
@@ -750,7 +714,7 @@ function renderInsertValue(value: InsertValue | undefined, pim: ParamIndexMap):
|
|
|
750
714
|
}
|
|
751
715
|
|
|
752
716
|
function renderInsert(ast: InsertAst, contract: PostgresContract, pim: ParamIndexMap): string {
|
|
753
|
-
const table =
|
|
717
|
+
const table = quoteIdentifier(ast.table.name);
|
|
754
718
|
const rows = ast.rows;
|
|
755
719
|
if (rows.length === 0) {
|
|
756
720
|
throw new Error('INSERT requires at least one row');
|
|
@@ -762,7 +726,7 @@ function renderInsert(ast: InsertAst, contract: PostgresContract, pim: ParamInde
|
|
|
762
726
|
return `INSERT INTO ${table} DEFAULT VALUES`;
|
|
763
727
|
}
|
|
764
728
|
|
|
765
|
-
const defaultColumns = getInsertColumnOrder(rows, contract, ast.table);
|
|
729
|
+
const defaultColumns = getInsertColumnOrder(rows, contract, ast.table.name);
|
|
766
730
|
if (defaultColumns.length === 0) {
|
|
767
731
|
return `INSERT INTO ${table} VALUES ${rows.map(() => '()').join(', ')}`;
|
|
768
732
|
}
|
|
@@ -774,7 +738,7 @@ function renderInsert(ast: InsertAst, contract: PostgresContract, pim: ParamInde
|
|
|
774
738
|
.join(', ')}`;
|
|
775
739
|
}
|
|
776
740
|
|
|
777
|
-
const columnOrder = getInsertColumnOrder(rows, contract, ast.table);
|
|
741
|
+
const columnOrder = getInsertColumnOrder(rows, contract, ast.table.name);
|
|
778
742
|
const columns = columnOrder.map((column) => quoteIdentifier(column));
|
|
779
743
|
const values = rows
|
|
780
744
|
.map((row) => {
|
|
@@ -822,7 +786,7 @@ function renderInsert(ast: InsertAst, contract: PostgresContract, pim: ParamInde
|
|
|
822
786
|
}
|
|
823
787
|
|
|
824
788
|
function renderUpdate(ast: UpdateAst, contract: PostgresContract, pim: ParamIndexMap): string {
|
|
825
|
-
const table =
|
|
789
|
+
const table = quoteIdentifier(ast.table.name);
|
|
826
790
|
const setEntries = Object.entries(ast.set);
|
|
827
791
|
if (setEntries.length === 0) {
|
|
828
792
|
throw new Error('UPDATE requires at least one SET assignment');
|
|
@@ -841,7 +805,7 @@ function renderUpdate(ast: UpdateAst, contract: PostgresContract, pim: ParamInde
|
|
|
841
805
|
}
|
|
842
806
|
|
|
843
807
|
function renderDelete(ast: DeleteAst, contract: PostgresContract, pim: ParamIndexMap): string {
|
|
844
|
-
const table =
|
|
808
|
+
const table = quoteIdentifier(ast.table.name);
|
|
845
809
|
const whereClause = ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : '';
|
|
846
810
|
const returningClause = ast.returning?.length
|
|
847
811
|
? ` RETURNING ${renderReturning(ast.returning, contract, pim)}`
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-Dr2W2Syq.mjs","names":[],"sources":["../src/core/adapter.ts"],"sourcesContent":["import type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport { APP_SPACE_ID } from '@prisma-next/framework-components/control';\nimport type {\n Adapter,\n AdapterProfile,\n AnyQueryAst,\n LowererContext,\n MarkerReadResult,\n RawSqlLiteral,\n SqlQueryable,\n} from '@prisma-next/sql-relational-core/ast';\nimport { isDdlNode } from '@prisma-next/sql-relational-core/ast';\nimport type { RawCodecInferer } from '@prisma-next/sql-relational-core/expression';\nimport { parseContractMarkerRow } from '@prisma-next/sql-runtime';\nimport type { PostgresDdlNode } from '@prisma-next/target-postgres/ddl';\nimport { createPostgresBuiltinCodecLookup } from './codec-lookup';\nimport { renderLoweredDdl } from './ddl-renderer';\nimport { renderLoweredSql } from './sql-renderer';\nimport type { PostgresAdapterOptions, PostgresContract, PostgresLoweredStatement } from './types';\n\nconst defaultCapabilities = Object.freeze({\n postgres: {\n orderBy: true,\n limit: true,\n lateral: true,\n jsonAgg: true,\n returning: true,\n distinctOn: true,\n },\n sql: {\n enums: true,\n returning: true,\n defaultInInsert: true,\n lateral: true,\n },\n});\n\nclass PostgresAdapterImpl\n implements Adapter<AnyQueryAst, PostgresContract, PostgresLoweredStatement>\n{\n // These fields make the adapter instance structurally compatible with RuntimeAdapterInstance<'sql', 'postgres'> without introducing a runtime-plane dependency.\n readonly familyId = 'sql' as const;\n readonly targetId = 'postgres' as const;\n\n readonly profile: AdapterProfile<'postgres'>;\n private readonly codecLookup: CodecLookup;\n\n constructor(options?: PostgresAdapterOptions) {\n this.codecLookup = options?.codecLookup ?? createPostgresBuiltinCodecLookup();\n this.profile = Object.freeze({\n id: options?.profileId ?? 'postgres/default@1',\n target: 'postgres',\n capabilities: defaultCapabilities,\n readMarker: (queryable: SqlQueryable) => readPostgresMarker(queryable),\n });\n }\n\n lower(\n ast: AnyQueryAst | PostgresDdlNode,\n context: LowererContext<PostgresContract>,\n ): PostgresLoweredStatement {\n if (isDdlNode(ast)) {\n return renderLoweredDdl(ast);\n }\n return renderLoweredSql(ast, context.contract, this.codecLookup);\n }\n}\n\n/** Codec-id lookup for bare-literal interpolations used by `fns.raw` on a postgres client. Contributed as the descriptor's static `rawCodecInferer` slot. */\nexport const postgresRawCodecInferer: RawCodecInferer = {\n inferCodec(value: RawSqlLiteral): string {\n switch (typeof value) {\n case 'number':\n return Number.isSafeInteger(value) && value % 1 === 0 ? 'pg/int4' : 'pg/float8';\n case 'bigint':\n return 'pg/int8';\n case 'string':\n return 'pg/text';\n case 'boolean':\n return 'pg/bool';\n case 'object':\n if (value instanceof Uint8Array) return 'pg/bytea';\n }\n throw new Error(\n 'unsupported JS value type for raw-SQL interpolation: wrap this value in `param(...)` with an explicit codec',\n );\n },\n};\n\nasync function readPostgresMarker(queryable: SqlQueryable): Promise<MarkerReadResult> {\n const exists = await queryable.query(\n 'select 1 from information_schema.tables where table_schema = $1 and table_name = $2',\n ['prisma_contract', 'marker'],\n );\n if (exists.rows.length === 0) {\n return { kind: 'no-table' };\n }\n\n const result = await queryable.query(\n 'select core_hash, profile_hash, contract_json, canonical_version, updated_at, app_tag, meta, invariants from prisma_contract.marker where space = $1',\n [APP_SPACE_ID],\n );\n const row = result.rows[0];\n if (!row) {\n return { kind: 'absent' };\n }\n // Postgres' driver hydrates `text[]` columns as native JS arrays, so the row is already in the shape the shared parser expects.\n return { kind: 'present', record: parseContractMarkerRow(row) };\n}\n\nexport function createPostgresAdapter(options?: PostgresAdapterOptions) {\n return Object.freeze(new PostgresAdapterImpl(options));\n}\n"],"mappings":";;;;;AAoBA,MAAM,sBAAsB,OAAO,OAAO;CACxC,UAAU;EACR,SAAS;EACT,OAAO;EACP,SAAS;EACT,SAAS;EACT,WAAW;EACX,YAAY;CACd;CACA,KAAK;EACH,OAAO;EACP,WAAW;EACX,iBAAiB;EACjB,SAAS;CACX;AACF,CAAC;AAED,IAAM,sBAAN,MAEA;CAEE,WAAoB;CACpB,WAAoB;CAEpB;CACA;CAEA,YAAY,SAAkC;EAC5C,KAAK,cAAc,SAAS,eAAe,iCAAiC;EAC5E,KAAK,UAAU,OAAO,OAAO;GAC3B,IAAI,SAAS,aAAa;GAC1B,QAAQ;GACR,cAAc;GACd,aAAa,cAA4B,mBAAmB,SAAS;EACvE,CAAC;CACH;CAEA,MACE,KACA,SAC0B;EAC1B,IAAI,UAAU,GAAG,GACf,OAAO,iBAAiB,GAAG;EAE7B,OAAO,iBAAiB,KAAK,QAAQ,UAAU,KAAK,WAAW;CACjE;AACF;;AAGA,MAAa,0BAA2C,EACtD,WAAW,OAA8B;CACvC,QAAQ,OAAO,OAAf;EACE,KAAK,UACH,OAAO,OAAO,cAAc,KAAK,KAAK,QAAQ,MAAM,IAAI,YAAY;EACtE,KAAK,UACH,OAAO;EACT,KAAK,UACH,OAAO;EACT,KAAK,WACH,OAAO;EACT,KAAK,UACH,IAAI,iBAAiB,YAAY,OAAO;CAC5C;CACA,MAAM,IAAI,MACR,6GACF;AACF,EACF;AAEA,eAAe,mBAAmB,WAAoD;CAKpF,KAAI,MAJiB,UAAU,MAC7B,uFACA,CAAC,mBAAmB,QAAQ,CAC9B,GACW,KAAK,WAAW,GACzB,OAAO,EAAE,MAAM,WAAW;CAO5B,MAAM,OAAM,MAJS,UAAU,MAC7B,wJACA,CAAC,YAAY,CACf,GACmB,KAAK;CACxB,IAAI,CAAC,KACH,OAAO,EAAE,MAAM,SAAS;CAG1B,OAAO;EAAE,MAAM;EAAW,QAAQ,uBAAuB,GAAG;CAAE;AAChE;AAEA,SAAgB,sBAAsB,SAAkC;CACtE,OAAO,OAAO,OAAO,IAAI,oBAAoB,OAAO,CAAC;AACvD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sql-renderer-DqVeL4hP.mjs","names":["renderColumn"],"sources":["../src/core/codec-lookup.ts","../src/core/ddl-renderer.ts","../src/core/sql-renderer.ts"],"sourcesContent":["import type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport { extractCodecLookup } from '@prisma-next/framework-components/control';\nimport { postgresCodecRegistry } from '@prisma-next/target-postgres/codecs';\n\n/**\n * Build a {@link CodecLookup} populated with the Postgres-builtin codec definitions only.\n *\n * This is the default lookup used by `createPostgresAdapter()` and `new PostgresControlAdapter()` when called without a stack-derived lookup (e.g. from tests, or one-off scripts that don't compose a full stack).\n *\n * Extension codecs (e.g. `pg/vector@1` from `@prisma-next/extension-pgvector`) are intentionally NOT included here: a bare adapter cannot see extensions. Stack-composed paths (`SqlControlAdapterDescriptor.create(stack)` / `SqlRuntimeAdapterDescriptor.create(stack)`) supply the broader, extension-inclusive lookup at construction time.\n */\nexport function createPostgresBuiltinCodecLookup(): CodecLookup {\n return extractCodecLookup([\n {\n id: 'postgres-builtin-codecs',\n types: { codecTypes: { codecDescriptors: Array.from(postgresCodecRegistry.values()) } },\n },\n ]);\n}\n","import type {\n DdlColumn,\n DdlColumnDefaultVisitor,\n FunctionColumnDefault,\n LiteralColumnDefault,\n} from '@prisma-next/sql-relational-core/ast';\nimport type {\n PostgresCreateSchema,\n PostgresCreateTable,\n PostgresDdlNode,\n PostgresDdlVisitor,\n} from '@prisma-next/target-postgres/ddl';\nimport { escapeLiteral } from '@prisma-next/target-postgres/sql-utils';\nimport type { PostgresLoweredStatement } from './types';\n\nclass PostgresDdlVisitorImpl implements PostgresDdlVisitor<string> {\n createTable(node: PostgresCreateTable): string {\n const ifNotExists = node.ifNotExists ? 'if not exists ' : '';\n const tableRef = node.schema ? `${node.schema}.${node.table}` : node.table;\n const columnDefs = node.columns.map((column) => renderColumn(column)).join(',\\n ');\n return `create table ${ifNotExists}${tableRef} (\\n ${columnDefs}\\n )`;\n }\n\n createSchema(node: PostgresCreateSchema): string {\n const ifNotExists = node.ifNotExists ? 'if not exists ' : '';\n return `create schema ${ifNotExists}${node.schema}`;\n }\n}\n\nconst defaultVisitor: DdlColumnDefaultVisitor<string> = {\n literal(node: LiteralColumnDefault): string {\n const { value } = node;\n if (typeof value === 'string') {\n return `default '${escapeLiteral(value)}'`;\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return `default ${String(value)}`;\n }\n if (value === null) {\n return 'default null';\n }\n return `default '${JSON.stringify(value)}'`;\n },\n function(node: FunctionColumnDefault): string {\n if (node.expression === 'autoincrement()') {\n return '';\n }\n if (node.expression === 'now()') {\n return 'default now()';\n }\n return `default (${node.expression})`;\n },\n};\n\nfunction renderColumn(column: DdlColumn): string {\n const parts = [column.name, column.type];\n if (column.notNull) {\n parts.push('not null');\n }\n if (column.primaryKey) {\n parts.push('primary key');\n }\n const defaultClause = column.default ? column.default.accept(defaultVisitor) : '';\n if (defaultClause.length > 0) {\n parts.push(defaultClause);\n }\n return parts.join(' ');\n}\n\nexport function renderLoweredDdl(ast: PostgresDdlNode): PostgresLoweredStatement {\n const sql = ast.accept(new PostgresDdlVisitorImpl());\n return Object.freeze({ sql, params: Object.freeze([]) });\n}\n","import type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport { runtimeError } from '@prisma-next/framework-components/runtime';\nimport {\n type AggregateExpr,\n type AnyExpression,\n type AnyFromSource,\n type AnyParamRef,\n type AnyQueryAst,\n type BinaryExpr,\n type ColumnRef,\n collectOrderedParamRefs,\n type DeleteAst,\n type InsertAst,\n type InsertValue,\n type JoinAst,\n type JoinOnExpr,\n type JsonArrayAggExpr,\n type JsonObjectExpr,\n type ListExpression,\n LiteralExpr,\n type LoweredParam,\n type NullCheckExpr,\n type OperationExpr,\n type OrderByItem,\n type ProjectionItem,\n type RawExpr,\n type RawSqlExpr,\n type SelectAst,\n type SubqueryExpr,\n type TableSource,\n type UpdateAst,\n type WindowFuncExpr,\n} from '@prisma-next/sql-relational-core/ast';\nimport { escapeLiteral, quoteIdentifier } from '@prisma-next/target-postgres/sql-utils';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { PostgresContract } from './types';\n\n/**\n * Postgres native types whose unknown-OID parameter inference is reliable in arbitrary expression positions. Parameters bound to a codec whose `meta.db.sql.postgres.nativeType` falls in this set are emitted as plain `$N`; everything else (including `json`, `jsonb`, extension types like `vector`, and unknown user types) is emitted as `$N::<nativeType>` so the planner picks an unambiguous overload.\n *\n * `json` / `jsonb` are intentionally excluded despite being Postgres builtins: their operator overloads make context inference unreliable in expression positions (e.g. `$1 -> 'key'` is ambiguous between the two).\n *\n * Spellings match the on-disk `meta.db.sql.postgres.nativeType` values in `@prisma-next/target-postgres`'s codec definitions, not the `udt_name` abbreviations that ADR 205 used as illustrative shorthand. The lookup-based cast policy compares against these strings directly.\n */\nconst POSTGRES_INFERRABLE_NATIVE_TYPES: ReadonlySet<string> = new Set([\n // Numeric\n 'integer',\n 'smallint',\n 'bigint',\n 'real',\n 'double precision',\n 'numeric',\n // Boolean\n 'boolean',\n // Strings\n 'text',\n 'character',\n 'character varying',\n // Temporal\n 'timestamp',\n 'timestamp without time zone',\n 'timestamp with time zone',\n 'time',\n 'timetz',\n 'interval',\n // Bit strings\n 'bit',\n 'bit varying',\n]);\n\nfunction renderTypedParam(\n index: number,\n codecId: string | undefined,\n codecLookup: CodecLookup,\n): string {\n if (codecId === undefined) {\n return `$${index}`;\n }\n const meta = codecLookup.metaFor(codecId);\n const isRegistered =\n codecLookup.get(codecId) !== undefined ||\n meta !== undefined ||\n codecLookup.targetTypesFor(codecId) !== undefined;\n if (!isRegistered) {\n throw new Error(\n `Postgres lowering: ParamRef carries codecId \"${codecId}\" but the ` +\n 'assembled codec lookup has no entry for it. This usually indicates ' +\n 'a missing extension pack in the runtime stack — register the pack ' +\n 'that contributes this codec (e.g. `extensionPacks: [pgvectorRuntime]`), ' +\n 'or use the codec directly from `@prisma-next/target-postgres/codecs` ' +\n \"if it's a builtin.\",\n );\n }\n // The framework `CodecLookup.metaFor` returns the family-agnostic `CodecMeta` whose `db` is `Record<string, unknown>`. The SQL family populates a narrower shape with `db.sql.<dialect>.nativeType: string`; navigate that path defensively and string-check the leaf.\n const dbRecord = meta?.db;\n const sqlBlock = isRecord(dbRecord) ? dbRecord['sql'] : undefined;\n const dialectBlock = isRecord(sqlBlock) ? sqlBlock['postgres'] : undefined;\n const nativeType = isRecord(dialectBlock) ? dialectBlock['nativeType'] : undefined;\n if (typeof nativeType === 'string' && !POSTGRES_INFERRABLE_NATIVE_TYPES.has(nativeType)) {\n return `$${index}::${nativeType}`;\n }\n return `$${index}`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/**\n * Per-render carrier threaded through every helper. Bundles the param-index map (for `$N` numbering) and the assembled-stack `codecLookup` (for cast policy at the `renderTypedParam` chokepoint). Carrying both on a single value keeps helper signatures stable.\n */\ninterface ParamIndexMap {\n readonly indexMap: Map<AnyParamRef, number>;\n readonly codecLookup: CodecLookup;\n}\n\n/**\n * Render a SQL query AST to a Postgres-flavored `{ sql, params }` payload.\n *\n * Shared between the runtime (`PostgresAdapterImpl.lower`) and control (`PostgresControlAdapter.lower`) entrypoints so emit-time and run-time paths produce byte-identical output for the same AST.\n */\nexport function renderLoweredSql(\n ast: AnyQueryAst,\n contract: PostgresContract,\n codecLookup: CodecLookup,\n): { readonly sql: string; readonly params: readonly LoweredParam[] } {\n const orderedRefs = collectOrderedParamRefs(ast);\n const indexMap = new Map<AnyParamRef, number>();\n const params: LoweredParam[] = orderedRefs.map((ref, i) => {\n indexMap.set(ref, i + 1);\n return ref.kind === 'prepared-param-ref'\n ? { kind: 'bind', name: ref.name }\n : { kind: 'literal', value: ref.value };\n });\n const pim: ParamIndexMap = { indexMap, codecLookup };\n\n const node = ast;\n let sql: string;\n switch (node.kind) {\n case 'select':\n sql = renderSelect(node, contract, pim);\n break;\n case 'insert':\n sql = renderInsert(node, contract, pim);\n break;\n case 'update':\n sql = renderUpdate(node, contract, pim);\n break;\n case 'delete':\n sql = renderDelete(node, contract, pim);\n break;\n case 'raw-sql':\n sql = renderRawSql(node, contract, pim);\n break;\n // v8 ignore next 4\n default:\n throw new Error(\n `Unsupported AST node kind: ${(node satisfies never as { kind: string }).kind}`,\n );\n }\n\n return Object.freeze({ sql, params: Object.freeze(params) });\n}\n\nfunction renderLimitOffset(\n keyword: 'LIMIT' | 'OFFSET',\n value: SelectAst['limit'] | SelectAst['offset'],\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n if (value === undefined) return '';\n if (typeof value === 'number') return `${keyword} ${value}`;\n return `${keyword} ${renderExpr(value, contract, pim)}`;\n}\n\nfunction renderSelect(ast: SelectAst, contract: PostgresContract, pim: ParamIndexMap): string {\n const selectClause = `SELECT ${renderDistinctPrefix(ast.distinct, ast.distinctOn, contract, pim)}${renderProjection(\n ast.projection,\n contract,\n pim,\n )}`;\n const fromClause = `FROM ${renderSource(ast.from, contract, pim)}`;\n\n const joinsClause = ast.joins?.length\n ? ast.joins.map((join) => renderJoin(join, contract, pim)).join(' ')\n : '';\n\n const whereClause = ast.where ? `WHERE ${renderWhere(ast.where, contract, pim)}` : '';\n const groupByClause = ast.groupBy?.length\n ? `GROUP BY ${ast.groupBy.map((expr) => renderExpr(expr, contract, pim)).join(', ')}`\n : '';\n const havingClause = ast.having ? `HAVING ${renderWhere(ast.having, contract, pim)}` : '';\n const orderClause = ast.orderBy?.length\n ? `ORDER BY ${ast.orderBy\n .map((order) => {\n const expr = renderExpr(order.expr, contract, pim);\n return `${expr} ${order.dir.toUpperCase()}`;\n })\n .join(', ')}`\n : '';\n const limitClause = renderLimitOffset('LIMIT', ast.limit, contract, pim);\n const offsetClause = renderLimitOffset('OFFSET', ast.offset, contract, pim);\n\n const clauses = [\n selectClause,\n fromClause,\n joinsClause,\n whereClause,\n groupByClause,\n havingClause,\n orderClause,\n limitClause,\n offsetClause,\n ]\n .filter((part) => part.length > 0)\n .join(' ');\n return clauses.trim();\n}\n\nfunction renderProjection(\n projection: ReadonlyArray<ProjectionItem>,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n return projection\n .map((item) => {\n const alias = quoteIdentifier(item.alias);\n if (item.expr.kind === 'literal') {\n return `${renderLiteral(item.expr)} AS ${alias}`;\n }\n return `${renderExpr(item.expr, contract, pim)} AS ${alias}`;\n })\n .join(', ');\n}\n\nfunction renderReturning(\n items: ReadonlyArray<ProjectionItem>,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n return items\n .map((item) => {\n if (item.expr.kind === 'column-ref') {\n const rendered = renderColumn(item.expr);\n return item.expr.column === item.alias\n ? rendered\n : `${rendered} AS ${quoteIdentifier(item.alias)}`;\n }\n if (item.expr.kind === 'literal') {\n return `${renderLiteral(item.expr)} AS ${quoteIdentifier(item.alias)}`;\n }\n return `${renderExpr(item.expr, contract, pim)} AS ${quoteIdentifier(item.alias)}`;\n })\n .join(', ');\n}\n\nfunction renderDistinctPrefix(\n distinct: true | undefined,\n distinctOn: ReadonlyArray<AnyExpression> | undefined,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n if (distinctOn && distinctOn.length > 0) {\n const rendered = distinctOn.map((expr) => renderExpr(expr, contract, pim)).join(', ');\n return `DISTINCT ON (${rendered}) `;\n }\n if (distinct) {\n return 'DISTINCT ';\n }\n return '';\n}\n\nfunction qualifyTableFromNamespaceCoordinate(\n table: Pick<TableSource, 'name' | 'namespaceId'>,\n contract: PostgresContract,\n): string {\n if (table.namespaceId === undefined) {\n return quoteIdentifier(table.name);\n }\n const namespace = contract.storage.namespaces[table.namespaceId];\n if (namespace === undefined) {\n throw new Error(\n `Table \"${table.name}\" references namespace \"${table.namespaceId}\" which is not present as a Postgres schema on the contract`,\n );\n }\n const qualifyTable = namespace.qualifyTable;\n if (qualifyTable === undefined) {\n throw new Error(\n `Table \"${table.name}\" references namespace \"${table.namespaceId}\" which is not materialised as a Postgres schema on the contract`,\n );\n }\n return qualifyTable.call(namespace, table.name);\n}\n\nfunction renderTableSource(source: TableSource, contract: PostgresContract): string {\n const qualified = qualifyTableFromNamespaceCoordinate(source, contract);\n if (!source.alias) {\n return qualified;\n }\n return `${qualified} AS ${quoteIdentifier(source.alias)}`;\n}\n\nfunction renderSource(\n source: AnyFromSource,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const node = source;\n switch (node.kind) {\n case 'table-source':\n return renderTableSource(node, contract);\n case 'derived-table-source':\n return `(${renderSelect(node.query, contract, pim)}) AS ${quoteIdentifier(node.alias)}`;\n // v8 ignore next 4\n default:\n throw new Error(\n `Unsupported source node kind: ${(node satisfies never as { kind: string }).kind}`,\n );\n }\n}\n\nfunction assertScalarSubquery(query: SelectAst): void {\n if (query.projection.length !== 1) {\n throw new Error('Subquery expressions must project exactly one column');\n }\n}\n\nfunction renderSubqueryExpr(\n expr: SubqueryExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n assertScalarSubquery(expr.query);\n return `(${renderSelect(expr.query, contract, pim)})`;\n}\n\nfunction renderWhere(expr: AnyExpression, contract: PostgresContract, pim: ParamIndexMap): string {\n return renderExpr(expr, contract, pim);\n}\n\nfunction renderNullCheck(\n expr: NullCheckExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const rendered = renderExpr(expr.expr, contract, pim);\n const renderedExpr = isAtomicExpressionKind(expr.expr.kind) ? rendered : `(${rendered})`;\n return expr.isNull ? `${renderedExpr} IS NULL` : `${renderedExpr} IS NOT NULL`;\n}\n\n/**\n * Atomic expression kinds whose rendered SQL is already self-delimited (a column reference, parameter, literal, function call, aggregate, etc.) and therefore does not need surrounding parentheses when used as the left operand of a postfix predicate like `IS NULL` or `IS NOT NULL`, or as either operand of a binary infix operator.\n *\n * Anything not in this set is treated as composite (binary, AND/OR/NOT, EXISTS, nested IS NULL, subqueries, operation templates) and gets wrapped to preserve grouping.\n */\nfunction isAtomicExpressionKind(kind: AnyExpression['kind']): boolean {\n switch (kind) {\n case 'column-ref':\n case 'identifier-ref':\n case 'param-ref':\n case 'prepared-param-ref':\n case 'literal':\n case 'aggregate':\n case 'window-func':\n case 'json-object':\n case 'json-array-agg':\n case 'list':\n return true;\n case 'subquery':\n case 'operation':\n case 'binary':\n case 'and':\n case 'or':\n case 'exists':\n case 'null-check':\n case 'not':\n case 'raw-expr':\n return false;\n }\n}\n\nfunction renderBinary(expr: BinaryExpr, contract: PostgresContract, pim: ParamIndexMap): string {\n if (expr.right.kind === 'list' && expr.right.values.length === 0) {\n if (expr.op === 'in') {\n return 'FALSE';\n }\n if (expr.op === 'notIn') {\n return 'TRUE';\n }\n }\n\n const leftExpr = expr.left;\n const left = renderExpr(leftExpr, contract, pim);\n const leftRendered =\n leftExpr.kind === 'operation' || leftExpr.kind === 'subquery' ? `(${left})` : left;\n\n const rightNode = expr.right;\n let right: string;\n switch (rightNode.kind) {\n case 'list':\n right = renderListLiteral(rightNode, contract, pim);\n break;\n case 'literal':\n right = renderLiteral(rightNode);\n break;\n case 'column-ref':\n right = renderColumn(rightNode);\n break;\n case 'param-ref':\n case 'prepared-param-ref':\n right = renderParamRef(rightNode, pim);\n break;\n default:\n right = renderExpr(rightNode, contract, pim);\n break;\n }\n\n const operatorMap: Record<BinaryExpr['op'], string> = {\n eq: '=',\n neq: '!=',\n gt: '>',\n lt: '<',\n gte: '>=',\n lte: '<=',\n like: 'LIKE',\n in: 'IN',\n notIn: 'NOT IN',\n };\n\n return `${leftRendered} ${operatorMap[expr.op]} ${right}`;\n}\n\nfunction renderListLiteral(\n expr: ListExpression,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n if (expr.values.length === 0) {\n return '(NULL)';\n }\n const values = expr.values\n .map((v) => {\n if (v.kind === 'param-ref' || v.kind === 'prepared-param-ref') {\n return renderParamRef(v, pim);\n }\n if (v.kind === 'literal') return renderLiteral(v);\n return renderExpr(v, contract, pim);\n })\n .join(', ');\n return `(${values})`;\n}\n\nfunction renderColumn(ref: ColumnRef): string {\n if (ref.table === 'excluded') {\n return `excluded.${quoteIdentifier(ref.column)}`;\n }\n return `${quoteIdentifier(ref.table)}.${quoteIdentifier(ref.column)}`;\n}\n\nfunction renderAggregateExpr(\n expr: AggregateExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const fn = expr.fn.toUpperCase();\n if (!expr.expr) {\n return `${fn}(*)`;\n }\n return `${fn}(${renderExpr(expr.expr, contract, pim)})`;\n}\n\nfunction renderWindowFuncExpr(\n expr: WindowFuncExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const fn = expr.fn.toUpperCase();\n const args = expr.args.map((arg) => renderExpr(arg, contract, pim)).join(', ');\n const partitionClause =\n expr.partitionBy && expr.partitionBy.length > 0\n ? `PARTITION BY ${expr.partitionBy.map((e) => renderExpr(e, contract, pim)).join(', ')}`\n : '';\n const orderClause =\n expr.orderBy && expr.orderBy.length > 0\n ? `ORDER BY ${renderOrderByItems(expr.orderBy, contract, pim)}`\n : '';\n const over = [partitionClause, orderClause].filter((part) => part.length > 0).join(' ');\n return `${fn}(${args}) OVER (${over})`;\n}\n\nfunction renderJsonObjectExpr(\n expr: JsonObjectExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const args = expr.entries\n .flatMap((entry): [string, string] => {\n const key = `'${escapeLiteral(entry.key)}'`;\n if (entry.value.kind === 'literal') {\n return [key, renderLiteral(entry.value)];\n }\n return [key, renderExpr(entry.value, contract, pim)];\n })\n .join(', ');\n return `json_build_object(${args})`;\n}\n\nfunction renderOrderByItems(\n items: ReadonlyArray<OrderByItem>,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n return items\n .map((item) => `${renderExpr(item.expr, contract, pim)} ${item.dir.toUpperCase()}`)\n .join(', ');\n}\n\nfunction renderJsonArrayAggExpr(\n expr: JsonArrayAggExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const aggregateOrderBy =\n expr.orderBy && expr.orderBy.length > 0\n ? ` ORDER BY ${renderOrderByItems(expr.orderBy, contract, pim)}`\n : '';\n const aggregated = `json_agg(${renderExpr(expr.expr, contract, pim)}${aggregateOrderBy})`;\n if (expr.onEmpty === 'emptyArray') {\n return `coalesce(${aggregated}, json_build_array())`;\n }\n return aggregated;\n}\n\nfunction renderExpr(expr: AnyExpression, contract: PostgresContract, pim: ParamIndexMap): string {\n const node = expr;\n switch (node.kind) {\n case 'column-ref':\n return renderColumn(node);\n case 'identifier-ref':\n return quoteIdentifier(node.name);\n case 'operation':\n return renderOperation(node, contract, pim);\n case 'subquery':\n return renderSubqueryExpr(node, contract, pim);\n case 'aggregate':\n return renderAggregateExpr(node, contract, pim);\n case 'window-func':\n return renderWindowFuncExpr(node, contract, pim);\n case 'json-object':\n return renderJsonObjectExpr(node, contract, pim);\n case 'json-array-agg':\n return renderJsonArrayAggExpr(node, contract, pim);\n case 'binary':\n return renderBinary(node, contract, pim);\n case 'and':\n if (node.exprs.length === 0) {\n return 'TRUE';\n }\n return `(${node.exprs.map((part) => renderExpr(part, contract, pim)).join(' AND ')})`;\n case 'or':\n if (node.exprs.length === 0) {\n return 'FALSE';\n }\n return `(${node.exprs.map((part) => renderExpr(part, contract, pim)).join(' OR ')})`;\n case 'exists': {\n const notKeyword = node.notExists ? 'NOT ' : '';\n const subquery = renderSelect(node.subquery, contract, pim);\n return `${notKeyword}EXISTS (${subquery})`;\n }\n case 'null-check':\n return renderNullCheck(node, contract, pim);\n case 'not':\n return `NOT (${renderExpr(node.expr, contract, pim)})`;\n case 'param-ref':\n case 'prepared-param-ref':\n return renderParamRef(node, pim);\n case 'literal':\n return renderLiteral(node);\n case 'list':\n return renderListLiteral(node, contract, pim);\n case 'raw-expr':\n return renderRawExpr(node, contract, pim);\n // v8 ignore next 4\n default:\n throw new Error(\n `Unsupported expression node kind: ${(node satisfies never as { kind: string }).kind}`,\n );\n }\n}\n\nfunction renderParamRef(ref: AnyParamRef, pim: ParamIndexMap): string {\n const index = pim.indexMap.get(ref);\n if (index === undefined) {\n throw new Error('ParamRef not found in index map');\n }\n if (ref.kind === 'prepared-param-ref') {\n return renderTypedParam(index, ref.codec.codecId, pim.codecLookup);\n }\n if (ref.codec === undefined) {\n throw runtimeError(\n 'RUNTIME.PARAM_REF_MISSING_CODEC',\n 'Postgres renderer: ParamRef reached lowering without a bound CodecRef. ' +\n 'Every column-bound ParamRef must carry a codec under the AST-bound codec contract. ' +\n 'This usually indicates a builder path that constructed a ParamRef without threading the column codec.',\n { paramIndex: index, ...ifDefined('name', ref.name) },\n );\n }\n return renderTypedParam(index, ref.codec.codecId, pim.codecLookup);\n}\n\nfunction renderLiteral(expr: LiteralExpr): string {\n if (typeof expr.value === 'string') {\n return `'${escapeLiteral(expr.value)}'`;\n }\n if (typeof expr.value === 'number' || typeof expr.value === 'boolean') {\n return String(expr.value);\n }\n if (typeof expr.value === 'bigint') {\n return String(expr.value);\n }\n if (expr.value === null) {\n return 'NULL';\n }\n if (expr.value === undefined) {\n return 'NULL';\n }\n if (expr.value instanceof Date) {\n return `'${escapeLiteral(expr.value.toISOString())}'`;\n }\n if (Array.isArray(expr.value)) {\n return `ARRAY[${expr.value.map((v: unknown) => renderLiteral(new LiteralExpr(v))).join(', ')}]`;\n }\n const json = JSON.stringify(expr.value);\n if (json === undefined) {\n return 'NULL';\n }\n return `'${escapeLiteral(json)}'`;\n}\n\nfunction renderOperation(\n expr: OperationExpr,\n contract: PostgresContract,\n pim: ParamIndexMap,\n): string {\n const self = renderExpr(expr.self, contract, pim);\n const args = expr.args.map((arg) => {\n return renderExpr(arg, contract, pim);\n });\n\n // Resolve `{{self}}` and `{{argN}}` from the original template in a single pass. Doing this with sequential `String.prototype.replace` calls is unsafe: a substituted fragment can itself contain text that matches a later token (e.g. an arg literal containing the substring `{{arg1}}`), and the next iteration would corrupt it. A single regex callback never re-scans already-substituted output.\n return expr.lowering.template.replace(\n /\\{\\{self\\}\\}|\\{\\{arg(\\d+)\\}\\}/g,\n (token, argIndex: string | undefined) => {\n if (token === '{{self}}') {\n return self;\n }\n const arg = args[Number(argIndex)];\n if (arg === undefined) {\n throw new Error(\n `Operation lowering template for \"${expr.method}\" referenced missing argument {{arg${argIndex}}}; template has ${args.length} arg(s)`,\n );\n }\n return arg;\n },\n );\n}\n\nfunction renderJoin(join: JoinAst, contract: PostgresContract, pim: ParamIndexMap): string {\n const joinType = join.joinType.toUpperCase();\n const lateral = join.lateral ? 'LATERAL ' : '';\n const source = renderSource(join.source, contract, pim);\n const onClause = renderJoinOn(join.on, contract, pim);\n return `${joinType} JOIN ${lateral}${source} ON ${onClause}`;\n}\n\nfunction renderJoinOn(on: JoinOnExpr, contract: PostgresContract, pim: ParamIndexMap): string {\n if (on.kind === 'eq-col-join-on') {\n const left = renderColumn(on.left);\n const right = renderColumn(on.right);\n return `${left} = ${right}`;\n }\n return renderWhere(on, contract, pim);\n}\n\nfunction getInsertColumnOrder(\n rows: ReadonlyArray<Record<string, InsertValue>>,\n contract: PostgresContract,\n tableRef: Pick<TableSource, 'name' | 'namespaceId'>,\n): string[] {\n const tableName = tableRef.name;\n const orderedColumns: string[] = [];\n const seenColumns = new Set<string>();\n\n for (const row of rows) {\n for (const column of Object.keys(row)) {\n if (seenColumns.has(column)) {\n continue;\n }\n seenColumns.add(column);\n orderedColumns.push(column);\n }\n }\n\n if (orderedColumns.length > 0) {\n return orderedColumns;\n }\n\n let table: { columns: Record<string, unknown> } | undefined;\n if (tableRef.namespaceId !== undefined) {\n const ns = contract.storage.namespaces[tableRef.namespaceId];\n const found = ns?.tables[tableName] as { columns: Record<string, unknown> } | undefined;\n if (found !== undefined) {\n table = found;\n }\n }\n if (table === undefined) {\n for (const ns of Object.values(contract.storage.namespaces)) {\n // Namespace.tables is Record<string, IRNode> at the interface level;\n // SQL family namespaces hold StorageTable instances which have .columns.\n const found = ns.tables[tableName] as { columns: Record<string, unknown> } | undefined;\n if (found !== undefined) {\n table = found;\n break;\n }\n }\n }\n if (!table) {\n throw new Error(`INSERT target table not found in contract storage: ${tableName}`);\n }\n return Object.keys(table.columns);\n}\n\nfunction renderInsertValue(value: InsertValue | undefined, pim: ParamIndexMap): string {\n if (!value || value.kind === 'default-value') {\n return 'DEFAULT';\n }\n\n switch (value.kind) {\n case 'param-ref':\n case 'prepared-param-ref':\n return renderParamRef(value, pim);\n case 'column-ref':\n return renderColumn(value);\n // v8 ignore next 4\n default:\n throw new Error(\n `Unsupported value node in INSERT: ${(value satisfies never as { kind: string }).kind}`,\n );\n }\n}\n\nfunction renderInsert(ast: InsertAst, contract: PostgresContract, pim: ParamIndexMap): string {\n const table = qualifyTableFromNamespaceCoordinate(ast.table, contract);\n const rows = ast.rows;\n if (rows.length === 0) {\n throw new Error('INSERT requires at least one row');\n }\n const hasExplicitValues = rows.some((row) => Object.keys(row).length > 0);\n const insertClause = (() => {\n if (!hasExplicitValues) {\n if (rows.length === 1) {\n return `INSERT INTO ${table} DEFAULT VALUES`;\n }\n\n const defaultColumns = getInsertColumnOrder(rows, contract, ast.table);\n if (defaultColumns.length === 0) {\n return `INSERT INTO ${table} VALUES ${rows.map(() => '()').join(', ')}`;\n }\n\n const quotedColumns = defaultColumns.map((column) => quoteIdentifier(column));\n const defaultRow = `(${defaultColumns.map(() => 'DEFAULT').join(', ')})`;\n return `INSERT INTO ${table} (${quotedColumns.join(', ')}) VALUES ${rows\n .map(() => defaultRow)\n .join(', ')}`;\n }\n\n const columnOrder = getInsertColumnOrder(rows, contract, ast.table);\n const columns = columnOrder.map((column) => quoteIdentifier(column));\n const values = rows\n .map((row) => {\n const renderedRow = columnOrder.map((column) => renderInsertValue(row[column], pim));\n return `(${renderedRow.join(', ')})`;\n })\n .join(', ');\n\n return `INSERT INTO ${table} (${columns.join(', ')}) VALUES ${values}`;\n })();\n const onConflictClause = ast.onConflict\n ? (() => {\n const conflictColumns = ast.onConflict.columns.map((col) => quoteIdentifier(col.column));\n if (conflictColumns.length === 0) {\n throw new Error('INSERT onConflict requires at least one conflict column');\n }\n\n const action = ast.onConflict.action;\n switch (action.kind) {\n case 'do-nothing':\n return ` ON CONFLICT (${conflictColumns.join(', ')}) DO NOTHING`;\n case 'do-update-set': {\n const updateEntries = Object.entries(action.set);\n if (updateEntries.length === 0) {\n throw new Error('INSERT onConflict do-update-set requires at least one assignment');\n }\n const updates = updateEntries.map(([colName, value]) => {\n return `${quoteIdentifier(colName)} = ${renderExpr(value, contract, pim)}`;\n });\n return ` ON CONFLICT (${conflictColumns.join(', ')}) DO UPDATE SET ${updates.join(', ')}`;\n }\n // v8 ignore next 4\n default:\n throw new Error(\n `Unsupported onConflict action: ${(action satisfies never as { kind: string }).kind}`,\n );\n }\n })()\n : '';\n const returningClause = ast.returning?.length\n ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}`\n : '';\n\n return `${insertClause}${onConflictClause}${returningClause}`;\n}\n\nfunction renderUpdate(ast: UpdateAst, contract: PostgresContract, pim: ParamIndexMap): string {\n const table = qualifyTableFromNamespaceCoordinate(ast.table, contract);\n const setEntries = Object.entries(ast.set);\n if (setEntries.length === 0) {\n throw new Error('UPDATE requires at least one SET assignment');\n }\n const setClauses = setEntries.map(([col, val]) => {\n const column = quoteIdentifier(col);\n return `${column} = ${renderExpr(val, contract, pim)}`;\n });\n\n const whereClause = ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : '';\n const returningClause = ast.returning?.length\n ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}`\n : '';\n\n return `UPDATE ${table} SET ${setClauses.join(', ')}${whereClause}${returningClause}`;\n}\n\nfunction renderDelete(ast: DeleteAst, contract: PostgresContract, pim: ParamIndexMap): string {\n const table = qualifyTableFromNamespaceCoordinate(ast.table, contract);\n const whereClause = ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : '';\n const returningClause = ast.returning?.length\n ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}`\n : '';\n\n return `DELETE FROM ${table}${whereClause}${returningClause}`;\n}\n\nfunction renderRawSql(ast: RawSqlExpr, contract: PostgresContract, pim: ParamIndexMap): string {\n const out: string[] = [];\n for (let i = 0; i < ast.fragments.length; i++) {\n out.push(ast.fragments[i] ?? '');\n if (i < ast.args.length) {\n const arg = ast.args[i];\n if (arg !== undefined) {\n out.push(renderExpr(arg, contract, pim));\n }\n }\n }\n return out.join('');\n}\n\nfunction renderRawExpr(node: RawExpr, contract: PostgresContract, pim: ParamIndexMap): string {\n return node.parts\n .map((part) => (typeof part === 'string' ? part : renderExpr(part, contract, pim)))\n .join('');\n}\n"],"mappings":"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"}
|