@prisma/client-engine-runtime 6.14.0-dev.3 → 6.14.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/QueryPlan.d.ts +15 -12
- package/dist/UserFacingError.d.ts +1 -0
- package/dist/index.d.mts +29 -14
- package/dist/index.d.ts +29 -14
- package/dist/index.js +461 -141
- package/dist/index.mjs +460 -141
- package/dist/interpreter/QueryInterpreter.d.ts +4 -2
- package/dist/interpreter/in-memory-processing.d.ts +3 -0
- package/dist/interpreter/renderQuery.d.ts +1 -1
- package/dist/raw-json-protocol.d.ts +6 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -43,6 +43,7 @@ __export(index_exports, {
|
|
|
43
43
|
isPrismaValuePlaceholder: () => isPrismaValuePlaceholder,
|
|
44
44
|
noopTracingHelper: () => noopTracingHelper,
|
|
45
45
|
normalizeJsonProtocolValues: () => normalizeJsonProtocolValues,
|
|
46
|
+
normalizeRawJsonProtocolResponse: () => normalizeRawJsonProtocolResponse,
|
|
46
47
|
safeJsonStringify: () => safeJsonStringify
|
|
47
48
|
});
|
|
48
49
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -318,8 +319,10 @@ function mapValue(value, columnName, resultType, enums) {
|
|
|
318
319
|
return values.map((v, i) => mapValue(v, `${columnName}[${i}]`, resultType.inner, enums));
|
|
319
320
|
}
|
|
320
321
|
case "Object": {
|
|
321
|
-
|
|
322
|
-
|
|
322
|
+
return { $type: "Json", value: safeJsonStringify(value) };
|
|
323
|
+
}
|
|
324
|
+
case "Json": {
|
|
325
|
+
return { $type: "Json", value: `${value}` };
|
|
323
326
|
}
|
|
324
327
|
case "Bytes": {
|
|
325
328
|
if (typeof value === "string" && value.startsWith("\\x")) {
|
|
@@ -340,7 +343,7 @@ function mapValue(value, columnName, resultType, enums) {
|
|
|
340
343
|
}
|
|
341
344
|
const enumValue = enumDef[`${value}`];
|
|
342
345
|
if (enumValue === void 0) {
|
|
343
|
-
throw new DataMapperError(`
|
|
346
|
+
throw new DataMapperError(`Value '${value}' not found in enum '${resultType.inner}'`);
|
|
344
347
|
}
|
|
345
348
|
return enumValue;
|
|
346
349
|
}
|
|
@@ -450,6 +453,16 @@ function rethrowAsUserFacing(error) {
|
|
|
450
453
|
}
|
|
451
454
|
throw new UserFacingError(message, code, { driverAdapterError: error });
|
|
452
455
|
}
|
|
456
|
+
function rethrowAsUserFacingRawError(error) {
|
|
457
|
+
if (!(0, import_driver_adapter_utils.isDriverAdapterError)(error)) {
|
|
458
|
+
throw error;
|
|
459
|
+
}
|
|
460
|
+
throw new UserFacingError(
|
|
461
|
+
`Raw query failed. Code: ${error.cause.originalCode ?? "N/A"}. Message: ${error.cause.originalMessage ?? renderErrorMessage(error)}`,
|
|
462
|
+
"P2010",
|
|
463
|
+
{ driverAdapterError: error }
|
|
464
|
+
);
|
|
465
|
+
}
|
|
453
466
|
function getErrorCode(err) {
|
|
454
467
|
switch (err.cause.kind) {
|
|
455
468
|
case "AuthenticationFailed":
|
|
@@ -693,6 +706,97 @@ var ProductGenerator = class {
|
|
|
693
706
|
}
|
|
694
707
|
};
|
|
695
708
|
|
|
709
|
+
// src/interpreter/in-memory-processing.ts
|
|
710
|
+
function processRecords(value, ops) {
|
|
711
|
+
if (value == null) {
|
|
712
|
+
return value;
|
|
713
|
+
}
|
|
714
|
+
if (typeof value === "string") {
|
|
715
|
+
return processRecords(JSON.parse(value), ops);
|
|
716
|
+
}
|
|
717
|
+
if (Array.isArray(value)) {
|
|
718
|
+
return processManyRecords(value, ops);
|
|
719
|
+
}
|
|
720
|
+
return processOneRecord(value, ops);
|
|
721
|
+
}
|
|
722
|
+
function processOneRecord(record, ops) {
|
|
723
|
+
if (ops.pagination) {
|
|
724
|
+
const { skip, take, cursor } = ops.pagination;
|
|
725
|
+
if (skip !== null && skip > 0) {
|
|
726
|
+
return null;
|
|
727
|
+
}
|
|
728
|
+
if (take === 0) {
|
|
729
|
+
return null;
|
|
730
|
+
}
|
|
731
|
+
if (cursor !== null && !doKeysMatch(record, cursor)) {
|
|
732
|
+
return null;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
return processNestedRecords(record, ops.nested);
|
|
736
|
+
}
|
|
737
|
+
function processNestedRecords(record, opsMap) {
|
|
738
|
+
for (const [key, ops] of Object.entries(opsMap)) {
|
|
739
|
+
record[key] = processRecords(record[key], ops);
|
|
740
|
+
}
|
|
741
|
+
return record;
|
|
742
|
+
}
|
|
743
|
+
function processManyRecords(records, ops) {
|
|
744
|
+
if (ops.distinct !== null) {
|
|
745
|
+
const fields = ops.linkingFields !== null ? [...ops.distinct, ...ops.linkingFields] : ops.distinct;
|
|
746
|
+
records = distinctBy(records, fields);
|
|
747
|
+
}
|
|
748
|
+
if (ops.pagination) {
|
|
749
|
+
records = paginate(records, ops.pagination, ops.linkingFields);
|
|
750
|
+
}
|
|
751
|
+
if (ops.reverse) {
|
|
752
|
+
records.reverse();
|
|
753
|
+
}
|
|
754
|
+
if (Object.keys(ops.nested).length === 0) {
|
|
755
|
+
return records;
|
|
756
|
+
}
|
|
757
|
+
return records.map((record) => processNestedRecords(record, ops.nested));
|
|
758
|
+
}
|
|
759
|
+
function distinctBy(records, fields) {
|
|
760
|
+
const seen = /* @__PURE__ */ new Set();
|
|
761
|
+
const result = [];
|
|
762
|
+
for (const record of records) {
|
|
763
|
+
const key = getRecordKey(record, fields);
|
|
764
|
+
if (!seen.has(key)) {
|
|
765
|
+
seen.add(key);
|
|
766
|
+
result.push(record);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
return result;
|
|
770
|
+
}
|
|
771
|
+
function paginate(records, pagination, linkingFields) {
|
|
772
|
+
if (linkingFields === null) {
|
|
773
|
+
return paginateSingleList(records, pagination);
|
|
774
|
+
}
|
|
775
|
+
const groupedByParent = /* @__PURE__ */ new Map();
|
|
776
|
+
for (const record of records) {
|
|
777
|
+
const parentKey = getRecordKey(record, linkingFields);
|
|
778
|
+
if (!groupedByParent.has(parentKey)) {
|
|
779
|
+
groupedByParent.set(parentKey, []);
|
|
780
|
+
}
|
|
781
|
+
groupedByParent.get(parentKey).push(record);
|
|
782
|
+
}
|
|
783
|
+
const groupList = Array.from(groupedByParent.entries());
|
|
784
|
+
groupList.sort(([aId], [bId]) => aId < bId ? -1 : aId > bId ? 1 : 0);
|
|
785
|
+
return groupList.flatMap(([, elems]) => paginateSingleList(elems, pagination));
|
|
786
|
+
}
|
|
787
|
+
function paginateSingleList(list, { cursor, skip, take }) {
|
|
788
|
+
const cursorIndex = cursor !== null ? list.findIndex((item) => doKeysMatch(item, cursor)) : 0;
|
|
789
|
+
if (cursorIndex === -1) {
|
|
790
|
+
return [];
|
|
791
|
+
}
|
|
792
|
+
const start = cursorIndex + (skip ?? 0);
|
|
793
|
+
const end = take !== null ? start + take : list.length;
|
|
794
|
+
return list.slice(start, end);
|
|
795
|
+
}
|
|
796
|
+
function getRecordKey(record, fields) {
|
|
797
|
+
return JSON.stringify(fields.map((field) => record[field]));
|
|
798
|
+
}
|
|
799
|
+
|
|
696
800
|
// src/QueryPlan.ts
|
|
697
801
|
function isPrismaValuePlaceholder(value) {
|
|
698
802
|
return typeof value === "object" && value !== null && value["prisma__type"] === "param";
|
|
@@ -708,17 +812,21 @@ function isPrismaValueBigInt(value) {
|
|
|
708
812
|
}
|
|
709
813
|
|
|
710
814
|
// src/interpreter/renderQuery.ts
|
|
711
|
-
function renderQuery(dbQuery, scope, generators) {
|
|
815
|
+
function renderQuery(dbQuery, scope, generators, maxChunkSize) {
|
|
712
816
|
const queryType = dbQuery.type;
|
|
817
|
+
const params = evaluateParams(dbQuery.params, scope, generators);
|
|
713
818
|
switch (queryType) {
|
|
714
819
|
case "rawSql":
|
|
715
|
-
return renderRawSql(dbQuery.sql, evaluateParams(dbQuery.params, scope, generators));
|
|
716
|
-
case "templateSql":
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
820
|
+
return [renderRawSql(dbQuery.sql, evaluateParams(dbQuery.params, scope, generators))];
|
|
821
|
+
case "templateSql": {
|
|
822
|
+
const chunks = dbQuery.chunkable ? chunkParams(dbQuery.fragments, params, maxChunkSize) : [params];
|
|
823
|
+
return chunks.map((params2) => {
|
|
824
|
+
if (maxChunkSize !== void 0 && params2.length > maxChunkSize) {
|
|
825
|
+
throw new UserFacingError("The query parameter limit supported by your database is exceeded.", "P2029");
|
|
826
|
+
}
|
|
827
|
+
return renderTemplateSql(dbQuery.fragments, dbQuery.placeholderFormat, params2);
|
|
828
|
+
});
|
|
829
|
+
}
|
|
722
830
|
default:
|
|
723
831
|
assertNever(queryType, `Invalid query type`);
|
|
724
832
|
}
|
|
@@ -756,61 +864,36 @@ function evaluateParam(param, scope, generators) {
|
|
|
756
864
|
return value;
|
|
757
865
|
}
|
|
758
866
|
function renderTemplateSql(fragments, placeholderFormat, params) {
|
|
759
|
-
let
|
|
760
|
-
|
|
867
|
+
let sql = "";
|
|
868
|
+
const ctx = { placeholderNumber: 1 };
|
|
761
869
|
const flattenedParams = [];
|
|
762
|
-
const
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
if (paramIndex >= params.length) {
|
|
767
|
-
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
768
|
-
}
|
|
769
|
-
flattenedParams.push(params[paramIndex++]);
|
|
770
|
-
return formatPlaceholder(placeholderFormat, placeholderNumber++);
|
|
771
|
-
case "stringChunk":
|
|
772
|
-
return fragment.chunk;
|
|
773
|
-
case "parameterTuple": {
|
|
774
|
-
if (paramIndex >= params.length) {
|
|
775
|
-
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
776
|
-
}
|
|
777
|
-
const paramValue = params[paramIndex++];
|
|
778
|
-
const paramArray = Array.isArray(paramValue) ? paramValue : [paramValue];
|
|
779
|
-
const placeholders = paramArray.length == 0 ? "NULL" : paramArray.map((value) => {
|
|
780
|
-
flattenedParams.push(value);
|
|
781
|
-
return formatPlaceholder(placeholderFormat, placeholderNumber++);
|
|
782
|
-
}).join(",");
|
|
783
|
-
return `(${placeholders})`;
|
|
784
|
-
}
|
|
785
|
-
case "parameterTupleList": {
|
|
786
|
-
if (paramIndex >= params.length) {
|
|
787
|
-
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
788
|
-
}
|
|
789
|
-
const paramValue = params[paramIndex++];
|
|
790
|
-
if (!Array.isArray(paramValue)) {
|
|
791
|
-
throw new Error(`Malformed query template. Tuple list expected.`);
|
|
792
|
-
}
|
|
793
|
-
if (paramValue.length === 0) {
|
|
794
|
-
throw new Error(`Malformed query template. Tuple list cannot be empty.`);
|
|
795
|
-
}
|
|
796
|
-
const tupleList = paramValue.map((tuple) => {
|
|
797
|
-
if (!Array.isArray(tuple)) {
|
|
798
|
-
throw new Error(`Malformed query template. Tuple expected.`);
|
|
799
|
-
}
|
|
800
|
-
const elements = tuple.map((value) => {
|
|
801
|
-
flattenedParams.push(value);
|
|
802
|
-
return formatPlaceholder(placeholderFormat, placeholderNumber++);
|
|
803
|
-
}).join(fragment.itemSeparator);
|
|
804
|
-
return `${fragment.itemPrefix}${elements}${fragment.itemSuffix}`;
|
|
805
|
-
}).join(fragment.groupSeparator);
|
|
806
|
-
return tupleList;
|
|
807
|
-
}
|
|
808
|
-
default:
|
|
809
|
-
assertNever(fragmentType, "Invalid fragment type");
|
|
810
|
-
}
|
|
811
|
-
}).join("");
|
|
870
|
+
for (const fragment of pairFragmentsWithParams(fragments, params)) {
|
|
871
|
+
flattenedParams.push(...flattenedFragmentParams(fragment));
|
|
872
|
+
sql += renderFragment(fragment, placeholderFormat, ctx);
|
|
873
|
+
}
|
|
812
874
|
return renderRawSql(sql, flattenedParams);
|
|
813
875
|
}
|
|
876
|
+
function renderFragment(fragment, placeholderFormat, ctx) {
|
|
877
|
+
const fragmentType = fragment.type;
|
|
878
|
+
switch (fragmentType) {
|
|
879
|
+
case "parameter":
|
|
880
|
+
return formatPlaceholder(placeholderFormat, ctx.placeholderNumber++);
|
|
881
|
+
case "stringChunk":
|
|
882
|
+
return fragment.chunk;
|
|
883
|
+
case "parameterTuple": {
|
|
884
|
+
const placeholders = fragment.value.length == 0 ? "NULL" : fragment.value.map(() => formatPlaceholder(placeholderFormat, ctx.placeholderNumber++)).join(",");
|
|
885
|
+
return `(${placeholders})`;
|
|
886
|
+
}
|
|
887
|
+
case "parameterTupleList": {
|
|
888
|
+
return fragment.value.map((tuple) => {
|
|
889
|
+
const elements = tuple.map(() => formatPlaceholder(placeholderFormat, ctx.placeholderNumber++)).join(fragment.itemSeparator);
|
|
890
|
+
return `${fragment.itemPrefix}${elements}${fragment.itemSuffix}`;
|
|
891
|
+
}).join(fragment.groupSeparator);
|
|
892
|
+
}
|
|
893
|
+
default:
|
|
894
|
+
assertNever(fragmentType, "Invalid fragment type");
|
|
895
|
+
}
|
|
896
|
+
}
|
|
814
897
|
function formatPlaceholder(placeholderFormat, placeholderNumber) {
|
|
815
898
|
return placeholderFormat.hasNumbering ? `${placeholderFormat.prefix}${placeholderNumber}` : placeholderFormat.prefix;
|
|
816
899
|
}
|
|
@@ -843,6 +926,143 @@ function toArgType(value) {
|
|
|
843
926
|
function doesRequireEvaluation(param) {
|
|
844
927
|
return isPrismaValuePlaceholder(param) || isPrismaValueGenerator(param);
|
|
845
928
|
}
|
|
929
|
+
function* pairFragmentsWithParams(fragments, params) {
|
|
930
|
+
let index = 0;
|
|
931
|
+
for (const fragment of fragments) {
|
|
932
|
+
switch (fragment.type) {
|
|
933
|
+
case "parameter": {
|
|
934
|
+
if (index >= params.length) {
|
|
935
|
+
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
936
|
+
}
|
|
937
|
+
yield { ...fragment, value: params[index++] };
|
|
938
|
+
break;
|
|
939
|
+
}
|
|
940
|
+
case "stringChunk": {
|
|
941
|
+
yield fragment;
|
|
942
|
+
break;
|
|
943
|
+
}
|
|
944
|
+
case "parameterTuple": {
|
|
945
|
+
if (index >= params.length) {
|
|
946
|
+
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
947
|
+
}
|
|
948
|
+
const value = params[index++];
|
|
949
|
+
yield { ...fragment, value: Array.isArray(value) ? value : [value] };
|
|
950
|
+
break;
|
|
951
|
+
}
|
|
952
|
+
case "parameterTupleList": {
|
|
953
|
+
if (index >= params.length) {
|
|
954
|
+
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
955
|
+
}
|
|
956
|
+
const value = params[index++];
|
|
957
|
+
if (!Array.isArray(value)) {
|
|
958
|
+
throw new Error(`Malformed query template. Tuple list expected.`);
|
|
959
|
+
}
|
|
960
|
+
if (value.length === 0) {
|
|
961
|
+
throw new Error(`Malformed query template. Tuple list cannot be empty.`);
|
|
962
|
+
}
|
|
963
|
+
for (const tuple of value) {
|
|
964
|
+
if (!Array.isArray(tuple)) {
|
|
965
|
+
throw new Error(`Malformed query template. Tuple expected.`);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
yield { ...fragment, value };
|
|
969
|
+
break;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
function* flattenedFragmentParams(fragment) {
|
|
975
|
+
switch (fragment.type) {
|
|
976
|
+
case "parameter":
|
|
977
|
+
yield fragment.value;
|
|
978
|
+
break;
|
|
979
|
+
case "stringChunk":
|
|
980
|
+
break;
|
|
981
|
+
case "parameterTuple":
|
|
982
|
+
yield* fragment.value;
|
|
983
|
+
break;
|
|
984
|
+
case "parameterTupleList":
|
|
985
|
+
for (const tuple of fragment.value) {
|
|
986
|
+
yield* tuple;
|
|
987
|
+
}
|
|
988
|
+
break;
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
function chunkParams(fragments, params, maxChunkSize) {
|
|
992
|
+
let totalParamCount = 0;
|
|
993
|
+
let maxParamsPerFragment = 0;
|
|
994
|
+
for (const fragment of pairFragmentsWithParams(fragments, params)) {
|
|
995
|
+
let paramSize = 0;
|
|
996
|
+
for (const _ of flattenedFragmentParams(fragment)) {
|
|
997
|
+
void _;
|
|
998
|
+
paramSize++;
|
|
999
|
+
}
|
|
1000
|
+
maxParamsPerFragment = Math.max(maxParamsPerFragment, paramSize);
|
|
1001
|
+
totalParamCount += paramSize;
|
|
1002
|
+
}
|
|
1003
|
+
let chunkedParams = [[]];
|
|
1004
|
+
for (const fragment of pairFragmentsWithParams(fragments, params)) {
|
|
1005
|
+
switch (fragment.type) {
|
|
1006
|
+
case "parameter": {
|
|
1007
|
+
for (const params2 of chunkedParams) {
|
|
1008
|
+
params2.push(fragment.value);
|
|
1009
|
+
}
|
|
1010
|
+
break;
|
|
1011
|
+
}
|
|
1012
|
+
case "stringChunk": {
|
|
1013
|
+
break;
|
|
1014
|
+
}
|
|
1015
|
+
case "parameterTuple": {
|
|
1016
|
+
const thisParamCount = fragment.value.length;
|
|
1017
|
+
let chunks = [];
|
|
1018
|
+
if (maxChunkSize && // Have we split the parameters into chunks already?
|
|
1019
|
+
chunkedParams.length === 1 && // Is this the fragment that has the most parameters?
|
|
1020
|
+
thisParamCount === maxParamsPerFragment && // Do we need chunking to fit the parameters?
|
|
1021
|
+
totalParamCount > maxChunkSize && // Would chunking enable us to fit the parameters?
|
|
1022
|
+
totalParamCount - thisParamCount < maxChunkSize) {
|
|
1023
|
+
const availableSize = maxChunkSize - (totalParamCount - thisParamCount);
|
|
1024
|
+
chunks = chunkArray(fragment.value, availableSize);
|
|
1025
|
+
} else {
|
|
1026
|
+
chunks = [fragment.value];
|
|
1027
|
+
}
|
|
1028
|
+
chunkedParams = chunkedParams.flatMap((params2) => chunks.map((chunk) => [...params2, chunk]));
|
|
1029
|
+
break;
|
|
1030
|
+
}
|
|
1031
|
+
case "parameterTupleList": {
|
|
1032
|
+
const thisParamCount = fragment.value.reduce((acc, tuple) => acc + tuple.length, 0);
|
|
1033
|
+
const completeChunks = [];
|
|
1034
|
+
let currentChunk = [];
|
|
1035
|
+
let currentChunkParamCount = 0;
|
|
1036
|
+
for (const tuple of fragment.value) {
|
|
1037
|
+
if (maxChunkSize && // Have we split the parameters into chunks already?
|
|
1038
|
+
chunkedParams.length === 1 && // Is this the fragment that has the most parameters?
|
|
1039
|
+
thisParamCount === maxParamsPerFragment && // Is there anything in the current chunk?
|
|
1040
|
+
currentChunk.length > 0 && // Will adding this tuple exceed the max chunk size?
|
|
1041
|
+
totalParamCount - thisParamCount + currentChunkParamCount + tuple.length > maxChunkSize) {
|
|
1042
|
+
completeChunks.push(currentChunk);
|
|
1043
|
+
currentChunk = [];
|
|
1044
|
+
currentChunkParamCount = 0;
|
|
1045
|
+
}
|
|
1046
|
+
currentChunk.push(tuple);
|
|
1047
|
+
currentChunkParamCount += tuple.length;
|
|
1048
|
+
}
|
|
1049
|
+
if (currentChunk.length > 0) {
|
|
1050
|
+
completeChunks.push(currentChunk);
|
|
1051
|
+
}
|
|
1052
|
+
chunkedParams = chunkedParams.flatMap((params2) => completeChunks.map((chunk) => [...params2, chunk]));
|
|
1053
|
+
break;
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
return chunkedParams;
|
|
1058
|
+
}
|
|
1059
|
+
function chunkArray(array, chunkSize) {
|
|
1060
|
+
const result = [];
|
|
1061
|
+
for (let i = 0; i < array.length; i += chunkSize) {
|
|
1062
|
+
result.push(array.slice(i, i + chunkSize));
|
|
1063
|
+
}
|
|
1064
|
+
return result;
|
|
1065
|
+
}
|
|
846
1066
|
|
|
847
1067
|
// src/interpreter/serializeSql.ts
|
|
848
1068
|
var import_driver_adapter_utils2 = require("@prisma/driver-adapter-utils");
|
|
@@ -875,29 +1095,90 @@ function serializeSql(resultSet) {
|
|
|
875
1095
|
);
|
|
876
1096
|
}
|
|
877
1097
|
function serializeRawSql(resultSet) {
|
|
878
|
-
const types = resultSet.columnTypes.map((type) => serializeColumnType(type));
|
|
879
|
-
const mappers = types.map((type) => {
|
|
880
|
-
switch (type) {
|
|
881
|
-
case "bytes":
|
|
882
|
-
return (value) => Array.isArray(value) ? new Uint8Array(value) : value;
|
|
883
|
-
case "int":
|
|
884
|
-
return (value) => value === null ? null : typeof value === "number" ? value : parseInt(`${value}`, 10);
|
|
885
|
-
case "bigint":
|
|
886
|
-
return (value) => value === null ? null : typeof value === "bigint" ? value : BigInt(`${value}`);
|
|
887
|
-
case "json":
|
|
888
|
-
return (value) => typeof value === "string" ? JSON.parse(value) : value;
|
|
889
|
-
case "bool":
|
|
890
|
-
return (value) => typeof value === "string" ? value === "true" || value === "1" : typeof value === "number" ? value === 1 : value;
|
|
891
|
-
default:
|
|
892
|
-
return (value) => value;
|
|
893
|
-
}
|
|
894
|
-
});
|
|
895
1098
|
return {
|
|
896
1099
|
columns: resultSet.columnNames,
|
|
897
1100
|
types: resultSet.columnTypes.map((type) => serializeColumnType(type)),
|
|
898
|
-
rows: resultSet.rows.map(
|
|
1101
|
+
rows: resultSet.rows.map(
|
|
1102
|
+
(row) => row.map((value, index) => serializeRawValue(value, resultSet.columnTypes[index]))
|
|
1103
|
+
)
|
|
899
1104
|
};
|
|
900
1105
|
}
|
|
1106
|
+
function serializeRawValue(value, type) {
|
|
1107
|
+
if (value === null) {
|
|
1108
|
+
return null;
|
|
1109
|
+
}
|
|
1110
|
+
switch (type) {
|
|
1111
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Int32:
|
|
1112
|
+
switch (typeof value) {
|
|
1113
|
+
case "number":
|
|
1114
|
+
return Math.trunc(value);
|
|
1115
|
+
case "string":
|
|
1116
|
+
return Math.trunc(Number(value));
|
|
1117
|
+
default:
|
|
1118
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as Int32`);
|
|
1119
|
+
}
|
|
1120
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Int32Array:
|
|
1121
|
+
if (!Array.isArray(value)) {
|
|
1122
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as Int32Array`);
|
|
1123
|
+
}
|
|
1124
|
+
return value.map((v) => serializeRawValue(v, import_driver_adapter_utils2.ColumnTypeEnum.Int32));
|
|
1125
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Int64:
|
|
1126
|
+
switch (typeof value) {
|
|
1127
|
+
case "number":
|
|
1128
|
+
return BigInt(Math.trunc(value));
|
|
1129
|
+
case "string":
|
|
1130
|
+
return value;
|
|
1131
|
+
default:
|
|
1132
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as Int64`);
|
|
1133
|
+
}
|
|
1134
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Int64Array:
|
|
1135
|
+
if (!Array.isArray(value)) {
|
|
1136
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as Int64Array`);
|
|
1137
|
+
}
|
|
1138
|
+
return value.map((v) => serializeRawValue(v, import_driver_adapter_utils2.ColumnTypeEnum.Int64));
|
|
1139
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Json:
|
|
1140
|
+
switch (typeof value) {
|
|
1141
|
+
case "string":
|
|
1142
|
+
return JSON.parse(value);
|
|
1143
|
+
default:
|
|
1144
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as Json`);
|
|
1145
|
+
}
|
|
1146
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.JsonArray:
|
|
1147
|
+
if (!Array.isArray(value)) {
|
|
1148
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as JsonArray`);
|
|
1149
|
+
}
|
|
1150
|
+
return value.map((v) => serializeRawValue(v, import_driver_adapter_utils2.ColumnTypeEnum.Json));
|
|
1151
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Bytes:
|
|
1152
|
+
if (Array.isArray(value)) {
|
|
1153
|
+
return new Uint8Array(value);
|
|
1154
|
+
} else {
|
|
1155
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as Bytes`);
|
|
1156
|
+
}
|
|
1157
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.BytesArray:
|
|
1158
|
+
if (!Array.isArray(value)) {
|
|
1159
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as BytesArray`);
|
|
1160
|
+
}
|
|
1161
|
+
return value.map((v) => serializeRawValue(v, import_driver_adapter_utils2.ColumnTypeEnum.Bytes));
|
|
1162
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Boolean:
|
|
1163
|
+
switch (typeof value) {
|
|
1164
|
+
case "boolean":
|
|
1165
|
+
return value;
|
|
1166
|
+
case "string":
|
|
1167
|
+
return value === "true" || value === "1";
|
|
1168
|
+
case "number":
|
|
1169
|
+
return value === 1;
|
|
1170
|
+
default:
|
|
1171
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as Boolean`);
|
|
1172
|
+
}
|
|
1173
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.BooleanArray:
|
|
1174
|
+
if (!Array.isArray(value)) {
|
|
1175
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as BooleanArray`);
|
|
1176
|
+
}
|
|
1177
|
+
return value.map((v) => serializeRawValue(v, import_driver_adapter_utils2.ColumnTypeEnum.Boolean));
|
|
1178
|
+
default:
|
|
1179
|
+
return value;
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
901
1182
|
function serializeColumnType(columnType) {
|
|
902
1183
|
switch (columnType) {
|
|
903
1184
|
case import_driver_adapter_utils2.ColumnTypeEnum.Int32:
|
|
@@ -1052,6 +1333,7 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1052
1333
|
#serializer;
|
|
1053
1334
|
#rawSerializer;
|
|
1054
1335
|
#provider;
|
|
1336
|
+
#connectioInfo;
|
|
1055
1337
|
constructor({
|
|
1056
1338
|
transactionManager,
|
|
1057
1339
|
placeholderValues,
|
|
@@ -1059,7 +1341,8 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1059
1341
|
tracingHelper,
|
|
1060
1342
|
serializer,
|
|
1061
1343
|
rawSerializer,
|
|
1062
|
-
provider
|
|
1344
|
+
provider,
|
|
1345
|
+
connectionInfo
|
|
1063
1346
|
}) {
|
|
1064
1347
|
this.#transactionManager = transactionManager;
|
|
1065
1348
|
this.#placeholderValues = placeholderValues;
|
|
@@ -1068,6 +1351,7 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1068
1351
|
this.#serializer = serializer;
|
|
1069
1352
|
this.#rawSerializer = rawSerializer ?? serializer;
|
|
1070
1353
|
this.#provider = provider;
|
|
1354
|
+
this.#connectioInfo = connectionInfo;
|
|
1071
1355
|
}
|
|
1072
1356
|
static forSql(options) {
|
|
1073
1357
|
return new _QueryInterpreter({
|
|
@@ -1077,7 +1361,8 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1077
1361
|
tracingHelper: options.tracingHelper,
|
|
1078
1362
|
serializer: serializeSql,
|
|
1079
1363
|
rawSerializer: serializeRawSql,
|
|
1080
|
-
provider: options.provider
|
|
1364
|
+
provider: options.provider,
|
|
1365
|
+
connectionInfo: options.connectionInfo
|
|
1081
1366
|
});
|
|
1082
1367
|
}
|
|
1083
1368
|
async run(queryPlan, queryable) {
|
|
@@ -1138,21 +1423,41 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1138
1423
|
};
|
|
1139
1424
|
}
|
|
1140
1425
|
case "execute": {
|
|
1141
|
-
const
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1426
|
+
const queries = renderQuery(node.args, scope, generators, this.#maxChunkSize());
|
|
1427
|
+
let sum = 0;
|
|
1428
|
+
for (const query of queries) {
|
|
1429
|
+
sum += await this.#withQuerySpanAndEvent(
|
|
1430
|
+
query,
|
|
1431
|
+
queryable,
|
|
1432
|
+
() => queryable.executeRaw(query).catch(
|
|
1433
|
+
(err) => node.args.type === "rawSql" ? rethrowAsUserFacingRawError(err) : rethrowAsUserFacing(err)
|
|
1434
|
+
)
|
|
1435
|
+
);
|
|
1436
|
+
}
|
|
1437
|
+
return { value: sum };
|
|
1145
1438
|
}
|
|
1146
1439
|
case "query": {
|
|
1147
|
-
const
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1440
|
+
const queries = renderQuery(node.args, scope, generators, this.#maxChunkSize());
|
|
1441
|
+
let results;
|
|
1442
|
+
for (const query of queries) {
|
|
1443
|
+
const result = await this.#withQuerySpanAndEvent(
|
|
1444
|
+
query,
|
|
1445
|
+
queryable,
|
|
1446
|
+
() => queryable.queryRaw(query).catch(
|
|
1447
|
+
(err) => node.args.type === "rawSql" ? rethrowAsUserFacingRawError(err) : rethrowAsUserFacing(err)
|
|
1448
|
+
)
|
|
1449
|
+
);
|
|
1450
|
+
if (results === void 0) {
|
|
1451
|
+
results = result;
|
|
1152
1452
|
} else {
|
|
1153
|
-
|
|
1453
|
+
results.rows.push(...result.rows);
|
|
1454
|
+
results.lastInsertId = result.lastInsertId;
|
|
1154
1455
|
}
|
|
1155
|
-
}
|
|
1456
|
+
}
|
|
1457
|
+
return {
|
|
1458
|
+
value: node.args.type === "rawSql" ? this.#rawSerializer(results) : this.#serializer(results),
|
|
1459
|
+
lastInsertId: results?.lastInsertId
|
|
1460
|
+
};
|
|
1156
1461
|
}
|
|
1157
1462
|
case "reverse": {
|
|
1158
1463
|
const { value, lastInsertId } = await this.interpretNode(node.args, queryable, scope, generators);
|
|
@@ -1231,43 +1536,12 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1231
1536
|
case "diff": {
|
|
1232
1537
|
const { value: from } = await this.interpretNode(node.args.from, queryable, scope, generators);
|
|
1233
1538
|
const { value: to } = await this.interpretNode(node.args.to, queryable, scope, generators);
|
|
1234
|
-
const toSet = new Set(asList(to));
|
|
1235
|
-
return { value: asList(from).filter((item) => !toSet.has(item)) };
|
|
1539
|
+
const toSet = new Set(asList(to).map((item) => JSON.stringify(item)));
|
|
1540
|
+
return { value: asList(from).filter((item) => !toSet.has(JSON.stringify(item))) };
|
|
1236
1541
|
}
|
|
1237
|
-
case "
|
|
1542
|
+
case "process": {
|
|
1238
1543
|
const { value, lastInsertId } = await this.interpretNode(node.args.expr, queryable, scope, generators);
|
|
1239
|
-
|
|
1240
|
-
const result = [];
|
|
1241
|
-
for (const item of asList(value)) {
|
|
1242
|
-
const key = getRecordKey(item, node.args.fields);
|
|
1243
|
-
if (!seen.has(key)) {
|
|
1244
|
-
seen.add(key);
|
|
1245
|
-
result.push(item);
|
|
1246
|
-
}
|
|
1247
|
-
}
|
|
1248
|
-
return { value: result, lastInsertId };
|
|
1249
|
-
}
|
|
1250
|
-
case "paginate": {
|
|
1251
|
-
const { value, lastInsertId } = await this.interpretNode(node.args.expr, queryable, scope, generators);
|
|
1252
|
-
const list = asList(value);
|
|
1253
|
-
const linkingFields = node.args.pagination.linkingFields;
|
|
1254
|
-
if (linkingFields !== null) {
|
|
1255
|
-
const groupedByParent = /* @__PURE__ */ new Map();
|
|
1256
|
-
for (const item of list) {
|
|
1257
|
-
const parentKey = getRecordKey(item, linkingFields);
|
|
1258
|
-
if (!groupedByParent.has(parentKey)) {
|
|
1259
|
-
groupedByParent.set(parentKey, []);
|
|
1260
|
-
}
|
|
1261
|
-
groupedByParent.get(parentKey).push(item);
|
|
1262
|
-
}
|
|
1263
|
-
const groupList = Array.from(groupedByParent.entries());
|
|
1264
|
-
groupList.sort(([aId], [bId]) => aId < bId ? -1 : aId > bId ? 1 : 0);
|
|
1265
|
-
return {
|
|
1266
|
-
value: groupList.flatMap(([, elems]) => paginate(elems, node.args.pagination)),
|
|
1267
|
-
lastInsertId
|
|
1268
|
-
};
|
|
1269
|
-
}
|
|
1270
|
-
return { value: paginate(list, node.args.pagination), lastInsertId };
|
|
1544
|
+
return { value: processRecords(value, node.args.operations), lastInsertId };
|
|
1271
1545
|
}
|
|
1272
1546
|
case "initializeRecord": {
|
|
1273
1547
|
const { lastInsertId } = await this.interpretNode(node.args.expr, queryable, scope, generators);
|
|
@@ -1289,6 +1563,34 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1289
1563
|
assertNever(node, `Unexpected node type: ${node.type}`);
|
|
1290
1564
|
}
|
|
1291
1565
|
}
|
|
1566
|
+
#maxChunkSize() {
|
|
1567
|
+
if (this.#connectioInfo?.maxBindValues !== void 0) {
|
|
1568
|
+
return this.#connectioInfo.maxBindValues;
|
|
1569
|
+
}
|
|
1570
|
+
return this.#providerMaxChunkSize();
|
|
1571
|
+
}
|
|
1572
|
+
#providerMaxChunkSize() {
|
|
1573
|
+
if (this.#provider === void 0) {
|
|
1574
|
+
return void 0;
|
|
1575
|
+
}
|
|
1576
|
+
switch (this.#provider) {
|
|
1577
|
+
case "cockroachdb":
|
|
1578
|
+
case "postgres":
|
|
1579
|
+
case "postgresql":
|
|
1580
|
+
case "prisma+postgres":
|
|
1581
|
+
return 32766;
|
|
1582
|
+
case "mysql":
|
|
1583
|
+
return 65535;
|
|
1584
|
+
case "sqlite":
|
|
1585
|
+
return 999;
|
|
1586
|
+
case "sqlserver":
|
|
1587
|
+
return 2098;
|
|
1588
|
+
case "mongodb":
|
|
1589
|
+
return void 0;
|
|
1590
|
+
default:
|
|
1591
|
+
assertNever(this.#provider, `Unexpected provider: ${this.#provider}`);
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1292
1594
|
#withQuerySpanAndEvent(query, queryable, execute) {
|
|
1293
1595
|
return withQuerySpanAndEvent({
|
|
1294
1596
|
query,
|
|
@@ -1366,18 +1668,6 @@ function attachChildrenToParents(parentRecords, children) {
|
|
|
1366
1668
|
}
|
|
1367
1669
|
return parentRecords;
|
|
1368
1670
|
}
|
|
1369
|
-
function paginate(list, { cursor, skip, take }) {
|
|
1370
|
-
const cursorIndex = cursor !== null ? list.findIndex((item) => doKeysMatch(item, cursor)) : 0;
|
|
1371
|
-
if (cursorIndex === -1) {
|
|
1372
|
-
return [];
|
|
1373
|
-
}
|
|
1374
|
-
const start = cursorIndex + (skip ?? 0);
|
|
1375
|
-
const end = take !== null ? start + take : list.length;
|
|
1376
|
-
return list.slice(start, end);
|
|
1377
|
-
}
|
|
1378
|
-
function getRecordKey(record, fields) {
|
|
1379
|
-
return JSON.stringify(fields.map((field) => record[field]));
|
|
1380
|
-
}
|
|
1381
1671
|
function evalFieldInitializer(initializer, lastInsertId, scope, generators) {
|
|
1382
1672
|
switch (initializer.type) {
|
|
1383
1673
|
case "value":
|
|
@@ -1458,6 +1748,35 @@ function mapObjectValues(object, mapper) {
|
|
|
1458
1748
|
return result;
|
|
1459
1749
|
}
|
|
1460
1750
|
|
|
1751
|
+
// src/raw-json-protocol.ts
|
|
1752
|
+
var import_decimal4 = __toESM(require("decimal.js"));
|
|
1753
|
+
function normalizeRawJsonProtocolResponse(response) {
|
|
1754
|
+
for (let i = 0; i < response.rows.length; i++) {
|
|
1755
|
+
const row = response.rows[i];
|
|
1756
|
+
for (let j = 0; j < row.length; j++) {
|
|
1757
|
+
row[j] = normalizeValue(response.types[j], row[j]);
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
return response;
|
|
1761
|
+
}
|
|
1762
|
+
function normalizeValue(type, value) {
|
|
1763
|
+
if (value === null) {
|
|
1764
|
+
return value;
|
|
1765
|
+
}
|
|
1766
|
+
switch (type) {
|
|
1767
|
+
case "bigint":
|
|
1768
|
+
return String(BigInt(value));
|
|
1769
|
+
case "decimal":
|
|
1770
|
+
return String(new import_decimal4.default(value));
|
|
1771
|
+
case "bigint-array":
|
|
1772
|
+
return value.map((v) => normalizeValue("bigint", v));
|
|
1773
|
+
case "decimal-array":
|
|
1774
|
+
return value.map((v) => normalizeValue("decimal", v));
|
|
1775
|
+
default:
|
|
1776
|
+
return value;
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1461
1780
|
// src/transactionManager/TransactionManager.ts
|
|
1462
1781
|
var import_debug = require("@prisma/debug");
|
|
1463
1782
|
|
|
@@ -1734,5 +2053,6 @@ var TransactionManager = class {
|
|
|
1734
2053
|
isPrismaValuePlaceholder,
|
|
1735
2054
|
noopTracingHelper,
|
|
1736
2055
|
normalizeJsonProtocolValues,
|
|
2056
|
+
normalizeRawJsonProtocolResponse,
|
|
1737
2057
|
safeJsonStringify
|
|
1738
2058
|
});
|