@prisma/query-plan-executor 7.10.0-dev.20 → 7.10.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +102 -82
  2. package/dist/index.js +269 -24
  3. package/package.json +6 -6
package/dist/index.d.ts CHANGED
@@ -1645,6 +1645,21 @@ declare interface HTTPResponseError extends Error {
1645
1645
 
1646
1646
  declare type IfAnyThenEmptyObject<T> = 0 extends 1 & T ? {} : T;
1647
1647
 
1648
+ /**
1649
+ * Query plan nodes that perform database I/O: individual queries and statements,
1650
+ * and subtrees executed within a transaction.
1651
+ */
1652
+ declare type ImpureQueryPlanNode = {
1653
+ type: 'query';
1654
+ args: QueryPlanDbQuery;
1655
+ } | {
1656
+ type: 'execute';
1657
+ args: QueryPlanDbQuery;
1658
+ } | {
1659
+ type: 'transaction';
1660
+ args: QueryPlanNode;
1661
+ };
1662
+
1648
1663
  /**
1649
1664
  * Logs an informational message using the active logger.
1650
1665
  *
@@ -1690,13 +1705,6 @@ declare type IsInvalid<T> = T extends InvalidJSONValue ? true : false;
1690
1705
 
1691
1706
  declare type IsolationLevel = 'READ UNCOMMITTED' | 'READ COMMITTED' | 'REPEATABLE READ' | 'SNAPSHOT' | 'SERIALIZABLE';
1692
1707
 
1693
- declare type JoinExpression = {
1694
- child: QueryPlanNode;
1695
- on: [left: string, right: string][];
1696
- parentField: string;
1697
- isRelationUnique: boolean;
1698
- };
1699
-
1700
1708
  declare type JSONArray = (JSONPrimitive | JSONObject | JSONArray)[];
1701
1709
 
1702
1710
  declare type JSONObject = {
@@ -2403,57 +2411,23 @@ declare type PropsForRenderer = [...Required<Parameters<Renderer>>] extends [unk
2403
2411
  declare type Provider = 'mysql' | 'postgres' | 'sqlite' | 'sqlserver';
2404
2412
 
2405
2413
  /**
2406
- * Logs a database query event using the active logger.
2407
- *
2408
- * @param message The message to log
2409
- * @param attributes Optional key-value pairs to include with the log event
2410
- * @throws {Error} if no active logger is found
2414
+ * Query plan nodes that are free of side effects and can be interpreted synchronously
2415
+ * without touching the database. The `Rest` parameter controls what other nodes may
2416
+ * appear in child positions: with the default `never` the tree is fully pure, while
2417
+ * `PureQueryPlanNode<ImpureQueryPlanNode>` describes a tree of pure nodes that may
2418
+ * contain impure nodes anywhere inside.
2411
2419
  */
2412
- declare function query(message: string, attributes?: ExtendedAttributes): void;
2413
-
2414
- declare interface Queryable<Query, Result> extends AdapterInfo {
2415
- /**
2416
- * Execute a query and return its result.
2417
- */
2418
- queryRaw(params: Query): Promise<Result>;
2419
- /**
2420
- * Execute a query and return the number of affected rows.
2421
- */
2422
- executeRaw(params: Query): Promise<number>;
2423
- }
2424
-
2425
- declare type QueryEvent = {
2426
- timestamp: Date;
2427
- query: string;
2428
- params: readonly unknown[];
2429
- duration: number;
2430
- };
2431
-
2432
- declare type QueryPlanBinding = {
2433
- name: string;
2434
- expr: QueryPlanNode;
2435
- };
2436
-
2437
- declare type QueryPlanDbQuery = {
2438
- type: 'rawSql';
2439
- sql: string;
2440
- args: PrismaValue[];
2441
- argTypes: ArgType[];
2442
- } | {
2443
- type: 'templateSql';
2444
- fragments: Fragment[];
2445
- placeholderFormat: PlaceholderFormat;
2446
- args: PrismaValue[];
2447
- argTypes: DynamicArgType[];
2448
- chunkable: boolean;
2449
- };
2450
-
2451
- declare type QueryPlanNode = {
2420
+ declare type PureQueryPlanNode<Rest = never> = {
2452
2421
  type: 'value';
2453
2422
  args: PrismaValue;
2423
+ /**
2424
+ * Present when this node is the result of evaluating an impure node during
2425
+ * query plan purification. Never produced by the query compiler.
2426
+ */
2427
+ lastInsertId?: string;
2454
2428
  } | {
2455
2429
  type: 'seq';
2456
- args: QueryPlanNode[];
2430
+ args: (PureQueryPlanNode<Rest> | Rest)[];
2457
2431
  } | {
2458
2432
  type: 'get';
2459
2433
  args: {
@@ -2462,101 +2436,147 @@ declare type QueryPlanNode = {
2462
2436
  } | {
2463
2437
  type: 'let';
2464
2438
  args: {
2465
- bindings: QueryPlanBinding[];
2466
- expr: QueryPlanNode;
2439
+ bindings: {
2440
+ name: string;
2441
+ expr: PureQueryPlanNode<Rest> | Rest;
2442
+ }[];
2443
+ expr: PureQueryPlanNode<Rest> | Rest;
2467
2444
  };
2468
2445
  } | {
2469
2446
  type: 'getFirstNonEmpty';
2470
2447
  args: {
2471
2448
  names: string[];
2472
2449
  };
2473
- } | {
2474
- type: 'query';
2475
- args: QueryPlanDbQuery;
2476
- } | {
2477
- type: 'execute';
2478
- args: QueryPlanDbQuery;
2479
2450
  } | {
2480
2451
  type: 'reverse';
2481
- args: QueryPlanNode;
2452
+ args: PureQueryPlanNode<Rest> | Rest;
2482
2453
  } | {
2483
2454
  type: 'sum';
2484
- args: QueryPlanNode[];
2455
+ args: (PureQueryPlanNode<Rest> | Rest)[];
2485
2456
  } | {
2486
2457
  type: 'concat';
2487
- args: QueryPlanNode[];
2458
+ args: (PureQueryPlanNode<Rest> | Rest)[];
2488
2459
  } | {
2489
2460
  type: 'unique';
2490
- args: QueryPlanNode;
2461
+ args: PureQueryPlanNode<Rest> | Rest;
2491
2462
  } | {
2492
2463
  type: 'required';
2493
- args: QueryPlanNode;
2464
+ args: PureQueryPlanNode<Rest> | Rest;
2494
2465
  } | {
2495
2466
  type: 'join';
2496
2467
  args: {
2497
- parent: QueryPlanNode;
2498
- children: JoinExpression[];
2468
+ parent: PureQueryPlanNode<Rest> | Rest;
2469
+ children: {
2470
+ child: PureQueryPlanNode<Rest> | Rest;
2471
+ on: [left: string, right: string][];
2472
+ parentField: string;
2473
+ isRelationUnique: boolean;
2474
+ }[];
2499
2475
  canAssumeStrictEquality: boolean;
2500
2476
  };
2501
2477
  } | {
2502
2478
  type: 'mapField';
2503
2479
  args: {
2504
2480
  field: string;
2505
- records: QueryPlanNode;
2481
+ records: PureQueryPlanNode<Rest> | Rest;
2506
2482
  };
2507
- } | {
2508
- type: 'transaction';
2509
- args: QueryPlanNode;
2510
2483
  } | {
2511
2484
  type: 'dataMap';
2512
2485
  args: {
2513
- expr: QueryPlanNode;
2486
+ expr: PureQueryPlanNode<Rest> | Rest;
2514
2487
  structure: ResultNode;
2515
2488
  enums: Record<string, Record<string, string>>;
2516
2489
  };
2517
2490
  } | {
2518
2491
  type: 'validate';
2519
2492
  args: {
2520
- expr: QueryPlanNode;
2493
+ expr: PureQueryPlanNode<Rest> | Rest;
2521
2494
  rules: DataRule[];
2522
2495
  } & ValidationError;
2523
2496
  } | {
2524
2497
  type: 'if';
2525
2498
  args: {
2526
- value: QueryPlanNode;
2499
+ value: PureQueryPlanNode<Rest> | Rest;
2527
2500
  rule: DataRule;
2528
- then: QueryPlanNode;
2529
- else: QueryPlanNode;
2501
+ then: PureQueryPlanNode<Rest> | Rest;
2502
+ else: PureQueryPlanNode<Rest> | Rest;
2530
2503
  };
2531
2504
  } | {
2532
2505
  type: 'unit';
2533
2506
  } | {
2534
2507
  type: 'diff';
2535
2508
  args: {
2536
- from: QueryPlanNode;
2537
- to: QueryPlanNode;
2509
+ from: PureQueryPlanNode<Rest> | Rest;
2510
+ to: PureQueryPlanNode<Rest> | Rest;
2538
2511
  fields: string[];
2539
2512
  };
2540
2513
  } | {
2541
2514
  type: 'initializeRecord';
2542
2515
  args: {
2543
- expr: QueryPlanNode;
2516
+ expr: PureQueryPlanNode<Rest> | Rest;
2544
2517
  fields: Record<string, FieldInitializer>;
2545
2518
  };
2546
2519
  } | {
2547
2520
  type: 'mapRecord';
2548
2521
  args: {
2549
- expr: QueryPlanNode;
2522
+ expr: PureQueryPlanNode<Rest> | Rest;
2550
2523
  fields: Record<string, FieldOperation>;
2551
2524
  };
2552
2525
  } | {
2553
2526
  type: 'process';
2554
2527
  args: {
2555
- expr: QueryPlanNode;
2528
+ expr: PureQueryPlanNode<Rest> | Rest;
2556
2529
  operations: InMemoryOps;
2557
2530
  };
2558
2531
  };
2559
2532
 
2533
+ /**
2534
+ * Logs a database query event using the active logger.
2535
+ *
2536
+ * @param message The message to log
2537
+ * @param attributes Optional key-value pairs to include with the log event
2538
+ * @throws {Error} if no active logger is found
2539
+ */
2540
+ declare function query(message: string, attributes?: ExtendedAttributes): void;
2541
+
2542
+ declare interface Queryable<Query, Result> extends AdapterInfo {
2543
+ /**
2544
+ * Execute a query and return its result.
2545
+ */
2546
+ queryRaw(params: Query): Promise<Result>;
2547
+ /**
2548
+ * Execute a query and return the number of affected rows.
2549
+ */
2550
+ executeRaw(params: Query): Promise<number>;
2551
+ }
2552
+
2553
+ declare type QueryEvent = {
2554
+ timestamp: Date;
2555
+ query: string;
2556
+ params: readonly unknown[];
2557
+ duration: number;
2558
+ };
2559
+
2560
+ declare type QueryPlanDbQuery = {
2561
+ type: 'rawSql';
2562
+ sql: string;
2563
+ args: PrismaValue[];
2564
+ argTypes: ArgType[];
2565
+ } | {
2566
+ type: 'templateSql';
2567
+ fragments: Fragment[];
2568
+ placeholderFormat: PlaceholderFormat;
2569
+ args: PrismaValue[];
2570
+ argTypes: DynamicArgType[];
2571
+ chunkable: boolean;
2572
+ };
2573
+
2574
+ /**
2575
+ * A query plan as emitted by the query compiler: a tree of pure nodes that may
2576
+ * contain impure nodes anywhere inside.
2577
+ */
2578
+ declare type QueryPlanNode = ImpureQueryPlanNode | PureQueryPlanNode<ImpureQueryPlanNode>;
2579
+
2560
2580
  declare type RedirectStatusCode = 300 | 301 | 302 | 303 | 304 | DeprecatedStatusCode | 307 | 308;
2561
2581
 
2562
2582
  declare type RemoveBlankRecord<T> = T extends Record<infer K, unknown> ? (K extends string ? T : never) : never;
package/dist/index.js CHANGED
@@ -93473,7 +93473,7 @@ __export(index_exports, {
93473
93473
  module.exports = __toCommonJS(index_exports);
93474
93474
 
93475
93475
  // package.json
93476
- var version = "7.10.0-dev.20";
93476
+ var version = "7.10.0-dev.22";
93477
93477
 
93478
93478
  // ../../node_modules/.pnpm/temporal-polyfill@0.3.0/node_modules/temporal-polyfill/chunks/internal.js
93479
93479
  function clampProp(e2, n2, t2, o2, r2) {
@@ -101793,6 +101793,16 @@ function safeJsonStringify(obj) {
101793
101793
  return val;
101794
101794
  });
101795
101795
  }
101796
+ var MAX_PUSH_SPREAD_ARGS = 8192;
101797
+ function appendToArray(target, source) {
101798
+ if (source.length <= MAX_PUSH_SPREAD_ARGS) {
101799
+ target.push(...source);
101800
+ return;
101801
+ }
101802
+ for (let i2 = 0; i2 < source.length; i2 += MAX_PUSH_SPREAD_ARGS) {
101803
+ target.push(...source.slice(i2, i2 + MAX_PUSH_SPREAD_ARGS));
101804
+ }
101805
+ }
101796
101806
  function normalizeJsonProtocolValues(result) {
101797
101807
  if (result === null) {
101798
101808
  return result;
@@ -102658,8 +102668,9 @@ function renderTemplateSql(fragments, placeholderFormat, params, argTypes) {
102658
102668
  if (fragment.type === "stringChunk") {
102659
102669
  continue;
102660
102670
  }
102661
- const length2 = flattenedParams.length;
102662
- const added = flattenedParams.push(...flattenedFragmentParams(fragment)) - length2;
102671
+ const fragmentParams = Array.from(flattenedFragmentParams(fragment));
102672
+ const added = fragmentParams.length;
102673
+ appendToArray(flattenedParams, fragmentParams);
102663
102674
  if (fragment.argType.arity === "tuple") {
102664
102675
  if (added % fragment.argType.elements.length !== 0) {
102665
102676
  throw new Error(
@@ -103115,17 +103126,27 @@ var QueryInterpreter = class _QueryInterpreter {
103115
103126
  });
103116
103127
  }
103117
103128
  async run(queryPlan, options) {
103118
- const { value } = await this.interpretNode(queryPlan, {
103119
- ...options,
103120
- generators: this.#generators.snapshot()
103121
- }).catch((e2) => rethrowAsUserFacing(e2));
103129
+ const generators = this.#generators.snapshot();
103130
+ const context4 = { ...options, generators };
103131
+ const purified = purifyQueryPlan(queryPlan, (node) => this.interpretNode(node, context4))?.catch(
103132
+ (e2) => rethrowAsUserFacing(e2)
103133
+ );
103134
+ if (purified) {
103135
+ try {
103136
+ return this.#interpretPureNode(await purified, context4.scope, generators).value;
103137
+ } catch (e2) {
103138
+ rethrowAsUserFacing(e2);
103139
+ }
103140
+ }
103141
+ const { value } = await this.interpretNode(queryPlan, context4).catch((e2) => rethrowAsUserFacing(e2));
103122
103142
  return value;
103123
103143
  }
103124
103144
  async interpretNode(node, context4) {
103125
103145
  switch (node.type) {
103126
103146
  case "value": {
103127
103147
  return {
103128
- value: evaluateArg(node.args, context4.scope, context4.generators)
103148
+ value: evaluateArg(node.args, context4.scope, context4.generators),
103149
+ lastInsertId: node.lastInsertId
103129
103150
  };
103130
103151
  }
103131
103152
  case "seq": {
@@ -103135,9 +103156,6 @@ var QueryInterpreter = class _QueryInterpreter {
103135
103156
  }
103136
103157
  return result ?? { value: void 0 };
103137
103158
  }
103138
- case "get": {
103139
- return { value: context4.scope[node.args.name] };
103140
- }
103141
103159
  case "let": {
103142
103160
  const nestedScope = Object.create(context4.scope);
103143
103161
  for (const binding of node.args.bindings) {
@@ -103146,15 +103164,6 @@ var QueryInterpreter = class _QueryInterpreter {
103146
103164
  }
103147
103165
  return this.interpretNode(node.args.expr, { ...context4, scope: nestedScope });
103148
103166
  }
103149
- case "getFirstNonEmpty": {
103150
- for (const name6 of node.args.names) {
103151
- const value = context4.scope[name6];
103152
- if (!isEmpty(value)) {
103153
- return { value };
103154
- }
103155
- }
103156
- return { value: [] };
103157
- }
103158
103167
  case "concat": {
103159
103168
  const parts = await Promise.all(
103160
103169
  node.args.map((arg) => this.interpretNode(arg, context4).then((res) => res.value))
@@ -103201,7 +103210,7 @@ var QueryInterpreter = class _QueryInterpreter {
103201
103210
  if (results === void 0) {
103202
103211
  results = result;
103203
103212
  } else {
103204
- results.rows.push(...result.rows);
103213
+ appendToArray(results.rows, result.rows);
103205
103214
  results.lastInsertId = result.lastInsertId;
103206
103215
  }
103207
103216
  }
@@ -103281,9 +103290,6 @@ var QueryInterpreter = class _QueryInterpreter {
103281
103290
  return await this.interpretNode(node.args.else, context4);
103282
103291
  }
103283
103292
  }
103284
- case "unit": {
103285
- return { value: void 0 };
103286
- }
103287
103293
  case "diff": {
103288
103294
  const { value: from } = await this.interpretNode(node.args.from, context4);
103289
103295
  const { value: to2 } = await this.interpretNode(node.args.to, context4);
@@ -103313,6 +103319,139 @@ var QueryInterpreter = class _QueryInterpreter {
103313
103319
  }
103314
103320
  return { value: record2, lastInsertId };
103315
103321
  }
103322
+ default:
103323
+ return this.#interpretPureNode(node, context4.scope, context4.generators);
103324
+ }
103325
+ }
103326
+ #interpretPureNode(node, scope, generators) {
103327
+ switch (node.type) {
103328
+ case "value": {
103329
+ return { value: evaluateArg(node.args, scope, generators), lastInsertId: node.lastInsertId };
103330
+ }
103331
+ case "seq": {
103332
+ let result;
103333
+ for (const arg of node.args) {
103334
+ result = this.#interpretPureNode(arg, scope, generators);
103335
+ }
103336
+ return result ?? { value: void 0 };
103337
+ }
103338
+ case "get": {
103339
+ return { value: scope[node.args.name] };
103340
+ }
103341
+ case "let": {
103342
+ const nestedScope = Object.create(scope);
103343
+ for (const binding of node.args.bindings) {
103344
+ const { value } = this.#interpretPureNode(binding.expr, nestedScope, generators);
103345
+ nestedScope[binding.name] = value;
103346
+ }
103347
+ return this.#interpretPureNode(node.args.expr, nestedScope, generators);
103348
+ }
103349
+ case "getFirstNonEmpty": {
103350
+ for (const name6 of node.args.names) {
103351
+ const value = scope[name6];
103352
+ if (!isEmpty(value)) {
103353
+ return { value };
103354
+ }
103355
+ }
103356
+ return { value: [] };
103357
+ }
103358
+ case "concat": {
103359
+ const parts = node.args.map((arg) => this.#interpretPureNode(arg, scope, generators).value);
103360
+ return {
103361
+ value: parts.length > 0 ? parts.reduce((acc, part) => acc.concat(asList(part)), []) : []
103362
+ };
103363
+ }
103364
+ case "sum": {
103365
+ const parts = node.args.map((arg) => this.#interpretPureNode(arg, scope, generators).value);
103366
+ return {
103367
+ value: parts.length > 0 ? parts.reduce((acc, part) => asNumber2(acc) + asNumber2(part)) : 0
103368
+ };
103369
+ }
103370
+ case "reverse": {
103371
+ const { value, lastInsertId } = this.#interpretPureNode(node.args, scope, generators);
103372
+ return { value: Array.isArray(value) ? value.reverse() : value, lastInsertId };
103373
+ }
103374
+ case "unique": {
103375
+ const { value, lastInsertId } = this.#interpretPureNode(node.args, scope, generators);
103376
+ if (!Array.isArray(value)) {
103377
+ return { value, lastInsertId };
103378
+ }
103379
+ if (value.length > 1) {
103380
+ throw new Error(`Expected zero or one element, got ${value.length}`);
103381
+ }
103382
+ return { value: value[0] ?? null, lastInsertId };
103383
+ }
103384
+ case "required": {
103385
+ const { value, lastInsertId } = this.#interpretPureNode(node.args, scope, generators);
103386
+ if (isEmpty(value)) {
103387
+ throw new Error("Required value is empty");
103388
+ }
103389
+ return { value, lastInsertId };
103390
+ }
103391
+ case "mapField": {
103392
+ const { value, lastInsertId } = this.#interpretPureNode(node.args.records, scope, generators);
103393
+ return { value: mapField2(value, node.args.field), lastInsertId };
103394
+ }
103395
+ case "join": {
103396
+ const { value: parent, lastInsertId } = this.#interpretPureNode(node.args.parent, scope, generators);
103397
+ if (parent === null) {
103398
+ return { value: null, lastInsertId };
103399
+ }
103400
+ const children = node.args.children.map((joinExpr) => ({
103401
+ joinExpr,
103402
+ childRecords: this.#interpretPureNode(joinExpr.child, scope, generators).value
103403
+ }));
103404
+ return { value: attachChildrenToParents(parent, children, node.args.canAssumeStrictEquality), lastInsertId };
103405
+ }
103406
+ case "dataMap": {
103407
+ const { value, lastInsertId } = this.#interpretPureNode(node.args.expr, scope, generators);
103408
+ return { value: applyDataMap(value, node.args.structure, node.args.enums), lastInsertId };
103409
+ }
103410
+ case "validate": {
103411
+ const { value, lastInsertId } = this.#interpretPureNode(node.args.expr, scope, generators);
103412
+ performValidation(value, node.args.rules, node.args);
103413
+ return { value, lastInsertId };
103414
+ }
103415
+ case "if": {
103416
+ const { value } = this.#interpretPureNode(node.args.value, scope, generators);
103417
+ if (doesSatisfyRule(value, node.args.rule)) {
103418
+ return this.#interpretPureNode(node.args.then, scope, generators);
103419
+ } else {
103420
+ return this.#interpretPureNode(node.args.else, scope, generators);
103421
+ }
103422
+ }
103423
+ case "unit": {
103424
+ return { value: void 0 };
103425
+ }
103426
+ case "diff": {
103427
+ const { value: from } = this.#interpretPureNode(node.args.from, scope, generators);
103428
+ const { value: to2 } = this.#interpretPureNode(node.args.to, scope, generators);
103429
+ const keyGetter = (item) => item !== null ? getRecordKey(asRecord(item), node.args.fields) : null;
103430
+ const toSet = new Set(asList(to2).map(keyGetter));
103431
+ return { value: asList(from).filter((item) => !toSet.has(keyGetter(item))) };
103432
+ }
103433
+ case "process": {
103434
+ const { value, lastInsertId } = this.#interpretPureNode(node.args.expr, scope, generators);
103435
+ const ops = cloneObject(node.args.operations);
103436
+ evaluateProcessingParameters(ops, scope, generators);
103437
+ return { value: processRecords(value, ops), lastInsertId };
103438
+ }
103439
+ case "initializeRecord": {
103440
+ const { lastInsertId } = this.#interpretPureNode(node.args.expr, scope, generators);
103441
+ const record2 = {};
103442
+ for (const [key, initializer3] of Object.entries(node.args.fields)) {
103443
+ record2[key] = evalFieldInitializer(initializer3, lastInsertId, scope, generators);
103444
+ }
103445
+ return { value: record2, lastInsertId };
103446
+ }
103447
+ case "mapRecord": {
103448
+ const { value, lastInsertId } = this.#interpretPureNode(node.args.expr, scope, generators);
103449
+ const record2 = value === null ? {} : asRecord(value);
103450
+ for (const [key, entry] of Object.entries(node.args.fields)) {
103451
+ record2[key] = evalFieldOperation(entry, record2[key], scope, generators);
103452
+ }
103453
+ return { value: record2, lastInsertId };
103454
+ }
103316
103455
  default:
103317
103456
  assertNever(node, `Unexpected node type: ${node.type}`);
103318
103457
  }
@@ -103490,6 +103629,112 @@ function evalFieldOperation(op, value, scope, generators) {
103490
103629
  assertNever(op, `Unexpected field operation type: ${op["type"]}`);
103491
103630
  }
103492
103631
  }
103632
+ function purifyQueryPlan(node, evalNode) {
103633
+ const impureNode = findUniqueUnconditionalImpureNode(node);
103634
+ if (!impureNode) {
103635
+ return void 0;
103636
+ }
103637
+ return evalNode(impureNode).then((result) => {
103638
+ const evaluated = {
103639
+ type: "value",
103640
+ args: result.value,
103641
+ lastInsertId: result.lastInsertId
103642
+ };
103643
+ const purified = replaceImpureNode(node, impureNode, evaluated);
103644
+ if (!purified) {
103645
+ throw new Error("Could not substitute the evaluated impure node into the query plan");
103646
+ }
103647
+ return purified;
103648
+ });
103649
+ }
103650
+ function replaceImpureNode(node, target, replacement) {
103651
+ if (node === target) {
103652
+ return replacement;
103653
+ }
103654
+ switch (node.type) {
103655
+ case "seq":
103656
+ case "sum":
103657
+ case "concat": {
103658
+ for (let i2 = 0; i2 < node.args.length; i2++) {
103659
+ const child = replaceImpureNode(node.args[i2], target, replacement);
103660
+ if (child) {
103661
+ return { ...node, args: node.args.map((arg, j2) => j2 === i2 ? child : arg) };
103662
+ }
103663
+ }
103664
+ return void 0;
103665
+ }
103666
+ case "dataMap":
103667
+ case "validate":
103668
+ case "initializeRecord":
103669
+ case "mapRecord":
103670
+ case "process": {
103671
+ const expr = replaceImpureNode(node.args.expr, target, replacement);
103672
+ return expr && { ...node, args: { ...node.args, expr } };
103673
+ }
103674
+ case "mapField": {
103675
+ const records = replaceImpureNode(node.args.records, target, replacement);
103676
+ return records && { ...node, args: { ...node.args, records } };
103677
+ }
103678
+ case "reverse":
103679
+ case "unique":
103680
+ case "required": {
103681
+ const args = replaceImpureNode(node.args, target, replacement);
103682
+ return args && { ...node, args };
103683
+ }
103684
+ default:
103685
+ return void 0;
103686
+ }
103687
+ }
103688
+ function findUniqueUnconditionalImpureNode(node) {
103689
+ switch (node.type) {
103690
+ case "query":
103691
+ case "execute":
103692
+ return node;
103693
+ case "seq":
103694
+ case "sum":
103695
+ case "concat": {
103696
+ let found = void 0;
103697
+ for (const child of node.args) {
103698
+ const childFound = findUniqueUnconditionalImpureNode(child);
103699
+ if (childFound === null) {
103700
+ return null;
103701
+ }
103702
+ if (childFound) {
103703
+ if (found) {
103704
+ return null;
103705
+ }
103706
+ found = childFound;
103707
+ }
103708
+ }
103709
+ return found;
103710
+ }
103711
+ case "dataMap":
103712
+ case "validate":
103713
+ case "initializeRecord":
103714
+ case "mapRecord":
103715
+ case "process":
103716
+ return findUniqueUnconditionalImpureNode(node.args.expr);
103717
+ case "mapField":
103718
+ return findUniqueUnconditionalImpureNode(node.args.records);
103719
+ case "reverse":
103720
+ case "unique":
103721
+ case "required":
103722
+ return findUniqueUnconditionalImpureNode(node.args);
103723
+ case "let":
103724
+ case "join":
103725
+ case "diff":
103726
+ case "if":
103727
+ case "transaction":
103728
+ return null;
103729
+ case "value":
103730
+ case "get":
103731
+ case "getFirstNonEmpty":
103732
+ case "unit":
103733
+ return void 0;
103734
+ default:
103735
+ assertNever(node, `Unexpected node type: ${node.type}`);
103736
+ }
103737
+ }
103493
103738
  function applyComments(query2, sqlCommenter) {
103494
103739
  if (!sqlCommenter || sqlCommenter.plugins.length === 0) {
103495
103740
  return query2;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma/query-plan-executor",
3
- "version": "7.10.0-dev.20",
3
+ "version": "7.10.0-dev.22",
4
4
  "description": "This package is intended for Prisma's internal use",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -19,11 +19,11 @@
19
19
  "hono": "^4.12.23",
20
20
  "temporal-polyfill": "0.3.0",
21
21
  "zod": "4.1.3",
22
- "@prisma/adapter-mssql": "7.10.0-dev.20",
23
- "@prisma/adapter-mariadb": "7.10.0-dev.20",
24
- "@prisma/driver-adapter-utils": "7.10.0-dev.20",
25
- "@prisma/client-engine-runtime": "7.10.0-dev.20",
26
- "@prisma/adapter-pg": "7.10.0-dev.20"
22
+ "@prisma/adapter-pg": "7.10.0-dev.22",
23
+ "@prisma/adapter-mariadb": "7.10.0-dev.22",
24
+ "@prisma/adapter-mssql": "7.10.0-dev.22",
25
+ "@prisma/client-engine-runtime": "7.10.0-dev.22",
26
+ "@prisma/driver-adapter-utils": "7.10.0-dev.22"
27
27
  },
28
28
  "files": [
29
29
  "dist"