@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.
Files changed (66) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +18 -1
  3. package/dist/builder-DpxuiFO4.d.mts +118 -0
  4. package/dist/builder-DpxuiFO4.d.mts.map +1 -0
  5. package/dist/builder-MYJh5-Gn.mjs +1153 -0
  6. package/dist/builder-MYJh5-Gn.mjs.map +1 -0
  7. package/dist/exports/sql.d.mts +3 -0
  8. package/dist/exports/sql.mjs +3 -0
  9. package/dist/index.d.mts +3 -0
  10. package/dist/index.mjs +3 -0
  11. package/package.json +29 -24
  12. package/src/raw.ts +9 -2
  13. package/src/sql/builder.ts +12 -9
  14. package/src/sql/context.ts +3 -3
  15. package/src/sql/include-builder.ts +109 -70
  16. package/src/sql/join-builder.ts +21 -11
  17. package/src/sql/mutation-builder.ts +94 -107
  18. package/src/sql/plan.ts +88 -128
  19. package/src/sql/predicate-builder.ts +74 -65
  20. package/src/sql/projection.ts +17 -12
  21. package/src/sql/select-builder.ts +64 -102
  22. package/src/types/internal.ts +6 -5
  23. package/src/utils/errors.ts +2 -2
  24. package/src/utils/state.ts +5 -6
  25. package/dist/chunk-AWSKRSFP.js +0 -1569
  26. package/dist/chunk-AWSKRSFP.js.map +0 -1
  27. package/dist/exports/sql.d.ts +0 -5
  28. package/dist/exports/sql.d.ts.map +0 -1
  29. package/dist/exports/sql.js +0 -11
  30. package/dist/exports/sql.js.map +0 -1
  31. package/dist/index.d.ts +0 -5
  32. package/dist/index.d.ts.map +0 -1
  33. package/dist/index.js +0 -11
  34. package/dist/index.js.map +0 -1
  35. package/dist/raw.d.ts +0 -11
  36. package/dist/raw.d.ts.map +0 -1
  37. package/dist/sql/builder.d.ts +0 -11
  38. package/dist/sql/builder.d.ts.map +0 -1
  39. package/dist/sql/context.d.ts +0 -5
  40. package/dist/sql/context.d.ts.map +0 -1
  41. package/dist/sql/include-builder.d.ts +0 -35
  42. package/dist/sql/include-builder.d.ts.map +0 -1
  43. package/dist/sql/join-builder.d.ts +0 -4
  44. package/dist/sql/join-builder.d.ts.map +0 -1
  45. package/dist/sql/mutation-builder.d.ts +0 -64
  46. package/dist/sql/mutation-builder.d.ts.map +0 -1
  47. package/dist/sql/plan.d.ts +0 -4
  48. package/dist/sql/plan.d.ts.map +0 -1
  49. package/dist/sql/predicate-builder.d.ts +0 -11
  50. package/dist/sql/predicate-builder.d.ts.map +0 -1
  51. package/dist/sql/projection.d.ts +0 -18
  52. package/dist/sql/projection.d.ts.map +0 -1
  53. package/dist/sql/select-builder.d.ts +0 -35
  54. package/dist/sql/select-builder.d.ts.map +0 -1
  55. package/dist/types/internal.d.ts +0 -35
  56. package/dist/types/internal.d.ts.map +0 -1
  57. package/dist/types/public.d.ts +0 -18
  58. package/dist/types/public.d.ts.map +0 -1
  59. package/dist/utils/assertions.d.ts +0 -28
  60. package/dist/utils/assertions.d.ts.map +0 -1
  61. package/dist/utils/capabilities.d.ts +0 -4
  62. package/dist/utils/capabilities.d.ts.map +0 -1
  63. package/dist/utils/errors.d.ts +0 -30
  64. package/dist/utils/errors.d.ts.map +0 -1
  65. package/dist/utils/state.d.ts +0 -30
  66. 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 type {
2
+ import {
3
+ AndExpr,
4
+ type AnyExpression,
4
5
  BinaryExpr,
5
6
  ColumnRef,
6
- IncludeAst,
7
- OperationExpr,
8
- TableRef,
9
- } from '@prisma-next/sql-relational-core/ast';
10
- import {
11
- createColumnRef,
12
- createJoinOnExpr,
13
- createOrderByItem,
14
- createTableRef,
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, codecTypes: CodecTypes, table: TableRef) {
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.codecTypes, this.table);
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
- export function buildIncludeAst(
176
+ function buildIncludeOrderArtifacts(
185
177
  include: IncludeState,
186
- contract: SqlContract<SqlStorage>,
187
- paramsMap: Record<string, unknown>,
188
- paramDescriptors: ParamDescriptor[],
189
- paramValues: unknown[],
190
- ): IncludeAst {
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
- const orderExpr = orderBy.expr;
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
- let childWhere: BinaryExpr | undefined;
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 leftCol = createColumnRef(onLeft.table, onLeft.column);
223
- const rightCol = createColumnRef(onRight.table, onRight.column);
224
- const onExpr = createJoinOnExpr(leftCol, rightCol);
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
- kind: 'includeMany' as const,
228
- alias: include.alias,
229
- child: {
230
- table: createTableRef(include.table.name),
231
- on: onExpr,
232
- ...(childWhere ? { where: childWhere } : {}),
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
  }
@@ -1,18 +1,28 @@
1
- import type { JoinAst } from '@prisma-next/sql-relational-core/ast';
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 leftCol = createColumnRef(onLeft.table, onLeft.column);
15
- const rightCol = createColumnRef(onRight.table, onRight.column);
16
- const onExpr = createJoinOnExpr(leftCol, rightCol);
17
- return createJoin(join.joinType, createTableRef(join.table.name), onExpr);
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
- createColumnRef,
6
- createDeleteAst,
7
- createInsertAst,
8
- createParamRef,
9
- createTableRef,
10
- createUpdateAst,
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 { QueryLaneContext } from '@prisma-next/sql-relational-core/query-lane-context';
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: QueryLaneContext<TContract>;
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
- if (!contractTable.columns[columnName]) {
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
- const index = paramValues.push(value);
143
+ values[columnName] = ParamRef.of(value, {
144
+ name: paramName,
145
+ codecId: columnMeta.codecId,
146
+ });
147
+ }
133
148
 
134
- const columnMeta = contractTable.columns[columnName];
135
- const codecId = columnMeta?.codecId;
136
- if (paramName && codecId) {
137
- paramCodecs[paramName] = codecId;
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
- paramDescriptors.push({
141
- name: paramName,
142
- source: 'dsl',
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 createColumnRef(c.table, c.column);
169
+ return ColumnRef.of(c.table, c.column);
156
170
  });
157
171
 
158
- const ast = createInsertAst({
159
- table: createTableRef(this.table.name),
160
- values,
161
- returning,
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: QueryLaneContext<TContract>;
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
- if (!contractTable.columns[columnName]) {
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
- const index = paramValues.push(value);
293
+ set[columnName] = ParamRef.of(value, {
294
+ name: paramName,
295
+ codecId: columnMeta.codecId,
296
+ });
297
+ }
283
298
 
284
- const columnMeta = contractTable.columns[columnName];
285
- const codecId = columnMeta?.codecId;
286
- if (paramName && codecId) {
287
- paramCodecs[paramName] = codecId;
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
- paramDescriptors.push({
291
- name: paramName,
292
- source: 'dsl',
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 createColumnRef(c.table, c.column);
325
+ return ColumnRef.of(c.table, c.column);
322
326
  });
323
327
 
324
- const ast = createUpdateAst({
325
- table: createTableRef(this.table.name),
326
- set,
327
- where: whereExpr,
328
- returning,
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: QueryLaneContext<TContract>;
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 createColumnRef(c.table, c.column);
438
+ return ColumnRef.of(c.table, c.column);
451
439
  });
452
440
 
453
- const ast = createDeleteAst({
454
- table: createTableRef(this.table.name),
455
- where: whereExpr,
456
- returning,
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