@prisma-next/adapter-postgres 0.14.0 → 0.15.0-dev.10
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-CwkcdpM_.mjs → adapter-Bh8GA6sC.mjs} +4 -3
- package/dist/adapter-Bh8GA6sC.mjs.map +1 -0
- package/dist/adapter.d.mts +1 -1
- package/dist/adapter.d.mts.map +1 -1
- package/dist/adapter.mjs +1 -1
- package/dist/{control-adapter-Dspz5uKp.mjs → control-adapter-aFfSI2bK.mjs} +427 -120
- package/dist/control-adapter-aFfSI2bK.mjs.map +1 -0
- package/dist/control.d.mts +23 -12
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +46 -107
- package/dist/control.mjs.map +1 -1
- package/dist/{descriptor-meta-DOgMfoqm.mjs → descriptor-meta-jMtx881n.mjs} +12 -4
- package/dist/descriptor-meta-jMtx881n.mjs.map +1 -0
- package/dist/runtime.d.mts +1 -1
- package/dist/runtime.mjs +2 -2
- package/dist/runtime.mjs.map +1 -1
- package/dist/{types-KXRwRZU8.d.mts → types-DkGeLfUp.d.mts} +3 -6
- package/dist/types-DkGeLfUp.d.mts.map +1 -0
- package/dist/types.d.mts +1 -1
- package/package.json +26 -25
- package/src/core/adapter.ts +1 -0
- package/src/core/codec-lookup.ts +2 -1
- package/src/core/control-adapter.ts +611 -152
- package/src/core/control-mutation-defaults.ts +61 -190
- package/src/core/descriptor-meta.ts +4 -0
- package/src/core/marker-ledger.ts +15 -0
- package/src/core/sql-renderer.ts +32 -6
- package/src/core/types.ts +2 -3
- package/src/exports/runtime.ts +2 -5
- package/dist/adapter-CwkcdpM_.mjs.map +0 -1
- package/dist/control-adapter-Dspz5uKp.mjs.map +0 -1
- package/dist/descriptor-meta-DOgMfoqm.mjs.map +0 -1
- package/dist/types-KXRwRZU8.d.mts.map +0 -1
|
@@ -5,16 +5,18 @@ import type {
|
|
|
5
5
|
DefaultFunctionLoweringContext,
|
|
6
6
|
LoweredDefaultResult,
|
|
7
7
|
MutationDefaultGeneratorDescriptor,
|
|
8
|
-
|
|
8
|
+
TypedDefaultFunctionCall,
|
|
9
9
|
} from '@prisma-next/framework-components/control';
|
|
10
10
|
import {
|
|
11
11
|
builtinGeneratorRegistryMetadata,
|
|
12
12
|
resolveBuiltinGeneratedColumnDescriptor,
|
|
13
13
|
} from '@prisma-next/ids';
|
|
14
|
+
import type { FuncCallSig } from '@prisma-next/psl-parser';
|
|
15
|
+
import { int, num, oneOf, optional, str } from '@prisma-next/psl-parser';
|
|
14
16
|
|
|
15
17
|
function invalidArgumentDiagnostic(input: {
|
|
16
18
|
readonly context: DefaultFunctionLoweringContext;
|
|
17
|
-
readonly span:
|
|
19
|
+
readonly span: TypedDefaultFunctionCall['span'];
|
|
18
20
|
readonly message: string;
|
|
19
21
|
}): LoweredDefaultResult {
|
|
20
22
|
return {
|
|
@@ -45,218 +47,62 @@ function executionGenerator(
|
|
|
45
47
|
};
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
function
|
|
49
|
-
readonly call: ParsedDefaultFunctionCall;
|
|
50
|
-
readonly context: DefaultFunctionLoweringContext;
|
|
51
|
-
readonly usage: string;
|
|
52
|
-
}): LoweredDefaultResult | undefined {
|
|
53
|
-
if (input.call.args.length === 0) {
|
|
54
|
-
return undefined;
|
|
55
|
-
}
|
|
56
|
-
return invalidArgumentDiagnostic({
|
|
57
|
-
context: input.context,
|
|
58
|
-
span: input.call.span,
|
|
59
|
-
message: `Default function "${input.call.name}" does not accept arguments. Use ${input.usage}.`,
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function parseIntegerArgument(raw: string): number | undefined {
|
|
64
|
-
const trimmed = raw.trim();
|
|
65
|
-
if (!/^-?\d+$/.test(trimmed)) {
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
|
-
const value = Number(trimmed);
|
|
69
|
-
if (!Number.isInteger(value)) {
|
|
70
|
-
return undefined;
|
|
71
|
-
}
|
|
72
|
-
return value;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function parseStringLiteral(raw: string): string | undefined {
|
|
76
|
-
const match = raw.trim().match(/^(['"])(.*)\1$/s);
|
|
77
|
-
if (!match) {
|
|
78
|
-
return undefined;
|
|
79
|
-
}
|
|
80
|
-
return match[2] ?? '';
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function lowerAutoincrement(input: {
|
|
84
|
-
readonly call: ParsedDefaultFunctionCall;
|
|
85
|
-
readonly context: DefaultFunctionLoweringContext;
|
|
86
|
-
}): LoweredDefaultResult {
|
|
87
|
-
const maybeNoArgs = expectNoArgs({
|
|
88
|
-
call: input.call,
|
|
89
|
-
context: input.context,
|
|
90
|
-
usage: '`autoincrement()`',
|
|
91
|
-
});
|
|
92
|
-
if (maybeNoArgs) {
|
|
93
|
-
return maybeNoArgs;
|
|
94
|
-
}
|
|
50
|
+
function lowerAutoincrement(): LoweredDefaultResult {
|
|
95
51
|
return {
|
|
96
52
|
ok: true,
|
|
97
53
|
value: {
|
|
98
54
|
kind: 'storage',
|
|
99
|
-
defaultValue: {
|
|
100
|
-
kind: 'function',
|
|
101
|
-
expression: 'autoincrement()',
|
|
102
|
-
},
|
|
55
|
+
defaultValue: { kind: 'function', expression: 'autoincrement()' },
|
|
103
56
|
},
|
|
104
57
|
};
|
|
105
58
|
}
|
|
106
59
|
|
|
107
|
-
function lowerNow(
|
|
108
|
-
readonly call: ParsedDefaultFunctionCall;
|
|
109
|
-
readonly context: DefaultFunctionLoweringContext;
|
|
110
|
-
}): LoweredDefaultResult {
|
|
111
|
-
const maybeNoArgs = expectNoArgs({
|
|
112
|
-
call: input.call,
|
|
113
|
-
context: input.context,
|
|
114
|
-
usage: '`now()`',
|
|
115
|
-
});
|
|
116
|
-
if (maybeNoArgs) {
|
|
117
|
-
return maybeNoArgs;
|
|
118
|
-
}
|
|
60
|
+
function lowerNow(): LoweredDefaultResult {
|
|
119
61
|
return {
|
|
120
62
|
ok: true,
|
|
121
63
|
value: {
|
|
122
64
|
kind: 'storage',
|
|
123
|
-
defaultValue: {
|
|
124
|
-
kind: 'function',
|
|
125
|
-
expression: 'now()',
|
|
126
|
-
},
|
|
65
|
+
defaultValue: { kind: 'function', expression: 'now()' },
|
|
127
66
|
},
|
|
128
67
|
};
|
|
129
68
|
}
|
|
130
69
|
|
|
131
|
-
function
|
|
132
|
-
|
|
133
|
-
readonly context: DefaultFunctionLoweringContext;
|
|
134
|
-
}): LoweredDefaultResult {
|
|
135
|
-
if (input.call.args.length === 0) {
|
|
136
|
-
return executionGenerator('uuidv4');
|
|
137
|
-
}
|
|
138
|
-
if (input.call.args.length !== 1) {
|
|
139
|
-
return invalidArgumentDiagnostic({
|
|
140
|
-
context: input.context,
|
|
141
|
-
span: input.call.span,
|
|
142
|
-
message:
|
|
143
|
-
'Default function "uuid" accepts at most one version argument: `uuid()`, `uuid(4)`, or `uuid(7)`.',
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
const version = parseIntegerArgument(input.call.args[0]?.raw ?? '');
|
|
147
|
-
if (version === 4) {
|
|
148
|
-
return executionGenerator('uuidv4');
|
|
149
|
-
}
|
|
150
|
-
if (version === 7) {
|
|
151
|
-
return executionGenerator('uuidv7');
|
|
152
|
-
}
|
|
153
|
-
return invalidArgumentDiagnostic({
|
|
154
|
-
context: input.context,
|
|
155
|
-
span: input.call.args[0]?.span ?? input.call.span,
|
|
156
|
-
message:
|
|
157
|
-
'Default function "uuid" supports only `uuid()`, `uuid(4)`, or `uuid(7)` in SQL PSL provider v1.',
|
|
158
|
-
});
|
|
70
|
+
function lowerUlid(): LoweredDefaultResult {
|
|
71
|
+
return executionGenerator('ulid');
|
|
159
72
|
}
|
|
160
73
|
|
|
161
|
-
function
|
|
162
|
-
readonly call:
|
|
74
|
+
function lowerUuid(input: {
|
|
75
|
+
readonly call: TypedDefaultFunctionCall;
|
|
163
76
|
readonly context: DefaultFunctionLoweringContext;
|
|
164
77
|
}): LoweredDefaultResult {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
diagnostic: {
|
|
169
|
-
code: 'PSL_UNKNOWN_DEFAULT_FUNCTION',
|
|
170
|
-
message:
|
|
171
|
-
'Default function "cuid()" is not supported in SQL PSL provider v1. Use `cuid(2)` instead.',
|
|
172
|
-
sourceId: input.context.sourceId,
|
|
173
|
-
span: input.call.span,
|
|
174
|
-
},
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
if (input.call.args.length !== 1) {
|
|
178
|
-
return invalidArgumentDiagnostic({
|
|
179
|
-
context: input.context,
|
|
180
|
-
span: input.call.span,
|
|
181
|
-
message: 'Default function "cuid" accepts exactly one version argument: `cuid(2)`.',
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
const version = parseIntegerArgument(input.call.args[0]?.raw ?? '');
|
|
185
|
-
if (version === 2) {
|
|
186
|
-
return executionGenerator('cuid2');
|
|
187
|
-
}
|
|
188
|
-
return invalidArgumentDiagnostic({
|
|
189
|
-
context: input.context,
|
|
190
|
-
span: input.call.args[0]?.span ?? input.call.span,
|
|
191
|
-
message: 'Default function "cuid" supports only `cuid(2)` in SQL PSL provider v1.',
|
|
192
|
-
});
|
|
78
|
+
return input.call.args['version'] === 7
|
|
79
|
+
? executionGenerator('uuidv7')
|
|
80
|
+
: executionGenerator('uuidv4');
|
|
193
81
|
}
|
|
194
82
|
|
|
195
|
-
function
|
|
196
|
-
|
|
197
|
-
readonly context: DefaultFunctionLoweringContext;
|
|
198
|
-
}): LoweredDefaultResult {
|
|
199
|
-
const maybeNoArgs = expectNoArgs({
|
|
200
|
-
call: input.call,
|
|
201
|
-
context: input.context,
|
|
202
|
-
usage: '`ulid()`',
|
|
203
|
-
});
|
|
204
|
-
if (maybeNoArgs) {
|
|
205
|
-
return maybeNoArgs;
|
|
206
|
-
}
|
|
207
|
-
return executionGenerator('ulid');
|
|
83
|
+
function lowerCuid(): LoweredDefaultResult {
|
|
84
|
+
return executionGenerator('cuid2');
|
|
208
85
|
}
|
|
209
86
|
|
|
210
87
|
function lowerNanoid(input: {
|
|
211
|
-
readonly call:
|
|
88
|
+
readonly call: TypedDefaultFunctionCall;
|
|
212
89
|
readonly context: DefaultFunctionLoweringContext;
|
|
213
90
|
}): LoweredDefaultResult {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
return invalidArgumentDiagnostic({
|
|
219
|
-
context: input.context,
|
|
220
|
-
span: input.call.span,
|
|
221
|
-
message:
|
|
222
|
-
'Default function "nanoid" accepts at most one size argument: `nanoid()` or `nanoid(<2-255>)`.',
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
const size = parseIntegerArgument(input.call.args[0]?.raw ?? '');
|
|
226
|
-
if (size !== undefined && size >= 2 && size <= 255) {
|
|
227
|
-
return executionGenerator('nanoid', { size });
|
|
228
|
-
}
|
|
229
|
-
return invalidArgumentDiagnostic({
|
|
230
|
-
context: input.context,
|
|
231
|
-
span: input.call.args[0]?.span ?? input.call.span,
|
|
232
|
-
message: 'Default function "nanoid" size argument must be an integer between 2 and 255.',
|
|
233
|
-
});
|
|
91
|
+
const size = input.call.args['size'];
|
|
92
|
+
return typeof size === 'number'
|
|
93
|
+
? executionGenerator('nanoid', { size })
|
|
94
|
+
: executionGenerator('nanoid');
|
|
234
95
|
}
|
|
235
96
|
|
|
236
97
|
function lowerDbgenerated(input: {
|
|
237
|
-
readonly call:
|
|
98
|
+
readonly call: TypedDefaultFunctionCall;
|
|
238
99
|
readonly context: DefaultFunctionLoweringContext;
|
|
239
100
|
}): LoweredDefaultResult {
|
|
240
|
-
|
|
101
|
+
const expression = input.call.args['expression'];
|
|
102
|
+
if (typeof expression !== 'string' || expression.trim().length === 0) {
|
|
241
103
|
return invalidArgumentDiagnostic({
|
|
242
104
|
context: input.context,
|
|
243
105
|
span: input.call.span,
|
|
244
|
-
message:
|
|
245
|
-
'Default function "dbgenerated" requires exactly one string argument: `dbgenerated("...")`.',
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
const rawExpression = parseStringLiteral(input.call.args[0]?.raw ?? '');
|
|
249
|
-
if (rawExpression === undefined) {
|
|
250
|
-
return invalidArgumentDiagnostic({
|
|
251
|
-
context: input.context,
|
|
252
|
-
span: input.call.args[0]?.span ?? input.call.span,
|
|
253
|
-
message: 'Default function "dbgenerated" argument must be a string literal.',
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
if (rawExpression.trim().length === 0) {
|
|
257
|
-
return invalidArgumentDiagnostic({
|
|
258
|
-
context: input.context,
|
|
259
|
-
span: input.call.args[0]?.span ?? input.call.span,
|
|
260
106
|
message: 'Default function "dbgenerated" argument cannot be empty.',
|
|
261
107
|
});
|
|
262
108
|
}
|
|
@@ -264,22 +110,47 @@ function lowerDbgenerated(input: {
|
|
|
264
110
|
ok: true,
|
|
265
111
|
value: {
|
|
266
112
|
kind: 'storage',
|
|
267
|
-
defaultValue: {
|
|
268
|
-
kind: 'function',
|
|
269
|
-
expression: rawExpression,
|
|
270
|
-
},
|
|
113
|
+
defaultValue: { kind: 'function', expression },
|
|
271
114
|
},
|
|
272
115
|
};
|
|
273
116
|
}
|
|
274
117
|
|
|
118
|
+
const nowSig: FuncCallSig = {};
|
|
119
|
+
const autoincrementSig: FuncCallSig = {};
|
|
120
|
+
const ulidSig: FuncCallSig = {};
|
|
121
|
+
const uuidSig: FuncCallSig = {
|
|
122
|
+
positional: [{ key: 'version', type: optional(oneOf(num(4), num(7))) }],
|
|
123
|
+
};
|
|
124
|
+
const cuidSig: FuncCallSig = { positional: [{ key: 'version', type: num(2) }] };
|
|
125
|
+
const nanoidSig: FuncCallSig = {
|
|
126
|
+
positional: [{ key: 'size', type: optional(int({ min: 2, max: 255 })) }],
|
|
127
|
+
};
|
|
128
|
+
const dbgeneratedSig: FuncCallSig = { positional: [{ key: 'expression', type: str() }] };
|
|
129
|
+
|
|
275
130
|
const postgresDefaultFunctionRegistryEntries = [
|
|
276
|
-
[
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
131
|
+
[
|
|
132
|
+
'autoincrement',
|
|
133
|
+
{
|
|
134
|
+
signature: autoincrementSig,
|
|
135
|
+
lower: lowerAutoincrement,
|
|
136
|
+
usageSignatures: ['autoincrement()'],
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
['now', { signature: nowSig, lower: lowerNow, usageSignatures: ['now()'] }],
|
|
140
|
+
[
|
|
141
|
+
'uuid',
|
|
142
|
+
{ signature: uuidSig, lower: lowerUuid, usageSignatures: ['uuid()', 'uuid(4)', 'uuid(7)'] },
|
|
143
|
+
],
|
|
144
|
+
['cuid', { signature: cuidSig, lower: lowerCuid, usageSignatures: ['cuid(2)'] }],
|
|
145
|
+
['ulid', { signature: ulidSig, lower: lowerUlid, usageSignatures: ['ulid()'] }],
|
|
146
|
+
[
|
|
147
|
+
'nanoid',
|
|
148
|
+
{ signature: nanoidSig, lower: lowerNanoid, usageSignatures: ['nanoid()', 'nanoid(<2-255>)'] },
|
|
149
|
+
],
|
|
150
|
+
[
|
|
151
|
+
'dbgenerated',
|
|
152
|
+
{ signature: dbgeneratedSig, lower: lowerDbgenerated, usageSignatures: ['dbgenerated("...")'] },
|
|
153
|
+
],
|
|
283
154
|
] satisfies ReadonlyArray<readonly [string, ControlMutationDefaultEntry]>;
|
|
284
155
|
|
|
285
156
|
const postgresScalarTypeDescriptors = new Map<string, string>([
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
PG_FLOAT_CODEC_ID,
|
|
15
15
|
PG_FLOAT4_CODEC_ID,
|
|
16
16
|
PG_FLOAT8_CODEC_ID,
|
|
17
|
+
PG_INET_CODEC_ID,
|
|
17
18
|
PG_INT_CODEC_ID,
|
|
18
19
|
PG_INT2_CODEC_ID,
|
|
19
20
|
PG_INT4_CODEC_ID,
|
|
@@ -172,6 +173,7 @@ export const postgresAdapterDescriptorMeta = {
|
|
|
172
173
|
returning: true,
|
|
173
174
|
defaultInInsert: true,
|
|
174
175
|
lateral: true,
|
|
176
|
+
scalarList: true,
|
|
175
177
|
},
|
|
176
178
|
},
|
|
177
179
|
types: {
|
|
@@ -217,6 +219,7 @@ export const postgresAdapterDescriptorMeta = {
|
|
|
217
219
|
[PG_JSONB_CODEC_ID]: identityHooks,
|
|
218
220
|
[PG_BYTEA_CODEC_ID]: identityHooks,
|
|
219
221
|
[PG_UUID_CODEC_ID]: identityHooks,
|
|
222
|
+
[PG_INET_CODEC_ID]: identityHooks,
|
|
220
223
|
},
|
|
221
224
|
},
|
|
222
225
|
storage: [
|
|
@@ -284,6 +287,7 @@ export const postgresAdapterDescriptorMeta = {
|
|
|
284
287
|
{ typeId: PG_JSONB_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'jsonb' },
|
|
285
288
|
{ typeId: PG_BYTEA_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'bytea' },
|
|
286
289
|
{ typeId: PG_UUID_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'uuid' },
|
|
290
|
+
{ typeId: PG_INET_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'inet' },
|
|
287
291
|
],
|
|
288
292
|
queryOperationTypes: {
|
|
289
293
|
import: {
|
|
@@ -48,6 +48,21 @@ export const ledger = pgTable(
|
|
|
48
48
|
},
|
|
49
49
|
);
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Content-addressed contract store: one row per distinct contract, keyed
|
|
53
|
+
* by its storage hash. The ledger's `origin_core_hash` /
|
|
54
|
+
* `destination_core_hash` resolve here by hash equality, so both
|
|
55
|
+
* endpoints of every edge are direct lookups and a contract revisited by
|
|
56
|
+
* a rollback cycle is stored exactly once (upsert DO NOTHING).
|
|
57
|
+
*/
|
|
58
|
+
export const ledgerContract = pgTable(
|
|
59
|
+
{ name: 'contract', schema: 'prisma_contract' },
|
|
60
|
+
{
|
|
61
|
+
core_hash: text(),
|
|
62
|
+
contract_json: jsonb(),
|
|
63
|
+
},
|
|
64
|
+
);
|
|
65
|
+
|
|
51
66
|
/**
|
|
52
67
|
* Read-side handle covering every column of `prisma_contract.ledger`,
|
|
53
68
|
* including the DB-generated `id` (for ORDER BY) and `created_at`.
|
package/src/core/sql-renderer.ts
CHANGED
|
@@ -73,11 +73,13 @@ function renderTypedParam(
|
|
|
73
73
|
index: number,
|
|
74
74
|
codecId: string | undefined,
|
|
75
75
|
codecLookup: CodecLookup,
|
|
76
|
+
many?: boolean,
|
|
77
|
+
typeParams?: JsonValue,
|
|
76
78
|
): string {
|
|
77
79
|
if (codecId === undefined) {
|
|
78
80
|
return `$${index}`;
|
|
79
81
|
}
|
|
80
|
-
const meta = codecLookup.metaFor(codecId);
|
|
82
|
+
const meta = codecLookup.metaFor(codecId, typeParams);
|
|
81
83
|
const isRegistered =
|
|
82
84
|
codecLookup.get(codecId) !== undefined ||
|
|
83
85
|
meta !== undefined ||
|
|
@@ -92,13 +94,25 @@ function renderTypedParam(
|
|
|
92
94
|
"if it's a builtin.",
|
|
93
95
|
);
|
|
94
96
|
}
|
|
95
|
-
//
|
|
97
|
+
// `typeParams` above already resolved a parameterized codec's per-instance
|
|
98
|
+
// meta (e.g. a native enum's type name) ahead of its static fallback.
|
|
99
|
+
//
|
|
100
|
+
// The framework `CodecLookup.metaFor` returns the family-agnostic
|
|
101
|
+
// `CodecMeta`, whose `db` is `Record<string, unknown>`. The SQL family
|
|
102
|
+
// populates a narrower shape with `db.sql.<dialect>.nativeType: string`, so
|
|
103
|
+
// navigate that path defensively and string-check the leaf.
|
|
96
104
|
const dbRecord = meta?.db;
|
|
97
105
|
const sqlBlock = isRecord(dbRecord) ? dbRecord['sql'] : undefined;
|
|
98
106
|
const dialectBlock = isRecord(sqlBlock) ? sqlBlock['postgres'] : undefined;
|
|
99
107
|
const nativeType = isRecord(dialectBlock) ? dialectBlock['nativeType'] : undefined;
|
|
100
|
-
if (typeof nativeType === 'string'
|
|
101
|
-
|
|
108
|
+
if (typeof nativeType === 'string') {
|
|
109
|
+
const arraySuffix = many ? '[]' : '';
|
|
110
|
+
if (!POSTGRES_INFERRABLE_NATIVE_TYPES.has(nativeType)) {
|
|
111
|
+
return `$${index}::${nativeType}${arraySuffix}`;
|
|
112
|
+
}
|
|
113
|
+
if (many) {
|
|
114
|
+
return `$${index}::${nativeType}${arraySuffix}`;
|
|
115
|
+
}
|
|
102
116
|
}
|
|
103
117
|
return `$${index}`;
|
|
104
118
|
}
|
|
@@ -736,7 +750,13 @@ function renderParamRef(ref: AnyParamRef, pim: ParamIndexMap): string {
|
|
|
736
750
|
throw new Error('ParamRef not found in index map');
|
|
737
751
|
}
|
|
738
752
|
if (ref.kind === 'prepared-param-ref') {
|
|
739
|
-
return renderTypedParam(
|
|
753
|
+
return renderTypedParam(
|
|
754
|
+
index,
|
|
755
|
+
ref.codec.codecId,
|
|
756
|
+
pim.codecLookup,
|
|
757
|
+
ref.codec.many,
|
|
758
|
+
ref.codec.typeParams,
|
|
759
|
+
);
|
|
740
760
|
}
|
|
741
761
|
if (ref.codec === undefined) {
|
|
742
762
|
throw runtimeError(
|
|
@@ -747,7 +767,13 @@ function renderParamRef(ref: AnyParamRef, pim: ParamIndexMap): string {
|
|
|
747
767
|
{ paramIndex: index, ...ifDefined('name', ref.name) },
|
|
748
768
|
);
|
|
749
769
|
}
|
|
750
|
-
return renderTypedParam(
|
|
770
|
+
return renderTypedParam(
|
|
771
|
+
index,
|
|
772
|
+
ref.codec.codecId,
|
|
773
|
+
pim.codecLookup,
|
|
774
|
+
ref.codec.many,
|
|
775
|
+
ref.codec.typeParams,
|
|
776
|
+
);
|
|
751
777
|
}
|
|
752
778
|
|
|
753
779
|
function renderLiteral(expr: LiteralExpr): string {
|
package/src/core/types.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import type { Contract } from '@prisma-next/contract/types';
|
|
2
1
|
import type { CodecRegistry } from '@prisma-next/framework-components/codec';
|
|
3
|
-
import type {
|
|
2
|
+
import type { StorageColumn, StorageTable } from '@prisma-next/sql-contract/types';
|
|
4
3
|
import type {
|
|
5
4
|
AnyQueryAst,
|
|
6
5
|
BinaryExpr,
|
|
@@ -32,7 +31,7 @@ export interface PostgresAdapterOptions {
|
|
|
32
31
|
readonly codecLookup?: CodecRegistry;
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
export type PostgresContract
|
|
34
|
+
export type { PostgresContract } from '@prisma-next/target-postgres/types';
|
|
36
35
|
|
|
37
36
|
export type Expr = ColumnRef | ParamRef | DefaultValueExpr;
|
|
38
37
|
|
package/src/exports/runtime.ts
CHANGED
|
@@ -39,11 +39,8 @@ 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
|
|
43
|
-
|
|
44
|
-
stack.adapter,
|
|
45
|
-
...stack.extensionPacks,
|
|
46
|
-
]);
|
|
42
|
+
const components = [stack.target, stack.adapter, ...stack.extensionPacks];
|
|
43
|
+
const codecLookup = extractCodecLookup(components);
|
|
47
44
|
return createPostgresAdapter({ codecLookup });
|
|
48
45
|
},
|
|
49
46
|
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-CwkcdpM_.mjs","names":[],"sources":["../src/core/adapter.ts"],"sourcesContent":["import type { CodecRegistry } from '@prisma-next/framework-components/codec';\nimport { APP_SPACE_ID } from '@prisma-next/framework-components/control';\nimport type {\n Adapter,\n AdapterProfile,\n AnyQueryAst,\n LowererContext,\n RawSqlLiteral,\n SqlQueryable,\n} from '@prisma-next/sql-relational-core/ast';\nimport { isDdlNode } from '@prisma-next/sql-relational-core/ast';\nimport type { RawCodecInferer } from '@prisma-next/sql-relational-core/expression';\nimport type { PostgresDdlNode } from '@prisma-next/target-postgres/ddl';\nimport { createPostgresBuiltinCodecLookup } from './codec-lookup';\nimport { PostgresControlAdapter } from './control-adapter';\nimport { renderLoweredSql } from './sql-renderer';\nimport type { PostgresAdapterOptions, PostgresContract, PostgresLoweredStatement } from './types';\n\nconst defaultCapabilities = Object.freeze({\n postgres: {\n orderBy: true,\n limit: true,\n lateral: true,\n jsonAgg: true,\n returning: true,\n distinctOn: true,\n },\n sql: {\n enums: true,\n returning: true,\n defaultInInsert: true,\n lateral: true,\n },\n});\n\nclass PostgresAdapterImpl\n implements Adapter<AnyQueryAst, PostgresContract, PostgresLoweredStatement>\n{\n // These fields make the adapter instance structurally compatible with RuntimeAdapterInstance<'sql', 'postgres'> without introducing a runtime-plane dependency.\n readonly familyId = 'sql' as const;\n readonly targetId = 'postgres' as const;\n\n readonly profile: AdapterProfile<'postgres'>;\n private readonly codecLookup: CodecRegistry;\n\n constructor(options?: PostgresAdapterOptions) {\n this.codecLookup = options?.codecLookup ?? createPostgresBuiltinCodecLookup();\n const controlAdapter = new PostgresControlAdapter(this.codecLookup);\n this.profile = Object.freeze({\n id: options?.profileId ?? 'postgres/default@1',\n target: 'postgres',\n capabilities: defaultCapabilities,\n readMarker: (queryable: SqlQueryable) =>\n controlAdapter.readMarkerDiscriminated(\n {\n familyId: 'sql',\n targetId: 'postgres',\n query: async <Row = Record<string, unknown>>(\n sql: string,\n params?: readonly unknown[],\n ) => {\n const result = await queryable.query<Row>(sql, params);\n return { rows: [...result.rows] };\n },\n close: async () => {},\n },\n APP_SPACE_ID,\n ),\n });\n }\n\n lower(\n ast: AnyQueryAst | PostgresDdlNode,\n context: LowererContext<PostgresContract>,\n ): PostgresLoweredStatement {\n if (isDdlNode(ast)) {\n throw new Error(\n 'lower() does not lower DDL on the runtime adapter — DDL lowering is a control-plane concern handled by the control adapter.',\n );\n }\n return renderLoweredSql(ast, context.contract, this.codecLookup);\n }\n}\n\n/** Codec-id lookup for bare-literal interpolations used by `fns.raw` on a postgres client. Contributed as the descriptor's static `rawCodecInferer` slot. */\nexport const postgresRawCodecInferer: RawCodecInferer = {\n inferCodec(value: RawSqlLiteral): string {\n switch (typeof value) {\n case 'number':\n return Number.isSafeInteger(value) && value % 1 === 0 ? 'pg/int4' : 'pg/float8';\n case 'bigint':\n return 'pg/int8';\n case 'string':\n return 'pg/text';\n case 'boolean':\n return 'pg/bool';\n case 'object':\n if (value instanceof Uint8Array) return 'pg/bytea';\n }\n throw new Error(\n 'unsupported JS value type for raw-SQL interpolation: wrap this value in `param(...)` with an explicit codec',\n );\n },\n};\n\nexport function createPostgresAdapter(options?: PostgresAdapterOptions) {\n return Object.freeze(new PostgresAdapterImpl(options));\n}\n"],"mappings":";;;;AAkBA,MAAM,sBAAsB,OAAO,OAAO;CACxC,UAAU;EACR,SAAS;EACT,OAAO;EACP,SAAS;EACT,SAAS;EACT,WAAW;EACX,YAAY;CACd;CACA,KAAK;EACH,OAAO;EACP,WAAW;EACX,iBAAiB;EACjB,SAAS;CACX;AACF,CAAC;AAED,IAAM,sBAAN,MAEA;CAEE,WAAoB;CACpB,WAAoB;CAEpB;CACA;CAEA,YAAY,SAAkC;EAC5C,KAAK,cAAc,SAAS,eAAe,iCAAiC;EAC5E,MAAM,iBAAiB,IAAI,uBAAuB,KAAK,WAAW;EAClE,KAAK,UAAU,OAAO,OAAO;GAC3B,IAAI,SAAS,aAAa;GAC1B,QAAQ;GACR,cAAc;GACd,aAAa,cACX,eAAe,wBACb;IACE,UAAU;IACV,UAAU;IACV,OAAO,OACL,KACA,WACG;KAEH,OAAO,EAAE,MAAM,CAAC,IAAG,MADE,UAAU,MAAW,KAAK,MAAM,EAAA,CAC3B,IAAI,EAAE;IAClC;IACA,OAAO,YAAY,CAAC;GACtB,GACA,YACF;EACJ,CAAC;CACH;CAEA,MACE,KACA,SAC0B;EAC1B,IAAI,UAAU,GAAG,GACf,MAAM,IAAI,MACR,6HACF;EAEF,OAAO,iBAAiB,KAAK,QAAQ,UAAU,KAAK,WAAW;CACjE;AACF;;AAGA,MAAa,0BAA2C,EACtD,WAAW,OAA8B;CACvC,QAAQ,OAAO,OAAf;EACE,KAAK,UACH,OAAO,OAAO,cAAc,KAAK,KAAK,QAAQ,MAAM,IAAI,YAAY;EACtE,KAAK,UACH,OAAO;EACT,KAAK,UACH,OAAO;EACT,KAAK,WACH,OAAO;EACT,KAAK,UACH,IAAI,iBAAiB,YAAY,OAAO;CAC5C;CACA,MAAM,IAAI,MACR,6GACF;AACF,EACF;AAEA,SAAgB,sBAAsB,SAAkC;CACtE,OAAO,OAAO,OAAO,IAAI,oBAAoB,OAAO,CAAC;AACvD"}
|