@prisma/client-engine-runtime 6.9.0-dev.20 → 6.9.0-dev.22

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 CHANGED
@@ -1,7 +1,7 @@
1
- import type { Context } from '@opentelemetry/api';
1
+ import { Context } from '@opentelemetry/api';
2
2
  import type { IsolationLevel } from '@prisma/driver-adapter-utils';
3
- import type { Span } from '@opentelemetry/api';
4
- import type { SpanOptions } from '@opentelemetry/api';
3
+ import { Span } from '@opentelemetry/api';
4
+ import { SpanOptions } from '@opentelemetry/api';
5
5
  import { SqlDriverAdapter } from '@prisma/driver-adapter-utils';
6
6
  import { SqlQueryable } from '@prisma/driver-adapter-utils';
7
7
  import { SqlResultSet } from '@prisma/driver-adapter-utils';
@@ -142,7 +142,7 @@ export declare type QueryEvent = {
142
142
 
143
143
  export declare class QueryInterpreter {
144
144
  #private;
145
- constructor({ transactionManager, placeholderValues, onQuery, tracingHelper, serializer }: QueryInterpreterOptions);
145
+ constructor({ transactionManager, placeholderValues, onQuery, tracingHelper, serializer, rawSerializer, }: QueryInterpreterOptions);
146
146
  static forSql(options: {
147
147
  transactionManager: QueryInterpreterTransactionManager;
148
148
  placeholderValues: Record<string, unknown>;
@@ -159,6 +159,7 @@ export declare type QueryInterpreterOptions = {
159
159
  onQuery?: (event: QueryEvent) => void;
160
160
  tracingHelper: TracingHelper;
161
161
  serializer: (results: SqlResultSet) => Value;
162
+ rawSerializer?: (results: SqlResultSet) => Value;
162
163
  };
163
164
 
164
165
  export declare type QueryInterpreterTransactionManager = {
@@ -291,6 +292,12 @@ export declare type ResultNode = {
291
292
  resultType: PrismaValueType;
292
293
  };
293
294
 
295
+ /**
296
+ * `JSON.stringify` wrapper with custom replacer function that handles nested
297
+ * BigInt and Uint8Array values.
298
+ */
299
+ export declare function safeJsonStringify(obj: unknown): string;
300
+
294
301
  declare type SpanCallback<R> = (span?: Span, context?: Context) => R;
295
302
 
296
303
  export declare interface TracingHelper {
@@ -308,10 +315,11 @@ export declare class TransactionManager {
308
315
  private readonly driverAdapter;
309
316
  private readonly transactionOptions;
310
317
  private readonly tracingHelper;
311
- constructor({ driverAdapter, transactionOptions, tracingHelper, }: {
318
+ constructor({ driverAdapter, transactionOptions, tracingHelper, onQuery, }: {
312
319
  driverAdapter: SqlDriverAdapter;
313
320
  transactionOptions: TransactionOptions;
314
321
  tracingHelper: TracingHelper;
322
+ onQuery?: (event: QueryEvent) => void;
315
323
  });
316
324
  startTransaction(options?: TransactionOptions): Promise<TransactionInfo>;
317
325
  commitTransaction(transactionId: string): Promise<void>;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import type { Context } from '@opentelemetry/api';
1
+ import { Context } from '@opentelemetry/api';
2
2
  import type { IsolationLevel } from '@prisma/driver-adapter-utils';
3
- import type { Span } from '@opentelemetry/api';
4
- import type { SpanOptions } from '@opentelemetry/api';
3
+ import { Span } from '@opentelemetry/api';
4
+ import { SpanOptions } from '@opentelemetry/api';
5
5
  import { SqlDriverAdapter } from '@prisma/driver-adapter-utils';
6
6
  import { SqlQueryable } from '@prisma/driver-adapter-utils';
7
7
  import { SqlResultSet } from '@prisma/driver-adapter-utils';
@@ -142,7 +142,7 @@ export declare type QueryEvent = {
142
142
 
143
143
  export declare class QueryInterpreter {
144
144
  #private;
145
- constructor({ transactionManager, placeholderValues, onQuery, tracingHelper, serializer }: QueryInterpreterOptions);
145
+ constructor({ transactionManager, placeholderValues, onQuery, tracingHelper, serializer, rawSerializer, }: QueryInterpreterOptions);
146
146
  static forSql(options: {
147
147
  transactionManager: QueryInterpreterTransactionManager;
148
148
  placeholderValues: Record<string, unknown>;
@@ -159,6 +159,7 @@ export declare type QueryInterpreterOptions = {
159
159
  onQuery?: (event: QueryEvent) => void;
160
160
  tracingHelper: TracingHelper;
161
161
  serializer: (results: SqlResultSet) => Value;
162
+ rawSerializer?: (results: SqlResultSet) => Value;
162
163
  };
163
164
 
164
165
  export declare type QueryInterpreterTransactionManager = {
@@ -291,6 +292,12 @@ export declare type ResultNode = {
291
292
  resultType: PrismaValueType;
292
293
  };
293
294
 
295
+ /**
296
+ * `JSON.stringify` wrapper with custom replacer function that handles nested
297
+ * BigInt and Uint8Array values.
298
+ */
299
+ export declare function safeJsonStringify(obj: unknown): string;
300
+
294
301
  declare type SpanCallback<R> = (span?: Span, context?: Context) => R;
295
302
 
296
303
  export declare interface TracingHelper {
@@ -308,10 +315,11 @@ export declare class TransactionManager {
308
315
  private readonly driverAdapter;
309
316
  private readonly transactionOptions;
310
317
  private readonly tracingHelper;
311
- constructor({ driverAdapter, transactionOptions, tracingHelper, }: {
318
+ constructor({ driverAdapter, transactionOptions, tracingHelper, onQuery, }: {
312
319
  driverAdapter: SqlDriverAdapter;
313
320
  transactionOptions: TransactionOptions;
314
321
  tracingHelper: TracingHelper;
322
+ onQuery?: (event: QueryEvent) => void;
315
323
  });
316
324
  startTransaction(options?: TransactionOptions): Promise<TransactionInfo>;
317
325
  commitTransaction(transactionId: string): Promise<void>;
package/dist/index.js CHANGED
@@ -41,7 +41,8 @@ __export(index_exports, {
41
41
  isPrismaValueBytes: () => isPrismaValueBytes,
42
42
  isPrismaValueGenerator: () => isPrismaValueGenerator,
43
43
  isPrismaValuePlaceholder: () => isPrismaValuePlaceholder,
44
- noopTracingHelper: () => noopTracingHelper
44
+ noopTracingHelper: () => noopTracingHelper,
45
+ safeJsonStringify: () => safeJsonStringify
45
46
  });
46
47
  module.exports = __toCommonJS(index_exports);
47
48
 
@@ -75,6 +76,16 @@ function doKeysMatch(lhs, rhs) {
75
76
  return isDeepStrictEqual(lhs[key], rhs[key]);
76
77
  });
77
78
  }
79
+ function safeJsonStringify(obj) {
80
+ return JSON.stringify(obj, (_key, val) => {
81
+ if (typeof val === "bigint") {
82
+ return val.toString();
83
+ } else if (val instanceof Uint8Array) {
84
+ return Buffer.from(val).toString("base64");
85
+ }
86
+ return val;
87
+ });
88
+ }
78
89
 
79
90
  // src/interpreter/DataMapper.ts
80
91
  var DataMapperError = class extends Error {
@@ -184,10 +195,8 @@ function mapValue(value, resultType) {
184
195
  }
185
196
  }
186
197
 
187
- // src/interpreter/QueryInterpreter.ts
188
- var import_api = require("@opentelemetry/api");
189
-
190
198
  // src/tracing.ts
199
+ var import_api = require("@opentelemetry/api");
191
200
  var noopTracingHelper = {
192
201
  runInChildSpan(_, callback) {
193
202
  return callback();
@@ -205,6 +214,37 @@ function providerToOtelSystem(provider) {
205
214
  assertNever(provider, `Unknown provider: ${provider}`);
206
215
  }
207
216
  }
217
+ async function withQuerySpanAndEvent({
218
+ query,
219
+ queryable,
220
+ tracingHelper,
221
+ onQuery,
222
+ execute
223
+ }) {
224
+ return await tracingHelper.runInChildSpan(
225
+ {
226
+ name: "db_query",
227
+ kind: import_api.SpanKind.CLIENT,
228
+ attributes: {
229
+ "db.query.text": query.sql,
230
+ "db.system.name": providerToOtelSystem(queryable.provider)
231
+ }
232
+ },
233
+ async () => {
234
+ const timestamp = /* @__PURE__ */ new Date();
235
+ const startInstant = performance.now();
236
+ const result = await execute();
237
+ const endInstant = performance.now();
238
+ onQuery?.({
239
+ timestamp,
240
+ duration: endInstant - startInstant,
241
+ query: query.sql,
242
+ params: query.args
243
+ });
244
+ return result;
245
+ }
246
+ );
247
+ }
208
248
 
209
249
  // src/UserFacingError.ts
210
250
  var import_driver_adapter_utils = require("@prisma/driver-adapter-utils");
@@ -595,6 +635,7 @@ function doesRequireEvaluation(param) {
595
635
  }
596
636
 
597
637
  // src/interpreter/serializeSql.ts
638
+ var import_driver_adapter_utils2 = require("@prisma/driver-adapter-utils");
598
639
  function serializeSql(resultSet) {
599
640
  return resultSet.rows.map(
600
641
  (row) => row.reduce((acc, value, index) => {
@@ -615,6 +656,85 @@ function serializeSql(resultSet) {
615
656
  }, {})
616
657
  );
617
658
  }
659
+ function serializeRawSql(resultSet) {
660
+ return {
661
+ columns: resultSet.columnNames,
662
+ types: resultSet.columnTypes.map((type) => serializeColumnType(type)),
663
+ rows: resultSet.rows
664
+ };
665
+ }
666
+ function serializeColumnType(columnType) {
667
+ switch (columnType) {
668
+ case import_driver_adapter_utils2.ColumnTypeEnum.Int32:
669
+ return "int";
670
+ case import_driver_adapter_utils2.ColumnTypeEnum.Int64:
671
+ return "bigint";
672
+ case import_driver_adapter_utils2.ColumnTypeEnum.Float:
673
+ return "float";
674
+ case import_driver_adapter_utils2.ColumnTypeEnum.Double:
675
+ return "double";
676
+ case import_driver_adapter_utils2.ColumnTypeEnum.Text:
677
+ return "string";
678
+ case import_driver_adapter_utils2.ColumnTypeEnum.Enum:
679
+ return "enum";
680
+ case import_driver_adapter_utils2.ColumnTypeEnum.Bytes:
681
+ return "bytes";
682
+ case import_driver_adapter_utils2.ColumnTypeEnum.Boolean:
683
+ return "bool";
684
+ case import_driver_adapter_utils2.ColumnTypeEnum.Character:
685
+ return "char";
686
+ case import_driver_adapter_utils2.ColumnTypeEnum.Numeric:
687
+ return "decimal";
688
+ case import_driver_adapter_utils2.ColumnTypeEnum.Json:
689
+ return "json";
690
+ case import_driver_adapter_utils2.ColumnTypeEnum.Uuid:
691
+ return "uuid";
692
+ case import_driver_adapter_utils2.ColumnTypeEnum.DateTime:
693
+ return "datetime";
694
+ case import_driver_adapter_utils2.ColumnTypeEnum.Date:
695
+ return "date";
696
+ case import_driver_adapter_utils2.ColumnTypeEnum.Time:
697
+ return "time";
698
+ case import_driver_adapter_utils2.ColumnTypeEnum.Int32Array:
699
+ return "int-array";
700
+ case import_driver_adapter_utils2.ColumnTypeEnum.Int64Array:
701
+ return "bigint-array";
702
+ case import_driver_adapter_utils2.ColumnTypeEnum.FloatArray:
703
+ return "float-array";
704
+ case import_driver_adapter_utils2.ColumnTypeEnum.DoubleArray:
705
+ return "double-array";
706
+ case import_driver_adapter_utils2.ColumnTypeEnum.TextArray:
707
+ return "string-array";
708
+ case import_driver_adapter_utils2.ColumnTypeEnum.EnumArray:
709
+ return "string-array";
710
+ case import_driver_adapter_utils2.ColumnTypeEnum.BytesArray:
711
+ return "bytes-array";
712
+ case import_driver_adapter_utils2.ColumnTypeEnum.BooleanArray:
713
+ return "bool-array";
714
+ case import_driver_adapter_utils2.ColumnTypeEnum.CharacterArray:
715
+ return "char-array";
716
+ case import_driver_adapter_utils2.ColumnTypeEnum.NumericArray:
717
+ return "decimal-array";
718
+ case import_driver_adapter_utils2.ColumnTypeEnum.JsonArray:
719
+ return "json-array";
720
+ case import_driver_adapter_utils2.ColumnTypeEnum.UuidArray:
721
+ return "uuid-array";
722
+ case import_driver_adapter_utils2.ColumnTypeEnum.DateTimeArray:
723
+ return "datetime-array";
724
+ case import_driver_adapter_utils2.ColumnTypeEnum.DateArray:
725
+ return "date-array";
726
+ case import_driver_adapter_utils2.ColumnTypeEnum.TimeArray:
727
+ return "time-array";
728
+ case import_driver_adapter_utils2.ColumnTypeEnum.UnknownNumber:
729
+ return "unknown";
730
+ /// The following PlanetScale type IDs are mapped into Set:
731
+ /// - SET (SET) -> e.g. `"foo,bar"` (String-encoded, comma-separated)
732
+ case import_driver_adapter_utils2.ColumnTypeEnum.Set:
733
+ return "string";
734
+ default:
735
+ assertNever(columnType, `Unexpected column type: ${columnType}`);
736
+ }
737
+ }
618
738
 
619
739
  // src/interpreter/validation.ts
620
740
  function performValidation(data, rules, error) {
@@ -695,12 +815,21 @@ var QueryInterpreter = class _QueryInterpreter {
695
815
  #generators = new GeneratorRegistry();
696
816
  #tracingHelper;
697
817
  #serializer;
698
- constructor({ transactionManager, placeholderValues, onQuery, tracingHelper, serializer }) {
818
+ #rawSerializer;
819
+ constructor({
820
+ transactionManager,
821
+ placeholderValues,
822
+ onQuery,
823
+ tracingHelper,
824
+ serializer,
825
+ rawSerializer
826
+ }) {
699
827
  this.#transactionManager = transactionManager;
700
828
  this.#placeholderValues = placeholderValues;
701
829
  this.#onQuery = onQuery;
702
830
  this.#tracingHelper = tracingHelper;
703
831
  this.#serializer = serializer;
832
+ this.#rawSerializer = rawSerializer ?? serializer;
704
833
  }
705
834
  static forSql(options) {
706
835
  return new _QueryInterpreter({
@@ -708,7 +837,8 @@ var QueryInterpreter = class _QueryInterpreter {
708
837
  placeholderValues: options.placeholderValues,
709
838
  onQuery: options.onQuery,
710
839
  tracingHelper: options.tracingHelper,
711
- serializer: serializeSql
840
+ serializer: serializeSql,
841
+ rawSerializer: serializeRawSql
712
842
  });
713
843
  }
714
844
  async run(queryPlan, queryable) {
@@ -754,14 +884,18 @@ var QueryInterpreter = class _QueryInterpreter {
754
884
  }
755
885
  case "execute": {
756
886
  const query = renderQuery(node.args, scope, generators);
757
- return this.#withQueryEvent(query, queryable, async () => {
887
+ return this.#withQuerySpanAndEvent(query, queryable, async () => {
758
888
  return await queryable.executeRaw(query);
759
889
  });
760
890
  }
761
891
  case "query": {
762
892
  const query = renderQuery(node.args, scope, generators);
763
- return this.#withQueryEvent(query, queryable, async () => {
764
- return this.#serializer(await queryable.queryRaw(query));
893
+ return this.#withQuerySpanAndEvent(query, queryable, async () => {
894
+ if (node.args.type === "rawSql") {
895
+ return this.#rawSerializer(await queryable.queryRaw(query));
896
+ } else {
897
+ return this.#serializer(await queryable.queryRaw(query));
898
+ }
765
899
  });
766
900
  }
767
901
  case "reverse": {
@@ -886,30 +1020,14 @@ var QueryInterpreter = class _QueryInterpreter {
886
1020
  assertNever(node, `Unexpected node type: ${node.type}`);
887
1021
  }
888
1022
  }
889
- #withQueryEvent(query, queryable, execute) {
890
- return this.#tracingHelper.runInChildSpan(
891
- {
892
- name: "db_query",
893
- kind: import_api.SpanKind.CLIENT,
894
- attributes: {
895
- "db.query.text": query.sql,
896
- "db.system.name": providerToOtelSystem(queryable.provider)
897
- }
898
- },
899
- async () => {
900
- const timestamp = /* @__PURE__ */ new Date();
901
- const startInstant = performance.now();
902
- const result = await execute();
903
- const endInstant = performance.now();
904
- this.#onQuery?.({
905
- timestamp,
906
- duration: endInstant - startInstant,
907
- query: query.sql,
908
- params: query.args
909
- });
910
- return result;
911
- }
912
- );
1023
+ #withQuerySpanAndEvent(query, queryable, execute) {
1024
+ return withQuerySpanAndEvent({
1025
+ query,
1026
+ queryable,
1027
+ execute,
1028
+ tracingHelper: this.#tracingHelper,
1029
+ onQuery: this.#onQuery
1030
+ });
913
1031
  }
914
1032
  };
915
1033
  function isEmpty(value) {
@@ -1052,6 +1170,16 @@ var MAX_CLOSED_TRANSACTIONS = 100;
1052
1170
  var debug = (0, import_debug.Debug)("prisma:client:transactionManager");
1053
1171
  var COMMIT_QUERY = () => ({ sql: "COMMIT", args: [], argTypes: [] });
1054
1172
  var ROLLBACK_QUERY = () => ({ sql: "ROLLBACK", args: [], argTypes: [] });
1173
+ var PHANTOM_COMMIT_QUERY = () => ({
1174
+ sql: '-- Implicit "COMMIT" query via underlying driver',
1175
+ args: [],
1176
+ argTypes: []
1177
+ });
1178
+ var PHANTOM_ROLLBACK_QUERY = () => ({
1179
+ sql: '-- Implicit "ROLLBACK" query via underlying driver',
1180
+ args: [],
1181
+ argTypes: []
1182
+ });
1055
1183
  var TransactionManager = class {
1056
1184
  // The map of active transactions.
1057
1185
  transactions = /* @__PURE__ */ new Map();
@@ -1061,14 +1189,17 @@ var TransactionManager = class {
1061
1189
  driverAdapter;
1062
1190
  transactionOptions;
1063
1191
  tracingHelper;
1192
+ #onQuery;
1064
1193
  constructor({
1065
1194
  driverAdapter,
1066
1195
  transactionOptions,
1067
- tracingHelper
1196
+ tracingHelper,
1197
+ onQuery
1068
1198
  }) {
1069
1199
  this.driverAdapter = driverAdapter;
1070
1200
  this.transactionOptions = transactionOptions;
1071
1201
  this.tracingHelper = tracingHelper;
1202
+ this.#onQuery = onQuery;
1072
1203
  }
1073
1204
  async startTransaction(options) {
1074
1205
  return await this.tracingHelper.runInChildSpan("start_transaction", () => this.#startTransactionImpl(options));
@@ -1172,14 +1303,20 @@ var TransactionManager = class {
1172
1303
  debug("Closing transaction.", { transactionId: tx.id, status });
1173
1304
  tx.status = status;
1174
1305
  if (tx.transaction && status === "committed") {
1175
- await tx.transaction.commit();
1176
- if (!tx.transaction.options.usePhantomQuery) {
1177
- await tx.transaction.executeRaw(COMMIT_QUERY());
1306
+ if (tx.transaction.options.usePhantomQuery) {
1307
+ await this.#withQuerySpanAndEvent(PHANTOM_COMMIT_QUERY(), tx.transaction, () => tx.transaction.commit());
1308
+ } else {
1309
+ await tx.transaction.commit();
1310
+ const query = COMMIT_QUERY();
1311
+ await this.#withQuerySpanAndEvent(query, tx.transaction, () => tx.transaction.executeRaw(query));
1178
1312
  }
1179
1313
  } else if (tx.transaction) {
1180
- await tx.transaction.rollback();
1181
- if (!tx.transaction.options.usePhantomQuery) {
1182
- await tx.transaction.executeRaw(ROLLBACK_QUERY());
1314
+ if (tx.transaction.options.usePhantomQuery) {
1315
+ await this.#withQuerySpanAndEvent(PHANTOM_ROLLBACK_QUERY(), tx.transaction, () => tx.transaction.rollback());
1316
+ } else {
1317
+ await tx.transaction.rollback();
1318
+ const query = ROLLBACK_QUERY();
1319
+ await this.#withQuerySpanAndEvent(query, tx.transaction, () => tx.transaction.executeRaw(query));
1183
1320
  }
1184
1321
  }
1185
1322
  clearTimeout(tx.timer);
@@ -1200,6 +1337,15 @@ var TransactionManager = class {
1200
1337
  maxWait: options.maxWait
1201
1338
  };
1202
1339
  }
1340
+ #withQuerySpanAndEvent(query, queryable, execute) {
1341
+ return withQuerySpanAndEvent({
1342
+ query,
1343
+ queryable,
1344
+ execute,
1345
+ tracingHelper: this.tracingHelper,
1346
+ onQuery: this.#onQuery
1347
+ });
1348
+ }
1203
1349
  };
1204
1350
  // Annotate the CommonJS export names for ESM import in node:
1205
1351
  0 && (module.exports = {
@@ -1214,5 +1360,6 @@ var TransactionManager = class {
1214
1360
  isPrismaValueBytes,
1215
1361
  isPrismaValueGenerator,
1216
1362
  isPrismaValuePlaceholder,
1217
- noopTracingHelper
1363
+ noopTracingHelper,
1364
+ safeJsonStringify
1218
1365
  });
package/dist/index.mjs CHANGED
@@ -28,6 +28,16 @@ function doKeysMatch(lhs, rhs) {
28
28
  return isDeepStrictEqual(lhs[key], rhs[key]);
29
29
  });
30
30
  }
31
+ function safeJsonStringify(obj) {
32
+ return JSON.stringify(obj, (_key, val) => {
33
+ if (typeof val === "bigint") {
34
+ return val.toString();
35
+ } else if (val instanceof Uint8Array) {
36
+ return Buffer.from(val).toString("base64");
37
+ }
38
+ return val;
39
+ });
40
+ }
31
41
 
32
42
  // src/interpreter/DataMapper.ts
33
43
  var DataMapperError = class extends Error {
@@ -137,10 +147,8 @@ function mapValue(value, resultType) {
137
147
  }
138
148
  }
139
149
 
140
- // src/interpreter/QueryInterpreter.ts
141
- import { SpanKind } from "@opentelemetry/api";
142
-
143
150
  // src/tracing.ts
151
+ import { SpanKind } from "@opentelemetry/api";
144
152
  var noopTracingHelper = {
145
153
  runInChildSpan(_, callback) {
146
154
  return callback();
@@ -158,6 +166,37 @@ function providerToOtelSystem(provider) {
158
166
  assertNever(provider, `Unknown provider: ${provider}`);
159
167
  }
160
168
  }
169
+ async function withQuerySpanAndEvent({
170
+ query,
171
+ queryable,
172
+ tracingHelper,
173
+ onQuery,
174
+ execute
175
+ }) {
176
+ return await tracingHelper.runInChildSpan(
177
+ {
178
+ name: "db_query",
179
+ kind: SpanKind.CLIENT,
180
+ attributes: {
181
+ "db.query.text": query.sql,
182
+ "db.system.name": providerToOtelSystem(queryable.provider)
183
+ }
184
+ },
185
+ async () => {
186
+ const timestamp = /* @__PURE__ */ new Date();
187
+ const startInstant = performance.now();
188
+ const result = await execute();
189
+ const endInstant = performance.now();
190
+ onQuery?.({
191
+ timestamp,
192
+ duration: endInstant - startInstant,
193
+ query: query.sql,
194
+ params: query.args
195
+ });
196
+ return result;
197
+ }
198
+ );
199
+ }
161
200
 
162
201
  // src/UserFacingError.ts
163
202
  import { isDriverAdapterError } from "@prisma/driver-adapter-utils";
@@ -548,6 +587,7 @@ function doesRequireEvaluation(param) {
548
587
  }
549
588
 
550
589
  // src/interpreter/serializeSql.ts
590
+ import { ColumnTypeEnum } from "@prisma/driver-adapter-utils";
551
591
  function serializeSql(resultSet) {
552
592
  return resultSet.rows.map(
553
593
  (row) => row.reduce((acc, value, index) => {
@@ -568,6 +608,85 @@ function serializeSql(resultSet) {
568
608
  }, {})
569
609
  );
570
610
  }
611
+ function serializeRawSql(resultSet) {
612
+ return {
613
+ columns: resultSet.columnNames,
614
+ types: resultSet.columnTypes.map((type) => serializeColumnType(type)),
615
+ rows: resultSet.rows
616
+ };
617
+ }
618
+ function serializeColumnType(columnType) {
619
+ switch (columnType) {
620
+ case ColumnTypeEnum.Int32:
621
+ return "int";
622
+ case ColumnTypeEnum.Int64:
623
+ return "bigint";
624
+ case ColumnTypeEnum.Float:
625
+ return "float";
626
+ case ColumnTypeEnum.Double:
627
+ return "double";
628
+ case ColumnTypeEnum.Text:
629
+ return "string";
630
+ case ColumnTypeEnum.Enum:
631
+ return "enum";
632
+ case ColumnTypeEnum.Bytes:
633
+ return "bytes";
634
+ case ColumnTypeEnum.Boolean:
635
+ return "bool";
636
+ case ColumnTypeEnum.Character:
637
+ return "char";
638
+ case ColumnTypeEnum.Numeric:
639
+ return "decimal";
640
+ case ColumnTypeEnum.Json:
641
+ return "json";
642
+ case ColumnTypeEnum.Uuid:
643
+ return "uuid";
644
+ case ColumnTypeEnum.DateTime:
645
+ return "datetime";
646
+ case ColumnTypeEnum.Date:
647
+ return "date";
648
+ case ColumnTypeEnum.Time:
649
+ return "time";
650
+ case ColumnTypeEnum.Int32Array:
651
+ return "int-array";
652
+ case ColumnTypeEnum.Int64Array:
653
+ return "bigint-array";
654
+ case ColumnTypeEnum.FloatArray:
655
+ return "float-array";
656
+ case ColumnTypeEnum.DoubleArray:
657
+ return "double-array";
658
+ case ColumnTypeEnum.TextArray:
659
+ return "string-array";
660
+ case ColumnTypeEnum.EnumArray:
661
+ return "string-array";
662
+ case ColumnTypeEnum.BytesArray:
663
+ return "bytes-array";
664
+ case ColumnTypeEnum.BooleanArray:
665
+ return "bool-array";
666
+ case ColumnTypeEnum.CharacterArray:
667
+ return "char-array";
668
+ case ColumnTypeEnum.NumericArray:
669
+ return "decimal-array";
670
+ case ColumnTypeEnum.JsonArray:
671
+ return "json-array";
672
+ case ColumnTypeEnum.UuidArray:
673
+ return "uuid-array";
674
+ case ColumnTypeEnum.DateTimeArray:
675
+ return "datetime-array";
676
+ case ColumnTypeEnum.DateArray:
677
+ return "date-array";
678
+ case ColumnTypeEnum.TimeArray:
679
+ return "time-array";
680
+ case ColumnTypeEnum.UnknownNumber:
681
+ return "unknown";
682
+ /// The following PlanetScale type IDs are mapped into Set:
683
+ /// - SET (SET) -> e.g. `"foo,bar"` (String-encoded, comma-separated)
684
+ case ColumnTypeEnum.Set:
685
+ return "string";
686
+ default:
687
+ assertNever(columnType, `Unexpected column type: ${columnType}`);
688
+ }
689
+ }
571
690
 
572
691
  // src/interpreter/validation.ts
573
692
  function performValidation(data, rules, error) {
@@ -648,12 +767,21 @@ var QueryInterpreter = class _QueryInterpreter {
648
767
  #generators = new GeneratorRegistry();
649
768
  #tracingHelper;
650
769
  #serializer;
651
- constructor({ transactionManager, placeholderValues, onQuery, tracingHelper, serializer }) {
770
+ #rawSerializer;
771
+ constructor({
772
+ transactionManager,
773
+ placeholderValues,
774
+ onQuery,
775
+ tracingHelper,
776
+ serializer,
777
+ rawSerializer
778
+ }) {
652
779
  this.#transactionManager = transactionManager;
653
780
  this.#placeholderValues = placeholderValues;
654
781
  this.#onQuery = onQuery;
655
782
  this.#tracingHelper = tracingHelper;
656
783
  this.#serializer = serializer;
784
+ this.#rawSerializer = rawSerializer ?? serializer;
657
785
  }
658
786
  static forSql(options) {
659
787
  return new _QueryInterpreter({
@@ -661,7 +789,8 @@ var QueryInterpreter = class _QueryInterpreter {
661
789
  placeholderValues: options.placeholderValues,
662
790
  onQuery: options.onQuery,
663
791
  tracingHelper: options.tracingHelper,
664
- serializer: serializeSql
792
+ serializer: serializeSql,
793
+ rawSerializer: serializeRawSql
665
794
  });
666
795
  }
667
796
  async run(queryPlan, queryable) {
@@ -707,14 +836,18 @@ var QueryInterpreter = class _QueryInterpreter {
707
836
  }
708
837
  case "execute": {
709
838
  const query = renderQuery(node.args, scope, generators);
710
- return this.#withQueryEvent(query, queryable, async () => {
839
+ return this.#withQuerySpanAndEvent(query, queryable, async () => {
711
840
  return await queryable.executeRaw(query);
712
841
  });
713
842
  }
714
843
  case "query": {
715
844
  const query = renderQuery(node.args, scope, generators);
716
- return this.#withQueryEvent(query, queryable, async () => {
717
- return this.#serializer(await queryable.queryRaw(query));
845
+ return this.#withQuerySpanAndEvent(query, queryable, async () => {
846
+ if (node.args.type === "rawSql") {
847
+ return this.#rawSerializer(await queryable.queryRaw(query));
848
+ } else {
849
+ return this.#serializer(await queryable.queryRaw(query));
850
+ }
718
851
  });
719
852
  }
720
853
  case "reverse": {
@@ -839,30 +972,14 @@ var QueryInterpreter = class _QueryInterpreter {
839
972
  assertNever(node, `Unexpected node type: ${node.type}`);
840
973
  }
841
974
  }
842
- #withQueryEvent(query, queryable, execute) {
843
- return this.#tracingHelper.runInChildSpan(
844
- {
845
- name: "db_query",
846
- kind: SpanKind.CLIENT,
847
- attributes: {
848
- "db.query.text": query.sql,
849
- "db.system.name": providerToOtelSystem(queryable.provider)
850
- }
851
- },
852
- async () => {
853
- const timestamp = /* @__PURE__ */ new Date();
854
- const startInstant = performance.now();
855
- const result = await execute();
856
- const endInstant = performance.now();
857
- this.#onQuery?.({
858
- timestamp,
859
- duration: endInstant - startInstant,
860
- query: query.sql,
861
- params: query.args
862
- });
863
- return result;
864
- }
865
- );
975
+ #withQuerySpanAndEvent(query, queryable, execute) {
976
+ return withQuerySpanAndEvent({
977
+ query,
978
+ queryable,
979
+ execute,
980
+ tracingHelper: this.#tracingHelper,
981
+ onQuery: this.#onQuery
982
+ });
866
983
  }
867
984
  };
868
985
  function isEmpty(value) {
@@ -1005,6 +1122,16 @@ var MAX_CLOSED_TRANSACTIONS = 100;
1005
1122
  var debug = Debug("prisma:client:transactionManager");
1006
1123
  var COMMIT_QUERY = () => ({ sql: "COMMIT", args: [], argTypes: [] });
1007
1124
  var ROLLBACK_QUERY = () => ({ sql: "ROLLBACK", args: [], argTypes: [] });
1125
+ var PHANTOM_COMMIT_QUERY = () => ({
1126
+ sql: '-- Implicit "COMMIT" query via underlying driver',
1127
+ args: [],
1128
+ argTypes: []
1129
+ });
1130
+ var PHANTOM_ROLLBACK_QUERY = () => ({
1131
+ sql: '-- Implicit "ROLLBACK" query via underlying driver',
1132
+ args: [],
1133
+ argTypes: []
1134
+ });
1008
1135
  var TransactionManager = class {
1009
1136
  // The map of active transactions.
1010
1137
  transactions = /* @__PURE__ */ new Map();
@@ -1014,14 +1141,17 @@ var TransactionManager = class {
1014
1141
  driverAdapter;
1015
1142
  transactionOptions;
1016
1143
  tracingHelper;
1144
+ #onQuery;
1017
1145
  constructor({
1018
1146
  driverAdapter,
1019
1147
  transactionOptions,
1020
- tracingHelper
1148
+ tracingHelper,
1149
+ onQuery
1021
1150
  }) {
1022
1151
  this.driverAdapter = driverAdapter;
1023
1152
  this.transactionOptions = transactionOptions;
1024
1153
  this.tracingHelper = tracingHelper;
1154
+ this.#onQuery = onQuery;
1025
1155
  }
1026
1156
  async startTransaction(options) {
1027
1157
  return await this.tracingHelper.runInChildSpan("start_transaction", () => this.#startTransactionImpl(options));
@@ -1125,14 +1255,20 @@ var TransactionManager = class {
1125
1255
  debug("Closing transaction.", { transactionId: tx.id, status });
1126
1256
  tx.status = status;
1127
1257
  if (tx.transaction && status === "committed") {
1128
- await tx.transaction.commit();
1129
- if (!tx.transaction.options.usePhantomQuery) {
1130
- await tx.transaction.executeRaw(COMMIT_QUERY());
1258
+ if (tx.transaction.options.usePhantomQuery) {
1259
+ await this.#withQuerySpanAndEvent(PHANTOM_COMMIT_QUERY(), tx.transaction, () => tx.transaction.commit());
1260
+ } else {
1261
+ await tx.transaction.commit();
1262
+ const query = COMMIT_QUERY();
1263
+ await this.#withQuerySpanAndEvent(query, tx.transaction, () => tx.transaction.executeRaw(query));
1131
1264
  }
1132
1265
  } else if (tx.transaction) {
1133
- await tx.transaction.rollback();
1134
- if (!tx.transaction.options.usePhantomQuery) {
1135
- await tx.transaction.executeRaw(ROLLBACK_QUERY());
1266
+ if (tx.transaction.options.usePhantomQuery) {
1267
+ await this.#withQuerySpanAndEvent(PHANTOM_ROLLBACK_QUERY(), tx.transaction, () => tx.transaction.rollback());
1268
+ } else {
1269
+ await tx.transaction.rollback();
1270
+ const query = ROLLBACK_QUERY();
1271
+ await this.#withQuerySpanAndEvent(query, tx.transaction, () => tx.transaction.executeRaw(query));
1136
1272
  }
1137
1273
  }
1138
1274
  clearTimeout(tx.timer);
@@ -1153,6 +1289,15 @@ var TransactionManager = class {
1153
1289
  maxWait: options.maxWait
1154
1290
  };
1155
1291
  }
1292
+ #withQuerySpanAndEvent(query, queryable, execute) {
1293
+ return withQuerySpanAndEvent({
1294
+ query,
1295
+ queryable,
1296
+ execute,
1297
+ tracingHelper: this.tracingHelper,
1298
+ onQuery: this.#onQuery
1299
+ });
1300
+ }
1156
1301
  };
1157
1302
  export {
1158
1303
  DataMapperError,
@@ -1166,5 +1311,6 @@ export {
1166
1311
  isPrismaValueBytes,
1167
1312
  isPrismaValueGenerator,
1168
1313
  isPrismaValuePlaceholder,
1169
- noopTracingHelper
1314
+ noopTracingHelper,
1315
+ safeJsonStringify
1170
1316
  };
@@ -16,10 +16,11 @@ export type QueryInterpreterOptions = {
16
16
  onQuery?: (event: QueryEvent) => void;
17
17
  tracingHelper: TracingHelper;
18
18
  serializer: (results: SqlResultSet) => Value;
19
+ rawSerializer?: (results: SqlResultSet) => Value;
19
20
  };
20
21
  export declare class QueryInterpreter {
21
22
  #private;
22
- constructor({ transactionManager, placeholderValues, onQuery, tracingHelper, serializer }: QueryInterpreterOptions);
23
+ constructor({ transactionManager, placeholderValues, onQuery, tracingHelper, serializer, rawSerializer, }: QueryInterpreterOptions);
23
24
  static forSql(options: {
24
25
  transactionManager: QueryInterpreterTransactionManager;
25
26
  placeholderValues: Record<string, unknown>;
@@ -1,2 +1,3 @@
1
- import type { SqlResultSet } from '@prisma/driver-adapter-utils';
1
+ import { type SqlResultSet } from '@prisma/driver-adapter-utils';
2
2
  export declare function serializeSql(resultSet: SqlResultSet): Record<string, unknown>[];
3
+ export declare function serializeRawSql(resultSet: SqlResultSet): Record<string, unknown>;
package/dist/tracing.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import type { Context, Span, SpanOptions } from '@opentelemetry/api';
2
- import type { Provider } from '@prisma/driver-adapter-utils';
1
+ import { type Context, type Span, type SpanOptions } from '@opentelemetry/api';
2
+ import type { Provider, SqlQuery, SqlQueryable } from '@prisma/driver-adapter-utils';
3
+ import { QueryEvent } from './events';
3
4
  export type SpanCallback<R> = (span?: Span, context?: Context) => R;
4
5
  export type ExtendedSpanOptions = SpanOptions & {
5
6
  name: string;
@@ -9,3 +10,10 @@ export interface TracingHelper {
9
10
  }
10
11
  export declare const noopTracingHelper: TracingHelper;
11
12
  export declare function providerToOtelSystem(provider: Provider): string;
13
+ export declare function withQuerySpanAndEvent<T>({ query, queryable, tracingHelper, onQuery, execute, }: {
14
+ query: SqlQuery;
15
+ queryable: SqlQueryable;
16
+ tracingHelper: TracingHelper;
17
+ onQuery?: (event: QueryEvent) => void;
18
+ execute: () => Promise<T>;
19
+ }): Promise<T>;
@@ -1,4 +1,5 @@
1
1
  import { SqlDriverAdapter, Transaction } from '@prisma/driver-adapter-utils';
2
+ import { QueryEvent } from '../events';
2
3
  import { TracingHelper } from '../tracing';
3
4
  import { Options, TransactionInfo } from './Transaction';
4
5
  export declare class TransactionManager {
@@ -8,10 +9,11 @@ export declare class TransactionManager {
8
9
  private readonly driverAdapter;
9
10
  private readonly transactionOptions;
10
11
  private readonly tracingHelper;
11
- constructor({ driverAdapter, transactionOptions, tracingHelper, }: {
12
+ constructor({ driverAdapter, transactionOptions, tracingHelper, onQuery, }: {
12
13
  driverAdapter: SqlDriverAdapter;
13
14
  transactionOptions: Options;
14
15
  tracingHelper: TracingHelper;
16
+ onQuery?: (event: QueryEvent) => void;
15
17
  });
16
18
  startTransaction(options?: Options): Promise<TransactionInfo>;
17
19
  commitTransaction(transactionId: string): Promise<void>;
package/dist/utils.d.ts CHANGED
@@ -9,3 +9,8 @@ export declare function isDeepStrictEqual(a: unknown, b: unknown): boolean;
9
9
  * converts arguments to the types used by driver adapters if necessary.
10
10
  */
11
11
  export declare function doKeysMatch(lhs: {}, rhs: {}): boolean;
12
+ /**
13
+ * `JSON.stringify` wrapper with custom replacer function that handles nested
14
+ * BigInt and Uint8Array values.
15
+ */
16
+ export declare function safeJsonStringify(obj: unknown): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma/client-engine-runtime",
3
- "version": "6.9.0-dev.20",
3
+ "version": "6.9.0-dev.22",
4
4
  "description": "This package is intended for Prisma's internal use",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -31,8 +31,8 @@
31
31
  "nanoid": "5.1.5",
32
32
  "ulid": "3.0.0",
33
33
  "uuid": "11.1.0",
34
- "@prisma/debug": "6.9.0-dev.20",
35
- "@prisma/driver-adapter-utils": "6.9.0-dev.20"
34
+ "@prisma/driver-adapter-utils": "6.9.0-dev.22",
35
+ "@prisma/debug": "6.9.0-dev.22"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/jest": "29.5.14",