@prisma/client-engine-runtime 6.6.0-dev.7 → 6.6.0-dev.70
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/QueryPlan.d.ts +19 -1
- package/dist/crypto.d.ts +1 -0
- package/dist/index.d.mts +28 -16
- package/dist/index.d.ts +28 -16
- package/dist/index.js +113 -218
- package/dist/index.mjs +113 -219
- package/dist/interpreter/QueryInterpreter.d.ts +2 -2
- package/dist/interpreter/renderQuery.d.ts +2 -2
- package/dist/transactionManager/Transaction.d.ts +1 -7
- package/dist/transactionManager/TransactionManager.d.ts +3 -4
- package/package.json +4 -4
- package/dist/interpreter/renderQueryTemplate.d.ts +0 -10
- /package/dist/interpreter/{renderQueryTemplate.test.d.ts → renderQuery.test.d.ts} +0 -0
package/dist/QueryPlan.d.ts
CHANGED
|
@@ -12,9 +12,27 @@ export type QueryPlanBinding = {
|
|
|
12
12
|
expr: QueryPlanNode;
|
|
13
13
|
};
|
|
14
14
|
export type QueryPlanDbQuery = {
|
|
15
|
-
|
|
15
|
+
type: 'rawSql';
|
|
16
|
+
sql: string;
|
|
16
17
|
params: PrismaValue[];
|
|
18
|
+
} | {
|
|
19
|
+
type: 'templateSql';
|
|
20
|
+
fragments: Fragment[];
|
|
21
|
+
placeholderFormat: PlaceholderFormat;
|
|
22
|
+
params: PrismaValue[];
|
|
23
|
+
};
|
|
24
|
+
export type Fragment = {
|
|
25
|
+
type: 'stringChunk';
|
|
26
|
+
value: string;
|
|
27
|
+
} | {
|
|
28
|
+
type: 'parameter';
|
|
29
|
+
} | {
|
|
30
|
+
type: 'parameterTuple';
|
|
17
31
|
};
|
|
32
|
+
export interface PlaceholderFormat {
|
|
33
|
+
prefix: string;
|
|
34
|
+
hasNumbering: boolean;
|
|
35
|
+
}
|
|
18
36
|
export type JoinExpression = {
|
|
19
37
|
child: QueryPlanNode;
|
|
20
38
|
on: [left: string, right: string][];
|
package/dist/crypto.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function randomUUID(): Promise<string>;
|
package/dist/index.d.mts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
1
|
+
import type { IsolationLevel } from '@prisma/driver-adapter-utils';
|
|
2
|
+
import { SqlDriverAdapter } from '@prisma/driver-adapter-utils';
|
|
3
|
+
import { SqlQueryable } from '@prisma/driver-adapter-utils';
|
|
4
|
+
import { Transaction } from '@prisma/driver-adapter-utils';
|
|
5
|
+
|
|
6
|
+
export declare type Fragment = {
|
|
7
|
+
type: 'stringChunk';
|
|
8
|
+
value: string;
|
|
9
|
+
} | {
|
|
10
|
+
type: 'parameter';
|
|
11
|
+
} | {
|
|
12
|
+
type: 'parameterTuple';
|
|
13
|
+
};
|
|
12
14
|
|
|
13
15
|
export declare function isPrismaValuePlaceholder(value: unknown): value is PrismaValuePlaceholder;
|
|
14
16
|
|
|
@@ -18,6 +20,11 @@ export declare type JoinExpression = {
|
|
|
18
20
|
parentField: string;
|
|
19
21
|
};
|
|
20
22
|
|
|
23
|
+
export declare interface PlaceholderFormat {
|
|
24
|
+
prefix: string;
|
|
25
|
+
hasNumbering: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
21
28
|
export declare type PrismaValue = string | boolean | number | PrismaValue[] | null | Record<string, unknown> | PrismaValuePlaceholder;
|
|
22
29
|
|
|
23
30
|
export declare type PrismaValuePlaceholder = {
|
|
@@ -43,7 +50,7 @@ export declare class QueryInterpreter {
|
|
|
43
50
|
}
|
|
44
51
|
|
|
45
52
|
export declare type QueryInterpreterOptions = {
|
|
46
|
-
queryable:
|
|
53
|
+
queryable: SqlQueryable;
|
|
47
54
|
placeholderValues: Record<string, unknown>;
|
|
48
55
|
onQuery?: (event: QueryEvent) => void;
|
|
49
56
|
};
|
|
@@ -54,7 +61,13 @@ export declare type QueryPlanBinding = {
|
|
|
54
61
|
};
|
|
55
62
|
|
|
56
63
|
export declare type QueryPlanDbQuery = {
|
|
57
|
-
|
|
64
|
+
type: 'rawSql';
|
|
65
|
+
sql: string;
|
|
66
|
+
params: PrismaValue[];
|
|
67
|
+
} | {
|
|
68
|
+
type: 'templateSql';
|
|
69
|
+
fragments: Fragment[];
|
|
70
|
+
placeholderFormat: PlaceholderFormat;
|
|
58
71
|
params: PrismaValue[];
|
|
59
72
|
};
|
|
60
73
|
|
|
@@ -121,18 +134,17 @@ export declare class TransactionManager {
|
|
|
121
134
|
private closedTransactions;
|
|
122
135
|
private readonly driverAdapter;
|
|
123
136
|
constructor({ driverAdapter }: {
|
|
124
|
-
driverAdapter:
|
|
137
|
+
driverAdapter: SqlDriverAdapter;
|
|
125
138
|
});
|
|
126
139
|
startTransaction(options: TransactionOptions): Promise<TransactionInfo>;
|
|
127
140
|
commitTransaction(transactionId: string): Promise<void>;
|
|
128
141
|
rollbackTransaction(transactionId: string): Promise<void>;
|
|
129
|
-
getTransaction(txInfo: TransactionInfo, operation: string):
|
|
142
|
+
getTransaction(txInfo: TransactionInfo, operation: string): Transaction;
|
|
130
143
|
private getActiveTransaction;
|
|
131
144
|
cancelAllTransactions(): Promise<void>;
|
|
132
145
|
private startTransactionTimeout;
|
|
133
146
|
private closeTransaction;
|
|
134
147
|
private validateOptions;
|
|
135
|
-
private requiresSettingIsolationLevelFirst;
|
|
136
148
|
}
|
|
137
149
|
|
|
138
150
|
export declare class TransactionManagerError extends Error {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
1
|
+
import type { IsolationLevel } from '@prisma/driver-adapter-utils';
|
|
2
|
+
import { SqlDriverAdapter } from '@prisma/driver-adapter-utils';
|
|
3
|
+
import { SqlQueryable } from '@prisma/driver-adapter-utils';
|
|
4
|
+
import { Transaction } from '@prisma/driver-adapter-utils';
|
|
5
|
+
|
|
6
|
+
export declare type Fragment = {
|
|
7
|
+
type: 'stringChunk';
|
|
8
|
+
value: string;
|
|
9
|
+
} | {
|
|
10
|
+
type: 'parameter';
|
|
11
|
+
} | {
|
|
12
|
+
type: 'parameterTuple';
|
|
13
|
+
};
|
|
12
14
|
|
|
13
15
|
export declare function isPrismaValuePlaceholder(value: unknown): value is PrismaValuePlaceholder;
|
|
14
16
|
|
|
@@ -18,6 +20,11 @@ export declare type JoinExpression = {
|
|
|
18
20
|
parentField: string;
|
|
19
21
|
};
|
|
20
22
|
|
|
23
|
+
export declare interface PlaceholderFormat {
|
|
24
|
+
prefix: string;
|
|
25
|
+
hasNumbering: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
21
28
|
export declare type PrismaValue = string | boolean | number | PrismaValue[] | null | Record<string, unknown> | PrismaValuePlaceholder;
|
|
22
29
|
|
|
23
30
|
export declare type PrismaValuePlaceholder = {
|
|
@@ -43,7 +50,7 @@ export declare class QueryInterpreter {
|
|
|
43
50
|
}
|
|
44
51
|
|
|
45
52
|
export declare type QueryInterpreterOptions = {
|
|
46
|
-
queryable:
|
|
53
|
+
queryable: SqlQueryable;
|
|
47
54
|
placeholderValues: Record<string, unknown>;
|
|
48
55
|
onQuery?: (event: QueryEvent) => void;
|
|
49
56
|
};
|
|
@@ -54,7 +61,13 @@ export declare type QueryPlanBinding = {
|
|
|
54
61
|
};
|
|
55
62
|
|
|
56
63
|
export declare type QueryPlanDbQuery = {
|
|
57
|
-
|
|
64
|
+
type: 'rawSql';
|
|
65
|
+
sql: string;
|
|
66
|
+
params: PrismaValue[];
|
|
67
|
+
} | {
|
|
68
|
+
type: 'templateSql';
|
|
69
|
+
fragments: Fragment[];
|
|
70
|
+
placeholderFormat: PlaceholderFormat;
|
|
58
71
|
params: PrismaValue[];
|
|
59
72
|
};
|
|
60
73
|
|
|
@@ -121,18 +134,17 @@ export declare class TransactionManager {
|
|
|
121
134
|
private closedTransactions;
|
|
122
135
|
private readonly driverAdapter;
|
|
123
136
|
constructor({ driverAdapter }: {
|
|
124
|
-
driverAdapter:
|
|
137
|
+
driverAdapter: SqlDriverAdapter;
|
|
125
138
|
});
|
|
126
139
|
startTransaction(options: TransactionOptions): Promise<TransactionInfo>;
|
|
127
140
|
commitTransaction(transactionId: string): Promise<void>;
|
|
128
141
|
rollbackTransaction(transactionId: string): Promise<void>;
|
|
129
|
-
getTransaction(txInfo: TransactionInfo, operation: string):
|
|
142
|
+
getTransaction(txInfo: TransactionInfo, operation: string): Transaction;
|
|
130
143
|
private getActiveTransaction;
|
|
131
144
|
cancelAllTransactions(): Promise<void>;
|
|
132
145
|
private startTransactionTimeout;
|
|
133
146
|
private closeTransaction;
|
|
134
147
|
private validateOptions;
|
|
135
|
-
private requiresSettingIsolationLevelFirst;
|
|
136
148
|
}
|
|
137
149
|
|
|
138
150
|
export declare class TransactionManagerError extends Error {
|
package/dist/index.js
CHANGED
|
@@ -5,10 +5,6 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __typeError = (msg) => {
|
|
9
|
-
throw TypeError(msg);
|
|
10
|
-
};
|
|
11
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
12
8
|
var __export = (target, all) => {
|
|
13
9
|
for (var name in all)
|
|
14
10
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -30,17 +26,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
26
|
mod
|
|
31
27
|
));
|
|
32
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
33
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
34
|
-
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
35
|
-
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
36
|
-
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
37
|
-
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
38
|
-
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
39
29
|
|
|
40
30
|
// src/index.ts
|
|
41
31
|
var index_exports = {};
|
|
42
32
|
__export(index_exports, {
|
|
43
|
-
IsolationLevel: () => IsolationLevel,
|
|
44
33
|
QueryInterpreter: () => QueryInterpreter,
|
|
45
34
|
TransactionManager: () => TransactionManager,
|
|
46
35
|
TransactionManagerError: () => TransactionManagerError,
|
|
@@ -53,107 +42,25 @@ function isPrismaValuePlaceholder(value) {
|
|
|
53
42
|
return typeof value === "object" && value !== null && value["prisma__type"] === "param";
|
|
54
43
|
}
|
|
55
44
|
|
|
56
|
-
// src/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
function renderQueryTemplate({
|
|
60
|
-
query,
|
|
61
|
-
params
|
|
62
|
-
}) {
|
|
63
|
-
if (!query.includes(BEGIN_REPEAT)) {
|
|
64
|
-
return { query, params };
|
|
65
|
-
}
|
|
66
|
-
const flattenedParams = [];
|
|
67
|
-
let lastParamId = 1;
|
|
68
|
-
let result = "";
|
|
69
|
-
let templatePos = 0;
|
|
70
|
-
let state = 0 /* Normal */;
|
|
71
|
-
let stateBeforeQuote = 0 /* Normal */;
|
|
72
|
-
while (templatePos < query.length) {
|
|
73
|
-
const nextChar = query[templatePos];
|
|
74
|
-
if (state === 1 /* Quoted */ && nextChar !== '"') {
|
|
75
|
-
result += nextChar;
|
|
76
|
-
templatePos++;
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
if (nextChar === '"') {
|
|
80
|
-
if (state === 1 /* Quoted */) {
|
|
81
|
-
state = stateBeforeQuote;
|
|
82
|
-
} else {
|
|
83
|
-
stateBeforeQuote = state;
|
|
84
|
-
state = 1 /* Quoted */;
|
|
85
|
-
}
|
|
86
|
-
result += nextChar;
|
|
87
|
-
templatePos++;
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
if (query.slice(templatePos, templatePos + BEGIN_REPEAT.length) === BEGIN_REPEAT) {
|
|
91
|
-
if (state === 2 /* Repeating */) {
|
|
92
|
-
throw new Error("Nested repetition is not allowed");
|
|
93
|
-
}
|
|
94
|
-
state = 2 /* Repeating */;
|
|
95
|
-
templatePos += BEGIN_REPEAT.length;
|
|
96
|
-
result += "(";
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
if (query.slice(templatePos, templatePos + END_REPEAT.length) === END_REPEAT) {
|
|
100
|
-
if (state === 0 /* Normal */) {
|
|
101
|
-
throw new Error("Unmatched repetition end");
|
|
102
|
-
}
|
|
103
|
-
state = 0 /* Normal */;
|
|
104
|
-
templatePos += END_REPEAT.length;
|
|
105
|
-
result += ")";
|
|
106
|
-
continue;
|
|
107
|
-
}
|
|
108
|
-
if (nextChar === "$") {
|
|
109
|
-
const paramMatch = query.slice(templatePos + 1).match(/^\d+/);
|
|
110
|
-
if (!paramMatch) {
|
|
111
|
-
result += "$";
|
|
112
|
-
templatePos++;
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
templatePos += paramMatch[0].length + 1;
|
|
116
|
-
const originalParamIdx = parseInt(paramMatch[0]);
|
|
117
|
-
const paramValue = params[originalParamIdx - 1];
|
|
118
|
-
switch (state) {
|
|
119
|
-
case 0 /* Normal */: {
|
|
120
|
-
flattenedParams.push(paramValue);
|
|
121
|
-
result += `$${lastParamId++}`;
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
case 2 /* Repeating */: {
|
|
125
|
-
const paramArray = Array.isArray(paramValue) ? paramValue : [paramValue];
|
|
126
|
-
if (paramArray.length === 0) {
|
|
127
|
-
result += "NULL";
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
|
-
paramArray.forEach((value, idx) => {
|
|
131
|
-
flattenedParams.push(value);
|
|
132
|
-
result += `$${lastParamId++}`;
|
|
133
|
-
if (idx !== paramArray.length - 1) {
|
|
134
|
-
result += ", ";
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
break;
|
|
138
|
-
}
|
|
139
|
-
default: {
|
|
140
|
-
throw new Error(`Unexpected state: ${state}`);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
continue;
|
|
144
|
-
}
|
|
145
|
-
result += nextChar;
|
|
146
|
-
templatePos++;
|
|
147
|
-
}
|
|
148
|
-
return {
|
|
149
|
-
query: result,
|
|
150
|
-
params: flattenedParams
|
|
151
|
-
};
|
|
45
|
+
// src/utils.ts
|
|
46
|
+
function assertNever(_, message) {
|
|
47
|
+
throw new Error(message);
|
|
152
48
|
}
|
|
153
49
|
|
|
154
50
|
// src/interpreter/renderQuery.ts
|
|
155
|
-
function renderQuery(
|
|
156
|
-
const
|
|
51
|
+
function renderQuery(dbQuery, scope) {
|
|
52
|
+
const queryType = dbQuery.type;
|
|
53
|
+
switch (queryType) {
|
|
54
|
+
case "rawSql":
|
|
55
|
+
return renderRawSql(dbQuery.sql, substituteParams(dbQuery.params, scope));
|
|
56
|
+
case "templateSql":
|
|
57
|
+
return renderTemplateSql(dbQuery.fragments, dbQuery.placeholderFormat, substituteParams(dbQuery.params, scope));
|
|
58
|
+
default:
|
|
59
|
+
assertNever(queryType, `Invalid query type`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function substituteParams(params, scope) {
|
|
63
|
+
return params.map((param) => {
|
|
157
64
|
if (!isPrismaValuePlaceholder(param)) {
|
|
158
65
|
return param;
|
|
159
66
|
}
|
|
@@ -163,11 +70,48 @@ function renderQuery({ query, params }, scope) {
|
|
|
163
70
|
}
|
|
164
71
|
return value;
|
|
165
72
|
});
|
|
166
|
-
|
|
167
|
-
|
|
73
|
+
}
|
|
74
|
+
function renderTemplateSql(fragments, placeholderFormat, params) {
|
|
75
|
+
let paramIndex = 0;
|
|
76
|
+
let placeholderNumber = 1;
|
|
77
|
+
const flattenedParams = [];
|
|
78
|
+
const sql = fragments.map((fragment) => {
|
|
79
|
+
const fragmentType = fragment.type;
|
|
80
|
+
switch (fragmentType) {
|
|
81
|
+
case "parameter":
|
|
82
|
+
if (paramIndex >= params.length) {
|
|
83
|
+
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
84
|
+
}
|
|
85
|
+
flattenedParams.push(params[paramIndex++]);
|
|
86
|
+
return formatPlaceholder(placeholderFormat, placeholderNumber++);
|
|
87
|
+
case "stringChunk":
|
|
88
|
+
return fragment.value;
|
|
89
|
+
case "parameterTuple": {
|
|
90
|
+
if (paramIndex >= params.length) {
|
|
91
|
+
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
92
|
+
}
|
|
93
|
+
const paramValue = params[paramIndex++];
|
|
94
|
+
const paramArray = Array.isArray(paramValue) ? paramValue : [paramValue];
|
|
95
|
+
const placeholders = paramArray.length == 0 ? "NULL" : paramArray.map((value) => {
|
|
96
|
+
flattenedParams.push(value);
|
|
97
|
+
return formatPlaceholder(placeholderFormat, placeholderNumber++);
|
|
98
|
+
}).join(",");
|
|
99
|
+
return `(${placeholders})`;
|
|
100
|
+
}
|
|
101
|
+
default:
|
|
102
|
+
assertNever(fragmentType, "Invalid fragment type");
|
|
103
|
+
}
|
|
104
|
+
}).join("");
|
|
105
|
+
return renderRawSql(sql, flattenedParams);
|
|
106
|
+
}
|
|
107
|
+
function formatPlaceholder(placeholderFormat, placeholderNumber) {
|
|
108
|
+
return placeholderFormat.hasNumbering ? `${placeholderFormat.prefix}${placeholderNumber}` : placeholderFormat.prefix;
|
|
109
|
+
}
|
|
110
|
+
function renderRawSql(sql, params) {
|
|
111
|
+
const argTypes = params.map((param) => toArgType(param));
|
|
168
112
|
return {
|
|
169
|
-
sql
|
|
170
|
-
args:
|
|
113
|
+
sql,
|
|
114
|
+
args: params,
|
|
171
115
|
argTypes
|
|
172
116
|
};
|
|
173
117
|
}
|
|
@@ -236,19 +180,17 @@ function serialize(resultSet) {
|
|
|
236
180
|
}
|
|
237
181
|
|
|
238
182
|
// src/interpreter/QueryInterpreter.ts
|
|
239
|
-
var _queryable, _placeholderValues, _onQuery, _QueryInterpreter_instances, withQueryEvent_fn;
|
|
240
183
|
var QueryInterpreter = class {
|
|
184
|
+
#queryable;
|
|
185
|
+
#placeholderValues;
|
|
186
|
+
#onQuery;
|
|
241
187
|
constructor({ queryable, placeholderValues, onQuery }) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
__privateAdd(this, _onQuery);
|
|
246
|
-
__privateSet(this, _queryable, queryable);
|
|
247
|
-
__privateSet(this, _placeholderValues, placeholderValues);
|
|
248
|
-
__privateSet(this, _onQuery, onQuery);
|
|
188
|
+
this.#queryable = queryable;
|
|
189
|
+
this.#placeholderValues = placeholderValues;
|
|
190
|
+
this.#onQuery = onQuery;
|
|
249
191
|
}
|
|
250
192
|
async run(queryPlan) {
|
|
251
|
-
return this.interpretNode(queryPlan,
|
|
193
|
+
return this.interpretNode(queryPlan, this.#placeholderValues);
|
|
252
194
|
}
|
|
253
195
|
async interpretNode(node, scope) {
|
|
254
196
|
switch (node.type) {
|
|
@@ -287,24 +229,14 @@ var QueryInterpreter = class {
|
|
|
287
229
|
}
|
|
288
230
|
case "execute": {
|
|
289
231
|
const query = renderQuery(node.args, scope);
|
|
290
|
-
return
|
|
291
|
-
|
|
292
|
-
if (result.ok) {
|
|
293
|
-
return result.value;
|
|
294
|
-
} else {
|
|
295
|
-
throw result.error;
|
|
296
|
-
}
|
|
232
|
+
return this.#withQueryEvent(query, async () => {
|
|
233
|
+
return await this.#queryable.executeRaw(query);
|
|
297
234
|
});
|
|
298
235
|
}
|
|
299
236
|
case "query": {
|
|
300
237
|
const query = renderQuery(node.args, scope);
|
|
301
|
-
return
|
|
302
|
-
|
|
303
|
-
if (result.ok) {
|
|
304
|
-
return serialize(result.value);
|
|
305
|
-
} else {
|
|
306
|
-
throw result.error;
|
|
307
|
-
}
|
|
238
|
+
return this.#withQueryEvent(query, async () => {
|
|
239
|
+
return serialize(await this.#queryable.queryRaw(query));
|
|
308
240
|
});
|
|
309
241
|
}
|
|
310
242
|
case "reverse": {
|
|
@@ -354,24 +286,19 @@ var QueryInterpreter = class {
|
|
|
354
286
|
}
|
|
355
287
|
}
|
|
356
288
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
duration: endInstant - startInstant,
|
|
371
|
-
query: query.sql,
|
|
372
|
-
params: query.args
|
|
373
|
-
});
|
|
374
|
-
return result;
|
|
289
|
+
async #withQueryEvent(query, execute) {
|
|
290
|
+
const timestamp = /* @__PURE__ */ new Date();
|
|
291
|
+
const startInstant = performance.now();
|
|
292
|
+
const result = await execute();
|
|
293
|
+
const endInstant = performance.now();
|
|
294
|
+
this.#onQuery?.({
|
|
295
|
+
timestamp,
|
|
296
|
+
duration: endInstant - startInstant,
|
|
297
|
+
query: query.sql,
|
|
298
|
+
params: query.args
|
|
299
|
+
});
|
|
300
|
+
return result;
|
|
301
|
+
}
|
|
375
302
|
};
|
|
376
303
|
function isEmpty(value) {
|
|
377
304
|
if (Array.isArray(value)) {
|
|
@@ -429,22 +356,16 @@ function childRecordMatchesParent(childRecord, parentRecord, joinExpr) {
|
|
|
429
356
|
return true;
|
|
430
357
|
}
|
|
431
358
|
|
|
432
|
-
// src/transactionManager/Transaction.ts
|
|
433
|
-
var IsolationLevel = /* @__PURE__ */ ((IsolationLevel2) => {
|
|
434
|
-
IsolationLevel2["ReadUncommitted"] = "ReadUncommitted";
|
|
435
|
-
IsolationLevel2["ReadCommitted"] = "ReadCommitted";
|
|
436
|
-
IsolationLevel2["RepeatableRead"] = "RepeatableRead";
|
|
437
|
-
IsolationLevel2["Snapshot"] = "Snapshot";
|
|
438
|
-
IsolationLevel2["Serializable"] = "Serializable";
|
|
439
|
-
return IsolationLevel2;
|
|
440
|
-
})(IsolationLevel || {});
|
|
441
|
-
|
|
442
359
|
// src/transactionManager/TransactionManager.ts
|
|
443
360
|
var import_debug = __toESM(require("@prisma/debug"));
|
|
444
361
|
|
|
445
|
-
// src/
|
|
446
|
-
function
|
|
447
|
-
|
|
362
|
+
// src/crypto.ts
|
|
363
|
+
async function getCrypto() {
|
|
364
|
+
return globalThis.crypto ?? await import("node:crypto");
|
|
365
|
+
}
|
|
366
|
+
async function randomUUID() {
|
|
367
|
+
const crypto = await getCrypto();
|
|
368
|
+
return crypto.randomUUID();
|
|
448
369
|
}
|
|
449
370
|
|
|
450
371
|
// src/transactionManager/TransactionManagerErrors.ts
|
|
@@ -452,8 +373,8 @@ var TransactionManagerError = class extends Error {
|
|
|
452
373
|
constructor(message, meta) {
|
|
453
374
|
super("Transaction API error: " + message);
|
|
454
375
|
this.meta = meta;
|
|
455
|
-
__publicField(this, "code", "P2028");
|
|
456
376
|
}
|
|
377
|
+
code = "P2028";
|
|
457
378
|
};
|
|
458
379
|
var TransactionDriverAdapterError = class extends TransactionManagerError {
|
|
459
380
|
constructor(message, errorParams) {
|
|
@@ -503,35 +424,23 @@ var InvalidTransactionIsolationLevelError = class extends TransactionManagerErro
|
|
|
503
424
|
|
|
504
425
|
// src/transactionManager/TransactionManager.ts
|
|
505
426
|
var MAX_CLOSED_TRANSACTIONS = 100;
|
|
506
|
-
var isolationLevelMap = {
|
|
507
|
-
ReadUncommitted: "READ UNCOMMITTED",
|
|
508
|
-
ReadCommitted: "READ COMMITTED",
|
|
509
|
-
RepeatableRead: "REPEATABLE READ",
|
|
510
|
-
Snapshot: "SNAPSHOT",
|
|
511
|
-
Serializable: "SERIALIZABLE"
|
|
512
|
-
};
|
|
513
427
|
var debug = (0, import_debug.default)("prisma:client:transactionManager");
|
|
514
428
|
var COMMIT_QUERY = () => ({ sql: "COMMIT", args: [], argTypes: [] });
|
|
515
429
|
var ROLLBACK_QUERY = () => ({ sql: "ROLLBACK", args: [], argTypes: [] });
|
|
516
|
-
var ISOLATION_LEVEL_QUERY = (isolationLevel) => ({
|
|
517
|
-
sql: "SET TRANSACTION ISOLATION LEVEL " + isolationLevelMap[isolationLevel],
|
|
518
|
-
args: [],
|
|
519
|
-
argTypes: []
|
|
520
|
-
});
|
|
521
430
|
var TransactionManager = class {
|
|
431
|
+
// The map of active transactions.
|
|
432
|
+
transactions = /* @__PURE__ */ new Map();
|
|
433
|
+
// List of last closed transactions. Max MAX_CLOSED_TRANSACTIONS entries.
|
|
434
|
+
// Used to provide better error messages than a generic "transaction not found".
|
|
435
|
+
closedTransactions = [];
|
|
436
|
+
driverAdapter;
|
|
522
437
|
constructor({ driverAdapter }) {
|
|
523
|
-
// The map of active transactions.
|
|
524
|
-
__publicField(this, "transactions", /* @__PURE__ */ new Map());
|
|
525
|
-
// List of last closed transactions. Max MAX_CLOSED_TRANSACTIONS entries.
|
|
526
|
-
// Used to provide better error messages than a generic "transaction not found".
|
|
527
|
-
__publicField(this, "closedTransactions", []);
|
|
528
|
-
__publicField(this, "driverAdapter");
|
|
529
438
|
this.driverAdapter = driverAdapter;
|
|
530
439
|
}
|
|
531
440
|
async startTransaction(options) {
|
|
532
441
|
const validatedOptions = this.validateOptions(options);
|
|
533
442
|
const transaction = {
|
|
534
|
-
id:
|
|
443
|
+
id: await randomUUID(),
|
|
535
444
|
status: "waiting",
|
|
536
445
|
timer: void 0,
|
|
537
446
|
timeout: validatedOptions.timeout,
|
|
@@ -540,28 +449,17 @@ var TransactionManager = class {
|
|
|
540
449
|
};
|
|
541
450
|
this.transactions.set(transaction.id, transaction);
|
|
542
451
|
transaction.timer = this.startTransactionTimeout(transaction.id, validatedOptions.maxWait);
|
|
543
|
-
|
|
544
|
-
|
|
452
|
+
let startedTransaction;
|
|
453
|
+
try {
|
|
454
|
+
startedTransaction = await this.driverAdapter.startTransaction(validatedOptions.isolationLevel);
|
|
455
|
+
} catch (error) {
|
|
545
456
|
throw new TransactionDriverAdapterError("Failed to start transaction.", {
|
|
546
|
-
driverAdapterError:
|
|
457
|
+
driverAdapterError: error
|
|
547
458
|
});
|
|
548
|
-
if (this.requiresSettingIsolationLevelFirst() && validatedOptions.isolationLevel) {
|
|
549
|
-
await txContext.value.executeRaw(ISOLATION_LEVEL_QUERY(validatedOptions.isolationLevel));
|
|
550
|
-
}
|
|
551
|
-
const startedTransaction = await txContext.value.startTransaction();
|
|
552
|
-
if (!startedTransaction.ok)
|
|
553
|
-
throw new TransactionDriverAdapterError("Failed to start transaction.", {
|
|
554
|
-
driverAdapterError: startedTransaction.error
|
|
555
|
-
});
|
|
556
|
-
if (!startedTransaction.value.options.usePhantomQuery) {
|
|
557
|
-
await startedTransaction.value.executeRaw({ sql: "BEGIN", args: [], argTypes: [] });
|
|
558
|
-
if (!this.requiresSettingIsolationLevelFirst() && validatedOptions.isolationLevel) {
|
|
559
|
-
await txContext.value.executeRaw(ISOLATION_LEVEL_QUERY(validatedOptions.isolationLevel));
|
|
560
|
-
}
|
|
561
459
|
}
|
|
562
460
|
switch (transaction.status) {
|
|
563
461
|
case "waiting":
|
|
564
|
-
transaction.transaction = startedTransaction
|
|
462
|
+
transaction.transaction = startedTransaction;
|
|
565
463
|
clearTimeout(transaction.timer);
|
|
566
464
|
transaction.timer = void 0;
|
|
567
465
|
transaction.status = "running";
|
|
@@ -641,20 +539,24 @@ var TransactionManager = class {
|
|
|
641
539
|
debug("Closing transaction.", { transactionId: tx.id, status });
|
|
642
540
|
tx.status = status;
|
|
643
541
|
if (tx.transaction && status === "committed") {
|
|
644
|
-
|
|
645
|
-
|
|
542
|
+
try {
|
|
543
|
+
await tx.transaction.commit();
|
|
544
|
+
} catch (error) {
|
|
646
545
|
throw new TransactionDriverAdapterError("Failed to commit transaction.", {
|
|
647
|
-
driverAdapterError:
|
|
546
|
+
driverAdapterError: error
|
|
648
547
|
});
|
|
548
|
+
}
|
|
649
549
|
if (!tx.transaction.options.usePhantomQuery) {
|
|
650
550
|
await tx.transaction.executeRaw(COMMIT_QUERY());
|
|
651
551
|
}
|
|
652
552
|
} else if (tx.transaction) {
|
|
653
|
-
|
|
654
|
-
|
|
553
|
+
try {
|
|
554
|
+
await tx.transaction.rollback();
|
|
555
|
+
} catch (error) {
|
|
655
556
|
throw new TransactionDriverAdapterError("Failed to rollback transaction.", {
|
|
656
|
-
driverAdapterError:
|
|
557
|
+
driverAdapterError: error
|
|
657
558
|
});
|
|
559
|
+
}
|
|
658
560
|
if (!tx.transaction.options.usePhantomQuery) {
|
|
659
561
|
await tx.transaction.executeRaw(ROLLBACK_QUERY());
|
|
660
562
|
}
|
|
@@ -670,23 +572,16 @@ var TransactionManager = class {
|
|
|
670
572
|
validateOptions(options) {
|
|
671
573
|
if (!options.timeout) throw new TransactionManagerError("timeout is required");
|
|
672
574
|
if (!options.maxWait) throw new TransactionManagerError("maxWait is required");
|
|
673
|
-
if (options.isolationLevel === "
|
|
674
|
-
throw new InvalidTransactionIsolationLevelError(options.isolationLevel);
|
|
675
|
-
if (this.driverAdapter.provider === "sqlite" && options.isolationLevel && options.isolationLevel !== "Serializable" /* Serializable */)
|
|
676
|
-
throw new InvalidTransactionIsolationLevelError(options.isolationLevel);
|
|
575
|
+
if (options.isolationLevel === "SNAPSHOT") throw new InvalidTransactionIsolationLevelError(options.isolationLevel);
|
|
677
576
|
return {
|
|
678
577
|
...options,
|
|
679
578
|
timeout: options.timeout,
|
|
680
579
|
maxWait: options.maxWait
|
|
681
580
|
};
|
|
682
581
|
}
|
|
683
|
-
requiresSettingIsolationLevelFirst() {
|
|
684
|
-
return this.driverAdapter.provider === "mysql";
|
|
685
|
-
}
|
|
686
582
|
};
|
|
687
583
|
// Annotate the CommonJS export names for ESM import in node:
|
|
688
584
|
0 && (module.exports = {
|
|
689
|
-
IsolationLevel,
|
|
690
585
|
QueryInterpreter,
|
|
691
586
|
TransactionManager,
|
|
692
587
|
TransactionManagerError,
|
package/dist/index.mjs
CHANGED
|
@@ -1,121 +1,27 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __typeError = (msg) => {
|
|
3
|
-
throw TypeError(msg);
|
|
4
|
-
};
|
|
5
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
7
|
-
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
8
|
-
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
9
|
-
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
10
|
-
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
11
|
-
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
12
|
-
|
|
13
1
|
// src/QueryPlan.ts
|
|
14
2
|
function isPrismaValuePlaceholder(value) {
|
|
15
3
|
return typeof value === "object" && value !== null && value["prisma__type"] === "param";
|
|
16
4
|
}
|
|
17
5
|
|
|
18
|
-
// src/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
function renderQueryTemplate({
|
|
22
|
-
query,
|
|
23
|
-
params
|
|
24
|
-
}) {
|
|
25
|
-
if (!query.includes(BEGIN_REPEAT)) {
|
|
26
|
-
return { query, params };
|
|
27
|
-
}
|
|
28
|
-
const flattenedParams = [];
|
|
29
|
-
let lastParamId = 1;
|
|
30
|
-
let result = "";
|
|
31
|
-
let templatePos = 0;
|
|
32
|
-
let state = 0 /* Normal */;
|
|
33
|
-
let stateBeforeQuote = 0 /* Normal */;
|
|
34
|
-
while (templatePos < query.length) {
|
|
35
|
-
const nextChar = query[templatePos];
|
|
36
|
-
if (state === 1 /* Quoted */ && nextChar !== '"') {
|
|
37
|
-
result += nextChar;
|
|
38
|
-
templatePos++;
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
if (nextChar === '"') {
|
|
42
|
-
if (state === 1 /* Quoted */) {
|
|
43
|
-
state = stateBeforeQuote;
|
|
44
|
-
} else {
|
|
45
|
-
stateBeforeQuote = state;
|
|
46
|
-
state = 1 /* Quoted */;
|
|
47
|
-
}
|
|
48
|
-
result += nextChar;
|
|
49
|
-
templatePos++;
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
if (query.slice(templatePos, templatePos + BEGIN_REPEAT.length) === BEGIN_REPEAT) {
|
|
53
|
-
if (state === 2 /* Repeating */) {
|
|
54
|
-
throw new Error("Nested repetition is not allowed");
|
|
55
|
-
}
|
|
56
|
-
state = 2 /* Repeating */;
|
|
57
|
-
templatePos += BEGIN_REPEAT.length;
|
|
58
|
-
result += "(";
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
if (query.slice(templatePos, templatePos + END_REPEAT.length) === END_REPEAT) {
|
|
62
|
-
if (state === 0 /* Normal */) {
|
|
63
|
-
throw new Error("Unmatched repetition end");
|
|
64
|
-
}
|
|
65
|
-
state = 0 /* Normal */;
|
|
66
|
-
templatePos += END_REPEAT.length;
|
|
67
|
-
result += ")";
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
if (nextChar === "$") {
|
|
71
|
-
const paramMatch = query.slice(templatePos + 1).match(/^\d+/);
|
|
72
|
-
if (!paramMatch) {
|
|
73
|
-
result += "$";
|
|
74
|
-
templatePos++;
|
|
75
|
-
continue;
|
|
76
|
-
}
|
|
77
|
-
templatePos += paramMatch[0].length + 1;
|
|
78
|
-
const originalParamIdx = parseInt(paramMatch[0]);
|
|
79
|
-
const paramValue = params[originalParamIdx - 1];
|
|
80
|
-
switch (state) {
|
|
81
|
-
case 0 /* Normal */: {
|
|
82
|
-
flattenedParams.push(paramValue);
|
|
83
|
-
result += `$${lastParamId++}`;
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
case 2 /* Repeating */: {
|
|
87
|
-
const paramArray = Array.isArray(paramValue) ? paramValue : [paramValue];
|
|
88
|
-
if (paramArray.length === 0) {
|
|
89
|
-
result += "NULL";
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
paramArray.forEach((value, idx) => {
|
|
93
|
-
flattenedParams.push(value);
|
|
94
|
-
result += `$${lastParamId++}`;
|
|
95
|
-
if (idx !== paramArray.length - 1) {
|
|
96
|
-
result += ", ";
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
break;
|
|
100
|
-
}
|
|
101
|
-
default: {
|
|
102
|
-
throw new Error(`Unexpected state: ${state}`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
107
|
-
result += nextChar;
|
|
108
|
-
templatePos++;
|
|
109
|
-
}
|
|
110
|
-
return {
|
|
111
|
-
query: result,
|
|
112
|
-
params: flattenedParams
|
|
113
|
-
};
|
|
6
|
+
// src/utils.ts
|
|
7
|
+
function assertNever(_, message) {
|
|
8
|
+
throw new Error(message);
|
|
114
9
|
}
|
|
115
10
|
|
|
116
11
|
// src/interpreter/renderQuery.ts
|
|
117
|
-
function renderQuery(
|
|
118
|
-
const
|
|
12
|
+
function renderQuery(dbQuery, scope) {
|
|
13
|
+
const queryType = dbQuery.type;
|
|
14
|
+
switch (queryType) {
|
|
15
|
+
case "rawSql":
|
|
16
|
+
return renderRawSql(dbQuery.sql, substituteParams(dbQuery.params, scope));
|
|
17
|
+
case "templateSql":
|
|
18
|
+
return renderTemplateSql(dbQuery.fragments, dbQuery.placeholderFormat, substituteParams(dbQuery.params, scope));
|
|
19
|
+
default:
|
|
20
|
+
assertNever(queryType, `Invalid query type`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function substituteParams(params, scope) {
|
|
24
|
+
return params.map((param) => {
|
|
119
25
|
if (!isPrismaValuePlaceholder(param)) {
|
|
120
26
|
return param;
|
|
121
27
|
}
|
|
@@ -125,11 +31,48 @@ function renderQuery({ query, params }, scope) {
|
|
|
125
31
|
}
|
|
126
32
|
return value;
|
|
127
33
|
});
|
|
128
|
-
|
|
129
|
-
|
|
34
|
+
}
|
|
35
|
+
function renderTemplateSql(fragments, placeholderFormat, params) {
|
|
36
|
+
let paramIndex = 0;
|
|
37
|
+
let placeholderNumber = 1;
|
|
38
|
+
const flattenedParams = [];
|
|
39
|
+
const sql = fragments.map((fragment) => {
|
|
40
|
+
const fragmentType = fragment.type;
|
|
41
|
+
switch (fragmentType) {
|
|
42
|
+
case "parameter":
|
|
43
|
+
if (paramIndex >= params.length) {
|
|
44
|
+
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
45
|
+
}
|
|
46
|
+
flattenedParams.push(params[paramIndex++]);
|
|
47
|
+
return formatPlaceholder(placeholderFormat, placeholderNumber++);
|
|
48
|
+
case "stringChunk":
|
|
49
|
+
return fragment.value;
|
|
50
|
+
case "parameterTuple": {
|
|
51
|
+
if (paramIndex >= params.length) {
|
|
52
|
+
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
53
|
+
}
|
|
54
|
+
const paramValue = params[paramIndex++];
|
|
55
|
+
const paramArray = Array.isArray(paramValue) ? paramValue : [paramValue];
|
|
56
|
+
const placeholders = paramArray.length == 0 ? "NULL" : paramArray.map((value) => {
|
|
57
|
+
flattenedParams.push(value);
|
|
58
|
+
return formatPlaceholder(placeholderFormat, placeholderNumber++);
|
|
59
|
+
}).join(",");
|
|
60
|
+
return `(${placeholders})`;
|
|
61
|
+
}
|
|
62
|
+
default:
|
|
63
|
+
assertNever(fragmentType, "Invalid fragment type");
|
|
64
|
+
}
|
|
65
|
+
}).join("");
|
|
66
|
+
return renderRawSql(sql, flattenedParams);
|
|
67
|
+
}
|
|
68
|
+
function formatPlaceholder(placeholderFormat, placeholderNumber) {
|
|
69
|
+
return placeholderFormat.hasNumbering ? `${placeholderFormat.prefix}${placeholderNumber}` : placeholderFormat.prefix;
|
|
70
|
+
}
|
|
71
|
+
function renderRawSql(sql, params) {
|
|
72
|
+
const argTypes = params.map((param) => toArgType(param));
|
|
130
73
|
return {
|
|
131
|
-
sql
|
|
132
|
-
args:
|
|
74
|
+
sql,
|
|
75
|
+
args: params,
|
|
133
76
|
argTypes
|
|
134
77
|
};
|
|
135
78
|
}
|
|
@@ -198,19 +141,17 @@ function serialize(resultSet) {
|
|
|
198
141
|
}
|
|
199
142
|
|
|
200
143
|
// src/interpreter/QueryInterpreter.ts
|
|
201
|
-
var _queryable, _placeholderValues, _onQuery, _QueryInterpreter_instances, withQueryEvent_fn;
|
|
202
144
|
var QueryInterpreter = class {
|
|
145
|
+
#queryable;
|
|
146
|
+
#placeholderValues;
|
|
147
|
+
#onQuery;
|
|
203
148
|
constructor({ queryable, placeholderValues, onQuery }) {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
__privateAdd(this, _onQuery);
|
|
208
|
-
__privateSet(this, _queryable, queryable);
|
|
209
|
-
__privateSet(this, _placeholderValues, placeholderValues);
|
|
210
|
-
__privateSet(this, _onQuery, onQuery);
|
|
149
|
+
this.#queryable = queryable;
|
|
150
|
+
this.#placeholderValues = placeholderValues;
|
|
151
|
+
this.#onQuery = onQuery;
|
|
211
152
|
}
|
|
212
153
|
async run(queryPlan) {
|
|
213
|
-
return this.interpretNode(queryPlan,
|
|
154
|
+
return this.interpretNode(queryPlan, this.#placeholderValues);
|
|
214
155
|
}
|
|
215
156
|
async interpretNode(node, scope) {
|
|
216
157
|
switch (node.type) {
|
|
@@ -249,24 +190,14 @@ var QueryInterpreter = class {
|
|
|
249
190
|
}
|
|
250
191
|
case "execute": {
|
|
251
192
|
const query = renderQuery(node.args, scope);
|
|
252
|
-
return
|
|
253
|
-
|
|
254
|
-
if (result.ok) {
|
|
255
|
-
return result.value;
|
|
256
|
-
} else {
|
|
257
|
-
throw result.error;
|
|
258
|
-
}
|
|
193
|
+
return this.#withQueryEvent(query, async () => {
|
|
194
|
+
return await this.#queryable.executeRaw(query);
|
|
259
195
|
});
|
|
260
196
|
}
|
|
261
197
|
case "query": {
|
|
262
198
|
const query = renderQuery(node.args, scope);
|
|
263
|
-
return
|
|
264
|
-
|
|
265
|
-
if (result.ok) {
|
|
266
|
-
return serialize(result.value);
|
|
267
|
-
} else {
|
|
268
|
-
throw result.error;
|
|
269
|
-
}
|
|
199
|
+
return this.#withQueryEvent(query, async () => {
|
|
200
|
+
return serialize(await this.#queryable.queryRaw(query));
|
|
270
201
|
});
|
|
271
202
|
}
|
|
272
203
|
case "reverse": {
|
|
@@ -316,24 +247,19 @@ var QueryInterpreter = class {
|
|
|
316
247
|
}
|
|
317
248
|
}
|
|
318
249
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
duration: endInstant - startInstant,
|
|
333
|
-
query: query.sql,
|
|
334
|
-
params: query.args
|
|
335
|
-
});
|
|
336
|
-
return result;
|
|
250
|
+
async #withQueryEvent(query, execute) {
|
|
251
|
+
const timestamp = /* @__PURE__ */ new Date();
|
|
252
|
+
const startInstant = performance.now();
|
|
253
|
+
const result = await execute();
|
|
254
|
+
const endInstant = performance.now();
|
|
255
|
+
this.#onQuery?.({
|
|
256
|
+
timestamp,
|
|
257
|
+
duration: endInstant - startInstant,
|
|
258
|
+
query: query.sql,
|
|
259
|
+
params: query.args
|
|
260
|
+
});
|
|
261
|
+
return result;
|
|
262
|
+
}
|
|
337
263
|
};
|
|
338
264
|
function isEmpty(value) {
|
|
339
265
|
if (Array.isArray(value)) {
|
|
@@ -391,22 +317,16 @@ function childRecordMatchesParent(childRecord, parentRecord, joinExpr) {
|
|
|
391
317
|
return true;
|
|
392
318
|
}
|
|
393
319
|
|
|
394
|
-
// src/transactionManager/Transaction.ts
|
|
395
|
-
var IsolationLevel = /* @__PURE__ */ ((IsolationLevel2) => {
|
|
396
|
-
IsolationLevel2["ReadUncommitted"] = "ReadUncommitted";
|
|
397
|
-
IsolationLevel2["ReadCommitted"] = "ReadCommitted";
|
|
398
|
-
IsolationLevel2["RepeatableRead"] = "RepeatableRead";
|
|
399
|
-
IsolationLevel2["Snapshot"] = "Snapshot";
|
|
400
|
-
IsolationLevel2["Serializable"] = "Serializable";
|
|
401
|
-
return IsolationLevel2;
|
|
402
|
-
})(IsolationLevel || {});
|
|
403
|
-
|
|
404
320
|
// src/transactionManager/TransactionManager.ts
|
|
405
321
|
import Debug from "@prisma/debug";
|
|
406
322
|
|
|
407
|
-
// src/
|
|
408
|
-
function
|
|
409
|
-
|
|
323
|
+
// src/crypto.ts
|
|
324
|
+
async function getCrypto() {
|
|
325
|
+
return globalThis.crypto ?? await import("node:crypto");
|
|
326
|
+
}
|
|
327
|
+
async function randomUUID() {
|
|
328
|
+
const crypto = await getCrypto();
|
|
329
|
+
return crypto.randomUUID();
|
|
410
330
|
}
|
|
411
331
|
|
|
412
332
|
// src/transactionManager/TransactionManagerErrors.ts
|
|
@@ -414,8 +334,8 @@ var TransactionManagerError = class extends Error {
|
|
|
414
334
|
constructor(message, meta) {
|
|
415
335
|
super("Transaction API error: " + message);
|
|
416
336
|
this.meta = meta;
|
|
417
|
-
__publicField(this, "code", "P2028");
|
|
418
337
|
}
|
|
338
|
+
code = "P2028";
|
|
419
339
|
};
|
|
420
340
|
var TransactionDriverAdapterError = class extends TransactionManagerError {
|
|
421
341
|
constructor(message, errorParams) {
|
|
@@ -465,35 +385,23 @@ var InvalidTransactionIsolationLevelError = class extends TransactionManagerErro
|
|
|
465
385
|
|
|
466
386
|
// src/transactionManager/TransactionManager.ts
|
|
467
387
|
var MAX_CLOSED_TRANSACTIONS = 100;
|
|
468
|
-
var isolationLevelMap = {
|
|
469
|
-
ReadUncommitted: "READ UNCOMMITTED",
|
|
470
|
-
ReadCommitted: "READ COMMITTED",
|
|
471
|
-
RepeatableRead: "REPEATABLE READ",
|
|
472
|
-
Snapshot: "SNAPSHOT",
|
|
473
|
-
Serializable: "SERIALIZABLE"
|
|
474
|
-
};
|
|
475
388
|
var debug = Debug("prisma:client:transactionManager");
|
|
476
389
|
var COMMIT_QUERY = () => ({ sql: "COMMIT", args: [], argTypes: [] });
|
|
477
390
|
var ROLLBACK_QUERY = () => ({ sql: "ROLLBACK", args: [], argTypes: [] });
|
|
478
|
-
var ISOLATION_LEVEL_QUERY = (isolationLevel) => ({
|
|
479
|
-
sql: "SET TRANSACTION ISOLATION LEVEL " + isolationLevelMap[isolationLevel],
|
|
480
|
-
args: [],
|
|
481
|
-
argTypes: []
|
|
482
|
-
});
|
|
483
391
|
var TransactionManager = class {
|
|
392
|
+
// The map of active transactions.
|
|
393
|
+
transactions = /* @__PURE__ */ new Map();
|
|
394
|
+
// List of last closed transactions. Max MAX_CLOSED_TRANSACTIONS entries.
|
|
395
|
+
// Used to provide better error messages than a generic "transaction not found".
|
|
396
|
+
closedTransactions = [];
|
|
397
|
+
driverAdapter;
|
|
484
398
|
constructor({ driverAdapter }) {
|
|
485
|
-
// The map of active transactions.
|
|
486
|
-
__publicField(this, "transactions", /* @__PURE__ */ new Map());
|
|
487
|
-
// List of last closed transactions. Max MAX_CLOSED_TRANSACTIONS entries.
|
|
488
|
-
// Used to provide better error messages than a generic "transaction not found".
|
|
489
|
-
__publicField(this, "closedTransactions", []);
|
|
490
|
-
__publicField(this, "driverAdapter");
|
|
491
399
|
this.driverAdapter = driverAdapter;
|
|
492
400
|
}
|
|
493
401
|
async startTransaction(options) {
|
|
494
402
|
const validatedOptions = this.validateOptions(options);
|
|
495
403
|
const transaction = {
|
|
496
|
-
id:
|
|
404
|
+
id: await randomUUID(),
|
|
497
405
|
status: "waiting",
|
|
498
406
|
timer: void 0,
|
|
499
407
|
timeout: validatedOptions.timeout,
|
|
@@ -502,28 +410,17 @@ var TransactionManager = class {
|
|
|
502
410
|
};
|
|
503
411
|
this.transactions.set(transaction.id, transaction);
|
|
504
412
|
transaction.timer = this.startTransactionTimeout(transaction.id, validatedOptions.maxWait);
|
|
505
|
-
|
|
506
|
-
|
|
413
|
+
let startedTransaction;
|
|
414
|
+
try {
|
|
415
|
+
startedTransaction = await this.driverAdapter.startTransaction(validatedOptions.isolationLevel);
|
|
416
|
+
} catch (error) {
|
|
507
417
|
throw new TransactionDriverAdapterError("Failed to start transaction.", {
|
|
508
|
-
driverAdapterError:
|
|
418
|
+
driverAdapterError: error
|
|
509
419
|
});
|
|
510
|
-
if (this.requiresSettingIsolationLevelFirst() && validatedOptions.isolationLevel) {
|
|
511
|
-
await txContext.value.executeRaw(ISOLATION_LEVEL_QUERY(validatedOptions.isolationLevel));
|
|
512
|
-
}
|
|
513
|
-
const startedTransaction = await txContext.value.startTransaction();
|
|
514
|
-
if (!startedTransaction.ok)
|
|
515
|
-
throw new TransactionDriverAdapterError("Failed to start transaction.", {
|
|
516
|
-
driverAdapterError: startedTransaction.error
|
|
517
|
-
});
|
|
518
|
-
if (!startedTransaction.value.options.usePhantomQuery) {
|
|
519
|
-
await startedTransaction.value.executeRaw({ sql: "BEGIN", args: [], argTypes: [] });
|
|
520
|
-
if (!this.requiresSettingIsolationLevelFirst() && validatedOptions.isolationLevel) {
|
|
521
|
-
await txContext.value.executeRaw(ISOLATION_LEVEL_QUERY(validatedOptions.isolationLevel));
|
|
522
|
-
}
|
|
523
420
|
}
|
|
524
421
|
switch (transaction.status) {
|
|
525
422
|
case "waiting":
|
|
526
|
-
transaction.transaction = startedTransaction
|
|
423
|
+
transaction.transaction = startedTransaction;
|
|
527
424
|
clearTimeout(transaction.timer);
|
|
528
425
|
transaction.timer = void 0;
|
|
529
426
|
transaction.status = "running";
|
|
@@ -603,20 +500,24 @@ var TransactionManager = class {
|
|
|
603
500
|
debug("Closing transaction.", { transactionId: tx.id, status });
|
|
604
501
|
tx.status = status;
|
|
605
502
|
if (tx.transaction && status === "committed") {
|
|
606
|
-
|
|
607
|
-
|
|
503
|
+
try {
|
|
504
|
+
await tx.transaction.commit();
|
|
505
|
+
} catch (error) {
|
|
608
506
|
throw new TransactionDriverAdapterError("Failed to commit transaction.", {
|
|
609
|
-
driverAdapterError:
|
|
507
|
+
driverAdapterError: error
|
|
610
508
|
});
|
|
509
|
+
}
|
|
611
510
|
if (!tx.transaction.options.usePhantomQuery) {
|
|
612
511
|
await tx.transaction.executeRaw(COMMIT_QUERY());
|
|
613
512
|
}
|
|
614
513
|
} else if (tx.transaction) {
|
|
615
|
-
|
|
616
|
-
|
|
514
|
+
try {
|
|
515
|
+
await tx.transaction.rollback();
|
|
516
|
+
} catch (error) {
|
|
617
517
|
throw new TransactionDriverAdapterError("Failed to rollback transaction.", {
|
|
618
|
-
driverAdapterError:
|
|
518
|
+
driverAdapterError: error
|
|
619
519
|
});
|
|
520
|
+
}
|
|
620
521
|
if (!tx.transaction.options.usePhantomQuery) {
|
|
621
522
|
await tx.transaction.executeRaw(ROLLBACK_QUERY());
|
|
622
523
|
}
|
|
@@ -632,22 +533,15 @@ var TransactionManager = class {
|
|
|
632
533
|
validateOptions(options) {
|
|
633
534
|
if (!options.timeout) throw new TransactionManagerError("timeout is required");
|
|
634
535
|
if (!options.maxWait) throw new TransactionManagerError("maxWait is required");
|
|
635
|
-
if (options.isolationLevel === "
|
|
636
|
-
throw new InvalidTransactionIsolationLevelError(options.isolationLevel);
|
|
637
|
-
if (this.driverAdapter.provider === "sqlite" && options.isolationLevel && options.isolationLevel !== "Serializable" /* Serializable */)
|
|
638
|
-
throw new InvalidTransactionIsolationLevelError(options.isolationLevel);
|
|
536
|
+
if (options.isolationLevel === "SNAPSHOT") throw new InvalidTransactionIsolationLevelError(options.isolationLevel);
|
|
639
537
|
return {
|
|
640
538
|
...options,
|
|
641
539
|
timeout: options.timeout,
|
|
642
540
|
maxWait: options.maxWait
|
|
643
541
|
};
|
|
644
542
|
}
|
|
645
|
-
requiresSettingIsolationLevelFirst() {
|
|
646
|
-
return this.driverAdapter.provider === "mysql";
|
|
647
|
-
}
|
|
648
543
|
};
|
|
649
544
|
export {
|
|
650
|
-
IsolationLevel,
|
|
651
545
|
QueryInterpreter,
|
|
652
546
|
TransactionManager,
|
|
653
547
|
TransactionManagerError,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SqlQueryable } from '@prisma/driver-adapter-utils';
|
|
2
2
|
import { QueryEvent } from '../events';
|
|
3
3
|
import { QueryPlanNode } from '../QueryPlan';
|
|
4
4
|
export type QueryInterpreterOptions = {
|
|
5
|
-
queryable:
|
|
5
|
+
queryable: SqlQueryable;
|
|
6
6
|
placeholderValues: Record<string, unknown>;
|
|
7
7
|
onQuery?: (event: QueryEvent) => void;
|
|
8
8
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { SqlQuery } from '@prisma/driver-adapter-utils';
|
|
2
|
-
import { QueryPlanDbQuery } from '../QueryPlan';
|
|
2
|
+
import type { QueryPlanDbQuery } from '../QueryPlan';
|
|
3
3
|
import { ScopeBindings } from './scope';
|
|
4
|
-
export declare function renderQuery(
|
|
4
|
+
export declare function renderQuery(dbQuery: QueryPlanDbQuery, scope: ScopeBindings): SqlQuery;
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
ReadUncommitted = "ReadUncommitted",
|
|
3
|
-
ReadCommitted = "ReadCommitted",
|
|
4
|
-
RepeatableRead = "RepeatableRead",
|
|
5
|
-
Snapshot = "Snapshot",
|
|
6
|
-
Serializable = "Serializable"
|
|
7
|
-
}
|
|
1
|
+
import type { IsolationLevel } from '@prisma/driver-adapter-utils';
|
|
8
2
|
export type Options = {
|
|
9
3
|
maxWait?: number;
|
|
10
4
|
timeout?: number;
|
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SqlDriverAdapter, Transaction } from '@prisma/driver-adapter-utils';
|
|
2
2
|
import { Options, TransactionInfo } from './Transaction';
|
|
3
3
|
export declare class TransactionManager {
|
|
4
4
|
private transactions;
|
|
5
5
|
private closedTransactions;
|
|
6
6
|
private readonly driverAdapter;
|
|
7
7
|
constructor({ driverAdapter }: {
|
|
8
|
-
driverAdapter:
|
|
8
|
+
driverAdapter: SqlDriverAdapter;
|
|
9
9
|
});
|
|
10
10
|
startTransaction(options: Options): Promise<TransactionInfo>;
|
|
11
11
|
commitTransaction(transactionId: string): Promise<void>;
|
|
12
12
|
rollbackTransaction(transactionId: string): Promise<void>;
|
|
13
|
-
getTransaction(txInfo: TransactionInfo, operation: string):
|
|
13
|
+
getTransaction(txInfo: TransactionInfo, operation: string): Transaction;
|
|
14
14
|
private getActiveTransaction;
|
|
15
15
|
cancelAllTransactions(): Promise<void>;
|
|
16
16
|
private startTransactionTimeout;
|
|
17
17
|
private closeTransaction;
|
|
18
18
|
private validateOptions;
|
|
19
|
-
private requiresSettingIsolationLevelFirst;
|
|
20
19
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/client-engine-runtime",
|
|
3
|
-
"version": "6.6.0-dev.
|
|
3
|
+
"version": "6.6.0-dev.70",
|
|
4
4
|
"description": "This package is intended for Prisma's internal use",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
"repository": {
|
|
21
21
|
"type": "git",
|
|
22
22
|
"url": "https://github.com/prisma/prisma.git",
|
|
23
|
-
"directory": "packages/
|
|
23
|
+
"directory": "packages/client-engine-runtime"
|
|
24
24
|
},
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@prisma/debug": "6.6.0-dev.
|
|
28
|
-
"@prisma/driver-adapter-utils": "6.6.0-dev.
|
|
27
|
+
"@prisma/debug": "6.6.0-dev.70",
|
|
28
|
+
"@prisma/driver-adapter-utils": "6.6.0-dev.70"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/jest": "29.5.14",
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Value } from './scope';
|
|
2
|
-
/**
|
|
3
|
-
* A `QueryPlanDbQuery` in which all placeholders have been substituted with
|
|
4
|
-
* their values from the environment.
|
|
5
|
-
*/
|
|
6
|
-
export type QueryWithSubstitutedPlaceholders = {
|
|
7
|
-
query: string;
|
|
8
|
-
params: Value[];
|
|
9
|
-
};
|
|
10
|
-
export declare function renderQueryTemplate({ query, params, }: QueryWithSubstitutedPlaceholders): QueryWithSubstitutedPlaceholders;
|
|
File without changes
|