@prisma/client-engine-runtime 6.15.0-dev.2 → 6.15.0-dev.20
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/index.d.mts +31 -58
- package/dist/index.d.ts +31 -58
- package/dist/index.js +215 -210
- package/dist/index.mjs +215 -208
- package/dist/interpreter/generators.d.ts +1 -2
- package/dist/interpreter/render-query.d.ts +2 -2
- package/dist/query-plan.d.ts +26 -48
- package/dist/transaction-manager/transaction-manager-error.d.ts +0 -3
- package/dist/transaction-manager/transaction-manager.d.ts +1 -5
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -120,7 +120,7 @@ function normalizeTaggedValue({ $type, value }) {
|
|
|
120
120
|
case "BigInt":
|
|
121
121
|
return { $type, value: String(value) };
|
|
122
122
|
case "Bytes":
|
|
123
|
-
return { $type, value };
|
|
123
|
+
return { $type, value: Buffer.from(value, "base64").toString("base64") };
|
|
124
124
|
case "DateTime":
|
|
125
125
|
return { $type, value: new Date(value).toISOString() };
|
|
126
126
|
case "Decimal":
|
|
@@ -395,15 +395,15 @@ var DataMapperError = class extends Error {
|
|
|
395
395
|
};
|
|
396
396
|
function applyDataMap(data, structure, enums) {
|
|
397
397
|
switch (structure.type) {
|
|
398
|
-
case "
|
|
398
|
+
case "affectedRows":
|
|
399
399
|
if (typeof data !== "number") {
|
|
400
400
|
throw new DataMapperError(`Expected an affected rows count, got: ${typeof data} (${data})`);
|
|
401
401
|
}
|
|
402
402
|
return { count: data };
|
|
403
|
-
case "
|
|
403
|
+
case "object":
|
|
404
404
|
return mapArrayOrObject(data, structure.fields, enums, structure.skipNulls);
|
|
405
|
-
case "
|
|
406
|
-
return mapValue(data, "<result>", structure.
|
|
405
|
+
case "field":
|
|
406
|
+
return mapValue(data, "<result>", structure.fieldType, enums);
|
|
407
407
|
default:
|
|
408
408
|
assertNever(structure, `Invalid data mapping type: '${structure.type}'`);
|
|
409
409
|
}
|
|
@@ -441,10 +441,10 @@ function mapObject(data, fields, enums) {
|
|
|
441
441
|
const result = {};
|
|
442
442
|
for (const [name, node] of Object.entries(fields)) {
|
|
443
443
|
switch (node.type) {
|
|
444
|
-
case "
|
|
444
|
+
case "affectedRows": {
|
|
445
445
|
throw new DataMapperError(`Unexpected 'AffectedRows' node in data mapping for field '${name}'`);
|
|
446
446
|
}
|
|
447
|
-
case "
|
|
447
|
+
case "object": {
|
|
448
448
|
if (node.serializedName !== null && !Object.hasOwn(data, node.serializedName)) {
|
|
449
449
|
throw new DataMapperError(
|
|
450
450
|
`Missing data field (Object): '${name}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
|
|
@@ -454,11 +454,11 @@ function mapObject(data, fields, enums) {
|
|
|
454
454
|
result[name] = mapArrayOrObject(target, node.fields, enums, node.skipNulls);
|
|
455
455
|
break;
|
|
456
456
|
}
|
|
457
|
-
case "
|
|
457
|
+
case "field":
|
|
458
458
|
{
|
|
459
459
|
const dbName = node.dbName;
|
|
460
460
|
if (Object.hasOwn(data, dbName)) {
|
|
461
|
-
result[name] =
|
|
461
|
+
result[name] = mapField(data[dbName], dbName, node.fieldType, enums);
|
|
462
462
|
} else {
|
|
463
463
|
throw new DataMapperError(
|
|
464
464
|
`Missing data field (Value): '${dbName}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
|
|
@@ -472,20 +472,27 @@ function mapObject(data, fields, enums) {
|
|
|
472
472
|
}
|
|
473
473
|
return result;
|
|
474
474
|
}
|
|
475
|
-
function
|
|
475
|
+
function mapField(value, columnName, fieldType, enums) {
|
|
476
476
|
if (value === null) {
|
|
477
|
-
return
|
|
477
|
+
return fieldType.arity === "list" ? [] : null;
|
|
478
478
|
}
|
|
479
|
-
|
|
480
|
-
|
|
479
|
+
if (fieldType.arity === "list") {
|
|
480
|
+
const values = value;
|
|
481
|
+
return values.map((v, i) => mapValue(v, `${columnName}[${i}]`, fieldType, enums));
|
|
482
|
+
}
|
|
483
|
+
return mapValue(value, columnName, fieldType, enums);
|
|
484
|
+
}
|
|
485
|
+
function mapValue(value, columnName, scalarType, enums) {
|
|
486
|
+
switch (scalarType.type) {
|
|
487
|
+
case "unsupported":
|
|
481
488
|
return value;
|
|
482
|
-
case "
|
|
489
|
+
case "string": {
|
|
483
490
|
if (typeof value !== "string") {
|
|
484
491
|
throw new DataMapperError(`Expected a string in column '${columnName}', got ${typeof value}: ${value}`);
|
|
485
492
|
}
|
|
486
493
|
return value;
|
|
487
494
|
}
|
|
488
|
-
case "
|
|
495
|
+
case "int": {
|
|
489
496
|
switch (typeof value) {
|
|
490
497
|
case "number": {
|
|
491
498
|
return Math.trunc(value);
|
|
@@ -506,13 +513,13 @@ function mapValue(value, columnName, resultType, enums) {
|
|
|
506
513
|
throw new DataMapperError(`Expected an integer in column '${columnName}', got ${typeof value}: ${value}`);
|
|
507
514
|
}
|
|
508
515
|
}
|
|
509
|
-
case "
|
|
516
|
+
case "bigint": {
|
|
510
517
|
if (typeof value !== "number" && typeof value !== "string") {
|
|
511
518
|
throw new DataMapperError(`Expected a bigint in column '${columnName}', got ${typeof value}: ${value}`);
|
|
512
519
|
}
|
|
513
520
|
return { $type: "BigInt", value };
|
|
514
521
|
}
|
|
515
|
-
case "
|
|
522
|
+
case "float": {
|
|
516
523
|
if (typeof value === "number") return value;
|
|
517
524
|
if (typeof value === "string") {
|
|
518
525
|
const parsedValue = Number(value);
|
|
@@ -523,7 +530,7 @@ function mapValue(value, columnName, resultType, enums) {
|
|
|
523
530
|
}
|
|
524
531
|
throw new DataMapperError(`Expected a float in column '${columnName}', got ${typeof value}: ${value}`);
|
|
525
532
|
}
|
|
526
|
-
case "
|
|
533
|
+
case "boolean": {
|
|
527
534
|
if (typeof value === "boolean") return value;
|
|
528
535
|
if (typeof value === "number") return value === 1;
|
|
529
536
|
if (typeof value === "string") {
|
|
@@ -535,7 +542,7 @@ function mapValue(value, columnName, resultType, enums) {
|
|
|
535
542
|
throw new DataMapperError(`Expected a boolean in column '${columnName}', got ${typeof value}: ${value}`);
|
|
536
543
|
}
|
|
537
544
|
}
|
|
538
|
-
if (value
|
|
545
|
+
if (Array.isArray(value)) {
|
|
539
546
|
for (const byte of value) {
|
|
540
547
|
if (byte !== 0) return true;
|
|
541
548
|
}
|
|
@@ -543,73 +550,87 @@ function mapValue(value, columnName, resultType, enums) {
|
|
|
543
550
|
}
|
|
544
551
|
throw new DataMapperError(`Expected a boolean in column '${columnName}', got ${typeof value}: ${value}`);
|
|
545
552
|
}
|
|
546
|
-
case "
|
|
553
|
+
case "decimal":
|
|
547
554
|
if (typeof value !== "number" && typeof value !== "string" && !Decimal3.isDecimal(value)) {
|
|
548
555
|
throw new DataMapperError(`Expected a decimal in column '${columnName}', got ${typeof value}: ${value}`);
|
|
549
556
|
}
|
|
550
557
|
return { $type: "Decimal", value };
|
|
551
|
-
case "
|
|
558
|
+
case "datetime": {
|
|
552
559
|
if (typeof value === "string") {
|
|
553
|
-
return { $type: "DateTime", value:
|
|
560
|
+
return { $type: "DateTime", value: normalizeDateTime(value) };
|
|
554
561
|
}
|
|
555
562
|
if (typeof value === "number" || value instanceof Date) {
|
|
556
563
|
return { $type: "DateTime", value };
|
|
557
564
|
}
|
|
558
565
|
throw new DataMapperError(`Expected a date in column '${columnName}', got ${typeof value}: ${value}`);
|
|
559
566
|
}
|
|
560
|
-
case "
|
|
561
|
-
if (typeof value === "string") {
|
|
562
|
-
return { $type: "DateTime", value: `1970-01-01T${ensureTimezoneInIsoString(value)}` };
|
|
563
|
-
}
|
|
564
|
-
throw new DataMapperError(`Expected a time in column '${columnName}', got ${typeof value}: ${value}`);
|
|
565
|
-
}
|
|
566
|
-
case "Array": {
|
|
567
|
-
const values = value;
|
|
568
|
-
return values.map((v, i) => mapValue(v, `${columnName}[${i}]`, resultType.inner, enums));
|
|
569
|
-
}
|
|
570
|
-
case "Object": {
|
|
567
|
+
case "object": {
|
|
571
568
|
return { $type: "Json", value: safeJsonStringify(value) };
|
|
572
569
|
}
|
|
573
|
-
case "
|
|
570
|
+
case "json": {
|
|
574
571
|
return { $type: "Json", value: `${value}` };
|
|
575
572
|
}
|
|
576
|
-
case "
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
573
|
+
case "bytes": {
|
|
574
|
+
switch (scalarType.encoding) {
|
|
575
|
+
case "base64":
|
|
576
|
+
if (typeof value !== "string") {
|
|
577
|
+
throw new DataMapperError(
|
|
578
|
+
`Expected a base64-encoded byte array in column '${columnName}', got ${typeof value}: ${value}`
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
return { $type: "Bytes", value };
|
|
582
|
+
case "hex":
|
|
583
|
+
if (typeof value !== "string" || !value.startsWith("\\x")) {
|
|
584
|
+
throw new DataMapperError(
|
|
585
|
+
`Expected a hex-encoded byte array in column '${columnName}', got ${typeof value}: ${value}`
|
|
586
|
+
);
|
|
587
|
+
}
|
|
588
|
+
return { $type: "Bytes", value: Buffer.from(value.slice(2), "hex").toString("base64") };
|
|
589
|
+
case "array":
|
|
590
|
+
if (Array.isArray(value)) {
|
|
591
|
+
return { $type: "Bytes", value: Buffer.from(value).toString("base64") };
|
|
592
|
+
}
|
|
593
|
+
if (value instanceof Uint8Array) {
|
|
594
|
+
return { $type: "Bytes", value: Buffer.from(value).toString("base64") };
|
|
595
|
+
}
|
|
596
|
+
throw new DataMapperError(`Expected a byte array in column '${columnName}', got ${typeof value}: ${value}`);
|
|
597
|
+
default:
|
|
598
|
+
assertNever(scalarType.encoding, `DataMapper: Unknown bytes encoding: ${scalarType.encoding}`);
|
|
585
599
|
}
|
|
586
|
-
|
|
600
|
+
break;
|
|
587
601
|
}
|
|
588
|
-
case "
|
|
589
|
-
const enumDef = enums[
|
|
602
|
+
case "enum": {
|
|
603
|
+
const enumDef = enums[scalarType.name];
|
|
590
604
|
if (enumDef === void 0) {
|
|
591
|
-
throw new DataMapperError(`Unknown enum '${
|
|
605
|
+
throw new DataMapperError(`Unknown enum '${scalarType.name}'`);
|
|
592
606
|
}
|
|
593
607
|
const enumValue = enumDef[`${value}`];
|
|
594
608
|
if (enumValue === void 0) {
|
|
595
|
-
throw new DataMapperError(`Value '${value}' not found in enum '${
|
|
609
|
+
throw new DataMapperError(`Value '${value}' not found in enum '${scalarType.name}'`);
|
|
596
610
|
}
|
|
597
611
|
return enumValue;
|
|
598
612
|
}
|
|
599
613
|
default:
|
|
600
|
-
assertNever(
|
|
614
|
+
assertNever(scalarType, `DataMapper: Unknown result type: ${scalarType["type"]}`);
|
|
601
615
|
}
|
|
602
616
|
}
|
|
603
|
-
var
|
|
604
|
-
function
|
|
605
|
-
const
|
|
606
|
-
if (
|
|
617
|
+
var TIME_TZ_PATTERN = /\d{2}:\d{2}:\d{2}(?:\.\d+)?(Z|[+-]\d{2}(:?\d{2})?)?$/;
|
|
618
|
+
function normalizeDateTime(dt) {
|
|
619
|
+
const matches = TIME_TZ_PATTERN.exec(dt);
|
|
620
|
+
if (matches === null) {
|
|
607
621
|
return `${dt}Z`;
|
|
608
|
-
} else if (results[0] !== "Z" && results[1] === void 0) {
|
|
609
|
-
return `${dt}:00`;
|
|
610
|
-
} else {
|
|
611
|
-
return dt;
|
|
612
622
|
}
|
|
623
|
+
let dtWithTz = dt;
|
|
624
|
+
const [timeTz, tz, tzMinuteOffset] = matches;
|
|
625
|
+
if (tz !== void 0 && tz !== "Z" && tzMinuteOffset === void 0) {
|
|
626
|
+
dtWithTz = `${dt}:00`;
|
|
627
|
+
} else if (tz === void 0) {
|
|
628
|
+
dtWithTz = `${dt}Z`;
|
|
629
|
+
}
|
|
630
|
+
if (timeTz.length === dt.length) {
|
|
631
|
+
return `1970-01-01T${dtWithTz}`;
|
|
632
|
+
}
|
|
633
|
+
return dtWithTz;
|
|
613
634
|
}
|
|
614
635
|
|
|
615
636
|
// src/tracing.ts
|
|
@@ -688,10 +709,10 @@ var GeneratorRegistry = class {
|
|
|
688
709
|
* method being called, meaning that the built-in time-based generators will always return
|
|
689
710
|
* the same value on repeated calls as long as the same snapshot is used.
|
|
690
711
|
*/
|
|
691
|
-
snapshot(
|
|
712
|
+
snapshot() {
|
|
692
713
|
return Object.create(this.#generators, {
|
|
693
714
|
now: {
|
|
694
|
-
value:
|
|
715
|
+
value: new NowGenerator()
|
|
695
716
|
}
|
|
696
717
|
});
|
|
697
718
|
}
|
|
@@ -708,12 +729,6 @@ var NowGenerator = class {
|
|
|
708
729
|
return this.#now.toISOString();
|
|
709
730
|
}
|
|
710
731
|
};
|
|
711
|
-
var MysqlNowGenerator = class {
|
|
712
|
-
#now = /* @__PURE__ */ new Date();
|
|
713
|
-
generate() {
|
|
714
|
-
return this.#now.toISOString().replace("T", " ").replace("Z", "");
|
|
715
|
-
}
|
|
716
|
-
};
|
|
717
732
|
var UuidGenerator = class {
|
|
718
733
|
generate(arg) {
|
|
719
734
|
if (arg === 4) {
|
|
@@ -867,74 +882,82 @@ function isPrismaValuePlaceholder(value) {
|
|
|
867
882
|
function isPrismaValueGenerator(value) {
|
|
868
883
|
return typeof value === "object" && value !== null && value["prisma__type"] === "generatorCall";
|
|
869
884
|
}
|
|
870
|
-
function isPrismaValueBytes(value) {
|
|
871
|
-
return typeof value === "object" && value !== null && value["prisma__type"] === "bytes";
|
|
872
|
-
}
|
|
873
|
-
function isPrismaValueBigInt(value) {
|
|
874
|
-
return typeof value === "object" && value !== null && value["prisma__type"] === "bigint";
|
|
875
|
-
}
|
|
876
885
|
|
|
877
886
|
// src/interpreter/render-query.ts
|
|
878
887
|
function renderQuery(dbQuery, scope, generators, maxChunkSize) {
|
|
879
|
-
const
|
|
880
|
-
|
|
881
|
-
switch (queryType) {
|
|
888
|
+
const args = dbQuery.args.map((arg) => evaluateArg(arg, scope, generators));
|
|
889
|
+
switch (dbQuery.type) {
|
|
882
890
|
case "rawSql":
|
|
883
|
-
return [renderRawSql(dbQuery.sql,
|
|
891
|
+
return [renderRawSql(dbQuery.sql, args, dbQuery.argTypes)];
|
|
884
892
|
case "templateSql": {
|
|
885
|
-
const chunks = dbQuery.chunkable ? chunkParams(dbQuery.fragments,
|
|
886
|
-
return chunks.map((
|
|
887
|
-
if (maxChunkSize !== void 0 &&
|
|
893
|
+
const chunks = dbQuery.chunkable ? chunkParams(dbQuery.fragments, args, maxChunkSize) : [args];
|
|
894
|
+
return chunks.map((params) => {
|
|
895
|
+
if (maxChunkSize !== void 0 && params.length > maxChunkSize) {
|
|
888
896
|
throw new UserFacingError("The query parameter limit supported by your database is exceeded.", "P2029");
|
|
889
897
|
}
|
|
890
|
-
return renderTemplateSql(dbQuery.fragments, dbQuery.placeholderFormat,
|
|
898
|
+
return renderTemplateSql(dbQuery.fragments, dbQuery.placeholderFormat, params, dbQuery.argTypes);
|
|
891
899
|
});
|
|
892
900
|
}
|
|
893
901
|
default:
|
|
894
|
-
assertNever(
|
|
902
|
+
assertNever(dbQuery["type"], `Invalid query type`);
|
|
895
903
|
}
|
|
896
904
|
}
|
|
897
|
-
function
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
let value = param;
|
|
902
|
-
while (doesRequireEvaluation(value)) {
|
|
903
|
-
if (isPrismaValuePlaceholder(value)) {
|
|
904
|
-
const found = scope[value.prisma__value.name];
|
|
905
|
+
function evaluateArg(arg, scope, generators) {
|
|
906
|
+
while (doesRequireEvaluation(arg)) {
|
|
907
|
+
if (isPrismaValuePlaceholder(arg)) {
|
|
908
|
+
const found = scope[arg.prisma__value.name];
|
|
905
909
|
if (found === void 0) {
|
|
906
|
-
throw new Error(`Missing value for query variable ${
|
|
910
|
+
throw new Error(`Missing value for query variable ${arg.prisma__value.name}`);
|
|
907
911
|
}
|
|
908
|
-
|
|
909
|
-
} else if (isPrismaValueGenerator(
|
|
910
|
-
const { name, args } =
|
|
912
|
+
arg = found;
|
|
913
|
+
} else if (isPrismaValueGenerator(arg)) {
|
|
914
|
+
const { name, args } = arg.prisma__value;
|
|
911
915
|
const generator = generators[name];
|
|
912
916
|
if (!generator) {
|
|
913
917
|
throw new Error(`Encountered an unknown generator '${name}'`);
|
|
914
918
|
}
|
|
915
|
-
|
|
919
|
+
arg = generator.generate(...args.map((arg2) => evaluateArg(arg2, scope, generators)));
|
|
916
920
|
} else {
|
|
917
|
-
assertNever(
|
|
921
|
+
assertNever(arg, `Unexpected unevaluated value type: ${arg}`);
|
|
918
922
|
}
|
|
919
923
|
}
|
|
920
|
-
if (Array.isArray(
|
|
921
|
-
|
|
922
|
-
} else if (isPrismaValueBytes(value)) {
|
|
923
|
-
value = Buffer.from(value.prisma__value, "base64");
|
|
924
|
-
} else if (isPrismaValueBigInt(value)) {
|
|
925
|
-
value = BigInt(value.prisma__value);
|
|
924
|
+
if (Array.isArray(arg)) {
|
|
925
|
+
arg = arg.map((el) => evaluateArg(el, scope, generators));
|
|
926
926
|
}
|
|
927
|
-
return
|
|
927
|
+
return arg;
|
|
928
928
|
}
|
|
929
|
-
function renderTemplateSql(fragments, placeholderFormat, params) {
|
|
929
|
+
function renderTemplateSql(fragments, placeholderFormat, params, argTypes) {
|
|
930
930
|
let sql = "";
|
|
931
931
|
const ctx = { placeholderNumber: 1 };
|
|
932
932
|
const flattenedParams = [];
|
|
933
|
-
|
|
934
|
-
|
|
933
|
+
const flattenedArgTypes = [];
|
|
934
|
+
for (const fragment of pairFragmentsWithParams(fragments, params, argTypes)) {
|
|
935
935
|
sql += renderFragment(fragment, placeholderFormat, ctx);
|
|
936
|
+
if (fragment.type === "stringChunk") {
|
|
937
|
+
continue;
|
|
938
|
+
}
|
|
939
|
+
const length = flattenedParams.length;
|
|
940
|
+
const added = flattenedParams.push(...flattenedFragmentParams(fragment)) - length;
|
|
941
|
+
if (fragment.argType.arity === "tuple") {
|
|
942
|
+
if (added % fragment.argType.elements.length !== 0) {
|
|
943
|
+
throw new Error(
|
|
944
|
+
`Malformed query template. Expected the number of parameters to match the tuple arity, but got ${added} parameters for a tuple of arity ${fragment.argType.elements.length}.`
|
|
945
|
+
);
|
|
946
|
+
}
|
|
947
|
+
for (let i = 0; i < added / fragment.argType.elements.length; i++) {
|
|
948
|
+
flattenedArgTypes.push(...fragment.argType.elements);
|
|
949
|
+
}
|
|
950
|
+
} else {
|
|
951
|
+
for (let i = 0; i < added; i++) {
|
|
952
|
+
flattenedArgTypes.push(fragment.argType);
|
|
953
|
+
}
|
|
954
|
+
}
|
|
936
955
|
}
|
|
937
|
-
return
|
|
956
|
+
return {
|
|
957
|
+
sql,
|
|
958
|
+
args: flattenedParams,
|
|
959
|
+
argTypes: flattenedArgTypes
|
|
960
|
+
};
|
|
938
961
|
}
|
|
939
962
|
function renderFragment(fragment, placeholderFormat, ctx) {
|
|
940
963
|
const fragmentType = fragment.type;
|
|
@@ -960,36 +983,17 @@ function renderFragment(fragment, placeholderFormat, ctx) {
|
|
|
960
983
|
function formatPlaceholder(placeholderFormat, placeholderNumber) {
|
|
961
984
|
return placeholderFormat.hasNumbering ? `${placeholderFormat.prefix}${placeholderNumber}` : placeholderFormat.prefix;
|
|
962
985
|
}
|
|
963
|
-
function renderRawSql(sql,
|
|
964
|
-
const argTypes = params.map((param) => toArgType(param));
|
|
986
|
+
function renderRawSql(sql, args, argTypes) {
|
|
965
987
|
return {
|
|
966
988
|
sql,
|
|
967
|
-
args
|
|
989
|
+
args,
|
|
968
990
|
argTypes
|
|
969
991
|
};
|
|
970
992
|
}
|
|
971
|
-
function toArgType(value) {
|
|
972
|
-
if (typeof value === "string") {
|
|
973
|
-
return "Text";
|
|
974
|
-
}
|
|
975
|
-
if (typeof value === "number") {
|
|
976
|
-
return "Numeric";
|
|
977
|
-
}
|
|
978
|
-
if (typeof value === "boolean") {
|
|
979
|
-
return "Boolean";
|
|
980
|
-
}
|
|
981
|
-
if (Array.isArray(value)) {
|
|
982
|
-
return "Array";
|
|
983
|
-
}
|
|
984
|
-
if (Buffer.isBuffer(value)) {
|
|
985
|
-
return "Bytes";
|
|
986
|
-
}
|
|
987
|
-
return "Unknown";
|
|
988
|
-
}
|
|
989
993
|
function doesRequireEvaluation(param) {
|
|
990
994
|
return isPrismaValuePlaceholder(param) || isPrismaValueGenerator(param);
|
|
991
995
|
}
|
|
992
|
-
function* pairFragmentsWithParams(fragments, params) {
|
|
996
|
+
function* pairFragmentsWithParams(fragments, params, argTypes) {
|
|
993
997
|
let index = 0;
|
|
994
998
|
for (const fragment of fragments) {
|
|
995
999
|
switch (fragment.type) {
|
|
@@ -997,7 +1001,8 @@ function* pairFragmentsWithParams(fragments, params) {
|
|
|
997
1001
|
if (index >= params.length) {
|
|
998
1002
|
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
999
1003
|
}
|
|
1000
|
-
yield { ...fragment, value: params[index
|
|
1004
|
+
yield { ...fragment, value: params[index], argType: argTypes?.[index] };
|
|
1005
|
+
index++;
|
|
1001
1006
|
break;
|
|
1002
1007
|
}
|
|
1003
1008
|
case "stringChunk": {
|
|
@@ -1008,15 +1013,16 @@ function* pairFragmentsWithParams(fragments, params) {
|
|
|
1008
1013
|
if (index >= params.length) {
|
|
1009
1014
|
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
1010
1015
|
}
|
|
1011
|
-
const value = params[index
|
|
1012
|
-
yield { ...fragment, value: Array.isArray(value) ? value : [value] };
|
|
1016
|
+
const value = params[index];
|
|
1017
|
+
yield { ...fragment, value: Array.isArray(value) ? value : [value], argType: argTypes?.[index] };
|
|
1018
|
+
index++;
|
|
1013
1019
|
break;
|
|
1014
1020
|
}
|
|
1015
1021
|
case "parameterTupleList": {
|
|
1016
1022
|
if (index >= params.length) {
|
|
1017
1023
|
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
1018
1024
|
}
|
|
1019
|
-
const value = params[index
|
|
1025
|
+
const value = params[index];
|
|
1020
1026
|
if (!Array.isArray(value)) {
|
|
1021
1027
|
throw new Error(`Malformed query template. Tuple list expected.`);
|
|
1022
1028
|
}
|
|
@@ -1028,7 +1034,8 @@ function* pairFragmentsWithParams(fragments, params) {
|
|
|
1028
1034
|
throw new Error(`Malformed query template. Tuple expected.`);
|
|
1029
1035
|
}
|
|
1030
1036
|
}
|
|
1031
|
-
yield { ...fragment, value };
|
|
1037
|
+
yield { ...fragment, value, argType: argTypes?.[index] };
|
|
1038
|
+
index++;
|
|
1032
1039
|
break;
|
|
1033
1040
|
}
|
|
1034
1041
|
}
|
|
@@ -1054,7 +1061,7 @@ function* flattenedFragmentParams(fragment) {
|
|
|
1054
1061
|
function chunkParams(fragments, params, maxChunkSize) {
|
|
1055
1062
|
let totalParamCount = 0;
|
|
1056
1063
|
let maxParamsPerFragment = 0;
|
|
1057
|
-
for (const fragment of pairFragmentsWithParams(fragments, params)) {
|
|
1064
|
+
for (const fragment of pairFragmentsWithParams(fragments, params, void 0)) {
|
|
1058
1065
|
let paramSize = 0;
|
|
1059
1066
|
for (const _ of flattenedFragmentParams(fragment)) {
|
|
1060
1067
|
void _;
|
|
@@ -1064,7 +1071,7 @@ function chunkParams(fragments, params, maxChunkSize) {
|
|
|
1064
1071
|
totalParamCount += paramSize;
|
|
1065
1072
|
}
|
|
1066
1073
|
let chunkedParams = [[]];
|
|
1067
|
-
for (const fragment of pairFragmentsWithParams(fragments, params)) {
|
|
1074
|
+
for (const fragment of pairFragmentsWithParams(fragments, params, void 0)) {
|
|
1068
1075
|
switch (fragment.type) {
|
|
1069
1076
|
case "parameter": {
|
|
1070
1077
|
for (const params2 of chunkedParams) {
|
|
@@ -1130,16 +1137,8 @@ function chunkArray(array, chunkSize) {
|
|
|
1130
1137
|
// src/interpreter/serialize-sql.ts
|
|
1131
1138
|
import { ColumnTypeEnum } from "@prisma/driver-adapter-utils";
|
|
1132
1139
|
function serializeSql(resultSet) {
|
|
1133
|
-
const mappers = resultSet.columnTypes.map((type) => {
|
|
1134
|
-
switch (type) {
|
|
1135
|
-
case ColumnTypeEnum.Bytes:
|
|
1136
|
-
return (value) => Array.isArray(value) ? new Uint8Array(value) : value;
|
|
1137
|
-
default:
|
|
1138
|
-
return (value) => value;
|
|
1139
|
-
}
|
|
1140
|
-
});
|
|
1141
1140
|
return resultSet.rows.map(
|
|
1142
|
-
(row) => row.
|
|
1141
|
+
(row) => row.reduce((acc, value, index) => {
|
|
1143
1142
|
const splitByDot = resultSet.columnNames[index].split(".");
|
|
1144
1143
|
let nested = acc;
|
|
1145
1144
|
for (let i = 0; i < splitByDot.length; i++) {
|
|
@@ -1433,14 +1432,14 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1433
1432
|
queryPlan,
|
|
1434
1433
|
queryable,
|
|
1435
1434
|
this.#placeholderValues,
|
|
1436
|
-
this.#generators.snapshot(
|
|
1435
|
+
this.#generators.snapshot()
|
|
1437
1436
|
).catch((e) => rethrowAsUserFacing(e));
|
|
1438
1437
|
return value;
|
|
1439
1438
|
}
|
|
1440
1439
|
async interpretNode(node, queryable, scope, generators) {
|
|
1441
1440
|
switch (node.type) {
|
|
1442
1441
|
case "value": {
|
|
1443
|
-
return { value:
|
|
1442
|
+
return { value: evaluateArg(node.args, scope, generators) };
|
|
1444
1443
|
}
|
|
1445
1444
|
case "seq": {
|
|
1446
1445
|
let result;
|
|
@@ -1545,7 +1544,7 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1545
1544
|
}
|
|
1546
1545
|
case "mapField": {
|
|
1547
1546
|
const { value, lastInsertId } = await this.interpretNode(node.args.records, queryable, scope, generators);
|
|
1548
|
-
return { value:
|
|
1547
|
+
return { value: mapField2(value, node.args.field), lastInsertId };
|
|
1549
1548
|
}
|
|
1550
1549
|
case "join": {
|
|
1551
1550
|
const { value: parent, lastInsertId } = await this.interpretNode(node.args.parent, queryable, scope, generators);
|
|
@@ -1566,7 +1565,7 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1566
1565
|
}
|
|
1567
1566
|
const transactionManager = this.#transactionManager.manager;
|
|
1568
1567
|
const transactionInfo = await transactionManager.startTransaction();
|
|
1569
|
-
const transaction = transactionManager.getTransaction(transactionInfo, "query");
|
|
1568
|
+
const transaction = await transactionManager.getTransaction(transactionInfo, "query");
|
|
1570
1569
|
try {
|
|
1571
1570
|
const value = await this.interpretNode(node.args, transaction, scope, generators);
|
|
1572
1571
|
await transactionManager.commitTransaction(transactionInfo.id);
|
|
@@ -1688,9 +1687,9 @@ function asRecord(value) {
|
|
|
1688
1687
|
}
|
|
1689
1688
|
throw new Error(`Expected object, got ${typeof value}`);
|
|
1690
1689
|
}
|
|
1691
|
-
function
|
|
1690
|
+
function mapField2(value, field) {
|
|
1692
1691
|
if (Array.isArray(value)) {
|
|
1693
|
-
return value.map((element) =>
|
|
1692
|
+
return value.map((element) => mapField2(element, field));
|
|
1694
1693
|
}
|
|
1695
1694
|
if (typeof value === "object" && value !== null) {
|
|
1696
1695
|
return value[field] ?? null;
|
|
@@ -1734,7 +1733,7 @@ function attachChildrenToParents(parentRecords, children) {
|
|
|
1734
1733
|
function evalFieldInitializer(initializer, lastInsertId, scope, generators) {
|
|
1735
1734
|
switch (initializer.type) {
|
|
1736
1735
|
case "value":
|
|
1737
|
-
return
|
|
1736
|
+
return evaluateArg(initializer.value, scope, generators);
|
|
1738
1737
|
case "lastInsertId":
|
|
1739
1738
|
return lastInsertId;
|
|
1740
1739
|
default:
|
|
@@ -1744,16 +1743,16 @@ function evalFieldInitializer(initializer, lastInsertId, scope, generators) {
|
|
|
1744
1743
|
function evalFieldOperation(op, value, scope, generators) {
|
|
1745
1744
|
switch (op.type) {
|
|
1746
1745
|
case "set":
|
|
1747
|
-
return
|
|
1746
|
+
return evaluateArg(op.value, scope, generators);
|
|
1748
1747
|
case "add":
|
|
1749
|
-
return asNumber2(value) + asNumber2(
|
|
1748
|
+
return asNumber2(value) + asNumber2(evaluateArg(op.value, scope, generators));
|
|
1750
1749
|
case "subtract":
|
|
1751
|
-
return asNumber2(value) - asNumber2(
|
|
1750
|
+
return asNumber2(value) - asNumber2(evaluateArg(op.value, scope, generators));
|
|
1752
1751
|
case "multiply":
|
|
1753
|
-
return asNumber2(value) * asNumber2(
|
|
1752
|
+
return asNumber2(value) * asNumber2(evaluateArg(op.value, scope, generators));
|
|
1754
1753
|
case "divide": {
|
|
1755
1754
|
const lhs = asNumber2(value);
|
|
1756
|
-
const rhs = asNumber2(
|
|
1755
|
+
const rhs = asNumber2(evaluateArg(op.value, scope, generators));
|
|
1757
1756
|
if (rhs === 0) {
|
|
1758
1757
|
return null;
|
|
1759
1758
|
}
|
|
@@ -1824,11 +1823,6 @@ var TransactionClosedError = class extends TransactionManagerError {
|
|
|
1824
1823
|
super(`Transaction already closed: A ${operation} cannot be executed on a committed transaction.`);
|
|
1825
1824
|
}
|
|
1826
1825
|
};
|
|
1827
|
-
var TransactionClosingError = class extends TransactionManagerError {
|
|
1828
|
-
constructor(operation) {
|
|
1829
|
-
super(`Transaction is being closed: A ${operation} cannot be executed on a closing transaction.`);
|
|
1830
|
-
}
|
|
1831
|
-
};
|
|
1832
1826
|
var TransactionRolledBackError = class extends TransactionManagerError {
|
|
1833
1827
|
constructor(operation) {
|
|
1834
1828
|
super(`Transaction already closed: A ${operation} cannot be executed on a transaction that was rolled back.`);
|
|
@@ -1901,7 +1895,7 @@ var TransactionManager = class {
|
|
|
1901
1895
|
return await this.tracingHelper.runInChildSpan("start_transaction", () => this.#startTransactionImpl(options));
|
|
1902
1896
|
}
|
|
1903
1897
|
async #startTransactionImpl(options) {
|
|
1904
|
-
const validatedOptions = options !== void 0 ? this
|
|
1898
|
+
const validatedOptions = options !== void 0 ? this.#validateOptions(options) : this.transactionOptions;
|
|
1905
1899
|
const transaction = {
|
|
1906
1900
|
id: await randomUUID(),
|
|
1907
1901
|
status: "waiting",
|
|
@@ -1918,13 +1912,12 @@ var TransactionManager = class {
|
|
|
1918
1912
|
switch (transaction.status) {
|
|
1919
1913
|
case "waiting":
|
|
1920
1914
|
if (hasTimedOut) {
|
|
1921
|
-
await this
|
|
1915
|
+
await this.#closeTransaction(transaction, "timed_out");
|
|
1922
1916
|
throw new TransactionStartTimeoutError();
|
|
1923
1917
|
}
|
|
1924
1918
|
transaction.status = "running";
|
|
1925
|
-
transaction.timer = this
|
|
1919
|
+
transaction.timer = this.#startTransactionTimeout(transaction.id, validatedOptions.timeout);
|
|
1926
1920
|
return { id: transaction.id };
|
|
1927
|
-
case "closing":
|
|
1928
1921
|
case "timed_out":
|
|
1929
1922
|
case "running":
|
|
1930
1923
|
case "committed":
|
|
@@ -1933,27 +1926,31 @@ var TransactionManager = class {
|
|
|
1933
1926
|
`Transaction in invalid state ${transaction.status} although it just finished startup.`
|
|
1934
1927
|
);
|
|
1935
1928
|
default:
|
|
1936
|
-
assertNever(transaction
|
|
1929
|
+
assertNever(transaction["status"], "Unknown transaction status.");
|
|
1937
1930
|
}
|
|
1938
1931
|
}
|
|
1939
1932
|
async commitTransaction(transactionId) {
|
|
1940
1933
|
return await this.tracingHelper.runInChildSpan("commit_transaction", async () => {
|
|
1941
|
-
const txw = this
|
|
1942
|
-
await this
|
|
1934
|
+
const txw = this.#getActiveOrClosingTransaction(transactionId, "commit");
|
|
1935
|
+
await this.#closeTransaction(txw, "committed");
|
|
1943
1936
|
});
|
|
1944
1937
|
}
|
|
1945
1938
|
async rollbackTransaction(transactionId) {
|
|
1946
1939
|
return await this.tracingHelper.runInChildSpan("rollback_transaction", async () => {
|
|
1947
|
-
const txw = this
|
|
1948
|
-
await this
|
|
1940
|
+
const txw = this.#getActiveOrClosingTransaction(transactionId, "rollback");
|
|
1941
|
+
await this.#closeTransaction(txw, "rolled_back");
|
|
1949
1942
|
});
|
|
1950
1943
|
}
|
|
1951
|
-
getTransaction(txInfo, operation) {
|
|
1952
|
-
|
|
1944
|
+
async getTransaction(txInfo, operation) {
|
|
1945
|
+
let tx = this.#getActiveOrClosingTransaction(txInfo.id, operation);
|
|
1946
|
+
if (tx.status === "closing") {
|
|
1947
|
+
await tx.closing;
|
|
1948
|
+
tx = this.#getActiveOrClosingTransaction(txInfo.id, operation);
|
|
1949
|
+
}
|
|
1953
1950
|
if (!tx.transaction) throw new TransactionNotFoundError();
|
|
1954
1951
|
return tx.transaction;
|
|
1955
1952
|
}
|
|
1956
|
-
|
|
1953
|
+
#getActiveOrClosingTransaction(transactionId, operation) {
|
|
1957
1954
|
const transaction = this.transactions.get(transactionId);
|
|
1958
1955
|
if (!transaction) {
|
|
1959
1956
|
const closedTransaction = this.closedTransactions.find((tx) => tx.id === transactionId);
|
|
@@ -1979,62 +1976,74 @@ var TransactionManager = class {
|
|
|
1979
1976
|
throw new TransactionNotFoundError();
|
|
1980
1977
|
}
|
|
1981
1978
|
}
|
|
1982
|
-
if (transaction.status === "closing") {
|
|
1983
|
-
throw new TransactionClosingError(operation);
|
|
1984
|
-
}
|
|
1985
1979
|
if (["committed", "rolled_back", "timed_out"].includes(transaction.status)) {
|
|
1986
1980
|
throw new TransactionInternalConsistencyError("Closed transaction found in active transactions map.");
|
|
1987
1981
|
}
|
|
1988
1982
|
return transaction;
|
|
1989
1983
|
}
|
|
1990
1984
|
async cancelAllTransactions() {
|
|
1991
|
-
await Promise.allSettled([...this.transactions.values()].map((tx) => this
|
|
1985
|
+
await Promise.allSettled([...this.transactions.values()].map((tx) => this.#closeTransaction(tx, "rolled_back")));
|
|
1992
1986
|
}
|
|
1993
|
-
startTransactionTimeout(transactionId, timeout) {
|
|
1987
|
+
#startTransactionTimeout(transactionId, timeout) {
|
|
1994
1988
|
const timeoutStartedAt = Date.now();
|
|
1995
1989
|
return setTimeout(async () => {
|
|
1996
1990
|
debug("Transaction timed out.", { transactionId, timeoutStartedAt, timeout });
|
|
1997
1991
|
const tx = this.transactions.get(transactionId);
|
|
1998
1992
|
if (tx && ["running", "waiting"].includes(tx.status)) {
|
|
1999
|
-
await this
|
|
1993
|
+
await this.#closeTransaction(tx, "timed_out");
|
|
2000
1994
|
} else {
|
|
2001
1995
|
debug("Transaction already committed or rolled back when timeout happened.", transactionId);
|
|
2002
1996
|
}
|
|
2003
1997
|
}, timeout);
|
|
2004
1998
|
}
|
|
2005
|
-
async closeTransaction(tx, status) {
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
1999
|
+
async #closeTransaction(tx, status) {
|
|
2000
|
+
const createClosingPromise = async () => {
|
|
2001
|
+
debug("Closing transaction.", { transactionId: tx.id, status });
|
|
2002
|
+
try {
|
|
2003
|
+
if (tx.transaction && status === "committed") {
|
|
2004
|
+
if (tx.transaction.options.usePhantomQuery) {
|
|
2005
|
+
await this.#withQuerySpanAndEvent(PHANTOM_COMMIT_QUERY(), tx.transaction, () => tx.transaction.commit());
|
|
2006
|
+
} else {
|
|
2007
|
+
const query = COMMIT_QUERY();
|
|
2008
|
+
await this.#withQuerySpanAndEvent(query, tx.transaction, () => tx.transaction.executeRaw(query));
|
|
2009
|
+
await tx.transaction.commit();
|
|
2010
|
+
}
|
|
2011
|
+
} else if (tx.transaction) {
|
|
2012
|
+
if (tx.transaction.options.usePhantomQuery) {
|
|
2013
|
+
await this.#withQuerySpanAndEvent(
|
|
2014
|
+
PHANTOM_ROLLBACK_QUERY(),
|
|
2015
|
+
tx.transaction,
|
|
2016
|
+
() => tx.transaction.rollback()
|
|
2017
|
+
);
|
|
2018
|
+
} else {
|
|
2019
|
+
const query = ROLLBACK_QUERY();
|
|
2020
|
+
await this.#withQuerySpanAndEvent(query, tx.transaction, () => tx.transaction.executeRaw(query));
|
|
2021
|
+
await tx.transaction.rollback();
|
|
2022
|
+
}
|
|
2016
2023
|
}
|
|
2017
|
-
}
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
+
} finally {
|
|
2025
|
+
tx.status = status;
|
|
2026
|
+
clearTimeout(tx.timer);
|
|
2027
|
+
tx.timer = void 0;
|
|
2028
|
+
this.transactions.delete(tx.id);
|
|
2029
|
+
this.closedTransactions.push(tx);
|
|
2030
|
+
if (this.closedTransactions.length > MAX_CLOSED_TRANSACTIONS) {
|
|
2031
|
+
this.closedTransactions.shift();
|
|
2024
2032
|
}
|
|
2025
2033
|
}
|
|
2026
|
-
}
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
tx.
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2034
|
+
};
|
|
2035
|
+
if (tx.status === "closing") {
|
|
2036
|
+
await tx.closing;
|
|
2037
|
+
this.#getActiveOrClosingTransaction(tx.id, status === "committed" ? "commit" : "rollback");
|
|
2038
|
+
} else {
|
|
2039
|
+
await Object.assign(tx, {
|
|
2040
|
+
status: "closing",
|
|
2041
|
+
reason: status,
|
|
2042
|
+
closing: createClosingPromise()
|
|
2043
|
+
}).closing;
|
|
2035
2044
|
}
|
|
2036
2045
|
}
|
|
2037
|
-
validateOptions(options) {
|
|
2046
|
+
#validateOptions(options) {
|
|
2038
2047
|
if (!options.timeout) throw new TransactionManagerError("timeout is required");
|
|
2039
2048
|
if (!options.maxWait) throw new TransactionManagerError("maxWait is required");
|
|
2040
2049
|
if (options.isolationLevel === "SNAPSHOT") throw new InvalidTransactionIsolationLevelError(options.isolationLevel);
|
|
@@ -2064,8 +2073,6 @@ export {
|
|
|
2064
2073
|
deserializeJsonResponse,
|
|
2065
2074
|
doKeysMatch,
|
|
2066
2075
|
isDeepStrictEqual,
|
|
2067
|
-
isPrismaValueBigInt,
|
|
2068
|
-
isPrismaValueBytes,
|
|
2069
2076
|
isPrismaValueGenerator,
|
|
2070
2077
|
isPrismaValuePlaceholder,
|
|
2071
2078
|
noopTracingHelper,
|