@prisma/client-engine-runtime 7.4.1 → 7.4.2-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/events.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export type QueryEvent = {
2
2
  timestamp: Date;
3
3
  query: string;
4
- params: unknown[];
4
+ params: readonly unknown[];
5
5
  duration: number;
6
6
  };
package/dist/index.d.mts CHANGED
@@ -80,6 +80,10 @@ export declare type DecimalTaggedValue = {
80
80
  value: string;
81
81
  };
82
82
 
83
+ declare type DeepReadonly<T> = T extends undefined | null | boolean | string | number | symbol | Function | Date ? T : T extends Array<infer U> ? ReadonlyArray<DeepReadonly<U>> : unknown extends T ? unknown : {
84
+ readonly [K in keyof T]: DeepReadonly<T[K]>;
85
+ };
86
+
83
87
  export declare function deserializeJsonObject(result: unknown): unknown;
84
88
 
85
89
  /**
@@ -155,6 +159,9 @@ export declare type Fragment = {
155
159
  type: 'parameter';
156
160
  } | {
157
161
  type: 'parameterTuple';
162
+ itemPrefix: string;
163
+ itemSeparator: string;
164
+ itemSuffix: string;
158
165
  } | {
159
166
  type: 'parameterTupleList';
160
167
  itemPrefix: string;
@@ -243,7 +250,7 @@ export declare type PrismaValuePlaceholder = {
243
250
  export declare type QueryEvent = {
244
251
  timestamp: Date;
245
252
  query: string;
246
- params: unknown[];
253
+ params: readonly unknown[];
247
254
  duration: number;
248
255
  };
249
256
 
@@ -256,7 +263,7 @@ export declare class QueryInterpreter {
256
263
  provider?: SchemaProvider;
257
264
  connectionInfo?: ConnectionInfo;
258
265
  }): QueryInterpreter;
259
- run(queryPlan: QueryPlanNode, options: QueryRuntimeOptions): Promise<unknown>;
266
+ run(queryPlan: DeepReadonly<QueryPlanNode>, options: QueryRuntimeOptions): Promise<unknown>;
260
267
  private interpretNode;
261
268
  }
262
269
 
@@ -348,6 +355,7 @@ export declare type QueryPlanNode = {
348
355
  args: {
349
356
  parent: QueryPlanNode;
350
357
  children: JoinExpression[];
358
+ canAssumeStrictEquality: boolean;
351
359
  };
352
360
  } | {
353
361
  type: 'mapField';
@@ -516,14 +524,14 @@ export declare class UserFacingError extends Error {
516
524
  }
517
525
 
518
526
  export declare type ValidationError = {
519
- error_identifier: 'RELATION_VIOLATION';
527
+ errorIdentifier: 'RELATION_VIOLATION';
520
528
  context: {
521
529
  relation: string;
522
530
  modelA: string;
523
531
  modelB: string;
524
532
  };
525
533
  } | {
526
- error_identifier: 'MISSING_RELATED_RECORD';
534
+ errorIdentifier: 'MISSING_RELATED_RECORD';
527
535
  context: {
528
536
  model: string;
529
537
  relation: string;
@@ -532,24 +540,24 @@ export declare type ValidationError = {
532
540
  neededFor?: string;
533
541
  };
534
542
  } | {
535
- error_identifier: 'MISSING_RECORD';
543
+ errorIdentifier: 'MISSING_RECORD';
536
544
  context: {
537
545
  operation: string;
538
546
  };
539
547
  } | {
540
- error_identifier: 'INCOMPLETE_CONNECT_INPUT';
548
+ errorIdentifier: 'INCOMPLETE_CONNECT_INPUT';
541
549
  context: {
542
550
  expectedRows: number;
543
551
  };
544
552
  } | {
545
- error_identifier: 'INCOMPLETE_CONNECT_OUTPUT';
553
+ errorIdentifier: 'INCOMPLETE_CONNECT_OUTPUT';
546
554
  context: {
547
555
  expectedRows: number;
548
556
  relation: string;
549
557
  relationType: string;
550
558
  };
551
559
  } | {
552
- error_identifier: 'RECORDS_NOT_CONNECTED';
560
+ errorIdentifier: 'RECORDS_NOT_CONNECTED';
553
561
  context: {
554
562
  relation: string;
555
563
  parent: string;
package/dist/index.d.ts CHANGED
@@ -80,6 +80,10 @@ export declare type DecimalTaggedValue = {
80
80
  value: string;
81
81
  };
82
82
 
83
+ declare type DeepReadonly<T> = T extends undefined | null | boolean | string | number | symbol | Function | Date ? T : T extends Array<infer U> ? ReadonlyArray<DeepReadonly<U>> : unknown extends T ? unknown : {
84
+ readonly [K in keyof T]: DeepReadonly<T[K]>;
85
+ };
86
+
83
87
  export declare function deserializeJsonObject(result: unknown): unknown;
84
88
 
85
89
  /**
@@ -155,6 +159,9 @@ export declare type Fragment = {
155
159
  type: 'parameter';
156
160
  } | {
157
161
  type: 'parameterTuple';
162
+ itemPrefix: string;
163
+ itemSeparator: string;
164
+ itemSuffix: string;
158
165
  } | {
159
166
  type: 'parameterTupleList';
160
167
  itemPrefix: string;
@@ -243,7 +250,7 @@ export declare type PrismaValuePlaceholder = {
243
250
  export declare type QueryEvent = {
244
251
  timestamp: Date;
245
252
  query: string;
246
- params: unknown[];
253
+ params: readonly unknown[];
247
254
  duration: number;
248
255
  };
249
256
 
@@ -256,7 +263,7 @@ export declare class QueryInterpreter {
256
263
  provider?: SchemaProvider;
257
264
  connectionInfo?: ConnectionInfo;
258
265
  }): QueryInterpreter;
259
- run(queryPlan: QueryPlanNode, options: QueryRuntimeOptions): Promise<unknown>;
266
+ run(queryPlan: DeepReadonly<QueryPlanNode>, options: QueryRuntimeOptions): Promise<unknown>;
260
267
  private interpretNode;
261
268
  }
262
269
 
@@ -348,6 +355,7 @@ export declare type QueryPlanNode = {
348
355
  args: {
349
356
  parent: QueryPlanNode;
350
357
  children: JoinExpression[];
358
+ canAssumeStrictEquality: boolean;
351
359
  };
352
360
  } | {
353
361
  type: 'mapField';
@@ -516,14 +524,14 @@ export declare class UserFacingError extends Error {
516
524
  }
517
525
 
518
526
  export declare type ValidationError = {
519
- error_identifier: 'RELATION_VIOLATION';
527
+ errorIdentifier: 'RELATION_VIOLATION';
520
528
  context: {
521
529
  relation: string;
522
530
  modelA: string;
523
531
  modelB: string;
524
532
  };
525
533
  } | {
526
- error_identifier: 'MISSING_RELATED_RECORD';
534
+ errorIdentifier: 'MISSING_RELATED_RECORD';
527
535
  context: {
528
536
  model: string;
529
537
  relation: string;
@@ -532,24 +540,24 @@ export declare type ValidationError = {
532
540
  neededFor?: string;
533
541
  };
534
542
  } | {
535
- error_identifier: 'MISSING_RECORD';
543
+ errorIdentifier: 'MISSING_RECORD';
536
544
  context: {
537
545
  operation: string;
538
546
  };
539
547
  } | {
540
- error_identifier: 'INCOMPLETE_CONNECT_INPUT';
548
+ errorIdentifier: 'INCOMPLETE_CONNECT_INPUT';
541
549
  context: {
542
550
  expectedRows: number;
543
551
  };
544
552
  } | {
545
- error_identifier: 'INCOMPLETE_CONNECT_OUTPUT';
553
+ errorIdentifier: 'INCOMPLETE_CONNECT_OUTPUT';
546
554
  context: {
547
555
  expectedRows: number;
548
556
  relation: string;
549
557
  relationType: string;
550
558
  };
551
559
  } | {
552
- error_identifier: 'RECORDS_NOT_CONNECTED';
560
+ errorIdentifier: 'RECORDS_NOT_CONNECTED';
553
561
  context: {
554
562
  relation: string;
555
563
  parent: string;
package/dist/index.js CHANGED
@@ -757,6 +757,9 @@ function normalizeDateTime(dt) {
757
757
  return dtWithTz;
758
758
  }
759
759
 
760
+ // src/interpreter/query-interpreter.ts
761
+ var import_klona2 = require("klona");
762
+
760
763
  // src/sql-commenter.ts
761
764
  var import_klona = require("klona");
762
765
  function formatSqlComment(tags) {
@@ -1040,8 +1043,11 @@ function paginateSingleList(list, { cursor, skip, take }) {
1040
1043
  const end = take !== null ? start + take : list.length;
1041
1044
  return list.slice(start, end);
1042
1045
  }
1043
- function getRecordKey(record, fields) {
1044
- return JSON.stringify(fields.map((field) => record[field]));
1046
+ function getRecordKey(record, fields, mappers) {
1047
+ const array = fields.map(
1048
+ (field, index) => mappers?.[index] ? record[field] !== null ? mappers[index](record[field]) : null : record[field]
1049
+ );
1050
+ return JSON.stringify(array);
1045
1051
  }
1046
1052
 
1047
1053
  // src/query-plan.ts
@@ -1136,7 +1142,10 @@ function renderFragment(fragment, placeholderFormat, ctx) {
1136
1142
  case "stringChunk":
1137
1143
  return fragment.chunk;
1138
1144
  case "parameterTuple": {
1139
- const placeholders = fragment.value.length == 0 ? "NULL" : fragment.value.map(() => formatPlaceholder(placeholderFormat, ctx.placeholderNumber++)).join(",");
1145
+ const placeholders = fragment.value.length == 0 ? "NULL" : fragment.value.map(() => {
1146
+ const item = formatPlaceholder(placeholderFormat, ctx.placeholderNumber++);
1147
+ return `${fragment.itemPrefix}${item}${fragment.itemSuffix}`;
1148
+ }).join(fragment.itemSeparator);
1140
1149
  return `(${placeholders})`;
1141
1150
  }
1142
1151
  case "parameterTupleList": {
@@ -1495,7 +1504,7 @@ function doesSatisfyRule(data, rule) {
1495
1504
  }
1496
1505
  }
1497
1506
  function renderMessage(data, error) {
1498
- switch (error.error_identifier) {
1507
+ switch (error.errorIdentifier) {
1499
1508
  case "RELATION_VIOLATION":
1500
1509
  return `The change you are trying to make would violate the required relation '${error.context.relation}' between the \`${error.context.modelA}\` and \`${error.context.modelB}\` models.`;
1501
1510
  case "MISSING_RECORD":
@@ -1515,7 +1524,7 @@ function renderMessage(data, error) {
1515
1524
  }
1516
1525
  }
1517
1526
  function getErrorCode2(error) {
1518
- switch (error.error_identifier) {
1527
+ switch (error.errorIdentifier) {
1519
1528
  case "RELATION_VIOLATION":
1520
1529
  return "P2014";
1521
1530
  case "RECORDS_NOT_CONNECTED":
@@ -1630,7 +1639,7 @@ var QueryInterpreter = class _QueryInterpreter {
1630
1639
  sum += await this.#withQuerySpanAndEvent(
1631
1640
  commentedQuery,
1632
1641
  context.queryable,
1633
- () => context.queryable.executeRaw(commentedQuery).catch(
1642
+ () => context.queryable.executeRaw(cloneObject(commentedQuery)).catch(
1634
1643
  (err) => node.args.type === "rawSql" ? rethrowAsUserFacingRawError(err) : rethrowAsUserFacing(err)
1635
1644
  )
1636
1645
  );
@@ -1645,7 +1654,7 @@ var QueryInterpreter = class _QueryInterpreter {
1645
1654
  const result = await this.#withQuerySpanAndEvent(
1646
1655
  commentedQuery,
1647
1656
  context.queryable,
1648
- () => context.queryable.queryRaw(commentedQuery).catch(
1657
+ () => context.queryable.queryRaw(cloneObject(commentedQuery)).catch(
1649
1658
  (err) => node.args.type === "rawSql" ? rethrowAsUserFacingRawError(err) : rethrowAsUserFacing(err)
1650
1659
  )
1651
1660
  );
@@ -1697,7 +1706,7 @@ var QueryInterpreter = class _QueryInterpreter {
1697
1706
  childRecords: (await this.interpretNode(joinExpr.child, context)).value
1698
1707
  }))
1699
1708
  );
1700
- return { value: attachChildrenToParents(parent, children), lastInsertId };
1709
+ return { value: attachChildrenToParents(parent, children, node.args.canAssumeStrictEquality), lastInsertId };
1701
1710
  }
1702
1711
  case "transaction": {
1703
1712
  if (!context.transactionManager.enabled) {
@@ -1744,8 +1753,9 @@ var QueryInterpreter = class _QueryInterpreter {
1744
1753
  }
1745
1754
  case "process": {
1746
1755
  const { value, lastInsertId } = await this.interpretNode(node.args.expr, context);
1747
- evaluateProcessingParameters(node.args.operations, context.scope, context.generators);
1748
- return { value: processRecords(value, node.args.operations), lastInsertId };
1756
+ const ops = cloneObject(node.args.operations);
1757
+ evaluateProcessingParameters(ops, context.scope, context.generators);
1758
+ return { value: processRecords(value, ops), lastInsertId };
1749
1759
  }
1750
1760
  case "initializeRecord": {
1751
1761
  const { lastInsertId } = await this.interpretNode(node.args.expr, context);
@@ -1838,12 +1848,13 @@ function mapField2(value, field) {
1838
1848
  }
1839
1849
  return value;
1840
1850
  }
1841
- function attachChildrenToParents(parentRecords, children) {
1851
+ function attachChildrenToParents(parentRecords, children, canAssumeStrictEquality) {
1842
1852
  for (const { joinExpr, childRecords } of children) {
1843
1853
  const parentKeys = joinExpr.on.map(([k]) => k);
1844
1854
  const childKeys = joinExpr.on.map(([, k]) => k);
1845
1855
  const parentMap = {};
1846
- for (const parent of Array.isArray(parentRecords) ? parentRecords : [parentRecords]) {
1856
+ const parentArray = Array.isArray(parentRecords) ? parentRecords : [parentRecords];
1857
+ for (const parent of parentArray) {
1847
1858
  const parentRecord = asRecord(parent);
1848
1859
  const key = getRecordKey(parentRecord, parentKeys);
1849
1860
  if (!parentMap[key]) {
@@ -1856,11 +1867,12 @@ function attachChildrenToParents(parentRecords, children) {
1856
1867
  parentRecord[joinExpr.parentField] = [];
1857
1868
  }
1858
1869
  }
1870
+ const mappers = canAssumeStrictEquality ? void 0 : inferKeyCasts(parentArray, parentKeys);
1859
1871
  for (const childRecord of Array.isArray(childRecords) ? childRecords : [childRecords]) {
1860
1872
  if (childRecord === null) {
1861
1873
  continue;
1862
1874
  }
1863
- const key = getRecordKey(asRecord(childRecord), childKeys);
1875
+ const key = getRecordKey(asRecord(childRecord), childKeys, mappers);
1864
1876
  for (const parentRecord of parentMap[key] ?? []) {
1865
1877
  if (joinExpr.isRelationUnique) {
1866
1878
  parentRecord[joinExpr.parentField] = childRecord;
@@ -1872,6 +1884,40 @@ function attachChildrenToParents(parentRecords, children) {
1872
1884
  }
1873
1885
  return parentRecords;
1874
1886
  }
1887
+ function inferKeyCasts(rows, keys) {
1888
+ function getKeyCast(type) {
1889
+ switch (type) {
1890
+ case "number":
1891
+ return Number;
1892
+ case "string":
1893
+ return String;
1894
+ case "boolean":
1895
+ return Boolean;
1896
+ case "bigint":
1897
+ return BigInt;
1898
+ default:
1899
+ return;
1900
+ }
1901
+ }
1902
+ const keyCasts = Array.from({ length: keys.length });
1903
+ let keysFound = 0;
1904
+ for (const parent of rows) {
1905
+ const parentRecord = asRecord(parent);
1906
+ for (const [i, key] of keys.entries()) {
1907
+ if (parentRecord[key] !== null && keyCasts[i] === void 0) {
1908
+ const keyCast = getKeyCast(typeof parentRecord[key]);
1909
+ if (keyCast !== void 0) {
1910
+ keyCasts[i] = keyCast;
1911
+ }
1912
+ keysFound++;
1913
+ }
1914
+ }
1915
+ if (keysFound === keys.length) {
1916
+ break;
1917
+ }
1918
+ }
1919
+ return keyCasts;
1920
+ }
1875
1921
  function evalFieldInitializer(initializer, lastInsertId, scope, generators) {
1876
1922
  switch (initializer.type) {
1877
1923
  case "value":
@@ -1931,6 +1977,9 @@ function evaluateProcessingParameters(ops, scope, generators) {
1931
1977
  evaluateProcessingParameters(nested, scope, generators);
1932
1978
  }
1933
1979
  }
1980
+ function cloneObject(value) {
1981
+ return (0, import_klona2.klona)(value);
1982
+ }
1934
1983
 
1935
1984
  // src/raw-json-protocol.ts
1936
1985
  var import_client_runtime_utils4 = require("@prisma/client-runtime-utils");
package/dist/index.mjs CHANGED
@@ -706,6 +706,9 @@ function normalizeDateTime(dt) {
706
706
  return dtWithTz;
707
707
  }
708
708
 
709
+ // src/interpreter/query-interpreter.ts
710
+ import { klona as klona2 } from "klona";
711
+
709
712
  // src/sql-commenter.ts
710
713
  import { klona } from "klona";
711
714
  function formatSqlComment(tags) {
@@ -989,8 +992,11 @@ function paginateSingleList(list, { cursor, skip, take }) {
989
992
  const end = take !== null ? start + take : list.length;
990
993
  return list.slice(start, end);
991
994
  }
992
- function getRecordKey(record, fields) {
993
- return JSON.stringify(fields.map((field) => record[field]));
995
+ function getRecordKey(record, fields, mappers) {
996
+ const array = fields.map(
997
+ (field, index) => mappers?.[index] ? record[field] !== null ? mappers[index](record[field]) : null : record[field]
998
+ );
999
+ return JSON.stringify(array);
994
1000
  }
995
1001
 
996
1002
  // src/query-plan.ts
@@ -1085,7 +1091,10 @@ function renderFragment(fragment, placeholderFormat, ctx) {
1085
1091
  case "stringChunk":
1086
1092
  return fragment.chunk;
1087
1093
  case "parameterTuple": {
1088
- const placeholders = fragment.value.length == 0 ? "NULL" : fragment.value.map(() => formatPlaceholder(placeholderFormat, ctx.placeholderNumber++)).join(",");
1094
+ const placeholders = fragment.value.length == 0 ? "NULL" : fragment.value.map(() => {
1095
+ const item = formatPlaceholder(placeholderFormat, ctx.placeholderNumber++);
1096
+ return `${fragment.itemPrefix}${item}${fragment.itemSuffix}`;
1097
+ }).join(fragment.itemSeparator);
1089
1098
  return `(${placeholders})`;
1090
1099
  }
1091
1100
  case "parameterTupleList": {
@@ -1444,7 +1453,7 @@ function doesSatisfyRule(data, rule) {
1444
1453
  }
1445
1454
  }
1446
1455
  function renderMessage(data, error) {
1447
- switch (error.error_identifier) {
1456
+ switch (error.errorIdentifier) {
1448
1457
  case "RELATION_VIOLATION":
1449
1458
  return `The change you are trying to make would violate the required relation '${error.context.relation}' between the \`${error.context.modelA}\` and \`${error.context.modelB}\` models.`;
1450
1459
  case "MISSING_RECORD":
@@ -1464,7 +1473,7 @@ function renderMessage(data, error) {
1464
1473
  }
1465
1474
  }
1466
1475
  function getErrorCode2(error) {
1467
- switch (error.error_identifier) {
1476
+ switch (error.errorIdentifier) {
1468
1477
  case "RELATION_VIOLATION":
1469
1478
  return "P2014";
1470
1479
  case "RECORDS_NOT_CONNECTED":
@@ -1579,7 +1588,7 @@ var QueryInterpreter = class _QueryInterpreter {
1579
1588
  sum += await this.#withQuerySpanAndEvent(
1580
1589
  commentedQuery,
1581
1590
  context.queryable,
1582
- () => context.queryable.executeRaw(commentedQuery).catch(
1591
+ () => context.queryable.executeRaw(cloneObject(commentedQuery)).catch(
1583
1592
  (err) => node.args.type === "rawSql" ? rethrowAsUserFacingRawError(err) : rethrowAsUserFacing(err)
1584
1593
  )
1585
1594
  );
@@ -1594,7 +1603,7 @@ var QueryInterpreter = class _QueryInterpreter {
1594
1603
  const result = await this.#withQuerySpanAndEvent(
1595
1604
  commentedQuery,
1596
1605
  context.queryable,
1597
- () => context.queryable.queryRaw(commentedQuery).catch(
1606
+ () => context.queryable.queryRaw(cloneObject(commentedQuery)).catch(
1598
1607
  (err) => node.args.type === "rawSql" ? rethrowAsUserFacingRawError(err) : rethrowAsUserFacing(err)
1599
1608
  )
1600
1609
  );
@@ -1646,7 +1655,7 @@ var QueryInterpreter = class _QueryInterpreter {
1646
1655
  childRecords: (await this.interpretNode(joinExpr.child, context)).value
1647
1656
  }))
1648
1657
  );
1649
- return { value: attachChildrenToParents(parent, children), lastInsertId };
1658
+ return { value: attachChildrenToParents(parent, children, node.args.canAssumeStrictEquality), lastInsertId };
1650
1659
  }
1651
1660
  case "transaction": {
1652
1661
  if (!context.transactionManager.enabled) {
@@ -1693,8 +1702,9 @@ var QueryInterpreter = class _QueryInterpreter {
1693
1702
  }
1694
1703
  case "process": {
1695
1704
  const { value, lastInsertId } = await this.interpretNode(node.args.expr, context);
1696
- evaluateProcessingParameters(node.args.operations, context.scope, context.generators);
1697
- return { value: processRecords(value, node.args.operations), lastInsertId };
1705
+ const ops = cloneObject(node.args.operations);
1706
+ evaluateProcessingParameters(ops, context.scope, context.generators);
1707
+ return { value: processRecords(value, ops), lastInsertId };
1698
1708
  }
1699
1709
  case "initializeRecord": {
1700
1710
  const { lastInsertId } = await this.interpretNode(node.args.expr, context);
@@ -1787,12 +1797,13 @@ function mapField2(value, field) {
1787
1797
  }
1788
1798
  return value;
1789
1799
  }
1790
- function attachChildrenToParents(parentRecords, children) {
1800
+ function attachChildrenToParents(parentRecords, children, canAssumeStrictEquality) {
1791
1801
  for (const { joinExpr, childRecords } of children) {
1792
1802
  const parentKeys = joinExpr.on.map(([k]) => k);
1793
1803
  const childKeys = joinExpr.on.map(([, k]) => k);
1794
1804
  const parentMap = {};
1795
- for (const parent of Array.isArray(parentRecords) ? parentRecords : [parentRecords]) {
1805
+ const parentArray = Array.isArray(parentRecords) ? parentRecords : [parentRecords];
1806
+ for (const parent of parentArray) {
1796
1807
  const parentRecord = asRecord(parent);
1797
1808
  const key = getRecordKey(parentRecord, parentKeys);
1798
1809
  if (!parentMap[key]) {
@@ -1805,11 +1816,12 @@ function attachChildrenToParents(parentRecords, children) {
1805
1816
  parentRecord[joinExpr.parentField] = [];
1806
1817
  }
1807
1818
  }
1819
+ const mappers = canAssumeStrictEquality ? void 0 : inferKeyCasts(parentArray, parentKeys);
1808
1820
  for (const childRecord of Array.isArray(childRecords) ? childRecords : [childRecords]) {
1809
1821
  if (childRecord === null) {
1810
1822
  continue;
1811
1823
  }
1812
- const key = getRecordKey(asRecord(childRecord), childKeys);
1824
+ const key = getRecordKey(asRecord(childRecord), childKeys, mappers);
1813
1825
  for (const parentRecord of parentMap[key] ?? []) {
1814
1826
  if (joinExpr.isRelationUnique) {
1815
1827
  parentRecord[joinExpr.parentField] = childRecord;
@@ -1821,6 +1833,40 @@ function attachChildrenToParents(parentRecords, children) {
1821
1833
  }
1822
1834
  return parentRecords;
1823
1835
  }
1836
+ function inferKeyCasts(rows, keys) {
1837
+ function getKeyCast(type) {
1838
+ switch (type) {
1839
+ case "number":
1840
+ return Number;
1841
+ case "string":
1842
+ return String;
1843
+ case "boolean":
1844
+ return Boolean;
1845
+ case "bigint":
1846
+ return BigInt;
1847
+ default:
1848
+ return;
1849
+ }
1850
+ }
1851
+ const keyCasts = Array.from({ length: keys.length });
1852
+ let keysFound = 0;
1853
+ for (const parent of rows) {
1854
+ const parentRecord = asRecord(parent);
1855
+ for (const [i, key] of keys.entries()) {
1856
+ if (parentRecord[key] !== null && keyCasts[i] === void 0) {
1857
+ const keyCast = getKeyCast(typeof parentRecord[key]);
1858
+ if (keyCast !== void 0) {
1859
+ keyCasts[i] = keyCast;
1860
+ }
1861
+ keysFound++;
1862
+ }
1863
+ }
1864
+ if (keysFound === keys.length) {
1865
+ break;
1866
+ }
1867
+ }
1868
+ return keyCasts;
1869
+ }
1824
1870
  function evalFieldInitializer(initializer, lastInsertId, scope, generators) {
1825
1871
  switch (initializer.type) {
1826
1872
  case "value":
@@ -1880,6 +1926,9 @@ function evaluateProcessingParameters(ops, scope, generators) {
1880
1926
  evaluateProcessingParameters(nested, scope, generators);
1881
1927
  }
1882
1928
  }
1929
+ function cloneObject(value) {
1930
+ return klona2(value);
1931
+ }
1883
1932
 
1884
1933
  // src/raw-json-protocol.ts
1885
1934
  import { Decimal as Decimal4 } from "@prisma/client-runtime-utils";
@@ -1,3 +1,3 @@
1
1
  import { InMemoryOps } from '../query-plan';
2
2
  export declare function processRecords(value: unknown, ops: InMemoryOps): unknown;
3
- export declare function getRecordKey(record: {}, fields: string[]): string;
3
+ export declare function getRecordKey(record: {}, fields: readonly string[], mappers?: ((value: unknown) => unknown)[]): string;
@@ -5,6 +5,7 @@ import { QueryPlanNode } from '../query-plan';
5
5
  import { type SchemaProvider } from '../schema';
6
6
  import { type TracingHelper } from '../tracing';
7
7
  import { type TransactionManager } from '../transaction-manager/transaction-manager';
8
+ import { DeepReadonly } from '../utils';
8
9
  import { Value } from './scope';
9
10
  export type QueryInterpreterTransactionManager = {
10
11
  enabled: true;
@@ -39,6 +40,6 @@ export declare class QueryInterpreter {
39
40
  provider?: SchemaProvider;
40
41
  connectionInfo?: ConnectionInfo;
41
42
  }): QueryInterpreter;
42
- run(queryPlan: QueryPlanNode, options: QueryRuntimeOptions): Promise<unknown>;
43
+ run(queryPlan: DeepReadonly<QueryPlanNode>, options: QueryRuntimeOptions): Promise<unknown>;
43
44
  private interpretNode;
44
45
  }
@@ -1,6 +1,7 @@
1
1
  import { SqlQuery } from '@prisma/driver-adapter-utils';
2
2
  import { type QueryPlanDbQuery } from '../query-plan';
3
+ import { DeepReadonly } from '../utils';
3
4
  import { GeneratorRegistrySnapshot } from './generators';
4
5
  import { ScopeBindings } from './scope';
5
- export declare function renderQuery(dbQuery: QueryPlanDbQuery, scope: ScopeBindings, generators: GeneratorRegistrySnapshot, maxChunkSize?: number): SqlQuery[];
6
+ export declare function renderQuery(dbQuery: DeepReadonly<QueryPlanDbQuery>, scope: ScopeBindings, generators: GeneratorRegistrySnapshot, maxChunkSize?: number): DeepReadonly<SqlQuery>[];
6
7
  export declare function evaluateArg(arg: unknown, scope: ScopeBindings, generators: GeneratorRegistrySnapshot): unknown;
@@ -1,3 +1,4 @@
1
1
  import { DataRule, ValidationError } from '../query-plan';
2
- export declare function performValidation(data: unknown, rules: DataRule[], error: ValidationError): void;
2
+ import { DeepReadonly } from '../utils';
3
+ export declare function performValidation(data: unknown, rules: DeepReadonly<DataRule[]>, error: ValidationError): void;
3
4
  export declare function doesSatisfyRule(data: unknown, rule: DataRule): boolean;
@@ -56,6 +56,9 @@ export type Fragment = {
56
56
  type: 'parameter';
57
57
  } | {
58
58
  type: 'parameterTuple';
59
+ itemPrefix: string;
60
+ itemSeparator: string;
61
+ itemSuffix: string;
59
62
  } | {
60
63
  type: 'parameterTupleList';
61
64
  itemPrefix: string;
@@ -121,6 +124,7 @@ export type QueryPlanNode = {
121
124
  args: {
122
125
  parent: QueryPlanNode;
123
126
  children: JoinExpression[];
127
+ canAssumeStrictEquality: boolean;
124
128
  };
125
129
  } | {
126
130
  type: 'mapField';
@@ -227,14 +231,14 @@ export type DataRule = {
227
231
  type: 'never';
228
232
  };
229
233
  export type ValidationError = {
230
- error_identifier: 'RELATION_VIOLATION';
234
+ errorIdentifier: 'RELATION_VIOLATION';
231
235
  context: {
232
236
  relation: string;
233
237
  modelA: string;
234
238
  modelB: string;
235
239
  };
236
240
  } | {
237
- error_identifier: 'MISSING_RELATED_RECORD';
241
+ errorIdentifier: 'MISSING_RELATED_RECORD';
238
242
  context: {
239
243
  model: string;
240
244
  relation: string;
@@ -243,24 +247,24 @@ export type ValidationError = {
243
247
  neededFor?: string;
244
248
  };
245
249
  } | {
246
- error_identifier: 'MISSING_RECORD';
250
+ errorIdentifier: 'MISSING_RECORD';
247
251
  context: {
248
252
  operation: string;
249
253
  };
250
254
  } | {
251
- error_identifier: 'INCOMPLETE_CONNECT_INPUT';
255
+ errorIdentifier: 'INCOMPLETE_CONNECT_INPUT';
252
256
  context: {
253
257
  expectedRows: number;
254
258
  };
255
259
  } | {
256
- error_identifier: 'INCOMPLETE_CONNECT_OUTPUT';
260
+ errorIdentifier: 'INCOMPLETE_CONNECT_OUTPUT';
257
261
  context: {
258
262
  expectedRows: number;
259
263
  relation: string;
260
264
  relationType: string;
261
265
  };
262
266
  } | {
263
- error_identifier: 'RECORDS_NOT_CONNECTED';
267
+ errorIdentifier: 'RECORDS_NOT_CONNECTED';
264
268
  context: {
265
269
  relation: string;
266
270
  parent: string;
package/dist/tracing.d.ts CHANGED
@@ -2,6 +2,7 @@ import { type Context, type Span, type SpanOptions } from '@opentelemetry/api';
2
2
  import type { SqlQuery } from '@prisma/driver-adapter-utils';
3
3
  import { QueryEvent } from './events';
4
4
  import type { SchemaProvider } from './schema';
5
+ import { DeepReadonly } from './utils';
5
6
  export type SpanCallback<R> = (span?: Span, context?: Context) => R;
6
7
  export type ExtendedSpanOptions = SpanOptions & {
7
8
  name: string;
@@ -13,7 +14,7 @@ export interface TracingHelper {
13
14
  export declare const noopTracingHelper: TracingHelper;
14
15
  export declare function providerToOtelSystem(provider: SchemaProvider): string;
15
16
  export declare function withQuerySpanAndEvent<T>({ query, tracingHelper, provider, onQuery, execute, }: {
16
- query: SqlQuery;
17
+ query: DeepReadonly<SqlQuery>;
17
18
  tracingHelper: TracingHelper;
18
19
  provider: SchemaProvider;
19
20
  onQuery?: (event: QueryEvent) => void;
package/dist/utils.d.ts CHANGED
@@ -1,3 +1,9 @@
1
+ export type DeepReadonly<T> = T extends undefined | null | boolean | string | number | symbol | Function | Date ? T : T extends Array<infer U> ? ReadonlyArray<DeepReadonly<U>> : unknown extends T ? unknown : {
2
+ readonly [K in keyof T]: DeepReadonly<T[K]>;
3
+ };
4
+ export type DeepUnreadonly<T> = T extends undefined | null | boolean | string | number | symbol | Function | Date ? T : T extends ReadonlyArray<infer U> ? Array<DeepUnreadonly<U>> : unknown extends T ? unknown : {
5
+ -readonly [K in keyof T]: DeepUnreadonly<T[K]>;
6
+ };
1
7
  export declare function assertNever(_: never, message: string): never;
2
8
  /**
3
9
  * Checks if two objects are deeply equal, recursively checking all properties for strict equality.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma/client-engine-runtime",
3
- "version": "7.4.1",
3
+ "version": "7.4.2-dev.1",
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,10 +31,10 @@
31
31
  "nanoid": "5.1.5",
32
32
  "ulid": "3.0.0",
33
33
  "uuid": "11.1.0",
34
- "@prisma/debug": "7.4.1",
35
- "@prisma/sqlcommenter": "7.4.1",
36
- "@prisma/driver-adapter-utils": "7.4.1",
37
- "@prisma/client-runtime-utils": "7.4.1"
34
+ "@prisma/client-runtime-utils": "7.4.2-dev.1",
35
+ "@prisma/debug": "7.4.2-dev.1",
36
+ "@prisma/driver-adapter-utils": "7.4.2-dev.1",
37
+ "@prisma/sqlcommenter": "7.4.2-dev.1"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@codspeed/benchmark.js-plugin": "4.0.0",