@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.d.mts +123 -91
- package/dist/index.d.ts +123 -91
- package/dist/index.js +268 -23
- package/dist/index.mjs +268 -23
- package/dist/interpreter/query-interpreter.d.ts +20 -1
- package/dist/interpreter/query-interpreter.test.d.ts +1 -0
- package/dist/query-plan.d.ts +61 -31
- package/dist/utils.d.ts +5 -0
- package/package.json +9 -9
package/dist/index.mjs
CHANGED
|
@@ -92,6 +92,16 @@ function safeJsonStringify(obj) {
|
|
|
92
92
|
return val;
|
|
93
93
|
});
|
|
94
94
|
}
|
|
95
|
+
var MAX_PUSH_SPREAD_ARGS = 8192;
|
|
96
|
+
function appendToArray(target, source) {
|
|
97
|
+
if (source.length <= MAX_PUSH_SPREAD_ARGS) {
|
|
98
|
+
target.push(...source);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
for (let i = 0; i < source.length; i += MAX_PUSH_SPREAD_ARGS) {
|
|
102
|
+
target.push(...source.slice(i, i + MAX_PUSH_SPREAD_ARGS));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
95
105
|
|
|
96
106
|
// src/json-protocol.ts
|
|
97
107
|
function normalizeJsonProtocolValues(result) {
|
|
@@ -1095,8 +1105,9 @@ function renderTemplateSql(fragments, placeholderFormat, params, argTypes) {
|
|
|
1095
1105
|
if (fragment.type === "stringChunk") {
|
|
1096
1106
|
continue;
|
|
1097
1107
|
}
|
|
1098
|
-
const
|
|
1099
|
-
const added =
|
|
1108
|
+
const fragmentParams = Array.from(flattenedFragmentParams(fragment));
|
|
1109
|
+
const added = fragmentParams.length;
|
|
1110
|
+
appendToArray(flattenedParams, fragmentParams);
|
|
1100
1111
|
if (fragment.argType.arity === "tuple") {
|
|
1101
1112
|
if (added % fragment.argType.elements.length !== 0) {
|
|
1102
1113
|
throw new Error(
|
|
@@ -1559,17 +1570,27 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1559
1570
|
});
|
|
1560
1571
|
}
|
|
1561
1572
|
async run(queryPlan, options) {
|
|
1562
|
-
const
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1573
|
+
const generators = this.#generators.snapshot();
|
|
1574
|
+
const context = { ...options, generators };
|
|
1575
|
+
const purified = purifyQueryPlan(queryPlan, (node) => this.interpretNode(node, context))?.catch(
|
|
1576
|
+
(e) => rethrowAsUserFacing(e)
|
|
1577
|
+
);
|
|
1578
|
+
if (purified) {
|
|
1579
|
+
try {
|
|
1580
|
+
return this.#interpretPureNode(await purified, context.scope, generators).value;
|
|
1581
|
+
} catch (e) {
|
|
1582
|
+
rethrowAsUserFacing(e);
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
const { value } = await this.interpretNode(queryPlan, context).catch((e) => rethrowAsUserFacing(e));
|
|
1566
1586
|
return value;
|
|
1567
1587
|
}
|
|
1568
1588
|
async interpretNode(node, context) {
|
|
1569
1589
|
switch (node.type) {
|
|
1570
1590
|
case "value": {
|
|
1571
1591
|
return {
|
|
1572
|
-
value: evaluateArg(node.args, context.scope, context.generators)
|
|
1592
|
+
value: evaluateArg(node.args, context.scope, context.generators),
|
|
1593
|
+
lastInsertId: node.lastInsertId
|
|
1573
1594
|
};
|
|
1574
1595
|
}
|
|
1575
1596
|
case "seq": {
|
|
@@ -1579,9 +1600,6 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1579
1600
|
}
|
|
1580
1601
|
return result ?? { value: void 0 };
|
|
1581
1602
|
}
|
|
1582
|
-
case "get": {
|
|
1583
|
-
return { value: context.scope[node.args.name] };
|
|
1584
|
-
}
|
|
1585
1603
|
case "let": {
|
|
1586
1604
|
const nestedScope = Object.create(context.scope);
|
|
1587
1605
|
for (const binding of node.args.bindings) {
|
|
@@ -1590,15 +1608,6 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1590
1608
|
}
|
|
1591
1609
|
return this.interpretNode(node.args.expr, { ...context, scope: nestedScope });
|
|
1592
1610
|
}
|
|
1593
|
-
case "getFirstNonEmpty": {
|
|
1594
|
-
for (const name of node.args.names) {
|
|
1595
|
-
const value = context.scope[name];
|
|
1596
|
-
if (!isEmpty(value)) {
|
|
1597
|
-
return { value };
|
|
1598
|
-
}
|
|
1599
|
-
}
|
|
1600
|
-
return { value: [] };
|
|
1601
|
-
}
|
|
1602
1611
|
case "concat": {
|
|
1603
1612
|
const parts = await Promise.all(
|
|
1604
1613
|
node.args.map((arg) => this.interpretNode(arg, context).then((res) => res.value))
|
|
@@ -1645,7 +1654,7 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1645
1654
|
if (results === void 0) {
|
|
1646
1655
|
results = result;
|
|
1647
1656
|
} else {
|
|
1648
|
-
results.rows
|
|
1657
|
+
appendToArray(results.rows, result.rows);
|
|
1649
1658
|
results.lastInsertId = result.lastInsertId;
|
|
1650
1659
|
}
|
|
1651
1660
|
}
|
|
@@ -1725,9 +1734,6 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1725
1734
|
return await this.interpretNode(node.args.else, context);
|
|
1726
1735
|
}
|
|
1727
1736
|
}
|
|
1728
|
-
case "unit": {
|
|
1729
|
-
return { value: void 0 };
|
|
1730
|
-
}
|
|
1731
1737
|
case "diff": {
|
|
1732
1738
|
const { value: from } = await this.interpretNode(node.args.from, context);
|
|
1733
1739
|
const { value: to } = await this.interpretNode(node.args.to, context);
|
|
@@ -1757,6 +1763,139 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
1757
1763
|
}
|
|
1758
1764
|
return { value: record, lastInsertId };
|
|
1759
1765
|
}
|
|
1766
|
+
default:
|
|
1767
|
+
return this.#interpretPureNode(node, context.scope, context.generators);
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
#interpretPureNode(node, scope, generators) {
|
|
1771
|
+
switch (node.type) {
|
|
1772
|
+
case "value": {
|
|
1773
|
+
return { value: evaluateArg(node.args, scope, generators), lastInsertId: node.lastInsertId };
|
|
1774
|
+
}
|
|
1775
|
+
case "seq": {
|
|
1776
|
+
let result;
|
|
1777
|
+
for (const arg of node.args) {
|
|
1778
|
+
result = this.#interpretPureNode(arg, scope, generators);
|
|
1779
|
+
}
|
|
1780
|
+
return result ?? { value: void 0 };
|
|
1781
|
+
}
|
|
1782
|
+
case "get": {
|
|
1783
|
+
return { value: scope[node.args.name] };
|
|
1784
|
+
}
|
|
1785
|
+
case "let": {
|
|
1786
|
+
const nestedScope = Object.create(scope);
|
|
1787
|
+
for (const binding of node.args.bindings) {
|
|
1788
|
+
const { value } = this.#interpretPureNode(binding.expr, nestedScope, generators);
|
|
1789
|
+
nestedScope[binding.name] = value;
|
|
1790
|
+
}
|
|
1791
|
+
return this.#interpretPureNode(node.args.expr, nestedScope, generators);
|
|
1792
|
+
}
|
|
1793
|
+
case "getFirstNonEmpty": {
|
|
1794
|
+
for (const name of node.args.names) {
|
|
1795
|
+
const value = scope[name];
|
|
1796
|
+
if (!isEmpty(value)) {
|
|
1797
|
+
return { value };
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
return { value: [] };
|
|
1801
|
+
}
|
|
1802
|
+
case "concat": {
|
|
1803
|
+
const parts = node.args.map((arg) => this.#interpretPureNode(arg, scope, generators).value);
|
|
1804
|
+
return {
|
|
1805
|
+
value: parts.length > 0 ? parts.reduce((acc, part) => acc.concat(asList(part)), []) : []
|
|
1806
|
+
};
|
|
1807
|
+
}
|
|
1808
|
+
case "sum": {
|
|
1809
|
+
const parts = node.args.map((arg) => this.#interpretPureNode(arg, scope, generators).value);
|
|
1810
|
+
return {
|
|
1811
|
+
value: parts.length > 0 ? parts.reduce((acc, part) => asNumber2(acc) + asNumber2(part)) : 0
|
|
1812
|
+
};
|
|
1813
|
+
}
|
|
1814
|
+
case "reverse": {
|
|
1815
|
+
const { value, lastInsertId } = this.#interpretPureNode(node.args, scope, generators);
|
|
1816
|
+
return { value: Array.isArray(value) ? value.reverse() : value, lastInsertId };
|
|
1817
|
+
}
|
|
1818
|
+
case "unique": {
|
|
1819
|
+
const { value, lastInsertId } = this.#interpretPureNode(node.args, scope, generators);
|
|
1820
|
+
if (!Array.isArray(value)) {
|
|
1821
|
+
return { value, lastInsertId };
|
|
1822
|
+
}
|
|
1823
|
+
if (value.length > 1) {
|
|
1824
|
+
throw new Error(`Expected zero or one element, got ${value.length}`);
|
|
1825
|
+
}
|
|
1826
|
+
return { value: value[0] ?? null, lastInsertId };
|
|
1827
|
+
}
|
|
1828
|
+
case "required": {
|
|
1829
|
+
const { value, lastInsertId } = this.#interpretPureNode(node.args, scope, generators);
|
|
1830
|
+
if (isEmpty(value)) {
|
|
1831
|
+
throw new Error("Required value is empty");
|
|
1832
|
+
}
|
|
1833
|
+
return { value, lastInsertId };
|
|
1834
|
+
}
|
|
1835
|
+
case "mapField": {
|
|
1836
|
+
const { value, lastInsertId } = this.#interpretPureNode(node.args.records, scope, generators);
|
|
1837
|
+
return { value: mapField2(value, node.args.field), lastInsertId };
|
|
1838
|
+
}
|
|
1839
|
+
case "join": {
|
|
1840
|
+
const { value: parent, lastInsertId } = this.#interpretPureNode(node.args.parent, scope, generators);
|
|
1841
|
+
if (parent === null) {
|
|
1842
|
+
return { value: null, lastInsertId };
|
|
1843
|
+
}
|
|
1844
|
+
const children = node.args.children.map((joinExpr) => ({
|
|
1845
|
+
joinExpr,
|
|
1846
|
+
childRecords: this.#interpretPureNode(joinExpr.child, scope, generators).value
|
|
1847
|
+
}));
|
|
1848
|
+
return { value: attachChildrenToParents(parent, children, node.args.canAssumeStrictEquality), lastInsertId };
|
|
1849
|
+
}
|
|
1850
|
+
case "dataMap": {
|
|
1851
|
+
const { value, lastInsertId } = this.#interpretPureNode(node.args.expr, scope, generators);
|
|
1852
|
+
return { value: applyDataMap(value, node.args.structure, node.args.enums), lastInsertId };
|
|
1853
|
+
}
|
|
1854
|
+
case "validate": {
|
|
1855
|
+
const { value, lastInsertId } = this.#interpretPureNode(node.args.expr, scope, generators);
|
|
1856
|
+
performValidation(value, node.args.rules, node.args);
|
|
1857
|
+
return { value, lastInsertId };
|
|
1858
|
+
}
|
|
1859
|
+
case "if": {
|
|
1860
|
+
const { value } = this.#interpretPureNode(node.args.value, scope, generators);
|
|
1861
|
+
if (doesSatisfyRule(value, node.args.rule)) {
|
|
1862
|
+
return this.#interpretPureNode(node.args.then, scope, generators);
|
|
1863
|
+
} else {
|
|
1864
|
+
return this.#interpretPureNode(node.args.else, scope, generators);
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
case "unit": {
|
|
1868
|
+
return { value: void 0 };
|
|
1869
|
+
}
|
|
1870
|
+
case "diff": {
|
|
1871
|
+
const { value: from } = this.#interpretPureNode(node.args.from, scope, generators);
|
|
1872
|
+
const { value: to } = this.#interpretPureNode(node.args.to, scope, generators);
|
|
1873
|
+
const keyGetter = (item) => item !== null ? getRecordKey(asRecord(item), node.args.fields) : null;
|
|
1874
|
+
const toSet = new Set(asList(to).map(keyGetter));
|
|
1875
|
+
return { value: asList(from).filter((item) => !toSet.has(keyGetter(item))) };
|
|
1876
|
+
}
|
|
1877
|
+
case "process": {
|
|
1878
|
+
const { value, lastInsertId } = this.#interpretPureNode(node.args.expr, scope, generators);
|
|
1879
|
+
const ops = cloneObject(node.args.operations);
|
|
1880
|
+
evaluateProcessingParameters(ops, scope, generators);
|
|
1881
|
+
return { value: processRecords(value, ops), lastInsertId };
|
|
1882
|
+
}
|
|
1883
|
+
case "initializeRecord": {
|
|
1884
|
+
const { lastInsertId } = this.#interpretPureNode(node.args.expr, scope, generators);
|
|
1885
|
+
const record = {};
|
|
1886
|
+
for (const [key, initializer] of Object.entries(node.args.fields)) {
|
|
1887
|
+
record[key] = evalFieldInitializer(initializer, lastInsertId, scope, generators);
|
|
1888
|
+
}
|
|
1889
|
+
return { value: record, lastInsertId };
|
|
1890
|
+
}
|
|
1891
|
+
case "mapRecord": {
|
|
1892
|
+
const { value, lastInsertId } = this.#interpretPureNode(node.args.expr, scope, generators);
|
|
1893
|
+
const record = value === null ? {} : asRecord(value);
|
|
1894
|
+
for (const [key, entry] of Object.entries(node.args.fields)) {
|
|
1895
|
+
record[key] = evalFieldOperation(entry, record[key], scope, generators);
|
|
1896
|
+
}
|
|
1897
|
+
return { value: record, lastInsertId };
|
|
1898
|
+
}
|
|
1760
1899
|
default:
|
|
1761
1900
|
assertNever(node, `Unexpected node type: ${node.type}`);
|
|
1762
1901
|
}
|
|
@@ -1934,6 +2073,112 @@ function evalFieldOperation(op, value, scope, generators) {
|
|
|
1934
2073
|
assertNever(op, `Unexpected field operation type: ${op["type"]}`);
|
|
1935
2074
|
}
|
|
1936
2075
|
}
|
|
2076
|
+
function purifyQueryPlan(node, evalNode) {
|
|
2077
|
+
const impureNode = findUniqueUnconditionalImpureNode(node);
|
|
2078
|
+
if (!impureNode) {
|
|
2079
|
+
return void 0;
|
|
2080
|
+
}
|
|
2081
|
+
return evalNode(impureNode).then((result) => {
|
|
2082
|
+
const evaluated = {
|
|
2083
|
+
type: "value",
|
|
2084
|
+
args: result.value,
|
|
2085
|
+
lastInsertId: result.lastInsertId
|
|
2086
|
+
};
|
|
2087
|
+
const purified = replaceImpureNode(node, impureNode, evaluated);
|
|
2088
|
+
if (!purified) {
|
|
2089
|
+
throw new Error("Could not substitute the evaluated impure node into the query plan");
|
|
2090
|
+
}
|
|
2091
|
+
return purified;
|
|
2092
|
+
});
|
|
2093
|
+
}
|
|
2094
|
+
function replaceImpureNode(node, target, replacement) {
|
|
2095
|
+
if (node === target) {
|
|
2096
|
+
return replacement;
|
|
2097
|
+
}
|
|
2098
|
+
switch (node.type) {
|
|
2099
|
+
case "seq":
|
|
2100
|
+
case "sum":
|
|
2101
|
+
case "concat": {
|
|
2102
|
+
for (let i = 0; i < node.args.length; i++) {
|
|
2103
|
+
const child = replaceImpureNode(node.args[i], target, replacement);
|
|
2104
|
+
if (child) {
|
|
2105
|
+
return { ...node, args: node.args.map((arg, j) => j === i ? child : arg) };
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
return void 0;
|
|
2109
|
+
}
|
|
2110
|
+
case "dataMap":
|
|
2111
|
+
case "validate":
|
|
2112
|
+
case "initializeRecord":
|
|
2113
|
+
case "mapRecord":
|
|
2114
|
+
case "process": {
|
|
2115
|
+
const expr = replaceImpureNode(node.args.expr, target, replacement);
|
|
2116
|
+
return expr && { ...node, args: { ...node.args, expr } };
|
|
2117
|
+
}
|
|
2118
|
+
case "mapField": {
|
|
2119
|
+
const records = replaceImpureNode(node.args.records, target, replacement);
|
|
2120
|
+
return records && { ...node, args: { ...node.args, records } };
|
|
2121
|
+
}
|
|
2122
|
+
case "reverse":
|
|
2123
|
+
case "unique":
|
|
2124
|
+
case "required": {
|
|
2125
|
+
const args = replaceImpureNode(node.args, target, replacement);
|
|
2126
|
+
return args && { ...node, args };
|
|
2127
|
+
}
|
|
2128
|
+
default:
|
|
2129
|
+
return void 0;
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
function findUniqueUnconditionalImpureNode(node) {
|
|
2133
|
+
switch (node.type) {
|
|
2134
|
+
case "query":
|
|
2135
|
+
case "execute":
|
|
2136
|
+
return node;
|
|
2137
|
+
case "seq":
|
|
2138
|
+
case "sum":
|
|
2139
|
+
case "concat": {
|
|
2140
|
+
let found = void 0;
|
|
2141
|
+
for (const child of node.args) {
|
|
2142
|
+
const childFound = findUniqueUnconditionalImpureNode(child);
|
|
2143
|
+
if (childFound === null) {
|
|
2144
|
+
return null;
|
|
2145
|
+
}
|
|
2146
|
+
if (childFound) {
|
|
2147
|
+
if (found) {
|
|
2148
|
+
return null;
|
|
2149
|
+
}
|
|
2150
|
+
found = childFound;
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
return found;
|
|
2154
|
+
}
|
|
2155
|
+
case "dataMap":
|
|
2156
|
+
case "validate":
|
|
2157
|
+
case "initializeRecord":
|
|
2158
|
+
case "mapRecord":
|
|
2159
|
+
case "process":
|
|
2160
|
+
return findUniqueUnconditionalImpureNode(node.args.expr);
|
|
2161
|
+
case "mapField":
|
|
2162
|
+
return findUniqueUnconditionalImpureNode(node.args.records);
|
|
2163
|
+
case "reverse":
|
|
2164
|
+
case "unique":
|
|
2165
|
+
case "required":
|
|
2166
|
+
return findUniqueUnconditionalImpureNode(node.args);
|
|
2167
|
+
case "let":
|
|
2168
|
+
case "join":
|
|
2169
|
+
case "diff":
|
|
2170
|
+
case "if":
|
|
2171
|
+
case "transaction":
|
|
2172
|
+
return null;
|
|
2173
|
+
case "value":
|
|
2174
|
+
case "get":
|
|
2175
|
+
case "getFirstNonEmpty":
|
|
2176
|
+
case "unit":
|
|
2177
|
+
return void 0;
|
|
2178
|
+
default:
|
|
2179
|
+
assertNever(node, `Unexpected node type: ${node.type}`);
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
1937
2182
|
function applyComments(query, sqlCommenter) {
|
|
1938
2183
|
if (!sqlCommenter || sqlCommenter.plugins.length === 0) {
|
|
1939
2184
|
return query;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ConnectionInfo, SqlQueryable, SqlResultSet } from '@prisma/driver-adapter-utils';
|
|
2
2
|
import type { SqlCommenterPlugin, SqlCommenterQueryInfo } from '@prisma/sqlcommenter';
|
|
3
3
|
import { QueryEvent } from '../events';
|
|
4
|
-
import { QueryPlanNode } from '../query-plan';
|
|
4
|
+
import { ImpureQueryPlanNode, PureQueryPlanNode, 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';
|
|
@@ -43,3 +43,22 @@ export declare class QueryInterpreter {
|
|
|
43
43
|
run(queryPlan: DeepReadonly<QueryPlanNode>, options: QueryRuntimeOptions): Promise<unknown>;
|
|
44
44
|
private interpretNode;
|
|
45
45
|
}
|
|
46
|
+
type IntermediateValue = {
|
|
47
|
+
value: Value;
|
|
48
|
+
lastInsertId?: string;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Attempts to convert a query plan into a pure one by finding the single impure node
|
|
52
|
+
* that is unconditionally evaluated exactly once, evaluating it eagerly via `evalNode`,
|
|
53
|
+
* and substituting its result into the plan as a constant. The remaining plan can then
|
|
54
|
+
* be interpreted synchronously.
|
|
55
|
+
*
|
|
56
|
+
* Returns `undefined` if the plan cannot be purified this way (it contains no impure
|
|
57
|
+
* nodes, more than one of them, or unsupported constructs).
|
|
58
|
+
*
|
|
59
|
+
* Query plans are cached and shared between requests, so the input plan is never
|
|
60
|
+
* modified; the returned plan shares all unaffected subtrees with the input and only
|
|
61
|
+
* copies the nodes on the path to the substituted one.
|
|
62
|
+
*/
|
|
63
|
+
export declare function purifyQueryPlan(node: DeepReadonly<QueryPlanNode>, evalNode: (node: DeepReadonly<ImpureQueryPlanNode>) => Promise<IntermediateValue>): Promise<DeepReadonly<PureQueryPlanNode>> | undefined;
|
|
64
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/query-plan.d.ts
CHANGED
|
@@ -76,12 +76,24 @@ export type JoinExpression = {
|
|
|
76
76
|
parentField: string;
|
|
77
77
|
isRelationUnique: boolean;
|
|
78
78
|
};
|
|
79
|
-
|
|
79
|
+
/**
|
|
80
|
+
* Query plan nodes that are free of side effects and can be interpreted synchronously
|
|
81
|
+
* without touching the database. The `Rest` parameter controls what other nodes may
|
|
82
|
+
* appear in child positions: with the default `never` the tree is fully pure, while
|
|
83
|
+
* `PureQueryPlanNode<ImpureQueryPlanNode>` describes a tree of pure nodes that may
|
|
84
|
+
* contain impure nodes anywhere inside.
|
|
85
|
+
*/
|
|
86
|
+
export type PureQueryPlanNode<Rest = never> = {
|
|
80
87
|
type: 'value';
|
|
81
88
|
args: PrismaValue;
|
|
89
|
+
/**
|
|
90
|
+
* Present when this node is the result of evaluating an impure node during
|
|
91
|
+
* query plan purification. Never produced by the query compiler.
|
|
92
|
+
*/
|
|
93
|
+
lastInsertId?: string;
|
|
82
94
|
} | {
|
|
83
95
|
type: 'seq';
|
|
84
|
-
args:
|
|
96
|
+
args: (PureQueryPlanNode<Rest> | Rest)[];
|
|
85
97
|
} | {
|
|
86
98
|
type: 'get';
|
|
87
99
|
args: {
|
|
@@ -90,100 +102,118 @@ export type QueryPlanNode = {
|
|
|
90
102
|
} | {
|
|
91
103
|
type: 'let';
|
|
92
104
|
args: {
|
|
93
|
-
bindings:
|
|
94
|
-
|
|
105
|
+
bindings: {
|
|
106
|
+
name: string;
|
|
107
|
+
expr: PureQueryPlanNode<Rest> | Rest;
|
|
108
|
+
}[];
|
|
109
|
+
expr: PureQueryPlanNode<Rest> | Rest;
|
|
95
110
|
};
|
|
96
111
|
} | {
|
|
97
112
|
type: 'getFirstNonEmpty';
|
|
98
113
|
args: {
|
|
99
114
|
names: string[];
|
|
100
115
|
};
|
|
101
|
-
} | {
|
|
102
|
-
type: 'query';
|
|
103
|
-
args: QueryPlanDbQuery;
|
|
104
|
-
} | {
|
|
105
|
-
type: 'execute';
|
|
106
|
-
args: QueryPlanDbQuery;
|
|
107
116
|
} | {
|
|
108
117
|
type: 'reverse';
|
|
109
|
-
args:
|
|
118
|
+
args: PureQueryPlanNode<Rest> | Rest;
|
|
110
119
|
} | {
|
|
111
120
|
type: 'sum';
|
|
112
|
-
args:
|
|
121
|
+
args: (PureQueryPlanNode<Rest> | Rest)[];
|
|
113
122
|
} | {
|
|
114
123
|
type: 'concat';
|
|
115
|
-
args:
|
|
124
|
+
args: (PureQueryPlanNode<Rest> | Rest)[];
|
|
116
125
|
} | {
|
|
117
126
|
type: 'unique';
|
|
118
|
-
args:
|
|
127
|
+
args: PureQueryPlanNode<Rest> | Rest;
|
|
119
128
|
} | {
|
|
120
129
|
type: 'required';
|
|
121
|
-
args:
|
|
130
|
+
args: PureQueryPlanNode<Rest> | Rest;
|
|
122
131
|
} | {
|
|
123
132
|
type: 'join';
|
|
124
133
|
args: {
|
|
125
|
-
parent:
|
|
126
|
-
children:
|
|
134
|
+
parent: PureQueryPlanNode<Rest> | Rest;
|
|
135
|
+
children: {
|
|
136
|
+
child: PureQueryPlanNode<Rest> | Rest;
|
|
137
|
+
on: [left: string, right: string][];
|
|
138
|
+
parentField: string;
|
|
139
|
+
isRelationUnique: boolean;
|
|
140
|
+
}[];
|
|
127
141
|
canAssumeStrictEquality: boolean;
|
|
128
142
|
};
|
|
129
143
|
} | {
|
|
130
144
|
type: 'mapField';
|
|
131
145
|
args: {
|
|
132
146
|
field: string;
|
|
133
|
-
records:
|
|
147
|
+
records: PureQueryPlanNode<Rest> | Rest;
|
|
134
148
|
};
|
|
135
|
-
} | {
|
|
136
|
-
type: 'transaction';
|
|
137
|
-
args: QueryPlanNode;
|
|
138
149
|
} | {
|
|
139
150
|
type: 'dataMap';
|
|
140
151
|
args: {
|
|
141
|
-
expr:
|
|
152
|
+
expr: PureQueryPlanNode<Rest> | Rest;
|
|
142
153
|
structure: ResultNode;
|
|
143
154
|
enums: Record<string, Record<string, string>>;
|
|
144
155
|
};
|
|
145
156
|
} | {
|
|
146
157
|
type: 'validate';
|
|
147
158
|
args: {
|
|
148
|
-
expr:
|
|
159
|
+
expr: PureQueryPlanNode<Rest> | Rest;
|
|
149
160
|
rules: DataRule[];
|
|
150
161
|
} & ValidationError;
|
|
151
162
|
} | {
|
|
152
163
|
type: 'if';
|
|
153
164
|
args: {
|
|
154
|
-
value:
|
|
165
|
+
value: PureQueryPlanNode<Rest> | Rest;
|
|
155
166
|
rule: DataRule;
|
|
156
|
-
then:
|
|
157
|
-
else:
|
|
167
|
+
then: PureQueryPlanNode<Rest> | Rest;
|
|
168
|
+
else: PureQueryPlanNode<Rest> | Rest;
|
|
158
169
|
};
|
|
159
170
|
} | {
|
|
160
171
|
type: 'unit';
|
|
161
172
|
} | {
|
|
162
173
|
type: 'diff';
|
|
163
174
|
args: {
|
|
164
|
-
from:
|
|
165
|
-
to:
|
|
175
|
+
from: PureQueryPlanNode<Rest> | Rest;
|
|
176
|
+
to: PureQueryPlanNode<Rest> | Rest;
|
|
166
177
|
fields: string[];
|
|
167
178
|
};
|
|
168
179
|
} | {
|
|
169
180
|
type: 'initializeRecord';
|
|
170
181
|
args: {
|
|
171
|
-
expr:
|
|
182
|
+
expr: PureQueryPlanNode<Rest> | Rest;
|
|
172
183
|
fields: Record<string, FieldInitializer>;
|
|
173
184
|
};
|
|
174
185
|
} | {
|
|
175
186
|
type: 'mapRecord';
|
|
176
187
|
args: {
|
|
177
|
-
expr:
|
|
188
|
+
expr: PureQueryPlanNode<Rest> | Rest;
|
|
178
189
|
fields: Record<string, FieldOperation>;
|
|
179
190
|
};
|
|
180
191
|
} | {
|
|
181
192
|
type: 'process';
|
|
182
193
|
args: {
|
|
183
|
-
expr:
|
|
194
|
+
expr: PureQueryPlanNode<Rest> | Rest;
|
|
184
195
|
operations: InMemoryOps;
|
|
185
196
|
};
|
|
186
197
|
};
|
|
198
|
+
/**
|
|
199
|
+
* Query plan nodes that perform database I/O: individual queries and statements,
|
|
200
|
+
* and subtrees executed within a transaction.
|
|
201
|
+
*/
|
|
202
|
+
export type ImpureQueryPlanNode = {
|
|
203
|
+
type: 'query';
|
|
204
|
+
args: QueryPlanDbQuery;
|
|
205
|
+
} | {
|
|
206
|
+
type: 'execute';
|
|
207
|
+
args: QueryPlanDbQuery;
|
|
208
|
+
} | {
|
|
209
|
+
type: 'transaction';
|
|
210
|
+
args: QueryPlanNode;
|
|
211
|
+
};
|
|
212
|
+
/**
|
|
213
|
+
* A query plan as emitted by the query compiler: a tree of pure nodes that may
|
|
214
|
+
* contain impure nodes anywhere inside.
|
|
215
|
+
*/
|
|
216
|
+
export type QueryPlanNode = ImpureQueryPlanNode | PureQueryPlanNode<ImpureQueryPlanNode>;
|
|
187
217
|
export type FieldInitializer = {
|
|
188
218
|
type: 'value';
|
|
189
219
|
value: PrismaValue;
|
package/dist/utils.d.ts
CHANGED
|
@@ -20,3 +20,8 @@ export declare function doKeysMatch(lhs: {}, rhs: {}): boolean;
|
|
|
20
20
|
* BigInt and Uint8Array values.
|
|
21
21
|
*/
|
|
22
22
|
export declare function safeJsonStringify(obj: unknown): string;
|
|
23
|
+
/**
|
|
24
|
+
* Appends all elements of `source` to `target` without spreading the whole
|
|
25
|
+
* array as call arguments, which overflows the stack for large arrays.
|
|
26
|
+
*/
|
|
27
|
+
export declare function appendToArray<T>(target: T[], source: readonly T[]): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/client-engine-runtime",
|
|
3
|
-
"version": "7.10.0-dev.
|
|
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
|
"module": "dist/index.mjs",
|
|
@@ -31,20 +31,20 @@
|
|
|
31
31
|
"nanoid": "5.1.5",
|
|
32
32
|
"ulid": "3.0.0",
|
|
33
33
|
"uuid": "14.0.0",
|
|
34
|
-
"@prisma/
|
|
35
|
-
"@prisma/
|
|
36
|
-
"@prisma/
|
|
37
|
-
"@prisma/sqlcommenter": "7.10.0-dev.
|
|
38
|
-
"@prisma/param-graph": "7.10.0-dev.
|
|
39
|
-
"@prisma/json-protocol": "7.10.0-dev.
|
|
34
|
+
"@prisma/driver-adapter-utils": "7.10.0-dev.22",
|
|
35
|
+
"@prisma/client-runtime-utils": "7.10.0-dev.22",
|
|
36
|
+
"@prisma/debug": "7.10.0-dev.22",
|
|
37
|
+
"@prisma/sqlcommenter": "7.10.0-dev.22",
|
|
38
|
+
"@prisma/param-graph": "7.10.0-dev.22",
|
|
39
|
+
"@prisma/json-protocol": "7.10.0-dev.22"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@codspeed/benchmark.js-plugin": "4.0.0",
|
|
43
43
|
"@types/benchmark": "2.1.5",
|
|
44
44
|
"@types/node": "~20.19.24",
|
|
45
45
|
"benchmark": "2.1.4",
|
|
46
|
-
"@prisma/param-graph-builder": "7.10.0-dev.
|
|
47
|
-
"@prisma/get-dmmf": "7.10.0-dev.
|
|
46
|
+
"@prisma/param-graph-builder": "7.10.0-dev.22",
|
|
47
|
+
"@prisma/get-dmmf": "7.10.0-dev.22"
|
|
48
48
|
},
|
|
49
49
|
"files": [
|
|
50
50
|
"dist"
|