@prisma-next/adapter-postgres 0.16.0-dev.2 → 0.16.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.
- package/dist/{adapter-BaZsfXGA.mjs → adapter-DcBWxseT.mjs} +2 -2
- package/dist/{adapter-BaZsfXGA.mjs.map → adapter-DcBWxseT.mjs.map} +1 -1
- package/dist/adapter.mjs +1 -1
- package/dist/{control-adapter-B6IM_oTR.mjs → control-adapter-hSsjUXtc.mjs} +48 -18
- package/dist/control-adapter-hSsjUXtc.mjs.map +1 -0
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +266 -31
- package/dist/control.mjs.map +1 -1
- package/dist/runtime.mjs +2 -2
- package/dist/runtime.mjs.map +1 -1
- package/package.json +23 -23
- package/src/core/control-adapter.ts +8 -2
- package/src/core/control-mutation-defaults.ts +140 -34
- package/src/core/sql-renderer.ts +95 -23
- package/src/exports/control.ts +2 -2
- package/src/exports/runtime.ts +1 -1
- package/dist/control-adapter-B6IM_oTR.mjs.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ExecutionMutationDefaultValue } from '@prisma-next/contract/types';
|
|
2
2
|
import { timestampNowControlDescriptor } from '@prisma-next/family-sql/control';
|
|
3
|
+
import type { AuthoringTypeNamespace } from '@prisma-next/framework-components/authoring';
|
|
3
4
|
import type {
|
|
4
5
|
ControlMutationDefaultEntry,
|
|
5
6
|
DefaultFunctionLoweringContext,
|
|
@@ -7,10 +8,7 @@ import type {
|
|
|
7
8
|
MutationDefaultGeneratorDescriptor,
|
|
8
9
|
TypedDefaultFunctionCall,
|
|
9
10
|
} from '@prisma-next/framework-components/control';
|
|
10
|
-
import {
|
|
11
|
-
builtinGeneratorRegistryMetadata,
|
|
12
|
-
resolveBuiltinGeneratedColumnDescriptor,
|
|
13
|
-
} from '@prisma-next/ids';
|
|
11
|
+
import { builtinGeneratorRegistryMetadata } from '@prisma-next/ids';
|
|
14
12
|
import type { FuncCallSig } from '@prisma-next/psl-parser';
|
|
15
13
|
import { int, num, oneOf, optional, str } from '@prisma-next/psl-parser';
|
|
16
14
|
|
|
@@ -153,17 +151,144 @@ const postgresDefaultFunctionRegistryEntries = [
|
|
|
153
151
|
],
|
|
154
152
|
] satisfies ReadonlyArray<readonly [string, ControlMutationDefaultEntry]>;
|
|
155
153
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
154
|
+
/**
|
|
155
|
+
* The base PSL scalars as zero-arg type constructors in the unified authoring
|
|
156
|
+
* channel, with explicit `nativeType` values pinned to the codec manifests
|
|
157
|
+
* (`codecLookup.targetTypesFor(codecId)[0]`).
|
|
158
|
+
*
|
|
159
|
+
* The type position is the only storage decider: a mutation-default generator
|
|
160
|
+
* (`@default(uuid())`) never re-picks a column's storage.
|
|
161
|
+
*/
|
|
162
|
+
export const postgresScalarAuthoringTypes = {
|
|
163
|
+
String: {
|
|
164
|
+
kind: 'typeConstructor',
|
|
165
|
+
output: { codecId: 'pg/text@1', nativeType: 'text' },
|
|
166
|
+
},
|
|
167
|
+
Boolean: {
|
|
168
|
+
kind: 'typeConstructor',
|
|
169
|
+
output: { codecId: 'pg/bool@1', nativeType: 'bool' },
|
|
170
|
+
},
|
|
171
|
+
Int: {
|
|
172
|
+
kind: 'typeConstructor',
|
|
173
|
+
output: { codecId: 'pg/int4@1', nativeType: 'int4' },
|
|
174
|
+
},
|
|
175
|
+
BigInt: {
|
|
176
|
+
kind: 'typeConstructor',
|
|
177
|
+
output: { codecId: 'pg/int8@1', nativeType: 'int8' },
|
|
178
|
+
},
|
|
179
|
+
Float: {
|
|
180
|
+
kind: 'typeConstructor',
|
|
181
|
+
output: { codecId: 'pg/float8@1', nativeType: 'float8' },
|
|
182
|
+
},
|
|
183
|
+
Decimal: {
|
|
184
|
+
kind: 'typeConstructor',
|
|
185
|
+
output: { codecId: 'pg/numeric@1', nativeType: 'numeric' },
|
|
186
|
+
},
|
|
187
|
+
DateTime: {
|
|
188
|
+
kind: 'typeConstructor',
|
|
189
|
+
output: { codecId: 'pg/timestamptz@1', nativeType: 'timestamptz' },
|
|
190
|
+
},
|
|
191
|
+
Json: {
|
|
192
|
+
kind: 'typeConstructor',
|
|
193
|
+
output: { codecId: 'pg/json@1', nativeType: 'json' },
|
|
194
|
+
},
|
|
195
|
+
Jsonb: {
|
|
196
|
+
kind: 'typeConstructor',
|
|
197
|
+
output: { codecId: 'pg/jsonb@1', nativeType: 'jsonb' },
|
|
198
|
+
},
|
|
199
|
+
Bytes: {
|
|
200
|
+
kind: 'typeConstructor',
|
|
201
|
+
output: { codecId: 'pg/bytea@1', nativeType: 'bytea' },
|
|
202
|
+
},
|
|
203
|
+
} as const satisfies AuthoringTypeNamespace;
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* The former `@db.*` native types as first-class top-level type constructors
|
|
207
|
+
* (TML-2986). Codec ids, native types, and typeParams key shapes mirror the
|
|
208
|
+
* legacy `@db.*` attribute path (`NATIVE_TYPE_SPECS` in sql-contract-psl)
|
|
209
|
+
* exactly; every argument is optional, so each name is also authorable bare
|
|
210
|
+
* (`VarChar` ≡ `VarChar()`), and omitted arguments omit their typeParams keys.
|
|
211
|
+
*/
|
|
212
|
+
export const postgresNativeAuthoringTypes = {
|
|
213
|
+
VarChar: {
|
|
214
|
+
kind: 'typeConstructor',
|
|
215
|
+
args: [{ kind: 'number', name: 'length', integer: true, minimum: 1, optional: true }],
|
|
216
|
+
output: {
|
|
217
|
+
codecId: 'sql/varchar@1',
|
|
218
|
+
nativeType: 'character varying',
|
|
219
|
+
typeParams: { length: { kind: 'arg', index: 0 } },
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
Char: {
|
|
223
|
+
kind: 'typeConstructor',
|
|
224
|
+
args: [{ kind: 'number', name: 'length', integer: true, minimum: 1, optional: true }],
|
|
225
|
+
output: {
|
|
226
|
+
codecId: 'sql/char@1',
|
|
227
|
+
nativeType: 'character',
|
|
228
|
+
typeParams: { length: { kind: 'arg', index: 0 } },
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
Numeric: {
|
|
232
|
+
kind: 'typeConstructor',
|
|
233
|
+
args: [
|
|
234
|
+
{ kind: 'number', name: 'precision', integer: true, minimum: 1, optional: true },
|
|
235
|
+
{ kind: 'number', name: 'scale', integer: true, minimum: 0, optional: true },
|
|
236
|
+
],
|
|
237
|
+
output: {
|
|
238
|
+
codecId: 'pg/numeric@1',
|
|
239
|
+
nativeType: 'numeric',
|
|
240
|
+
typeParams: {
|
|
241
|
+
precision: { kind: 'arg', index: 0 },
|
|
242
|
+
scale: { kind: 'arg', index: 1 },
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
Timestamp: {
|
|
247
|
+
kind: 'typeConstructor',
|
|
248
|
+
args: [{ kind: 'number', name: 'precision', integer: true, minimum: 0, optional: true }],
|
|
249
|
+
output: {
|
|
250
|
+
codecId: 'pg/timestamp@1',
|
|
251
|
+
nativeType: 'timestamp',
|
|
252
|
+
typeParams: { precision: { kind: 'arg', index: 0 } },
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
Timestamptz: {
|
|
256
|
+
kind: 'typeConstructor',
|
|
257
|
+
args: [{ kind: 'number', name: 'precision', integer: true, minimum: 0, optional: true }],
|
|
258
|
+
output: {
|
|
259
|
+
codecId: 'pg/timestamptz@1',
|
|
260
|
+
nativeType: 'timestamptz',
|
|
261
|
+
typeParams: { precision: { kind: 'arg', index: 0 } },
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
Time: {
|
|
265
|
+
kind: 'typeConstructor',
|
|
266
|
+
args: [{ kind: 'number', name: 'precision', integer: true, minimum: 0, optional: true }],
|
|
267
|
+
output: {
|
|
268
|
+
codecId: 'pg/time@1',
|
|
269
|
+
nativeType: 'time',
|
|
270
|
+
typeParams: { precision: { kind: 'arg', index: 0 } },
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
Timetz: {
|
|
274
|
+
kind: 'typeConstructor',
|
|
275
|
+
args: [{ kind: 'number', name: 'precision', integer: true, minimum: 0, optional: true }],
|
|
276
|
+
output: {
|
|
277
|
+
codecId: 'pg/timetz@1',
|
|
278
|
+
nativeType: 'timetz',
|
|
279
|
+
typeParams: { precision: { kind: 'arg', index: 0 } },
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
Uuid: { kind: 'typeConstructor', output: { codecId: 'pg/uuid@1', nativeType: 'uuid' } },
|
|
283
|
+
SmallInt: { kind: 'typeConstructor', output: { codecId: 'pg/int2@1', nativeType: 'int2' } },
|
|
284
|
+
Real: { kind: 'typeConstructor', output: { codecId: 'pg/float4@1', nativeType: 'float4' } },
|
|
285
|
+
Date: { kind: 'typeConstructor', output: { codecId: 'pg/date@1', nativeType: 'date' } },
|
|
286
|
+
} as const satisfies AuthoringTypeNamespace;
|
|
287
|
+
|
|
288
|
+
export const postgresAuthoringTypes = {
|
|
289
|
+
...postgresScalarAuthoringTypes,
|
|
290
|
+
...postgresNativeAuthoringTypes,
|
|
291
|
+
} as const satisfies AuthoringTypeNamespace;
|
|
167
292
|
|
|
168
293
|
export function createPostgresDefaultFunctionRegistry(): ReadonlyMap<
|
|
169
294
|
string,
|
|
@@ -178,27 +303,8 @@ export function createPostgresMutationDefaultGeneratorDescriptors(): readonly Mu
|
|
|
178
303
|
({ id, applicableCodecIds }): MutationDefaultGeneratorDescriptor => ({
|
|
179
304
|
id,
|
|
180
305
|
applicableCodecIds,
|
|
181
|
-
resolveGeneratedColumnDescriptor: ({ generated }) => {
|
|
182
|
-
if (generated.kind !== 'generator' || generated.id !== id) {
|
|
183
|
-
return undefined;
|
|
184
|
-
}
|
|
185
|
-
const descriptor = resolveBuiltinGeneratedColumnDescriptor({
|
|
186
|
-
id,
|
|
187
|
-
...(generated.params ? { params: generated.params } : {}),
|
|
188
|
-
});
|
|
189
|
-
return {
|
|
190
|
-
codecId: descriptor.type.codecId,
|
|
191
|
-
nativeType: descriptor.type.nativeType,
|
|
192
|
-
...(descriptor.type.typeRef ? { typeRef: descriptor.type.typeRef } : {}),
|
|
193
|
-
...(descriptor.typeParams ? { typeParams: descriptor.typeParams } : {}),
|
|
194
|
-
};
|
|
195
|
-
},
|
|
196
306
|
}),
|
|
197
307
|
),
|
|
198
308
|
timestampNowControlDescriptor(),
|
|
199
309
|
];
|
|
200
310
|
}
|
|
201
|
-
|
|
202
|
-
export function createPostgresScalarTypeDescriptors(): ReadonlyMap<string, string> {
|
|
203
|
-
return new Map(postgresScalarTypeDescriptors);
|
|
204
|
-
}
|
package/src/core/sql-renderer.ts
CHANGED
|
@@ -5,18 +5,23 @@ import {
|
|
|
5
5
|
type AggregateExpr,
|
|
6
6
|
type AnyExpression,
|
|
7
7
|
type AnyFromSource,
|
|
8
|
+
type AnyJsonValueProjection,
|
|
8
9
|
type AnyParamRef,
|
|
9
10
|
type AnyQueryAst,
|
|
10
11
|
type BinaryExpr,
|
|
12
|
+
type CaseExpr,
|
|
13
|
+
type CastExpr,
|
|
11
14
|
type ColumnRef,
|
|
12
15
|
collectOrderedParamRefs,
|
|
13
16
|
type DeleteAst,
|
|
17
|
+
type FunctionCallExpr,
|
|
14
18
|
type InsertAst,
|
|
15
19
|
type InsertValue,
|
|
16
20
|
type JoinAst,
|
|
17
21
|
type JoinOnExpr,
|
|
18
22
|
type JsonArrayAggExpr,
|
|
19
23
|
type JsonObjectExpr,
|
|
24
|
+
type JsonValueProjectionVisitor,
|
|
20
25
|
type ListExpression,
|
|
21
26
|
LiteralExpr,
|
|
22
27
|
type LoweredParam,
|
|
@@ -32,7 +37,12 @@ import {
|
|
|
32
37
|
type UpdateAst,
|
|
33
38
|
type WindowFuncExpr,
|
|
34
39
|
} from '@prisma-next/sql-relational-core/ast';
|
|
35
|
-
import {
|
|
40
|
+
import { isPgEnumParams } from '@prisma-next/target-postgres/codecs';
|
|
41
|
+
import {
|
|
42
|
+
escapeLiteral,
|
|
43
|
+
quoteIdentifier,
|
|
44
|
+
quoteQualifiedName,
|
|
45
|
+
} from '@prisma-next/target-postgres/sql-utils';
|
|
36
46
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
37
47
|
import type { PostgresContract } from './types';
|
|
38
48
|
|
|
@@ -89,7 +99,7 @@ function renderTypedParam(
|
|
|
89
99
|
`Postgres lowering: ParamRef carries codecId "${codecId}" but the ` +
|
|
90
100
|
'assembled codec lookup has no entry for it. This usually indicates ' +
|
|
91
101
|
'a missing extension pack in the runtime stack — register the pack ' +
|
|
92
|
-
'that contributes this codec (e.g. `
|
|
102
|
+
'that contributes this codec (e.g. `extensions: [pgvectorRuntime]`), ' +
|
|
93
103
|
'or use the codec directly from `@prisma-next/target-postgres/codecs` ' +
|
|
94
104
|
"if it's a builtin.",
|
|
95
105
|
);
|
|
@@ -107,6 +117,15 @@ function renderTypedParam(
|
|
|
107
117
|
const nativeType = isRecord(dialectBlock) ? dialectBlock['nativeType'] : undefined;
|
|
108
118
|
if (typeof nativeType === 'string') {
|
|
109
119
|
const arraySuffix = many ? '[]' : '';
|
|
120
|
+
// A `typeParams.typeName` marks a named database type (e.g. a native
|
|
121
|
+
// enum): cast to its quoted, schema-qualified identifier so Postgres does
|
|
122
|
+
// not case-fold it (`$1::HoldType` would resolve as `holdtype`). Mirrors
|
|
123
|
+
// the DDL-side policy in `buildColumnTypeSql`. Builtin spellings
|
|
124
|
+
// (`double precision`, `jsonb`, …) stay verbatim — quoting them would
|
|
125
|
+
// turn them into (nonexistent) user-type lookups.
|
|
126
|
+
if (isPgEnumParams(typeParams)) {
|
|
127
|
+
return `$${index}::${quoteQualifiedName(nativeType)}${arraySuffix}`;
|
|
128
|
+
}
|
|
110
129
|
if (!POSTGRES_INFERRABLE_NATIVE_TYPES.has(nativeType)) {
|
|
111
130
|
return `$${index}::${nativeType}${arraySuffix}`;
|
|
112
131
|
}
|
|
@@ -121,6 +140,19 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
|
|
121
140
|
return typeof value === 'object' && value !== null;
|
|
122
141
|
}
|
|
123
142
|
|
|
143
|
+
function unreachableKind(value: never): string {
|
|
144
|
+
const candidate: unknown = value;
|
|
145
|
+
if (
|
|
146
|
+
typeof candidate === 'object' &&
|
|
147
|
+
candidate !== null &&
|
|
148
|
+
'kind' in candidate &&
|
|
149
|
+
typeof candidate.kind === 'string'
|
|
150
|
+
) {
|
|
151
|
+
return candidate.kind;
|
|
152
|
+
}
|
|
153
|
+
return 'unknown';
|
|
154
|
+
}
|
|
155
|
+
|
|
124
156
|
/**
|
|
125
157
|
* Per-render carrier threaded through every helper. Bundles the param-index map (for `$N` numbering) and the assembled-stack `codecLookup` (for cast policy at the `renderTypedParam` chokepoint). Carrying both on a single value keeps helper signatures stable.
|
|
126
158
|
*/
|
|
@@ -169,9 +201,7 @@ export function renderLoweredSql(
|
|
|
169
201
|
break;
|
|
170
202
|
// v8 ignore next 4
|
|
171
203
|
default:
|
|
172
|
-
throw new Error(
|
|
173
|
-
`Unsupported AST node kind: ${(node satisfies never as { kind: string }).kind}`,
|
|
174
|
-
);
|
|
204
|
+
throw new Error(`Unsupported AST node kind: ${unreachableKind(node)}`);
|
|
175
205
|
}
|
|
176
206
|
|
|
177
207
|
return Object.freeze({ sql, params: Object.freeze(params) });
|
|
@@ -465,13 +495,17 @@ function renderSource(
|
|
|
465
495
|
case 'function-source': {
|
|
466
496
|
const args = node.args.map((arg) => renderExpr(arg, contract, pim)).join(', ');
|
|
467
497
|
const call = `${node.fn}(${args})`;
|
|
468
|
-
|
|
498
|
+
const ordinality = node.ordinality ? ' WITH ORDINALITY' : '';
|
|
499
|
+
const alias = node.alias === undefined ? '' : ` AS ${quoteIdentifier(node.alias)}`;
|
|
500
|
+
const columnAliases =
|
|
501
|
+
node.columnAliases === undefined
|
|
502
|
+
? ''
|
|
503
|
+
: `(${node.columnAliases.map((column) => quoteIdentifier(column)).join(', ')})`;
|
|
504
|
+
return `${call}${ordinality}${alias}${columnAliases}`;
|
|
469
505
|
}
|
|
470
506
|
// v8 ignore next 4
|
|
471
507
|
default:
|
|
472
|
-
throw new Error(
|
|
473
|
-
`Unsupported source node kind: ${(node satisfies never as { kind: string }).kind}`,
|
|
474
|
-
);
|
|
508
|
+
throw new Error(`Unsupported source node kind: ${unreachableKind(node)}`);
|
|
475
509
|
}
|
|
476
510
|
}
|
|
477
511
|
|
|
@@ -518,6 +552,9 @@ function isAtomicExpressionKind(kind: AnyExpression['kind']): boolean {
|
|
|
518
552
|
case 'literal':
|
|
519
553
|
case 'aggregate':
|
|
520
554
|
case 'window-func':
|
|
555
|
+
case 'function-call':
|
|
556
|
+
case 'cast':
|
|
557
|
+
case 'case':
|
|
521
558
|
case 'json-object':
|
|
522
559
|
case 'json-array-agg':
|
|
523
560
|
case 'list':
|
|
@@ -644,6 +681,44 @@ function renderWindowFuncExpr(
|
|
|
644
681
|
return `${fn}(${args}) OVER (${over})`;
|
|
645
682
|
}
|
|
646
683
|
|
|
684
|
+
function renderFunctionCallExpr(
|
|
685
|
+
expr: FunctionCallExpr,
|
|
686
|
+
contract: PostgresContract,
|
|
687
|
+
pim: ParamIndexMap,
|
|
688
|
+
): string {
|
|
689
|
+
const args = expr.args.map((arg) => renderExpr(arg, contract, pim)).join(', ');
|
|
690
|
+
return `${expr.fn}(${args})`;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
function renderCastExpr(expr: CastExpr, contract: PostgresContract, pim: ParamIndexMap): string {
|
|
694
|
+
return `CAST(${renderExpr(expr.expr, contract, pim)} AS ${expr.targetType})`;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
function renderCaseExpr(expr: CaseExpr, contract: PostgresContract, pim: ParamIndexMap): string {
|
|
698
|
+
const branches = expr.branches
|
|
699
|
+
.map(
|
|
700
|
+
(branch) =>
|
|
701
|
+
`WHEN ${renderExpr(branch.condition, contract, pim)} THEN ${renderExpr(branch.value, contract, pim)}`,
|
|
702
|
+
)
|
|
703
|
+
.join(' ');
|
|
704
|
+
const elseClause =
|
|
705
|
+
expr.elseExpr === undefined ? '' : ` ELSE ${renderExpr(expr.elseExpr, contract, pim)}`;
|
|
706
|
+
return `CASE ${branches}${elseClause} END`;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
function renderJsonValueProjection(
|
|
710
|
+
projection: AnyJsonValueProjection,
|
|
711
|
+
contract: PostgresContract,
|
|
712
|
+
pim: ParamIndexMap,
|
|
713
|
+
): string {
|
|
714
|
+
const visitor: JsonValueProjectionVisitor<string> = {
|
|
715
|
+
codec: ({ value }) => renderExpr(value, contract, pim),
|
|
716
|
+
native: ({ value }) => renderExpr(value, contract, pim),
|
|
717
|
+
document: ({ value }) => renderExpr(value, contract, pim),
|
|
718
|
+
};
|
|
719
|
+
return projection.accept(visitor);
|
|
720
|
+
}
|
|
721
|
+
|
|
647
722
|
function renderJsonObjectExpr(
|
|
648
723
|
expr: JsonObjectExpr,
|
|
649
724
|
contract: PostgresContract,
|
|
@@ -652,10 +727,7 @@ function renderJsonObjectExpr(
|
|
|
652
727
|
const args = expr.entries
|
|
653
728
|
.flatMap((entry): [string, string] => {
|
|
654
729
|
const key = `'${escapeLiteral(entry.key)}'`;
|
|
655
|
-
|
|
656
|
-
return [key, renderLiteral(entry.value)];
|
|
657
|
-
}
|
|
658
|
-
return [key, renderExpr(entry.value, contract, pim)];
|
|
730
|
+
return [key, renderJsonValueProjection(entry.value, contract, pim)];
|
|
659
731
|
})
|
|
660
732
|
.join(', ');
|
|
661
733
|
return `json_build_object(${args})`;
|
|
@@ -680,7 +752,7 @@ function renderJsonArrayAggExpr(
|
|
|
680
752
|
expr.orderBy && expr.orderBy.length > 0
|
|
681
753
|
? ` ORDER BY ${renderOrderByItems(expr.orderBy, contract, pim)}`
|
|
682
754
|
: '';
|
|
683
|
-
const aggregated = `json_agg(${
|
|
755
|
+
const aggregated = `json_agg(${renderJsonValueProjection(expr.expr, contract, pim)}${aggregateOrderBy})`;
|
|
684
756
|
if (expr.onEmpty === 'emptyArray') {
|
|
685
757
|
return `coalesce(${aggregated}, json_build_array())`;
|
|
686
758
|
}
|
|
@@ -702,6 +774,12 @@ function renderExpr(expr: AnyExpression, contract: PostgresContract, pim: ParamI
|
|
|
702
774
|
return renderAggregateExpr(node, contract, pim);
|
|
703
775
|
case 'window-func':
|
|
704
776
|
return renderWindowFuncExpr(node, contract, pim);
|
|
777
|
+
case 'function-call':
|
|
778
|
+
return renderFunctionCallExpr(node, contract, pim);
|
|
779
|
+
case 'cast':
|
|
780
|
+
return renderCastExpr(node, contract, pim);
|
|
781
|
+
case 'case':
|
|
782
|
+
return renderCaseExpr(node, contract, pim);
|
|
705
783
|
case 'json-object':
|
|
706
784
|
return renderJsonObjectExpr(node, contract, pim);
|
|
707
785
|
case 'json-array-agg':
|
|
@@ -738,9 +816,7 @@ function renderExpr(expr: AnyExpression, contract: PostgresContract, pim: ParamI
|
|
|
738
816
|
return renderRawExpr(node, contract, pim);
|
|
739
817
|
// v8 ignore next 4
|
|
740
818
|
default:
|
|
741
|
-
throw new Error(
|
|
742
|
-
`Unsupported expression node kind: ${(node satisfies never as { kind: string }).kind}`,
|
|
743
|
-
);
|
|
819
|
+
throw new Error(`Unsupported expression node kind: ${unreachableKind(node)}`);
|
|
744
820
|
}
|
|
745
821
|
}
|
|
746
822
|
|
|
@@ -912,9 +988,7 @@ function renderInsertValue(
|
|
|
912
988
|
return renderExpr(value, contract, pim);
|
|
913
989
|
// v8 ignore next 4
|
|
914
990
|
default:
|
|
915
|
-
throw new Error(
|
|
916
|
-
`Unsupported value node in INSERT: ${(value satisfies never as { kind: string }).kind}`,
|
|
917
|
-
);
|
|
991
|
+
throw new Error(`Unsupported value node in INSERT: ${unreachableKind(value)}`);
|
|
918
992
|
}
|
|
919
993
|
}
|
|
920
994
|
|
|
@@ -979,9 +1053,7 @@ function renderInsert(ast: InsertAst, contract: PostgresContract, pim: ParamInde
|
|
|
979
1053
|
}
|
|
980
1054
|
// v8 ignore next 4
|
|
981
1055
|
default:
|
|
982
|
-
throw new Error(
|
|
983
|
-
`Unsupported onConflict action: ${(action satisfies never as { kind: string }).kind}`,
|
|
984
|
-
);
|
|
1056
|
+
throw new Error(`Unsupported onConflict action: ${unreachableKind(action)}`);
|
|
985
1057
|
}
|
|
986
1058
|
})()
|
|
987
1059
|
: '';
|
package/src/exports/control.ts
CHANGED
|
@@ -10,13 +10,13 @@ import { PostgresControlAdapter } from '../core/control-adapter';
|
|
|
10
10
|
import {
|
|
11
11
|
createPostgresDefaultFunctionRegistry,
|
|
12
12
|
createPostgresMutationDefaultGeneratorDescriptors,
|
|
13
|
-
|
|
13
|
+
postgresAuthoringTypes,
|
|
14
14
|
} from '../core/control-mutation-defaults';
|
|
15
15
|
import { postgresAdapterDescriptorMeta } from '../core/descriptor-meta';
|
|
16
16
|
|
|
17
17
|
const postgresAdapterDescriptor: SqlControlAdapterDescriptor<'postgres'> = {
|
|
18
18
|
...postgresAdapterDescriptorMeta,
|
|
19
|
-
|
|
19
|
+
authoring: { type: postgresAuthoringTypes, valueObjectStorageType: 'Jsonb' },
|
|
20
20
|
controlMutationDefaults: {
|
|
21
21
|
defaultFunctionRegistry: createPostgresDefaultFunctionRegistry(),
|
|
22
22
|
generatorDescriptors: createPostgresMutationDefaultGeneratorDescriptors(),
|
package/src/exports/runtime.ts
CHANGED
|
@@ -39,7 +39,7 @@ const postgresRuntimeAdapterDescriptor: SqlRuntimeAdapterDescriptor<'postgres',
|
|
|
39
39
|
create(stack): SqlRuntimeAdapter {
|
|
40
40
|
// The runtime `ExecutionStack` does not (yet) carry a pre-assembled `codecLookup` field the way the control `ControlStack` does, so we derive an equivalent lookup here from the stack's component metadata (target + adapter + extension packs) using the same assembly helper that `createControlStack` uses. This keeps the renderer fed with the same codec set on both planes — including extension-contributed codecs like
|
|
41
41
|
// `pg/vector@1` from `@prisma-next/extension-pgvector`.
|
|
42
|
-
const components = [stack.target, stack.adapter, ...stack.
|
|
42
|
+
const components = [stack.target, stack.adapter, ...stack.extensions];
|
|
43
43
|
const codecLookup = extractCodecLookup(components);
|
|
44
44
|
return createPostgresAdapter({ codecLookup });
|
|
45
45
|
},
|