@prisma/client-engine-runtime 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.
package/dist/index.js CHANGED
@@ -145,6 +145,16 @@ function safeJsonStringify(obj) {
145
145
  return val;
146
146
  });
147
147
  }
148
+ var MAX_PUSH_SPREAD_ARGS = 8192;
149
+ function appendToArray(target, source) {
150
+ if (source.length <= MAX_PUSH_SPREAD_ARGS) {
151
+ target.push(...source);
152
+ return;
153
+ }
154
+ for (let i = 0; i < source.length; i += MAX_PUSH_SPREAD_ARGS) {
155
+ target.push(...source.slice(i, i + MAX_PUSH_SPREAD_ARGS));
156
+ }
157
+ }
148
158
 
149
159
  // src/json-protocol.ts
150
160
  function normalizeJsonProtocolValues(result) {
@@ -1148,8 +1158,9 @@ function renderTemplateSql(fragments, placeholderFormat, params, argTypes) {
1148
1158
  if (fragment.type === "stringChunk") {
1149
1159
  continue;
1150
1160
  }
1151
- const length = flattenedParams.length;
1152
- const added = flattenedParams.push(...flattenedFragmentParams(fragment)) - length;
1161
+ const fragmentParams = Array.from(flattenedFragmentParams(fragment));
1162
+ const added = fragmentParams.length;
1163
+ appendToArray(flattenedParams, fragmentParams);
1153
1164
  if (fragment.argType.arity === "tuple") {
1154
1165
  if (added % fragment.argType.elements.length !== 0) {
1155
1166
  throw new Error(
@@ -1612,17 +1623,27 @@ var QueryInterpreter = class _QueryInterpreter {
1612
1623
  });
1613
1624
  }
1614
1625
  async run(queryPlan, options) {
1615
- const { value } = await this.interpretNode(queryPlan, {
1616
- ...options,
1617
- generators: this.#generators.snapshot()
1618
- }).catch((e) => rethrowAsUserFacing(e));
1626
+ const generators = this.#generators.snapshot();
1627
+ const context = { ...options, generators };
1628
+ const purified = purifyQueryPlan(queryPlan, (node) => this.interpretNode(node, context))?.catch(
1629
+ (e) => rethrowAsUserFacing(e)
1630
+ );
1631
+ if (purified) {
1632
+ try {
1633
+ return this.#interpretPureNode(await purified, context.scope, generators).value;
1634
+ } catch (e) {
1635
+ rethrowAsUserFacing(e);
1636
+ }
1637
+ }
1638
+ const { value } = await this.interpretNode(queryPlan, context).catch((e) => rethrowAsUserFacing(e));
1619
1639
  return value;
1620
1640
  }
1621
1641
  async interpretNode(node, context) {
1622
1642
  switch (node.type) {
1623
1643
  case "value": {
1624
1644
  return {
1625
- value: evaluateArg(node.args, context.scope, context.generators)
1645
+ value: evaluateArg(node.args, context.scope, context.generators),
1646
+ lastInsertId: node.lastInsertId
1626
1647
  };
1627
1648
  }
1628
1649
  case "seq": {
@@ -1632,9 +1653,6 @@ var QueryInterpreter = class _QueryInterpreter {
1632
1653
  }
1633
1654
  return result ?? { value: void 0 };
1634
1655
  }
1635
- case "get": {
1636
- return { value: context.scope[node.args.name] };
1637
- }
1638
1656
  case "let": {
1639
1657
  const nestedScope = Object.create(context.scope);
1640
1658
  for (const binding of node.args.bindings) {
@@ -1643,15 +1661,6 @@ var QueryInterpreter = class _QueryInterpreter {
1643
1661
  }
1644
1662
  return this.interpretNode(node.args.expr, { ...context, scope: nestedScope });
1645
1663
  }
1646
- case "getFirstNonEmpty": {
1647
- for (const name of node.args.names) {
1648
- const value = context.scope[name];
1649
- if (!isEmpty(value)) {
1650
- return { value };
1651
- }
1652
- }
1653
- return { value: [] };
1654
- }
1655
1664
  case "concat": {
1656
1665
  const parts = await Promise.all(
1657
1666
  node.args.map((arg) => this.interpretNode(arg, context).then((res) => res.value))
@@ -1698,7 +1707,7 @@ var QueryInterpreter = class _QueryInterpreter {
1698
1707
  if (results === void 0) {
1699
1708
  results = result;
1700
1709
  } else {
1701
- results.rows.push(...result.rows);
1710
+ appendToArray(results.rows, result.rows);
1702
1711
  results.lastInsertId = result.lastInsertId;
1703
1712
  }
1704
1713
  }
@@ -1778,9 +1787,6 @@ var QueryInterpreter = class _QueryInterpreter {
1778
1787
  return await this.interpretNode(node.args.else, context);
1779
1788
  }
1780
1789
  }
1781
- case "unit": {
1782
- return { value: void 0 };
1783
- }
1784
1790
  case "diff": {
1785
1791
  const { value: from } = await this.interpretNode(node.args.from, context);
1786
1792
  const { value: to } = await this.interpretNode(node.args.to, context);
@@ -1810,6 +1816,139 @@ var QueryInterpreter = class _QueryInterpreter {
1810
1816
  }
1811
1817
  return { value: record, lastInsertId };
1812
1818
  }
1819
+ default:
1820
+ return this.#interpretPureNode(node, context.scope, context.generators);
1821
+ }
1822
+ }
1823
+ #interpretPureNode(node, scope, generators) {
1824
+ switch (node.type) {
1825
+ case "value": {
1826
+ return { value: evaluateArg(node.args, scope, generators), lastInsertId: node.lastInsertId };
1827
+ }
1828
+ case "seq": {
1829
+ let result;
1830
+ for (const arg of node.args) {
1831
+ result = this.#interpretPureNode(arg, scope, generators);
1832
+ }
1833
+ return result ?? { value: void 0 };
1834
+ }
1835
+ case "get": {
1836
+ return { value: scope[node.args.name] };
1837
+ }
1838
+ case "let": {
1839
+ const nestedScope = Object.create(scope);
1840
+ for (const binding of node.args.bindings) {
1841
+ const { value } = this.#interpretPureNode(binding.expr, nestedScope, generators);
1842
+ nestedScope[binding.name] = value;
1843
+ }
1844
+ return this.#interpretPureNode(node.args.expr, nestedScope, generators);
1845
+ }
1846
+ case "getFirstNonEmpty": {
1847
+ for (const name of node.args.names) {
1848
+ const value = scope[name];
1849
+ if (!isEmpty(value)) {
1850
+ return { value };
1851
+ }
1852
+ }
1853
+ return { value: [] };
1854
+ }
1855
+ case "concat": {
1856
+ const parts = node.args.map((arg) => this.#interpretPureNode(arg, scope, generators).value);
1857
+ return {
1858
+ value: parts.length > 0 ? parts.reduce((acc, part) => acc.concat(asList(part)), []) : []
1859
+ };
1860
+ }
1861
+ case "sum": {
1862
+ const parts = node.args.map((arg) => this.#interpretPureNode(arg, scope, generators).value);
1863
+ return {
1864
+ value: parts.length > 0 ? parts.reduce((acc, part) => asNumber2(acc) + asNumber2(part)) : 0
1865
+ };
1866
+ }
1867
+ case "reverse": {
1868
+ const { value, lastInsertId } = this.#interpretPureNode(node.args, scope, generators);
1869
+ return { value: Array.isArray(value) ? value.reverse() : value, lastInsertId };
1870
+ }
1871
+ case "unique": {
1872
+ const { value, lastInsertId } = this.#interpretPureNode(node.args, scope, generators);
1873
+ if (!Array.isArray(value)) {
1874
+ return { value, lastInsertId };
1875
+ }
1876
+ if (value.length > 1) {
1877
+ throw new Error(`Expected zero or one element, got ${value.length}`);
1878
+ }
1879
+ return { value: value[0] ?? null, lastInsertId };
1880
+ }
1881
+ case "required": {
1882
+ const { value, lastInsertId } = this.#interpretPureNode(node.args, scope, generators);
1883
+ if (isEmpty(value)) {
1884
+ throw new Error("Required value is empty");
1885
+ }
1886
+ return { value, lastInsertId };
1887
+ }
1888
+ case "mapField": {
1889
+ const { value, lastInsertId } = this.#interpretPureNode(node.args.records, scope, generators);
1890
+ return { value: mapField2(value, node.args.field), lastInsertId };
1891
+ }
1892
+ case "join": {
1893
+ const { value: parent, lastInsertId } = this.#interpretPureNode(node.args.parent, scope, generators);
1894
+ if (parent === null) {
1895
+ return { value: null, lastInsertId };
1896
+ }
1897
+ const children = node.args.children.map((joinExpr) => ({
1898
+ joinExpr,
1899
+ childRecords: this.#interpretPureNode(joinExpr.child, scope, generators).value
1900
+ }));
1901
+ return { value: attachChildrenToParents(parent, children, node.args.canAssumeStrictEquality), lastInsertId };
1902
+ }
1903
+ case "dataMap": {
1904
+ const { value, lastInsertId } = this.#interpretPureNode(node.args.expr, scope, generators);
1905
+ return { value: applyDataMap(value, node.args.structure, node.args.enums), lastInsertId };
1906
+ }
1907
+ case "validate": {
1908
+ const { value, lastInsertId } = this.#interpretPureNode(node.args.expr, scope, generators);
1909
+ performValidation(value, node.args.rules, node.args);
1910
+ return { value, lastInsertId };
1911
+ }
1912
+ case "if": {
1913
+ const { value } = this.#interpretPureNode(node.args.value, scope, generators);
1914
+ if (doesSatisfyRule(value, node.args.rule)) {
1915
+ return this.#interpretPureNode(node.args.then, scope, generators);
1916
+ } else {
1917
+ return this.#interpretPureNode(node.args.else, scope, generators);
1918
+ }
1919
+ }
1920
+ case "unit": {
1921
+ return { value: void 0 };
1922
+ }
1923
+ case "diff": {
1924
+ const { value: from } = this.#interpretPureNode(node.args.from, scope, generators);
1925
+ const { value: to } = this.#interpretPureNode(node.args.to, scope, generators);
1926
+ const keyGetter = (item) => item !== null ? getRecordKey(asRecord(item), node.args.fields) : null;
1927
+ const toSet = new Set(asList(to).map(keyGetter));
1928
+ return { value: asList(from).filter((item) => !toSet.has(keyGetter(item))) };
1929
+ }
1930
+ case "process": {
1931
+ const { value, lastInsertId } = this.#interpretPureNode(node.args.expr, scope, generators);
1932
+ const ops = cloneObject(node.args.operations);
1933
+ evaluateProcessingParameters(ops, scope, generators);
1934
+ return { value: processRecords(value, ops), lastInsertId };
1935
+ }
1936
+ case "initializeRecord": {
1937
+ const { lastInsertId } = this.#interpretPureNode(node.args.expr, scope, generators);
1938
+ const record = {};
1939
+ for (const [key, initializer] of Object.entries(node.args.fields)) {
1940
+ record[key] = evalFieldInitializer(initializer, lastInsertId, scope, generators);
1941
+ }
1942
+ return { value: record, lastInsertId };
1943
+ }
1944
+ case "mapRecord": {
1945
+ const { value, lastInsertId } = this.#interpretPureNode(node.args.expr, scope, generators);
1946
+ const record = value === null ? {} : asRecord(value);
1947
+ for (const [key, entry] of Object.entries(node.args.fields)) {
1948
+ record[key] = evalFieldOperation(entry, record[key], scope, generators);
1949
+ }
1950
+ return { value: record, lastInsertId };
1951
+ }
1813
1952
  default:
1814
1953
  assertNever(node, `Unexpected node type: ${node.type}`);
1815
1954
  }
@@ -1987,6 +2126,112 @@ function evalFieldOperation(op, value, scope, generators) {
1987
2126
  assertNever(op, `Unexpected field operation type: ${op["type"]}`);
1988
2127
  }
1989
2128
  }
2129
+ function purifyQueryPlan(node, evalNode) {
2130
+ const impureNode = findUniqueUnconditionalImpureNode(node);
2131
+ if (!impureNode) {
2132
+ return void 0;
2133
+ }
2134
+ return evalNode(impureNode).then((result) => {
2135
+ const evaluated = {
2136
+ type: "value",
2137
+ args: result.value,
2138
+ lastInsertId: result.lastInsertId
2139
+ };
2140
+ const purified = replaceImpureNode(node, impureNode, evaluated);
2141
+ if (!purified) {
2142
+ throw new Error("Could not substitute the evaluated impure node into the query plan");
2143
+ }
2144
+ return purified;
2145
+ });
2146
+ }
2147
+ function replaceImpureNode(node, target, replacement) {
2148
+ if (node === target) {
2149
+ return replacement;
2150
+ }
2151
+ switch (node.type) {
2152
+ case "seq":
2153
+ case "sum":
2154
+ case "concat": {
2155
+ for (let i = 0; i < node.args.length; i++) {
2156
+ const child = replaceImpureNode(node.args[i], target, replacement);
2157
+ if (child) {
2158
+ return { ...node, args: node.args.map((arg, j) => j === i ? child : arg) };
2159
+ }
2160
+ }
2161
+ return void 0;
2162
+ }
2163
+ case "dataMap":
2164
+ case "validate":
2165
+ case "initializeRecord":
2166
+ case "mapRecord":
2167
+ case "process": {
2168
+ const expr = replaceImpureNode(node.args.expr, target, replacement);
2169
+ return expr && { ...node, args: { ...node.args, expr } };
2170
+ }
2171
+ case "mapField": {
2172
+ const records = replaceImpureNode(node.args.records, target, replacement);
2173
+ return records && { ...node, args: { ...node.args, records } };
2174
+ }
2175
+ case "reverse":
2176
+ case "unique":
2177
+ case "required": {
2178
+ const args = replaceImpureNode(node.args, target, replacement);
2179
+ return args && { ...node, args };
2180
+ }
2181
+ default:
2182
+ return void 0;
2183
+ }
2184
+ }
2185
+ function findUniqueUnconditionalImpureNode(node) {
2186
+ switch (node.type) {
2187
+ case "query":
2188
+ case "execute":
2189
+ return node;
2190
+ case "seq":
2191
+ case "sum":
2192
+ case "concat": {
2193
+ let found = void 0;
2194
+ for (const child of node.args) {
2195
+ const childFound = findUniqueUnconditionalImpureNode(child);
2196
+ if (childFound === null) {
2197
+ return null;
2198
+ }
2199
+ if (childFound) {
2200
+ if (found) {
2201
+ return null;
2202
+ }
2203
+ found = childFound;
2204
+ }
2205
+ }
2206
+ return found;
2207
+ }
2208
+ case "dataMap":
2209
+ case "validate":
2210
+ case "initializeRecord":
2211
+ case "mapRecord":
2212
+ case "process":
2213
+ return findUniqueUnconditionalImpureNode(node.args.expr);
2214
+ case "mapField":
2215
+ return findUniqueUnconditionalImpureNode(node.args.records);
2216
+ case "reverse":
2217
+ case "unique":
2218
+ case "required":
2219
+ return findUniqueUnconditionalImpureNode(node.args);
2220
+ case "let":
2221
+ case "join":
2222
+ case "diff":
2223
+ case "if":
2224
+ case "transaction":
2225
+ return null;
2226
+ case "value":
2227
+ case "get":
2228
+ case "getFirstNonEmpty":
2229
+ case "unit":
2230
+ return void 0;
2231
+ default:
2232
+ assertNever(node, `Unexpected node type: ${node.type}`);
2233
+ }
2234
+ }
1990
2235
  function applyComments(query, sqlCommenter) {
1991
2236
  if (!sqlCommenter || sqlCommenter.plugins.length === 0) {
1992
2237
  return query;