@prisma-next/sql-runtime 0.3.0-dev.6 → 0.3.0-dev.64
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/LICENSE +201 -0
- package/README.md +137 -26
- package/dist/exports-BhZqJPVb.mjs +771 -0
- package/dist/exports-BhZqJPVb.mjs.map +1 -0
- package/dist/index-D59jqEKF.d.mts +159 -0
- package/dist/index-D59jqEKF.d.mts.map +1 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +3 -0
- package/dist/test/utils.d.mts +82 -0
- package/dist/test/utils.d.mts.map +1 -0
- package/dist/test/utils.mjs +212 -0
- package/dist/test/utils.mjs.map +1 -0
- package/package.json +32 -25
- package/src/codecs/decoding.ts +84 -3
- package/src/codecs/encoding.ts +15 -2
- package/src/codecs/json-schema-validation.ts +61 -0
- package/src/exports/index.ts +14 -6
- package/src/lower-sql-plan.ts +8 -8
- package/src/plugins/lints.ts +204 -0
- package/src/sql-context.ts +385 -98
- package/src/sql-family-adapter.ts +9 -5
- package/src/sql-marker.ts +2 -2
- package/src/sql-runtime.ts +131 -31
- package/test/async-iterable-result.test.ts +42 -34
- package/test/context.types.test-d.ts +68 -0
- package/test/execution-stack.test.ts +166 -0
- package/test/json-schema-validation.test.ts +653 -0
- package/test/lints.test.ts +330 -0
- package/test/parameterized-types.test.ts +539 -0
- package/test/sql-context.test.ts +292 -117
- package/test/sql-family-adapter.test.ts +7 -6
- package/test/sql-runtime.test.ts +218 -30
- package/test/utils.ts +80 -51
- package/dist/accelerate-EEKAFGN3-P6A6XJWJ.js +0 -137863
- package/dist/accelerate-EEKAFGN3-P6A6XJWJ.js.map +0 -1
- package/dist/amcheck-24VY6X5V.js +0 -13
- package/dist/amcheck-24VY6X5V.js.map +0 -1
- package/dist/bloom-VS74NLHT.js +0 -13
- package/dist/bloom-VS74NLHT.js.map +0 -1
- package/dist/btree_gin-WBC4EAAI.js +0 -13
- package/dist/btree_gin-WBC4EAAI.js.map +0 -1
- package/dist/btree_gist-UNC6QD3M.js +0 -13
- package/dist/btree_gist-UNC6QD3M.js.map +0 -1
- package/dist/chunk-3KTOEDFX.js +0 -49
- package/dist/chunk-3KTOEDFX.js.map +0 -1
- package/dist/chunk-47DZBRQC.js +0 -1280
- package/dist/chunk-47DZBRQC.js.map +0 -1
- package/dist/chunk-52N6AFZM.js +0 -133
- package/dist/chunk-52N6AFZM.js.map +0 -1
- package/dist/chunk-7D4SUZUM.js +0 -38
- package/dist/chunk-7D4SUZUM.js.map +0 -1
- package/dist/chunk-C6I3V3DM.js +0 -455
- package/dist/chunk-C6I3V3DM.js.map +0 -1
- package/dist/chunk-ECWIHLAT.js +0 -37
- package/dist/chunk-ECWIHLAT.js.map +0 -1
- package/dist/chunk-EI626SDC.js +0 -105
- package/dist/chunk-EI626SDC.js.map +0 -1
- package/dist/chunk-UKKOYUGL.js +0 -578
- package/dist/chunk-UKKOYUGL.js.map +0 -1
- package/dist/chunk-XPLNMXQV.js +0 -1537
- package/dist/chunk-XPLNMXQV.js.map +0 -1
- package/dist/citext-T7MXGUY7.js +0 -13
- package/dist/citext-T7MXGUY7.js.map +0 -1
- package/dist/client-5FENX6AW.js +0 -299
- package/dist/client-5FENX6AW.js.map +0 -1
- package/dist/cube-TFDQBZCI.js +0 -13
- package/dist/cube-TFDQBZCI.js.map +0 -1
- package/dist/dict_int-AEUOPGWP.js +0 -13
- package/dist/dict_int-AEUOPGWP.js.map +0 -1
- package/dist/dict_xsyn-DAAYX3FL.js +0 -13
- package/dist/dict_xsyn-DAAYX3FL.js.map +0 -1
- package/dist/dist-AQ3LWXOX.js +0 -570
- package/dist/dist-AQ3LWXOX.js.map +0 -1
- package/dist/dist-LBVX6BJW.js +0 -189
- package/dist/dist-LBVX6BJW.js.map +0 -1
- package/dist/dist-WLKUVDN2.js +0 -5127
- package/dist/dist-WLKUVDN2.js.map +0 -1
- package/dist/earthdistance-KIGTF4LE.js +0 -13
- package/dist/earthdistance-KIGTF4LE.js.map +0 -1
- package/dist/file_fdw-5N55UP6I.js +0 -13
- package/dist/file_fdw-5N55UP6I.js.map +0 -1
- package/dist/fuzzystrmatch-KN3YWBFP.js +0 -13
- package/dist/fuzzystrmatch-KN3YWBFP.js.map +0 -1
- package/dist/hstore-YX726NKN.js +0 -13
- package/dist/hstore-YX726NKN.js.map +0 -1
- package/dist/http-exception-FZY2H4OF.js +0 -8
- package/dist/http-exception-FZY2H4OF.js.map +0 -1
- package/dist/index.js +0 -30
- package/dist/index.js.map +0 -1
- package/dist/intarray-NKVXNO2D.js +0 -13
- package/dist/intarray-NKVXNO2D.js.map +0 -1
- package/dist/isn-FTEMJGEV.js +0 -13
- package/dist/isn-FTEMJGEV.js.map +0 -1
- package/dist/lo-DB7L4NGI.js +0 -13
- package/dist/lo-DB7L4NGI.js.map +0 -1
- package/dist/logger-WQ7SHNDD.js +0 -68
- package/dist/logger-WQ7SHNDD.js.map +0 -1
- package/dist/ltree-Z32TZT6W.js +0 -13
- package/dist/ltree-Z32TZT6W.js.map +0 -1
- package/dist/nodefs-NM46ACH7.js +0 -31
- package/dist/nodefs-NM46ACH7.js.map +0 -1
- package/dist/opfs-ahp-NJO33LVZ.js +0 -332
- package/dist/opfs-ahp-NJO33LVZ.js.map +0 -1
- package/dist/pageinspect-YP3IZR4X.js +0 -13
- package/dist/pageinspect-YP3IZR4X.js.map +0 -1
- package/dist/pg_buffercache-7TD5J2FB.js +0 -13
- package/dist/pg_buffercache-7TD5J2FB.js.map +0 -1
- package/dist/pg_dump-SG4KYBUB.js +0 -2492
- package/dist/pg_dump-SG4KYBUB.js.map +0 -1
- package/dist/pg_freespacemap-DZDNCPZK.js +0 -13
- package/dist/pg_freespacemap-DZDNCPZK.js.map +0 -1
- package/dist/pg_surgery-J2MUEWEP.js +0 -13
- package/dist/pg_surgery-J2MUEWEP.js.map +0 -1
- package/dist/pg_trgm-7VNQOYS6.js +0 -13
- package/dist/pg_trgm-7VNQOYS6.js.map +0 -1
- package/dist/pg_visibility-TTSIPHFL.js +0 -13
- package/dist/pg_visibility-TTSIPHFL.js.map +0 -1
- package/dist/pg_walinspect-KPFHSHRJ.js +0 -13
- package/dist/pg_walinspect-KPFHSHRJ.js.map +0 -1
- package/dist/proxy-signals-GUDAMDHV.js +0 -39
- package/dist/proxy-signals-GUDAMDHV.js.map +0 -1
- package/dist/seg-IYVDLE4O.js +0 -13
- package/dist/seg-IYVDLE4O.js.map +0 -1
- package/dist/src/codecs/decoding.d.ts +0 -4
- package/dist/src/codecs/decoding.d.ts.map +0 -1
- package/dist/src/codecs/encoding.d.ts +0 -5
- package/dist/src/codecs/encoding.d.ts.map +0 -1
- package/dist/src/codecs/validation.d.ts +0 -6
- package/dist/src/codecs/validation.d.ts.map +0 -1
- package/dist/src/exports/index.d.ts +0 -11
- package/dist/src/exports/index.d.ts.map +0 -1
- package/dist/src/index.d.ts +0 -2
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/lower-sql-plan.d.ts +0 -15
- package/dist/src/lower-sql-plan.d.ts.map +0 -1
- package/dist/src/sql-context.d.ts +0 -65
- package/dist/src/sql-context.d.ts.map +0 -1
- package/dist/src/sql-family-adapter.d.ts +0 -10
- package/dist/src/sql-family-adapter.d.ts.map +0 -1
- package/dist/src/sql-marker.d.ts +0 -22
- package/dist/src/sql-marker.d.ts.map +0 -1
- package/dist/src/sql-runtime.d.ts +0 -25
- package/dist/src/sql-runtime.d.ts.map +0 -1
- package/dist/tablefunc-EF4RCS7S.js +0 -13
- package/dist/tablefunc-EF4RCS7S.js.map +0 -1
- package/dist/tcn-3VT5BQYW.js +0 -13
- package/dist/tcn-3VT5BQYW.js.map +0 -1
- package/dist/test/utils.d.ts +0 -59
- package/dist/test/utils.d.ts.map +0 -1
- package/dist/test/utils.js +0 -24634
- package/dist/test/utils.js.map +0 -1
- package/dist/tiny-CW6F4GX6.js +0 -10
- package/dist/tiny-CW6F4GX6.js.map +0 -1
- package/dist/tsm_system_rows-ES7KNUQH.js +0 -13
- package/dist/tsm_system_rows-ES7KNUQH.js.map +0 -1
- package/dist/tsm_system_time-76WEIMBG.js +0 -13
- package/dist/tsm_system_time-76WEIMBG.js.map +0 -1
- package/dist/unaccent-7RYF3R64.js +0 -13
- package/dist/unaccent-7RYF3R64.js.map +0 -1
- package/dist/utility-Q5A254LJ-J4HTKZPT.js +0 -347
- package/dist/utility-Q5A254LJ-J4HTKZPT.js.map +0 -1
- package/dist/uuid_ossp-4ETE4FPE.js +0 -13
- package/dist/uuid_ossp-4ETE4FPE.js.map +0 -1
- package/dist/vector-74GPNV7V.js +0 -13
- package/dist/vector-74GPNV7V.js.map +0 -1
- package/src/index.ts +0 -1
package/src/sql-runtime.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { ExecutionPlan } from '@prisma-next/contract/types';
|
|
2
|
+
import type { ExecutionStackInstance } from '@prisma-next/core-execution-plane/stack';
|
|
3
|
+
import type { RuntimeDriverInstance } from '@prisma-next/core-execution-plane/types';
|
|
2
4
|
import type { OperationRegistry } from '@prisma-next/operations';
|
|
3
5
|
import type {
|
|
4
6
|
Log,
|
|
@@ -15,41 +17,90 @@ import type {
|
|
|
15
17
|
Adapter,
|
|
16
18
|
CodecRegistry,
|
|
17
19
|
LoweredStatement,
|
|
20
|
+
QueryAst,
|
|
18
21
|
SelectAst,
|
|
19
22
|
SqlDriver,
|
|
20
23
|
} from '@prisma-next/sql-relational-core/ast';
|
|
21
24
|
import type { SqlQueryPlan } from '@prisma-next/sql-relational-core/plan';
|
|
25
|
+
import type { JsonSchemaValidatorRegistry } from '@prisma-next/sql-relational-core/query-lane-context';
|
|
26
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
22
27
|
import { decodeRow } from './codecs/decoding';
|
|
23
28
|
import { encodeParams } from './codecs/encoding';
|
|
24
29
|
import { validateCodecRegistryCompleteness } from './codecs/validation';
|
|
25
30
|
import { lowerSqlPlan } from './lower-sql-plan';
|
|
26
|
-
import type {
|
|
31
|
+
import type {
|
|
32
|
+
ExecutionContext,
|
|
33
|
+
SqlRuntimeAdapterInstance,
|
|
34
|
+
SqlRuntimeExtensionInstance,
|
|
35
|
+
} from './sql-context';
|
|
27
36
|
import { SqlFamilyAdapter } from './sql-family-adapter';
|
|
28
37
|
|
|
29
38
|
export interface RuntimeOptions<
|
|
30
39
|
TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
|
|
31
40
|
> {
|
|
32
|
-
readonly
|
|
41
|
+
readonly context: ExecutionContext<TContract>;
|
|
42
|
+
readonly adapter: Adapter<QueryAst, SqlContract<SqlStorage>, LoweredStatement>;
|
|
43
|
+
readonly driver: SqlDriver<unknown>;
|
|
33
44
|
readonly verify: RuntimeVerifyOptions;
|
|
34
|
-
readonly context: RuntimeContext<TContract>;
|
|
35
45
|
readonly plugins?: readonly Plugin<
|
|
36
46
|
TContract,
|
|
37
47
|
Adapter<SelectAst, SqlContract<SqlStorage>, LoweredStatement>,
|
|
38
|
-
SqlDriver
|
|
48
|
+
SqlDriver<unknown>
|
|
39
49
|
>[];
|
|
40
50
|
readonly mode?: 'strict' | 'permissive';
|
|
41
51
|
readonly log?: Log;
|
|
42
52
|
}
|
|
43
53
|
|
|
44
|
-
export interface
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
54
|
+
export interface CreateRuntimeOptions<
|
|
55
|
+
TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
|
|
56
|
+
TTargetId extends string = string,
|
|
57
|
+
> {
|
|
58
|
+
readonly stackInstance: ExecutionStackInstance<
|
|
59
|
+
'sql',
|
|
60
|
+
TTargetId,
|
|
61
|
+
SqlRuntimeAdapterInstance<TTargetId>,
|
|
62
|
+
RuntimeDriverInstance<'sql', TTargetId>,
|
|
63
|
+
SqlRuntimeExtensionInstance<TTargetId>
|
|
64
|
+
>;
|
|
65
|
+
readonly context: ExecutionContext<TContract>;
|
|
66
|
+
readonly driver: SqlDriver<unknown>;
|
|
67
|
+
readonly verify: RuntimeVerifyOptions;
|
|
68
|
+
readonly plugins?: readonly Plugin<
|
|
69
|
+
TContract,
|
|
70
|
+
Adapter<SelectAst, SqlContract<SqlStorage>, LoweredStatement>,
|
|
71
|
+
SqlDriver<unknown>
|
|
72
|
+
>[];
|
|
73
|
+
readonly mode?: 'strict' | 'permissive';
|
|
74
|
+
readonly log?: Log;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface Runtime extends RuntimeQueryable {
|
|
78
|
+
connection(): Promise<RuntimeConnection>;
|
|
48
79
|
telemetry(): RuntimeTelemetryEvent | null;
|
|
49
80
|
close(): Promise<void>;
|
|
50
81
|
operations(): OperationRegistry;
|
|
51
82
|
}
|
|
52
83
|
|
|
84
|
+
export interface RuntimeConnection extends RuntimeQueryable {
|
|
85
|
+
transaction(): Promise<RuntimeTransaction>;
|
|
86
|
+
release(): Promise<void>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface RuntimeTransaction extends RuntimeQueryable {
|
|
90
|
+
commit(): Promise<void>;
|
|
91
|
+
rollback(): Promise<void>;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface RuntimeQueryable {
|
|
95
|
+
execute<Row = Record<string, unknown>>(
|
|
96
|
+
plan: ExecutionPlan<Row> | SqlQueryPlan<Row>,
|
|
97
|
+
): AsyncIterableResult<Row>;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
interface CoreQueryable {
|
|
101
|
+
execute<Row = Record<string, unknown>>(plan: ExecutionPlan<Row>): AsyncIterableResult<Row>;
|
|
102
|
+
}
|
|
103
|
+
|
|
53
104
|
export type { RuntimeTelemetryEvent, RuntimeVerifyOptions, TelemetryOutcome };
|
|
54
105
|
|
|
55
106
|
class SqlRuntimeImpl<TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>>
|
|
@@ -58,18 +109,20 @@ class SqlRuntimeImpl<TContract extends SqlContract<SqlStorage> = SqlContract<Sql
|
|
|
58
109
|
private readonly core: RuntimeCore<
|
|
59
110
|
TContract,
|
|
60
111
|
Adapter<SelectAst, SqlContract<SqlStorage>, LoweredStatement>,
|
|
61
|
-
SqlDriver
|
|
112
|
+
SqlDriver<unknown>
|
|
62
113
|
>;
|
|
63
114
|
private readonly contract: TContract;
|
|
64
|
-
private readonly
|
|
115
|
+
private readonly adapter: Adapter<QueryAst, SqlContract<SqlStorage>, LoweredStatement>;
|
|
65
116
|
private readonly codecRegistry: CodecRegistry;
|
|
117
|
+
private readonly jsonSchemaValidators: JsonSchemaValidatorRegistry | undefined;
|
|
66
118
|
private codecRegistryValidated: boolean;
|
|
67
119
|
|
|
68
120
|
constructor(options: RuntimeOptions<TContract>) {
|
|
69
|
-
const { context, driver, verify, plugins, mode, log } = options;
|
|
121
|
+
const { context, adapter, driver, verify, plugins, mode, log } = options;
|
|
70
122
|
this.contract = context.contract;
|
|
71
|
-
this.
|
|
123
|
+
this.adapter = adapter;
|
|
72
124
|
this.codecRegistry = context.codecs;
|
|
125
|
+
this.jsonSchemaValidators = context.jsonSchemaValidators;
|
|
73
126
|
this.codecRegistryValidated = false;
|
|
74
127
|
|
|
75
128
|
const familyAdapter = new SqlFamilyAdapter(context.contract);
|
|
@@ -77,7 +130,7 @@ class SqlRuntimeImpl<TContract extends SqlContract<SqlStorage> = SqlContract<Sql
|
|
|
77
130
|
const coreOptions: RuntimeCoreOptions<
|
|
78
131
|
TContract,
|
|
79
132
|
Adapter<SelectAst, SqlContract<SqlStorage>, LoweredStatement>,
|
|
80
|
-
SqlDriver
|
|
133
|
+
SqlDriver<unknown>
|
|
81
134
|
> = {
|
|
82
135
|
familyAdapter,
|
|
83
136
|
driver,
|
|
@@ -85,10 +138,10 @@ class SqlRuntimeImpl<TContract extends SqlContract<SqlStorage> = SqlContract<Sql
|
|
|
85
138
|
plugins: plugins as readonly Plugin<
|
|
86
139
|
TContract,
|
|
87
140
|
Adapter<SelectAst, SqlContract<SqlStorage>, LoweredStatement>,
|
|
88
|
-
SqlDriver
|
|
141
|
+
SqlDriver<unknown>
|
|
89
142
|
>[],
|
|
90
|
-
...(mode
|
|
91
|
-
...(log
|
|
143
|
+
...ifDefined('mode', mode),
|
|
144
|
+
...ifDefined('log', log),
|
|
92
145
|
operationRegistry: context.operations,
|
|
93
146
|
};
|
|
94
147
|
|
|
@@ -107,37 +160,42 @@ class SqlRuntimeImpl<TContract extends SqlContract<SqlStorage> = SqlContract<Sql
|
|
|
107
160
|
}
|
|
108
161
|
}
|
|
109
162
|
|
|
110
|
-
|
|
111
|
-
plan: ExecutionPlan<Row> | SqlQueryPlan<Row>,
|
|
112
|
-
): AsyncIterableResult<Row> {
|
|
113
|
-
this.ensureCodecRegistryValidated(this.contract);
|
|
114
|
-
|
|
115
|
-
// Check if plan is SqlQueryPlan (has ast but no sql)
|
|
163
|
+
private toExecutionPlan<Row>(plan: ExecutionPlan<Row> | SqlQueryPlan<Row>): ExecutionPlan<Row> {
|
|
116
164
|
const isSqlQueryPlan = (p: ExecutionPlan<Row> | SqlQueryPlan<Row>): p is SqlQueryPlan<Row> => {
|
|
117
165
|
return 'ast' in p && !('sql' in p);
|
|
118
166
|
};
|
|
119
167
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
168
|
+
return isSqlQueryPlan(plan) ? lowerSqlPlan(this.adapter, this.contract, plan) : plan;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private executeAgainstQueryable<Row = Record<string, unknown>>(
|
|
172
|
+
plan: ExecutionPlan<Row> | SqlQueryPlan<Row>,
|
|
173
|
+
queryable: CoreQueryable,
|
|
174
|
+
): AsyncIterableResult<Row> {
|
|
175
|
+
this.ensureCodecRegistryValidated(this.contract);
|
|
176
|
+
const executablePlan = this.toExecutionPlan(plan);
|
|
124
177
|
|
|
125
178
|
const iterator = async function* (
|
|
126
179
|
self: SqlRuntimeImpl<TContract>,
|
|
127
180
|
): AsyncGenerator<Row, void, unknown> {
|
|
128
|
-
const encodedParams = encodeParams(
|
|
181
|
+
const encodedParams = encodeParams(
|
|
182
|
+
executablePlan,
|
|
183
|
+
self.codecRegistry,
|
|
184
|
+
self.jsonSchemaValidators,
|
|
185
|
+
);
|
|
129
186
|
const planWithEncodedParams: ExecutionPlan<Row> = {
|
|
130
187
|
...executablePlan,
|
|
131
188
|
params: encodedParams,
|
|
132
189
|
};
|
|
133
190
|
|
|
134
|
-
const coreIterator =
|
|
191
|
+
const coreIterator = queryable.execute(planWithEncodedParams);
|
|
135
192
|
|
|
136
193
|
for await (const rawRow of coreIterator) {
|
|
137
194
|
const decodedRow = decodeRow(
|
|
138
195
|
rawRow as Record<string, unknown>,
|
|
139
196
|
executablePlan,
|
|
140
197
|
self.codecRegistry,
|
|
198
|
+
self.jsonSchemaValidators,
|
|
141
199
|
);
|
|
142
200
|
yield decodedRow as Row;
|
|
143
201
|
}
|
|
@@ -146,6 +204,38 @@ class SqlRuntimeImpl<TContract extends SqlContract<SqlStorage> = SqlContract<Sql
|
|
|
146
204
|
return new AsyncIterableResult(iterator(this));
|
|
147
205
|
}
|
|
148
206
|
|
|
207
|
+
execute<Row = Record<string, unknown>>(
|
|
208
|
+
plan: ExecutionPlan<Row> | SqlQueryPlan<Row>,
|
|
209
|
+
): AsyncIterableResult<Row> {
|
|
210
|
+
return this.executeAgainstQueryable(plan, this.core);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async connection(): Promise<RuntimeConnection> {
|
|
214
|
+
const coreConn = await this.core.connection();
|
|
215
|
+
const self = this;
|
|
216
|
+
const wrappedConnection: RuntimeConnection = {
|
|
217
|
+
async transaction(): Promise<RuntimeTransaction> {
|
|
218
|
+
const coreTx = await coreConn.transaction();
|
|
219
|
+
return {
|
|
220
|
+
commit: coreTx.commit.bind(coreTx),
|
|
221
|
+
rollback: coreTx.rollback.bind(coreTx),
|
|
222
|
+
execute<Row = Record<string, unknown>>(
|
|
223
|
+
plan: ExecutionPlan<Row> | SqlQueryPlan<Row>,
|
|
224
|
+
): AsyncIterableResult<Row> {
|
|
225
|
+
return self.executeAgainstQueryable(plan, coreTx);
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
},
|
|
229
|
+
release: coreConn.release.bind(coreConn),
|
|
230
|
+
execute<Row = Record<string, unknown>>(
|
|
231
|
+
plan: ExecutionPlan<Row> | SqlQueryPlan<Row>,
|
|
232
|
+
): AsyncIterableResult<Row> {
|
|
233
|
+
return self.executeAgainstQueryable(plan, coreConn);
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
return wrappedConnection;
|
|
237
|
+
}
|
|
238
|
+
|
|
149
239
|
telemetry(): RuntimeTelemetryEvent | null {
|
|
150
240
|
return this.core.telemetry();
|
|
151
241
|
}
|
|
@@ -159,8 +249,18 @@ class SqlRuntimeImpl<TContract extends SqlContract<SqlStorage> = SqlContract<Sql
|
|
|
159
249
|
}
|
|
160
250
|
}
|
|
161
251
|
|
|
162
|
-
export function createRuntime<TContract extends SqlContract<SqlStorage
|
|
163
|
-
options:
|
|
252
|
+
export function createRuntime<TContract extends SqlContract<SqlStorage>, TTargetId extends string>(
|
|
253
|
+
options: CreateRuntimeOptions<TContract, TTargetId>,
|
|
164
254
|
): Runtime {
|
|
165
|
-
|
|
255
|
+
const { stackInstance, context, driver, verify, plugins, mode, log } = options;
|
|
256
|
+
|
|
257
|
+
return new SqlRuntimeImpl({
|
|
258
|
+
context,
|
|
259
|
+
adapter: stackInstance.adapter,
|
|
260
|
+
driver,
|
|
261
|
+
verify,
|
|
262
|
+
...ifDefined('plugins', plugins),
|
|
263
|
+
...ifDefined('mode', mode),
|
|
264
|
+
...ifDefined('log', log),
|
|
265
|
+
});
|
|
166
266
|
}
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import type { ExecutionPlan } from '@prisma-next/contract/types';
|
|
2
|
+
import { instantiateExecutionStack } from '@prisma-next/core-execution-plane/stack';
|
|
2
3
|
import type { AsyncIterableResult } from '@prisma-next/runtime-executor';
|
|
3
4
|
import { describe, expect, it } from 'vitest';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
5
|
+
import type { Runtime } from '../src/exports';
|
|
6
|
+
import { createRuntime, createSqlExecutionStack } from '../src/exports';
|
|
7
|
+
import {
|
|
8
|
+
createStubAdapter,
|
|
9
|
+
createTestAdapterDescriptor,
|
|
10
|
+
createTestContext,
|
|
11
|
+
createTestContract,
|
|
12
|
+
createTestTargetDescriptor,
|
|
13
|
+
} from './utils';
|
|
6
14
|
|
|
7
|
-
// Mock driver that implements SqlDriver interface
|
|
8
15
|
class MockDriver {
|
|
9
16
|
private rows: ReadonlyArray<Record<string, unknown>> = [];
|
|
10
17
|
|
|
@@ -12,11 +19,10 @@ class MockDriver {
|
|
|
12
19
|
this.rows = rows;
|
|
13
20
|
}
|
|
14
21
|
|
|
15
|
-
async query(
|
|
22
|
+
async query<Row = Record<string, unknown>>(
|
|
16
23
|
_sql: string,
|
|
17
|
-
_params
|
|
18
|
-
): Promise<{ rows: ReadonlyArray<
|
|
19
|
-
// Return empty marker result for contract verification
|
|
24
|
+
_params?: readonly unknown[],
|
|
25
|
+
): Promise<{ rows: ReadonlyArray<Row> }> {
|
|
20
26
|
return { rows: [] };
|
|
21
27
|
}
|
|
22
28
|
|
|
@@ -29,20 +35,20 @@ class MockDriver {
|
|
|
29
35
|
}
|
|
30
36
|
}
|
|
31
37
|
|
|
32
|
-
async
|
|
33
|
-
|
|
38
|
+
async acquireConnection(): Promise<never> {
|
|
39
|
+
throw new Error('Not implemented in mock');
|
|
34
40
|
}
|
|
35
41
|
|
|
36
|
-
async
|
|
37
|
-
|
|
38
|
-
}
|
|
42
|
+
async connect(): Promise<void> {}
|
|
43
|
+
|
|
44
|
+
async close(): Promise<void> {}
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
const fixtureContract = createTestContract({
|
|
42
48
|
schemaVersion: '1',
|
|
43
49
|
targetFamily: 'sql',
|
|
44
50
|
target: 'postgres',
|
|
45
|
-
|
|
51
|
+
storageHash: 'test-hash',
|
|
46
52
|
profileHash: 'test-profile-hash',
|
|
47
53
|
storage: {
|
|
48
54
|
tables: {
|
|
@@ -62,20 +68,31 @@ const fixtureContract = createTestContract({
|
|
|
62
68
|
mappings: { codecTypes: {}, operationTypes: {} },
|
|
63
69
|
});
|
|
64
70
|
|
|
71
|
+
function createTestRuntime(mockDriver: MockDriver): Runtime {
|
|
72
|
+
const adapter = createStubAdapter();
|
|
73
|
+
const stack = createSqlExecutionStack({
|
|
74
|
+
target: createTestTargetDescriptor(),
|
|
75
|
+
adapter: createTestAdapterDescriptor(adapter),
|
|
76
|
+
extensionPacks: [],
|
|
77
|
+
});
|
|
78
|
+
const stackInstance = instantiateExecutionStack(stack);
|
|
79
|
+
const context = createTestContext(fixtureContract, adapter);
|
|
80
|
+
return createRuntime({
|
|
81
|
+
stackInstance,
|
|
82
|
+
context,
|
|
83
|
+
driver: mockDriver,
|
|
84
|
+
verify: { mode: 'onFirstUse', requireMarker: false },
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
65
88
|
describe('SqlRuntime AsyncIterableResult integration', () => {
|
|
66
89
|
it('returns AsyncIterableResult from execute', async () => {
|
|
67
|
-
const adapter = createStubAdapter();
|
|
68
90
|
const driver = new MockDriver();
|
|
69
91
|
driver.setRows([
|
|
70
92
|
{ id: 1, email: 'test1@example.com' },
|
|
71
93
|
{ id: 2, email: 'test2@example.com' },
|
|
72
94
|
]);
|
|
73
|
-
const
|
|
74
|
-
const runtime = createRuntime({
|
|
75
|
-
driver: driver as unknown as Parameters<typeof createRuntime>[0]['driver'],
|
|
76
|
-
context,
|
|
77
|
-
verify: { mode: 'onFirstUse', requireMarker: false },
|
|
78
|
-
});
|
|
95
|
+
const runtime = createTestRuntime(driver);
|
|
79
96
|
|
|
80
97
|
const plan: ExecutionPlan<{ id: number; email: string }> = {
|
|
81
98
|
sql: 'SELECT id, email FROM "user" ORDER BY id',
|
|
@@ -83,7 +100,7 @@ describe('SqlRuntime AsyncIterableResult integration', () => {
|
|
|
83
100
|
meta: {
|
|
84
101
|
target: 'postgres',
|
|
85
102
|
targetFamily: 'sql',
|
|
86
|
-
|
|
103
|
+
storageHash: 'test-hash',
|
|
87
104
|
lane: 'sql',
|
|
88
105
|
paramDescriptors: [],
|
|
89
106
|
},
|
|
@@ -91,7 +108,6 @@ describe('SqlRuntime AsyncIterableResult integration', () => {
|
|
|
91
108
|
|
|
92
109
|
const result = runtime.execute(plan);
|
|
93
110
|
|
|
94
|
-
// Verify it's an AsyncIterableResult
|
|
95
111
|
expect(result).toBeInstanceOf(Object);
|
|
96
112
|
expect(typeof result.toArray).toBe('function');
|
|
97
113
|
expect(typeof result[Symbol.asyncIterator]).toBe('function');
|
|
@@ -100,15 +116,9 @@ describe('SqlRuntime AsyncIterableResult integration', () => {
|
|
|
100
116
|
});
|
|
101
117
|
|
|
102
118
|
it('preserves type information', async () => {
|
|
103
|
-
const adapter = createStubAdapter();
|
|
104
119
|
const driver = new MockDriver();
|
|
105
120
|
driver.setRows([{ id: 1, email: 'test@example.com' }]);
|
|
106
|
-
const
|
|
107
|
-
const runtime = createRuntime({
|
|
108
|
-
driver: driver as unknown as Parameters<typeof createRuntime>[0]['driver'],
|
|
109
|
-
context,
|
|
110
|
-
verify: { mode: 'onFirstUse', requireMarker: false },
|
|
111
|
-
});
|
|
121
|
+
const runtime = createTestRuntime(driver);
|
|
112
122
|
|
|
113
123
|
const plan: ExecutionPlan<{ id: number; email: string }> = {
|
|
114
124
|
sql: 'SELECT id, email FROM "user" LIMIT 1',
|
|
@@ -116,7 +126,7 @@ describe('SqlRuntime AsyncIterableResult integration', () => {
|
|
|
116
126
|
meta: {
|
|
117
127
|
target: 'postgres',
|
|
118
128
|
targetFamily: 'sql',
|
|
119
|
-
|
|
129
|
+
storageHash: 'test-hash',
|
|
120
130
|
lane: 'sql',
|
|
121
131
|
paramDescriptors: [],
|
|
122
132
|
},
|
|
@@ -126,10 +136,8 @@ describe('SqlRuntime AsyncIterableResult integration', () => {
|
|
|
126
136
|
const rows = await result.toArray();
|
|
127
137
|
|
|
128
138
|
expect(rows.length).toBe(1);
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
expect(typeof rows[0].email).toBe('string');
|
|
132
|
-
}
|
|
139
|
+
expect(typeof rows[0]!.id).toBe('number');
|
|
140
|
+
expect(typeof rows[0]!.email).toBe('string');
|
|
133
141
|
|
|
134
142
|
await runtime.close();
|
|
135
143
|
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { SqlContract, SqlMappings, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
2
|
+
import { expectTypeOf, test } from 'vitest';
|
|
3
|
+
import type { ExecutionContext, TypeHelperRegistry } from '../src/sql-context';
|
|
4
|
+
|
|
5
|
+
// Contract type with storage.types using literal types (matching emission output)
|
|
6
|
+
type TestContract = SqlContract<
|
|
7
|
+
{
|
|
8
|
+
readonly tables: {
|
|
9
|
+
readonly document: {
|
|
10
|
+
readonly columns: {
|
|
11
|
+
readonly id: {
|
|
12
|
+
readonly nativeType: 'int4';
|
|
13
|
+
readonly codecId: 'pg/int4@1';
|
|
14
|
+
nullable: false;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
readonly primaryKey: { readonly columns: readonly ['id'] };
|
|
18
|
+
readonly uniques: readonly [];
|
|
19
|
+
readonly indexes: readonly [];
|
|
20
|
+
readonly foreignKeys: readonly [];
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
readonly types: {
|
|
24
|
+
readonly Vector1536: {
|
|
25
|
+
readonly codecId: 'pg/vector@1';
|
|
26
|
+
readonly nativeType: 'vector';
|
|
27
|
+
readonly typeParams: { readonly length: 1536 };
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
Record<string, never>,
|
|
32
|
+
Record<string, never>,
|
|
33
|
+
SqlMappings
|
|
34
|
+
>;
|
|
35
|
+
|
|
36
|
+
test('ExecutionContext.types is TypeHelperRegistry', () => {
|
|
37
|
+
// ExecutionContext.types is intentionally loose (Record<string, unknown>)
|
|
38
|
+
// The strong typing comes from schema(context).types via ExtractSchemaTypes
|
|
39
|
+
expectTypeOf<ExecutionContext<TestContract>['types']>().toEqualTypeOf<TypeHelperRegistry>();
|
|
40
|
+
|
|
41
|
+
// TypeHelperRegistry allows any values - the actual type depends on init hooks
|
|
42
|
+
expectTypeOf<TypeHelperRegistry>().toEqualTypeOf<Record<string, unknown>>();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('ExecutionContext preserves contract type parameter', () => {
|
|
46
|
+
// Verify the contract type is preserved in ExecutionContext
|
|
47
|
+
expectTypeOf<ExecutionContext<TestContract>['contract']>().toEqualTypeOf<TestContract>();
|
|
48
|
+
|
|
49
|
+
// Verify we can access storage.types through the context's contract
|
|
50
|
+
type ContractStorageTypes = ExecutionContext<TestContract>['contract']['storage']['types'];
|
|
51
|
+
expectTypeOf<ContractStorageTypes>().toExtend<
|
|
52
|
+
| {
|
|
53
|
+
readonly Vector1536: {
|
|
54
|
+
readonly codecId: 'pg/vector@1';
|
|
55
|
+
readonly nativeType: 'vector';
|
|
56
|
+
readonly typeParams: { readonly length: 1536 };
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
| undefined
|
|
60
|
+
>();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('ExecutionContext accepts generic SqlContract', () => {
|
|
64
|
+
// Verify ExecutionContext defaults work
|
|
65
|
+
type DefaultContext = ExecutionContext;
|
|
66
|
+
expectTypeOf<DefaultContext['contract']>().toExtend<SqlContract<SqlStorage>>();
|
|
67
|
+
expectTypeOf<DefaultContext['types']>().toEqualTypeOf<TypeHelperRegistry>();
|
|
68
|
+
});
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { createExecutionStack } from '@prisma-next/core-execution-plane/stack';
|
|
2
|
+
import { codec, createCodecRegistry } from '@prisma-next/sql-relational-core/ast';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
import { createExecutionContext, createSqlExecutionStack } from '../src/exports';
|
|
5
|
+
import type {
|
|
6
|
+
ExecutionContext,
|
|
7
|
+
SqlRuntimeAdapterDescriptor,
|
|
8
|
+
SqlRuntimeExtensionDescriptor,
|
|
9
|
+
SqlRuntimeTargetDescriptor,
|
|
10
|
+
} from '../src/sql-context';
|
|
11
|
+
import { createTestContract } from './utils';
|
|
12
|
+
|
|
13
|
+
function createStubAdapterDescriptor(): SqlRuntimeAdapterDescriptor<'postgres'> {
|
|
14
|
+
const registry = createCodecRegistry();
|
|
15
|
+
registry.register(
|
|
16
|
+
codec({
|
|
17
|
+
typeId: 'pg/text@1',
|
|
18
|
+
targetTypes: ['text'],
|
|
19
|
+
encode: (value: string) => value,
|
|
20
|
+
decode: (wire: string) => wire,
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
kind: 'adapter',
|
|
26
|
+
id: 'test-adapter',
|
|
27
|
+
version: '0.0.1',
|
|
28
|
+
familyId: 'sql' as const,
|
|
29
|
+
targetId: 'postgres' as const,
|
|
30
|
+
codecs: () => registry,
|
|
31
|
+
operationSignatures: () => [],
|
|
32
|
+
parameterizedCodecs: () => [],
|
|
33
|
+
create() {
|
|
34
|
+
return Object.assign(
|
|
35
|
+
{ familyId: 'sql' as const, targetId: 'postgres' as const },
|
|
36
|
+
{
|
|
37
|
+
profile: {
|
|
38
|
+
id: 'test-profile',
|
|
39
|
+
target: 'postgres',
|
|
40
|
+
capabilities: {},
|
|
41
|
+
codecs: () => registry,
|
|
42
|
+
},
|
|
43
|
+
lower() {
|
|
44
|
+
return {
|
|
45
|
+
profileId: 'test-profile',
|
|
46
|
+
body: Object.freeze({ sql: '', params: [] }),
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function createStubTargetDescriptor(): SqlRuntimeTargetDescriptor<'postgres'> {
|
|
56
|
+
return {
|
|
57
|
+
kind: 'target',
|
|
58
|
+
id: 'postgres',
|
|
59
|
+
version: '0.0.1',
|
|
60
|
+
familyId: 'sql' as const,
|
|
61
|
+
targetId: 'postgres' as const,
|
|
62
|
+
codecs: () => createCodecRegistry(),
|
|
63
|
+
operationSignatures: () => [],
|
|
64
|
+
parameterizedCodecs: () => [],
|
|
65
|
+
create() {
|
|
66
|
+
return { familyId: 'sql' as const, targetId: 'postgres' as const };
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function createStubExtensionDescriptor(): SqlRuntimeExtensionDescriptor<'postgres'> {
|
|
72
|
+
const registry = createCodecRegistry();
|
|
73
|
+
registry.register(
|
|
74
|
+
codec({
|
|
75
|
+
typeId: 'pg/uuid@1',
|
|
76
|
+
targetTypes: ['uuid'],
|
|
77
|
+
encode: (value: string) => value,
|
|
78
|
+
decode: (wire: string) => wire,
|
|
79
|
+
}),
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const operations = [
|
|
83
|
+
{
|
|
84
|
+
forTypeId: 'pg/text@1',
|
|
85
|
+
method: 'example',
|
|
86
|
+
args: [],
|
|
87
|
+
returns: { kind: 'builtin' as const, type: 'string' as const },
|
|
88
|
+
lowering: {
|
|
89
|
+
targetFamily: 'sql' as const,
|
|
90
|
+
strategy: 'function' as const,
|
|
91
|
+
template: 'example({args})',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
];
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
kind: 'extension',
|
|
98
|
+
id: 'test-extension',
|
|
99
|
+
version: '0.0.1',
|
|
100
|
+
familyId: 'sql' as const,
|
|
101
|
+
targetId: 'postgres' as const,
|
|
102
|
+
codecs: () => registry,
|
|
103
|
+
operationSignatures: () => operations,
|
|
104
|
+
parameterizedCodecs: () => [],
|
|
105
|
+
create() {
|
|
106
|
+
return {
|
|
107
|
+
familyId: 'sql' as const,
|
|
108
|
+
targetId: 'postgres' as const,
|
|
109
|
+
};
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
describe('createExecutionStack', () => {
|
|
115
|
+
it('defaults driver to undefined and extensions to empty', () => {
|
|
116
|
+
const stack = createExecutionStack({
|
|
117
|
+
target: createStubTargetDescriptor(),
|
|
118
|
+
adapter: createStubAdapterDescriptor(),
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
expect(stack.driver).toBeUndefined();
|
|
122
|
+
expect(stack.extensionPacks).toEqual([]);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('creates an execution context from descriptors-only stack', () => {
|
|
126
|
+
const contract = createTestContract({
|
|
127
|
+
storage: { tables: {} },
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const context = createExecutionContext({
|
|
131
|
+
contract,
|
|
132
|
+
stack: {
|
|
133
|
+
target: createStubTargetDescriptor(),
|
|
134
|
+
adapter: createStubAdapterDescriptor(),
|
|
135
|
+
extensionPacks: [createStubExtensionDescriptor()],
|
|
136
|
+
},
|
|
137
|
+
}) as ExecutionContext<typeof contract>;
|
|
138
|
+
|
|
139
|
+
expect(context.contract).toBe(contract);
|
|
140
|
+
expect(context.codecs.get('pg/text@1')).toBeDefined();
|
|
141
|
+
expect(context.codecs.get('pg/uuid@1')).toBeDefined();
|
|
142
|
+
expect(context.operations.byType('pg/text@1')).toHaveLength(1);
|
|
143
|
+
expect(context.types).toEqual({});
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe('createSqlExecutionStack', () => {
|
|
148
|
+
it('preserves descriptor references and defaults extensions', () => {
|
|
149
|
+
const target = createStubTargetDescriptor();
|
|
150
|
+
const adapter = createStubAdapterDescriptor();
|
|
151
|
+
const stack = createSqlExecutionStack({ target, adapter });
|
|
152
|
+
|
|
153
|
+
expect(stack.target).toBe(target);
|
|
154
|
+
expect(stack.adapter).toBe(adapter);
|
|
155
|
+
expect(stack.extensionPacks).toEqual([]);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('keeps extension packs intact', () => {
|
|
159
|
+
const target = createStubTargetDescriptor();
|
|
160
|
+
const adapter = createStubAdapterDescriptor();
|
|
161
|
+
const extension = createStubExtensionDescriptor();
|
|
162
|
+
const stack = createSqlExecutionStack({ target, adapter, extensionPacks: [extension] });
|
|
163
|
+
|
|
164
|
+
expect(stack.extensionPacks).toEqual([extension]);
|
|
165
|
+
});
|
|
166
|
+
});
|