@prisma/client-engine-runtime 7.5.0-dev.3 → 7.5.0-dev.31
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/events.d.ts +1 -1
- package/dist/index.d.mts +24 -10
- package/dist/index.d.ts +24 -10
- package/dist/index.js +227 -31
- package/dist/index.mjs +226 -30
- package/dist/interpreter/in-memory-processing.d.ts +1 -1
- package/dist/interpreter/query-interpreter.d.ts +2 -1
- package/dist/interpreter/render-query.d.ts +2 -1
- package/dist/interpreter/validation.d.ts +2 -1
- package/dist/json-protocol.d.ts +6 -2
- package/dist/query-plan.d.ts +10 -6
- package/dist/tracing.d.ts +2 -1
- package/dist/transaction-manager/transaction.d.ts +1 -0
- package/dist/utils.d.ts +6 -0
- package/package.json +7 -10
package/dist/events.d.ts
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -80,7 +80,11 @@ export declare type DecimalTaggedValue = {
|
|
|
80
80
|
value: string;
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
declare type DeepReadonly<T> = T extends undefined | null | boolean | string | number | symbol | Function | Date ? T : T extends Array<infer U> ? ReadonlyArray<DeepReadonly<U>> : unknown extends T ? unknown : {
|
|
84
|
+
readonly [K in keyof T]: DeepReadonly<T[K]>;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export declare function deserializeJsonObject(result: unknown): unknown;
|
|
84
88
|
|
|
85
89
|
/**
|
|
86
90
|
* Checks if two objects representing the names and values of key columns match. A match is
|
|
@@ -155,6 +159,9 @@ export declare type Fragment = {
|
|
|
155
159
|
type: 'parameter';
|
|
156
160
|
} | {
|
|
157
161
|
type: 'parameterTuple';
|
|
162
|
+
itemPrefix: string;
|
|
163
|
+
itemSeparator: string;
|
|
164
|
+
itemSuffix: string;
|
|
158
165
|
} | {
|
|
159
166
|
type: 'parameterTupleList';
|
|
160
167
|
itemPrefix: string;
|
|
@@ -187,7 +194,7 @@ export declare type JoinExpression = {
|
|
|
187
194
|
isRelationUnique: boolean;
|
|
188
195
|
};
|
|
189
196
|
|
|
190
|
-
export declare type JsonInputTaggedValue = DateTaggedValue | DecimalTaggedValue | BytesTaggedValue | BigIntTaggedValue | FieldRefTaggedValue | JsonTaggedValue | EnumTaggedValue;
|
|
197
|
+
export declare type JsonInputTaggedValue = DateTaggedValue | DecimalTaggedValue | BytesTaggedValue | BigIntTaggedValue | FieldRefTaggedValue | JsonTaggedValue | EnumTaggedValue | RawTaggedValue;
|
|
191
198
|
|
|
192
199
|
export declare type JsonOutputTaggedValue = DateTaggedValue | DecimalTaggedValue | BytesTaggedValue | BigIntTaggedValue | JsonTaggedValue;
|
|
193
200
|
|
|
@@ -243,7 +250,7 @@ export declare type PrismaValuePlaceholder = {
|
|
|
243
250
|
export declare type QueryEvent = {
|
|
244
251
|
timestamp: Date;
|
|
245
252
|
query: string;
|
|
246
|
-
params: unknown[];
|
|
253
|
+
params: readonly unknown[];
|
|
247
254
|
duration: number;
|
|
248
255
|
};
|
|
249
256
|
|
|
@@ -256,7 +263,7 @@ export declare class QueryInterpreter {
|
|
|
256
263
|
provider?: SchemaProvider;
|
|
257
264
|
connectionInfo?: ConnectionInfo;
|
|
258
265
|
}): QueryInterpreter;
|
|
259
|
-
run(queryPlan: QueryPlanNode
|
|
266
|
+
run(queryPlan: DeepReadonly<QueryPlanNode>, options: QueryRuntimeOptions): Promise<unknown>;
|
|
260
267
|
private interpretNode;
|
|
261
268
|
}
|
|
262
269
|
|
|
@@ -348,6 +355,7 @@ export declare type QueryPlanNode = {
|
|
|
348
355
|
args: {
|
|
349
356
|
parent: QueryPlanNode;
|
|
350
357
|
children: JoinExpression[];
|
|
358
|
+
canAssumeStrictEquality: boolean;
|
|
351
359
|
};
|
|
352
360
|
} | {
|
|
353
361
|
type: 'mapField';
|
|
@@ -421,6 +429,11 @@ export declare type RawResponse = {
|
|
|
421
429
|
rows: unknown[][];
|
|
422
430
|
};
|
|
423
431
|
|
|
432
|
+
export declare type RawTaggedValue = {
|
|
433
|
+
$type: 'Raw';
|
|
434
|
+
value: unknown;
|
|
435
|
+
};
|
|
436
|
+
|
|
424
437
|
export declare type ResultNode = {
|
|
425
438
|
type: 'affectedRows';
|
|
426
439
|
} | {
|
|
@@ -492,6 +505,7 @@ export declare type TransactionOptions = {
|
|
|
492
505
|
maxWait?: number;
|
|
493
506
|
timeout?: number;
|
|
494
507
|
isolationLevel?: IsolationLevel;
|
|
508
|
+
newTxId?: string;
|
|
495
509
|
};
|
|
496
510
|
|
|
497
511
|
export declare class UserFacingError extends Error {
|
|
@@ -511,14 +525,14 @@ export declare class UserFacingError extends Error {
|
|
|
511
525
|
}
|
|
512
526
|
|
|
513
527
|
export declare type ValidationError = {
|
|
514
|
-
|
|
528
|
+
errorIdentifier: 'RELATION_VIOLATION';
|
|
515
529
|
context: {
|
|
516
530
|
relation: string;
|
|
517
531
|
modelA: string;
|
|
518
532
|
modelB: string;
|
|
519
533
|
};
|
|
520
534
|
} | {
|
|
521
|
-
|
|
535
|
+
errorIdentifier: 'MISSING_RELATED_RECORD';
|
|
522
536
|
context: {
|
|
523
537
|
model: string;
|
|
524
538
|
relation: string;
|
|
@@ -527,24 +541,24 @@ export declare type ValidationError = {
|
|
|
527
541
|
neededFor?: string;
|
|
528
542
|
};
|
|
529
543
|
} | {
|
|
530
|
-
|
|
544
|
+
errorIdentifier: 'MISSING_RECORD';
|
|
531
545
|
context: {
|
|
532
546
|
operation: string;
|
|
533
547
|
};
|
|
534
548
|
} | {
|
|
535
|
-
|
|
549
|
+
errorIdentifier: 'INCOMPLETE_CONNECT_INPUT';
|
|
536
550
|
context: {
|
|
537
551
|
expectedRows: number;
|
|
538
552
|
};
|
|
539
553
|
} | {
|
|
540
|
-
|
|
554
|
+
errorIdentifier: 'INCOMPLETE_CONNECT_OUTPUT';
|
|
541
555
|
context: {
|
|
542
556
|
expectedRows: number;
|
|
543
557
|
relation: string;
|
|
544
558
|
relationType: string;
|
|
545
559
|
};
|
|
546
560
|
} | {
|
|
547
|
-
|
|
561
|
+
errorIdentifier: 'RECORDS_NOT_CONNECTED';
|
|
548
562
|
context: {
|
|
549
563
|
relation: string;
|
|
550
564
|
parent: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -80,7 +80,11 @@ export declare type DecimalTaggedValue = {
|
|
|
80
80
|
value: string;
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
declare type DeepReadonly<T> = T extends undefined | null | boolean | string | number | symbol | Function | Date ? T : T extends Array<infer U> ? ReadonlyArray<DeepReadonly<U>> : unknown extends T ? unknown : {
|
|
84
|
+
readonly [K in keyof T]: DeepReadonly<T[K]>;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export declare function deserializeJsonObject(result: unknown): unknown;
|
|
84
88
|
|
|
85
89
|
/**
|
|
86
90
|
* Checks if two objects representing the names and values of key columns match. A match is
|
|
@@ -155,6 +159,9 @@ export declare type Fragment = {
|
|
|
155
159
|
type: 'parameter';
|
|
156
160
|
} | {
|
|
157
161
|
type: 'parameterTuple';
|
|
162
|
+
itemPrefix: string;
|
|
163
|
+
itemSeparator: string;
|
|
164
|
+
itemSuffix: string;
|
|
158
165
|
} | {
|
|
159
166
|
type: 'parameterTupleList';
|
|
160
167
|
itemPrefix: string;
|
|
@@ -187,7 +194,7 @@ export declare type JoinExpression = {
|
|
|
187
194
|
isRelationUnique: boolean;
|
|
188
195
|
};
|
|
189
196
|
|
|
190
|
-
export declare type JsonInputTaggedValue = DateTaggedValue | DecimalTaggedValue | BytesTaggedValue | BigIntTaggedValue | FieldRefTaggedValue | JsonTaggedValue | EnumTaggedValue;
|
|
197
|
+
export declare type JsonInputTaggedValue = DateTaggedValue | DecimalTaggedValue | BytesTaggedValue | BigIntTaggedValue | FieldRefTaggedValue | JsonTaggedValue | EnumTaggedValue | RawTaggedValue;
|
|
191
198
|
|
|
192
199
|
export declare type JsonOutputTaggedValue = DateTaggedValue | DecimalTaggedValue | BytesTaggedValue | BigIntTaggedValue | JsonTaggedValue;
|
|
193
200
|
|
|
@@ -243,7 +250,7 @@ export declare type PrismaValuePlaceholder = {
|
|
|
243
250
|
export declare type QueryEvent = {
|
|
244
251
|
timestamp: Date;
|
|
245
252
|
query: string;
|
|
246
|
-
params: unknown[];
|
|
253
|
+
params: readonly unknown[];
|
|
247
254
|
duration: number;
|
|
248
255
|
};
|
|
249
256
|
|
|
@@ -256,7 +263,7 @@ export declare class QueryInterpreter {
|
|
|
256
263
|
provider?: SchemaProvider;
|
|
257
264
|
connectionInfo?: ConnectionInfo;
|
|
258
265
|
}): QueryInterpreter;
|
|
259
|
-
run(queryPlan: QueryPlanNode
|
|
266
|
+
run(queryPlan: DeepReadonly<QueryPlanNode>, options: QueryRuntimeOptions): Promise<unknown>;
|
|
260
267
|
private interpretNode;
|
|
261
268
|
}
|
|
262
269
|
|
|
@@ -348,6 +355,7 @@ export declare type QueryPlanNode = {
|
|
|
348
355
|
args: {
|
|
349
356
|
parent: QueryPlanNode;
|
|
350
357
|
children: JoinExpression[];
|
|
358
|
+
canAssumeStrictEquality: boolean;
|
|
351
359
|
};
|
|
352
360
|
} | {
|
|
353
361
|
type: 'mapField';
|
|
@@ -421,6 +429,11 @@ export declare type RawResponse = {
|
|
|
421
429
|
rows: unknown[][];
|
|
422
430
|
};
|
|
423
431
|
|
|
432
|
+
export declare type RawTaggedValue = {
|
|
433
|
+
$type: 'Raw';
|
|
434
|
+
value: unknown;
|
|
435
|
+
};
|
|
436
|
+
|
|
424
437
|
export declare type ResultNode = {
|
|
425
438
|
type: 'affectedRows';
|
|
426
439
|
} | {
|
|
@@ -492,6 +505,7 @@ export declare type TransactionOptions = {
|
|
|
492
505
|
maxWait?: number;
|
|
493
506
|
timeout?: number;
|
|
494
507
|
isolationLevel?: IsolationLevel;
|
|
508
|
+
newTxId?: string;
|
|
495
509
|
};
|
|
496
510
|
|
|
497
511
|
export declare class UserFacingError extends Error {
|
|
@@ -511,14 +525,14 @@ export declare class UserFacingError extends Error {
|
|
|
511
525
|
}
|
|
512
526
|
|
|
513
527
|
export declare type ValidationError = {
|
|
514
|
-
|
|
528
|
+
errorIdentifier: 'RELATION_VIOLATION';
|
|
515
529
|
context: {
|
|
516
530
|
relation: string;
|
|
517
531
|
modelA: string;
|
|
518
532
|
modelB: string;
|
|
519
533
|
};
|
|
520
534
|
} | {
|
|
521
|
-
|
|
535
|
+
errorIdentifier: 'MISSING_RELATED_RECORD';
|
|
522
536
|
context: {
|
|
523
537
|
model: string;
|
|
524
538
|
relation: string;
|
|
@@ -527,24 +541,24 @@ export declare type ValidationError = {
|
|
|
527
541
|
neededFor?: string;
|
|
528
542
|
};
|
|
529
543
|
} | {
|
|
530
|
-
|
|
544
|
+
errorIdentifier: 'MISSING_RECORD';
|
|
531
545
|
context: {
|
|
532
546
|
operation: string;
|
|
533
547
|
};
|
|
534
548
|
} | {
|
|
535
|
-
|
|
549
|
+
errorIdentifier: 'INCOMPLETE_CONNECT_INPUT';
|
|
536
550
|
context: {
|
|
537
551
|
expectedRows: number;
|
|
538
552
|
};
|
|
539
553
|
} | {
|
|
540
|
-
|
|
554
|
+
errorIdentifier: 'INCOMPLETE_CONNECT_OUTPUT';
|
|
541
555
|
context: {
|
|
542
556
|
expectedRows: number;
|
|
543
557
|
relation: string;
|
|
544
558
|
relationType: string;
|
|
545
559
|
};
|
|
546
560
|
} | {
|
|
547
|
-
|
|
561
|
+
errorIdentifier: 'RECORDS_NOT_CONNECTED';
|
|
548
562
|
context: {
|
|
549
563
|
relation: string;
|
|
550
564
|
parent: string;
|
package/dist/index.js
CHANGED
|
@@ -37,7 +37,7 @@ __export(index_exports, {
|
|
|
37
37
|
UserFacingError: () => UserFacingError,
|
|
38
38
|
applySqlCommenters: () => applySqlCommenters,
|
|
39
39
|
convertCompactedRows: () => convertCompactedRows,
|
|
40
|
-
|
|
40
|
+
deserializeJsonObject: () => deserializeJsonObject,
|
|
41
41
|
doKeysMatch: () => doKeysMatch,
|
|
42
42
|
isDeepStrictEqual: () => isDeepStrictEqual,
|
|
43
43
|
isPrismaValueGenerator: () => isPrismaValueGenerator,
|
|
@@ -170,7 +170,10 @@ function normalizeJsonProtocolValues(result) {
|
|
|
170
170
|
function isTaggedValue(value) {
|
|
171
171
|
return value !== null && typeof value == "object" && typeof value["$type"] === "string";
|
|
172
172
|
}
|
|
173
|
-
function normalizeTaggedValue({
|
|
173
|
+
function normalizeTaggedValue({
|
|
174
|
+
$type,
|
|
175
|
+
value
|
|
176
|
+
}) {
|
|
174
177
|
switch ($type) {
|
|
175
178
|
case "BigInt":
|
|
176
179
|
return { $type, value: String(value) };
|
|
@@ -182,6 +185,12 @@ function normalizeTaggedValue({ $type, value }) {
|
|
|
182
185
|
return { $type, value: String(new import_client_runtime_utils2.Decimal(value)) };
|
|
183
186
|
case "Json":
|
|
184
187
|
return { $type, value: JSON.stringify(JSON.parse(value)) };
|
|
188
|
+
case "Raw":
|
|
189
|
+
return { $type, value };
|
|
190
|
+
case "FieldRef":
|
|
191
|
+
return { $type, value };
|
|
192
|
+
case "Enum":
|
|
193
|
+
return { $type, value };
|
|
185
194
|
default:
|
|
186
195
|
assertNever(value, "Unknown tagged value");
|
|
187
196
|
}
|
|
@@ -193,12 +202,12 @@ function mapObjectValues(object, mapper) {
|
|
|
193
202
|
}
|
|
194
203
|
return result;
|
|
195
204
|
}
|
|
196
|
-
function
|
|
205
|
+
function deserializeJsonObject(result) {
|
|
197
206
|
if (result === null) {
|
|
198
207
|
return result;
|
|
199
208
|
}
|
|
200
209
|
if (Array.isArray(result)) {
|
|
201
|
-
return result.map(
|
|
210
|
+
return result.map(deserializeJsonObject);
|
|
202
211
|
}
|
|
203
212
|
if (typeof result === "object") {
|
|
204
213
|
if (isTaggedValue(result)) {
|
|
@@ -207,7 +216,7 @@ function deserializeJsonResponse(result) {
|
|
|
207
216
|
if (result.constructor !== null && result.constructor.name !== "Object") {
|
|
208
217
|
return result;
|
|
209
218
|
}
|
|
210
|
-
return mapObjectValues(result,
|
|
219
|
+
return mapObjectValues(result, deserializeJsonObject);
|
|
211
220
|
}
|
|
212
221
|
return result;
|
|
213
222
|
}
|
|
@@ -225,6 +234,12 @@ function deserializeTaggedValue({ $type, value }) {
|
|
|
225
234
|
return new import_client_runtime_utils2.Decimal(value);
|
|
226
235
|
case "Json":
|
|
227
236
|
return JSON.parse(value);
|
|
237
|
+
case "Raw":
|
|
238
|
+
return value;
|
|
239
|
+
case "FieldRef":
|
|
240
|
+
throw new Error("FieldRef tagged values cannot be deserialized to JavaScript values");
|
|
241
|
+
case "Enum":
|
|
242
|
+
return value;
|
|
228
243
|
default:
|
|
229
244
|
assertNever(value, "Unknown tagged value");
|
|
230
245
|
}
|
|
@@ -456,7 +471,7 @@ function resolveArgPlaceholders(args, placeholderValues) {
|
|
|
456
471
|
function convertCompactedRows(rows, compiledBatch, placeholderValues = {}) {
|
|
457
472
|
const keysPerRow = rows.map(
|
|
458
473
|
(item) => compiledBatch.keys.reduce((acc, key) => {
|
|
459
|
-
acc[key] =
|
|
474
|
+
acc[key] = deserializeJsonObject(item[key]);
|
|
460
475
|
return acc;
|
|
461
476
|
}, {})
|
|
462
477
|
);
|
|
@@ -742,6 +757,9 @@ function normalizeDateTime(dt) {
|
|
|
742
757
|
return dtWithTz;
|
|
743
758
|
}
|
|
744
759
|
|
|
760
|
+
// src/interpreter/query-interpreter.ts
|
|
761
|
+
var import_klona2 = require("klona");
|
|
762
|
+
|
|
745
763
|
// src/sql-commenter.ts
|
|
746
764
|
var import_klona = require("klona");
|
|
747
765
|
function formatSqlComment(tags) {
|
|
@@ -1025,8 +1043,11 @@ function paginateSingleList(list, { cursor, skip, take }) {
|
|
|
1025
1043
|
const end = take !== null ? start + take : list.length;
|
|
1026
1044
|
return list.slice(start, end);
|
|
1027
1045
|
}
|
|
1028
|
-
function getRecordKey(record, fields) {
|
|
1029
|
-
|
|
1046
|
+
function getRecordKey(record, fields, mappers) {
|
|
1047
|
+
const array = fields.map(
|
|
1048
|
+
(field, index) => mappers?.[index] ? record[field] !== null ? mappers[index](record[field]) : null : record[field]
|
|
1049
|
+
);
|
|
1050
|
+
return JSON.stringify(array);
|
|
1030
1051
|
}
|
|
1031
1052
|
|
|
1032
1053
|
// src/query-plan.ts
|
|
@@ -1121,7 +1142,10 @@ function renderFragment(fragment, placeholderFormat, ctx) {
|
|
|
1121
1142
|
case "stringChunk":
|
|
1122
1143
|
return fragment.chunk;
|
|
1123
1144
|
case "parameterTuple": {
|
|
1124
|
-
const placeholders = fragment.value.length == 0 ? "NULL" : fragment.value.map(() =>
|
|
1145
|
+
const placeholders = fragment.value.length == 0 ? "NULL" : fragment.value.map(() => {
|
|
1146
|
+
const item = formatPlaceholder(placeholderFormat, ctx.placeholderNumber++);
|
|
1147
|
+
return `${fragment.itemPrefix}${item}${fragment.itemSuffix}`;
|
|
1148
|
+
}).join(fragment.itemSeparator);
|
|
1125
1149
|
return `(${placeholders})`;
|
|
1126
1150
|
}
|
|
1127
1151
|
case "parameterTupleList": {
|
|
@@ -1480,7 +1504,7 @@ function doesSatisfyRule(data, rule) {
|
|
|
1480
1504
|
}
|
|
1481
1505
|
}
|
|
1482
1506
|
function renderMessage(data, error) {
|
|
1483
|
-
switch (error.
|
|
1507
|
+
switch (error.errorIdentifier) {
|
|
1484
1508
|
case "RELATION_VIOLATION":
|
|
1485
1509
|
return `The change you are trying to make would violate the required relation '${error.context.relation}' between the \`${error.context.modelA}\` and \`${error.context.modelB}\` models.`;
|
|
1486
1510
|
case "MISSING_RECORD":
|
|
@@ -1500,7 +1524,7 @@ function renderMessage(data, error) {
|
|
|
1500
1524
|
}
|
|
1501
1525
|
}
|
|
1502
1526
|
function getErrorCode2(error) {
|
|
1503
|
-
switch (error.
|
|
1527
|
+
switch (error.errorIdentifier) {
|
|
1504
1528
|
case "RELATION_VIOLATION":
|
|
1505
1529
|
return "P2014";
|
|
1506
1530
|
case "RECORDS_NOT_CONNECTED":
|
|
@@ -1615,7 +1639,7 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1615
1639
|
sum += await this.#withQuerySpanAndEvent(
|
|
1616
1640
|
commentedQuery,
|
|
1617
1641
|
context.queryable,
|
|
1618
|
-
() => context.queryable.executeRaw(commentedQuery).catch(
|
|
1642
|
+
() => context.queryable.executeRaw(cloneObject(commentedQuery)).catch(
|
|
1619
1643
|
(err) => node.args.type === "rawSql" ? rethrowAsUserFacingRawError(err) : rethrowAsUserFacing(err)
|
|
1620
1644
|
)
|
|
1621
1645
|
);
|
|
@@ -1630,7 +1654,7 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1630
1654
|
const result = await this.#withQuerySpanAndEvent(
|
|
1631
1655
|
commentedQuery,
|
|
1632
1656
|
context.queryable,
|
|
1633
|
-
() => context.queryable.queryRaw(commentedQuery).catch(
|
|
1657
|
+
() => context.queryable.queryRaw(cloneObject(commentedQuery)).catch(
|
|
1634
1658
|
(err) => node.args.type === "rawSql" ? rethrowAsUserFacingRawError(err) : rethrowAsUserFacing(err)
|
|
1635
1659
|
)
|
|
1636
1660
|
);
|
|
@@ -1682,7 +1706,7 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1682
1706
|
childRecords: (await this.interpretNode(joinExpr.child, context)).value
|
|
1683
1707
|
}))
|
|
1684
1708
|
);
|
|
1685
|
-
return { value: attachChildrenToParents(parent, children), lastInsertId };
|
|
1709
|
+
return { value: attachChildrenToParents(parent, children, node.args.canAssumeStrictEquality), lastInsertId };
|
|
1686
1710
|
}
|
|
1687
1711
|
case "transaction": {
|
|
1688
1712
|
if (!context.transactionManager.enabled) {
|
|
@@ -1729,8 +1753,9 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1729
1753
|
}
|
|
1730
1754
|
case "process": {
|
|
1731
1755
|
const { value, lastInsertId } = await this.interpretNode(node.args.expr, context);
|
|
1732
|
-
|
|
1733
|
-
|
|
1756
|
+
const ops = cloneObject(node.args.operations);
|
|
1757
|
+
evaluateProcessingParameters(ops, context.scope, context.generators);
|
|
1758
|
+
return { value: processRecords(value, ops), lastInsertId };
|
|
1734
1759
|
}
|
|
1735
1760
|
case "initializeRecord": {
|
|
1736
1761
|
const { lastInsertId } = await this.interpretNode(node.args.expr, context);
|
|
@@ -1823,12 +1848,13 @@ function mapField2(value, field) {
|
|
|
1823
1848
|
}
|
|
1824
1849
|
return value;
|
|
1825
1850
|
}
|
|
1826
|
-
function attachChildrenToParents(parentRecords, children) {
|
|
1851
|
+
function attachChildrenToParents(parentRecords, children, canAssumeStrictEquality) {
|
|
1827
1852
|
for (const { joinExpr, childRecords } of children) {
|
|
1828
1853
|
const parentKeys = joinExpr.on.map(([k]) => k);
|
|
1829
1854
|
const childKeys = joinExpr.on.map(([, k]) => k);
|
|
1830
1855
|
const parentMap = {};
|
|
1831
|
-
|
|
1856
|
+
const parentArray = Array.isArray(parentRecords) ? parentRecords : [parentRecords];
|
|
1857
|
+
for (const parent of parentArray) {
|
|
1832
1858
|
const parentRecord = asRecord(parent);
|
|
1833
1859
|
const key = getRecordKey(parentRecord, parentKeys);
|
|
1834
1860
|
if (!parentMap[key]) {
|
|
@@ -1841,11 +1867,12 @@ function attachChildrenToParents(parentRecords, children) {
|
|
|
1841
1867
|
parentRecord[joinExpr.parentField] = [];
|
|
1842
1868
|
}
|
|
1843
1869
|
}
|
|
1870
|
+
const mappers = canAssumeStrictEquality ? void 0 : inferKeyCasts(parentArray, parentKeys);
|
|
1844
1871
|
for (const childRecord of Array.isArray(childRecords) ? childRecords : [childRecords]) {
|
|
1845
1872
|
if (childRecord === null) {
|
|
1846
1873
|
continue;
|
|
1847
1874
|
}
|
|
1848
|
-
const key = getRecordKey(asRecord(childRecord), childKeys);
|
|
1875
|
+
const key = getRecordKey(asRecord(childRecord), childKeys, mappers);
|
|
1849
1876
|
for (const parentRecord of parentMap[key] ?? []) {
|
|
1850
1877
|
if (joinExpr.isRelationUnique) {
|
|
1851
1878
|
parentRecord[joinExpr.parentField] = childRecord;
|
|
@@ -1857,6 +1884,40 @@ function attachChildrenToParents(parentRecords, children) {
|
|
|
1857
1884
|
}
|
|
1858
1885
|
return parentRecords;
|
|
1859
1886
|
}
|
|
1887
|
+
function inferKeyCasts(rows, keys) {
|
|
1888
|
+
function getKeyCast(type) {
|
|
1889
|
+
switch (type) {
|
|
1890
|
+
case "number":
|
|
1891
|
+
return Number;
|
|
1892
|
+
case "string":
|
|
1893
|
+
return String;
|
|
1894
|
+
case "boolean":
|
|
1895
|
+
return Boolean;
|
|
1896
|
+
case "bigint":
|
|
1897
|
+
return BigInt;
|
|
1898
|
+
default:
|
|
1899
|
+
return;
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
const keyCasts = Array.from({ length: keys.length });
|
|
1903
|
+
let keysFound = 0;
|
|
1904
|
+
for (const parent of rows) {
|
|
1905
|
+
const parentRecord = asRecord(parent);
|
|
1906
|
+
for (const [i, key] of keys.entries()) {
|
|
1907
|
+
if (parentRecord[key] !== null && keyCasts[i] === void 0) {
|
|
1908
|
+
const keyCast = getKeyCast(typeof parentRecord[key]);
|
|
1909
|
+
if (keyCast !== void 0) {
|
|
1910
|
+
keyCasts[i] = keyCast;
|
|
1911
|
+
}
|
|
1912
|
+
keysFound++;
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
if (keysFound === keys.length) {
|
|
1916
|
+
break;
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
return keyCasts;
|
|
1920
|
+
}
|
|
1860
1921
|
function evalFieldInitializer(initializer, lastInsertId, scope, generators) {
|
|
1861
1922
|
switch (initializer.type) {
|
|
1862
1923
|
case "value":
|
|
@@ -1916,6 +1977,9 @@ function evaluateProcessingParameters(ops, scope, generators) {
|
|
|
1916
1977
|
evaluateProcessingParameters(nested, scope, generators);
|
|
1917
1978
|
}
|
|
1918
1979
|
}
|
|
1980
|
+
function cloneObject(value) {
|
|
1981
|
+
return (0, import_klona2.klona)(value);
|
|
1982
|
+
}
|
|
1919
1983
|
|
|
1920
1984
|
// src/raw-json-protocol.ts
|
|
1921
1985
|
var import_client_runtime_utils4 = require("@prisma/client-runtime-utils");
|
|
@@ -2072,13 +2136,42 @@ var TransactionManager = class {
|
|
|
2072
2136
|
);
|
|
2073
2137
|
}
|
|
2074
2138
|
async #startTransactionImpl(options) {
|
|
2139
|
+
if (options.newTxId) {
|
|
2140
|
+
return await this.#withActiveTransactionLock(options.newTxId, "start", async (existing) => {
|
|
2141
|
+
if (existing.status !== "running") {
|
|
2142
|
+
throw new TransactionInternalConsistencyError(
|
|
2143
|
+
`Transaction in invalid state ${existing.status} when starting a nested transaction.`
|
|
2144
|
+
);
|
|
2145
|
+
}
|
|
2146
|
+
if (!existing.transaction) {
|
|
2147
|
+
throw new TransactionInternalConsistencyError(
|
|
2148
|
+
`Transaction missing underlying driver transaction when starting a nested transaction.`
|
|
2149
|
+
);
|
|
2150
|
+
}
|
|
2151
|
+
existing.depth += 1;
|
|
2152
|
+
const savepointName = this.#nextSavepointName(existing);
|
|
2153
|
+
existing.savepoints.push(savepointName);
|
|
2154
|
+
try {
|
|
2155
|
+
await this.#requiredCreateSavepoint(existing.transaction)(savepointName);
|
|
2156
|
+
} catch (e) {
|
|
2157
|
+
existing.depth -= 1;
|
|
2158
|
+
existing.savepoints.pop();
|
|
2159
|
+
throw e;
|
|
2160
|
+
}
|
|
2161
|
+
return { id: existing.id };
|
|
2162
|
+
});
|
|
2163
|
+
}
|
|
2075
2164
|
const transaction = {
|
|
2076
2165
|
id: await randomUUID(),
|
|
2077
2166
|
status: "waiting",
|
|
2078
2167
|
timer: void 0,
|
|
2079
2168
|
timeout: options.timeout,
|
|
2080
2169
|
startedAt: Date.now(),
|
|
2081
|
-
transaction: void 0
|
|
2170
|
+
transaction: void 0,
|
|
2171
|
+
operationQueue: Promise.resolve(),
|
|
2172
|
+
depth: 1,
|
|
2173
|
+
savepoints: [],
|
|
2174
|
+
savepointCounter: 0
|
|
2082
2175
|
};
|
|
2083
2176
|
const abortController = new AbortController();
|
|
2084
2177
|
const startTimer = createTimeoutIfDefined(() => abortController.abort(), options.maxWait);
|
|
@@ -2112,14 +2205,49 @@ var TransactionManager = class {
|
|
|
2112
2205
|
}
|
|
2113
2206
|
async commitTransaction(transactionId) {
|
|
2114
2207
|
return await this.tracingHelper.runInChildSpan("commit_transaction", async () => {
|
|
2115
|
-
|
|
2116
|
-
|
|
2208
|
+
await this.#withActiveTransactionLock(transactionId, "commit", async (txw) => {
|
|
2209
|
+
if (txw.depth > 1) {
|
|
2210
|
+
if (!txw.transaction) throw new TransactionNotFoundError();
|
|
2211
|
+
const savepointName = txw.savepoints.at(-1);
|
|
2212
|
+
if (!savepointName) {
|
|
2213
|
+
throw new TransactionInternalConsistencyError(
|
|
2214
|
+
`Missing savepoint for nested commit. Depth: ${txw.depth}, transactionId: ${txw.id}`
|
|
2215
|
+
);
|
|
2216
|
+
}
|
|
2217
|
+
try {
|
|
2218
|
+
await this.#releaseSavepoint(txw.transaction, savepointName);
|
|
2219
|
+
} finally {
|
|
2220
|
+
txw.savepoints.pop();
|
|
2221
|
+
txw.depth -= 1;
|
|
2222
|
+
}
|
|
2223
|
+
return;
|
|
2224
|
+
}
|
|
2225
|
+
await this.#closeTransaction(txw, "committed");
|
|
2226
|
+
});
|
|
2117
2227
|
});
|
|
2118
2228
|
}
|
|
2119
2229
|
async rollbackTransaction(transactionId) {
|
|
2120
2230
|
return await this.tracingHelper.runInChildSpan("rollback_transaction", async () => {
|
|
2121
|
-
|
|
2122
|
-
|
|
2231
|
+
await this.#withActiveTransactionLock(transactionId, "rollback", async (txw) => {
|
|
2232
|
+
if (txw.depth > 1) {
|
|
2233
|
+
if (!txw.transaction) throw new TransactionNotFoundError();
|
|
2234
|
+
const savepointName = txw.savepoints.at(-1);
|
|
2235
|
+
if (!savepointName) {
|
|
2236
|
+
throw new TransactionInternalConsistencyError(
|
|
2237
|
+
`Missing savepoint for nested rollback. Depth: ${txw.depth}, transactionId: ${txw.id}`
|
|
2238
|
+
);
|
|
2239
|
+
}
|
|
2240
|
+
try {
|
|
2241
|
+
await this.#requiredRollbackToSavepoint(txw.transaction)(savepointName);
|
|
2242
|
+
await this.#releaseSavepoint(txw.transaction, savepointName);
|
|
2243
|
+
} finally {
|
|
2244
|
+
txw.savepoints.pop();
|
|
2245
|
+
txw.depth -= 1;
|
|
2246
|
+
}
|
|
2247
|
+
return;
|
|
2248
|
+
}
|
|
2249
|
+
await this.#closeTransaction(txw, "rolled_back");
|
|
2250
|
+
});
|
|
2123
2251
|
});
|
|
2124
2252
|
}
|
|
2125
2253
|
async getTransaction(txInfo, operation) {
|
|
@@ -2163,22 +2291,90 @@ var TransactionManager = class {
|
|
|
2163
2291
|
return transaction;
|
|
2164
2292
|
}
|
|
2165
2293
|
async cancelAllTransactions() {
|
|
2166
|
-
await Promise.allSettled(
|
|
2294
|
+
await Promise.allSettled(
|
|
2295
|
+
[...this.transactions.values()].map(
|
|
2296
|
+
(tx) => this.#runSerialized(tx, async () => {
|
|
2297
|
+
const current = this.transactions.get(tx.id);
|
|
2298
|
+
if (current) {
|
|
2299
|
+
await this.#closeTransaction(current, "rolled_back");
|
|
2300
|
+
}
|
|
2301
|
+
})
|
|
2302
|
+
)
|
|
2303
|
+
);
|
|
2304
|
+
}
|
|
2305
|
+
#nextSavepointName(transaction) {
|
|
2306
|
+
return `prisma_sp_${transaction.savepointCounter++}`;
|
|
2307
|
+
}
|
|
2308
|
+
#requiredCreateSavepoint(transaction) {
|
|
2309
|
+
if (transaction.createSavepoint) {
|
|
2310
|
+
return transaction.createSavepoint.bind(transaction);
|
|
2311
|
+
}
|
|
2312
|
+
throw new TransactionManagerError(
|
|
2313
|
+
`Nested transactions are not supported by adapter "${transaction.adapterName}" (${transaction.provider}): createSavepoint is not implemented.`
|
|
2314
|
+
);
|
|
2315
|
+
}
|
|
2316
|
+
#requiredRollbackToSavepoint(transaction) {
|
|
2317
|
+
if (transaction.rollbackToSavepoint) {
|
|
2318
|
+
return transaction.rollbackToSavepoint.bind(transaction);
|
|
2319
|
+
}
|
|
2320
|
+
throw new TransactionManagerError(
|
|
2321
|
+
`Nested transactions are not supported by adapter "${transaction.adapterName}" (${transaction.provider}): rollbackToSavepoint is not implemented.`
|
|
2322
|
+
);
|
|
2323
|
+
}
|
|
2324
|
+
async #releaseSavepoint(transaction, name) {
|
|
2325
|
+
if (transaction.releaseSavepoint) {
|
|
2326
|
+
await transaction.releaseSavepoint(name);
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
#debugTransactionAlreadyClosedOnTimeout(transactionId) {
|
|
2330
|
+
debug("Transaction already committed or rolled back when timeout happened.", transactionId);
|
|
2167
2331
|
}
|
|
2168
2332
|
#startTransactionTimeout(transactionId, timeout) {
|
|
2169
2333
|
const timeoutStartedAt = Date.now();
|
|
2170
2334
|
const timer = createTimeoutIfDefined(async () => {
|
|
2171
2335
|
debug("Transaction timed out.", { transactionId, timeoutStartedAt, timeout });
|
|
2172
2336
|
const tx = this.transactions.get(transactionId);
|
|
2173
|
-
if (tx
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2337
|
+
if (!tx) {
|
|
2338
|
+
this.#debugTransactionAlreadyClosedOnTimeout(transactionId);
|
|
2339
|
+
return;
|
|
2340
|
+
}
|
|
2341
|
+
await this.#runSerialized(tx, async () => {
|
|
2342
|
+
const current = this.transactions.get(transactionId);
|
|
2343
|
+
if (current && ["running", "waiting"].includes(current.status)) {
|
|
2344
|
+
await this.#closeTransaction(current, "timed_out");
|
|
2345
|
+
} else {
|
|
2346
|
+
this.#debugTransactionAlreadyClosedOnTimeout(transactionId);
|
|
2347
|
+
}
|
|
2348
|
+
});
|
|
2178
2349
|
}, timeout);
|
|
2179
2350
|
timer?.unref?.();
|
|
2180
2351
|
return timer;
|
|
2181
2352
|
}
|
|
2353
|
+
// Any operation that mutates or closes a transaction must run through this lock so
|
|
2354
|
+
// status/savepoint/depth checks and updates happen against a stable view of state.
|
|
2355
|
+
async #withActiveTransactionLock(transactionId, operation, callback) {
|
|
2356
|
+
const tx = this.#getActiveOrClosingTransaction(transactionId, operation);
|
|
2357
|
+
return await this.#runSerialized(tx, async () => {
|
|
2358
|
+
const current = this.#getActiveOrClosingTransaction(transactionId, operation);
|
|
2359
|
+
return await callback(current);
|
|
2360
|
+
});
|
|
2361
|
+
}
|
|
2362
|
+
// Serializes operations per transaction id to prevent interleaving across awaits.
|
|
2363
|
+
// This avoids races where one operation mutates savepoint/depth state while another
|
|
2364
|
+
// operation is suspended, which could otherwise corrupt cleanup logic.
|
|
2365
|
+
async #runSerialized(tx, callback) {
|
|
2366
|
+
const previousOperation = tx.operationQueue;
|
|
2367
|
+
let releaseOperationLock;
|
|
2368
|
+
tx.operationQueue = new Promise((resolve) => {
|
|
2369
|
+
releaseOperationLock = resolve;
|
|
2370
|
+
});
|
|
2371
|
+
await previousOperation;
|
|
2372
|
+
try {
|
|
2373
|
+
return await callback();
|
|
2374
|
+
} finally {
|
|
2375
|
+
releaseOperationLock();
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2182
2378
|
async #closeTransaction(tx, status) {
|
|
2183
2379
|
const createClosingPromise = async () => {
|
|
2184
2380
|
debug("Closing transaction.", { transactionId: tx.id, status });
|
|
@@ -2266,7 +2462,7 @@ function createTimeoutIfDefined(cb, ms) {
|
|
|
2266
2462
|
UserFacingError,
|
|
2267
2463
|
applySqlCommenters,
|
|
2268
2464
|
convertCompactedRows,
|
|
2269
|
-
|
|
2465
|
+
deserializeJsonObject,
|
|
2270
2466
|
doKeysMatch,
|
|
2271
2467
|
isDeepStrictEqual,
|
|
2272
2468
|
isPrismaValueGenerator,
|
package/dist/index.mjs
CHANGED
|
@@ -119,7 +119,10 @@ function normalizeJsonProtocolValues(result) {
|
|
|
119
119
|
function isTaggedValue(value) {
|
|
120
120
|
return value !== null && typeof value == "object" && typeof value["$type"] === "string";
|
|
121
121
|
}
|
|
122
|
-
function normalizeTaggedValue({
|
|
122
|
+
function normalizeTaggedValue({
|
|
123
|
+
$type,
|
|
124
|
+
value
|
|
125
|
+
}) {
|
|
123
126
|
switch ($type) {
|
|
124
127
|
case "BigInt":
|
|
125
128
|
return { $type, value: String(value) };
|
|
@@ -131,6 +134,12 @@ function normalizeTaggedValue({ $type, value }) {
|
|
|
131
134
|
return { $type, value: String(new Decimal2(value)) };
|
|
132
135
|
case "Json":
|
|
133
136
|
return { $type, value: JSON.stringify(JSON.parse(value)) };
|
|
137
|
+
case "Raw":
|
|
138
|
+
return { $type, value };
|
|
139
|
+
case "FieldRef":
|
|
140
|
+
return { $type, value };
|
|
141
|
+
case "Enum":
|
|
142
|
+
return { $type, value };
|
|
134
143
|
default:
|
|
135
144
|
assertNever(value, "Unknown tagged value");
|
|
136
145
|
}
|
|
@@ -142,12 +151,12 @@ function mapObjectValues(object, mapper) {
|
|
|
142
151
|
}
|
|
143
152
|
return result;
|
|
144
153
|
}
|
|
145
|
-
function
|
|
154
|
+
function deserializeJsonObject(result) {
|
|
146
155
|
if (result === null) {
|
|
147
156
|
return result;
|
|
148
157
|
}
|
|
149
158
|
if (Array.isArray(result)) {
|
|
150
|
-
return result.map(
|
|
159
|
+
return result.map(deserializeJsonObject);
|
|
151
160
|
}
|
|
152
161
|
if (typeof result === "object") {
|
|
153
162
|
if (isTaggedValue(result)) {
|
|
@@ -156,7 +165,7 @@ function deserializeJsonResponse(result) {
|
|
|
156
165
|
if (result.constructor !== null && result.constructor.name !== "Object") {
|
|
157
166
|
return result;
|
|
158
167
|
}
|
|
159
|
-
return mapObjectValues(result,
|
|
168
|
+
return mapObjectValues(result, deserializeJsonObject);
|
|
160
169
|
}
|
|
161
170
|
return result;
|
|
162
171
|
}
|
|
@@ -174,6 +183,12 @@ function deserializeTaggedValue({ $type, value }) {
|
|
|
174
183
|
return new Decimal2(value);
|
|
175
184
|
case "Json":
|
|
176
185
|
return JSON.parse(value);
|
|
186
|
+
case "Raw":
|
|
187
|
+
return value;
|
|
188
|
+
case "FieldRef":
|
|
189
|
+
throw new Error("FieldRef tagged values cannot be deserialized to JavaScript values");
|
|
190
|
+
case "Enum":
|
|
191
|
+
return value;
|
|
177
192
|
default:
|
|
178
193
|
assertNever(value, "Unknown tagged value");
|
|
179
194
|
}
|
|
@@ -405,7 +420,7 @@ function resolveArgPlaceholders(args, placeholderValues) {
|
|
|
405
420
|
function convertCompactedRows(rows, compiledBatch, placeholderValues = {}) {
|
|
406
421
|
const keysPerRow = rows.map(
|
|
407
422
|
(item) => compiledBatch.keys.reduce((acc, key) => {
|
|
408
|
-
acc[key] =
|
|
423
|
+
acc[key] = deserializeJsonObject(item[key]);
|
|
409
424
|
return acc;
|
|
410
425
|
}, {})
|
|
411
426
|
);
|
|
@@ -691,6 +706,9 @@ function normalizeDateTime(dt) {
|
|
|
691
706
|
return dtWithTz;
|
|
692
707
|
}
|
|
693
708
|
|
|
709
|
+
// src/interpreter/query-interpreter.ts
|
|
710
|
+
import { klona as klona2 } from "klona";
|
|
711
|
+
|
|
694
712
|
// src/sql-commenter.ts
|
|
695
713
|
import { klona } from "klona";
|
|
696
714
|
function formatSqlComment(tags) {
|
|
@@ -974,8 +992,11 @@ function paginateSingleList(list, { cursor, skip, take }) {
|
|
|
974
992
|
const end = take !== null ? start + take : list.length;
|
|
975
993
|
return list.slice(start, end);
|
|
976
994
|
}
|
|
977
|
-
function getRecordKey(record, fields) {
|
|
978
|
-
|
|
995
|
+
function getRecordKey(record, fields, mappers) {
|
|
996
|
+
const array = fields.map(
|
|
997
|
+
(field, index) => mappers?.[index] ? record[field] !== null ? mappers[index](record[field]) : null : record[field]
|
|
998
|
+
);
|
|
999
|
+
return JSON.stringify(array);
|
|
979
1000
|
}
|
|
980
1001
|
|
|
981
1002
|
// src/query-plan.ts
|
|
@@ -1070,7 +1091,10 @@ function renderFragment(fragment, placeholderFormat, ctx) {
|
|
|
1070
1091
|
case "stringChunk":
|
|
1071
1092
|
return fragment.chunk;
|
|
1072
1093
|
case "parameterTuple": {
|
|
1073
|
-
const placeholders = fragment.value.length == 0 ? "NULL" : fragment.value.map(() =>
|
|
1094
|
+
const placeholders = fragment.value.length == 0 ? "NULL" : fragment.value.map(() => {
|
|
1095
|
+
const item = formatPlaceholder(placeholderFormat, ctx.placeholderNumber++);
|
|
1096
|
+
return `${fragment.itemPrefix}${item}${fragment.itemSuffix}`;
|
|
1097
|
+
}).join(fragment.itemSeparator);
|
|
1074
1098
|
return `(${placeholders})`;
|
|
1075
1099
|
}
|
|
1076
1100
|
case "parameterTupleList": {
|
|
@@ -1429,7 +1453,7 @@ function doesSatisfyRule(data, rule) {
|
|
|
1429
1453
|
}
|
|
1430
1454
|
}
|
|
1431
1455
|
function renderMessage(data, error) {
|
|
1432
|
-
switch (error.
|
|
1456
|
+
switch (error.errorIdentifier) {
|
|
1433
1457
|
case "RELATION_VIOLATION":
|
|
1434
1458
|
return `The change you are trying to make would violate the required relation '${error.context.relation}' between the \`${error.context.modelA}\` and \`${error.context.modelB}\` models.`;
|
|
1435
1459
|
case "MISSING_RECORD":
|
|
@@ -1449,7 +1473,7 @@ function renderMessage(data, error) {
|
|
|
1449
1473
|
}
|
|
1450
1474
|
}
|
|
1451
1475
|
function getErrorCode2(error) {
|
|
1452
|
-
switch (error.
|
|
1476
|
+
switch (error.errorIdentifier) {
|
|
1453
1477
|
case "RELATION_VIOLATION":
|
|
1454
1478
|
return "P2014";
|
|
1455
1479
|
case "RECORDS_NOT_CONNECTED":
|
|
@@ -1564,7 +1588,7 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1564
1588
|
sum += await this.#withQuerySpanAndEvent(
|
|
1565
1589
|
commentedQuery,
|
|
1566
1590
|
context.queryable,
|
|
1567
|
-
() => context.queryable.executeRaw(commentedQuery).catch(
|
|
1591
|
+
() => context.queryable.executeRaw(cloneObject(commentedQuery)).catch(
|
|
1568
1592
|
(err) => node.args.type === "rawSql" ? rethrowAsUserFacingRawError(err) : rethrowAsUserFacing(err)
|
|
1569
1593
|
)
|
|
1570
1594
|
);
|
|
@@ -1579,7 +1603,7 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1579
1603
|
const result = await this.#withQuerySpanAndEvent(
|
|
1580
1604
|
commentedQuery,
|
|
1581
1605
|
context.queryable,
|
|
1582
|
-
() => context.queryable.queryRaw(commentedQuery).catch(
|
|
1606
|
+
() => context.queryable.queryRaw(cloneObject(commentedQuery)).catch(
|
|
1583
1607
|
(err) => node.args.type === "rawSql" ? rethrowAsUserFacingRawError(err) : rethrowAsUserFacing(err)
|
|
1584
1608
|
)
|
|
1585
1609
|
);
|
|
@@ -1631,7 +1655,7 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1631
1655
|
childRecords: (await this.interpretNode(joinExpr.child, context)).value
|
|
1632
1656
|
}))
|
|
1633
1657
|
);
|
|
1634
|
-
return { value: attachChildrenToParents(parent, children), lastInsertId };
|
|
1658
|
+
return { value: attachChildrenToParents(parent, children, node.args.canAssumeStrictEquality), lastInsertId };
|
|
1635
1659
|
}
|
|
1636
1660
|
case "transaction": {
|
|
1637
1661
|
if (!context.transactionManager.enabled) {
|
|
@@ -1678,8 +1702,9 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1678
1702
|
}
|
|
1679
1703
|
case "process": {
|
|
1680
1704
|
const { value, lastInsertId } = await this.interpretNode(node.args.expr, context);
|
|
1681
|
-
|
|
1682
|
-
|
|
1705
|
+
const ops = cloneObject(node.args.operations);
|
|
1706
|
+
evaluateProcessingParameters(ops, context.scope, context.generators);
|
|
1707
|
+
return { value: processRecords(value, ops), lastInsertId };
|
|
1683
1708
|
}
|
|
1684
1709
|
case "initializeRecord": {
|
|
1685
1710
|
const { lastInsertId } = await this.interpretNode(node.args.expr, context);
|
|
@@ -1772,12 +1797,13 @@ function mapField2(value, field) {
|
|
|
1772
1797
|
}
|
|
1773
1798
|
return value;
|
|
1774
1799
|
}
|
|
1775
|
-
function attachChildrenToParents(parentRecords, children) {
|
|
1800
|
+
function attachChildrenToParents(parentRecords, children, canAssumeStrictEquality) {
|
|
1776
1801
|
for (const { joinExpr, childRecords } of children) {
|
|
1777
1802
|
const parentKeys = joinExpr.on.map(([k]) => k);
|
|
1778
1803
|
const childKeys = joinExpr.on.map(([, k]) => k);
|
|
1779
1804
|
const parentMap = {};
|
|
1780
|
-
|
|
1805
|
+
const parentArray = Array.isArray(parentRecords) ? parentRecords : [parentRecords];
|
|
1806
|
+
for (const parent of parentArray) {
|
|
1781
1807
|
const parentRecord = asRecord(parent);
|
|
1782
1808
|
const key = getRecordKey(parentRecord, parentKeys);
|
|
1783
1809
|
if (!parentMap[key]) {
|
|
@@ -1790,11 +1816,12 @@ function attachChildrenToParents(parentRecords, children) {
|
|
|
1790
1816
|
parentRecord[joinExpr.parentField] = [];
|
|
1791
1817
|
}
|
|
1792
1818
|
}
|
|
1819
|
+
const mappers = canAssumeStrictEquality ? void 0 : inferKeyCasts(parentArray, parentKeys);
|
|
1793
1820
|
for (const childRecord of Array.isArray(childRecords) ? childRecords : [childRecords]) {
|
|
1794
1821
|
if (childRecord === null) {
|
|
1795
1822
|
continue;
|
|
1796
1823
|
}
|
|
1797
|
-
const key = getRecordKey(asRecord(childRecord), childKeys);
|
|
1824
|
+
const key = getRecordKey(asRecord(childRecord), childKeys, mappers);
|
|
1798
1825
|
for (const parentRecord of parentMap[key] ?? []) {
|
|
1799
1826
|
if (joinExpr.isRelationUnique) {
|
|
1800
1827
|
parentRecord[joinExpr.parentField] = childRecord;
|
|
@@ -1806,6 +1833,40 @@ function attachChildrenToParents(parentRecords, children) {
|
|
|
1806
1833
|
}
|
|
1807
1834
|
return parentRecords;
|
|
1808
1835
|
}
|
|
1836
|
+
function inferKeyCasts(rows, keys) {
|
|
1837
|
+
function getKeyCast(type) {
|
|
1838
|
+
switch (type) {
|
|
1839
|
+
case "number":
|
|
1840
|
+
return Number;
|
|
1841
|
+
case "string":
|
|
1842
|
+
return String;
|
|
1843
|
+
case "boolean":
|
|
1844
|
+
return Boolean;
|
|
1845
|
+
case "bigint":
|
|
1846
|
+
return BigInt;
|
|
1847
|
+
default:
|
|
1848
|
+
return;
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
const keyCasts = Array.from({ length: keys.length });
|
|
1852
|
+
let keysFound = 0;
|
|
1853
|
+
for (const parent of rows) {
|
|
1854
|
+
const parentRecord = asRecord(parent);
|
|
1855
|
+
for (const [i, key] of keys.entries()) {
|
|
1856
|
+
if (parentRecord[key] !== null && keyCasts[i] === void 0) {
|
|
1857
|
+
const keyCast = getKeyCast(typeof parentRecord[key]);
|
|
1858
|
+
if (keyCast !== void 0) {
|
|
1859
|
+
keyCasts[i] = keyCast;
|
|
1860
|
+
}
|
|
1861
|
+
keysFound++;
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
if (keysFound === keys.length) {
|
|
1865
|
+
break;
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
return keyCasts;
|
|
1869
|
+
}
|
|
1809
1870
|
function evalFieldInitializer(initializer, lastInsertId, scope, generators) {
|
|
1810
1871
|
switch (initializer.type) {
|
|
1811
1872
|
case "value":
|
|
@@ -1865,6 +1926,9 @@ function evaluateProcessingParameters(ops, scope, generators) {
|
|
|
1865
1926
|
evaluateProcessingParameters(nested, scope, generators);
|
|
1866
1927
|
}
|
|
1867
1928
|
}
|
|
1929
|
+
function cloneObject(value) {
|
|
1930
|
+
return klona2(value);
|
|
1931
|
+
}
|
|
1868
1932
|
|
|
1869
1933
|
// src/raw-json-protocol.ts
|
|
1870
1934
|
import { Decimal as Decimal4 } from "@prisma/client-runtime-utils";
|
|
@@ -2021,13 +2085,42 @@ var TransactionManager = class {
|
|
|
2021
2085
|
);
|
|
2022
2086
|
}
|
|
2023
2087
|
async #startTransactionImpl(options) {
|
|
2088
|
+
if (options.newTxId) {
|
|
2089
|
+
return await this.#withActiveTransactionLock(options.newTxId, "start", async (existing) => {
|
|
2090
|
+
if (existing.status !== "running") {
|
|
2091
|
+
throw new TransactionInternalConsistencyError(
|
|
2092
|
+
`Transaction in invalid state ${existing.status} when starting a nested transaction.`
|
|
2093
|
+
);
|
|
2094
|
+
}
|
|
2095
|
+
if (!existing.transaction) {
|
|
2096
|
+
throw new TransactionInternalConsistencyError(
|
|
2097
|
+
`Transaction missing underlying driver transaction when starting a nested transaction.`
|
|
2098
|
+
);
|
|
2099
|
+
}
|
|
2100
|
+
existing.depth += 1;
|
|
2101
|
+
const savepointName = this.#nextSavepointName(existing);
|
|
2102
|
+
existing.savepoints.push(savepointName);
|
|
2103
|
+
try {
|
|
2104
|
+
await this.#requiredCreateSavepoint(existing.transaction)(savepointName);
|
|
2105
|
+
} catch (e) {
|
|
2106
|
+
existing.depth -= 1;
|
|
2107
|
+
existing.savepoints.pop();
|
|
2108
|
+
throw e;
|
|
2109
|
+
}
|
|
2110
|
+
return { id: existing.id };
|
|
2111
|
+
});
|
|
2112
|
+
}
|
|
2024
2113
|
const transaction = {
|
|
2025
2114
|
id: await randomUUID(),
|
|
2026
2115
|
status: "waiting",
|
|
2027
2116
|
timer: void 0,
|
|
2028
2117
|
timeout: options.timeout,
|
|
2029
2118
|
startedAt: Date.now(),
|
|
2030
|
-
transaction: void 0
|
|
2119
|
+
transaction: void 0,
|
|
2120
|
+
operationQueue: Promise.resolve(),
|
|
2121
|
+
depth: 1,
|
|
2122
|
+
savepoints: [],
|
|
2123
|
+
savepointCounter: 0
|
|
2031
2124
|
};
|
|
2032
2125
|
const abortController = new AbortController();
|
|
2033
2126
|
const startTimer = createTimeoutIfDefined(() => abortController.abort(), options.maxWait);
|
|
@@ -2061,14 +2154,49 @@ var TransactionManager = class {
|
|
|
2061
2154
|
}
|
|
2062
2155
|
async commitTransaction(transactionId) {
|
|
2063
2156
|
return await this.tracingHelper.runInChildSpan("commit_transaction", async () => {
|
|
2064
|
-
|
|
2065
|
-
|
|
2157
|
+
await this.#withActiveTransactionLock(transactionId, "commit", async (txw) => {
|
|
2158
|
+
if (txw.depth > 1) {
|
|
2159
|
+
if (!txw.transaction) throw new TransactionNotFoundError();
|
|
2160
|
+
const savepointName = txw.savepoints.at(-1);
|
|
2161
|
+
if (!savepointName) {
|
|
2162
|
+
throw new TransactionInternalConsistencyError(
|
|
2163
|
+
`Missing savepoint for nested commit. Depth: ${txw.depth}, transactionId: ${txw.id}`
|
|
2164
|
+
);
|
|
2165
|
+
}
|
|
2166
|
+
try {
|
|
2167
|
+
await this.#releaseSavepoint(txw.transaction, savepointName);
|
|
2168
|
+
} finally {
|
|
2169
|
+
txw.savepoints.pop();
|
|
2170
|
+
txw.depth -= 1;
|
|
2171
|
+
}
|
|
2172
|
+
return;
|
|
2173
|
+
}
|
|
2174
|
+
await this.#closeTransaction(txw, "committed");
|
|
2175
|
+
});
|
|
2066
2176
|
});
|
|
2067
2177
|
}
|
|
2068
2178
|
async rollbackTransaction(transactionId) {
|
|
2069
2179
|
return await this.tracingHelper.runInChildSpan("rollback_transaction", async () => {
|
|
2070
|
-
|
|
2071
|
-
|
|
2180
|
+
await this.#withActiveTransactionLock(transactionId, "rollback", async (txw) => {
|
|
2181
|
+
if (txw.depth > 1) {
|
|
2182
|
+
if (!txw.transaction) throw new TransactionNotFoundError();
|
|
2183
|
+
const savepointName = txw.savepoints.at(-1);
|
|
2184
|
+
if (!savepointName) {
|
|
2185
|
+
throw new TransactionInternalConsistencyError(
|
|
2186
|
+
`Missing savepoint for nested rollback. Depth: ${txw.depth}, transactionId: ${txw.id}`
|
|
2187
|
+
);
|
|
2188
|
+
}
|
|
2189
|
+
try {
|
|
2190
|
+
await this.#requiredRollbackToSavepoint(txw.transaction)(savepointName);
|
|
2191
|
+
await this.#releaseSavepoint(txw.transaction, savepointName);
|
|
2192
|
+
} finally {
|
|
2193
|
+
txw.savepoints.pop();
|
|
2194
|
+
txw.depth -= 1;
|
|
2195
|
+
}
|
|
2196
|
+
return;
|
|
2197
|
+
}
|
|
2198
|
+
await this.#closeTransaction(txw, "rolled_back");
|
|
2199
|
+
});
|
|
2072
2200
|
});
|
|
2073
2201
|
}
|
|
2074
2202
|
async getTransaction(txInfo, operation) {
|
|
@@ -2112,22 +2240,90 @@ var TransactionManager = class {
|
|
|
2112
2240
|
return transaction;
|
|
2113
2241
|
}
|
|
2114
2242
|
async cancelAllTransactions() {
|
|
2115
|
-
await Promise.allSettled(
|
|
2243
|
+
await Promise.allSettled(
|
|
2244
|
+
[...this.transactions.values()].map(
|
|
2245
|
+
(tx) => this.#runSerialized(tx, async () => {
|
|
2246
|
+
const current = this.transactions.get(tx.id);
|
|
2247
|
+
if (current) {
|
|
2248
|
+
await this.#closeTransaction(current, "rolled_back");
|
|
2249
|
+
}
|
|
2250
|
+
})
|
|
2251
|
+
)
|
|
2252
|
+
);
|
|
2253
|
+
}
|
|
2254
|
+
#nextSavepointName(transaction) {
|
|
2255
|
+
return `prisma_sp_${transaction.savepointCounter++}`;
|
|
2256
|
+
}
|
|
2257
|
+
#requiredCreateSavepoint(transaction) {
|
|
2258
|
+
if (transaction.createSavepoint) {
|
|
2259
|
+
return transaction.createSavepoint.bind(transaction);
|
|
2260
|
+
}
|
|
2261
|
+
throw new TransactionManagerError(
|
|
2262
|
+
`Nested transactions are not supported by adapter "${transaction.adapterName}" (${transaction.provider}): createSavepoint is not implemented.`
|
|
2263
|
+
);
|
|
2264
|
+
}
|
|
2265
|
+
#requiredRollbackToSavepoint(transaction) {
|
|
2266
|
+
if (transaction.rollbackToSavepoint) {
|
|
2267
|
+
return transaction.rollbackToSavepoint.bind(transaction);
|
|
2268
|
+
}
|
|
2269
|
+
throw new TransactionManagerError(
|
|
2270
|
+
`Nested transactions are not supported by adapter "${transaction.adapterName}" (${transaction.provider}): rollbackToSavepoint is not implemented.`
|
|
2271
|
+
);
|
|
2272
|
+
}
|
|
2273
|
+
async #releaseSavepoint(transaction, name) {
|
|
2274
|
+
if (transaction.releaseSavepoint) {
|
|
2275
|
+
await transaction.releaseSavepoint(name);
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
2278
|
+
#debugTransactionAlreadyClosedOnTimeout(transactionId) {
|
|
2279
|
+
debug("Transaction already committed or rolled back when timeout happened.", transactionId);
|
|
2116
2280
|
}
|
|
2117
2281
|
#startTransactionTimeout(transactionId, timeout) {
|
|
2118
2282
|
const timeoutStartedAt = Date.now();
|
|
2119
2283
|
const timer = createTimeoutIfDefined(async () => {
|
|
2120
2284
|
debug("Transaction timed out.", { transactionId, timeoutStartedAt, timeout });
|
|
2121
2285
|
const tx = this.transactions.get(transactionId);
|
|
2122
|
-
if (tx
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2286
|
+
if (!tx) {
|
|
2287
|
+
this.#debugTransactionAlreadyClosedOnTimeout(transactionId);
|
|
2288
|
+
return;
|
|
2289
|
+
}
|
|
2290
|
+
await this.#runSerialized(tx, async () => {
|
|
2291
|
+
const current = this.transactions.get(transactionId);
|
|
2292
|
+
if (current && ["running", "waiting"].includes(current.status)) {
|
|
2293
|
+
await this.#closeTransaction(current, "timed_out");
|
|
2294
|
+
} else {
|
|
2295
|
+
this.#debugTransactionAlreadyClosedOnTimeout(transactionId);
|
|
2296
|
+
}
|
|
2297
|
+
});
|
|
2127
2298
|
}, timeout);
|
|
2128
2299
|
timer?.unref?.();
|
|
2129
2300
|
return timer;
|
|
2130
2301
|
}
|
|
2302
|
+
// Any operation that mutates or closes a transaction must run through this lock so
|
|
2303
|
+
// status/savepoint/depth checks and updates happen against a stable view of state.
|
|
2304
|
+
async #withActiveTransactionLock(transactionId, operation, callback) {
|
|
2305
|
+
const tx = this.#getActiveOrClosingTransaction(transactionId, operation);
|
|
2306
|
+
return await this.#runSerialized(tx, async () => {
|
|
2307
|
+
const current = this.#getActiveOrClosingTransaction(transactionId, operation);
|
|
2308
|
+
return await callback(current);
|
|
2309
|
+
});
|
|
2310
|
+
}
|
|
2311
|
+
// Serializes operations per transaction id to prevent interleaving across awaits.
|
|
2312
|
+
// This avoids races where one operation mutates savepoint/depth state while another
|
|
2313
|
+
// operation is suspended, which could otherwise corrupt cleanup logic.
|
|
2314
|
+
async #runSerialized(tx, callback) {
|
|
2315
|
+
const previousOperation = tx.operationQueue;
|
|
2316
|
+
let releaseOperationLock;
|
|
2317
|
+
tx.operationQueue = new Promise((resolve) => {
|
|
2318
|
+
releaseOperationLock = resolve;
|
|
2319
|
+
});
|
|
2320
|
+
await previousOperation;
|
|
2321
|
+
try {
|
|
2322
|
+
return await callback();
|
|
2323
|
+
} finally {
|
|
2324
|
+
releaseOperationLock();
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2131
2327
|
async #closeTransaction(tx, status) {
|
|
2132
2328
|
const createClosingPromise = async () => {
|
|
2133
2329
|
debug("Closing transaction.", { transactionId: tx.id, status });
|
|
@@ -2214,7 +2410,7 @@ export {
|
|
|
2214
2410
|
UserFacingError,
|
|
2215
2411
|
applySqlCommenters,
|
|
2216
2412
|
convertCompactedRows,
|
|
2217
|
-
|
|
2413
|
+
deserializeJsonObject,
|
|
2218
2414
|
doKeysMatch,
|
|
2219
2415
|
isDeepStrictEqual,
|
|
2220
2416
|
isPrismaValueGenerator,
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { InMemoryOps } from '../query-plan';
|
|
2
2
|
export declare function processRecords(value: unknown, ops: InMemoryOps): unknown;
|
|
3
|
-
export declare function getRecordKey(record: {}, fields: string[]): string;
|
|
3
|
+
export declare function getRecordKey(record: {}, fields: readonly string[], mappers?: ((value: unknown) => unknown)[]): string;
|
|
@@ -5,6 +5,7 @@ import { QueryPlanNode } from '../query-plan';
|
|
|
5
5
|
import { type SchemaProvider } from '../schema';
|
|
6
6
|
import { type TracingHelper } from '../tracing';
|
|
7
7
|
import { type TransactionManager } from '../transaction-manager/transaction-manager';
|
|
8
|
+
import { DeepReadonly } from '../utils';
|
|
8
9
|
import { Value } from './scope';
|
|
9
10
|
export type QueryInterpreterTransactionManager = {
|
|
10
11
|
enabled: true;
|
|
@@ -39,6 +40,6 @@ export declare class QueryInterpreter {
|
|
|
39
40
|
provider?: SchemaProvider;
|
|
40
41
|
connectionInfo?: ConnectionInfo;
|
|
41
42
|
}): QueryInterpreter;
|
|
42
|
-
run(queryPlan: QueryPlanNode
|
|
43
|
+
run(queryPlan: DeepReadonly<QueryPlanNode>, options: QueryRuntimeOptions): Promise<unknown>;
|
|
43
44
|
private interpretNode;
|
|
44
45
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SqlQuery } from '@prisma/driver-adapter-utils';
|
|
2
2
|
import { type QueryPlanDbQuery } from '../query-plan';
|
|
3
|
+
import { DeepReadonly } from '../utils';
|
|
3
4
|
import { GeneratorRegistrySnapshot } from './generators';
|
|
4
5
|
import { ScopeBindings } from './scope';
|
|
5
|
-
export declare function renderQuery(dbQuery: QueryPlanDbQuery
|
|
6
|
+
export declare function renderQuery(dbQuery: DeepReadonly<QueryPlanDbQuery>, scope: ScopeBindings, generators: GeneratorRegistrySnapshot, maxChunkSize?: number): DeepReadonly<SqlQuery>[];
|
|
6
7
|
export declare function evaluateArg(arg: unknown, scope: ScopeBindings, generators: GeneratorRegistrySnapshot): unknown;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { DataRule, ValidationError } from '../query-plan';
|
|
2
|
-
|
|
2
|
+
import { DeepReadonly } from '../utils';
|
|
3
|
+
export declare function performValidation(data: unknown, rules: DeepReadonly<DataRule[]>, error: ValidationError): void;
|
|
3
4
|
export declare function doesSatisfyRule(data: unknown, rule: DataRule): boolean;
|
package/dist/json-protocol.d.ts
CHANGED
|
@@ -29,10 +29,14 @@ export type JsonTaggedValue = {
|
|
|
29
29
|
$type: 'Json';
|
|
30
30
|
value: string;
|
|
31
31
|
};
|
|
32
|
-
export type
|
|
32
|
+
export type RawTaggedValue = {
|
|
33
|
+
$type: 'Raw';
|
|
34
|
+
value: unknown;
|
|
35
|
+
};
|
|
36
|
+
export type JsonInputTaggedValue = DateTaggedValue | DecimalTaggedValue | BytesTaggedValue | BigIntTaggedValue | FieldRefTaggedValue | JsonTaggedValue | EnumTaggedValue | RawTaggedValue;
|
|
33
37
|
export type JsonOutputTaggedValue = DateTaggedValue | DecimalTaggedValue | BytesTaggedValue | BigIntTaggedValue | JsonTaggedValue;
|
|
34
38
|
export type JsOutputValue = null | string | number | boolean | bigint | Uint8Array | Date | Decimal | JsOutputValue[] | {
|
|
35
39
|
[key: string]: JsOutputValue;
|
|
36
40
|
};
|
|
37
41
|
export declare function normalizeJsonProtocolValues(result: unknown): unknown;
|
|
38
|
-
export declare function
|
|
42
|
+
export declare function deserializeJsonObject(result: unknown): unknown;
|
package/dist/query-plan.d.ts
CHANGED
|
@@ -56,6 +56,9 @@ export type Fragment = {
|
|
|
56
56
|
type: 'parameter';
|
|
57
57
|
} | {
|
|
58
58
|
type: 'parameterTuple';
|
|
59
|
+
itemPrefix: string;
|
|
60
|
+
itemSeparator: string;
|
|
61
|
+
itemSuffix: string;
|
|
59
62
|
} | {
|
|
60
63
|
type: 'parameterTupleList';
|
|
61
64
|
itemPrefix: string;
|
|
@@ -121,6 +124,7 @@ export type QueryPlanNode = {
|
|
|
121
124
|
args: {
|
|
122
125
|
parent: QueryPlanNode;
|
|
123
126
|
children: JoinExpression[];
|
|
127
|
+
canAssumeStrictEquality: boolean;
|
|
124
128
|
};
|
|
125
129
|
} | {
|
|
126
130
|
type: 'mapField';
|
|
@@ -227,14 +231,14 @@ export type DataRule = {
|
|
|
227
231
|
type: 'never';
|
|
228
232
|
};
|
|
229
233
|
export type ValidationError = {
|
|
230
|
-
|
|
234
|
+
errorIdentifier: 'RELATION_VIOLATION';
|
|
231
235
|
context: {
|
|
232
236
|
relation: string;
|
|
233
237
|
modelA: string;
|
|
234
238
|
modelB: string;
|
|
235
239
|
};
|
|
236
240
|
} | {
|
|
237
|
-
|
|
241
|
+
errorIdentifier: 'MISSING_RELATED_RECORD';
|
|
238
242
|
context: {
|
|
239
243
|
model: string;
|
|
240
244
|
relation: string;
|
|
@@ -243,24 +247,24 @@ export type ValidationError = {
|
|
|
243
247
|
neededFor?: string;
|
|
244
248
|
};
|
|
245
249
|
} | {
|
|
246
|
-
|
|
250
|
+
errorIdentifier: 'MISSING_RECORD';
|
|
247
251
|
context: {
|
|
248
252
|
operation: string;
|
|
249
253
|
};
|
|
250
254
|
} | {
|
|
251
|
-
|
|
255
|
+
errorIdentifier: 'INCOMPLETE_CONNECT_INPUT';
|
|
252
256
|
context: {
|
|
253
257
|
expectedRows: number;
|
|
254
258
|
};
|
|
255
259
|
} | {
|
|
256
|
-
|
|
260
|
+
errorIdentifier: 'INCOMPLETE_CONNECT_OUTPUT';
|
|
257
261
|
context: {
|
|
258
262
|
expectedRows: number;
|
|
259
263
|
relation: string;
|
|
260
264
|
relationType: string;
|
|
261
265
|
};
|
|
262
266
|
} | {
|
|
263
|
-
|
|
267
|
+
errorIdentifier: 'RECORDS_NOT_CONNECTED';
|
|
264
268
|
context: {
|
|
265
269
|
relation: string;
|
|
266
270
|
parent: string;
|
package/dist/tracing.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { type Context, type Span, type SpanOptions } from '@opentelemetry/api';
|
|
|
2
2
|
import type { SqlQuery } from '@prisma/driver-adapter-utils';
|
|
3
3
|
import { QueryEvent } from './events';
|
|
4
4
|
import type { SchemaProvider } from './schema';
|
|
5
|
+
import { DeepReadonly } from './utils';
|
|
5
6
|
export type SpanCallback<R> = (span?: Span, context?: Context) => R;
|
|
6
7
|
export type ExtendedSpanOptions = SpanOptions & {
|
|
7
8
|
name: string;
|
|
@@ -13,7 +14,7 @@ export interface TracingHelper {
|
|
|
13
14
|
export declare const noopTracingHelper: TracingHelper;
|
|
14
15
|
export declare function providerToOtelSystem(provider: SchemaProvider): string;
|
|
15
16
|
export declare function withQuerySpanAndEvent<T>({ query, tracingHelper, provider, onQuery, execute, }: {
|
|
16
|
-
query: SqlQuery
|
|
17
|
+
query: DeepReadonly<SqlQuery>;
|
|
17
18
|
tracingHelper: TracingHelper;
|
|
18
19
|
provider: SchemaProvider;
|
|
19
20
|
onQuery?: (event: QueryEvent) => void;
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
export type DeepReadonly<T> = T extends undefined | null | boolean | string | number | symbol | Function | Date ? T : T extends Array<infer U> ? ReadonlyArray<DeepReadonly<U>> : unknown extends T ? unknown : {
|
|
2
|
+
readonly [K in keyof T]: DeepReadonly<T[K]>;
|
|
3
|
+
};
|
|
4
|
+
export type DeepUnreadonly<T> = T extends undefined | null | boolean | string | number | symbol | Function | Date ? T : T extends ReadonlyArray<infer U> ? Array<DeepUnreadonly<U>> : unknown extends T ? unknown : {
|
|
5
|
+
-readonly [K in keyof T]: DeepUnreadonly<T[K]>;
|
|
6
|
+
};
|
|
1
7
|
export declare function assertNever(_: never, message: string): never;
|
|
2
8
|
/**
|
|
3
9
|
* Checks if two objects are deeply equal, recursively checking all properties for strict equality.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/client-engine-runtime",
|
|
3
|
-
"version": "7.5.0-dev.
|
|
3
|
+
"version": "7.5.0-dev.31",
|
|
4
4
|
"description": "This package is intended for Prisma's internal use",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -31,19 +31,16 @@
|
|
|
31
31
|
"nanoid": "5.1.5",
|
|
32
32
|
"ulid": "3.0.0",
|
|
33
33
|
"uuid": "11.1.0",
|
|
34
|
-
"@prisma/
|
|
35
|
-
"@prisma/
|
|
36
|
-
"@prisma/
|
|
37
|
-
"@prisma/
|
|
34
|
+
"@prisma/client-runtime-utils": "7.5.0-dev.31",
|
|
35
|
+
"@prisma/driver-adapter-utils": "7.5.0-dev.31",
|
|
36
|
+
"@prisma/sqlcommenter": "7.5.0-dev.31",
|
|
37
|
+
"@prisma/debug": "7.5.0-dev.31"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@codspeed/benchmark.js-plugin": "4.0.0",
|
|
41
41
|
"@types/benchmark": "2.1.5",
|
|
42
|
-
"@types/jest": "29.5.14",
|
|
43
42
|
"@types/node": "~20.19.24",
|
|
44
|
-
"benchmark": "2.1.4"
|
|
45
|
-
"jest": "29.7.0",
|
|
46
|
-
"jest-junit": "16.0.0"
|
|
43
|
+
"benchmark": "2.1.4"
|
|
47
44
|
},
|
|
48
45
|
"files": [
|
|
49
46
|
"dist"
|
|
@@ -52,6 +49,6 @@
|
|
|
52
49
|
"scripts": {
|
|
53
50
|
"dev": "DEV=true tsx helpers/build.ts",
|
|
54
51
|
"build": "tsx helpers/build.ts",
|
|
55
|
-
"test": "
|
|
52
|
+
"test": "vitest run"
|
|
56
53
|
}
|
|
57
54
|
}
|