@prisma-next/adapter-postgres 0.16.0-dev.22 → 0.16.0-dev.23
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/dist/{adapter-DcBWxseT.mjs → adapter-CuTsfsz3.mjs} +4 -4
- package/dist/adapter-CuTsfsz3.mjs.map +1 -0
- package/dist/adapter.d.mts.map +1 -1
- package/dist/adapter.mjs +1 -1
- package/dist/{control-adapter-hSsjUXtc.mjs → control-adapter-Xog0HsuP.mjs} +49 -25
- package/dist/control-adapter-Xog0HsuP.mjs.map +1 -0
- package/dist/control.d.mts +2 -2
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +4 -4
- package/dist/control.mjs.map +1 -1
- package/dist/{descriptor-meta-jMtx881n.mjs → descriptor-meta-DpA4aG-x.mjs} +26 -6
- package/dist/descriptor-meta-DpA4aG-x.mjs.map +1 -0
- package/dist/runtime.mjs +2 -2
- package/package.json +23 -23
- package/src/core/adapter-errors.ts +25 -0
- package/src/core/adapter.ts +7 -2
- package/src/core/control-adapter.ts +19 -6
- package/src/core/control-codecs.ts +4 -1
- package/src/core/descriptor-meta.ts +16 -5
- package/src/core/sql-renderer.ts +46 -16
- package/src/exports/control.ts +1 -2
- package/dist/adapter-DcBWxseT.mjs.map +0 -1
- package/dist/control-adapter-hSsjUXtc.mjs.map +0 -1
- package/dist/descriptor-meta-jMtx881n.mjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as renderLoweredSql, r as createPostgresBuiltinCodecLookup, t as PostgresControlAdapter } from "./control-adapter-
|
|
1
|
+
import { i as adapterError, n as renderLoweredSql, r as createPostgresBuiltinCodecLookup, t as PostgresControlAdapter } from "./control-adapter-Xog0HsuP.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
|
|
@@ -42,7 +42,7 @@ var PostgresAdapterImpl = class {
|
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
44
|
lower(ast, context) {
|
|
45
|
-
if (isDdlNode(ast)) throw
|
|
45
|
+
if (isDdlNode(ast)) throw adapterError("RUNTIME.DDL_UNSUPPORTED", "lower() does not lower DDL on the runtime adapter — DDL lowering is a control-plane concern handled by the control adapter.", { meta: { surface: "runtime-adapter" } });
|
|
46
46
|
return renderLoweredSql(ast, context.contract, this.codecLookup);
|
|
47
47
|
}
|
|
48
48
|
};
|
|
@@ -55,7 +55,7 @@ const postgresRawCodecInferer = { inferCodec(value) {
|
|
|
55
55
|
case "boolean": return "pg/bool";
|
|
56
56
|
case "object": if (value instanceof Uint8Array) return "pg/bytea";
|
|
57
57
|
}
|
|
58
|
-
throw
|
|
58
|
+
throw adapterError("RUNTIME.RAW_SQL_UNSUPPORTED_INTERPOLATION", "unsupported JS value type for raw-SQL interpolation: wrap this value in `param(...)` with an explicit codec", { meta: { valueType: typeof value } });
|
|
59
59
|
} };
|
|
60
60
|
function createPostgresAdapter(options) {
|
|
61
61
|
return Object.freeze(new PostgresAdapterImpl(options));
|
|
@@ -63,4 +63,4 @@ function createPostgresAdapter(options) {
|
|
|
63
63
|
//#endregion
|
|
64
64
|
export { postgresRawCodecInferer as n, createPostgresAdapter as t };
|
|
65
65
|
|
|
66
|
-
//# sourceMappingURL=adapter-
|
|
66
|
+
//# sourceMappingURL=adapter-CuTsfsz3.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-CuTsfsz3.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 { adapterError } from './adapter-errors';\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 scalarList: 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 adapterError(\n 'RUNTIME.DDL_UNSUPPORTED',\n 'lower() does not lower DDL on the runtime adapter — DDL lowering is a control-plane concern handled by the control adapter.',\n { meta: { surface: 'runtime-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 adapterError(\n 'RUNTIME.RAW_SQL_UNSUPPORTED_INTERPOLATION',\n 'unsupported JS value type for raw-SQL interpolation: wrap this value in `param(...)` with an explicit codec',\n { meta: { valueType: typeof value } },\n );\n },\n};\n\nexport function createPostgresAdapter(options?: PostgresAdapterOptions) {\n return Object.freeze(new PostgresAdapterImpl(options));\n}\n"],"mappings":";;;;AAmBA,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;EACT,YAAY;CACd;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,aACJ,2BACA,+HACA,EAAE,MAAM,EAAE,SAAS,kBAAkB,EAAE,CACzC;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,aACJ,6CACA,+GACA,EAAE,MAAM,EAAE,WAAW,OAAO,MAAM,EAAE,CACtC;AACF,EACF;AAEA,SAAgB,sBAAsB,SAAkC;CACtE,OAAO,OAAO,OAAO,IAAI,oBAAoB,OAAO,CAAC;AACvD"}
|
package/dist/adapter.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.mts","names":[],"sources":["../src/core/adapter.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"adapter.d.mts","names":[],"sources":["../src/core/adapter.ts"],"mappings":";;;;;cAqCM,+BACO,QAAQ,aAAa,kBAAkB;WAGzC;WACA;WAEA,SAAS;mBACD;cAEL,UAAU;EA0BtB,MACE,KAAK,cAAc,iBACnB,SAAS,eAAe,oBACvB;;;cAaQ,yBAAyB;iBAsBtB,sBAAsB,UAAU,yBAAsB,SAAA"}
|
package/dist/adapter.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as postgresRawCodecInferer, t as createPostgresAdapter } from "./adapter-
|
|
1
|
+
import { n as postgresRawCodecInferer, t as createPostgresAdapter } from "./adapter-CuTsfsz3.mjs";
|
|
2
2
|
export { createPostgresAdapter, postgresRawCodecInferer };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { APP_SPACE_ID, extractCodecLookup } from "@prisma-next/framework-components/control";
|
|
2
2
|
import { LiteralExpr, RawExpr, collectOrderedParamRefs, isDdlNode } from "@prisma-next/sql-relational-core/ast";
|
|
3
|
+
import { structuredError } from "@prisma-next/utils/structured-error";
|
|
3
4
|
import { isPgEnumParams, postgresCodecRegistry } from "@prisma-next/target-postgres/codecs";
|
|
4
5
|
import { parseMarkerRowSafely, rethrowMarkerReadError, withMarkerReadErrorHandling } from "@prisma-next/errors/execution";
|
|
5
6
|
import { parseContractMarkerRow } from "@prisma-next/family-sql/verify";
|
|
@@ -15,8 +16,14 @@ import { PostgresDatabaseSchemaNode, PostgresNamespaceSchemaNode, PostgresNative
|
|
|
15
16
|
import { blindCast } from "@prisma-next/utils/casts";
|
|
16
17
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
17
18
|
import { createAstCodecRegistry, deriveParamMetadata, encodeParamsWithMetadata } from "@prisma-next/sql-runtime";
|
|
19
|
+
import { InternalError, assertNever } from "@prisma-next/utils/internal-error";
|
|
18
20
|
import { PG_TIMESTAMPTZ_CODEC_ID } from "@prisma-next/target-postgres/codec-ids";
|
|
19
21
|
import { runtimeError } from "@prisma-next/framework-components/runtime";
|
|
22
|
+
//#region src/core/adapter-errors.ts
|
|
23
|
+
function adapterError(code, message, options) {
|
|
24
|
+
return structuredError(code, message, options);
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
20
27
|
//#region src/core/codec-lookup.ts
|
|
21
28
|
/**
|
|
22
29
|
* Build a {@link CodecRegistry} populated with the Postgres-builtin codec definitions only.
|
|
@@ -43,7 +50,7 @@ const CONTROL_CODECS = createAstCodecRegistry(postgresCodecRegistry);
|
|
|
43
50
|
async function encodeControlQueryParams(lowered, ast, codecs = CONTROL_CODECS) {
|
|
44
51
|
return encodeParamsWithMetadata(lowered.params.map((slot) => {
|
|
45
52
|
if (slot.kind === "literal") return slot.value;
|
|
46
|
-
throw new
|
|
53
|
+
throw new InternalError(`control query lowered to a bind slot '${slot.name}', which is unsupported`);
|
|
47
54
|
}), deriveParamMetadata(ast), {}, codecs);
|
|
48
55
|
}
|
|
49
56
|
//#endregion
|
|
@@ -163,7 +170,7 @@ const POSTGRES_INFERRABLE_NATIVE_TYPES = /* @__PURE__ */ new Set([
|
|
|
163
170
|
function renderTypedParam(index, codecId, codecLookup, many, typeParams) {
|
|
164
171
|
if (codecId === void 0) return `$${index}`;
|
|
165
172
|
const meta = codecLookup.metaFor(codecId, typeParams);
|
|
166
|
-
if (!(codecLookup.get(codecId) !== void 0 || meta !== void 0 || codecLookup.targetTypesFor(codecId) !== void 0)) throw
|
|
173
|
+
if (!(codecLookup.get(codecId) !== void 0 || meta !== void 0 || codecLookup.targetTypesFor(codecId) !== void 0)) throw adapterError("RUNTIME.PARAM_REF_MISSING_CODEC", `Postgres lowering: ParamRef carries codecId "${codecId}" but the assembled codec lookup has no entry for it. This usually indicates a missing extension pack in the runtime stack — register the pack that contributes this codec (e.g. \`extensions: [pgvectorRuntime]\`), or use the codec directly from \`@prisma-next/target-postgres/codecs\` if it's a builtin.`, { meta: { codecId } });
|
|
167
174
|
const dbRecord = meta?.db;
|
|
168
175
|
const sqlBlock = isRecord(dbRecord) ? dbRecord["sql"] : void 0;
|
|
169
176
|
const dialectBlock = isRecord(sqlBlock) ? sqlBlock["postgres"] : void 0;
|
|
@@ -225,7 +232,7 @@ function renderLoweredSql(ast, contract, codecLookup) {
|
|
|
225
232
|
sql = renderRawSql(node, contract, pim);
|
|
226
233
|
break;
|
|
227
234
|
// v8 ignore next 4
|
|
228
|
-
default:
|
|
235
|
+
default: assertNever(node, `Unsupported AST node kind: ${unreachableKind(node)}`);
|
|
229
236
|
}
|
|
230
237
|
return Object.freeze({
|
|
231
238
|
sql,
|
|
@@ -348,9 +355,17 @@ function qualifyTableFromNamespaceCoordinate(table, contract) {
|
|
|
348
355
|
if (hasExplicitSchema(table)) return `${quoteIdentifier(table.schema)}.${quoteIdentifier(table.name)}`;
|
|
349
356
|
if (table.namespaceId === void 0) return quoteIdentifier(table.name);
|
|
350
357
|
const namespace = contract.storage.namespaces[table.namespaceId];
|
|
351
|
-
if (namespace === void 0) throw
|
|
358
|
+
if (namespace === void 0) throw adapterError("RUNTIME.NAMESPACE_UNKNOWN", `Table "${table.name}" references namespace "${table.namespaceId}" which is not present as a Postgres schema on the contract`, { meta: {
|
|
359
|
+
table: table.name,
|
|
360
|
+
namespaceId: table.namespaceId,
|
|
361
|
+
reason: "not-present"
|
|
362
|
+
} });
|
|
352
363
|
const qualifyTable = namespace.qualifyTable;
|
|
353
|
-
if (qualifyTable === void 0) throw
|
|
364
|
+
if (qualifyTable === void 0) throw adapterError("RUNTIME.NAMESPACE_UNKNOWN", `Table "${table.name}" references namespace "${table.namespaceId}" which is not materialised as a Postgres schema on the contract`, { meta: {
|
|
365
|
+
table: table.name,
|
|
366
|
+
namespaceId: table.namespaceId,
|
|
367
|
+
reason: "not-materialised"
|
|
368
|
+
} });
|
|
354
369
|
return qualifyTable.call(namespace, table.name);
|
|
355
370
|
}
|
|
356
371
|
function renderTableSource(source, contract) {
|
|
@@ -368,11 +383,11 @@ function renderSource(source, contract, pim) {
|
|
|
368
383
|
return `${`${node.fn}(${args})`}${node.ordinality ? " WITH ORDINALITY" : ""}${node.alias === void 0 ? "" : ` AS ${quoteIdentifier(node.alias)}`}${node.columnAliases === void 0 ? "" : `(${node.columnAliases.map((column) => quoteIdentifier(column)).join(", ")})`}`;
|
|
369
384
|
}
|
|
370
385
|
// v8 ignore next 4
|
|
371
|
-
default:
|
|
386
|
+
default: assertNever(node, `Unsupported source node kind: ${unreachableKind(node)}`);
|
|
372
387
|
}
|
|
373
388
|
}
|
|
374
389
|
function assertScalarSubquery(query) {
|
|
375
|
-
if (query.projection.length !== 1) throw
|
|
390
|
+
if (query.projection.length !== 1) throw adapterError("RUNTIME.AST_INVALID", "Subquery expressions must project exactly one column", { meta: { node: "subquery-expr" } });
|
|
376
391
|
}
|
|
377
392
|
function renderSubqueryExpr(expr, contract, pim) {
|
|
378
393
|
assertScalarSubquery(expr.query);
|
|
@@ -538,12 +553,12 @@ function renderExpr(expr, contract, pim) {
|
|
|
538
553
|
case "list": return renderListLiteral(node, contract, pim);
|
|
539
554
|
case "raw-expr": return renderRawExpr(node, contract, pim);
|
|
540
555
|
// v8 ignore next 4
|
|
541
|
-
default:
|
|
556
|
+
default: assertNever(node, `Unsupported expression node kind: ${unreachableKind(node)}`);
|
|
542
557
|
}
|
|
543
558
|
}
|
|
544
559
|
function renderParamRef(ref, pim) {
|
|
545
560
|
const index = pim.indexMap.get(ref);
|
|
546
|
-
if (index === void 0) throw new
|
|
561
|
+
if (index === void 0) throw new InternalError("ParamRef not found in index map");
|
|
547
562
|
if (ref.kind === "prepared-param-ref") return renderTypedParam(index, ref.codec.codecId, pim.codecLookup, ref.codec.many, ref.codec.typeParams);
|
|
548
563
|
if (ref.codec === void 0) throw runtimeError("RUNTIME.PARAM_REF_MISSING_CODEC", "Postgres renderer: ParamRef reached lowering without a bound CodecRef. Every column-bound ParamRef must carry a codec under the AST-bound codec contract. This usually indicates a builder path that constructed a ParamRef without threading the column codec.", {
|
|
549
564
|
paramIndex: index,
|
|
@@ -571,7 +586,7 @@ function renderOperation(expr, contract, pim) {
|
|
|
571
586
|
return expr.lowering.template.replace(/\{\{self\}\}|\{\{arg(\d+)\}\}/g, (token, argIndex) => {
|
|
572
587
|
if (token === "{{self}}") return self;
|
|
573
588
|
const arg = args[Number(argIndex)];
|
|
574
|
-
if (arg === void 0) throw
|
|
589
|
+
if (arg === void 0) throw adapterError("CONTRACT.PACK_CONTRIBUTION_INVALID", `Operation lowering template for "${expr.method}" referenced missing argument {{arg${argIndex}}}; template has ${args.length} arg(s)`, { meta: { method: expr.method } });
|
|
575
590
|
return arg;
|
|
576
591
|
});
|
|
577
592
|
}
|
|
@@ -604,7 +619,10 @@ function getInsertColumnOrder(rows, contract, tableRef) {
|
|
|
604
619
|
break;
|
|
605
620
|
}
|
|
606
621
|
}
|
|
607
|
-
if (!table) throw
|
|
622
|
+
if (!table) throw adapterError("RUNTIME.AST_INVALID", `INSERT target table not found in contract storage: ${tableName}`, { meta: {
|
|
623
|
+
node: "insert",
|
|
624
|
+
table: tableName
|
|
625
|
+
} });
|
|
608
626
|
return Object.keys(table.columns);
|
|
609
627
|
}
|
|
610
628
|
function renderInsertValue(value, contract, pim) {
|
|
@@ -615,13 +633,13 @@ function renderInsertValue(value, contract, pim) {
|
|
|
615
633
|
case "column-ref": return renderColumn(value);
|
|
616
634
|
case "raw-expr": return renderExpr(value, contract, pim);
|
|
617
635
|
// v8 ignore next 4
|
|
618
|
-
default:
|
|
636
|
+
default: assertNever(value, `Unsupported value node in INSERT: ${unreachableKind(value)}`);
|
|
619
637
|
}
|
|
620
638
|
}
|
|
621
639
|
function renderInsert(ast, contract, pim) {
|
|
622
640
|
const table = qualifyTableFromNamespaceCoordinate(ast.table, contract);
|
|
623
641
|
const rows = ast.rows;
|
|
624
|
-
if (rows.length === 0) throw
|
|
642
|
+
if (rows.length === 0) throw adapterError("RUNTIME.AST_INVALID", "INSERT requires at least one row", { meta: { node: "insert" } });
|
|
625
643
|
const hasExplicitValues = rows.some((row) => Object.keys(row).length > 0);
|
|
626
644
|
return `${(() => {
|
|
627
645
|
if (!hasExplicitValues) {
|
|
@@ -640,27 +658,27 @@ function renderInsert(ast, contract, pim) {
|
|
|
640
658
|
return `INSERT INTO ${table} (${columns.join(", ")}) VALUES ${values}`;
|
|
641
659
|
})()}${ast.onConflict ? (() => {
|
|
642
660
|
const conflictColumns = ast.onConflict.columns.map((col) => quoteIdentifier(col.column));
|
|
643
|
-
if (conflictColumns.length === 0) throw
|
|
661
|
+
if (conflictColumns.length === 0) throw adapterError("RUNTIME.AST_INVALID", "INSERT onConflict requires at least one conflict column", { meta: { node: "insert-on-conflict" } });
|
|
644
662
|
const action = ast.onConflict.action;
|
|
645
663
|
switch (action.kind) {
|
|
646
664
|
case "do-nothing": return ` ON CONFLICT (${conflictColumns.join(", ")}) DO NOTHING`;
|
|
647
665
|
case "do-update-set": {
|
|
648
666
|
const updateEntries = Object.entries(action.set);
|
|
649
|
-
if (updateEntries.length === 0) throw
|
|
667
|
+
if (updateEntries.length === 0) throw adapterError("RUNTIME.AST_INVALID", "INSERT onConflict do-update-set requires at least one assignment", { meta: { node: "insert-on-conflict" } });
|
|
650
668
|
const updates = updateEntries.map(([colName, value]) => {
|
|
651
669
|
return `${quoteIdentifier(colName)} = ${renderExpr(value, contract, pim)}`;
|
|
652
670
|
});
|
|
653
671
|
return ` ON CONFLICT (${conflictColumns.join(", ")}) DO UPDATE SET ${updates.join(", ")}`;
|
|
654
672
|
}
|
|
655
673
|
// v8 ignore next 4
|
|
656
|
-
default:
|
|
674
|
+
default: assertNever(action, `Unsupported onConflict action: ${unreachableKind(action)}`);
|
|
657
675
|
}
|
|
658
676
|
})() : ""}${ast.returning?.length ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}` : ""}`;
|
|
659
677
|
}
|
|
660
678
|
function renderUpdate(ast, contract, pim) {
|
|
661
679
|
const table = qualifyTableFromNamespaceCoordinate(ast.table, contract);
|
|
662
680
|
const setEntries = Object.entries(ast.set);
|
|
663
|
-
if (setEntries.length === 0) throw
|
|
681
|
+
if (setEntries.length === 0) throw adapterError("RUNTIME.AST_INVALID", "UPDATE requires at least one SET assignment", { meta: { node: "update" } });
|
|
664
682
|
const setClauses = setEntries.map(([col, val]) => {
|
|
665
683
|
return `${quoteIdentifier(col)} = ${renderExpr(val, contract, pim)}`;
|
|
666
684
|
});
|
|
@@ -726,7 +744,7 @@ var PostgresControlAdapter = class {
|
|
|
726
744
|
* without instantiating the runtime adapter.
|
|
727
745
|
*/
|
|
728
746
|
lower(ast, context) {
|
|
729
|
-
if (isDdlNode(ast)) throw
|
|
747
|
+
if (isDdlNode(ast)) throw adapterError("RUNTIME.DDL_UNSUPPORTED", "lower() cannot lower DDL: DDL default literals require inline codec encoding, which is async. Use lowerToExecuteRequest().", { meta: { surface: "control-adapter" } });
|
|
730
748
|
return renderLoweredSql(ast, blindCast(context.contract), this.codecRegistry);
|
|
731
749
|
}
|
|
732
750
|
/**
|
|
@@ -1492,7 +1510,7 @@ const PG_REFERENTIAL_ACTION_MAP = {
|
|
|
1492
1510
|
*/
|
|
1493
1511
|
function mapReferentialAction(rule) {
|
|
1494
1512
|
const mapped = PG_REFERENTIAL_ACTION_MAP[rule];
|
|
1495
|
-
if (mapped === void 0) throw
|
|
1513
|
+
if (mapped === void 0) throw adapterError("CONTRACT.INTROSPECTION_UNSUPPORTED", `Unknown PostgreSQL referential action rule: "${rule}". Expected one of: NO ACTION, RESTRICT, CASCADE, SET NULL, SET DEFAULT.`, { meta: { rule } });
|
|
1496
1514
|
if (mapped === "noAction") return void 0;
|
|
1497
1515
|
return mapped;
|
|
1498
1516
|
}
|
|
@@ -1559,7 +1577,10 @@ function parsePgReloptions(reloptions, indexName) {
|
|
|
1559
1577
|
const result = {};
|
|
1560
1578
|
for (const entry of reloptions) {
|
|
1561
1579
|
const eq = entry.indexOf("=");
|
|
1562
|
-
if (eq === -1) throw
|
|
1580
|
+
if (eq === -1) throw adapterError("CONTRACT.INTROSPECTION_UNSUPPORTED", `Postgres introspection: malformed reloption entry "${entry}" on index "${indexName}" (expected "key=value")`, { meta: {
|
|
1581
|
+
entry,
|
|
1582
|
+
indexName
|
|
1583
|
+
} });
|
|
1563
1584
|
const key = entry.slice(0, eq);
|
|
1564
1585
|
result[key] = entry.slice(eq + 1);
|
|
1565
1586
|
}
|
|
@@ -1664,12 +1685,12 @@ function pgInlineLiteral(wire, nativeType) {
|
|
|
1664
1685
|
if (wire === null) return "NULL";
|
|
1665
1686
|
if (typeof wire === "boolean") return wire ? "true" : "false";
|
|
1666
1687
|
if (typeof wire === "number") {
|
|
1667
|
-
if (!Number.isFinite(wire)) throw
|
|
1688
|
+
if (!Number.isFinite(wire)) throw adapterError("CONTRACT.DEFAULT_INVALID", `pgRenderDdlExecuteRequest: non-finite number wire value ${String(wire)} cannot be emitted as a DEFAULT literal for native type "${nativeType}"`, { meta: { nativeType } });
|
|
1668
1689
|
return String(wire);
|
|
1669
1690
|
}
|
|
1670
1691
|
if (typeof wire === "bigint") return String(wire);
|
|
1671
1692
|
if (wire instanceof Date) {
|
|
1672
|
-
if (Number.isNaN(wire.getTime())) throw
|
|
1693
|
+
if (Number.isNaN(wire.getTime())) throw adapterError("CONTRACT.DEFAULT_INVALID", `pgRenderDdlExecuteRequest: invalid Date value cannot be emitted as a DEFAULT literal for native type "${nativeType}"`, { meta: { nativeType } });
|
|
1673
1694
|
const quoted = `'${escapeLiteral(wire.toISOString())}'`;
|
|
1674
1695
|
return pgIsTextLikeNativeType(nativeType) ? quoted : `${quoted}::${nativeType}`;
|
|
1675
1696
|
}
|
|
@@ -1680,7 +1701,10 @@ function pgInlineLiteral(wire, nativeType) {
|
|
|
1680
1701
|
if (wire instanceof Uint8Array) return `'\\x${Array.from(wire).map((b) => b.toString(16).padStart(2, "0")).join("")}'::${nativeType}`;
|
|
1681
1702
|
if (Array.isArray(wire) && nativeType.endsWith("[]")) return pgRenderArrayLiteral(wire);
|
|
1682
1703
|
if (typeof wire === "object") return `${`'${escapeLiteral(JSON.stringify(wire))}'`}::${nativeType}`;
|
|
1683
|
-
throw
|
|
1704
|
+
throw adapterError("CONTRACT.PACK_CONTRIBUTION_INVALID", `pgRenderDdlExecuteRequest: unexpected wire type "${typeof wire}" for native type "${nativeType}"`, { meta: {
|
|
1705
|
+
wireType: typeof wire,
|
|
1706
|
+
nativeType
|
|
1707
|
+
} });
|
|
1684
1708
|
}
|
|
1685
1709
|
async function pgRenderDdlColumnDefault(def, nativeType, codecLookup, codecRef) {
|
|
1686
1710
|
if (def.kind === "function") {
|
|
@@ -1818,6 +1842,6 @@ async function pgRenderDdlExecuteRequest(ast, codecLookup) {
|
|
|
1818
1842
|
});
|
|
1819
1843
|
}
|
|
1820
1844
|
//#endregion
|
|
1821
|
-
export { renderLoweredSql as n, createPostgresBuiltinCodecLookup as r, PostgresControlAdapter as t };
|
|
1845
|
+
export { adapterError as i, renderLoweredSql as n, createPostgresBuiltinCodecLookup as r, PostgresControlAdapter as t };
|
|
1822
1846
|
|
|
1823
|
-
//# sourceMappingURL=control-adapter-
|
|
1847
|
+
//# sourceMappingURL=control-adapter-Xog0HsuP.mjs.map
|