@prisma/client-engine-runtime 6.14.0-dev.2 → 6.14.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 +3 -0
- package/dist/UserFacingError.d.ts +1 -0
- package/dist/index.d.mts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +366 -94
- package/dist/index.mjs +365 -94
- package/dist/interpreter/QueryInterpreter.d.ts +4 -2
- 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.mjs
CHANGED
|
@@ -269,8 +269,10 @@ function mapValue(value, columnName, resultType, enums) {
|
|
|
269
269
|
return values.map((v, i) => mapValue(v, `${columnName}[${i}]`, resultType.inner, enums));
|
|
270
270
|
}
|
|
271
271
|
case "Object": {
|
|
272
|
-
|
|
273
|
-
|
|
272
|
+
return { $type: "Json", value: safeJsonStringify(value) };
|
|
273
|
+
}
|
|
274
|
+
case "Json": {
|
|
275
|
+
return { $type: "Json", value: `${value}` };
|
|
274
276
|
}
|
|
275
277
|
case "Bytes": {
|
|
276
278
|
if (typeof value === "string" && value.startsWith("\\x")) {
|
|
@@ -291,7 +293,7 @@ function mapValue(value, columnName, resultType, enums) {
|
|
|
291
293
|
}
|
|
292
294
|
const enumValue = enumDef[`${value}`];
|
|
293
295
|
if (enumValue === void 0) {
|
|
294
|
-
throw new DataMapperError(`
|
|
296
|
+
throw new DataMapperError(`Value '${value}' not found in enum '${resultType.inner}'`);
|
|
295
297
|
}
|
|
296
298
|
return enumValue;
|
|
297
299
|
}
|
|
@@ -401,6 +403,16 @@ function rethrowAsUserFacing(error) {
|
|
|
401
403
|
}
|
|
402
404
|
throw new UserFacingError(message, code, { driverAdapterError: error });
|
|
403
405
|
}
|
|
406
|
+
function rethrowAsUserFacingRawError(error) {
|
|
407
|
+
if (!isDriverAdapterError(error)) {
|
|
408
|
+
throw error;
|
|
409
|
+
}
|
|
410
|
+
throw new UserFacingError(
|
|
411
|
+
`Raw query failed. Code: ${error.cause.originalCode ?? "N/A"}. Message: ${error.cause.originalMessage ?? renderErrorMessage(error)}`,
|
|
412
|
+
"P2010",
|
|
413
|
+
{ driverAdapterError: error }
|
|
414
|
+
);
|
|
415
|
+
}
|
|
404
416
|
function getErrorCode(err) {
|
|
405
417
|
switch (err.cause.kind) {
|
|
406
418
|
case "AuthenticationFailed":
|
|
@@ -659,17 +671,21 @@ function isPrismaValueBigInt(value) {
|
|
|
659
671
|
}
|
|
660
672
|
|
|
661
673
|
// src/interpreter/renderQuery.ts
|
|
662
|
-
function renderQuery(dbQuery, scope, generators) {
|
|
674
|
+
function renderQuery(dbQuery, scope, generators, maxChunkSize) {
|
|
663
675
|
const queryType = dbQuery.type;
|
|
676
|
+
const params = evaluateParams(dbQuery.params, scope, generators);
|
|
664
677
|
switch (queryType) {
|
|
665
678
|
case "rawSql":
|
|
666
|
-
return renderRawSql(dbQuery.sql, evaluateParams(dbQuery.params, scope, generators));
|
|
667
|
-
case "templateSql":
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
679
|
+
return [renderRawSql(dbQuery.sql, evaluateParams(dbQuery.params, scope, generators))];
|
|
680
|
+
case "templateSql": {
|
|
681
|
+
const chunks = dbQuery.chunkable ? chunkParams(dbQuery.fragments, params, maxChunkSize) : [params];
|
|
682
|
+
return chunks.map((params2) => {
|
|
683
|
+
if (maxChunkSize !== void 0 && params2.length > maxChunkSize) {
|
|
684
|
+
throw new UserFacingError("The query parameter limit supported by your database is exceeded.", "P2029");
|
|
685
|
+
}
|
|
686
|
+
return renderTemplateSql(dbQuery.fragments, dbQuery.placeholderFormat, params2);
|
|
687
|
+
});
|
|
688
|
+
}
|
|
673
689
|
default:
|
|
674
690
|
assertNever(queryType, `Invalid query type`);
|
|
675
691
|
}
|
|
@@ -707,61 +723,36 @@ function evaluateParam(param, scope, generators) {
|
|
|
707
723
|
return value;
|
|
708
724
|
}
|
|
709
725
|
function renderTemplateSql(fragments, placeholderFormat, params) {
|
|
710
|
-
let
|
|
711
|
-
|
|
726
|
+
let sql = "";
|
|
727
|
+
const ctx = { placeholderNumber: 1 };
|
|
712
728
|
const flattenedParams = [];
|
|
713
|
-
const
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
if (paramIndex >= params.length) {
|
|
718
|
-
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
719
|
-
}
|
|
720
|
-
flattenedParams.push(params[paramIndex++]);
|
|
721
|
-
return formatPlaceholder(placeholderFormat, placeholderNumber++);
|
|
722
|
-
case "stringChunk":
|
|
723
|
-
return fragment.chunk;
|
|
724
|
-
case "parameterTuple": {
|
|
725
|
-
if (paramIndex >= params.length) {
|
|
726
|
-
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
727
|
-
}
|
|
728
|
-
const paramValue = params[paramIndex++];
|
|
729
|
-
const paramArray = Array.isArray(paramValue) ? paramValue : [paramValue];
|
|
730
|
-
const placeholders = paramArray.length == 0 ? "NULL" : paramArray.map((value) => {
|
|
731
|
-
flattenedParams.push(value);
|
|
732
|
-
return formatPlaceholder(placeholderFormat, placeholderNumber++);
|
|
733
|
-
}).join(",");
|
|
734
|
-
return `(${placeholders})`;
|
|
735
|
-
}
|
|
736
|
-
case "parameterTupleList": {
|
|
737
|
-
if (paramIndex >= params.length) {
|
|
738
|
-
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
739
|
-
}
|
|
740
|
-
const paramValue = params[paramIndex++];
|
|
741
|
-
if (!Array.isArray(paramValue)) {
|
|
742
|
-
throw new Error(`Malformed query template. Tuple list expected.`);
|
|
743
|
-
}
|
|
744
|
-
if (paramValue.length === 0) {
|
|
745
|
-
throw new Error(`Malformed query template. Tuple list cannot be empty.`);
|
|
746
|
-
}
|
|
747
|
-
const tupleList = paramValue.map((tuple) => {
|
|
748
|
-
if (!Array.isArray(tuple)) {
|
|
749
|
-
throw new Error(`Malformed query template. Tuple expected.`);
|
|
750
|
-
}
|
|
751
|
-
const elements = tuple.map((value) => {
|
|
752
|
-
flattenedParams.push(value);
|
|
753
|
-
return formatPlaceholder(placeholderFormat, placeholderNumber++);
|
|
754
|
-
}).join(fragment.itemSeparator);
|
|
755
|
-
return `${fragment.itemPrefix}${elements}${fragment.itemSuffix}`;
|
|
756
|
-
}).join(fragment.groupSeparator);
|
|
757
|
-
return tupleList;
|
|
758
|
-
}
|
|
759
|
-
default:
|
|
760
|
-
assertNever(fragmentType, "Invalid fragment type");
|
|
761
|
-
}
|
|
762
|
-
}).join("");
|
|
729
|
+
for (const fragment of pairFragmentsWithParams(fragments, params)) {
|
|
730
|
+
flattenedParams.push(...flattenedFragmentParams(fragment));
|
|
731
|
+
sql += renderFragment(fragment, placeholderFormat, ctx);
|
|
732
|
+
}
|
|
763
733
|
return renderRawSql(sql, flattenedParams);
|
|
764
734
|
}
|
|
735
|
+
function renderFragment(fragment, placeholderFormat, ctx) {
|
|
736
|
+
const fragmentType = fragment.type;
|
|
737
|
+
switch (fragmentType) {
|
|
738
|
+
case "parameter":
|
|
739
|
+
return formatPlaceholder(placeholderFormat, ctx.placeholderNumber++);
|
|
740
|
+
case "stringChunk":
|
|
741
|
+
return fragment.chunk;
|
|
742
|
+
case "parameterTuple": {
|
|
743
|
+
const placeholders = fragment.value.length == 0 ? "NULL" : fragment.value.map(() => formatPlaceholder(placeholderFormat, ctx.placeholderNumber++)).join(",");
|
|
744
|
+
return `(${placeholders})`;
|
|
745
|
+
}
|
|
746
|
+
case "parameterTupleList": {
|
|
747
|
+
return fragment.value.map((tuple) => {
|
|
748
|
+
const elements = tuple.map(() => formatPlaceholder(placeholderFormat, ctx.placeholderNumber++)).join(fragment.itemSeparator);
|
|
749
|
+
return `${fragment.itemPrefix}${elements}${fragment.itemSuffix}`;
|
|
750
|
+
}).join(fragment.groupSeparator);
|
|
751
|
+
}
|
|
752
|
+
default:
|
|
753
|
+
assertNever(fragmentType, "Invalid fragment type");
|
|
754
|
+
}
|
|
755
|
+
}
|
|
765
756
|
function formatPlaceholder(placeholderFormat, placeholderNumber) {
|
|
766
757
|
return placeholderFormat.hasNumbering ? `${placeholderFormat.prefix}${placeholderNumber}` : placeholderFormat.prefix;
|
|
767
758
|
}
|
|
@@ -794,6 +785,143 @@ function toArgType(value) {
|
|
|
794
785
|
function doesRequireEvaluation(param) {
|
|
795
786
|
return isPrismaValuePlaceholder(param) || isPrismaValueGenerator(param);
|
|
796
787
|
}
|
|
788
|
+
function* pairFragmentsWithParams(fragments, params) {
|
|
789
|
+
let index = 0;
|
|
790
|
+
for (const fragment of fragments) {
|
|
791
|
+
switch (fragment.type) {
|
|
792
|
+
case "parameter": {
|
|
793
|
+
if (index >= params.length) {
|
|
794
|
+
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
795
|
+
}
|
|
796
|
+
yield { ...fragment, value: params[index++] };
|
|
797
|
+
break;
|
|
798
|
+
}
|
|
799
|
+
case "stringChunk": {
|
|
800
|
+
yield fragment;
|
|
801
|
+
break;
|
|
802
|
+
}
|
|
803
|
+
case "parameterTuple": {
|
|
804
|
+
if (index >= params.length) {
|
|
805
|
+
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
806
|
+
}
|
|
807
|
+
const value = params[index++];
|
|
808
|
+
yield { ...fragment, value: Array.isArray(value) ? value : [value] };
|
|
809
|
+
break;
|
|
810
|
+
}
|
|
811
|
+
case "parameterTupleList": {
|
|
812
|
+
if (index >= params.length) {
|
|
813
|
+
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
814
|
+
}
|
|
815
|
+
const value = params[index++];
|
|
816
|
+
if (!Array.isArray(value)) {
|
|
817
|
+
throw new Error(`Malformed query template. Tuple list expected.`);
|
|
818
|
+
}
|
|
819
|
+
if (value.length === 0) {
|
|
820
|
+
throw new Error(`Malformed query template. Tuple list cannot be empty.`);
|
|
821
|
+
}
|
|
822
|
+
for (const tuple of value) {
|
|
823
|
+
if (!Array.isArray(tuple)) {
|
|
824
|
+
throw new Error(`Malformed query template. Tuple expected.`);
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
yield { ...fragment, value };
|
|
828
|
+
break;
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
function* flattenedFragmentParams(fragment) {
|
|
834
|
+
switch (fragment.type) {
|
|
835
|
+
case "parameter":
|
|
836
|
+
yield fragment.value;
|
|
837
|
+
break;
|
|
838
|
+
case "stringChunk":
|
|
839
|
+
break;
|
|
840
|
+
case "parameterTuple":
|
|
841
|
+
yield* fragment.value;
|
|
842
|
+
break;
|
|
843
|
+
case "parameterTupleList":
|
|
844
|
+
for (const tuple of fragment.value) {
|
|
845
|
+
yield* tuple;
|
|
846
|
+
}
|
|
847
|
+
break;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
function chunkParams(fragments, params, maxChunkSize) {
|
|
851
|
+
let totalParamCount = 0;
|
|
852
|
+
let maxParamsPerFragment = 0;
|
|
853
|
+
for (const fragment of pairFragmentsWithParams(fragments, params)) {
|
|
854
|
+
let paramSize = 0;
|
|
855
|
+
for (const _ of flattenedFragmentParams(fragment)) {
|
|
856
|
+
void _;
|
|
857
|
+
paramSize++;
|
|
858
|
+
}
|
|
859
|
+
maxParamsPerFragment = Math.max(maxParamsPerFragment, paramSize);
|
|
860
|
+
totalParamCount += paramSize;
|
|
861
|
+
}
|
|
862
|
+
let chunkedParams = [[]];
|
|
863
|
+
for (const fragment of pairFragmentsWithParams(fragments, params)) {
|
|
864
|
+
switch (fragment.type) {
|
|
865
|
+
case "parameter": {
|
|
866
|
+
for (const params2 of chunkedParams) {
|
|
867
|
+
params2.push(fragment.value);
|
|
868
|
+
}
|
|
869
|
+
break;
|
|
870
|
+
}
|
|
871
|
+
case "stringChunk": {
|
|
872
|
+
break;
|
|
873
|
+
}
|
|
874
|
+
case "parameterTuple": {
|
|
875
|
+
const thisParamCount = fragment.value.length;
|
|
876
|
+
let chunks = [];
|
|
877
|
+
if (maxChunkSize && // Have we split the parameters into chunks already?
|
|
878
|
+
chunkedParams.length === 1 && // Is this the fragment that has the most parameters?
|
|
879
|
+
thisParamCount === maxParamsPerFragment && // Do we need chunking to fit the parameters?
|
|
880
|
+
totalParamCount > maxChunkSize && // Would chunking enable us to fit the parameters?
|
|
881
|
+
totalParamCount - thisParamCount < maxChunkSize) {
|
|
882
|
+
const availableSize = maxChunkSize - (totalParamCount - thisParamCount);
|
|
883
|
+
chunks = chunkArray(fragment.value, availableSize);
|
|
884
|
+
} else {
|
|
885
|
+
chunks = [fragment.value];
|
|
886
|
+
}
|
|
887
|
+
chunkedParams = chunkedParams.flatMap((params2) => chunks.map((chunk) => [...params2, chunk]));
|
|
888
|
+
break;
|
|
889
|
+
}
|
|
890
|
+
case "parameterTupleList": {
|
|
891
|
+
const thisParamCount = fragment.value.reduce((acc, tuple) => acc + tuple.length, 0);
|
|
892
|
+
const completeChunks = [];
|
|
893
|
+
let currentChunk = [];
|
|
894
|
+
let currentChunkParamCount = 0;
|
|
895
|
+
for (const tuple of fragment.value) {
|
|
896
|
+
if (maxChunkSize && // Have we split the parameters into chunks already?
|
|
897
|
+
chunkedParams.length === 1 && // Is this the fragment that has the most parameters?
|
|
898
|
+
thisParamCount === maxParamsPerFragment && // Is there anything in the current chunk?
|
|
899
|
+
currentChunk.length > 0 && // Will adding this tuple exceed the max chunk size?
|
|
900
|
+
totalParamCount - thisParamCount + currentChunkParamCount + tuple.length > maxChunkSize) {
|
|
901
|
+
completeChunks.push(currentChunk);
|
|
902
|
+
currentChunk = [];
|
|
903
|
+
currentChunkParamCount = 0;
|
|
904
|
+
}
|
|
905
|
+
currentChunk.push(tuple);
|
|
906
|
+
currentChunkParamCount += tuple.length;
|
|
907
|
+
}
|
|
908
|
+
if (currentChunk.length > 0) {
|
|
909
|
+
completeChunks.push(currentChunk);
|
|
910
|
+
}
|
|
911
|
+
chunkedParams = chunkedParams.flatMap((params2) => completeChunks.map((chunk) => [...params2, chunk]));
|
|
912
|
+
break;
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
return chunkedParams;
|
|
917
|
+
}
|
|
918
|
+
function chunkArray(array, chunkSize) {
|
|
919
|
+
const result = [];
|
|
920
|
+
for (let i = 0; i < array.length; i += chunkSize) {
|
|
921
|
+
result.push(array.slice(i, i + chunkSize));
|
|
922
|
+
}
|
|
923
|
+
return result;
|
|
924
|
+
}
|
|
797
925
|
|
|
798
926
|
// src/interpreter/serializeSql.ts
|
|
799
927
|
import { ColumnTypeEnum } from "@prisma/driver-adapter-utils";
|
|
@@ -826,29 +954,90 @@ function serializeSql(resultSet) {
|
|
|
826
954
|
);
|
|
827
955
|
}
|
|
828
956
|
function serializeRawSql(resultSet) {
|
|
829
|
-
const types = resultSet.columnTypes.map((type) => serializeColumnType(type));
|
|
830
|
-
const mappers = types.map((type) => {
|
|
831
|
-
switch (type) {
|
|
832
|
-
case "bytes":
|
|
833
|
-
return (value) => Array.isArray(value) ? new Uint8Array(value) : value;
|
|
834
|
-
case "int":
|
|
835
|
-
return (value) => value === null ? null : typeof value === "number" ? value : parseInt(`${value}`, 10);
|
|
836
|
-
case "bigint":
|
|
837
|
-
return (value) => value === null ? null : typeof value === "bigint" ? value : BigInt(`${value}`);
|
|
838
|
-
case "json":
|
|
839
|
-
return (value) => typeof value === "string" ? JSON.parse(value) : value;
|
|
840
|
-
case "bool":
|
|
841
|
-
return (value) => typeof value === "string" ? value === "true" || value === "1" : typeof value === "number" ? value === 1 : value;
|
|
842
|
-
default:
|
|
843
|
-
return (value) => value;
|
|
844
|
-
}
|
|
845
|
-
});
|
|
846
957
|
return {
|
|
847
958
|
columns: resultSet.columnNames,
|
|
848
959
|
types: resultSet.columnTypes.map((type) => serializeColumnType(type)),
|
|
849
|
-
rows: resultSet.rows.map(
|
|
960
|
+
rows: resultSet.rows.map(
|
|
961
|
+
(row) => row.map((value, index) => serializeRawValue(value, resultSet.columnTypes[index]))
|
|
962
|
+
)
|
|
850
963
|
};
|
|
851
964
|
}
|
|
965
|
+
function serializeRawValue(value, type) {
|
|
966
|
+
if (value === null) {
|
|
967
|
+
return null;
|
|
968
|
+
}
|
|
969
|
+
switch (type) {
|
|
970
|
+
case ColumnTypeEnum.Int32:
|
|
971
|
+
switch (typeof value) {
|
|
972
|
+
case "number":
|
|
973
|
+
return Math.trunc(value);
|
|
974
|
+
case "string":
|
|
975
|
+
return Math.trunc(Number(value));
|
|
976
|
+
default:
|
|
977
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as Int32`);
|
|
978
|
+
}
|
|
979
|
+
case ColumnTypeEnum.Int32Array:
|
|
980
|
+
if (!Array.isArray(value)) {
|
|
981
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as Int32Array`);
|
|
982
|
+
}
|
|
983
|
+
return value.map((v) => serializeRawValue(v, ColumnTypeEnum.Int32));
|
|
984
|
+
case ColumnTypeEnum.Int64:
|
|
985
|
+
switch (typeof value) {
|
|
986
|
+
case "number":
|
|
987
|
+
return BigInt(Math.trunc(value));
|
|
988
|
+
case "string":
|
|
989
|
+
return value;
|
|
990
|
+
default:
|
|
991
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as Int64`);
|
|
992
|
+
}
|
|
993
|
+
case ColumnTypeEnum.Int64Array:
|
|
994
|
+
if (!Array.isArray(value)) {
|
|
995
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as Int64Array`);
|
|
996
|
+
}
|
|
997
|
+
return value.map((v) => serializeRawValue(v, ColumnTypeEnum.Int64));
|
|
998
|
+
case ColumnTypeEnum.Json:
|
|
999
|
+
switch (typeof value) {
|
|
1000
|
+
case "string":
|
|
1001
|
+
return JSON.parse(value);
|
|
1002
|
+
default:
|
|
1003
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as Json`);
|
|
1004
|
+
}
|
|
1005
|
+
case ColumnTypeEnum.JsonArray:
|
|
1006
|
+
if (!Array.isArray(value)) {
|
|
1007
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as JsonArray`);
|
|
1008
|
+
}
|
|
1009
|
+
return value.map((v) => serializeRawValue(v, ColumnTypeEnum.Json));
|
|
1010
|
+
case ColumnTypeEnum.Bytes:
|
|
1011
|
+
if (Array.isArray(value)) {
|
|
1012
|
+
return new Uint8Array(value);
|
|
1013
|
+
} else {
|
|
1014
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as Bytes`);
|
|
1015
|
+
}
|
|
1016
|
+
case ColumnTypeEnum.BytesArray:
|
|
1017
|
+
if (!Array.isArray(value)) {
|
|
1018
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as BytesArray`);
|
|
1019
|
+
}
|
|
1020
|
+
return value.map((v) => serializeRawValue(v, ColumnTypeEnum.Bytes));
|
|
1021
|
+
case ColumnTypeEnum.Boolean:
|
|
1022
|
+
switch (typeof value) {
|
|
1023
|
+
case "boolean":
|
|
1024
|
+
return value;
|
|
1025
|
+
case "string":
|
|
1026
|
+
return value === "true" || value === "1";
|
|
1027
|
+
case "number":
|
|
1028
|
+
return value === 1;
|
|
1029
|
+
default:
|
|
1030
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as Boolean`);
|
|
1031
|
+
}
|
|
1032
|
+
case ColumnTypeEnum.BooleanArray:
|
|
1033
|
+
if (!Array.isArray(value)) {
|
|
1034
|
+
throw new Error(`Cannot serialize value of type ${typeof value} as BooleanArray`);
|
|
1035
|
+
}
|
|
1036
|
+
return value.map((v) => serializeRawValue(v, ColumnTypeEnum.Boolean));
|
|
1037
|
+
default:
|
|
1038
|
+
return value;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
852
1041
|
function serializeColumnType(columnType) {
|
|
853
1042
|
switch (columnType) {
|
|
854
1043
|
case ColumnTypeEnum.Int32:
|
|
@@ -1003,6 +1192,7 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1003
1192
|
#serializer;
|
|
1004
1193
|
#rawSerializer;
|
|
1005
1194
|
#provider;
|
|
1195
|
+
#connectioInfo;
|
|
1006
1196
|
constructor({
|
|
1007
1197
|
transactionManager,
|
|
1008
1198
|
placeholderValues,
|
|
@@ -1010,7 +1200,8 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1010
1200
|
tracingHelper,
|
|
1011
1201
|
serializer,
|
|
1012
1202
|
rawSerializer,
|
|
1013
|
-
provider
|
|
1203
|
+
provider,
|
|
1204
|
+
connectionInfo
|
|
1014
1205
|
}) {
|
|
1015
1206
|
this.#transactionManager = transactionManager;
|
|
1016
1207
|
this.#placeholderValues = placeholderValues;
|
|
@@ -1019,6 +1210,7 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1019
1210
|
this.#serializer = serializer;
|
|
1020
1211
|
this.#rawSerializer = rawSerializer ?? serializer;
|
|
1021
1212
|
this.#provider = provider;
|
|
1213
|
+
this.#connectioInfo = connectionInfo;
|
|
1022
1214
|
}
|
|
1023
1215
|
static forSql(options) {
|
|
1024
1216
|
return new _QueryInterpreter({
|
|
@@ -1028,7 +1220,8 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1028
1220
|
tracingHelper: options.tracingHelper,
|
|
1029
1221
|
serializer: serializeSql,
|
|
1030
1222
|
rawSerializer: serializeRawSql,
|
|
1031
|
-
provider: options.provider
|
|
1223
|
+
provider: options.provider,
|
|
1224
|
+
connectionInfo: options.connectionInfo
|
|
1032
1225
|
});
|
|
1033
1226
|
}
|
|
1034
1227
|
async run(queryPlan, queryable) {
|
|
@@ -1089,21 +1282,41 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1089
1282
|
};
|
|
1090
1283
|
}
|
|
1091
1284
|
case "execute": {
|
|
1092
|
-
const
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1285
|
+
const queries = renderQuery(node.args, scope, generators, this.#maxChunkSize());
|
|
1286
|
+
let sum = 0;
|
|
1287
|
+
for (const query of queries) {
|
|
1288
|
+
sum += await this.#withQuerySpanAndEvent(
|
|
1289
|
+
query,
|
|
1290
|
+
queryable,
|
|
1291
|
+
() => queryable.executeRaw(query).catch(
|
|
1292
|
+
(err) => node.args.type === "rawSql" ? rethrowAsUserFacingRawError(err) : rethrowAsUserFacing(err)
|
|
1293
|
+
)
|
|
1294
|
+
);
|
|
1295
|
+
}
|
|
1296
|
+
return { value: sum };
|
|
1096
1297
|
}
|
|
1097
1298
|
case "query": {
|
|
1098
|
-
const
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1299
|
+
const queries = renderQuery(node.args, scope, generators, this.#maxChunkSize());
|
|
1300
|
+
let results;
|
|
1301
|
+
for (const query of queries) {
|
|
1302
|
+
const result = await this.#withQuerySpanAndEvent(
|
|
1303
|
+
query,
|
|
1304
|
+
queryable,
|
|
1305
|
+
() => queryable.queryRaw(query).catch(
|
|
1306
|
+
(err) => node.args.type === "rawSql" ? rethrowAsUserFacingRawError(err) : rethrowAsUserFacing(err)
|
|
1307
|
+
)
|
|
1308
|
+
);
|
|
1309
|
+
if (results === void 0) {
|
|
1310
|
+
results = result;
|
|
1103
1311
|
} else {
|
|
1104
|
-
|
|
1312
|
+
results.rows.push(...result.rows);
|
|
1313
|
+
results.lastInsertId = result.lastInsertId;
|
|
1105
1314
|
}
|
|
1106
|
-
}
|
|
1315
|
+
}
|
|
1316
|
+
return {
|
|
1317
|
+
value: node.args.type === "rawSql" ? this.#rawSerializer(results) : this.#serializer(results),
|
|
1318
|
+
lastInsertId: results?.lastInsertId
|
|
1319
|
+
};
|
|
1107
1320
|
}
|
|
1108
1321
|
case "reverse": {
|
|
1109
1322
|
const { value, lastInsertId } = await this.interpretNode(node.args, queryable, scope, generators);
|
|
@@ -1240,6 +1453,34 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1240
1453
|
assertNever(node, `Unexpected node type: ${node.type}`);
|
|
1241
1454
|
}
|
|
1242
1455
|
}
|
|
1456
|
+
#maxChunkSize() {
|
|
1457
|
+
if (this.#connectioInfo?.maxBindValues !== void 0) {
|
|
1458
|
+
return this.#connectioInfo.maxBindValues;
|
|
1459
|
+
}
|
|
1460
|
+
return this.#providerMaxChunkSize();
|
|
1461
|
+
}
|
|
1462
|
+
#providerMaxChunkSize() {
|
|
1463
|
+
if (this.#provider === void 0) {
|
|
1464
|
+
return void 0;
|
|
1465
|
+
}
|
|
1466
|
+
switch (this.#provider) {
|
|
1467
|
+
case "cockroachdb":
|
|
1468
|
+
case "postgres":
|
|
1469
|
+
case "postgresql":
|
|
1470
|
+
case "prisma+postgres":
|
|
1471
|
+
return 32766;
|
|
1472
|
+
case "mysql":
|
|
1473
|
+
return 65535;
|
|
1474
|
+
case "sqlite":
|
|
1475
|
+
return 999;
|
|
1476
|
+
case "sqlserver":
|
|
1477
|
+
return 2098;
|
|
1478
|
+
case "mongodb":
|
|
1479
|
+
return void 0;
|
|
1480
|
+
default:
|
|
1481
|
+
assertNever(this.#provider, `Unexpected provider: ${this.#provider}`);
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1243
1484
|
#withQuerySpanAndEvent(query, queryable, execute) {
|
|
1244
1485
|
return withQuerySpanAndEvent({
|
|
1245
1486
|
query,
|
|
@@ -1409,6 +1650,35 @@ function mapObjectValues(object, mapper) {
|
|
|
1409
1650
|
return result;
|
|
1410
1651
|
}
|
|
1411
1652
|
|
|
1653
|
+
// src/raw-json-protocol.ts
|
|
1654
|
+
import Decimal4 from "decimal.js";
|
|
1655
|
+
function normalizeRawJsonProtocolResponse(response) {
|
|
1656
|
+
for (let i = 0; i < response.rows.length; i++) {
|
|
1657
|
+
const row = response.rows[i];
|
|
1658
|
+
for (let j = 0; j < row.length; j++) {
|
|
1659
|
+
row[j] = normalizeValue(response.types[j], row[j]);
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
return response;
|
|
1663
|
+
}
|
|
1664
|
+
function normalizeValue(type, value) {
|
|
1665
|
+
if (value === null) {
|
|
1666
|
+
return value;
|
|
1667
|
+
}
|
|
1668
|
+
switch (type) {
|
|
1669
|
+
case "bigint":
|
|
1670
|
+
return String(BigInt(value));
|
|
1671
|
+
case "decimal":
|
|
1672
|
+
return String(new Decimal4(value));
|
|
1673
|
+
case "bigint-array":
|
|
1674
|
+
return value.map((v) => normalizeValue("bigint", v));
|
|
1675
|
+
case "decimal-array":
|
|
1676
|
+
return value.map((v) => normalizeValue("decimal", v));
|
|
1677
|
+
default:
|
|
1678
|
+
return value;
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1412
1682
|
// src/transactionManager/TransactionManager.ts
|
|
1413
1683
|
import { Debug } from "@prisma/debug";
|
|
1414
1684
|
|
|
@@ -1684,5 +1954,6 @@ export {
|
|
|
1684
1954
|
isPrismaValuePlaceholder,
|
|
1685
1955
|
noopTracingHelper,
|
|
1686
1956
|
normalizeJsonProtocolValues,
|
|
1957
|
+
normalizeRawJsonProtocolResponse,
|
|
1687
1958
|
safeJsonStringify
|
|
1688
1959
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SqlQueryable, SqlResultSet } from '@prisma/driver-adapter-utils';
|
|
1
|
+
import { ConnectionInfo, SqlQueryable, SqlResultSet } from '@prisma/driver-adapter-utils';
|
|
2
2
|
import { QueryEvent } from '../events';
|
|
3
3
|
import { QueryPlanNode } from '../QueryPlan';
|
|
4
4
|
import { type SchemaProvider } from '../schema';
|
|
@@ -19,16 +19,18 @@ export type QueryInterpreterOptions = {
|
|
|
19
19
|
serializer: (results: SqlResultSet) => Value;
|
|
20
20
|
rawSerializer?: (results: SqlResultSet) => Value;
|
|
21
21
|
provider?: SchemaProvider;
|
|
22
|
+
connectionInfo?: ConnectionInfo;
|
|
22
23
|
};
|
|
23
24
|
export declare class QueryInterpreter {
|
|
24
25
|
#private;
|
|
25
|
-
constructor({ transactionManager, placeholderValues, onQuery, tracingHelper, serializer, rawSerializer, provider, }: QueryInterpreterOptions);
|
|
26
|
+
constructor({ transactionManager, placeholderValues, onQuery, tracingHelper, serializer, rawSerializer, provider, connectionInfo, }: QueryInterpreterOptions);
|
|
26
27
|
static forSql(options: {
|
|
27
28
|
transactionManager: QueryInterpreterTransactionManager;
|
|
28
29
|
placeholderValues: Record<string, unknown>;
|
|
29
30
|
onQuery?: (event: QueryEvent) => void;
|
|
30
31
|
tracingHelper: TracingHelper;
|
|
31
32
|
provider?: SchemaProvider;
|
|
33
|
+
connectionInfo?: ConnectionInfo;
|
|
32
34
|
}): QueryInterpreter;
|
|
33
35
|
run(queryPlan: QueryPlanNode, queryable: SqlQueryable): Promise<unknown>;
|
|
34
36
|
private interpretNode;
|
|
@@ -2,5 +2,5 @@ import { SqlQuery } from '@prisma/driver-adapter-utils';
|
|
|
2
2
|
import type { PrismaValue, QueryPlanDbQuery } from '../QueryPlan';
|
|
3
3
|
import { GeneratorRegistrySnapshot } from './generators';
|
|
4
4
|
import { ScopeBindings } from './scope';
|
|
5
|
-
export declare function renderQuery(dbQuery: QueryPlanDbQuery, scope: ScopeBindings, generators: GeneratorRegistrySnapshot): SqlQuery;
|
|
5
|
+
export declare function renderQuery(dbQuery: QueryPlanDbQuery, scope: ScopeBindings, generators: GeneratorRegistrySnapshot, maxChunkSize?: number): SqlQuery[];
|
|
6
6
|
export declare function evaluateParam(param: PrismaValue, scope: ScopeBindings, generators: GeneratorRegistrySnapshot): unknown;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/client-engine-runtime",
|
|
3
|
-
"version": "6.14.0-dev.
|
|
3
|
+
"version": "6.14.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/
|
|
35
|
-
"@prisma/
|
|
34
|
+
"@prisma/driver-adapter-utils": "6.14.0-dev.21",
|
|
35
|
+
"@prisma/debug": "6.14.0-dev.21"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/jest": "29.5.14",
|