@prisma/client-engine-runtime 6.9.0-dev.2 → 6.9.0-dev.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/QueryPlan.d.ts +36 -1
- package/dist/UserFacingError.d.ts +3 -3
- package/dist/index.d.mts +63 -9
- package/dist/index.d.ts +63 -9
- package/dist/index.js +321 -115
- package/dist/index.mjs +317 -115
- package/dist/interpreter/DataMapper.d.ts +3 -0
- package/dist/interpreter/QueryInterpreter.d.ts +2 -1
- package/dist/interpreter/serializeSql.d.ts +2 -1
- package/dist/transactionManager/TransactionManagerErrors.d.ts +4 -4
- package/dist/utils.d.ts +10 -0
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,144 @@
|
|
|
1
|
-
// src/interpreter/
|
|
2
|
-
import
|
|
1
|
+
// src/interpreter/DataMapper.ts
|
|
2
|
+
import Decimal2 from "decimal.js";
|
|
3
3
|
|
|
4
4
|
// src/utils.ts
|
|
5
|
+
import Decimal from "decimal.js";
|
|
5
6
|
function assertNever(_, message) {
|
|
6
7
|
throw new Error(message);
|
|
7
8
|
}
|
|
9
|
+
function isDeepStrictEqual(a, b) {
|
|
10
|
+
return a === b || a !== null && b !== null && typeof a === "object" && typeof b === "object" && Object.keys(a).length === Object.keys(b).length && Object.keys(a).every((key) => isDeepStrictEqual(a[key], b[key]));
|
|
11
|
+
}
|
|
12
|
+
function doKeysMatch(lhs, rhs) {
|
|
13
|
+
const lhsKeys = Object.keys(lhs);
|
|
14
|
+
const rhsKeys = Object.keys(rhs);
|
|
15
|
+
const smallerKeyList = lhsKeys.length < rhsKeys.length ? lhsKeys : rhsKeys;
|
|
16
|
+
return smallerKeyList.every((key) => {
|
|
17
|
+
if (typeof lhs[key] !== typeof rhs[key]) {
|
|
18
|
+
if (typeof lhs[key] === "number" || typeof rhs[key] === "number") {
|
|
19
|
+
return `${lhs[key]}` === `${rhs[key]}`;
|
|
20
|
+
} else if (typeof lhs[key] === "bigint" || typeof rhs[key] === "bigint") {
|
|
21
|
+
return BigInt(`${lhs[key]}`.replace(/n$/, "")) === BigInt(`${rhs[key]}`.replace(/n$/, ""));
|
|
22
|
+
} else if (lhs[key] instanceof Date || rhs[key] instanceof Date) {
|
|
23
|
+
return (/* @__PURE__ */ new Date(`${lhs[key]}`)).getTime() === (/* @__PURE__ */ new Date(`${rhs[key]}`)).getTime();
|
|
24
|
+
} else if (Decimal.isDecimal(lhs[key]) || Decimal.isDecimal(rhs[key])) {
|
|
25
|
+
return new Decimal(`${lhs[key]}`).equals(new Decimal(`${rhs[key]}`));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return isDeepStrictEqual(lhs[key], rhs[key]);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/interpreter/DataMapper.ts
|
|
33
|
+
var DataMapperError = class extends Error {
|
|
34
|
+
name = "DataMapperError";
|
|
35
|
+
};
|
|
36
|
+
function applyDataMap(data, structure) {
|
|
37
|
+
switch (structure.type) {
|
|
38
|
+
case "Object":
|
|
39
|
+
return mapArrayOrObject(data, structure.fields);
|
|
40
|
+
case "Value":
|
|
41
|
+
return mapValue(data, structure.resultType);
|
|
42
|
+
default:
|
|
43
|
+
assertNever(structure, `Invalid data mapping type: '${structure.type}'`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function mapArrayOrObject(data, fields) {
|
|
47
|
+
if (data === null) return null;
|
|
48
|
+
if (Array.isArray(data)) {
|
|
49
|
+
const rows = data;
|
|
50
|
+
return rows.map((row) => mapObject(row, fields));
|
|
51
|
+
}
|
|
52
|
+
if (typeof data === "object") {
|
|
53
|
+
const row = data;
|
|
54
|
+
return mapObject(row, fields);
|
|
55
|
+
}
|
|
56
|
+
if (typeof data === "string") {
|
|
57
|
+
let decodedData;
|
|
58
|
+
try {
|
|
59
|
+
decodedData = JSON.parse(data);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
throw new DataMapperError(`Expected an array or object, got a string that is not valid JSON`, {
|
|
62
|
+
cause: error
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return mapArrayOrObject(decodedData, fields);
|
|
66
|
+
}
|
|
67
|
+
throw new DataMapperError(`Expected an array or an object, got: ${typeof data}`);
|
|
68
|
+
}
|
|
69
|
+
function mapObject(data, fields) {
|
|
70
|
+
if (typeof data !== "object") {
|
|
71
|
+
throw new DataMapperError(`Expected an object, but got '${typeof data}'`);
|
|
72
|
+
}
|
|
73
|
+
const result = {};
|
|
74
|
+
for (const [name, node] of Object.entries(fields)) {
|
|
75
|
+
switch (node.type) {
|
|
76
|
+
case "Object": {
|
|
77
|
+
if (!node.flattened && !Object.hasOwn(data, name)) {
|
|
78
|
+
throw new DataMapperError(
|
|
79
|
+
`Missing data field (Object): '${name}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
const target = node.flattened ? data : data[name];
|
|
83
|
+
result[name] = mapArrayOrObject(target, node.fields);
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
case "Value":
|
|
87
|
+
{
|
|
88
|
+
const dbName = node.dbName;
|
|
89
|
+
if (Object.hasOwn(data, dbName)) {
|
|
90
|
+
result[name] = mapValue(data[dbName], node.resultType);
|
|
91
|
+
} else {
|
|
92
|
+
throw new DataMapperError(
|
|
93
|
+
`Missing data field (Value): '${dbName}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
default:
|
|
99
|
+
assertNever(node, `DataMapper: Invalid data mapping node type: '${node.type}'`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
function mapValue(value, resultType) {
|
|
105
|
+
if (value === null) return null;
|
|
106
|
+
switch (resultType.type) {
|
|
107
|
+
case "Any":
|
|
108
|
+
return value;
|
|
109
|
+
case "String":
|
|
110
|
+
return typeof value === "string" ? value : `${value}`;
|
|
111
|
+
case "Int":
|
|
112
|
+
return typeof value === "number" ? value : parseInt(`${value}`, 10);
|
|
113
|
+
case "BigInt":
|
|
114
|
+
return typeof value === "bigint" ? value : BigInt(`${value}`);
|
|
115
|
+
case "Float":
|
|
116
|
+
return typeof value === "number" ? value : parseFloat(`${value}`);
|
|
117
|
+
case "Boolean":
|
|
118
|
+
return typeof value === "boolean" ? value : value !== "0";
|
|
119
|
+
case "Decimal":
|
|
120
|
+
return typeof value === "number" ? new Decimal2(value) : new Decimal2(`${value}`);
|
|
121
|
+
case "Date":
|
|
122
|
+
return value instanceof Date ? value : /* @__PURE__ */ new Date(`${value}`);
|
|
123
|
+
case "Array": {
|
|
124
|
+
const values = value;
|
|
125
|
+
return values.map((v) => mapValue(v, resultType.inner));
|
|
126
|
+
}
|
|
127
|
+
case "Object":
|
|
128
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
129
|
+
case "Bytes": {
|
|
130
|
+
if (!Array.isArray(value)) {
|
|
131
|
+
throw new DataMapperError(`Bytes data is invalid, got: ${typeof value}`);
|
|
132
|
+
}
|
|
133
|
+
return new Uint8Array(value);
|
|
134
|
+
}
|
|
135
|
+
default:
|
|
136
|
+
assertNever(resultType, `DataMapper: Unknown result type: ${resultType.type}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// src/interpreter/QueryInterpreter.ts
|
|
141
|
+
import { SpanKind } from "@opentelemetry/api";
|
|
8
142
|
|
|
9
143
|
// src/tracing.ts
|
|
10
144
|
var noopTracingHelper = {
|
|
@@ -34,7 +168,7 @@ var UserFacingError = class extends Error {
|
|
|
34
168
|
constructor(message, code, meta) {
|
|
35
169
|
super(message);
|
|
36
170
|
this.code = code;
|
|
37
|
-
this.meta = meta;
|
|
171
|
+
this.meta = meta ?? {};
|
|
38
172
|
}
|
|
39
173
|
toQueryResponseErrorObject() {
|
|
40
174
|
return {
|
|
@@ -57,7 +191,7 @@ function rethrowAsUserFacing(error) {
|
|
|
57
191
|
if (!code || !message) {
|
|
58
192
|
throw error;
|
|
59
193
|
}
|
|
60
|
-
throw new UserFacingError(message, code, error);
|
|
194
|
+
throw new UserFacingError(message, code, { driverAdapterError: error });
|
|
61
195
|
}
|
|
62
196
|
function getErrorCode(err) {
|
|
63
197
|
switch (err.cause.kind) {
|
|
@@ -168,100 +302,6 @@ function renderConstraint(constraint) {
|
|
|
168
302
|
return "(not available)";
|
|
169
303
|
}
|
|
170
304
|
|
|
171
|
-
// src/interpreter/DataMapper.ts
|
|
172
|
-
import Decimal from "decimal.js";
|
|
173
|
-
function applyDataMap(data, structure) {
|
|
174
|
-
switch (structure.type) {
|
|
175
|
-
case "Object":
|
|
176
|
-
return mapArrayOrObject(data, structure.fields);
|
|
177
|
-
case "Value":
|
|
178
|
-
return mapValue(data, structure.resultType);
|
|
179
|
-
default:
|
|
180
|
-
assertNever(structure, `Invalid data mapping type: '${structure.type}'`);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
function mapArrayOrObject(data, fields) {
|
|
184
|
-
if (data === null) return null;
|
|
185
|
-
if (Array.isArray(data)) {
|
|
186
|
-
const rows = data;
|
|
187
|
-
return rows.map((row) => mapObject(row, fields));
|
|
188
|
-
}
|
|
189
|
-
if (typeof data === "object") {
|
|
190
|
-
const row = data;
|
|
191
|
-
return mapObject(row, fields);
|
|
192
|
-
}
|
|
193
|
-
throw new Error(`DataMapper: Expected an array or an object, got: ${typeof data}`);
|
|
194
|
-
}
|
|
195
|
-
function mapObject(data, fields) {
|
|
196
|
-
if (typeof data !== "object") {
|
|
197
|
-
throw new Error(`DataMapper: Expected an object, but got '${typeof data}'`);
|
|
198
|
-
}
|
|
199
|
-
const result = {};
|
|
200
|
-
for (const [name, node] of Object.entries(fields)) {
|
|
201
|
-
switch (node.type) {
|
|
202
|
-
case "Object":
|
|
203
|
-
if (Object.hasOwn(data, name)) {
|
|
204
|
-
result[name] = mapArrayOrObject(data[name], node.fields);
|
|
205
|
-
} else {
|
|
206
|
-
throw new Error(
|
|
207
|
-
`DataMapper: Missing data field (Object): '${name}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
|
|
208
|
-
);
|
|
209
|
-
}
|
|
210
|
-
break;
|
|
211
|
-
case "Value":
|
|
212
|
-
{
|
|
213
|
-
const dbName = node.dbName;
|
|
214
|
-
if (Object.hasOwn(data, dbName)) {
|
|
215
|
-
result[name] = mapValue(data[dbName], node.resultType);
|
|
216
|
-
} else {
|
|
217
|
-
throw new Error(
|
|
218
|
-
`DataMapper: Missing data field (Value): '${dbName}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
break;
|
|
223
|
-
default:
|
|
224
|
-
assertNever(node, `DataMapper: Invalid data mapping node type: '${node.type}'`);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
return result;
|
|
228
|
-
}
|
|
229
|
-
function mapValue(value, resultType) {
|
|
230
|
-
if (value === null) return null;
|
|
231
|
-
switch (resultType.type) {
|
|
232
|
-
case "Any":
|
|
233
|
-
return value;
|
|
234
|
-
case "String":
|
|
235
|
-
return typeof value === "string" ? value : `${value}`;
|
|
236
|
-
case "Int":
|
|
237
|
-
return typeof value === "number" ? value : parseInt(`${value}`, 10);
|
|
238
|
-
case "BigInt":
|
|
239
|
-
return typeof value === "bigint" ? value : BigInt(`${value}`);
|
|
240
|
-
case "Float":
|
|
241
|
-
return typeof value === "number" ? value : parseFloat(`${value}`);
|
|
242
|
-
case "Boolean":
|
|
243
|
-
return typeof value === "boolean" ? value : value !== "0";
|
|
244
|
-
case "Decimal":
|
|
245
|
-
return typeof value === "number" ? new Decimal(value) : new Decimal(`${value}`);
|
|
246
|
-
case "Date":
|
|
247
|
-
return value instanceof Date ? value : /* @__PURE__ */ new Date(`${value}`);
|
|
248
|
-
case "Array": {
|
|
249
|
-
const values = value;
|
|
250
|
-
return values.map((v) => mapValue(v, resultType.inner));
|
|
251
|
-
}
|
|
252
|
-
case "Object":
|
|
253
|
-
return typeof value === "string" ? value : JSON.stringify(value);
|
|
254
|
-
case "Bytes": {
|
|
255
|
-
if (!Array.isArray(value)) {
|
|
256
|
-
throw new Error(`DataMapper: Bytes data is invalid, got: ${typeof value}`);
|
|
257
|
-
}
|
|
258
|
-
return new Uint8Array(value);
|
|
259
|
-
}
|
|
260
|
-
default:
|
|
261
|
-
assertNever(resultType, `DataMapper: Unknown result type: ${resultType.type}`);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
305
|
// src/interpreter/generators.ts
|
|
266
306
|
import cuid1 from "@bugsnag/cuid";
|
|
267
307
|
import { createId as cuid2 } from "@paralleldrive/cuid2";
|
|
@@ -366,6 +406,9 @@ function isPrismaValueGenerator(value) {
|
|
|
366
406
|
function isPrismaValueBytes(value) {
|
|
367
407
|
return typeof value === "object" && value !== null && value["prisma__type"] === "bytes";
|
|
368
408
|
}
|
|
409
|
+
function isPrismaValueBigInt(value) {
|
|
410
|
+
return typeof value === "object" && value !== null && value["prisma__type"] === "bigint";
|
|
411
|
+
}
|
|
369
412
|
|
|
370
413
|
// src/interpreter/renderQuery.ts
|
|
371
414
|
function renderQuery(dbQuery, scope, generators) {
|
|
@@ -408,9 +451,10 @@ function evaluateParam(param, scope, generators) {
|
|
|
408
451
|
}
|
|
409
452
|
if (Array.isArray(value)) {
|
|
410
453
|
value = value.map((el) => evaluateParam(el, scope, generators));
|
|
411
|
-
}
|
|
412
|
-
if (isPrismaValueBytes(value)) {
|
|
454
|
+
} else if (isPrismaValueBytes(value)) {
|
|
413
455
|
value = Buffer.from(value.prisma__value, "base64");
|
|
456
|
+
} else if (isPrismaValueBigInt(value)) {
|
|
457
|
+
value = BigInt(value.prisma__value);
|
|
414
458
|
}
|
|
415
459
|
return value;
|
|
416
460
|
}
|
|
@@ -504,6 +548,7 @@ function doesRequireEvaluation(param) {
|
|
|
504
548
|
}
|
|
505
549
|
|
|
506
550
|
// src/interpreter/serializeSql.ts
|
|
551
|
+
import { ColumnTypeEnum } from "@prisma/driver-adapter-utils";
|
|
507
552
|
function serializeSql(resultSet) {
|
|
508
553
|
return resultSet.rows.map(
|
|
509
554
|
(row) => row.reduce((acc, value, index) => {
|
|
@@ -524,6 +569,85 @@ function serializeSql(resultSet) {
|
|
|
524
569
|
}, {})
|
|
525
570
|
);
|
|
526
571
|
}
|
|
572
|
+
function serializeRawSql(resultSet) {
|
|
573
|
+
return {
|
|
574
|
+
columns: resultSet.columnNames,
|
|
575
|
+
types: resultSet.columnTypes.map((type) => serializeColumnType(type)),
|
|
576
|
+
rows: resultSet.rows
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
function serializeColumnType(columnType) {
|
|
580
|
+
switch (columnType) {
|
|
581
|
+
case ColumnTypeEnum.Int32:
|
|
582
|
+
return "int";
|
|
583
|
+
case ColumnTypeEnum.Int64:
|
|
584
|
+
return "bigint";
|
|
585
|
+
case ColumnTypeEnum.Float:
|
|
586
|
+
return "float";
|
|
587
|
+
case ColumnTypeEnum.Double:
|
|
588
|
+
return "double";
|
|
589
|
+
case ColumnTypeEnum.Text:
|
|
590
|
+
return "string";
|
|
591
|
+
case ColumnTypeEnum.Enum:
|
|
592
|
+
return "enum";
|
|
593
|
+
case ColumnTypeEnum.Bytes:
|
|
594
|
+
return "bytes";
|
|
595
|
+
case ColumnTypeEnum.Boolean:
|
|
596
|
+
return "bool";
|
|
597
|
+
case ColumnTypeEnum.Character:
|
|
598
|
+
return "char";
|
|
599
|
+
case ColumnTypeEnum.Numeric:
|
|
600
|
+
return "decimal";
|
|
601
|
+
case ColumnTypeEnum.Json:
|
|
602
|
+
return "json";
|
|
603
|
+
case ColumnTypeEnum.Uuid:
|
|
604
|
+
return "uuid";
|
|
605
|
+
case ColumnTypeEnum.DateTime:
|
|
606
|
+
return "datetime";
|
|
607
|
+
case ColumnTypeEnum.Date:
|
|
608
|
+
return "date";
|
|
609
|
+
case ColumnTypeEnum.Time:
|
|
610
|
+
return "time";
|
|
611
|
+
case ColumnTypeEnum.Int32Array:
|
|
612
|
+
return "int-array";
|
|
613
|
+
case ColumnTypeEnum.Int64Array:
|
|
614
|
+
return "bigint-array";
|
|
615
|
+
case ColumnTypeEnum.FloatArray:
|
|
616
|
+
return "float-array";
|
|
617
|
+
case ColumnTypeEnum.DoubleArray:
|
|
618
|
+
return "double-array";
|
|
619
|
+
case ColumnTypeEnum.TextArray:
|
|
620
|
+
return "string-array";
|
|
621
|
+
case ColumnTypeEnum.EnumArray:
|
|
622
|
+
return "string-array";
|
|
623
|
+
case ColumnTypeEnum.BytesArray:
|
|
624
|
+
return "bytes-array";
|
|
625
|
+
case ColumnTypeEnum.BooleanArray:
|
|
626
|
+
return "bool-array";
|
|
627
|
+
case ColumnTypeEnum.CharacterArray:
|
|
628
|
+
return "char-array";
|
|
629
|
+
case ColumnTypeEnum.NumericArray:
|
|
630
|
+
return "decimal-array";
|
|
631
|
+
case ColumnTypeEnum.JsonArray:
|
|
632
|
+
return "json-array";
|
|
633
|
+
case ColumnTypeEnum.UuidArray:
|
|
634
|
+
return "uuid-array";
|
|
635
|
+
case ColumnTypeEnum.DateTimeArray:
|
|
636
|
+
return "datetime-array";
|
|
637
|
+
case ColumnTypeEnum.DateArray:
|
|
638
|
+
return "date-array";
|
|
639
|
+
case ColumnTypeEnum.TimeArray:
|
|
640
|
+
return "time-array";
|
|
641
|
+
case ColumnTypeEnum.UnknownNumber:
|
|
642
|
+
return "unknown";
|
|
643
|
+
/// The following PlanetScale type IDs are mapped into Set:
|
|
644
|
+
/// - SET (SET) -> e.g. `"foo,bar"` (String-encoded, comma-separated)
|
|
645
|
+
case ColumnTypeEnum.Set:
|
|
646
|
+
return "string";
|
|
647
|
+
default:
|
|
648
|
+
assertNever(columnType, `Unexpected column type: ${columnType}`);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
527
651
|
|
|
528
652
|
// src/interpreter/validation.ts
|
|
529
653
|
function performValidation(data, rules, error) {
|
|
@@ -551,6 +675,8 @@ function doesSatisfyRule(data, rule) {
|
|
|
551
675
|
return rule.args !== 0;
|
|
552
676
|
}
|
|
553
677
|
return rule.args !== 1;
|
|
678
|
+
case "affectedRowCountEq":
|
|
679
|
+
return data === rule.args;
|
|
554
680
|
case "never":
|
|
555
681
|
return false;
|
|
556
682
|
default:
|
|
@@ -568,7 +694,9 @@ function renderMessage(data, error) {
|
|
|
568
694
|
return `An operation failed because it depends on one or more records that were required but not found. No '${error.context.model}' record${hint} was found for ${error.context.operation} on ${error.context.relationType} relation '${error.context.relation}'.`;
|
|
569
695
|
}
|
|
570
696
|
case "INCOMPLETE_CONNECT_INPUT":
|
|
571
|
-
return `An operation failed because it depends on one or more records that were required but not found. Expected ${error.context.expectedRows} records to be connected, found only ${Array.isArray(data) ? data.length :
|
|
697
|
+
return `An operation failed because it depends on one or more records that were required but not found. Expected ${error.context.expectedRows} records to be connected, found only ${Array.isArray(data) ? data.length : data}.`;
|
|
698
|
+
case "INCOMPLETE_CONNECT_OUTPUT":
|
|
699
|
+
return `The required connected records were not found. Expected ${error.context.expectedRows} records to be connected after connect operation on ${error.context.relationType} relation '${error.context.relation}', found ${Array.isArray(data) ? data.length : data}.`;
|
|
572
700
|
case "RECORDS_NOT_CONNECTED":
|
|
573
701
|
return `The records for relation \`${error.context.relation}\` between the \`${error.context.parent}\` and \`${error.context.child}\` models are not connected.`;
|
|
574
702
|
default:
|
|
@@ -581,6 +709,8 @@ function getErrorCode2(error) {
|
|
|
581
709
|
return "P2014";
|
|
582
710
|
case "RECORDS_NOT_CONNECTED":
|
|
583
711
|
return "P2017";
|
|
712
|
+
case "INCOMPLETE_CONNECT_OUTPUT":
|
|
713
|
+
return "P2018";
|
|
584
714
|
case "MISSING_RECORD":
|
|
585
715
|
case "MISSING_RELATED_RECORD":
|
|
586
716
|
case "INCOMPLETE_CONNECT_INPUT":
|
|
@@ -598,12 +728,21 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
598
728
|
#generators = new GeneratorRegistry();
|
|
599
729
|
#tracingHelper;
|
|
600
730
|
#serializer;
|
|
601
|
-
|
|
731
|
+
#rawSerializer;
|
|
732
|
+
constructor({
|
|
733
|
+
transactionManager,
|
|
734
|
+
placeholderValues,
|
|
735
|
+
onQuery,
|
|
736
|
+
tracingHelper,
|
|
737
|
+
serializer,
|
|
738
|
+
rawSerializer
|
|
739
|
+
}) {
|
|
602
740
|
this.#transactionManager = transactionManager;
|
|
603
741
|
this.#placeholderValues = placeholderValues;
|
|
604
742
|
this.#onQuery = onQuery;
|
|
605
743
|
this.#tracingHelper = tracingHelper;
|
|
606
744
|
this.#serializer = serializer;
|
|
745
|
+
this.#rawSerializer = rawSerializer ?? serializer;
|
|
607
746
|
}
|
|
608
747
|
static forSql(options) {
|
|
609
748
|
return new _QueryInterpreter({
|
|
@@ -611,7 +750,8 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
611
750
|
placeholderValues: options.placeholderValues,
|
|
612
751
|
onQuery: options.onQuery,
|
|
613
752
|
tracingHelper: options.tracingHelper,
|
|
614
|
-
serializer: serializeSql
|
|
753
|
+
serializer: serializeSql,
|
|
754
|
+
rawSerializer: serializeRawSql
|
|
615
755
|
});
|
|
616
756
|
}
|
|
617
757
|
async run(queryPlan, queryable) {
|
|
@@ -622,8 +762,11 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
622
762
|
async interpretNode(node, queryable, scope, generators) {
|
|
623
763
|
switch (node.type) {
|
|
624
764
|
case "seq": {
|
|
625
|
-
|
|
626
|
-
|
|
765
|
+
let result;
|
|
766
|
+
for (const arg of node.args) {
|
|
767
|
+
result = await this.interpretNode(arg, queryable, scope, generators);
|
|
768
|
+
}
|
|
769
|
+
return result;
|
|
627
770
|
}
|
|
628
771
|
case "get": {
|
|
629
772
|
return scope[node.args.name];
|
|
@@ -646,11 +789,11 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
646
789
|
}
|
|
647
790
|
case "concat": {
|
|
648
791
|
const parts = await Promise.all(node.args.map((arg) => this.interpretNode(arg, queryable, scope, generators)));
|
|
649
|
-
return parts.reduce((acc, part) => acc.concat(asList(part)), []);
|
|
792
|
+
return parts.length > 0 ? parts.reduce((acc, part) => acc.concat(asList(part)), []) : [];
|
|
650
793
|
}
|
|
651
794
|
case "sum": {
|
|
652
795
|
const parts = await Promise.all(node.args.map((arg) => this.interpretNode(arg, queryable, scope, generators)));
|
|
653
|
-
return parts.reduce((acc, part) => asNumber(acc) + asNumber(part));
|
|
796
|
+
return parts.length > 0 ? parts.reduce((acc, part) => asNumber(acc) + asNumber(part)) : 0;
|
|
654
797
|
}
|
|
655
798
|
case "execute": {
|
|
656
799
|
const query = renderQuery(node.args, scope, generators);
|
|
@@ -661,7 +804,11 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
661
804
|
case "query": {
|
|
662
805
|
const query = renderQuery(node.args, scope, generators);
|
|
663
806
|
return this.#withQueryEvent(query, queryable, async () => {
|
|
664
|
-
|
|
807
|
+
if (node.args.type === "rawSql") {
|
|
808
|
+
return this.#rawSerializer(await queryable.queryRaw(query));
|
|
809
|
+
} else {
|
|
810
|
+
return this.#serializer(await queryable.queryRaw(query));
|
|
811
|
+
}
|
|
665
812
|
});
|
|
666
813
|
}
|
|
667
814
|
case "reverse": {
|
|
@@ -691,6 +838,9 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
691
838
|
}
|
|
692
839
|
case "join": {
|
|
693
840
|
const parent = await this.interpretNode(node.args.parent, queryable, scope, generators);
|
|
841
|
+
if (parent === null) {
|
|
842
|
+
return null;
|
|
843
|
+
}
|
|
694
844
|
const children = await Promise.all(
|
|
695
845
|
node.args.children.map(async (joinExpr) => ({
|
|
696
846
|
joinExpr,
|
|
@@ -747,6 +897,38 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
747
897
|
const toSet = new Set(asList(to));
|
|
748
898
|
return asList(from).filter((item) => !toSet.has(item));
|
|
749
899
|
}
|
|
900
|
+
case "distinctBy": {
|
|
901
|
+
const value = await this.interpretNode(node.args.expr, queryable, scope, generators);
|
|
902
|
+
const seen = /* @__PURE__ */ new Set();
|
|
903
|
+
const result = [];
|
|
904
|
+
for (const item of asList(value)) {
|
|
905
|
+
const key = getRecordKey(item, node.args.fields);
|
|
906
|
+
if (!seen.has(key)) {
|
|
907
|
+
seen.add(key);
|
|
908
|
+
result.push(item);
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
return result;
|
|
912
|
+
}
|
|
913
|
+
case "paginate": {
|
|
914
|
+
const value = await this.interpretNode(node.args.expr, queryable, scope, generators);
|
|
915
|
+
const list = asList(value);
|
|
916
|
+
const linkingFields = node.args.pagination.linkingFields;
|
|
917
|
+
if (linkingFields !== null) {
|
|
918
|
+
const groupedByParent = /* @__PURE__ */ new Map();
|
|
919
|
+
for (const item of list) {
|
|
920
|
+
const parentKey = getRecordKey(item, linkingFields);
|
|
921
|
+
if (!groupedByParent.has(parentKey)) {
|
|
922
|
+
groupedByParent.set(parentKey, []);
|
|
923
|
+
}
|
|
924
|
+
groupedByParent.get(parentKey).push(item);
|
|
925
|
+
}
|
|
926
|
+
const groupList = Array.from(groupedByParent.entries());
|
|
927
|
+
groupList.sort(([aId], [bId]) => aId < bId ? -1 : aId > bId ? 1 : 0);
|
|
928
|
+
return groupList.flatMap(([, elems]) => paginate(elems, node.args.pagination));
|
|
929
|
+
}
|
|
930
|
+
return paginate(list, node.args.pagination);
|
|
931
|
+
}
|
|
750
932
|
default:
|
|
751
933
|
assertNever(node, `Unexpected node type: ${node.type}`);
|
|
752
934
|
}
|
|
@@ -818,7 +1000,12 @@ function attachChildrenToParent(parentRecord, children) {
|
|
|
818
1000
|
}
|
|
819
1001
|
function filterChildRecords(records, parentRecord, joinExpr) {
|
|
820
1002
|
if (Array.isArray(records)) {
|
|
821
|
-
|
|
1003
|
+
const filtered = records.filter((record) => childRecordMatchesParent(asRecord(record), parentRecord, joinExpr));
|
|
1004
|
+
if (joinExpr.isRelationUnique) {
|
|
1005
|
+
return filtered.length > 0 ? filtered[0] : null;
|
|
1006
|
+
} else {
|
|
1007
|
+
return filtered;
|
|
1008
|
+
}
|
|
822
1009
|
} else if (records === null) {
|
|
823
1010
|
return null;
|
|
824
1011
|
} else {
|
|
@@ -834,6 +1021,18 @@ function childRecordMatchesParent(childRecord, parentRecord, joinExpr) {
|
|
|
834
1021
|
}
|
|
835
1022
|
return true;
|
|
836
1023
|
}
|
|
1024
|
+
function paginate(list, { cursor, skip, take }) {
|
|
1025
|
+
const cursorIndex = cursor !== null ? list.findIndex((item) => doKeysMatch(item, cursor)) : 0;
|
|
1026
|
+
if (cursorIndex === -1) {
|
|
1027
|
+
return [];
|
|
1028
|
+
}
|
|
1029
|
+
const start = cursorIndex + (skip ?? 0);
|
|
1030
|
+
const end = take !== null ? start + take : list.length;
|
|
1031
|
+
return list.slice(start, end);
|
|
1032
|
+
}
|
|
1033
|
+
function getRecordKey(record, fields) {
|
|
1034
|
+
return JSON.stringify(fields.map((field) => record[field]));
|
|
1035
|
+
}
|
|
837
1036
|
|
|
838
1037
|
// src/transactionManager/TransactionManager.ts
|
|
839
1038
|
import { Debug } from "@prisma/debug";
|
|
@@ -848,12 +1047,11 @@ async function randomUUID() {
|
|
|
848
1047
|
}
|
|
849
1048
|
|
|
850
1049
|
// src/transactionManager/TransactionManagerErrors.ts
|
|
851
|
-
var TransactionManagerError = class extends
|
|
1050
|
+
var TransactionManagerError = class extends UserFacingError {
|
|
1051
|
+
name = "TransactionManagerError";
|
|
852
1052
|
constructor(message, meta) {
|
|
853
|
-
super("Transaction API error: " + message);
|
|
854
|
-
this.meta = meta;
|
|
1053
|
+
super("Transaction API error: " + message, "P2028", meta);
|
|
855
1054
|
}
|
|
856
|
-
code = "P2028";
|
|
857
1055
|
};
|
|
858
1056
|
var TransactionNotFoundError = class extends TransactionManagerError {
|
|
859
1057
|
constructor() {
|
|
@@ -864,12 +1062,12 @@ var TransactionNotFoundError = class extends TransactionManagerError {
|
|
|
864
1062
|
};
|
|
865
1063
|
var TransactionClosedError = class extends TransactionManagerError {
|
|
866
1064
|
constructor(operation) {
|
|
867
|
-
super(`Transaction already closed: A ${operation} cannot be executed on a committed transaction
|
|
1065
|
+
super(`Transaction already closed: A ${operation} cannot be executed on a committed transaction.`);
|
|
868
1066
|
}
|
|
869
1067
|
};
|
|
870
1068
|
var TransactionRolledBackError = class extends TransactionManagerError {
|
|
871
1069
|
constructor(operation) {
|
|
872
|
-
super(`Transaction already closed: A ${operation} cannot be executed on a transaction that was rolled back
|
|
1070
|
+
super(`Transaction already closed: A ${operation} cannot be executed on a transaction that was rolled back.`);
|
|
873
1071
|
}
|
|
874
1072
|
};
|
|
875
1073
|
var TransactionStartTimeoutError = class extends TransactionManagerError {
|
|
@@ -1051,10 +1249,14 @@ var TransactionManager = class {
|
|
|
1051
1249
|
}
|
|
1052
1250
|
};
|
|
1053
1251
|
export {
|
|
1252
|
+
DataMapperError,
|
|
1054
1253
|
QueryInterpreter,
|
|
1055
1254
|
TransactionManager,
|
|
1056
1255
|
TransactionManagerError,
|
|
1057
1256
|
UserFacingError,
|
|
1257
|
+
doKeysMatch,
|
|
1258
|
+
isDeepStrictEqual,
|
|
1259
|
+
isPrismaValueBigInt,
|
|
1058
1260
|
isPrismaValueBytes,
|
|
1059
1261
|
isPrismaValueGenerator,
|
|
1060
1262
|
isPrismaValuePlaceholder,
|
|
@@ -16,10 +16,11 @@ export type QueryInterpreterOptions = {
|
|
|
16
16
|
onQuery?: (event: QueryEvent) => void;
|
|
17
17
|
tracingHelper: TracingHelper;
|
|
18
18
|
serializer: (results: SqlResultSet) => Value;
|
|
19
|
+
rawSerializer?: (results: SqlResultSet) => Value;
|
|
19
20
|
};
|
|
20
21
|
export declare class QueryInterpreter {
|
|
21
22
|
#private;
|
|
22
|
-
constructor({ transactionManager, placeholderValues, onQuery, tracingHelper, serializer }: QueryInterpreterOptions);
|
|
23
|
+
constructor({ transactionManager, placeholderValues, onQuery, tracingHelper, serializer, rawSerializer, }: QueryInterpreterOptions);
|
|
23
24
|
static forSql(options: {
|
|
24
25
|
transactionManager: QueryInterpreterTransactionManager;
|
|
25
26
|
placeholderValues: Record<string, unknown>;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type SqlResultSet } from '@prisma/driver-adapter-utils';
|
|
2
2
|
export declare function serializeSql(resultSet: SqlResultSet): Record<string, unknown>[];
|
|
3
|
+
export declare function serializeRawSql(resultSet: SqlResultSet): Record<string, unknown>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
constructor(message: string, meta?: Record<string, unknown>
|
|
1
|
+
import { UserFacingError } from '../UserFacingError';
|
|
2
|
+
export declare class TransactionManagerError extends UserFacingError {
|
|
3
|
+
name: string;
|
|
4
|
+
constructor(message: string, meta?: Record<string, unknown>);
|
|
5
5
|
}
|
|
6
6
|
export declare class TransactionNotFoundError extends TransactionManagerError {
|
|
7
7
|
constructor();
|
package/dist/utils.d.ts
CHANGED
|
@@ -1 +1,11 @@
|
|
|
1
1
|
export declare function assertNever(_: never, message: string): never;
|
|
2
|
+
/**
|
|
3
|
+
* Checks if two objects are deeply equal, recursively checking all properties for strict equality.
|
|
4
|
+
*/
|
|
5
|
+
export declare function isDeepStrictEqual(a: unknown, b: unknown): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Checks if two objects representing the names and values of key columns match. A match is
|
|
8
|
+
* defined by one of the sets of keys being a subset of the other. This function also
|
|
9
|
+
* converts arguments to the types used by driver adapters if necessary.
|
|
10
|
+
*/
|
|
11
|
+
export declare function doKeysMatch(lhs: {}, rhs: {}): boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/client-engine-runtime",
|
|
3
|
-
"version": "6.9.0-dev.
|
|
3
|
+
"version": "6.9.0-dev.21",
|
|
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,8 +31,8 @@
|
|
|
31
31
|
"nanoid": "5.1.5",
|
|
32
32
|
"ulid": "3.0.0",
|
|
33
33
|
"uuid": "11.1.0",
|
|
34
|
-
"@prisma/debug": "6.9.0-dev.
|
|
35
|
-
"@prisma/driver-adapter-utils": "6.9.0-dev.
|
|
34
|
+
"@prisma/debug": "6.9.0-dev.21",
|
|
35
|
+
"@prisma/driver-adapter-utils": "6.9.0-dev.21"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/jest": "29.5.14",
|