@prisma-next/adapter-postgres 0.16.0-dev.3 → 0.16.0-dev.30
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-DlDJIHgB.mjs} +4 -4
- package/dist/adapter-DlDJIHgB.mjs.map +1 -0
- package/dist/adapter.d.mts.map +1 -1
- package/dist/adapter.mjs +1 -1
- package/dist/{control-adapter-B6IM_oTR.mjs → control-adapter-DKbwTazN.mjs} +164 -58
- package/dist/control-adapter-DKbwTazN.mjs.map +1 -0
- package/dist/control.d.mts +2 -2
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +269 -34
- package/dist/control.mjs.map +1 -1
- package/dist/{descriptor-meta-jMtx881n.mjs → descriptor-meta-pc7bA0_C.mjs} +26 -6
- package/dist/descriptor-meta-pc7bA0_C.mjs.map +1 -0
- package/dist/runtime.mjs +3 -3
- package/dist/runtime.mjs.map +1 -1
- 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 +140 -62
- package/src/core/control-codecs.ts +4 -1
- package/src/core/control-mutation-defaults.ts +134 -34
- package/src/core/descriptor-meta.ts +16 -5
- package/src/core/sql-renderer.ts +136 -34
- package/src/exports/control.ts +3 -4
- package/src/exports/runtime.ts +1 -1
- package/dist/adapter-BaZsfXGA.mjs.map +0 -1
- package/dist/control-adapter-B6IM_oTR.mjs.map +0 -1
- package/dist/descriptor-meta-jMtx881n.mjs.map +0 -1
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,8 +37,15 @@ 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';
|
|
47
|
+
import { assertNever, InternalError } from '@prisma-next/utils/internal-error';
|
|
48
|
+
import { adapterError } from './adapter-errors';
|
|
37
49
|
import type { PostgresContract } from './types';
|
|
38
50
|
|
|
39
51
|
/**
|
|
@@ -85,13 +97,15 @@ function renderTypedParam(
|
|
|
85
97
|
meta !== undefined ||
|
|
86
98
|
codecLookup.targetTypesFor(codecId) !== undefined;
|
|
87
99
|
if (!isRegistered) {
|
|
88
|
-
throw
|
|
100
|
+
throw adapterError(
|
|
101
|
+
'RUNTIME.PARAM_REF_MISSING_CODEC',
|
|
89
102
|
`Postgres lowering: ParamRef carries codecId "${codecId}" but the ` +
|
|
90
103
|
'assembled codec lookup has no entry for it. This usually indicates ' +
|
|
91
104
|
'a missing extension pack in the runtime stack — register the pack ' +
|
|
92
|
-
'that contributes this codec (e.g. `
|
|
105
|
+
'that contributes this codec (e.g. `extensions: [pgvectorRuntime]`), ' +
|
|
93
106
|
'or use the codec directly from `@prisma-next/target-postgres/codecs` ' +
|
|
94
107
|
"if it's a builtin.",
|
|
108
|
+
{ meta: { codecId } },
|
|
95
109
|
);
|
|
96
110
|
}
|
|
97
111
|
// `typeParams` above already resolved a parameterized codec's per-instance
|
|
@@ -107,6 +121,15 @@ function renderTypedParam(
|
|
|
107
121
|
const nativeType = isRecord(dialectBlock) ? dialectBlock['nativeType'] : undefined;
|
|
108
122
|
if (typeof nativeType === 'string') {
|
|
109
123
|
const arraySuffix = many ? '[]' : '';
|
|
124
|
+
// A `typeParams.typeName` marks a named database type (e.g. a native
|
|
125
|
+
// enum): cast to its quoted, schema-qualified identifier so Postgres does
|
|
126
|
+
// not case-fold it (`$1::HoldType` would resolve as `holdtype`). Mirrors
|
|
127
|
+
// the DDL-side policy in `buildColumnTypeSql`. Builtin spellings
|
|
128
|
+
// (`double precision`, `jsonb`, …) stay verbatim — quoting them would
|
|
129
|
+
// turn them into (nonexistent) user-type lookups.
|
|
130
|
+
if (isPgEnumParams(typeParams)) {
|
|
131
|
+
return `$${index}::${quoteQualifiedName(nativeType)}${arraySuffix}`;
|
|
132
|
+
}
|
|
110
133
|
if (!POSTGRES_INFERRABLE_NATIVE_TYPES.has(nativeType)) {
|
|
111
134
|
return `$${index}::${nativeType}${arraySuffix}`;
|
|
112
135
|
}
|
|
@@ -121,6 +144,19 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
|
|
121
144
|
return typeof value === 'object' && value !== null;
|
|
122
145
|
}
|
|
123
146
|
|
|
147
|
+
function unreachableKind(value: never): string {
|
|
148
|
+
const candidate: unknown = value;
|
|
149
|
+
if (
|
|
150
|
+
typeof candidate === 'object' &&
|
|
151
|
+
candidate !== null &&
|
|
152
|
+
'kind' in candidate &&
|
|
153
|
+
typeof candidate.kind === 'string'
|
|
154
|
+
) {
|
|
155
|
+
return candidate.kind;
|
|
156
|
+
}
|
|
157
|
+
return 'unknown';
|
|
158
|
+
}
|
|
159
|
+
|
|
124
160
|
/**
|
|
125
161
|
* 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
162
|
*/
|
|
@@ -169,9 +205,7 @@ export function renderLoweredSql(
|
|
|
169
205
|
break;
|
|
170
206
|
// v8 ignore next 4
|
|
171
207
|
default:
|
|
172
|
-
|
|
173
|
-
`Unsupported AST node kind: ${(node satisfies never as { kind: string }).kind}`,
|
|
174
|
-
);
|
|
208
|
+
assertNever(node, `Unsupported AST node kind: ${unreachableKind(node)}`);
|
|
175
209
|
}
|
|
176
210
|
|
|
177
211
|
return Object.freeze({ sql, params: Object.freeze(params) });
|
|
@@ -430,14 +464,18 @@ function qualifyTableFromNamespaceCoordinate(
|
|
|
430
464
|
}
|
|
431
465
|
const namespace = contract.storage.namespaces[table.namespaceId];
|
|
432
466
|
if (namespace === undefined) {
|
|
433
|
-
throw
|
|
467
|
+
throw adapterError(
|
|
468
|
+
'RUNTIME.NAMESPACE_UNKNOWN',
|
|
434
469
|
`Table "${table.name}" references namespace "${table.namespaceId}" which is not present as a Postgres schema on the contract`,
|
|
470
|
+
{ meta: { table: table.name, namespaceId: table.namespaceId, reason: 'not-present' } },
|
|
435
471
|
);
|
|
436
472
|
}
|
|
437
473
|
const qualifyTable = namespace.qualifyTable;
|
|
438
474
|
if (qualifyTable === undefined) {
|
|
439
|
-
throw
|
|
475
|
+
throw adapterError(
|
|
476
|
+
'RUNTIME.NAMESPACE_UNKNOWN',
|
|
440
477
|
`Table "${table.name}" references namespace "${table.namespaceId}" which is not materialised as a Postgres schema on the contract`,
|
|
478
|
+
{ meta: { table: table.name, namespaceId: table.namespaceId, reason: 'not-materialised' } },
|
|
441
479
|
);
|
|
442
480
|
}
|
|
443
481
|
return qualifyTable.call(namespace, table.name);
|
|
@@ -465,19 +503,27 @@ function renderSource(
|
|
|
465
503
|
case 'function-source': {
|
|
466
504
|
const args = node.args.map((arg) => renderExpr(arg, contract, pim)).join(', ');
|
|
467
505
|
const call = `${node.fn}(${args})`;
|
|
468
|
-
|
|
506
|
+
const ordinality = node.ordinality ? ' WITH ORDINALITY' : '';
|
|
507
|
+
const alias = node.alias === undefined ? '' : ` AS ${quoteIdentifier(node.alias)}`;
|
|
508
|
+
const columnAliases =
|
|
509
|
+
node.columnAliases === undefined
|
|
510
|
+
? ''
|
|
511
|
+
: `(${node.columnAliases.map((column) => quoteIdentifier(column)).join(', ')})`;
|
|
512
|
+
return `${call}${ordinality}${alias}${columnAliases}`;
|
|
469
513
|
}
|
|
470
514
|
// v8 ignore next 4
|
|
471
515
|
default:
|
|
472
|
-
|
|
473
|
-
`Unsupported source node kind: ${(node satisfies never as { kind: string }).kind}`,
|
|
474
|
-
);
|
|
516
|
+
assertNever(node, `Unsupported source node kind: ${unreachableKind(node)}`);
|
|
475
517
|
}
|
|
476
518
|
}
|
|
477
519
|
|
|
478
520
|
function assertScalarSubquery(query: SelectAst): void {
|
|
479
521
|
if (query.projection.length !== 1) {
|
|
480
|
-
throw
|
|
522
|
+
throw adapterError(
|
|
523
|
+
'RUNTIME.AST_INVALID',
|
|
524
|
+
'Subquery expressions must project exactly one column',
|
|
525
|
+
{ meta: { node: 'subquery-expr' } },
|
|
526
|
+
);
|
|
481
527
|
}
|
|
482
528
|
}
|
|
483
529
|
|
|
@@ -518,6 +564,9 @@ function isAtomicExpressionKind(kind: AnyExpression['kind']): boolean {
|
|
|
518
564
|
case 'literal':
|
|
519
565
|
case 'aggregate':
|
|
520
566
|
case 'window-func':
|
|
567
|
+
case 'function-call':
|
|
568
|
+
case 'cast':
|
|
569
|
+
case 'case':
|
|
521
570
|
case 'json-object':
|
|
522
571
|
case 'json-array-agg':
|
|
523
572
|
case 'list':
|
|
@@ -644,6 +693,44 @@ function renderWindowFuncExpr(
|
|
|
644
693
|
return `${fn}(${args}) OVER (${over})`;
|
|
645
694
|
}
|
|
646
695
|
|
|
696
|
+
function renderFunctionCallExpr(
|
|
697
|
+
expr: FunctionCallExpr,
|
|
698
|
+
contract: PostgresContract,
|
|
699
|
+
pim: ParamIndexMap,
|
|
700
|
+
): string {
|
|
701
|
+
const args = expr.args.map((arg) => renderExpr(arg, contract, pim)).join(', ');
|
|
702
|
+
return `${expr.fn}(${args})`;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
function renderCastExpr(expr: CastExpr, contract: PostgresContract, pim: ParamIndexMap): string {
|
|
706
|
+
return `CAST(${renderExpr(expr.expr, contract, pim)} AS ${expr.targetType})`;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
function renderCaseExpr(expr: CaseExpr, contract: PostgresContract, pim: ParamIndexMap): string {
|
|
710
|
+
const branches = expr.branches
|
|
711
|
+
.map(
|
|
712
|
+
(branch) =>
|
|
713
|
+
`WHEN ${renderExpr(branch.condition, contract, pim)} THEN ${renderExpr(branch.value, contract, pim)}`,
|
|
714
|
+
)
|
|
715
|
+
.join(' ');
|
|
716
|
+
const elseClause =
|
|
717
|
+
expr.elseExpr === undefined ? '' : ` ELSE ${renderExpr(expr.elseExpr, contract, pim)}`;
|
|
718
|
+
return `CASE ${branches}${elseClause} END`;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
function renderJsonValueProjection(
|
|
722
|
+
projection: AnyJsonValueProjection,
|
|
723
|
+
contract: PostgresContract,
|
|
724
|
+
pim: ParamIndexMap,
|
|
725
|
+
): string {
|
|
726
|
+
const visitor: JsonValueProjectionVisitor<string> = {
|
|
727
|
+
codec: ({ value }) => renderExpr(value, contract, pim),
|
|
728
|
+
native: ({ value }) => renderExpr(value, contract, pim),
|
|
729
|
+
document: ({ value }) => renderExpr(value, contract, pim),
|
|
730
|
+
};
|
|
731
|
+
return projection.accept(visitor);
|
|
732
|
+
}
|
|
733
|
+
|
|
647
734
|
function renderJsonObjectExpr(
|
|
648
735
|
expr: JsonObjectExpr,
|
|
649
736
|
contract: PostgresContract,
|
|
@@ -652,10 +739,7 @@ function renderJsonObjectExpr(
|
|
|
652
739
|
const args = expr.entries
|
|
653
740
|
.flatMap((entry): [string, string] => {
|
|
654
741
|
const key = `'${escapeLiteral(entry.key)}'`;
|
|
655
|
-
|
|
656
|
-
return [key, renderLiteral(entry.value)];
|
|
657
|
-
}
|
|
658
|
-
return [key, renderExpr(entry.value, contract, pim)];
|
|
742
|
+
return [key, renderJsonValueProjection(entry.value, contract, pim)];
|
|
659
743
|
})
|
|
660
744
|
.join(', ');
|
|
661
745
|
return `json_build_object(${args})`;
|
|
@@ -680,7 +764,7 @@ function renderJsonArrayAggExpr(
|
|
|
680
764
|
expr.orderBy && expr.orderBy.length > 0
|
|
681
765
|
? ` ORDER BY ${renderOrderByItems(expr.orderBy, contract, pim)}`
|
|
682
766
|
: '';
|
|
683
|
-
const aggregated = `json_agg(${
|
|
767
|
+
const aggregated = `json_agg(${renderJsonValueProjection(expr.expr, contract, pim)}${aggregateOrderBy})`;
|
|
684
768
|
if (expr.onEmpty === 'emptyArray') {
|
|
685
769
|
return `coalesce(${aggregated}, json_build_array())`;
|
|
686
770
|
}
|
|
@@ -702,6 +786,12 @@ function renderExpr(expr: AnyExpression, contract: PostgresContract, pim: ParamI
|
|
|
702
786
|
return renderAggregateExpr(node, contract, pim);
|
|
703
787
|
case 'window-func':
|
|
704
788
|
return renderWindowFuncExpr(node, contract, pim);
|
|
789
|
+
case 'function-call':
|
|
790
|
+
return renderFunctionCallExpr(node, contract, pim);
|
|
791
|
+
case 'cast':
|
|
792
|
+
return renderCastExpr(node, contract, pim);
|
|
793
|
+
case 'case':
|
|
794
|
+
return renderCaseExpr(node, contract, pim);
|
|
705
795
|
case 'json-object':
|
|
706
796
|
return renderJsonObjectExpr(node, contract, pim);
|
|
707
797
|
case 'json-array-agg':
|
|
@@ -738,16 +828,14 @@ function renderExpr(expr: AnyExpression, contract: PostgresContract, pim: ParamI
|
|
|
738
828
|
return renderRawExpr(node, contract, pim);
|
|
739
829
|
// v8 ignore next 4
|
|
740
830
|
default:
|
|
741
|
-
|
|
742
|
-
`Unsupported expression node kind: ${(node satisfies never as { kind: string }).kind}`,
|
|
743
|
-
);
|
|
831
|
+
assertNever(node, `Unsupported expression node kind: ${unreachableKind(node)}`);
|
|
744
832
|
}
|
|
745
833
|
}
|
|
746
834
|
|
|
747
835
|
function renderParamRef(ref: AnyParamRef, pim: ParamIndexMap): string {
|
|
748
836
|
const index = pim.indexMap.get(ref);
|
|
749
837
|
if (index === undefined) {
|
|
750
|
-
throw new
|
|
838
|
+
throw new InternalError('ParamRef not found in index map');
|
|
751
839
|
}
|
|
752
840
|
if (ref.kind === 'prepared-param-ref') {
|
|
753
841
|
return renderTypedParam(
|
|
@@ -824,8 +912,10 @@ function renderOperation(
|
|
|
824
912
|
}
|
|
825
913
|
const arg = args[Number(argIndex)];
|
|
826
914
|
if (arg === undefined) {
|
|
827
|
-
throw
|
|
915
|
+
throw adapterError(
|
|
916
|
+
'CONTRACT.PACK_CONTRIBUTION_INVALID',
|
|
828
917
|
`Operation lowering template for "${expr.method}" referenced missing argument {{arg${argIndex}}}; template has ${args.length} arg(s)`,
|
|
918
|
+
{ meta: { method: expr.method } },
|
|
829
919
|
);
|
|
830
920
|
}
|
|
831
921
|
return arg;
|
|
@@ -888,7 +978,11 @@ function getInsertColumnOrder(
|
|
|
888
978
|
}
|
|
889
979
|
}
|
|
890
980
|
if (!table) {
|
|
891
|
-
throw
|
|
981
|
+
throw adapterError(
|
|
982
|
+
'RUNTIME.AST_INVALID',
|
|
983
|
+
`INSERT target table not found in contract storage: ${tableName}`,
|
|
984
|
+
{ meta: { node: 'insert', table: tableName } },
|
|
985
|
+
);
|
|
892
986
|
}
|
|
893
987
|
return Object.keys(table.columns);
|
|
894
988
|
}
|
|
@@ -912,9 +1006,7 @@ function renderInsertValue(
|
|
|
912
1006
|
return renderExpr(value, contract, pim);
|
|
913
1007
|
// v8 ignore next 4
|
|
914
1008
|
default:
|
|
915
|
-
|
|
916
|
-
`Unsupported value node in INSERT: ${(value satisfies never as { kind: string }).kind}`,
|
|
917
|
-
);
|
|
1009
|
+
assertNever(value, `Unsupported value node in INSERT: ${unreachableKind(value)}`);
|
|
918
1010
|
}
|
|
919
1011
|
}
|
|
920
1012
|
|
|
@@ -922,7 +1014,9 @@ function renderInsert(ast: InsertAst, contract: PostgresContract, pim: ParamInde
|
|
|
922
1014
|
const table = qualifyTableFromNamespaceCoordinate(ast.table, contract);
|
|
923
1015
|
const rows = ast.rows;
|
|
924
1016
|
if (rows.length === 0) {
|
|
925
|
-
throw
|
|
1017
|
+
throw adapterError('RUNTIME.AST_INVALID', 'INSERT requires at least one row', {
|
|
1018
|
+
meta: { node: 'insert' },
|
|
1019
|
+
});
|
|
926
1020
|
}
|
|
927
1021
|
const hasExplicitValues = rows.some((row) => Object.keys(row).length > 0);
|
|
928
1022
|
const insertClause = (() => {
|
|
@@ -960,7 +1054,11 @@ function renderInsert(ast: InsertAst, contract: PostgresContract, pim: ParamInde
|
|
|
960
1054
|
? (() => {
|
|
961
1055
|
const conflictColumns = ast.onConflict.columns.map((col) => quoteIdentifier(col.column));
|
|
962
1056
|
if (conflictColumns.length === 0) {
|
|
963
|
-
throw
|
|
1057
|
+
throw adapterError(
|
|
1058
|
+
'RUNTIME.AST_INVALID',
|
|
1059
|
+
'INSERT onConflict requires at least one conflict column',
|
|
1060
|
+
{ meta: { node: 'insert-on-conflict' } },
|
|
1061
|
+
);
|
|
964
1062
|
}
|
|
965
1063
|
|
|
966
1064
|
const action = ast.onConflict.action;
|
|
@@ -970,7 +1068,11 @@ function renderInsert(ast: InsertAst, contract: PostgresContract, pim: ParamInde
|
|
|
970
1068
|
case 'do-update-set': {
|
|
971
1069
|
const updateEntries = Object.entries(action.set);
|
|
972
1070
|
if (updateEntries.length === 0) {
|
|
973
|
-
throw
|
|
1071
|
+
throw adapterError(
|
|
1072
|
+
'RUNTIME.AST_INVALID',
|
|
1073
|
+
'INSERT onConflict do-update-set requires at least one assignment',
|
|
1074
|
+
{ meta: { node: 'insert-on-conflict' } },
|
|
1075
|
+
);
|
|
974
1076
|
}
|
|
975
1077
|
const updates = updateEntries.map(([colName, value]) => {
|
|
976
1078
|
return `${quoteIdentifier(colName)} = ${renderExpr(value, contract, pim)}`;
|
|
@@ -979,9 +1081,7 @@ function renderInsert(ast: InsertAst, contract: PostgresContract, pim: ParamInde
|
|
|
979
1081
|
}
|
|
980
1082
|
// v8 ignore next 4
|
|
981
1083
|
default:
|
|
982
|
-
|
|
983
|
-
`Unsupported onConflict action: ${(action satisfies never as { kind: string }).kind}`,
|
|
984
|
-
);
|
|
1084
|
+
assertNever(action, `Unsupported onConflict action: ${unreachableKind(action)}`);
|
|
985
1085
|
}
|
|
986
1086
|
})()
|
|
987
1087
|
: '';
|
|
@@ -996,7 +1096,9 @@ function renderUpdate(ast: UpdateAst, contract: PostgresContract, pim: ParamInde
|
|
|
996
1096
|
const table = qualifyTableFromNamespaceCoordinate(ast.table, contract);
|
|
997
1097
|
const setEntries = Object.entries(ast.set);
|
|
998
1098
|
if (setEntries.length === 0) {
|
|
999
|
-
throw
|
|
1099
|
+
throw adapterError('RUNTIME.AST_INVALID', 'UPDATE requires at least one SET assignment', {
|
|
1100
|
+
meta: { node: 'update' },
|
|
1101
|
+
});
|
|
1000
1102
|
}
|
|
1001
1103
|
const setClauses = setEntries.map(([col, val]) => {
|
|
1002
1104
|
const column = quoteIdentifier(col);
|
package/src/exports/control.ts
CHANGED
|
@@ -4,19 +4,18 @@ import {
|
|
|
4
4
|
escapeLiteral,
|
|
5
5
|
qualifyName,
|
|
6
6
|
quoteIdentifier,
|
|
7
|
-
SqlEscapeError,
|
|
8
7
|
} from '@prisma-next/target-postgres/sql-utils';
|
|
9
8
|
import { PostgresControlAdapter } from '../core/control-adapter';
|
|
10
9
|
import {
|
|
11
10
|
createPostgresDefaultFunctionRegistry,
|
|
12
11
|
createPostgresMutationDefaultGeneratorDescriptors,
|
|
13
|
-
|
|
12
|
+
postgresAuthoringTypes,
|
|
14
13
|
} from '../core/control-mutation-defaults';
|
|
15
14
|
import { postgresAdapterDescriptorMeta } from '../core/descriptor-meta';
|
|
16
15
|
|
|
17
16
|
const postgresAdapterDescriptor: SqlControlAdapterDescriptor<'postgres'> = {
|
|
18
17
|
...postgresAdapterDescriptorMeta,
|
|
19
|
-
|
|
18
|
+
authoring: { type: postgresAuthoringTypes, valueObjectStorageType: 'Jsonb' },
|
|
20
19
|
controlMutationDefaults: {
|
|
21
20
|
defaultFunctionRegistry: createPostgresDefaultFunctionRegistry(),
|
|
22
21
|
generatorDescriptors: createPostgresMutationDefaultGeneratorDescriptors(),
|
|
@@ -32,4 +31,4 @@ export { parsePostgresDefault } from '@prisma-next/target-postgres/default-norma
|
|
|
32
31
|
export { normalizeSchemaNativeType } from '@prisma-next/target-postgres/native-type-normalizer';
|
|
33
32
|
export { createPostgresBuiltinCodecLookup } from '../core/codec-lookup';
|
|
34
33
|
export { PostgresControlAdapter } from '../core/control-adapter';
|
|
35
|
-
export { escapeLiteral, qualifyName, quoteIdentifier
|
|
34
|
+
export { escapeLiteral, qualifyName, quoteIdentifier };
|
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
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-BaZsfXGA.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 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 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;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,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"}
|