@prisma/orm-target-postgres 0.17.0-dev.1 → 0.17.0-dev.2
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-DhqcO3YO-jzwDVcCv.mjs → adapter-wewzDGJh-DkJnr3kE.mjs} +4 -3
- package/dist/adapter-wewzDGJh-DkJnr3kE.mjs.map +1 -0
- package/dist/adapter.d.mts +2 -1
- package/dist/adapter.mjs +4 -3
- package/dist/adapter__adapter.mjs +1 -1
- package/dist/adapter__control.mjs +2 -2
- package/dist/adapter__control.mjs.map +1 -1
- package/dist/adapter__runtime.mjs +4 -4
- package/dist/adapter__runtime.mjs.map +1 -1
- package/dist/adapter__sql-renderer.d.mts +2 -0
- package/dist/adapter__sql-renderer.mjs +2 -0
- package/dist/aggregates-CgqNfj2O.d.mts +10 -0
- package/dist/aggregates-CgqNfj2O.d.mts.map +1 -0
- package/dist/aggregates-ftUgi-eC.mjs +102 -0
- package/dist/aggregates-ftUgi-eC.mjs.map +1 -0
- package/dist/{codecs-CBl0nD44-CaWPc1bd.mjs → codecs-CBl0nD44-CjInu_aV.mjs} +2 -2
- package/dist/{codecs-CBl0nD44-CaWPc1bd.mjs.map → codecs-CBl0nD44-CjInu_aV.mjs.map} +1 -1
- package/dist/{codecs-CHIVTNZs.mjs → codecs-rujsdlZR.mjs} +2 -2
- package/dist/{codecs-CHIVTNZs.mjs.map → codecs-rujsdlZR.mjs.map} +1 -1
- package/dist/{control-DRMWptiJ.mjs → control-BzDnaGim.mjs} +5 -5
- package/dist/{control-DRMWptiJ.mjs.map → control-BzDnaGim.mjs.map} +1 -1
- package/dist/{control-adapter-B9t0g7Pf-HrCxlM65.mjs → control-adapter-CipVam9p-B-E2SF8_.mjs} +9 -578
- package/dist/control-adapter-CipVam9p-B-E2SF8_.mjs.map +1 -0
- package/dist/{control-policy-Cl3RRSPg-CT3QGpR3.mjs → control-policy-Cl3RRSPg-BUi6pcI-.mjs} +3 -3
- package/dist/{control-policy-Cl3RRSPg-CT3QGpR3.mjs.map → control-policy-Cl3RRSPg-BUi6pcI-.mjs.map} +1 -1
- package/dist/{descriptor-meta-2IlVC6_d-DnV00Qd_.mjs → descriptor-meta--MCrvIgj-DFsLFDj1.mjs} +6 -4
- package/dist/descriptor-meta--MCrvIgj-DFsLFDj1.mjs.map +1 -0
- package/dist/{descriptor-meta-DnHabAS3-C53XXPQw.mjs → descriptor-meta-DnHabAS3-BiTguA3K.mjs} +2 -2
- package/dist/{descriptor-meta-DnHabAS3-C53XXPQw.mjs.map → descriptor-meta-DnHabAS3-BiTguA3K.mjs.map} +1 -1
- package/dist/{diff-database-schema-BfRs2vrG-D2o4KII0.mjs → diff-database-schema-BfRs2vrG-DInOv5LW.mjs} +2 -2
- package/dist/{diff-database-schema-BfRs2vrG-D2o4KII0.mjs.map → diff-database-schema-BfRs2vrG-DInOv5LW.mjs.map} +1 -1
- package/dist/{op-factory-call-DifL68KT-Bo6pxs-R.mjs → op-factory-call-DifL68KT-CNFEDNsf.mjs} +2 -2
- package/dist/{op-factory-call-DifL68KT-Bo6pxs-R.mjs.map → op-factory-call-DifL68KT-CNFEDNsf.mjs.map} +1 -1
- package/dist/{planner-Bmje9ii8-B99fEsNM.mjs → planner-Bmje9ii8-DdjXZxyD.mjs} +5 -5
- package/dist/{planner-Bmje9ii8-B99fEsNM.mjs.map → planner-Bmje9ii8-DdjXZxyD.mjs.map} +1 -1
- package/dist/{planner-ddl-builders-CbfICQfm-CxYiLrhX.mjs → planner-ddl-builders-CbfICQfm-CGjwaNy7.mjs} +2 -2
- package/dist/{planner-ddl-builders-CbfICQfm-CxYiLrhX.mjs.map → planner-ddl-builders-CbfICQfm-CGjwaNy7.mjs.map} +1 -1
- package/dist/{planner-produced-postgres-migration-Cicg2sXg-Ck9iDxGI.mjs → planner-produced-postgres-migration-Cicg2sXg-CZI7mdz9.mjs} +2 -2
- package/dist/{planner-produced-postgres-migration-Cicg2sXg-Ck9iDxGI.mjs.map → planner-produced-postgres-migration-Cicg2sXg-CZI7mdz9.mjs.map} +1 -1
- package/dist/{postgres-migration-CJshdIZn-DYYjgdD0.mjs → postgres-migration-CJshdIZn-CT6Cxd4x.mjs} +2 -2
- package/dist/{postgres-migration-CJshdIZn-DYYjgdD0.mjs.map → postgres-migration-CJshdIZn-CT6Cxd4x.mjs.map} +1 -1
- package/dist/sql-renderer-CZE98PJj-Bx5D-Txz.mjs +579 -0
- package/dist/sql-renderer-CZE98PJj-Bx5D-Txz.mjs.map +1 -0
- package/dist/sql-renderer-Cyls5Xy4.d.mts +19 -0
- package/dist/sql-renderer-Cyls5Xy4.d.mts.map +1 -0
- package/dist/target.d.mts +2 -1
- package/dist/target.mjs +13 -12
- package/dist/target__aggregates.d.mts +2 -0
- package/dist/target__aggregates.mjs +2 -0
- package/dist/target__codecs.mjs +2 -2
- package/dist/target__control.mjs +1 -1
- package/dist/target__diff-database-schema.mjs +1 -1
- package/dist/target__issue-planner.mjs +1 -1
- package/dist/target__migration.mjs +2 -2
- package/dist/target__op-factory-call.mjs +1 -1
- package/dist/target__pack.mjs +1 -1
- package/dist/target__planner-ddl-builders.mjs +1 -1
- package/dist/target__planner-produced-postgres-migration.mjs +1 -1
- package/dist/target__planner.mjs +2 -2
- package/package.json +11 -9
- package/dist/adapter-DhqcO3YO-jzwDVcCv.mjs.map +0 -1
- package/dist/control-adapter-B9t0g7Pf-HrCxlM65.mjs.map +0 -1
- package/dist/descriptor-meta-2IlVC6_d-DnV00Qd_.mjs.map +0 -1
package/dist/{control-adapter-B9t0g7Pf-HrCxlM65.mjs → control-adapter-CipVam9p-B-E2SF8_.mjs}
RENAMED
|
@@ -1,32 +1,27 @@
|
|
|
1
|
-
import { n as buildPostgresCodecDescriptorRegistry } from "./codec-descriptor-CB6x0xEu-C-Zn2IEz.mjs";
|
|
2
1
|
import { x as PG_TIMESTAMPTZ_CODEC_ID } from "./codec-ids-tX7Svtz--BuOfRaVU.mjs";
|
|
2
|
+
import { n as buildPostgresCodecDescriptorRegistry } from "./codec-descriptor-CB6x0xEu-C-Zn2IEz.mjs";
|
|
3
3
|
import { n as postgresError } from "./errors-kYxOQjdD-D4T3rbVp.mjs";
|
|
4
|
-
import { n as
|
|
5
|
-
import {
|
|
6
|
-
import { i as quoteQualifiedName, r as quoteIdentifier, t as escapeLiteral } from "./sql-utils-BnBlQxyh-DaX9Nb7Z.mjs";
|
|
4
|
+
import { n as postgresCodecRegistry, t as postgresCodecDescriptorRegistry } from "./codecs-rujsdlZR.mjs";
|
|
5
|
+
import { r as quoteIdentifier, t as escapeLiteral } from "./sql-utils-BnBlQxyh-DaX9Nb7Z.mjs";
|
|
7
6
|
import { a as jsonb, c as textArray, i as int8, l as timestamptz, n as buildSignMarkerBootstrapQueries, o as pgTable, r as int4, s as text, t as buildControlTableBootstrapQueries } from "./contract-free-BZUS18FU.mjs";
|
|
8
7
|
import { t as parsePostgresDefault } from "./default-normalizer-Ba5ZebHM-isV86rjy.mjs";
|
|
9
8
|
import { n as PostgresSchemaNodeKind, r as PostgresTableSchemaNode, t as PostgresNativeEnumSchemaNode } from "./postgres-table-schema-node-BBkitBQh-DT1T5VWU.mjs";
|
|
10
9
|
import { i as PostgresRoleSchemaNode, n as PostgresNamespaceSchemaNode, r as PostgresPolicySchemaNode, t as PostgresDatabaseSchemaNode } from "./postgres-role-schema-node-B8Z5i5D--PObwlU2Z.mjs";
|
|
11
10
|
import { t as normalizeSchemaNativeType } from "./native-type-normalizer-yvd3tqv-.mjs";
|
|
12
|
-
import {
|
|
11
|
+
import { n as renderLoweredSql, t as adapterError } from "./sql-renderer-CZE98PJj-Bx5D-Txz.mjs";
|
|
12
|
+
import { RawExpr, isDdlNode } from "@prisma/orm-family-sql/relational-core/ast";
|
|
13
13
|
import { blindCast } from "@prisma/orm-framework/utils/casts";
|
|
14
|
-
import { structuredError } from "@prisma/orm-framework/utils/structured-error";
|
|
15
14
|
import { UNBOUND_NAMESPACE_ID } from "@prisma/orm-framework/components/ir";
|
|
16
15
|
import { ifDefined } from "@prisma/orm-framework/utils/defined";
|
|
17
16
|
import { namingOfLiveName } from "@prisma/orm-family-sql/schema-ir/naming";
|
|
18
17
|
import { APP_SPACE_ID, extractCodecLookup } from "@prisma/orm-framework/components/control";
|
|
19
18
|
import { RelationalSchemaNodeKind } from "@prisma/orm-family-sql/schema-ir/types";
|
|
20
|
-
import { InternalError
|
|
19
|
+
import { InternalError } from "@prisma/orm-framework/utils/internal-error";
|
|
21
20
|
import { REFERENTIAL_ACTION_SQL } from "@prisma/orm-family-sql/contract/referential-action-sql";
|
|
22
21
|
import { parseMarkerRowSafely, rethrowMarkerReadError, withMarkerReadErrorHandling } from "@prisma/orm-framework/errors/execution";
|
|
23
22
|
import { parseContractMarkerRow } from "@prisma/orm-family-sql/family/verify";
|
|
24
23
|
import { createAstCodecRegistry, deriveParamMetadata, encodeParamsWithMetadata } from "@prisma/orm-family-sql/runtime";
|
|
25
|
-
|
|
26
|
-
//#region ../../../3-targets/6-adapters/postgres/dist/control-adapter-B9t0g7Pf.mjs
|
|
27
|
-
function adapterError(code, message, options) {
|
|
28
|
-
return structuredError(code, message, options);
|
|
29
|
-
}
|
|
24
|
+
//#region ../../../3-targets/6-adapters/postgres/dist/control-adapter-CipVam9p.mjs
|
|
30
25
|
function buildPostgresCodecRegistry(descriptors) {
|
|
31
26
|
const descriptorRegistry = buildPostgresCodecDescriptorRegistry(descriptors);
|
|
32
27
|
const registry = {
|
|
@@ -147,570 +142,6 @@ async function execute(lower, driver, query) {
|
|
|
147
142
|
const encoded = await encodeControlQueryParams(lowered, query);
|
|
148
143
|
return (await driver.query(lowered.sql, encoded)).rows;
|
|
149
144
|
}
|
|
150
|
-
/**
|
|
151
|
-
* Postgres native types whose unknown-OID parameter inference is reliable in arbitrary expression positions. Parameters bound to a descriptor whose `nativeTypeFor` result 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.
|
|
152
|
-
*
|
|
153
|
-
* `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).
|
|
154
|
-
*
|
|
155
|
-
* Spellings match the target descriptors' `nativeTypeFor` results, not the `udt_name` abbreviations that ADR 205 used as illustrative shorthand. The registry-based cast policy compares against these strings directly.
|
|
156
|
-
*/
|
|
157
|
-
const POSTGRES_INFERRABLE_NATIVE_TYPES = /* @__PURE__ */ new Set([
|
|
158
|
-
"integer",
|
|
159
|
-
"smallint",
|
|
160
|
-
"bigint",
|
|
161
|
-
"real",
|
|
162
|
-
"double precision",
|
|
163
|
-
"numeric",
|
|
164
|
-
"boolean",
|
|
165
|
-
"text",
|
|
166
|
-
"character",
|
|
167
|
-
"character varying",
|
|
168
|
-
"timestamp",
|
|
169
|
-
"timestamp without time zone",
|
|
170
|
-
"timestamp with time zone",
|
|
171
|
-
"time",
|
|
172
|
-
"timetz",
|
|
173
|
-
"interval",
|
|
174
|
-
"bit",
|
|
175
|
-
"bit varying"
|
|
176
|
-
]);
|
|
177
|
-
function renderTypedParam(index, codecId, codecDescriptorRegistry, many, typeParams) {
|
|
178
|
-
if (codecId === void 0) return `$${index}`;
|
|
179
|
-
const descriptor = codecDescriptorRegistry.descriptorFor(codecId);
|
|
180
|
-
if (descriptor === void 0) throw adapterError("RUNTIME.PARAM_REF_MISSING_CODEC", `Postgres lowering: ParamRef carries codecId "${codecId}" but the validated PostgreSQL codec registry 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 \`@internal/target-postgres/codecs\` if it's a builtin.`, { meta: { codecId } });
|
|
181
|
-
const ref = {
|
|
182
|
-
codecId,
|
|
183
|
-
...ifDefined("many", many),
|
|
184
|
-
...ifDefined("typeParams", typeParams)
|
|
185
|
-
};
|
|
186
|
-
const nativeType = descriptor.nativeTypeFor(ref);
|
|
187
|
-
const arraySuffix = many ? "[]" : "";
|
|
188
|
-
if (isPgEnumParams(typeParams)) return `$${index}::${quoteQualifiedName(nativeType)}${arraySuffix}`;
|
|
189
|
-
if (!POSTGRES_INFERRABLE_NATIVE_TYPES.has(nativeType) || many) return `$${index}::${nativeType}${arraySuffix}`;
|
|
190
|
-
return `$${index}`;
|
|
191
|
-
}
|
|
192
|
-
function unreachableKind(value) {
|
|
193
|
-
const candidate = value;
|
|
194
|
-
if (typeof candidate === "object" && candidate !== null && "kind" in candidate && typeof candidate.kind === "string") return candidate.kind;
|
|
195
|
-
return "unknown";
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Render a SQL query AST to a Postgres-flavored `{ sql, params }` payload.
|
|
199
|
-
*
|
|
200
|
-
* 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.
|
|
201
|
-
*/
|
|
202
|
-
function renderLoweredSql(ast, contract, codecDescriptorRegistry) {
|
|
203
|
-
const orderedRefs = collectOrderedParamRefs(ast);
|
|
204
|
-
const indexMap = /* @__PURE__ */ new Map();
|
|
205
|
-
const params = orderedRefs.map((ref, i) => {
|
|
206
|
-
indexMap.set(ref, i + 1);
|
|
207
|
-
return ref.kind === "prepared-param-ref" ? {
|
|
208
|
-
kind: "bind",
|
|
209
|
-
name: ref.name
|
|
210
|
-
} : {
|
|
211
|
-
kind: "literal",
|
|
212
|
-
value: ref.value
|
|
213
|
-
};
|
|
214
|
-
});
|
|
215
|
-
const pim = {
|
|
216
|
-
indexMap,
|
|
217
|
-
codecDescriptorRegistry
|
|
218
|
-
};
|
|
219
|
-
const node = ast;
|
|
220
|
-
let sql;
|
|
221
|
-
switch (node.kind) {
|
|
222
|
-
case "select":
|
|
223
|
-
sql = renderSelect(node, contract, pim);
|
|
224
|
-
break;
|
|
225
|
-
case "insert":
|
|
226
|
-
sql = renderInsert(node, contract, pim);
|
|
227
|
-
break;
|
|
228
|
-
case "update":
|
|
229
|
-
sql = renderUpdate(node, contract, pim);
|
|
230
|
-
break;
|
|
231
|
-
case "delete":
|
|
232
|
-
sql = renderDelete(node, contract, pim);
|
|
233
|
-
break;
|
|
234
|
-
case "raw-sql":
|
|
235
|
-
sql = renderRawSql(node, contract, pim);
|
|
236
|
-
break;
|
|
237
|
-
// v8 ignore next 4
|
|
238
|
-
default: assertNever(node, `Unsupported AST node kind: ${unreachableKind(node)}`);
|
|
239
|
-
}
|
|
240
|
-
return Object.freeze({
|
|
241
|
-
sql,
|
|
242
|
-
params: Object.freeze(params)
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
function renderLimitOffset(keyword, value, contract, pim) {
|
|
246
|
-
if (value === void 0) return "";
|
|
247
|
-
if (typeof value === "number") return `${keyword} ${value}`;
|
|
248
|
-
return `${keyword} ${renderExpr(value, contract, pim)}`;
|
|
249
|
-
}
|
|
250
|
-
function renderSelect(ast, contract, pim) {
|
|
251
|
-
const sourcesByRef = collectTableSources(ast);
|
|
252
|
-
return [
|
|
253
|
-
`SELECT ${renderDistinctPrefix(ast.distinct, ast.distinctOn, sourcesByRef, contract, pim)}${renderProjection(ast.projection, contract, pim)}`,
|
|
254
|
-
ast.from !== void 0 ? `FROM ${renderSource(ast.from, contract, pim)}` : "",
|
|
255
|
-
ast.joins?.length ? ast.joins.map((join) => renderJoin(join, contract, pim)).join(" ") : "",
|
|
256
|
-
ast.where ? `WHERE ${renderWhere(ast.where, contract, pim)}` : "",
|
|
257
|
-
ast.groupBy?.length ? `GROUP BY ${ast.groupBy.map((expr) => renderExpr(expr, contract, pim)).join(", ")}` : "",
|
|
258
|
-
ast.having ? `HAVING ${renderWhere(ast.having, contract, pim)}` : "",
|
|
259
|
-
ast.orderBy?.length ? `ORDER BY ${ast.orderBy.map((order) => {
|
|
260
|
-
return `${renderOrderByExpr(order.expr, sourcesByRef, contract, pim)} ${order.dir.toUpperCase()}`;
|
|
261
|
-
}).join(", ")}` : "",
|
|
262
|
-
renderLimitOffset("LIMIT", ast.limit, contract, pim),
|
|
263
|
-
renderLimitOffset("OFFSET", ast.offset, contract, pim)
|
|
264
|
-
].filter((part) => part.length > 0).join(" ").trim();
|
|
265
|
-
}
|
|
266
|
-
/**
|
|
267
|
-
* 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.
|
|
268
|
-
*/
|
|
269
|
-
function collectTableSources(ast) {
|
|
270
|
-
const sources = /* @__PURE__ */ new Map();
|
|
271
|
-
const add = (source) => {
|
|
272
|
-
if (source.kind !== "table-source") return;
|
|
273
|
-
const ref = source.alias ?? source.name;
|
|
274
|
-
sources.set(ref, {
|
|
275
|
-
name: source.name,
|
|
276
|
-
namespaceId: source.namespaceId
|
|
277
|
-
});
|
|
278
|
-
};
|
|
279
|
-
if (ast.from !== void 0) add(ast.from);
|
|
280
|
-
for (const join of ast.joins ?? []) add(join.source);
|
|
281
|
-
return sources;
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* 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`.
|
|
285
|
-
*/
|
|
286
|
-
function allStrings(values) {
|
|
287
|
-
return values.every((value) => typeof value === "string");
|
|
288
|
-
}
|
|
289
|
-
function resolveEnumOrderValues(ref, sourcesByRef, contract) {
|
|
290
|
-
const source = sourcesByRef.get(ref.table);
|
|
291
|
-
if (source === void 0 || source.namespaceId === void 0) return;
|
|
292
|
-
const sourceNs = contract.storage.namespaces[source.namespaceId];
|
|
293
|
-
const valueSet = (sourceNs !== void 0 ? sourceNs.entries.table?.[source.name]?.columns[ref.column] : void 0)?.valueSet;
|
|
294
|
-
if (valueSet === void 0) return;
|
|
295
|
-
const valueSetNs = contract.storage.namespaces[valueSet.namespaceId];
|
|
296
|
-
return valueSetNs !== void 0 ? valueSetNs.entries.valueSet?.[valueSet.entityName]?.values : void 0;
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* 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.
|
|
300
|
-
*/
|
|
301
|
-
function resolveEnumOrderValuesForIdentifier(name, sourcesByRef, contract) {
|
|
302
|
-
let matchedColumns = 0;
|
|
303
|
-
let resolved;
|
|
304
|
-
for (const source of sourcesByRef.values()) {
|
|
305
|
-
if (source.namespaceId === void 0) continue;
|
|
306
|
-
const identNs = contract.storage.namespaces[source.namespaceId];
|
|
307
|
-
const column = identNs !== void 0 ? identNs.entries.table?.[source.name]?.columns[name] : void 0;
|
|
308
|
-
if (column === void 0) continue;
|
|
309
|
-
matchedColumns += 1;
|
|
310
|
-
if (matchedColumns > 1) return;
|
|
311
|
-
const valueSet = column.valueSet;
|
|
312
|
-
if (valueSet === void 0) return;
|
|
313
|
-
const valueSetNs = contract.storage.namespaces[valueSet.namespaceId];
|
|
314
|
-
resolved = valueSetNs !== void 0 ? valueSetNs.entries.valueSet?.[valueSet.entityName]?.values : void 0;
|
|
315
|
-
}
|
|
316
|
-
return resolved;
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* 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.
|
|
320
|
-
*/
|
|
321
|
-
function renderOrderByExpr(expr, sourcesByRef, contract, pim) {
|
|
322
|
-
if (expr.kind === "column-ref") {
|
|
323
|
-
const orderValues = resolveEnumOrderValues(expr, sourcesByRef, contract);
|
|
324
|
-
if (orderValues !== void 0 && allStrings(orderValues)) return `array_position(ARRAY[${orderValues.map((value) => `'${escapeLiteral(value)}'`).join(", ")}]::text[], ${renderColumn(expr)})`;
|
|
325
|
-
}
|
|
326
|
-
if (expr.kind === "identifier-ref") {
|
|
327
|
-
const orderValues = resolveEnumOrderValuesForIdentifier(expr.name, sourcesByRef, contract);
|
|
328
|
-
if (orderValues !== void 0 && allStrings(orderValues)) return `array_position(ARRAY[${orderValues.map((value) => `'${escapeLiteral(value)}'`).join(", ")}]::text[], ${quoteIdentifier(expr.name)})`;
|
|
329
|
-
}
|
|
330
|
-
return renderExpr(expr, contract, pim);
|
|
331
|
-
}
|
|
332
|
-
function renderProjection(projection, contract, pim) {
|
|
333
|
-
return projection.map((item) => {
|
|
334
|
-
const alias = quoteIdentifier(item.alias);
|
|
335
|
-
if (item.expr.kind === "literal") return `${renderLiteral(item.expr)} AS ${alias}`;
|
|
336
|
-
return `${renderExpr(item.expr, contract, pim)} AS ${alias}`;
|
|
337
|
-
}).join(", ");
|
|
338
|
-
}
|
|
339
|
-
function renderReturning(items, contract, pim) {
|
|
340
|
-
return items.map((item) => {
|
|
341
|
-
if (item.expr.kind === "column-ref") {
|
|
342
|
-
const rendered = renderColumn(item.expr);
|
|
343
|
-
return item.expr.column === item.alias ? rendered : `${rendered} AS ${quoteIdentifier(item.alias)}`;
|
|
344
|
-
}
|
|
345
|
-
if (item.expr.kind === "literal") return `${renderLiteral(item.expr)} AS ${quoteIdentifier(item.alias)}`;
|
|
346
|
-
return `${renderExpr(item.expr, contract, pim)} AS ${quoteIdentifier(item.alias)}`;
|
|
347
|
-
}).join(", ");
|
|
348
|
-
}
|
|
349
|
-
function renderDistinctPrefix(distinct, distinctOn, sourcesByRef, contract, pim) {
|
|
350
|
-
if (distinctOn && distinctOn.length > 0) return `DISTINCT ON (${distinctOn.map((expr) => renderOrderByExpr(expr, sourcesByRef, contract, pim)).join(", ")}) `;
|
|
351
|
-
if (distinct) return "DISTINCT ";
|
|
352
|
-
return "";
|
|
353
|
-
}
|
|
354
|
-
function hasExplicitSchema(table) {
|
|
355
|
-
return "schema" in table && typeof table.schema === "string";
|
|
356
|
-
}
|
|
357
|
-
function qualifyTableFromNamespaceCoordinate(table, contract) {
|
|
358
|
-
if (hasExplicitSchema(table)) return `${quoteIdentifier(table.schema)}.${quoteIdentifier(table.name)}`;
|
|
359
|
-
if (table.namespaceId === void 0) return quoteIdentifier(table.name);
|
|
360
|
-
const namespace = contract.storage.namespaces[table.namespaceId];
|
|
361
|
-
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: {
|
|
362
|
-
table: table.name,
|
|
363
|
-
namespaceId: table.namespaceId,
|
|
364
|
-
reason: "not-present"
|
|
365
|
-
} });
|
|
366
|
-
const qualifyTable = namespace.qualifyTable;
|
|
367
|
-
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: {
|
|
368
|
-
table: table.name,
|
|
369
|
-
namespaceId: table.namespaceId,
|
|
370
|
-
reason: "not-materialised"
|
|
371
|
-
} });
|
|
372
|
-
return qualifyTable.call(namespace, table.name);
|
|
373
|
-
}
|
|
374
|
-
function renderTableSource(source, contract) {
|
|
375
|
-
const qualified = qualifyTableFromNamespaceCoordinate(source, contract);
|
|
376
|
-
if (!source.alias) return qualified;
|
|
377
|
-
return `${qualified} AS ${quoteIdentifier(source.alias)}`;
|
|
378
|
-
}
|
|
379
|
-
function renderSource(source, contract, pim) {
|
|
380
|
-
const node = source;
|
|
381
|
-
switch (node.kind) {
|
|
382
|
-
case "table-source": return renderTableSource(node, contract);
|
|
383
|
-
case "derived-table-source": return `(${renderSelect(node.query, contract, pim)}) AS ${quoteIdentifier(node.alias)}`;
|
|
384
|
-
case "function-source": {
|
|
385
|
-
const args = node.args.map((arg) => renderExpr(arg, contract, pim)).join(", ");
|
|
386
|
-
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(", ")})`}`;
|
|
387
|
-
}
|
|
388
|
-
// v8 ignore next 4
|
|
389
|
-
default: assertNever(node, `Unsupported source node kind: ${unreachableKind(node)}`);
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
function assertScalarSubquery(query) {
|
|
393
|
-
if (query.projection.length !== 1) throw adapterError("RUNTIME.AST_INVALID", "Subquery expressions must project exactly one column", { meta: { node: "subquery-expr" } });
|
|
394
|
-
}
|
|
395
|
-
function renderSubqueryExpr(expr, contract, pim) {
|
|
396
|
-
assertScalarSubquery(expr.query);
|
|
397
|
-
return `(${renderSelect(expr.query, contract, pim)})`;
|
|
398
|
-
}
|
|
399
|
-
function renderWhere(expr, contract, pim) {
|
|
400
|
-
return renderExpr(expr, contract, pim);
|
|
401
|
-
}
|
|
402
|
-
function renderNullCheck(expr, contract, pim) {
|
|
403
|
-
const rendered = renderExpr(expr.expr, contract, pim);
|
|
404
|
-
const renderedExpr = isAtomicExpressionKind(expr.expr.kind) ? rendered : `(${rendered})`;
|
|
405
|
-
return expr.isNull ? `${renderedExpr} IS NULL` : `${renderedExpr} IS NOT NULL`;
|
|
406
|
-
}
|
|
407
|
-
/**
|
|
408
|
-
* 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.
|
|
409
|
-
*
|
|
410
|
-
* 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.
|
|
411
|
-
*/
|
|
412
|
-
function isAtomicExpressionKind(kind) {
|
|
413
|
-
switch (kind) {
|
|
414
|
-
case "column-ref":
|
|
415
|
-
case "identifier-ref":
|
|
416
|
-
case "param-ref":
|
|
417
|
-
case "prepared-param-ref":
|
|
418
|
-
case "literal":
|
|
419
|
-
case "aggregate":
|
|
420
|
-
case "window-func":
|
|
421
|
-
case "function-call":
|
|
422
|
-
case "cast":
|
|
423
|
-
case "case":
|
|
424
|
-
case "json-object":
|
|
425
|
-
case "json-array-agg":
|
|
426
|
-
case "list": return true;
|
|
427
|
-
case "subquery":
|
|
428
|
-
case "operation":
|
|
429
|
-
case "binary":
|
|
430
|
-
case "and":
|
|
431
|
-
case "or":
|
|
432
|
-
case "exists":
|
|
433
|
-
case "null-check":
|
|
434
|
-
case "not":
|
|
435
|
-
case "raw-expr": return false;
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
function renderBinary(expr, contract, pim) {
|
|
439
|
-
if (expr.right.kind === "list" && expr.right.values.length === 0) {
|
|
440
|
-
if (expr.op === "in") return "FALSE";
|
|
441
|
-
if (expr.op === "notIn") return "TRUE";
|
|
442
|
-
}
|
|
443
|
-
const leftExpr = expr.left;
|
|
444
|
-
const left = renderExpr(leftExpr, contract, pim);
|
|
445
|
-
const leftRendered = leftExpr.kind === "operation" || leftExpr.kind === "subquery" ? `(${left})` : left;
|
|
446
|
-
const rightNode = expr.right;
|
|
447
|
-
let right;
|
|
448
|
-
switch (rightNode.kind) {
|
|
449
|
-
case "list":
|
|
450
|
-
right = renderListLiteral(rightNode, contract, pim);
|
|
451
|
-
break;
|
|
452
|
-
case "literal":
|
|
453
|
-
right = renderLiteral(rightNode);
|
|
454
|
-
break;
|
|
455
|
-
case "column-ref":
|
|
456
|
-
right = renderColumn(rightNode);
|
|
457
|
-
break;
|
|
458
|
-
case "param-ref":
|
|
459
|
-
case "prepared-param-ref":
|
|
460
|
-
right = renderParamRef(rightNode, pim);
|
|
461
|
-
break;
|
|
462
|
-
default:
|
|
463
|
-
right = renderExpr(rightNode, contract, pim);
|
|
464
|
-
break;
|
|
465
|
-
}
|
|
466
|
-
return `${leftRendered} ${{
|
|
467
|
-
eq: "=",
|
|
468
|
-
neq: "!=",
|
|
469
|
-
gt: ">",
|
|
470
|
-
lt: "<",
|
|
471
|
-
gte: ">=",
|
|
472
|
-
lte: "<=",
|
|
473
|
-
like: "LIKE",
|
|
474
|
-
in: "IN",
|
|
475
|
-
notIn: "NOT IN"
|
|
476
|
-
}[expr.op]} ${right}`;
|
|
477
|
-
}
|
|
478
|
-
function renderListLiteral(expr, contract, pim) {
|
|
479
|
-
if (expr.values.length === 0) return "(NULL)";
|
|
480
|
-
return `(${expr.values.map((v) => {
|
|
481
|
-
if (v.kind === "param-ref" || v.kind === "prepared-param-ref") return renderParamRef(v, pim);
|
|
482
|
-
if (v.kind === "literal") return renderLiteral(v);
|
|
483
|
-
return renderExpr(v, contract, pim);
|
|
484
|
-
}).join(", ")})`;
|
|
485
|
-
}
|
|
486
|
-
function renderColumn(ref) {
|
|
487
|
-
if (ref.table === "excluded") return `excluded.${quoteIdentifier(ref.column)}`;
|
|
488
|
-
return `${quoteIdentifier(ref.table)}.${quoteIdentifier(ref.column)}`;
|
|
489
|
-
}
|
|
490
|
-
function renderAggregateExpr(expr, contract, pim) {
|
|
491
|
-
const fn = expr.fn.toUpperCase();
|
|
492
|
-
if (!expr.expr) return `${fn}(*)`;
|
|
493
|
-
return `${fn}(${renderExpr(expr.expr, contract, pim)})`;
|
|
494
|
-
}
|
|
495
|
-
function renderWindowFuncExpr(expr, contract, pim) {
|
|
496
|
-
return `${expr.fn.toUpperCase()}(${expr.args.map((arg) => renderExpr(arg, contract, pim)).join(", ")}) OVER (${[expr.partitionBy && expr.partitionBy.length > 0 ? `PARTITION BY ${expr.partitionBy.map((e) => renderExpr(e, contract, pim)).join(", ")}` : "", expr.orderBy && expr.orderBy.length > 0 ? `ORDER BY ${renderOrderByItems(expr.orderBy, contract, pim)}` : ""].filter((part) => part.length > 0).join(" ")})`;
|
|
497
|
-
}
|
|
498
|
-
function renderFunctionCallExpr(expr, contract, pim) {
|
|
499
|
-
const args = expr.args.map((arg) => renderExpr(arg, contract, pim)).join(", ");
|
|
500
|
-
return `${expr.fn}(${args})`;
|
|
501
|
-
}
|
|
502
|
-
function renderCastExpr(expr, contract, pim) {
|
|
503
|
-
return `CAST(${renderExpr(expr.expr, contract, pim)} AS ${expr.targetType})`;
|
|
504
|
-
}
|
|
505
|
-
function renderCaseExpr(expr, contract, pim) {
|
|
506
|
-
return `CASE ${expr.branches.map((branch) => `WHEN ${renderExpr(branch.condition, contract, pim)} THEN ${renderExpr(branch.value, contract, pim)}`).join(" ")}${expr.elseExpr === void 0 ? "" : ` ELSE ${renderExpr(expr.elseExpr, contract, pim)}`} END`;
|
|
507
|
-
}
|
|
508
|
-
function renderJsonValueProjection(projection, contract, pim) {
|
|
509
|
-
return projection.accept({
|
|
510
|
-
codec: ({ value, codec }) => renderExpr(projectJsonThroughCodec(value, codec, pim), contract, pim),
|
|
511
|
-
native: ({ value }) => renderExpr(value, contract, pim),
|
|
512
|
-
document: ({ value }) => renderExpr(value, contract, pim)
|
|
513
|
-
});
|
|
514
|
-
}
|
|
515
|
-
function projectJsonThroughCodec(value, codec, pim) {
|
|
516
|
-
const descriptor = pim.codecDescriptorRegistry.descriptorFor(codec.codecId);
|
|
517
|
-
if (descriptor === void 0) throw adapterError("RUNTIME.PARAM_REF_MISSING_CODEC", `Postgres lowering: a JSON projection carries codecId "${codec.codecId}" but the validated PostgreSQL codec registry 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 \`@internal/target-postgres/codecs\` if it's a builtin.`, { meta: { codecId: codec.codecId } });
|
|
518
|
-
return descriptor.projectJson(value, codec);
|
|
519
|
-
}
|
|
520
|
-
function renderJsonObjectExpr(expr, contract, pim) {
|
|
521
|
-
return `json_build_object(${expr.entries.flatMap((entry) => {
|
|
522
|
-
return [`'${escapeLiteral(entry.key)}'`, renderJsonValueProjection(entry.value, contract, pim)];
|
|
523
|
-
}).join(", ")})`;
|
|
524
|
-
}
|
|
525
|
-
function renderOrderByItems(items, contract, pim) {
|
|
526
|
-
return items.map((item) => `${renderExpr(item.expr, contract, pim)} ${item.dir.toUpperCase()}`).join(", ");
|
|
527
|
-
}
|
|
528
|
-
function renderJsonArrayAggExpr(expr, contract, pim) {
|
|
529
|
-
const aggregateOrderBy = expr.orderBy && expr.orderBy.length > 0 ? ` ORDER BY ${renderOrderByItems(expr.orderBy, contract, pim)}` : "";
|
|
530
|
-
const aggregated = `json_agg(${renderJsonValueProjection(expr.expr, contract, pim)}${aggregateOrderBy})`;
|
|
531
|
-
if (expr.onEmpty === "emptyArray") return `coalesce(${aggregated}, json_build_array())`;
|
|
532
|
-
return aggregated;
|
|
533
|
-
}
|
|
534
|
-
function renderExpr(expr, contract, pim) {
|
|
535
|
-
const node = expr;
|
|
536
|
-
switch (node.kind) {
|
|
537
|
-
case "column-ref": return renderColumn(node);
|
|
538
|
-
case "identifier-ref": return quoteIdentifier(node.name);
|
|
539
|
-
case "operation": return renderOperation(node, contract, pim);
|
|
540
|
-
case "subquery": return renderSubqueryExpr(node, contract, pim);
|
|
541
|
-
case "aggregate": return renderAggregateExpr(node, contract, pim);
|
|
542
|
-
case "window-func": return renderWindowFuncExpr(node, contract, pim);
|
|
543
|
-
case "function-call": return renderFunctionCallExpr(node, contract, pim);
|
|
544
|
-
case "cast": return renderCastExpr(node, contract, pim);
|
|
545
|
-
case "case": return renderCaseExpr(node, contract, pim);
|
|
546
|
-
case "json-object": return renderJsonObjectExpr(node, contract, pim);
|
|
547
|
-
case "json-array-agg": return renderJsonArrayAggExpr(node, contract, pim);
|
|
548
|
-
case "binary": return renderBinary(node, contract, pim);
|
|
549
|
-
case "and":
|
|
550
|
-
if (node.exprs.length === 0) return "TRUE";
|
|
551
|
-
return `(${node.exprs.map((part) => renderExpr(part, contract, pim)).join(" AND ")})`;
|
|
552
|
-
case "or":
|
|
553
|
-
if (node.exprs.length === 0) return "FALSE";
|
|
554
|
-
return `(${node.exprs.map((part) => renderExpr(part, contract, pim)).join(" OR ")})`;
|
|
555
|
-
case "exists": return `${node.notExists ? "NOT " : ""}EXISTS (${renderSelect(node.subquery, contract, pim)})`;
|
|
556
|
-
case "null-check": return renderNullCheck(node, contract, pim);
|
|
557
|
-
case "not": return `NOT (${renderExpr(node.expr, contract, pim)})`;
|
|
558
|
-
case "param-ref":
|
|
559
|
-
case "prepared-param-ref": return renderParamRef(node, pim);
|
|
560
|
-
case "literal": return renderLiteral(node);
|
|
561
|
-
case "list": return renderListLiteral(node, contract, pim);
|
|
562
|
-
case "raw-expr": return renderRawExpr(node, contract, pim);
|
|
563
|
-
// v8 ignore next 4
|
|
564
|
-
default: assertNever(node, `Unsupported expression node kind: ${unreachableKind(node)}`);
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
function renderParamRef(ref, pim) {
|
|
568
|
-
const index = pim.indexMap.get(ref);
|
|
569
|
-
if (index === void 0) throw new InternalError("ParamRef not found in index map");
|
|
570
|
-
if (ref.kind === "prepared-param-ref") return renderTypedParam(index, ref.codec.codecId, pim.codecDescriptorRegistry, ref.codec.many, ref.codec.typeParams);
|
|
571
|
-
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.", {
|
|
572
|
-
paramIndex: index,
|
|
573
|
-
...ifDefined("name", ref.name)
|
|
574
|
-
});
|
|
575
|
-
return renderTypedParam(index, ref.codec.codecId, pim.codecDescriptorRegistry, ref.codec.many, ref.codec.typeParams);
|
|
576
|
-
}
|
|
577
|
-
function renderLiteral(expr) {
|
|
578
|
-
if (typeof expr.value === "string") return `'${escapeLiteral(expr.value)}'`;
|
|
579
|
-
if (typeof expr.value === "number" || typeof expr.value === "boolean") return String(expr.value);
|
|
580
|
-
if (typeof expr.value === "bigint") return String(expr.value);
|
|
581
|
-
if (expr.value === null) return "NULL";
|
|
582
|
-
if (expr.value === void 0) return "NULL";
|
|
583
|
-
if (expr.value instanceof Date) return `'${escapeLiteral(expr.value.toISOString())}'`;
|
|
584
|
-
if (Array.isArray(expr.value)) return `ARRAY[${expr.value.map((v) => renderLiteral(new LiteralExpr(v))).join(", ")}]`;
|
|
585
|
-
const json = JSON.stringify(expr.value);
|
|
586
|
-
if (json === void 0) return "NULL";
|
|
587
|
-
return `'${escapeLiteral(json)}'`;
|
|
588
|
-
}
|
|
589
|
-
function renderOperation(expr, contract, pim) {
|
|
590
|
-
const self = renderExpr(expr.self, contract, pim);
|
|
591
|
-
const args = expr.args.map((arg) => {
|
|
592
|
-
return renderExpr(arg, contract, pim);
|
|
593
|
-
});
|
|
594
|
-
return expr.lowering.template.replace(/\{\{self\}\}|\{\{arg(\d+)\}\}/g, (token, argIndex) => {
|
|
595
|
-
if (token === "{{self}}") return self;
|
|
596
|
-
const arg = args[Number(argIndex)];
|
|
597
|
-
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 } });
|
|
598
|
-
return arg;
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
function renderJoin(join, contract, pim) {
|
|
602
|
-
return `${join.joinType.toUpperCase()} JOIN ${join.lateral ? "LATERAL " : ""}${renderSource(join.source, contract, pim)} ON ${renderJoinOn(join.on, contract, pim)}`;
|
|
603
|
-
}
|
|
604
|
-
function renderJoinOn(on, contract, pim) {
|
|
605
|
-
if (on.kind === "eq-col-join-on") return `${renderColumn(on.left)} = ${renderColumn(on.right)}`;
|
|
606
|
-
return renderWhere(on, contract, pim);
|
|
607
|
-
}
|
|
608
|
-
function getInsertColumnOrder(rows, contract, tableRef) {
|
|
609
|
-
const tableName = tableRef.name;
|
|
610
|
-
const orderedColumns = [];
|
|
611
|
-
const seenColumns = /* @__PURE__ */ new Set();
|
|
612
|
-
for (const row of rows) for (const column of Object.keys(row)) {
|
|
613
|
-
if (seenColumns.has(column)) continue;
|
|
614
|
-
seenColumns.add(column);
|
|
615
|
-
orderedColumns.push(column);
|
|
616
|
-
}
|
|
617
|
-
if (orderedColumns.length > 0) return orderedColumns;
|
|
618
|
-
let table;
|
|
619
|
-
if (tableRef.namespaceId !== void 0) {
|
|
620
|
-
const ns = contract.storage.namespaces[tableRef.namespaceId];
|
|
621
|
-
table = ns !== void 0 ? ns.entries.table?.[tableName] : void 0;
|
|
622
|
-
}
|
|
623
|
-
if (table === void 0) for (const ns of Object.values(contract.storage.namespaces)) {
|
|
624
|
-
const found = ns.entries.table?.[tableName];
|
|
625
|
-
if (found !== void 0) {
|
|
626
|
-
table = found;
|
|
627
|
-
break;
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
if (!table) throw adapterError("RUNTIME.AST_INVALID", `INSERT target table not found in contract storage: ${tableName}`, { meta: {
|
|
631
|
-
node: "insert",
|
|
632
|
-
table: tableName
|
|
633
|
-
} });
|
|
634
|
-
return Object.keys(table.columns);
|
|
635
|
-
}
|
|
636
|
-
function renderInsertValue(value, contract, pim) {
|
|
637
|
-
if (!value || value.kind === "default-value") return "DEFAULT";
|
|
638
|
-
switch (value.kind) {
|
|
639
|
-
case "param-ref":
|
|
640
|
-
case "prepared-param-ref": return renderParamRef(value, pim);
|
|
641
|
-
case "column-ref": return renderColumn(value);
|
|
642
|
-
case "raw-expr": return renderExpr(value, contract, pim);
|
|
643
|
-
// v8 ignore next 4
|
|
644
|
-
default: assertNever(value, `Unsupported value node in INSERT: ${unreachableKind(value)}`);
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
function renderInsert(ast, contract, pim) {
|
|
648
|
-
const table = qualifyTableFromNamespaceCoordinate(ast.table, contract);
|
|
649
|
-
const rows = ast.rows;
|
|
650
|
-
if (rows.length === 0) throw adapterError("RUNTIME.AST_INVALID", "INSERT requires at least one row", { meta: { node: "insert" } });
|
|
651
|
-
const hasExplicitValues = rows.some((row) => Object.keys(row).length > 0);
|
|
652
|
-
return `${(() => {
|
|
653
|
-
if (!hasExplicitValues) {
|
|
654
|
-
if (rows.length === 1) return `INSERT INTO ${table} DEFAULT VALUES`;
|
|
655
|
-
const defaultColumns = getInsertColumnOrder(rows, contract, ast.table);
|
|
656
|
-
if (defaultColumns.length === 0) return `INSERT INTO ${table} VALUES ${rows.map(() => "()").join(", ")}`;
|
|
657
|
-
const quotedColumns = defaultColumns.map((column) => quoteIdentifier(column));
|
|
658
|
-
const defaultRow = `(${defaultColumns.map(() => "DEFAULT").join(", ")})`;
|
|
659
|
-
return `INSERT INTO ${table} (${quotedColumns.join(", ")}) VALUES ${rows.map(() => defaultRow).join(", ")}`;
|
|
660
|
-
}
|
|
661
|
-
const columnOrder = getInsertColumnOrder(rows, contract, ast.table);
|
|
662
|
-
const columns = columnOrder.map((column) => quoteIdentifier(column));
|
|
663
|
-
const values = rows.map((row) => {
|
|
664
|
-
return `(${columnOrder.map((column) => renderInsertValue(row[column], contract, pim)).join(", ")})`;
|
|
665
|
-
}).join(", ");
|
|
666
|
-
return `INSERT INTO ${table} (${columns.join(", ")}) VALUES ${values}`;
|
|
667
|
-
})()}${ast.onConflict ? (() => {
|
|
668
|
-
const conflictColumns = ast.onConflict.columns.map((col) => quoteIdentifier(col.column));
|
|
669
|
-
if (conflictColumns.length === 0) throw adapterError("RUNTIME.AST_INVALID", "INSERT onConflict requires at least one conflict column", { meta: { node: "insert-on-conflict" } });
|
|
670
|
-
const action = ast.onConflict.action;
|
|
671
|
-
switch (action.kind) {
|
|
672
|
-
case "do-nothing": return ` ON CONFLICT (${conflictColumns.join(", ")}) DO NOTHING`;
|
|
673
|
-
case "do-update-set": {
|
|
674
|
-
const updateEntries = Object.entries(action.set);
|
|
675
|
-
if (updateEntries.length === 0) throw adapterError("RUNTIME.AST_INVALID", "INSERT onConflict do-update-set requires at least one assignment", { meta: { node: "insert-on-conflict" } });
|
|
676
|
-
const updates = updateEntries.map(([colName, value]) => {
|
|
677
|
-
return `${quoteIdentifier(colName)} = ${renderExpr(value, contract, pim)}`;
|
|
678
|
-
});
|
|
679
|
-
return ` ON CONFLICT (${conflictColumns.join(", ")}) DO UPDATE SET ${updates.join(", ")}`;
|
|
680
|
-
}
|
|
681
|
-
// v8 ignore next 4
|
|
682
|
-
default: assertNever(action, `Unsupported onConflict action: ${unreachableKind(action)}`);
|
|
683
|
-
}
|
|
684
|
-
})() : ""}${ast.returning?.length ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}` : ""}`;
|
|
685
|
-
}
|
|
686
|
-
function renderUpdate(ast, contract, pim) {
|
|
687
|
-
const table = qualifyTableFromNamespaceCoordinate(ast.table, contract);
|
|
688
|
-
const setEntries = Object.entries(ast.set);
|
|
689
|
-
if (setEntries.length === 0) throw adapterError("RUNTIME.AST_INVALID", "UPDATE requires at least one SET assignment", { meta: { node: "update" } });
|
|
690
|
-
const setClauses = setEntries.map(([col, val]) => {
|
|
691
|
-
return `${quoteIdentifier(col)} = ${renderExpr(val, contract, pim)}`;
|
|
692
|
-
});
|
|
693
|
-
const whereClause = ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : "";
|
|
694
|
-
const returningClause = ast.returning?.length ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}` : "";
|
|
695
|
-
return `UPDATE ${table} SET ${setClauses.join(", ")}${whereClause}${returningClause}`;
|
|
696
|
-
}
|
|
697
|
-
function renderDelete(ast, contract, pim) {
|
|
698
|
-
return `DELETE FROM ${qualifyTableFromNamespaceCoordinate(ast.table, contract)}${ast.where ? ` WHERE ${renderWhere(ast.where, contract, pim)}` : ""}${ast.returning?.length ? ` RETURNING ${renderReturning(ast.returning, contract, pim)}` : ""}`;
|
|
699
|
-
}
|
|
700
|
-
function renderRawSql(ast, contract, pim) {
|
|
701
|
-
const out = [];
|
|
702
|
-
for (let i = 0; i < ast.fragments.length; i++) {
|
|
703
|
-
out.push(ast.fragments[i] ?? "");
|
|
704
|
-
if (i < ast.args.length) {
|
|
705
|
-
const arg = ast.args[i];
|
|
706
|
-
if (arg !== void 0) out.push(renderExpr(arg, contract, pim));
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
return out.join("");
|
|
710
|
-
}
|
|
711
|
-
function renderRawExpr(node, contract, pim) {
|
|
712
|
-
return node.parts.map((part) => typeof part === "string" ? part : renderExpr(part, contract, pim)).join("");
|
|
713
|
-
}
|
|
714
145
|
const POSTGRES_MARKER_TABLE = "prisma_contract.marker";
|
|
715
146
|
const POSTGRES_LEDGER_TABLE = "prisma_contract.ledger";
|
|
716
147
|
/**
|
|
@@ -1896,6 +1327,6 @@ async function pgRenderDdlExecuteRequest(ast, codecLookup) {
|
|
|
1896
1327
|
});
|
|
1897
1328
|
}
|
|
1898
1329
|
//#endregion
|
|
1899
|
-
export { createPostgresCodecRegistryWithBuiltins as
|
|
1330
|
+
export { createPostgresCodecRegistryWithBuiltins as i, assemblePostgresCodecRegistry as n, createPostgresBuiltinCodecLookup as r, PostgresControlAdapter as t };
|
|
1900
1331
|
|
|
1901
|
-
//# sourceMappingURL=control-adapter-
|
|
1332
|
+
//# sourceMappingURL=control-adapter-CipVam9p-B-E2SF8_.mjs.map
|