@prisma-next/adapter-postgres 0.13.0-dev.2 → 0.13.0-dev.21

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.
@@ -1,4 +1,4 @@
1
- import { i as createPostgresBuiltinCodecLookup, n as renderLoweredSql, r as renderLoweredDdl, t as PostgresControlAdapter } from "./control-adapter-ZWrjGBq7.mjs";
1
+ import { n as renderLoweredSql, r as createPostgresBuiltinCodecLookup, t as PostgresControlAdapter } from "./control-adapter-BeSqyOGl.mjs";
2
2
  import { APP_SPACE_ID } from "@prisma-next/framework-components/control";
3
3
  import { isDdlNode } from "@prisma-next/sql-relational-core/ast";
4
4
  //#region src/core/adapter.ts
@@ -41,7 +41,7 @@ var PostgresAdapterImpl = class {
41
41
  });
42
42
  }
43
43
  lower(ast, context) {
44
- if (isDdlNode(ast)) return renderLoweredDdl(ast);
44
+ if (isDdlNode(ast)) throw new Error("lower() does not lower DDL on the runtime adapter — DDL lowering is a control-plane concern handled by the control adapter.");
45
45
  return renderLoweredSql(ast, context.contract, this.codecLookup);
46
46
  }
47
47
  };
@@ -62,4 +62,4 @@ function createPostgresAdapter(options) {
62
62
  //#endregion
63
63
  export { postgresRawCodecInferer as n, createPostgresAdapter as t };
64
64
 
65
- //# sourceMappingURL=adapter-CAlWA4ug.mjs.map
65
+ //# sourceMappingURL=adapter-CoRrSTXZ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-CoRrSTXZ.mjs","names":[],"sources":["../src/core/adapter.ts"],"sourcesContent":["import type { CodecRegistry } 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 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 type { PostgresDdlNode } from '@prisma-next/target-postgres/ddl';\nimport { createPostgresBuiltinCodecLookup } from './codec-lookup';\nimport { PostgresControlAdapter } from './control-adapter';\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: CodecRegistry;\n\n constructor(options?: PostgresAdapterOptions) {\n this.codecLookup = options?.codecLookup ?? createPostgresBuiltinCodecLookup();\n const controlAdapter = new PostgresControlAdapter(this.codecLookup);\n this.profile = Object.freeze({\n id: options?.profileId ?? 'postgres/default@1',\n target: 'postgres',\n capabilities: defaultCapabilities,\n readMarker: (queryable: SqlQueryable) =>\n controlAdapter.readMarkerDiscriminated(\n {\n familyId: 'sql',\n targetId: 'postgres',\n query: async <Row = Record<string, unknown>>(\n sql: string,\n params?: readonly unknown[],\n ) => {\n const result = await queryable.query<Row>(sql, params);\n return { rows: [...result.rows] };\n },\n close: async () => {},\n },\n APP_SPACE_ID,\n ),\n });\n }\n\n lower(\n ast: AnyQueryAst | PostgresDdlNode,\n context: LowererContext<PostgresContract>,\n ): PostgresLoweredStatement {\n if (isDdlNode(ast)) {\n throw new Error(\n 'lower() does not lower DDL on the runtime adapter — DDL lowering is a control-plane concern handled by the control adapter.',\n );\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\nexport function createPostgresAdapter(options?: PostgresAdapterOptions) {\n return Object.freeze(new PostgresAdapterImpl(options));\n}\n"],"mappings":";;;;AAkBA,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,MAAM,iBAAiB,IAAI,uBAAuB,KAAK,WAAW;EAClE,KAAK,UAAU,OAAO,OAAO;GAC3B,IAAI,SAAS,aAAa;GAC1B,QAAQ;GACR,cAAc;GACd,aAAa,cACX,eAAe,wBACb;IACE,UAAU;IACV,UAAU;IACV,OAAO,OACL,KACA,WACG;KAEH,OAAO,EAAE,MAAM,CAAC,IAAG,MADE,UAAU,MAAW,KAAK,MAAM,EAAA,CAC3B,IAAI,EAAE;IAClC;IACA,OAAO,YAAY,CAAC;GACtB,GACA,YACF;EACJ,CAAC;CACH;CAEA,MACE,KACA,SAC0B;EAC1B,IAAI,UAAU,GAAG,GACf,MAAM,IAAI,MACR,6HACF;EAEF,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,SAAgB,sBAAsB,SAAkC;CACtE,OAAO,OAAO,OAAO,IAAI,oBAAoB,OAAO,CAAC;AACvD"}
@@ -1,4 +1,4 @@
1
- import { c as PostgresContract, l as PostgresLoweredStatement, s as PostgresAdapterOptions } from "./types-Dv7M8jx8.mjs";
1
+ import { c as PostgresContract, l as PostgresLoweredStatement, s as PostgresAdapterOptions } from "./types-KXRwRZU8.mjs";
2
2
  import { Adapter, AdapterProfile, AnyQueryAst, LowererContext } from "@prisma-next/sql-relational-core/ast";
3
3
  import { RawCodecInferer } from "@prisma-next/sql-relational-core/expression";
4
4
  import { PostgresDdlNode } from "@prisma-next/target-postgres/ddl";
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.mts","names":[],"sources":["../src/core/adapter.ts"],"mappings":";;;;;;cAoCM,mBAAA,YACO,OAAA,CAAQ,WAAA,EAAa,gBAAA,EAAkB,wBAAA;EAAA,SAGzC,QAAA;EAAA,SACA,QAAA;EAAA,SAEA,OAAA,EAAS,cAAA;EAAA,iBACD,WAAA;cAEL,OAAA,GAAU,sBAAA;EA0BtB,KAAA,CACE,GAAA,EAAK,WAAA,GAAc,eAAA,EACnB,OAAA,EAAS,cAAA,CAAe,gBAAA,IACvB,wBAAA;AAAA;;cASQ,uBAAA,EAAyB,eAkBrC;AAAA,iBAEe,qBAAA,CAAsB,OAAA,GAAU,sBAAA,GAAsB,QAAA,CAAA,mBAAA"}
1
+ {"version":3,"file":"adapter.d.mts","names":[],"sources":["../src/core/adapter.ts"],"mappings":";;;;;;cAmCM,mBAAA,YACO,OAAA,CAAQ,WAAA,EAAa,gBAAA,EAAkB,wBAAA;EAAA,SAGzC,QAAA;EAAA,SACA,QAAA;EAAA,SAEA,OAAA,EAAS,cAAA;EAAA,iBACD,WAAA;cAEL,OAAA,GAAU,sBAAA;EA0BtB,KAAA,CACE,GAAA,EAAK,WAAA,GAAc,eAAA,EACnB,OAAA,EAAS,cAAA,CAAe,gBAAA,IACvB,wBAAA;AAAA;;cAWQ,uBAAA,EAAyB,eAkBrC;AAAA,iBAEe,qBAAA,CAAsB,OAAA,GAAU,sBAAA,GAAsB,QAAA,CAAA,mBAAA"}
package/dist/adapter.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { n as postgresRawCodecInferer, t as createPostgresAdapter } from "./adapter-CAlWA4ug.mjs";
1
+ import { n as postgresRawCodecInferer, t as createPostgresAdapter } from "./adapter-CoRrSTXZ.mjs";
2
2
  export { createPostgresAdapter, postgresRawCodecInferer };
@@ -4,24 +4,24 @@ import { postgresCodecRegistry } from "@prisma-next/target-postgres/codecs";
4
4
  import { parseMarkerRowSafely, rethrowMarkerReadError, withMarkerReadErrorHandling } from "@prisma-next/errors/execution";
5
5
  import { parseContractMarkerRow } from "@prisma-next/family-sql/verify";
6
6
  import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
7
+ import { REFERENTIAL_ACTION_SQL } from "@prisma-next/sql-contract/referential-action-sql";
7
8
  import { PostgresTableSource, buildControlTableBootstrapQueries, buildSignMarkerBootstrapQueries, int4, int8, jsonb, pgTable, text, textArray, timestamptz } from "@prisma-next/target-postgres/contract-free";
8
9
  import { parsePostgresDefault } from "@prisma-next/target-postgres/default-normalizer";
9
- import { createResolveExistingEnumValues, enumStorageCompoundKey, readExistingEnumValues, readPostgresSchemaIrAnnotations } from "@prisma-next/target-postgres/enum-planning";
10
+ import { createResolveExistingEnumValues, readExistingEnumValues, readPostgresSchemaIrAnnotations } from "@prisma-next/target-postgres/enum-planning";
10
11
  import { normalizeSchemaNativeType } from "@prisma-next/target-postgres/native-type-normalizer";
12
+ import { escapeLiteral, quoteIdentifier } from "@prisma-next/target-postgres/sql-utils";
11
13
  import { blindCast } from "@prisma-next/utils/casts";
12
14
  import { ifDefined } from "@prisma-next/utils/defined";
13
- import { REFERENTIAL_ACTION_SQL } from "@prisma-next/sql-contract/referential-action-sql";
14
- import { escapeLiteral, quoteIdentifier } from "@prisma-next/target-postgres/sql-utils";
15
- import { PG_ENUM_CODEC_ID, PG_TIMESTAMPTZ_CODEC_ID } from "@prisma-next/target-postgres/codec-ids";
16
15
  import { createAstCodecRegistry, deriveParamMetadata, encodeParamsWithMetadata } from "@prisma-next/sql-runtime";
16
+ import { PG_ENUM_CODEC_ID, PG_TIMESTAMPTZ_CODEC_ID } from "@prisma-next/target-postgres/codec-ids";
17
17
  import { runtimeError } from "@prisma-next/framework-components/runtime";
18
18
  //#region src/core/codec-lookup.ts
19
19
  /**
20
- * Build a {@link CodecLookup} populated with the Postgres-builtin codec definitions only.
20
+ * Build a {@link CodecRegistry} populated with the Postgres-builtin codec definitions only.
21
21
  *
22
- * 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).
22
+ * This is the default registry used by `createPostgresAdapter()` and `new PostgresControlAdapter()` when called without a stack-derived registry (e.g. from tests, or one-off scripts that don't compose a full stack).
23
23
  *
24
- * 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.
24
+ * 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 registry at construction time.
25
25
  */
26
26
  function createPostgresBuiltinCodecLookup() {
27
27
  return extractCodecLookup([{
@@ -36,78 +36,13 @@ function ledgerOriginFromStored(originCoreHash) {
36
36
  return originCoreHash;
37
37
  }
38
38
  //#endregion
39
- //#region src/core/ddl-renderer.ts
40
- function quoteQualifiedIdentifier(name) {
41
- return name.split(".").map(quoteIdentifier).join(".");
42
- }
43
- function renderPrimaryKeyConstraint(constraint) {
44
- const cols = constraint.columns.map(quoteIdentifier).join(", ");
45
- if (constraint.name !== void 0) return `CONSTRAINT ${quoteIdentifier(constraint.name)} PRIMARY KEY (${cols})`;
46
- return `PRIMARY KEY (${cols})`;
47
- }
48
- function renderForeignKeyConstraint(constraint) {
49
- const cols = constraint.columns.map(quoteIdentifier).join(", ");
50
- const refCols = constraint.refColumns.map(quoteIdentifier).join(", ");
51
- let sql = `FOREIGN KEY (${cols}) REFERENCES ${quoteQualifiedIdentifier(constraint.refTable)} (${refCols})`;
52
- if (constraint.onDelete !== void 0) sql += ` ON DELETE ${REFERENTIAL_ACTION_SQL[constraint.onDelete]}`;
53
- if (constraint.onUpdate !== void 0) sql += ` ON UPDATE ${REFERENTIAL_ACTION_SQL[constraint.onUpdate]}`;
54
- if (constraint.name !== void 0) sql = `CONSTRAINT ${quoteIdentifier(constraint.name)} ${sql}`;
55
- return sql;
56
- }
57
- function renderUniqueConstraint(constraint) {
58
- const cols = constraint.columns.map(quoteIdentifier).join(", ");
59
- if (constraint.name !== void 0) return `CONSTRAINT ${quoteIdentifier(constraint.name)} UNIQUE (${cols})`;
60
- return `UNIQUE (${cols})`;
61
- }
62
- function renderTableConstraint(constraint) {
63
- switch (constraint.kind) {
64
- case "primary-key": return renderPrimaryKeyConstraint(constraint);
65
- case "foreign-key": return renderForeignKeyConstraint(constraint);
66
- case "unique": return renderUniqueConstraint(constraint);
67
- }
68
- }
69
- var PostgresDdlVisitorImpl = class {
70
- createTable(node) {
71
- const ifNotExists = node.ifNotExists ? "IF NOT EXISTS " : "";
72
- const tableRef = node.schema ? `${quoteIdentifier(node.schema)}.${quoteIdentifier(node.table)}` : quoteIdentifier(node.table);
73
- const columnDefs = node.columns.map((column) => renderColumn$1(column));
74
- const constraintDefs = node.constraints !== void 0 ? node.constraints.map(renderTableConstraint) : [];
75
- return `CREATE TABLE ${ifNotExists}${tableRef} (\n ${[...columnDefs, ...constraintDefs].join(",\n ")}\n)`;
76
- }
77
- createSchema(node) {
78
- return `CREATE SCHEMA ${node.ifNotExists ? "IF NOT EXISTS " : ""}${quoteIdentifier(node.schema)}`;
79
- }
80
- };
81
- function isTextLikeNativeType(nativeType) {
82
- return nativeType === "text" || nativeType === "varchar" || nativeType.startsWith("varchar(") || nativeType === "character varying" || nativeType.startsWith("character varying(") || nativeType === "char" || nativeType.startsWith("char(") || nativeType === "character" || nativeType.startsWith("character(");
83
- }
84
- const defaultVisitor = {
85
- literal(node, ctx) {
86
- const { value } = node;
87
- if (typeof value === "number" || typeof value === "boolean") return `DEFAULT ${String(value)}`;
88
- if (value === null) return "DEFAULT NULL";
89
- const literal = `'${escapeLiteral(typeof value === "string" ? value : JSON.stringify(value))}'`;
90
- return isTextLikeNativeType(ctx.nativeType) ? `DEFAULT ${literal}` : `DEFAULT ${literal}::${ctx.nativeType}`;
91
- },
92
- function(node, _ctx) {
93
- if (node.expression === "autoincrement()") return "";
94
- return `DEFAULT (${node.expression})`;
95
- }
96
- };
97
- function renderColumn$1(column) {
98
- const parts = [quoteIdentifier(column.name), column.type];
99
- if (column.notNull) parts.push("NOT NULL");
100
- if (column.primaryKey) parts.push("PRIMARY KEY");
101
- const defaultClause = column.default ? column.default.accept(defaultVisitor, { nativeType: column.type }) : "";
102
- if (defaultClause.length > 0) parts.push(defaultClause);
103
- return parts.join(" ");
104
- }
105
- function renderLoweredDdl(ast) {
106
- const sql = ast.accept(new PostgresDdlVisitorImpl());
107
- return Object.freeze({
108
- sql,
109
- params: Object.freeze([])
110
- });
39
+ //#region src/core/control-codecs.ts
40
+ const CONTROL_CODECS = createAstCodecRegistry(postgresCodecRegistry);
41
+ async function encodeControlQueryParams(lowered, ast, codecs = CONTROL_CODECS) {
42
+ return encodeParamsWithMetadata(lowered.params.map((slot) => {
43
+ if (slot.kind === "literal") return slot.value;
44
+ throw new Error(`control query lowered to a bind slot '${slot.name}', which is unsupported`);
45
+ }), deriveParamMetadata(ast), {}, codecs);
111
46
  }
112
47
  //#endregion
113
48
  //#region src/core/enum-control-hooks.ts
@@ -202,7 +137,6 @@ async function introspectPostgresEnumTypes(options) {
202
137
  }
203
138
  //#endregion
204
139
  //#region src/core/marker-ledger.ts
205
- const CONTROL_CODECS = createAstCodecRegistry(postgresCodecRegistry);
206
140
  const marker = pgTable({
207
141
  name: "marker",
208
142
  schema: "prisma_contract"
@@ -269,10 +203,7 @@ function mergeInvariants(current, incoming) {
269
203
  }
270
204
  async function execute(lower, driver, query) {
271
205
  const lowered = lower(query);
272
- const encoded = await encodeParamsWithMetadata(lowered.params.map((slot) => {
273
- if (slot.kind === "literal") return slot.value;
274
- throw new Error("Postgres control DML lowered to a bind parameter, which is unsupported");
275
- }), deriveParamMetadata(query), {}, CONTROL_CODECS);
206
+ const encoded = await encodeControlQueryParams(lowered, query);
276
207
  return (await driver.query(lowered.sql, encoded)).rows;
277
208
  }
278
209
  //#endregion
@@ -372,20 +303,89 @@ function renderLimitOffset(keyword, value, contract, pim) {
372
303
  return `${keyword} ${renderExpr(value, contract, pim)}`;
373
304
  }
374
305
  function renderSelect(ast, contract, pim) {
306
+ const selectClause = `SELECT ${renderDistinctPrefix(ast.distinct, ast.distinctOn, contract, pim)}${renderProjection(ast.projection, contract, pim)}`;
307
+ const fromClause = `FROM ${renderSource(ast.from, contract, pim)}`;
308
+ const joinsClause = ast.joins?.length ? ast.joins.map((join) => renderJoin(join, contract, pim)).join(" ") : "";
309
+ const whereClause = ast.where ? `WHERE ${renderWhere(ast.where, contract, pim)}` : "";
310
+ const groupByClause = ast.groupBy?.length ? `GROUP BY ${ast.groupBy.map((expr) => renderExpr(expr, contract, pim)).join(", ")}` : "";
311
+ const havingClause = ast.having ? `HAVING ${renderWhere(ast.having, contract, pim)}` : "";
312
+ const sourcesByRef = collectTableSources(ast);
375
313
  return [
376
- `SELECT ${renderDistinctPrefix(ast.distinct, ast.distinctOn, contract, pim)}${renderProjection(ast.projection, contract, pim)}`,
377
- `FROM ${renderSource(ast.from, contract, pim)}`,
378
- ast.joins?.length ? ast.joins.map((join) => renderJoin(join, contract, pim)).join(" ") : "",
379
- ast.where ? `WHERE ${renderWhere(ast.where, contract, pim)}` : "",
380
- ast.groupBy?.length ? `GROUP BY ${ast.groupBy.map((expr) => renderExpr(expr, contract, pim)).join(", ")}` : "",
381
- ast.having ? `HAVING ${renderWhere(ast.having, contract, pim)}` : "",
314
+ selectClause,
315
+ fromClause,
316
+ joinsClause,
317
+ whereClause,
318
+ groupByClause,
319
+ havingClause,
382
320
  ast.orderBy?.length ? `ORDER BY ${ast.orderBy.map((order) => {
383
- return `${renderExpr(order.expr, contract, pim)} ${order.dir.toUpperCase()}`;
321
+ return `${renderOrderByExpr(order.expr, sourcesByRef, contract, pim)} ${order.dir.toUpperCase()}`;
384
322
  }).join(", ")}` : "",
385
323
  renderLimitOffset("LIMIT", ast.limit, contract, pim),
386
324
  renderLimitOffset("OFFSET", ast.offset, contract, pim)
387
325
  ].filter((part) => part.length > 0).join(" ").trim();
388
326
  }
327
+ /**
328
+ * Map a SELECT's table references (the FROM source and any JOIN sources) to their storage coordinate, keyed by the name a `ColumnRef.table` would carry (the alias when present, otherwise the table name). Derived-table sources are skipped — their columns are projected through a sub-select, not a base storage column, so the enum hook does not apply.
329
+ */
330
+ function collectTableSources(ast) {
331
+ const sources = /* @__PURE__ */ new Map();
332
+ const add = (source) => {
333
+ if (source.kind !== "table-source") return;
334
+ const ref = source.alias ?? source.name;
335
+ sources.set(ref, {
336
+ name: source.name,
337
+ namespaceId: source.namespaceId
338
+ });
339
+ };
340
+ add(ast.from);
341
+ for (const join of ast.joins ?? []) add(join.source);
342
+ return sources;
343
+ }
344
+ /**
345
+ * Ordered, codec-encoded values of the value-set a storage column restricts to, or `undefined` when the referenced column carries no value-set (the common, non-enum case). Resolves the column's storage coordinate from the SELECT's table sources, then the column's `valueSet` ref to the value-set's `values`.
346
+ */
347
+ function allStrings(values) {
348
+ return values.every((value) => typeof value === "string");
349
+ }
350
+ function resolveEnumOrderValues(ref, sourcesByRef, contract) {
351
+ const source = sourcesByRef.get(ref.table);
352
+ if (source === void 0 || source.namespaceId === void 0) return;
353
+ const valueSet = (contract.storage.namespaces[source.namespaceId]?.entries.table[source.name]?.columns[ref.column])?.valueSet;
354
+ if (valueSet === void 0) return;
355
+ return contract.storage.namespaces[valueSet.namespaceId]?.entries.valueSet?.[valueSet.entityName]?.values;
356
+ }
357
+ /**
358
+ * Ordered values for an unqualified ORDER BY column (an `identifier-ref`, the shape the sql-builder emits for `.orderBy('col')`). Scans every FROM/JOIN source for a column of that name. Resolves only when exactly one source has a column of that name and it carries a value-set; if more than one source has such a column the bare identifier is ambiguous (regardless of which are enum-backed), so it falls through to the plain column rendering.
359
+ */
360
+ function resolveEnumOrderValuesForIdentifier(name, sourcesByRef, contract) {
361
+ let matchedColumns = 0;
362
+ let resolved;
363
+ for (const source of sourcesByRef.values()) {
364
+ if (source.namespaceId === void 0) continue;
365
+ const column = contract.storage.namespaces[source.namespaceId]?.entries.table[source.name]?.columns[name];
366
+ if (column === void 0) continue;
367
+ matchedColumns += 1;
368
+ if (matchedColumns > 1) return;
369
+ const valueSet = column.valueSet;
370
+ if (valueSet === void 0) return;
371
+ resolved = contract.storage.namespaces[valueSet.namespaceId]?.entries.valueSet?.[valueSet.entityName]?.values;
372
+ }
373
+ return resolved;
374
+ }
375
+ /**
376
+ * Render an ORDER BY expression. A column reference onto an enum-restricted column sorts by declaration order via `array_position(ARRAY[…]::text[], <col>)` over the value-set's ordered values (NULLs return `NULL` from `array_position`, sorting per the clause's default NULL handling). Both qualified `column-ref`s and the unqualified `identifier-ref`s the sql-builder emits for `.orderBy('col')` are intercepted. Every other expression renders unchanged.
377
+ */
378
+ function renderOrderByExpr(expr, sourcesByRef, contract, pim) {
379
+ if (expr.kind === "column-ref") {
380
+ const orderValues = resolveEnumOrderValues(expr, sourcesByRef, contract);
381
+ if (orderValues !== void 0 && allStrings(orderValues)) return `array_position(ARRAY[${orderValues.map((value) => `'${escapeLiteral(value)}'`).join(", ")}]::text[], ${renderColumn(expr)})`;
382
+ }
383
+ if (expr.kind === "identifier-ref") {
384
+ const orderValues = resolveEnumOrderValuesForIdentifier(expr.name, sourcesByRef, contract);
385
+ if (orderValues !== void 0 && allStrings(orderValues)) return `array_position(ARRAY[${orderValues.map((value) => `'${escapeLiteral(value)}'`).join(", ")}]::text[], ${quoteIdentifier(expr.name)})`;
386
+ }
387
+ return renderExpr(expr, contract, pim);
388
+ }
389
389
  function renderProjection(projection, contract, pim) {
390
390
  return projection.map((item) => {
391
391
  const alias = quoteIdentifier(item.alias);
@@ -732,16 +732,9 @@ const POSTGRES_LEDGER_TABLE = "prisma_contract.ledger";
732
732
  var PostgresControlAdapter = class {
733
733
  familyId = "sql";
734
734
  targetId = "postgres";
735
- codecLookup;
736
- /**
737
- * @param codecLookup - Codec lookup used by the SQL renderer to resolve
738
- * per-codec metadata at lower-time. Defaults to a Postgres-builtins-only
739
- * lookup when omitted. Stack-aware callers
740
- * (`SqlControlAdapterDescriptor.create(stack)`) supply
741
- * `stack.codecLookup` so extension codecs are visible to the renderer.
742
- */
743
- constructor(codecLookup) {
744
- this.codecLookup = codecLookup ?? createPostgresBuiltinCodecLookup();
735
+ codecRegistry;
736
+ constructor(codecRegistry) {
737
+ this.codecRegistry = codecRegistry;
745
738
  }
746
739
  /**
747
740
  * Target-specific normalizer for raw Postgres default expressions.
@@ -779,8 +772,24 @@ var PostgresControlAdapter = class {
779
772
  * without instantiating the runtime adapter.
780
773
  */
781
774
  lower(ast, context) {
782
- if (isDdlNode(ast)) return renderLoweredDdl(ast);
783
- return renderLoweredSql(ast, context.contract, this.codecLookup);
775
+ if (isDdlNode(ast)) throw new Error("lower() cannot lower DDL: DDL default literals require inline codec encoding, which is async. Use lowerToExecuteRequest().");
776
+ return renderLoweredSql(ast, blindCast(context.contract), this.codecRegistry);
777
+ }
778
+ /**
779
+ * Lower an AST all the way to a driver-ready statement. For DDL nodes,
780
+ * literal column defaults are formatted as inline SQL with proper quoting and
781
+ * `::nativeType` cast suffixes. For query ASTs, params are kept as `$N`
782
+ * placeholders; wire values go in `params`. Does NOT call `this.lower()` —
783
+ * independent implementation.
784
+ */
785
+ async lowerToExecuteRequest(ast, context) {
786
+ if (isDdlNode(ast)) return pgRenderDdlExecuteRequest(blindCast(ast), this.codecRegistry);
787
+ const lowered = renderLoweredSql(ast, blindCast(context?.contract), this.codecRegistry);
788
+ const params = await encodeControlQueryParams(lowered, ast, blindCast(this.codecRegistry));
789
+ return {
790
+ sql: lowered.sql,
791
+ params
792
+ };
784
793
  }
785
794
  /**
786
795
  * Reads the contract marker from `prisma_contract.marker`. Probes
@@ -1020,12 +1029,15 @@ var PostgresControlAdapter = class {
1020
1029
  for (const schema of uniqueSchemas) perSchema.push(await this.introspectSchema(driver, schema));
1021
1030
  const mergedTables = {};
1022
1031
  for (const ir of perSchema) for (const [tableName, table] of Object.entries(ir.tables)) mergedTables[tableName] = table;
1023
- const mergedStorageTypes = {};
1024
- for (let i = 0; i < perSchema.length; i++) {
1025
- const ir = perSchema[i];
1026
- const pg = blindCast(ir?.annotations?.["pg"])?.storageTypes;
1027
- if (!pg) continue;
1028
- for (const [key, value] of Object.entries(pg)) mergedStorageTypes[key] = value;
1032
+ const mergedEnumTypes = {};
1033
+ for (const ir of perSchema) {
1034
+ const enumTypes = blindCast(ir?.annotations?.["pg"])?.enumTypes;
1035
+ if (!enumTypes) continue;
1036
+ for (const [schemaName, byType] of Object.entries(enumTypes)) {
1037
+ const merged = mergedEnumTypes[schemaName] ?? {};
1038
+ Object.assign(merged, byType);
1039
+ mergedEnumTypes[schemaName] = merged;
1040
+ }
1029
1041
  }
1030
1042
  const firstAnnotations = perSchema[0]?.annotations;
1031
1043
  const firstPg = blindCast(firstAnnotations?.["pg"]) ?? {};
@@ -1035,7 +1047,7 @@ var PostgresControlAdapter = class {
1035
1047
  ...firstAnnotations,
1036
1048
  pg: {
1037
1049
  ...firstPg,
1038
- ...ifDefined("storageTypes", Object.keys(mergedStorageTypes).length > 0 ? mergedStorageTypes : void 0)
1050
+ ...ifDefined("enumTypes", Object.keys(mergedEnumTypes).length > 0 ? mergedEnumTypes : void 0)
1039
1051
  }
1040
1052
  })
1041
1053
  };
@@ -1295,18 +1307,17 @@ var PostgresControlAdapter = class {
1295
1307
  ...ifDefined("checks", checksForTable.length > 0 ? checksForTable : void 0)
1296
1308
  };
1297
1309
  }
1298
- const rawStorageTypes = await introspectPostgresEnumTypes({
1310
+ const rawEnumTypes = await introspectPostgresEnumTypes({
1299
1311
  driver,
1300
1312
  schemaName: schema
1301
1313
  });
1302
- const storageTypes = {};
1303
- for (const [typeName, annotation] of Object.entries(rawStorageTypes)) storageTypes[enumStorageCompoundKey(schema, typeName)] = annotation;
1314
+ const enumTypes = Object.keys(rawEnumTypes).length > 0 ? { [schema]: rawEnumTypes } : {};
1304
1315
  return {
1305
1316
  tables,
1306
1317
  annotations: { pg: {
1307
1318
  schema,
1308
1319
  version: await this.getPostgresVersion(driver),
1309
- ...ifDefined("storageTypes", Object.keys(storageTypes).length > 0 ? storageTypes : void 0)
1320
+ ...ifDefined("enumTypes", Object.keys(enumTypes).length > 0 ? enumTypes : void 0)
1310
1321
  } }
1311
1322
  };
1312
1323
  }
@@ -1474,7 +1485,89 @@ function extractQuotedLiterals(listBody) {
1474
1485
  const values = [...listBody.matchAll(/'((?:[^'\\]|\\.|'')*)'/g)].map((m) => (m[1] ?? "").replace(/''/g, "'"));
1475
1486
  return values.length > 0 ? values : void 0;
1476
1487
  }
1488
+ function pgIsTextLikeNativeType(nativeType) {
1489
+ return nativeType === "text" || nativeType === "varchar" || nativeType.startsWith("varchar(") || nativeType === "character varying" || nativeType.startsWith("character varying(") || nativeType === "char" || nativeType.startsWith("char(") || nativeType === "character" || nativeType.startsWith("character(");
1490
+ }
1491
+ function pgInlineLiteral(wire, nativeType) {
1492
+ if (wire === null) return "NULL";
1493
+ if (typeof wire === "boolean") return wire ? "true" : "false";
1494
+ if (typeof wire === "number") {
1495
+ if (!Number.isFinite(wire)) throw new Error(`pgRenderDdlExecuteRequest: non-finite number wire value ${String(wire)} cannot be emitted as a DEFAULT literal for native type "${nativeType}"`);
1496
+ return String(wire);
1497
+ }
1498
+ if (typeof wire === "bigint") return String(wire);
1499
+ if (wire instanceof Date) {
1500
+ if (Number.isNaN(wire.getTime())) throw new Error(`pgRenderDdlExecuteRequest: invalid Date value cannot be emitted as a DEFAULT literal for native type "${nativeType}"`);
1501
+ const quoted = `'${escapeLiteral(wire.toISOString())}'`;
1502
+ return pgIsTextLikeNativeType(nativeType) ? quoted : `${quoted}::${nativeType}`;
1503
+ }
1504
+ if (typeof wire === "string") {
1505
+ const quoted = `'${escapeLiteral(wire)}'`;
1506
+ return pgIsTextLikeNativeType(nativeType) ? quoted : `${quoted}::${nativeType}`;
1507
+ }
1508
+ if (wire instanceof Uint8Array) return `'\\x${Array.from(wire).map((b) => b.toString(16).padStart(2, "0")).join("")}'::${nativeType}`;
1509
+ if (typeof wire === "object") return `${`'${escapeLiteral(JSON.stringify(wire))}'`}::${nativeType}`;
1510
+ throw new Error(`pgRenderDdlExecuteRequest: unexpected wire type "${typeof wire}" for native type "${nativeType}"`);
1511
+ }
1512
+ async function pgRenderDdlColumnDefault(def, nativeType, codecLookup, codecRef) {
1513
+ if (def.kind === "function") {
1514
+ if (def.expression === "autoincrement()") return "";
1515
+ return `DEFAULT (${def.expression})`;
1516
+ }
1517
+ if (codecRef !== void 0) {
1518
+ const codec = codecLookup.get(codecRef.codecId);
1519
+ if (codec !== void 0) return `DEFAULT ${pgInlineLiteral(await codec.encode(def.value, {}), nativeType)}`;
1520
+ }
1521
+ return `DEFAULT ${pgInlineLiteral(def.value, nativeType)}`;
1522
+ }
1523
+ async function pgRenderDdlColumn(column, codecLookup) {
1524
+ const parts = [quoteIdentifier(column.name), column.type];
1525
+ if (column.notNull) parts.push("NOT NULL");
1526
+ if (column.primaryKey) parts.push("PRIMARY KEY");
1527
+ if (column.default) {
1528
+ const clause = await pgRenderDdlColumnDefault(column.default, column.type, codecLookup, column.codecRef);
1529
+ if (clause.length > 0) parts.push(clause);
1530
+ }
1531
+ return parts.join(" ");
1532
+ }
1533
+ function pgRenderDdlConstraint(constraint) {
1534
+ if (constraint.kind === "primary-key") {
1535
+ const cols = constraint.columns.map(quoteIdentifier).join(", ");
1536
+ if (constraint.name !== void 0) return `CONSTRAINT ${quoteIdentifier(constraint.name)} PRIMARY KEY (${cols})`;
1537
+ return `PRIMARY KEY (${cols})`;
1538
+ }
1539
+ if (constraint.kind === "foreign-key") {
1540
+ let sql = `FOREIGN KEY (${constraint.columns.map(quoteIdentifier).join(", ")}) REFERENCES ${constraint.refTable.split(".").map(quoteIdentifier).join(".")} (${constraint.refColumns.map(quoteIdentifier).join(", ")})`;
1541
+ if (constraint.onDelete !== void 0) sql += ` ON DELETE ${REFERENTIAL_ACTION_SQL[constraint.onDelete]}`;
1542
+ if (constraint.onUpdate !== void 0) sql += ` ON UPDATE ${REFERENTIAL_ACTION_SQL[constraint.onUpdate]}`;
1543
+ if (constraint.name !== void 0) sql = `CONSTRAINT ${quoteIdentifier(constraint.name)} ${sql}`;
1544
+ return sql;
1545
+ }
1546
+ const cols = constraint.columns.map(quoteIdentifier).join(", ");
1547
+ if (constraint.name !== void 0) return `CONSTRAINT ${quoteIdentifier(constraint.name)} UNIQUE (${cols})`;
1548
+ return `UNIQUE (${cols})`;
1549
+ }
1550
+ async function pgRenderCreateTable(node, codecLookup) {
1551
+ const ifNotExists = node.ifNotExists ? "IF NOT EXISTS " : "";
1552
+ const tableRef = node.schema ? `${quoteIdentifier(node.schema)}.${quoteIdentifier(node.table)}` : quoteIdentifier(node.table);
1553
+ const columnDefs = await Promise.all(node.columns.map((col) => pgRenderDdlColumn(col, codecLookup)));
1554
+ const constraintDefs = node.constraints !== void 0 ? node.constraints.map(pgRenderDdlConstraint) : [];
1555
+ return {
1556
+ sql: `CREATE TABLE ${ifNotExists}${tableRef} (\n ${[...columnDefs, ...constraintDefs].join(",\n ")}\n)`,
1557
+ params: []
1558
+ };
1559
+ }
1560
+ function pgRenderCreateSchema(node) {
1561
+ return {
1562
+ sql: `CREATE SCHEMA ${node.ifNotExists ? "IF NOT EXISTS " : ""}${quoteIdentifier(node.schema)}`,
1563
+ params: []
1564
+ };
1565
+ }
1566
+ async function pgRenderDdlExecuteRequest(ast, codecLookup) {
1567
+ if (ast.kind === "create-table") return pgRenderCreateTable(blindCast(ast), codecLookup);
1568
+ return pgRenderCreateSchema(blindCast(ast));
1569
+ }
1477
1570
  //#endregion
1478
- export { createPostgresBuiltinCodecLookup as i, renderLoweredSql as n, renderLoweredDdl as r, PostgresControlAdapter as t };
1571
+ export { renderLoweredSql as n, createPostgresBuiltinCodecLookup as r, PostgresControlAdapter as t };
1479
1572
 
1480
- //# sourceMappingURL=control-adapter-ZWrjGBq7.mjs.map
1573
+ //# sourceMappingURL=control-adapter-BeSqyOGl.mjs.map