@prisma-next/sql-lane 0.3.0-dev.11 → 0.3.0-dev.113
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/LICENSE +201 -0
- package/README.md +18 -1
- package/dist/builder-DpxuiFO4.d.mts +118 -0
- package/dist/builder-DpxuiFO4.d.mts.map +1 -0
- package/dist/builder-MYJh5-Gn.mjs +1153 -0
- package/dist/builder-MYJh5-Gn.mjs.map +1 -0
- package/dist/exports/sql.d.mts +3 -0
- package/dist/exports/sql.mjs +3 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +3 -0
- package/package.json +29 -24
- package/src/raw.ts +9 -2
- package/src/sql/builder.ts +12 -9
- package/src/sql/context.ts +3 -3
- package/src/sql/include-builder.ts +109 -70
- package/src/sql/join-builder.ts +21 -11
- package/src/sql/mutation-builder.ts +94 -107
- package/src/sql/plan.ts +88 -128
- package/src/sql/predicate-builder.ts +74 -65
- package/src/sql/projection.ts +17 -12
- package/src/sql/select-builder.ts +64 -102
- package/src/types/internal.ts +6 -5
- package/src/utils/errors.ts +2 -2
- package/src/utils/state.ts +5 -6
- package/dist/chunk-AWSKRSFP.js +0 -1569
- package/dist/chunk-AWSKRSFP.js.map +0 -1
- package/dist/exports/sql.d.ts +0 -5
- package/dist/exports/sql.d.ts.map +0 -1
- package/dist/exports/sql.js +0 -11
- package/dist/exports/sql.js.map +0 -1
- package/dist/index.d.ts +0 -5
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -11
- package/dist/index.js.map +0 -1
- package/dist/raw.d.ts +0 -11
- package/dist/raw.d.ts.map +0 -1
- package/dist/sql/builder.d.ts +0 -11
- package/dist/sql/builder.d.ts.map +0 -1
- package/dist/sql/context.d.ts +0 -5
- package/dist/sql/context.d.ts.map +0 -1
- package/dist/sql/include-builder.d.ts +0 -35
- package/dist/sql/include-builder.d.ts.map +0 -1
- package/dist/sql/join-builder.d.ts +0 -4
- package/dist/sql/join-builder.d.ts.map +0 -1
- package/dist/sql/mutation-builder.d.ts +0 -64
- package/dist/sql/mutation-builder.d.ts.map +0 -1
- package/dist/sql/plan.d.ts +0 -4
- package/dist/sql/plan.d.ts.map +0 -1
- package/dist/sql/predicate-builder.d.ts +0 -11
- package/dist/sql/predicate-builder.d.ts.map +0 -1
- package/dist/sql/projection.d.ts +0 -18
- package/dist/sql/projection.d.ts.map +0 -1
- package/dist/sql/select-builder.d.ts +0 -35
- package/dist/sql/select-builder.d.ts.map +0 -1
- package/dist/types/internal.d.ts +0 -35
- package/dist/types/internal.d.ts.map +0 -1
- package/dist/types/public.d.ts +0 -18
- package/dist/types/public.d.ts.map +0 -1
- package/dist/utils/assertions.d.ts +0 -28
- package/dist/utils/assertions.d.ts.map +0 -1
- package/dist/utils/capabilities.d.ts +0 -4
- package/dist/utils/capabilities.d.ts.map +0 -1
- package/dist/utils/errors.d.ts +0 -30
- package/dist/utils/errors.d.ts.map +0 -1
- package/dist/utils/state.d.ts +0 -30
- package/dist/utils/state.d.ts.map +0 -1
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import type { ParamDescriptor } from '@prisma-next/contract/types';
|
|
2
1
|
import type { SqlContract, SqlStorage, StorageColumn } from '@prisma-next/sql-contract/types';
|
|
3
|
-
import
|
|
2
|
+
import {
|
|
3
|
+
AndExpr,
|
|
4
|
+
type AnyExpression,
|
|
4
5
|
BinaryExpr,
|
|
5
6
|
ColumnRef,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
DerivedTableSource,
|
|
8
|
+
JoinAst,
|
|
9
|
+
JsonArrayAggExpr,
|
|
10
|
+
JsonObjectExpr,
|
|
11
|
+
OrderByItem,
|
|
12
|
+
ProjectionItem,
|
|
13
|
+
SelectAst,
|
|
14
|
+
type TableRef,
|
|
15
|
+
TableSource,
|
|
15
16
|
} from '@prisma-next/sql-relational-core/ast';
|
|
16
17
|
import type {
|
|
17
18
|
AnyBinaryBuilder,
|
|
@@ -22,10 +23,6 @@ import type {
|
|
|
22
23
|
NestedProjection,
|
|
23
24
|
OrderBuilder,
|
|
24
25
|
} from '@prisma-next/sql-relational-core/types';
|
|
25
|
-
import {
|
|
26
|
-
extractBaseColumnRef,
|
|
27
|
-
isOperationExpr,
|
|
28
|
-
} from '@prisma-next/sql-relational-core/utils/guards';
|
|
29
26
|
import {
|
|
30
27
|
errorChildProjectionMustBeSpecified,
|
|
31
28
|
errorLimitMustBeNonNegativeInteger,
|
|
@@ -55,16 +52,14 @@ export class IncludeChildBuilderImpl<
|
|
|
55
52
|
> implements IncludeChildBuilder<TContract, CodecTypes, ChildRow>
|
|
56
53
|
{
|
|
57
54
|
private readonly contract: TContract;
|
|
58
|
-
private readonly codecTypes: CodecTypes;
|
|
59
55
|
private readonly table: TableRef;
|
|
60
56
|
private childProjection?: ProjectionState;
|
|
61
57
|
private childWhere?: BinaryBuilder;
|
|
62
58
|
private childOrderBy?: OrderBuilder;
|
|
63
59
|
private childLimit?: number;
|
|
64
60
|
|
|
65
|
-
constructor(contract: TContract,
|
|
61
|
+
constructor(contract: TContract, table: TableRef) {
|
|
66
62
|
this.contract = contract;
|
|
67
|
-
this.codecTypes = codecTypes;
|
|
68
63
|
this.table = table;
|
|
69
64
|
}
|
|
70
65
|
|
|
@@ -76,7 +71,7 @@ export class IncludeChildBuilderImpl<
|
|
|
76
71
|
TContract,
|
|
77
72
|
CodecTypes,
|
|
78
73
|
InferNestedProjectionRow<P, CodecTypes>
|
|
79
|
-
>(this.contract, this.
|
|
74
|
+
>(this.contract, this.table);
|
|
80
75
|
builder.childProjection = projectionState;
|
|
81
76
|
if (this.childWhere !== undefined) {
|
|
82
77
|
builder.childWhere = this.childWhere;
|
|
@@ -93,7 +88,6 @@ export class IncludeChildBuilderImpl<
|
|
|
93
88
|
where(expr: AnyBinaryBuilder): IncludeChildBuilderImpl<TContract, CodecTypes, ChildRow> {
|
|
94
89
|
const builder = new IncludeChildBuilderImpl<TContract, CodecTypes, ChildRow>(
|
|
95
90
|
this.contract,
|
|
96
|
-
this.codecTypes,
|
|
97
91
|
this.table,
|
|
98
92
|
);
|
|
99
93
|
if (this.childProjection !== undefined) {
|
|
@@ -112,7 +106,6 @@ export class IncludeChildBuilderImpl<
|
|
|
112
106
|
orderBy(order: AnyOrderBuilder): IncludeChildBuilderImpl<TContract, CodecTypes, ChildRow> {
|
|
113
107
|
const builder = new IncludeChildBuilderImpl<TContract, CodecTypes, ChildRow>(
|
|
114
108
|
this.contract,
|
|
115
|
-
this.codecTypes,
|
|
116
109
|
this.table,
|
|
117
110
|
);
|
|
118
111
|
if (this.childProjection !== undefined) {
|
|
@@ -135,7 +128,6 @@ export class IncludeChildBuilderImpl<
|
|
|
135
128
|
|
|
136
129
|
const builder = new IncludeChildBuilderImpl<TContract, CodecTypes, ChildRow>(
|
|
137
130
|
this.contract,
|
|
138
|
-
this.codecTypes,
|
|
139
131
|
this.table,
|
|
140
132
|
);
|
|
141
133
|
if (this.childProjection !== undefined) {
|
|
@@ -181,68 +173,115 @@ export class IncludeChildBuilderImpl<
|
|
|
181
173
|
}
|
|
182
174
|
}
|
|
183
175
|
|
|
184
|
-
|
|
176
|
+
function buildIncludeOrderArtifacts(
|
|
185
177
|
include: IncludeState,
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
178
|
+
rowsAlias: string,
|
|
179
|
+
): {
|
|
180
|
+
readonly childOrderBy: ReadonlyArray<OrderByItem> | undefined;
|
|
181
|
+
readonly hiddenOrderProjection: ReadonlyArray<ProjectionItem>;
|
|
182
|
+
readonly aggregateOrderBy: ReadonlyArray<OrderByItem> | undefined;
|
|
183
|
+
} {
|
|
191
184
|
const childOrderBy = include.childOrderBy
|
|
192
185
|
? (() => {
|
|
193
186
|
const orderBy = include.childOrderBy as OrderBuilder<string, StorageColumn, unknown>;
|
|
194
|
-
|
|
195
|
-
const expr: ColumnRef | OperationExpr = (() => {
|
|
196
|
-
if (isOperationExpr(orderExpr)) {
|
|
197
|
-
const baseCol = extractBaseColumnRef(orderExpr);
|
|
198
|
-
return createColumnRef(baseCol.table, baseCol.column);
|
|
199
|
-
}
|
|
200
|
-
// orderExpr is ColumnBuilder - TypeScript can't narrow properly
|
|
201
|
-
const colBuilder = orderExpr as { table: string; column: string };
|
|
202
|
-
return createColumnRef(colBuilder.table, colBuilder.column);
|
|
203
|
-
})();
|
|
204
|
-
return [createOrderByItem(expr, orderBy.dir)];
|
|
187
|
+
return [new OrderByItem(orderBy.expr, orderBy.dir)];
|
|
205
188
|
})()
|
|
206
189
|
: undefined;
|
|
207
190
|
|
|
208
|
-
|
|
191
|
+
if (!childOrderBy || childOrderBy.length === 0) {
|
|
192
|
+
return {
|
|
193
|
+
childOrderBy: undefined,
|
|
194
|
+
hiddenOrderProjection: [],
|
|
195
|
+
aggregateOrderBy: undefined,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const hiddenOrderProjection = childOrderBy.map((orderItem, index) =>
|
|
200
|
+
ProjectionItem.of(`${include.alias}__order_${index}`, orderItem.expr),
|
|
201
|
+
);
|
|
202
|
+
const aggregateOrderBy = hiddenOrderProjection.map((projection, index) => {
|
|
203
|
+
const orderItem = childOrderBy[index];
|
|
204
|
+
if (!orderItem) {
|
|
205
|
+
throw new Error(`Missing include order metadata at index ${index}`);
|
|
206
|
+
}
|
|
207
|
+
return new OrderByItem(ColumnRef.of(rowsAlias, projection.alias), orderItem.dir);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
childOrderBy,
|
|
212
|
+
hiddenOrderProjection,
|
|
213
|
+
aggregateOrderBy,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function buildChildProjectionItems(include: IncludeState): ProjectionItem[] {
|
|
218
|
+
return include.childProjection.aliases.map((alias, idx) => {
|
|
219
|
+
const column = include.childProjection.columns[idx];
|
|
220
|
+
if (!column) {
|
|
221
|
+
errorMissingColumnForAlias(alias, idx);
|
|
222
|
+
}
|
|
223
|
+
return ProjectionItem.of(alias, column.toExpr());
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export interface IncludeJoinArtifact {
|
|
228
|
+
readonly join: JoinAst;
|
|
229
|
+
readonly projection: ProjectionItem;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export function buildIncludeJoinArtifact(
|
|
233
|
+
include: IncludeState,
|
|
234
|
+
contract: SqlContract<SqlStorage>,
|
|
235
|
+
paramsMap: Record<string, unknown>,
|
|
236
|
+
): IncludeJoinArtifact {
|
|
237
|
+
let childWhere: AnyExpression | undefined;
|
|
209
238
|
if (include.childWhere) {
|
|
210
|
-
const whereResult = buildWhereExpr(
|
|
211
|
-
contract,
|
|
212
|
-
include.childWhere,
|
|
213
|
-
paramsMap,
|
|
214
|
-
paramDescriptors,
|
|
215
|
-
paramValues,
|
|
216
|
-
);
|
|
239
|
+
const whereResult = buildWhereExpr(contract, include.childWhere, paramsMap);
|
|
217
240
|
childWhere = whereResult.expr;
|
|
218
241
|
}
|
|
219
242
|
|
|
220
243
|
const onLeft = include.on.left as { table: string; column: string };
|
|
221
244
|
const onRight = include.on.right as { table: string; column: string };
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
245
|
+
const onExpr = BinaryExpr.eq(
|
|
246
|
+
ColumnRef.of(onLeft.table, onLeft.column),
|
|
247
|
+
ColumnRef.of(onRight.table, onRight.column),
|
|
248
|
+
);
|
|
249
|
+
const rowsWhere = childWhere ? AndExpr.of([onExpr, childWhere]) : onExpr;
|
|
250
|
+
|
|
251
|
+
const childProjectItems = buildChildProjectionItems(include);
|
|
252
|
+
const rowsAlias = `${include.alias}__rows`;
|
|
253
|
+
const { childOrderBy, hiddenOrderProjection, aggregateOrderBy } = buildIncludeOrderArtifacts(
|
|
254
|
+
include,
|
|
255
|
+
rowsAlias,
|
|
256
|
+
);
|
|
257
|
+
let childRowsAst = SelectAst.from(TableSource.named(include.table.name, include.table.alias))
|
|
258
|
+
.withProjection([...childProjectItems, ...hiddenOrderProjection])
|
|
259
|
+
.withWhere(rowsWhere);
|
|
260
|
+
if (childOrderBy) {
|
|
261
|
+
childRowsAst = childRowsAst.withOrderBy(childOrderBy);
|
|
262
|
+
}
|
|
263
|
+
if (typeof include.childLimit === 'number') {
|
|
264
|
+
childRowsAst = childRowsAst.withLimit(include.childLimit);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const aggregatedAlias = `${include.alias}_lateral`;
|
|
268
|
+
const jsonObjectExpr = JsonObjectExpr.fromEntries(
|
|
269
|
+
childProjectItems.map((item) =>
|
|
270
|
+
JsonObjectExpr.entry(item.alias, ColumnRef.of(rowsAlias, item.alias)),
|
|
271
|
+
),
|
|
272
|
+
);
|
|
273
|
+
const jsonAggExpr = JsonArrayAggExpr.of(jsonObjectExpr, 'emptyArray', aggregateOrderBy);
|
|
274
|
+
|
|
275
|
+
const aggregateSelect = SelectAst.from(
|
|
276
|
+
DerivedTableSource.as(rowsAlias, childRowsAst),
|
|
277
|
+
).withProjection([ProjectionItem.of(include.alias, jsonAggExpr)]);
|
|
225
278
|
|
|
226
279
|
return {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
...(childOrderBy ? { orderBy: childOrderBy } : {}),
|
|
234
|
-
...(typeof include.childLimit === 'number' ? { limit: include.childLimit } : {}),
|
|
235
|
-
project: include.childProjection.aliases.map((alias, idx) => {
|
|
236
|
-
const column = include.childProjection.columns[idx];
|
|
237
|
-
if (!column || !alias) {
|
|
238
|
-
errorMissingColumnForAlias(alias ?? 'unknown', idx);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
return {
|
|
242
|
-
alias,
|
|
243
|
-
expr: createColumnRef(column.table, column.column),
|
|
244
|
-
};
|
|
245
|
-
}),
|
|
246
|
-
},
|
|
280
|
+
join: JoinAst.left(
|
|
281
|
+
DerivedTableSource.as(aggregatedAlias, aggregateSelect),
|
|
282
|
+
AndExpr.true(),
|
|
283
|
+
true,
|
|
284
|
+
),
|
|
285
|
+
projection: ProjectionItem.of(include.alias, ColumnRef.of(aggregatedAlias, include.alias)),
|
|
247
286
|
};
|
|
248
287
|
}
|
package/src/sql/join-builder.ts
CHANGED
|
@@ -1,18 +1,28 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
createColumnRef,
|
|
4
|
-
createJoin,
|
|
5
|
-
createJoinOnExpr,
|
|
6
|
-
createTableRef,
|
|
7
|
-
} from '@prisma-next/sql-relational-core/ast';
|
|
1
|
+
import { ColumnRef, EqColJoinOn, JoinAst, TableSource } from '@prisma-next/sql-relational-core/ast';
|
|
8
2
|
import type { JoinState } from '../utils/state';
|
|
9
3
|
|
|
10
4
|
export function buildJoinAst(join: JoinState): JoinAst {
|
|
11
5
|
// TypeScript can't narrow ColumnBuilder properly, so we assert
|
|
12
6
|
const onLeft = join.on.left as { table: string; column: string };
|
|
13
7
|
const onRight = join.on.right as { table: string; column: string };
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
const onExpr = EqColJoinOn.of(
|
|
9
|
+
ColumnRef.of(onLeft.table, onLeft.column),
|
|
10
|
+
ColumnRef.of(onRight.table, onRight.column),
|
|
11
|
+
);
|
|
12
|
+
const tableSource = TableSource.named(join.table.name, join.table.alias);
|
|
13
|
+
|
|
14
|
+
switch (join.joinType) {
|
|
15
|
+
case 'inner':
|
|
16
|
+
return JoinAst.inner(tableSource, onExpr);
|
|
17
|
+
case 'left':
|
|
18
|
+
return JoinAst.left(tableSource, onExpr);
|
|
19
|
+
case 'right':
|
|
20
|
+
return JoinAst.right(tableSource, onExpr);
|
|
21
|
+
case 'full':
|
|
22
|
+
return JoinAst.full(tableSource, onExpr);
|
|
23
|
+
default: {
|
|
24
|
+
const exhaustiveCheck: never = join.joinType;
|
|
25
|
+
throw new Error(`Unsupported join type: ${String(exhaustiveCheck)}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
18
28
|
}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import type { ParamDescriptor } from '@prisma-next/contract/types';
|
|
2
1
|
import type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
3
|
-
import type { ColumnRef, ParamRef, TableRef } from '@prisma-next/sql-relational-core/ast';
|
|
4
2
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
ColumnRef,
|
|
4
|
+
DeleteAst,
|
|
5
|
+
InsertAst,
|
|
6
|
+
ParamRef,
|
|
7
|
+
type TableRef,
|
|
8
|
+
TableSource,
|
|
9
|
+
UpdateAst,
|
|
11
10
|
} from '@prisma-next/sql-relational-core/ast';
|
|
12
11
|
import type { SqlQueryPlan } from '@prisma-next/sql-relational-core/plan';
|
|
13
|
-
import type {
|
|
12
|
+
import type { ExecutionContext } from '@prisma-next/sql-relational-core/query-lane-context';
|
|
14
13
|
import type {
|
|
15
14
|
AnyColumnBuilder,
|
|
16
15
|
BinaryBuilder,
|
|
@@ -18,7 +17,9 @@ import type {
|
|
|
18
17
|
InferReturningRow,
|
|
19
18
|
ParamPlaceholder,
|
|
20
19
|
SqlBuilderOptions,
|
|
20
|
+
UnaryBuilder,
|
|
21
21
|
} from '@prisma-next/sql-relational-core/types';
|
|
22
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
22
23
|
import { checkReturningCapability } from '../utils/capabilities';
|
|
23
24
|
import {
|
|
24
25
|
errorFailedToBuildWhereClause,
|
|
@@ -32,6 +33,18 @@ import type { ProjectionState } from '../utils/state';
|
|
|
32
33
|
import { buildMeta } from './plan';
|
|
33
34
|
import { buildWhereExpr } from './predicate-builder';
|
|
34
35
|
|
|
36
|
+
function deriveParamsFromAst(ast: { collectParamRefs(): ParamRef[] }) {
|
|
37
|
+
const collected = [...new Set(ast.collectParamRefs())];
|
|
38
|
+
return {
|
|
39
|
+
paramValues: collected.map((p) => p.value),
|
|
40
|
+
paramDescriptors: collected.map((p) => ({
|
|
41
|
+
...ifDefined('name', p.name),
|
|
42
|
+
source: 'dsl' as const,
|
|
43
|
+
...ifDefined('codecId', p.codecId),
|
|
44
|
+
})),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
35
48
|
export interface InsertBuilder<
|
|
36
49
|
TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
|
|
37
50
|
CodecTypes extends Record<string, { readonly output: unknown }> = Record<string, never>,
|
|
@@ -48,7 +61,7 @@ export interface UpdateBuilder<
|
|
|
48
61
|
CodecTypes extends Record<string, { readonly output: unknown }> = Record<string, never>,
|
|
49
62
|
Row = unknown,
|
|
50
63
|
> {
|
|
51
|
-
where(predicate: BinaryBuilder): UpdateBuilder<TContract, CodecTypes, Row>;
|
|
64
|
+
where(predicate: BinaryBuilder | UnaryBuilder): UpdateBuilder<TContract, CodecTypes, Row>;
|
|
52
65
|
returning<const Columns extends readonly AnyColumnBuilder[]>(
|
|
53
66
|
...columns: Columns
|
|
54
67
|
): UpdateBuilder<TContract, CodecTypes, InferReturningRow<Columns>>;
|
|
@@ -60,7 +73,7 @@ export interface DeleteBuilder<
|
|
|
60
73
|
CodecTypes extends Record<string, { readonly output: unknown }> = Record<string, never>,
|
|
61
74
|
Row = unknown,
|
|
62
75
|
> {
|
|
63
|
-
where(predicate: BinaryBuilder): DeleteBuilder<TContract, CodecTypes, Row>;
|
|
76
|
+
where(predicate: BinaryBuilder | UnaryBuilder): DeleteBuilder<TContract, CodecTypes, Row>;
|
|
64
77
|
returning<const Columns extends readonly AnyColumnBuilder[]>(
|
|
65
78
|
...columns: Columns
|
|
66
79
|
): DeleteBuilder<TContract, CodecTypes, InferReturningRow<Columns>>;
|
|
@@ -74,7 +87,7 @@ export class InsertBuilderImpl<
|
|
|
74
87
|
> implements InsertBuilder<TContract, CodecTypes, Row>
|
|
75
88
|
{
|
|
76
89
|
private readonly contract: TContract;
|
|
77
|
-
private readonly context:
|
|
90
|
+
private readonly context: ExecutionContext<TContract>;
|
|
78
91
|
private readonly table: TableRef;
|
|
79
92
|
private readonly values: Record<string, ParamPlaceholder>;
|
|
80
93
|
private returningColumns: AnyColumnBuilder[] = [];
|
|
@@ -108,9 +121,6 @@ export class InsertBuilderImpl<
|
|
|
108
121
|
|
|
109
122
|
build(options?: BuildOptions): SqlQueryPlan<Row> {
|
|
110
123
|
const paramsMap = (options?.params ?? {}) as Record<string, unknown>;
|
|
111
|
-
const paramDescriptors: ParamDescriptor[] = [];
|
|
112
|
-
const paramValues: unknown[] = [];
|
|
113
|
-
const paramCodecs: Record<string, string> = {};
|
|
114
124
|
|
|
115
125
|
const contractTable = this.contract.storage.tables[this.table.name];
|
|
116
126
|
if (!contractTable) {
|
|
@@ -119,7 +129,8 @@ export class InsertBuilderImpl<
|
|
|
119
129
|
|
|
120
130
|
const values: Record<string, ColumnRef | ParamRef> = {};
|
|
121
131
|
for (const [columnName, placeholder] of Object.entries(this.values)) {
|
|
122
|
-
|
|
132
|
+
const columnMeta = contractTable.columns[columnName];
|
|
133
|
+
if (!columnMeta) {
|
|
123
134
|
errorUnknownColumn(columnName, this.table.name);
|
|
124
135
|
}
|
|
125
136
|
|
|
@@ -129,41 +140,44 @@ export class InsertBuilderImpl<
|
|
|
129
140
|
}
|
|
130
141
|
|
|
131
142
|
const value = paramsMap[paramName];
|
|
132
|
-
|
|
143
|
+
values[columnName] = ParamRef.of(value, {
|
|
144
|
+
name: paramName,
|
|
145
|
+
codecId: columnMeta.codecId,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
133
148
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
149
|
+
const appliedDefaults = this.context.applyMutationDefaults({
|
|
150
|
+
op: 'create',
|
|
151
|
+
table: this.table.name,
|
|
152
|
+
values,
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
for (const defaultValue of appliedDefaults) {
|
|
156
|
+
const columnMeta = contractTable.columns[defaultValue.column];
|
|
157
|
+
if (!columnMeta) {
|
|
158
|
+
errorUnknownColumn(defaultValue.column, this.table.name);
|
|
138
159
|
}
|
|
139
160
|
|
|
140
|
-
|
|
141
|
-
name:
|
|
142
|
-
|
|
143
|
-
refs: { table: this.table.name, column: columnName },
|
|
144
|
-
...(codecId ? { codecId } : {}),
|
|
145
|
-
...(columnMeta?.nativeType ? { nativeType: columnMeta.nativeType } : {}),
|
|
146
|
-
...(columnMeta?.nullable !== undefined ? { nullable: columnMeta.nullable } : {}),
|
|
161
|
+
values[defaultValue.column] = ParamRef.of(defaultValue.value, {
|
|
162
|
+
name: defaultValue.column,
|
|
163
|
+
codecId: columnMeta.codecId,
|
|
147
164
|
});
|
|
148
|
-
|
|
149
|
-
values[columnName] = createParamRef(index, paramName);
|
|
150
165
|
}
|
|
151
166
|
|
|
152
167
|
const returning: ColumnRef[] = this.returningColumns.map((col) => {
|
|
153
|
-
// TypeScript can't narrow ColumnBuilder properly
|
|
154
168
|
const c = col as unknown as { table: string; column: string };
|
|
155
|
-
return
|
|
169
|
+
return ColumnRef.of(c.table, c.column);
|
|
156
170
|
});
|
|
157
171
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
172
|
+
let ast = InsertAst.into(TableSource.named(this.table.name)).withValues(values);
|
|
173
|
+
if (returning.length > 0) {
|
|
174
|
+
ast = ast.withReturning(returning);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const { paramValues, paramDescriptors } = deriveParamsFromAst(ast);
|
|
163
178
|
|
|
164
179
|
const returningProjection: ProjectionState = {
|
|
165
180
|
aliases: this.returningColumns.map((col) => {
|
|
166
|
-
// TypeScript can't narrow ColumnBuilder properly
|
|
167
181
|
const c = col as unknown as { column: string };
|
|
168
182
|
return c.column;
|
|
169
183
|
}),
|
|
@@ -175,7 +189,6 @@ export class InsertBuilderImpl<
|
|
|
175
189
|
table: this.table,
|
|
176
190
|
projection: returning.length > 0 ? returningProjection : { aliases: [], columns: [] },
|
|
177
191
|
paramDescriptors,
|
|
178
|
-
...(Object.keys(paramCodecs).length > 0 ? { paramCodecs } : {}),
|
|
179
192
|
});
|
|
180
193
|
|
|
181
194
|
const queryPlan: SqlQueryPlan<Row> = Object.freeze({
|
|
@@ -203,10 +216,10 @@ export class UpdateBuilderImpl<
|
|
|
203
216
|
> implements UpdateBuilder<TContract, CodecTypes, Row>
|
|
204
217
|
{
|
|
205
218
|
private readonly contract: TContract;
|
|
206
|
-
private readonly context:
|
|
219
|
+
private readonly context: ExecutionContext<TContract>;
|
|
207
220
|
private readonly table: TableRef;
|
|
208
221
|
private readonly set: Record<string, ParamPlaceholder>;
|
|
209
|
-
private wherePredicate?: BinaryBuilder;
|
|
222
|
+
private wherePredicate?: BinaryBuilder | UnaryBuilder;
|
|
210
223
|
private returningColumns: AnyColumnBuilder[] = [];
|
|
211
224
|
|
|
212
225
|
constructor(
|
|
@@ -220,7 +233,7 @@ export class UpdateBuilderImpl<
|
|
|
220
233
|
this.set = set;
|
|
221
234
|
}
|
|
222
235
|
|
|
223
|
-
where(predicate: BinaryBuilder): UpdateBuilder<TContract, CodecTypes, Row> {
|
|
236
|
+
where(predicate: BinaryBuilder | UnaryBuilder): UpdateBuilder<TContract, CodecTypes, Row> {
|
|
224
237
|
const builder = new UpdateBuilderImpl<TContract, CodecTypes, Row>(
|
|
225
238
|
{
|
|
226
239
|
context: this.context,
|
|
@@ -258,9 +271,6 @@ export class UpdateBuilderImpl<
|
|
|
258
271
|
}
|
|
259
272
|
|
|
260
273
|
const paramsMap = (options?.params ?? {}) as Record<string, unknown>;
|
|
261
|
-
const paramDescriptors: ParamDescriptor[] = [];
|
|
262
|
-
const paramValues: unknown[] = [];
|
|
263
|
-
const paramCodecs: Record<string, string> = {};
|
|
264
274
|
|
|
265
275
|
const contractTable = this.contract.storage.tables[this.table.name];
|
|
266
276
|
if (!contractTable) {
|
|
@@ -269,7 +279,8 @@ export class UpdateBuilderImpl<
|
|
|
269
279
|
|
|
270
280
|
const set: Record<string, ColumnRef | ParamRef> = {};
|
|
271
281
|
for (const [columnName, placeholder] of Object.entries(this.set)) {
|
|
272
|
-
|
|
282
|
+
const columnMeta = contractTable.columns[columnName];
|
|
283
|
+
if (!columnMeta) {
|
|
273
284
|
errorUnknownColumn(columnName, this.table.name);
|
|
274
285
|
}
|
|
275
286
|
|
|
@@ -279,58 +290,50 @@ export class UpdateBuilderImpl<
|
|
|
279
290
|
}
|
|
280
291
|
|
|
281
292
|
const value = paramsMap[paramName];
|
|
282
|
-
|
|
293
|
+
set[columnName] = ParamRef.of(value, {
|
|
294
|
+
name: paramName,
|
|
295
|
+
codecId: columnMeta.codecId,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
283
298
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
299
|
+
const appliedDefaults = this.context.applyMutationDefaults({
|
|
300
|
+
op: 'update',
|
|
301
|
+
table: this.table.name,
|
|
302
|
+
values: set,
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
for (const defaultValue of appliedDefaults) {
|
|
306
|
+
const columnMeta = contractTable.columns[defaultValue.column];
|
|
307
|
+
if (!columnMeta) {
|
|
308
|
+
errorUnknownColumn(defaultValue.column, this.table.name);
|
|
288
309
|
}
|
|
289
310
|
|
|
290
|
-
|
|
291
|
-
name:
|
|
292
|
-
|
|
293
|
-
refs: { table: this.table.name, column: columnName },
|
|
294
|
-
...(codecId ? { codecId } : {}),
|
|
295
|
-
...(columnMeta?.nativeType ? { nativeType: columnMeta.nativeType } : {}),
|
|
296
|
-
...(columnMeta?.nullable !== undefined ? { nullable: columnMeta.nullable } : {}),
|
|
311
|
+
set[defaultValue.column] = ParamRef.of(defaultValue.value, {
|
|
312
|
+
name: defaultValue.column,
|
|
313
|
+
codecId: columnMeta.codecId,
|
|
297
314
|
});
|
|
298
|
-
|
|
299
|
-
set[columnName] = createParamRef(index, paramName);
|
|
300
315
|
}
|
|
301
316
|
|
|
302
|
-
const whereResult = buildWhereExpr(
|
|
303
|
-
this.contract,
|
|
304
|
-
this.wherePredicate,
|
|
305
|
-
paramsMap,
|
|
306
|
-
paramDescriptors,
|
|
307
|
-
paramValues,
|
|
308
|
-
);
|
|
317
|
+
const whereResult = buildWhereExpr(this.contract, this.wherePredicate, paramsMap);
|
|
309
318
|
const whereExpr = whereResult.expr;
|
|
310
319
|
if (!whereExpr) {
|
|
311
320
|
errorFailedToBuildWhereClause();
|
|
312
321
|
}
|
|
313
322
|
|
|
314
|
-
if (whereResult.codecId && whereResult.paramName) {
|
|
315
|
-
paramCodecs[whereResult.paramName] = whereResult.codecId;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
323
|
const returning: ColumnRef[] = this.returningColumns.map((col) => {
|
|
319
|
-
// TypeScript can't narrow ColumnBuilder properly
|
|
320
324
|
const c = col as unknown as { table: string; column: string };
|
|
321
|
-
return
|
|
325
|
+
return ColumnRef.of(c.table, c.column);
|
|
322
326
|
});
|
|
323
327
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
});
|
|
328
|
+
let ast = UpdateAst.table(TableSource.named(this.table.name)).withSet(set).withWhere(whereExpr);
|
|
329
|
+
if (returning.length > 0) {
|
|
330
|
+
ast = ast.withReturning(returning);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const { paramValues, paramDescriptors } = deriveParamsFromAst(ast);
|
|
330
334
|
|
|
331
335
|
const returningProjection: ProjectionState = {
|
|
332
336
|
aliases: this.returningColumns.map((col) => {
|
|
333
|
-
// TypeScript can't narrow ColumnBuilder properly
|
|
334
337
|
const c = col as unknown as { column: string };
|
|
335
338
|
return c.column;
|
|
336
339
|
}),
|
|
@@ -342,7 +345,6 @@ export class UpdateBuilderImpl<
|
|
|
342
345
|
table: this.table,
|
|
343
346
|
projection: returning.length > 0 ? returningProjection : { aliases: [], columns: [] },
|
|
344
347
|
paramDescriptors,
|
|
345
|
-
...(Object.keys(paramCodecs).length > 0 ? { paramCodecs } : {}),
|
|
346
348
|
where: this.wherePredicate,
|
|
347
349
|
});
|
|
348
350
|
|
|
@@ -372,9 +374,9 @@ export class DeleteBuilderImpl<
|
|
|
372
374
|
> implements DeleteBuilder<TContract, CodecTypes, Row>
|
|
373
375
|
{
|
|
374
376
|
private readonly contract: TContract;
|
|
375
|
-
private readonly context:
|
|
377
|
+
private readonly context: ExecutionContext<TContract>;
|
|
376
378
|
private readonly table: TableRef;
|
|
377
|
-
private wherePredicate?: BinaryBuilder;
|
|
379
|
+
private wherePredicate?: BinaryBuilder | UnaryBuilder;
|
|
378
380
|
private returningColumns: AnyColumnBuilder[] = [];
|
|
379
381
|
|
|
380
382
|
constructor(options: SqlBuilderOptions<TContract>, table: TableRef) {
|
|
@@ -383,7 +385,7 @@ export class DeleteBuilderImpl<
|
|
|
383
385
|
this.table = table;
|
|
384
386
|
}
|
|
385
387
|
|
|
386
|
-
where(predicate: BinaryBuilder): DeleteBuilder<TContract, CodecTypes, Row> {
|
|
388
|
+
where(predicate: BinaryBuilder | UnaryBuilder): DeleteBuilder<TContract, CodecTypes, Row> {
|
|
387
389
|
const builder = new DeleteBuilderImpl<TContract, CodecTypes, Row>(
|
|
388
390
|
{
|
|
389
391
|
context: this.context,
|
|
@@ -419,46 +421,32 @@ export class DeleteBuilderImpl<
|
|
|
419
421
|
}
|
|
420
422
|
|
|
421
423
|
const paramsMap = (options?.params ?? {}) as Record<string, unknown>;
|
|
422
|
-
const paramDescriptors: ParamDescriptor[] = [];
|
|
423
|
-
const paramValues: unknown[] = [];
|
|
424
|
-
const paramCodecs: Record<string, string> = {};
|
|
425
424
|
|
|
426
425
|
const contractTable = this.contract.storage.tables[this.table.name];
|
|
427
426
|
if (!contractTable) {
|
|
428
427
|
errorUnknownTable(this.table.name);
|
|
429
428
|
}
|
|
430
429
|
|
|
431
|
-
const whereResult = buildWhereExpr(
|
|
432
|
-
this.contract,
|
|
433
|
-
this.wherePredicate,
|
|
434
|
-
paramsMap,
|
|
435
|
-
paramDescriptors,
|
|
436
|
-
paramValues,
|
|
437
|
-
);
|
|
430
|
+
const whereResult = buildWhereExpr(this.contract, this.wherePredicate, paramsMap);
|
|
438
431
|
const whereExpr = whereResult.expr;
|
|
439
432
|
if (!whereExpr) {
|
|
440
433
|
errorFailedToBuildWhereClause();
|
|
441
434
|
}
|
|
442
435
|
|
|
443
|
-
if (whereResult.codecId && whereResult.paramName) {
|
|
444
|
-
paramCodecs[whereResult.paramName] = whereResult.codecId;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
436
|
const returning: ColumnRef[] = this.returningColumns.map((col) => {
|
|
448
|
-
// TypeScript can't narrow ColumnBuilder properly
|
|
449
437
|
const c = col as unknown as { table: string; column: string };
|
|
450
|
-
return
|
|
438
|
+
return ColumnRef.of(c.table, c.column);
|
|
451
439
|
});
|
|
452
440
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
441
|
+
let ast = DeleteAst.from(TableSource.named(this.table.name)).withWhere(whereExpr);
|
|
442
|
+
if (returning.length > 0) {
|
|
443
|
+
ast = ast.withReturning(returning);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const { paramValues, paramDescriptors } = deriveParamsFromAst(ast);
|
|
458
447
|
|
|
459
448
|
const returningProjection: ProjectionState = {
|
|
460
449
|
aliases: this.returningColumns.map((col) => {
|
|
461
|
-
// TypeScript can't narrow ColumnBuilder properly
|
|
462
450
|
const c = col as unknown as { column: string };
|
|
463
451
|
return c.column;
|
|
464
452
|
}),
|
|
@@ -470,7 +458,6 @@ export class DeleteBuilderImpl<
|
|
|
470
458
|
table: this.table,
|
|
471
459
|
projection: returning.length > 0 ? returningProjection : { aliases: [], columns: [] },
|
|
472
460
|
paramDescriptors,
|
|
473
|
-
...(Object.keys(paramCodecs).length > 0 ? { paramCodecs } : {}),
|
|
474
461
|
where: this.wherePredicate,
|
|
475
462
|
});
|
|
476
463
|
|