@prisma-next/sql-lane 0.3.0-dev.10 → 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
@@ -0,0 +1,1153 @@
1
+ import { planInvalid } from "@prisma-next/plan";
2
+ import { AndExpr, BinaryExpr, ColumnRef, DeleteAst, DerivedTableSource, EqColJoinOn, InsertAst, JoinAst, JsonArrayAggExpr, JsonObjectExpr, NullCheckExpr, OrderByItem, ParamRef, ProjectionItem, SelectAst, TableSource, UpdateAst, compact, createJoinOnBuilder, createJoinOnBuilder as createJoinOnBuilder$1 } from "@prisma-next/sql-relational-core/ast";
3
+ import { ifDefined } from "@prisma-next/utils/defined";
4
+ import { isColumnBuilder, isExpressionBuilder, isExpressionSource, isParamPlaceholder } from "@prisma-next/sql-relational-core/utils/guards";
5
+
6
+ //#region src/raw.ts
7
+ const RAW_OPTIONS_SENTINEL = Symbol("rawOptions");
8
+ function ifDefined$1(key, value) {
9
+ return value !== void 0 ? { [key]: value } : {};
10
+ }
11
+ function createRawFactory(contract) {
12
+ const factory = ((first, ...rest) => {
13
+ if (isTemplateInvocation(first)) {
14
+ const { values, options: options$1 } = splitTemplateValues(rest);
15
+ const compiled = compileTemplateToPositional(first, values);
16
+ return buildRawPlan({
17
+ contract,
18
+ sql: compiled.sql,
19
+ params: compiled.params,
20
+ paramDescriptors: compiled.paramDescriptors,
21
+ ...options$1 ? { options: options$1 } : {}
22
+ });
23
+ }
24
+ const text = first;
25
+ const [options] = rest;
26
+ if (!options) throw planInvalid("Function form requires params option");
27
+ if (!Array.isArray(options.params)) throw planInvalid("Function form params must be an array");
28
+ const paramDescriptors = buildSequentialDescriptors(options.params.length);
29
+ return buildRawPlan({
30
+ contract,
31
+ sql: text,
32
+ params: options.params,
33
+ paramDescriptors,
34
+ options
35
+ });
36
+ });
37
+ factory.with = (options) => {
38
+ return ((strings, ...values) => {
39
+ const compiled = compileTemplateToPositional(strings, values);
40
+ return buildRawPlan({
41
+ contract,
42
+ sql: compiled.sql,
43
+ params: compiled.params,
44
+ paramDescriptors: compiled.paramDescriptors,
45
+ options
46
+ });
47
+ });
48
+ };
49
+ return factory;
50
+ }
51
+ function compileTemplateToPositional(strings, values) {
52
+ let sql$1 = "";
53
+ const params = [];
54
+ const paramDescriptors = [];
55
+ strings.forEach((part, index) => {
56
+ sql$1 += part;
57
+ if (index < values.length) {
58
+ const value = values[index];
59
+ const placeholderIndex = params.push(value);
60
+ sql$1 += `$${placeholderIndex}`;
61
+ paramDescriptors.push({
62
+ index: placeholderIndex,
63
+ name: `p${placeholderIndex}`,
64
+ source: "raw"
65
+ });
66
+ }
67
+ });
68
+ return {
69
+ sql: sql$1,
70
+ params,
71
+ paramDescriptors
72
+ };
73
+ }
74
+ function buildRawPlan(args) {
75
+ const params = Array.from(args.params);
76
+ const descriptors = args.paramDescriptors.map((descriptor) => Object.freeze({
77
+ ...descriptor,
78
+ source: "raw"
79
+ }));
80
+ const meta = buildRawMeta({
81
+ contract: args.contract,
82
+ paramDescriptors: descriptors,
83
+ ...args.options ? { options: args.options } : {}
84
+ });
85
+ return Object.freeze({
86
+ sql: args.sql,
87
+ params: Object.freeze(params),
88
+ meta
89
+ });
90
+ }
91
+ function buildRawMeta(args) {
92
+ const { contract, paramDescriptors, options } = args;
93
+ const meta = {
94
+ target: contract.target,
95
+ targetFamily: contract.targetFamily,
96
+ storageHash: contract.storageHash,
97
+ ...ifDefined$1("profileHash", contract.profileHash),
98
+ lane: "raw",
99
+ paramDescriptors: Object.freeze([...paramDescriptors]),
100
+ ...options?.annotations ? { annotations: Object.freeze({ ...options.annotations }) } : {},
101
+ ...options?.refs ? { refs: freezeRefs(options.refs) } : {},
102
+ ...options?.projection ? { projection: Object.freeze([...options.projection]) } : {}
103
+ };
104
+ return Object.freeze(meta);
105
+ }
106
+ function freezeRefs(refs) {
107
+ return Object.freeze({
108
+ ...refs.tables ? { tables: Object.freeze([...refs.tables]) } : {},
109
+ ...refs.columns ? { columns: Object.freeze(refs.columns.map((col) => Object.freeze({ ...col }))) } : {},
110
+ ...refs.indexes ? { indexes: Object.freeze(refs.indexes.map((index) => Object.freeze({
111
+ ...index,
112
+ columns: Object.freeze([...index.columns])
113
+ }))) } : {}
114
+ });
115
+ }
116
+ function buildSequentialDescriptors(count) {
117
+ return Array.from({ length: count }, (_, idx) => Object.freeze({
118
+ index: idx + 1,
119
+ name: `p${idx + 1}`,
120
+ source: "raw"
121
+ }));
122
+ }
123
+ function isTemplateInvocation(value) {
124
+ return Array.isArray(value) && Object.hasOwn(value, "raw");
125
+ }
126
+ function rawOptions(options) {
127
+ return Object.freeze({
128
+ [RAW_OPTIONS_SENTINEL]: true,
129
+ value: options
130
+ });
131
+ }
132
+ function splitTemplateValues(values) {
133
+ if (values.length === 0) return { values };
134
+ const last = values[values.length - 1];
135
+ if (!isOptionsSentinel(last)) return { values };
136
+ return {
137
+ values: values.slice(0, values.length - 1),
138
+ options: last.value
139
+ };
140
+ }
141
+ function isOptionsSentinel(value) {
142
+ return typeof value === "object" && value !== null && RAW_OPTIONS_SENTINEL in value;
143
+ }
144
+
145
+ //#endregion
146
+ //#region src/utils/errors.ts
147
+ function errorAliasPathEmpty() {
148
+ throw planInvalid("Alias path cannot be empty");
149
+ }
150
+ function errorAliasCollision(path, alias, existingPath) {
151
+ throw planInvalid(`Alias collision: path ${path.join(".")} would generate alias "${alias}" which conflicts with path ${existingPath?.join(".") ?? "unknown"}`);
152
+ }
153
+ function errorLimitMustBeNonNegativeInteger() {
154
+ throw planInvalid("Limit must be a non-negative integer");
155
+ }
156
+ function errorChildProjectionMustBeSpecified() {
157
+ throw planInvalid("Child projection must be specified");
158
+ }
159
+ function errorIncludeRequiresCapabilities(target) {
160
+ throw planInvalid("includeMany requires lateral and jsonAgg capabilities", target ? { target } : void 0, [
161
+ "Enable capabilities for your target in contract.capabilities[target]",
162
+ "For SQL includes, set both 'lateral' and 'jsonAgg' to true",
163
+ "If your database lacks lateral/json_agg, use explicit joins + group aggregates"
164
+ ], [
165
+ "docs/Architecture Overview.md",
166
+ "docs/reference/extensions-glossary.md",
167
+ "packages/3-targets/6-adapters/postgres/README.md"
168
+ ]);
169
+ }
170
+ function errorIncludeCapabilitiesNotTrue(target, values) {
171
+ throw planInvalid("includeMany requires lateral and jsonAgg capabilities to be true", target ? {
172
+ target,
173
+ values
174
+ } : void 0, ["Set contract.capabilities[target].lateral = true and .jsonAgg = true", "If the target does not support these, avoid includeMany and compose a two-step plan"], [
175
+ "docs/Architecture Overview.md",
176
+ "docs/reference/extensions-glossary.md",
177
+ "packages/3-targets/6-adapters/postgres/README.md"
178
+ ]);
179
+ }
180
+ function errorUnknownTable(tableName) {
181
+ throw planInvalid(`Unknown table ${tableName}`);
182
+ }
183
+ function errorSelfJoinNotSupported() {
184
+ throw planInvalid("Self-joins are not supported in MVP");
185
+ }
186
+ function errorChildProjectionEmpty() {
187
+ throw planInvalid("Child projection must not be empty");
188
+ }
189
+ function errorIncludeAliasCollision(alias, type) {
190
+ throw planInvalid(`Alias collision: include alias "${alias}" conflicts with existing ${type} alias`);
191
+ }
192
+ function errorMissingColumnForAlias(alias, index) {
193
+ throw planInvalid(`Missing column for alias ${alias} at index ${index}`);
194
+ }
195
+ function errorMissingAlias(index) {
196
+ throw planInvalid(`Missing alias at index ${index}`);
197
+ }
198
+ function errorFromMustBeCalled() {
199
+ throw planInvalid("from() must be called before building a query");
200
+ }
201
+ function errorSelectMustBeCalled() {
202
+ throw planInvalid("select() must be called before build()");
203
+ }
204
+ function errorMissingParameter(paramName) {
205
+ throw planInvalid(`Missing value for parameter ${paramName}`);
206
+ }
207
+ function errorInvalidProjectionValue(path) {
208
+ throw planInvalid(`Invalid projection value at path ${path.join(".")}: expected ExpressionSource (ColumnBuilder or ExpressionBuilder) or nested object`);
209
+ }
210
+ function errorIncludeAliasNotFound(alias) {
211
+ throw planInvalid(`Include alias "${alias}" not found. Did you call includeMany() with alias "${alias}"?`);
212
+ }
213
+ function errorInvalidProjectionKey(key) {
214
+ throw planInvalid(`Invalid projection value at key "${key}": expected ColumnBuilder, boolean true (for includes), or nested object`);
215
+ }
216
+ function errorProjectionEmpty() {
217
+ throw planInvalid("select() requires at least one column or include");
218
+ }
219
+ function errorReturningRequiresCapability(target) {
220
+ throw planInvalid("returning() requires returning capability", target ? { target } : void 0, [
221
+ "Enable 'returning' for your target in contract.capabilities[target]",
222
+ "PostgreSQL supports RETURNING; MySQL does not",
223
+ "If unsupported, remove returning() and fetch with a follow-up select()"
224
+ ], [
225
+ "docs/Architecture Overview.md",
226
+ "docs/reference/extensions-glossary.md",
227
+ "packages/3-targets/6-adapters/postgres/README.md"
228
+ ]);
229
+ }
230
+ function errorReturningCapabilityNotTrue(target, value) {
231
+ throw planInvalid("returning() requires returning capability to be true", target ? {
232
+ target,
233
+ value
234
+ } : void 0, ["Set contract.capabilities[target].returning = true", "If your database/adapter cannot support RETURNING, remove returning() and select after"], [
235
+ "docs/Architecture Overview.md",
236
+ "docs/reference/extensions-glossary.md",
237
+ "packages/3-targets/6-adapters/postgres/README.md"
238
+ ]);
239
+ }
240
+ function errorUnknownColumn(columnName, tableName) {
241
+ throw planInvalid(`Unknown column ${columnName} in table ${tableName}`);
242
+ }
243
+ function errorWhereMustBeCalledForUpdate() {
244
+ throw planInvalid("where() must be called before building an UPDATE query");
245
+ }
246
+ function errorFailedToBuildWhereClause() {
247
+ throw planInvalid("Failed to build WHERE clause");
248
+ }
249
+ function errorWhereMustBeCalledForDelete() {
250
+ throw planInvalid("where() must be called before building a DELETE query");
251
+ }
252
+
253
+ //#endregion
254
+ //#region src/utils/capabilities.ts
255
+ function checkIncludeCapabilities(contract) {
256
+ const target = contract.target;
257
+ const contractCapabilities = contract.capabilities;
258
+ const declaredTargetCapabilities = contractCapabilities?.[target];
259
+ if (!contractCapabilities || !declaredTargetCapabilities) errorIncludeRequiresCapabilities(target);
260
+ if (declaredTargetCapabilities["lateral"] !== true || declaredTargetCapabilities["jsonAgg"] !== true) errorIncludeCapabilitiesNotTrue(target, {
261
+ lateral: declaredTargetCapabilities["lateral"],
262
+ jsonAgg: declaredTargetCapabilities["jsonAgg"]
263
+ });
264
+ }
265
+ function checkReturningCapability(contract) {
266
+ const target = contract.target;
267
+ const capabilities = contract.capabilities;
268
+ if (!capabilities || !capabilities[target]) errorReturningRequiresCapability(target);
269
+ const targetCapabilities = capabilities[target];
270
+ if (targetCapabilities["returning"] !== true) errorReturningCapabilityNotTrue(target, targetCapabilities["returning"]);
271
+ }
272
+
273
+ //#endregion
274
+ //#region src/utils/assertions.ts
275
+ /**
276
+ * Asserts that a ColumnBuilder has table and column properties.
277
+ */
278
+ function assertColumnBuilder(col, context) {
279
+ if (typeof col === "object" && col !== null && "table" in col && "column" in col && typeof col.table === "string" && typeof col.column === "string") return col;
280
+ throw planInvalid(`ColumnBuilder missing table/column in ${context}`);
281
+ }
282
+
283
+ //#endregion
284
+ //#region src/sql/plan.ts
285
+ /**
286
+ * Extracts column references from an ExpressionSource (ColumnBuilder or ExpressionBuilder).
287
+ */
288
+ function collectRefsFromExpressionSource(source, refsColumns) {
289
+ if (isExpressionBuilder(source)) {
290
+ const allRefs = source.expr.collectColumnRefs();
291
+ for (const ref of allRefs) refsColumns.set(`${ref.table}.${ref.column}`, {
292
+ table: ref.table,
293
+ column: ref.column
294
+ });
295
+ } else if (isColumnBuilder(source)) {
296
+ const col = source;
297
+ refsColumns.set(`${col.table}.${col.column}`, {
298
+ table: col.table,
299
+ column: col.column
300
+ });
301
+ }
302
+ }
303
+ /**
304
+ * Extracts column references from an Expression (AST node).
305
+ */
306
+ function collectRefsFromExpression(expr, refsColumns) {
307
+ for (const ref of expr.collectColumnRefs()) refsColumns.set(`${ref.table}.${ref.column}`, {
308
+ table: ref.table,
309
+ column: ref.column
310
+ });
311
+ }
312
+ function buildMeta(args) {
313
+ const refsColumns = /* @__PURE__ */ new Map();
314
+ const refsTables = new Set([args.table.name]);
315
+ for (const column of args.projection.columns) collectRefsFromExpressionSource(column, refsColumns);
316
+ if (args.joins) for (const join of args.joins) {
317
+ refsTables.add(join.table.name);
318
+ const onLeft = assertColumnBuilder(join.on.left, "join ON left");
319
+ const onRight = assertColumnBuilder(join.on.right, "join ON right");
320
+ refsColumns.set(`${onLeft.table}.${onLeft.column}`, {
321
+ table: onLeft.table,
322
+ column: onLeft.column
323
+ });
324
+ refsColumns.set(`${onRight.table}.${onRight.column}`, {
325
+ table: onRight.table,
326
+ column: onRight.column
327
+ });
328
+ }
329
+ if (args.includes) for (const include of args.includes) {
330
+ refsTables.add(include.table.name);
331
+ const leftCol = assertColumnBuilder(include.on.left, "include ON left");
332
+ const rightCol = assertColumnBuilder(include.on.right, "include ON right");
333
+ refsColumns.set(`${leftCol.table}.${leftCol.column}`, {
334
+ table: leftCol.table,
335
+ column: leftCol.column
336
+ });
337
+ refsColumns.set(`${rightCol.table}.${rightCol.column}`, {
338
+ table: rightCol.table,
339
+ column: rightCol.column
340
+ });
341
+ for (const column of include.childProjection.columns) {
342
+ const col = assertColumnBuilder(column, "include child projection column");
343
+ refsColumns.set(`${col.table}.${col.column}`, {
344
+ table: col.table,
345
+ column: col.column
346
+ });
347
+ }
348
+ if (include.childWhere) if (include.childWhere.kind === "nullCheck") collectRefsFromExpression(include.childWhere.expr, refsColumns);
349
+ else {
350
+ collectRefsFromExpression(include.childWhere.left, refsColumns);
351
+ const childWhereRight = include.childWhere.right;
352
+ if (isColumnBuilder(childWhereRight) || isExpressionBuilder(childWhereRight)) collectRefsFromExpressionSource(childWhereRight, refsColumns);
353
+ }
354
+ if (include.childOrderBy) collectRefsFromExpression(include.childOrderBy.expr, refsColumns);
355
+ }
356
+ if (args.where) if (args.where.kind === "nullCheck") collectRefsFromExpression(args.where.expr, refsColumns);
357
+ else {
358
+ collectRefsFromExpression(args.where.left, refsColumns);
359
+ const whereRight = args.where.right;
360
+ if (isColumnBuilder(whereRight) || isExpressionBuilder(whereRight)) collectRefsFromExpressionSource(whereRight, refsColumns);
361
+ }
362
+ if (args.orderBy) collectRefsFromExpression(args.orderBy.expr, refsColumns);
363
+ const includeAliases = new Set(args.includes?.map((inc) => inc.alias) ?? []);
364
+ const projectionMap = Object.fromEntries(args.projection.aliases.map((alias, index) => {
365
+ if (includeAliases.has(alias)) return [alias, `include:${alias}`];
366
+ const column = args.projection.columns[index];
367
+ if (!column) errorMissingColumnForAlias(alias, index);
368
+ if (isExpressionBuilder(column)) return [alias, `operation:${column.expr.method}`];
369
+ const col = column;
370
+ if (!col.table || !col.column) return [alias, `include:${alias}`];
371
+ return [alias, `${col.table}.${col.column}`];
372
+ }));
373
+ const projectionTypes = {};
374
+ for (let i = 0; i < args.projection.aliases.length; i++) {
375
+ const alias = args.projection.aliases[i];
376
+ if (!alias || includeAliases.has(alias)) continue;
377
+ const column = args.projection.columns[i];
378
+ if (!column) continue;
379
+ if (isExpressionBuilder(column)) {
380
+ const operationExpr = column.expr;
381
+ if (operationExpr.returns.kind === "typeId") projectionTypes[alias] = operationExpr.returns.type;
382
+ else if (operationExpr.returns.kind === "builtin") projectionTypes[alias] = operationExpr.returns.type;
383
+ } else {
384
+ const codecId = column.columnMeta?.codecId;
385
+ if (codecId) projectionTypes[alias] = codecId;
386
+ }
387
+ }
388
+ const codecs = {};
389
+ for (let i = 0; i < args.projection.aliases.length; i++) {
390
+ const alias = args.projection.aliases[i];
391
+ if (!alias || includeAliases.has(alias)) continue;
392
+ const column = args.projection.columns[i];
393
+ if (!column) continue;
394
+ if (isExpressionBuilder(column)) {
395
+ const operationExpr = column.expr;
396
+ if (operationExpr.returns.kind === "typeId") codecs[alias] = operationExpr.returns.type;
397
+ } else {
398
+ const codecId = column.columnMeta?.codecId;
399
+ if (codecId) codecs[alias] = codecId;
400
+ }
401
+ }
402
+ return Object.freeze(compact({
403
+ target: args.contract.target,
404
+ targetFamily: args.contract.targetFamily,
405
+ storageHash: args.contract.storageHash,
406
+ lane: "dsl",
407
+ refs: {
408
+ tables: Array.from(refsTables),
409
+ columns: Array.from(refsColumns.values())
410
+ },
411
+ projection: projectionMap,
412
+ projectionTypes: Object.keys(projectionTypes).length > 0 ? projectionTypes : void 0,
413
+ annotations: Object.keys(codecs).length > 0 || args.limit !== void 0 ? Object.freeze(compact({
414
+ codecs: Object.keys(codecs).length > 0 ? Object.freeze(codecs) : void 0,
415
+ limit: args.limit
416
+ })) : void 0,
417
+ paramDescriptors: args.paramDescriptors,
418
+ profileHash: args.contract.profileHash
419
+ }));
420
+ }
421
+
422
+ //#endregion
423
+ //#region src/sql/predicate-builder.ts
424
+ function isNullCheckBuilder(builder) {
425
+ return builder.kind === "nullCheck";
426
+ }
427
+ function buildNullCheckExpr(contract, where) {
428
+ const expr = where.expr;
429
+ if (expr.kind === "column-ref") {
430
+ const { table, column } = expr;
431
+ const contractTable = contract.storage.tables[table];
432
+ if (!contractTable) errorUnknownTable(table);
433
+ if (!contractTable.columns[column]) errorUnknownColumn(column, table);
434
+ }
435
+ return where.isNull ? NullCheckExpr.isNull(expr) : NullCheckExpr.isNotNull(expr);
436
+ }
437
+ function buildWhereExpr(contract, where, paramsMap) {
438
+ if (isNullCheckBuilder(where)) return {
439
+ expr: buildNullCheckExpr(contract, where),
440
+ codecId: void 0,
441
+ paramName: ""
442
+ };
443
+ let leftExpr;
444
+ let codecId;
445
+ let rightExpr;
446
+ let paramName;
447
+ leftExpr = where.left;
448
+ if (leftExpr.kind === "column-ref") {
449
+ const { table, column } = leftExpr;
450
+ const contractTable = contract.storage.tables[table];
451
+ if (!contractTable) errorUnknownTable(table);
452
+ const columnMeta = contractTable.columns[column];
453
+ if (!columnMeta) errorUnknownColumn(column, table);
454
+ codecId = columnMeta.codecId;
455
+ } else if (leftExpr.kind === "operation") codecId = leftExpr.returns.kind === "typeId" ? leftExpr.returns.type : leftExpr.forTypeId;
456
+ if (isParamPlaceholder(where.right)) {
457
+ paramName = where.right.name;
458
+ if (!Object.hasOwn(paramsMap, paramName)) errorMissingParameter(paramName);
459
+ const value = paramsMap[paramName];
460
+ if (!codecId) throw planInvalid(`Cannot determine codecId for parameter '${paramName}'`);
461
+ rightExpr = ParamRef.of(value, {
462
+ name: paramName,
463
+ codecId
464
+ });
465
+ } else if (isColumnBuilder(where.right) || isExpressionBuilder(where.right)) {
466
+ rightExpr = where.right.toExpr();
467
+ if (rightExpr.kind === "column-ref") {
468
+ const { table, column } = rightExpr;
469
+ const contractTable = contract.storage.tables[table];
470
+ if (!contractTable) errorUnknownTable(table);
471
+ if (!contractTable.columns[column]) errorUnknownColumn(column, table);
472
+ }
473
+ paramName = "";
474
+ } else errorFailedToBuildWhereClause();
475
+ return {
476
+ expr: new BinaryExpr(where.op, leftExpr, rightExpr),
477
+ codecId,
478
+ paramName
479
+ };
480
+ }
481
+
482
+ //#endregion
483
+ //#region src/sql/mutation-builder.ts
484
+ function deriveParamsFromAst$1(ast) {
485
+ const collected = [...new Set(ast.collectParamRefs())];
486
+ return {
487
+ paramValues: collected.map((p) => p.value),
488
+ paramDescriptors: collected.map((p) => ({
489
+ ...ifDefined("name", p.name),
490
+ source: "dsl",
491
+ ...ifDefined("codecId", p.codecId)
492
+ }))
493
+ };
494
+ }
495
+ var InsertBuilderImpl = class InsertBuilderImpl {
496
+ contract;
497
+ context;
498
+ table;
499
+ values;
500
+ returningColumns = [];
501
+ constructor(options, table, values) {
502
+ this.context = options.context;
503
+ this.contract = options.context.contract;
504
+ this.table = table;
505
+ this.values = values;
506
+ }
507
+ returning(...columns) {
508
+ checkReturningCapability(this.contract);
509
+ const builder = new InsertBuilderImpl({ context: this.context }, this.table, this.values);
510
+ builder.returningColumns = [...this.returningColumns, ...columns];
511
+ return builder;
512
+ }
513
+ build(options) {
514
+ const paramsMap = options?.params ?? {};
515
+ const contractTable = this.contract.storage.tables[this.table.name];
516
+ if (!contractTable) errorUnknownTable(this.table.name);
517
+ const values = {};
518
+ for (const [columnName, placeholder] of Object.entries(this.values)) {
519
+ const columnMeta = contractTable.columns[columnName];
520
+ if (!columnMeta) errorUnknownColumn(columnName, this.table.name);
521
+ const paramName = placeholder.name;
522
+ if (!Object.hasOwn(paramsMap, paramName)) errorMissingParameter(paramName);
523
+ const value = paramsMap[paramName];
524
+ values[columnName] = ParamRef.of(value, {
525
+ name: paramName,
526
+ codecId: columnMeta.codecId
527
+ });
528
+ }
529
+ const appliedDefaults = this.context.applyMutationDefaults({
530
+ op: "create",
531
+ table: this.table.name,
532
+ values
533
+ });
534
+ for (const defaultValue of appliedDefaults) {
535
+ const columnMeta = contractTable.columns[defaultValue.column];
536
+ if (!columnMeta) errorUnknownColumn(defaultValue.column, this.table.name);
537
+ values[defaultValue.column] = ParamRef.of(defaultValue.value, {
538
+ name: defaultValue.column,
539
+ codecId: columnMeta.codecId
540
+ });
541
+ }
542
+ const returning = this.returningColumns.map((col) => {
543
+ const c = col;
544
+ return ColumnRef.of(c.table, c.column);
545
+ });
546
+ let ast = InsertAst.into(TableSource.named(this.table.name)).withValues(values);
547
+ if (returning.length > 0) ast = ast.withReturning(returning);
548
+ const { paramValues, paramDescriptors } = deriveParamsFromAst$1(ast);
549
+ const returningProjection = {
550
+ aliases: this.returningColumns.map((col) => {
551
+ return col.column;
552
+ }),
553
+ columns: this.returningColumns
554
+ };
555
+ const planMeta = buildMeta({
556
+ contract: this.contract,
557
+ table: this.table,
558
+ projection: returning.length > 0 ? returningProjection : {
559
+ aliases: [],
560
+ columns: []
561
+ },
562
+ paramDescriptors
563
+ });
564
+ return Object.freeze({
565
+ ast,
566
+ params: paramValues,
567
+ meta: {
568
+ ...planMeta,
569
+ lane: "dsl",
570
+ annotations: {
571
+ ...planMeta.annotations,
572
+ intent: "write",
573
+ isMutation: true
574
+ }
575
+ }
576
+ });
577
+ }
578
+ };
579
+ var UpdateBuilderImpl = class UpdateBuilderImpl {
580
+ contract;
581
+ context;
582
+ table;
583
+ set;
584
+ wherePredicate;
585
+ returningColumns = [];
586
+ constructor(options, table, set) {
587
+ this.context = options.context;
588
+ this.contract = options.context.contract;
589
+ this.table = table;
590
+ this.set = set;
591
+ }
592
+ where(predicate) {
593
+ const builder = new UpdateBuilderImpl({ context: this.context }, this.table, this.set);
594
+ builder.wherePredicate = predicate;
595
+ builder.returningColumns = [...this.returningColumns];
596
+ return builder;
597
+ }
598
+ returning(...columns) {
599
+ checkReturningCapability(this.contract);
600
+ const builder = new UpdateBuilderImpl({ context: this.context }, this.table, this.set);
601
+ if (this.wherePredicate) builder.wherePredicate = this.wherePredicate;
602
+ builder.returningColumns = [...this.returningColumns, ...columns];
603
+ return builder;
604
+ }
605
+ build(options) {
606
+ if (!this.wherePredicate) errorWhereMustBeCalledForUpdate();
607
+ const paramsMap = options?.params ?? {};
608
+ const contractTable = this.contract.storage.tables[this.table.name];
609
+ if (!contractTable) errorUnknownTable(this.table.name);
610
+ const set = {};
611
+ for (const [columnName, placeholder] of Object.entries(this.set)) {
612
+ const columnMeta = contractTable.columns[columnName];
613
+ if (!columnMeta) errorUnknownColumn(columnName, this.table.name);
614
+ const paramName = placeholder.name;
615
+ if (!Object.hasOwn(paramsMap, paramName)) errorMissingParameter(paramName);
616
+ const value = paramsMap[paramName];
617
+ set[columnName] = ParamRef.of(value, {
618
+ name: paramName,
619
+ codecId: columnMeta.codecId
620
+ });
621
+ }
622
+ const appliedDefaults = this.context.applyMutationDefaults({
623
+ op: "update",
624
+ table: this.table.name,
625
+ values: set
626
+ });
627
+ for (const defaultValue of appliedDefaults) {
628
+ const columnMeta = contractTable.columns[defaultValue.column];
629
+ if (!columnMeta) errorUnknownColumn(defaultValue.column, this.table.name);
630
+ set[defaultValue.column] = ParamRef.of(defaultValue.value, {
631
+ name: defaultValue.column,
632
+ codecId: columnMeta.codecId
633
+ });
634
+ }
635
+ const whereExpr = buildWhereExpr(this.contract, this.wherePredicate, paramsMap).expr;
636
+ if (!whereExpr) errorFailedToBuildWhereClause();
637
+ const returning = this.returningColumns.map((col) => {
638
+ const c = col;
639
+ return ColumnRef.of(c.table, c.column);
640
+ });
641
+ let ast = UpdateAst.table(TableSource.named(this.table.name)).withSet(set).withWhere(whereExpr);
642
+ if (returning.length > 0) ast = ast.withReturning(returning);
643
+ const { paramValues, paramDescriptors } = deriveParamsFromAst$1(ast);
644
+ const returningProjection = {
645
+ aliases: this.returningColumns.map((col) => {
646
+ return col.column;
647
+ }),
648
+ columns: this.returningColumns
649
+ };
650
+ const planMeta = buildMeta({
651
+ contract: this.contract,
652
+ table: this.table,
653
+ projection: returning.length > 0 ? returningProjection : {
654
+ aliases: [],
655
+ columns: []
656
+ },
657
+ paramDescriptors,
658
+ where: this.wherePredicate
659
+ });
660
+ return Object.freeze({
661
+ ast,
662
+ params: paramValues,
663
+ meta: {
664
+ ...planMeta,
665
+ lane: "dsl",
666
+ annotations: {
667
+ ...planMeta.annotations,
668
+ intent: "write",
669
+ isMutation: true,
670
+ hasWhere: true
671
+ }
672
+ }
673
+ });
674
+ }
675
+ };
676
+ var DeleteBuilderImpl = class DeleteBuilderImpl {
677
+ contract;
678
+ context;
679
+ table;
680
+ wherePredicate;
681
+ returningColumns = [];
682
+ constructor(options, table) {
683
+ this.context = options.context;
684
+ this.contract = options.context.contract;
685
+ this.table = table;
686
+ }
687
+ where(predicate) {
688
+ const builder = new DeleteBuilderImpl({ context: this.context }, this.table);
689
+ builder.wherePredicate = predicate;
690
+ builder.returningColumns = [...this.returningColumns];
691
+ return builder;
692
+ }
693
+ returning(...columns) {
694
+ checkReturningCapability(this.contract);
695
+ const builder = new DeleteBuilderImpl({ context: this.context }, this.table);
696
+ if (this.wherePredicate) builder.wherePredicate = this.wherePredicate;
697
+ builder.returningColumns = [...this.returningColumns, ...columns];
698
+ return builder;
699
+ }
700
+ build(options) {
701
+ if (!this.wherePredicate) errorWhereMustBeCalledForDelete();
702
+ const paramsMap = options?.params ?? {};
703
+ if (!this.contract.storage.tables[this.table.name]) errorUnknownTable(this.table.name);
704
+ const whereExpr = buildWhereExpr(this.contract, this.wherePredicate, paramsMap).expr;
705
+ if (!whereExpr) errorFailedToBuildWhereClause();
706
+ const returning = this.returningColumns.map((col) => {
707
+ const c = col;
708
+ return ColumnRef.of(c.table, c.column);
709
+ });
710
+ let ast = DeleteAst.from(TableSource.named(this.table.name)).withWhere(whereExpr);
711
+ if (returning.length > 0) ast = ast.withReturning(returning);
712
+ const { paramValues, paramDescriptors } = deriveParamsFromAst$1(ast);
713
+ const returningProjection = {
714
+ aliases: this.returningColumns.map((col) => {
715
+ return col.column;
716
+ }),
717
+ columns: this.returningColumns
718
+ };
719
+ const planMeta = buildMeta({
720
+ contract: this.contract,
721
+ table: this.table,
722
+ projection: returning.length > 0 ? returningProjection : {
723
+ aliases: [],
724
+ columns: []
725
+ },
726
+ paramDescriptors,
727
+ where: this.wherePredicate
728
+ });
729
+ return Object.freeze({
730
+ ast,
731
+ params: paramValues,
732
+ meta: {
733
+ ...planMeta,
734
+ lane: "dsl",
735
+ annotations: {
736
+ ...planMeta.annotations,
737
+ intent: "write",
738
+ isMutation: true,
739
+ hasWhere: true
740
+ }
741
+ }
742
+ });
743
+ }
744
+ };
745
+
746
+ //#endregion
747
+ //#region src/sql/projection.ts
748
+ function generateAlias(path) {
749
+ if (path.length === 0) errorAliasPathEmpty();
750
+ return path.join("_");
751
+ }
752
+ var AliasTracker = class {
753
+ aliases = /* @__PURE__ */ new Set();
754
+ aliasToPath = /* @__PURE__ */ new Map();
755
+ register(path) {
756
+ const alias = generateAlias(path);
757
+ if (this.aliases.has(alias)) errorAliasCollision(path, alias, this.aliasToPath.get(alias));
758
+ this.aliases.add(alias);
759
+ this.aliasToPath.set(alias, path);
760
+ return alias;
761
+ }
762
+ getPath(alias) {
763
+ return this.aliasToPath.get(alias);
764
+ }
765
+ has(alias) {
766
+ return this.aliases.has(alias);
767
+ }
768
+ };
769
+ function flattenProjection(projection, tracker, currentPath = []) {
770
+ const aliases = [];
771
+ const columns = [];
772
+ for (const [key, value] of Object.entries(projection)) {
773
+ const path = [...currentPath, key];
774
+ if (isExpressionSource(value)) {
775
+ const alias = tracker.register(path);
776
+ aliases.push(alias);
777
+ columns.push(value);
778
+ } else if (typeof value === "object" && value !== null) {
779
+ const nested = flattenProjection(value, tracker, path);
780
+ aliases.push(...nested.aliases);
781
+ columns.push(...nested.columns);
782
+ } else errorInvalidProjectionValue(path);
783
+ }
784
+ return {
785
+ aliases,
786
+ columns
787
+ };
788
+ }
789
+ function buildProjectionState(_table, projection, includes) {
790
+ const tracker = new AliasTracker();
791
+ const aliases = [];
792
+ const columns = [];
793
+ for (const [key, value] of Object.entries(projection)) if (value === true) {
794
+ const matchingInclude = includes?.find((inc) => inc.alias === key);
795
+ if (!matchingInclude) errorIncludeAliasNotFound(key);
796
+ aliases.push(key);
797
+ columns.push({
798
+ kind: "column",
799
+ table: matchingInclude.table.name,
800
+ column: "",
801
+ columnMeta: {
802
+ nativeType: "jsonb",
803
+ codecId: "core/json@1",
804
+ nullable: true
805
+ },
806
+ toExpr: () => ColumnRef.of(matchingInclude.table.name, "")
807
+ });
808
+ } else if (isExpressionSource(value)) {
809
+ const alias = tracker.register([key]);
810
+ aliases.push(alias);
811
+ columns.push(value);
812
+ } else if (typeof value === "object" && value !== null) {
813
+ const nested = flattenProjection(value, tracker, [key]);
814
+ aliases.push(...nested.aliases);
815
+ columns.push(...nested.columns);
816
+ } else errorInvalidProjectionKey(key);
817
+ if (aliases.length === 0) errorProjectionEmpty();
818
+ return {
819
+ aliases,
820
+ columns
821
+ };
822
+ }
823
+
824
+ //#endregion
825
+ //#region src/sql/include-builder.ts
826
+ var IncludeChildBuilderImpl = class IncludeChildBuilderImpl {
827
+ contract;
828
+ table;
829
+ childProjection;
830
+ childWhere;
831
+ childOrderBy;
832
+ childLimit;
833
+ constructor(contract, table) {
834
+ this.contract = contract;
835
+ this.table = table;
836
+ }
837
+ select(projection) {
838
+ const projectionState = buildProjectionState(this.table, projection);
839
+ const builder = new IncludeChildBuilderImpl(this.contract, this.table);
840
+ builder.childProjection = projectionState;
841
+ if (this.childWhere !== void 0) builder.childWhere = this.childWhere;
842
+ if (this.childOrderBy !== void 0) builder.childOrderBy = this.childOrderBy;
843
+ if (this.childLimit !== void 0) builder.childLimit = this.childLimit;
844
+ return builder;
845
+ }
846
+ where(expr) {
847
+ const builder = new IncludeChildBuilderImpl(this.contract, this.table);
848
+ if (this.childProjection !== void 0) builder.childProjection = this.childProjection;
849
+ builder.childWhere = expr;
850
+ if (this.childOrderBy !== void 0) builder.childOrderBy = this.childOrderBy;
851
+ if (this.childLimit !== void 0) builder.childLimit = this.childLimit;
852
+ return builder;
853
+ }
854
+ orderBy(order) {
855
+ const builder = new IncludeChildBuilderImpl(this.contract, this.table);
856
+ if (this.childProjection !== void 0) builder.childProjection = this.childProjection;
857
+ if (this.childWhere !== void 0) builder.childWhere = this.childWhere;
858
+ builder.childOrderBy = order;
859
+ if (this.childLimit !== void 0) builder.childLimit = this.childLimit;
860
+ return builder;
861
+ }
862
+ limit(count) {
863
+ if (!Number.isInteger(count) || count < 0) errorLimitMustBeNonNegativeInteger();
864
+ const builder = new IncludeChildBuilderImpl(this.contract, this.table);
865
+ if (this.childProjection !== void 0) builder.childProjection = this.childProjection;
866
+ if (this.childWhere !== void 0) builder.childWhere = this.childWhere;
867
+ if (this.childOrderBy !== void 0) builder.childOrderBy = this.childOrderBy;
868
+ builder.childLimit = count;
869
+ return builder;
870
+ }
871
+ getState() {
872
+ if (!this.childProjection) errorChildProjectionMustBeSpecified();
873
+ const state = { childProjection: this.childProjection };
874
+ if (this.childWhere !== void 0) state.childWhere = this.childWhere;
875
+ if (this.childOrderBy !== void 0) state.childOrderBy = this.childOrderBy;
876
+ if (this.childLimit !== void 0) state.childLimit = this.childLimit;
877
+ return state;
878
+ }
879
+ };
880
+ function buildIncludeOrderArtifacts(include, rowsAlias) {
881
+ const childOrderBy = include.childOrderBy ? (() => {
882
+ const orderBy = include.childOrderBy;
883
+ return [new OrderByItem(orderBy.expr, orderBy.dir)];
884
+ })() : void 0;
885
+ if (!childOrderBy || childOrderBy.length === 0) return {
886
+ childOrderBy: void 0,
887
+ hiddenOrderProjection: [],
888
+ aggregateOrderBy: void 0
889
+ };
890
+ const hiddenOrderProjection = childOrderBy.map((orderItem, index) => ProjectionItem.of(`${include.alias}__order_${index}`, orderItem.expr));
891
+ return {
892
+ childOrderBy,
893
+ hiddenOrderProjection,
894
+ aggregateOrderBy: hiddenOrderProjection.map((projection, index) => {
895
+ const orderItem = childOrderBy[index];
896
+ if (!orderItem) throw new Error(`Missing include order metadata at index ${index}`);
897
+ return new OrderByItem(ColumnRef.of(rowsAlias, projection.alias), orderItem.dir);
898
+ })
899
+ };
900
+ }
901
+ function buildChildProjectionItems(include) {
902
+ return include.childProjection.aliases.map((alias, idx) => {
903
+ const column = include.childProjection.columns[idx];
904
+ if (!column) errorMissingColumnForAlias(alias, idx);
905
+ return ProjectionItem.of(alias, column.toExpr());
906
+ });
907
+ }
908
+ function buildIncludeJoinArtifact(include, contract, paramsMap) {
909
+ let childWhere;
910
+ if (include.childWhere) childWhere = buildWhereExpr(contract, include.childWhere, paramsMap).expr;
911
+ const onLeft = include.on.left;
912
+ const onRight = include.on.right;
913
+ const onExpr = BinaryExpr.eq(ColumnRef.of(onLeft.table, onLeft.column), ColumnRef.of(onRight.table, onRight.column));
914
+ const rowsWhere = childWhere ? AndExpr.of([onExpr, childWhere]) : onExpr;
915
+ const childProjectItems = buildChildProjectionItems(include);
916
+ const rowsAlias = `${include.alias}__rows`;
917
+ const { childOrderBy, hiddenOrderProjection, aggregateOrderBy } = buildIncludeOrderArtifacts(include, rowsAlias);
918
+ let childRowsAst = SelectAst.from(TableSource.named(include.table.name, include.table.alias)).withProjection([...childProjectItems, ...hiddenOrderProjection]).withWhere(rowsWhere);
919
+ if (childOrderBy) childRowsAst = childRowsAst.withOrderBy(childOrderBy);
920
+ if (typeof include.childLimit === "number") childRowsAst = childRowsAst.withLimit(include.childLimit);
921
+ const aggregatedAlias = `${include.alias}_lateral`;
922
+ const jsonObjectExpr = JsonObjectExpr.fromEntries(childProjectItems.map((item) => JsonObjectExpr.entry(item.alias, ColumnRef.of(rowsAlias, item.alias))));
923
+ const jsonAggExpr = JsonArrayAggExpr.of(jsonObjectExpr, "emptyArray", aggregateOrderBy);
924
+ const aggregateSelect = SelectAst.from(DerivedTableSource.as(rowsAlias, childRowsAst)).withProjection([ProjectionItem.of(include.alias, jsonAggExpr)]);
925
+ return {
926
+ join: JoinAst.left(DerivedTableSource.as(aggregatedAlias, aggregateSelect), AndExpr.true(), true),
927
+ projection: ProjectionItem.of(include.alias, ColumnRef.of(aggregatedAlias, include.alias))
928
+ };
929
+ }
930
+
931
+ //#endregion
932
+ //#region src/sql/join-builder.ts
933
+ function buildJoinAst(join) {
934
+ const onLeft = join.on.left;
935
+ const onRight = join.on.right;
936
+ const onExpr = EqColJoinOn.of(ColumnRef.of(onLeft.table, onLeft.column), ColumnRef.of(onRight.table, onRight.column));
937
+ const tableSource = TableSource.named(join.table.name, join.table.alias);
938
+ switch (join.joinType) {
939
+ case "inner": return JoinAst.inner(tableSource, onExpr);
940
+ case "left": return JoinAst.left(tableSource, onExpr);
941
+ case "right": return JoinAst.right(tableSource, onExpr);
942
+ case "full": return JoinAst.full(tableSource, onExpr);
943
+ default: {
944
+ const exhaustiveCheck = join.joinType;
945
+ throw new Error(`Unsupported join type: ${String(exhaustiveCheck)}`);
946
+ }
947
+ }
948
+ }
949
+
950
+ //#endregion
951
+ //#region src/sql/select-builder.ts
952
+ function deriveParamsFromAst(ast) {
953
+ const collected = [...new Set(ast.collectParamRefs())];
954
+ return {
955
+ paramValues: collected.map((p) => p.value),
956
+ paramDescriptors: collected.map((p) => ({
957
+ ...ifDefined("name", p.name),
958
+ source: "dsl",
959
+ ...ifDefined("codecId", p.codecId)
960
+ }))
961
+ };
962
+ }
963
+ var SelectBuilderImpl = class SelectBuilderImpl {
964
+ contract;
965
+ context;
966
+ state = {};
967
+ constructor(options, state) {
968
+ this.context = options.context;
969
+ this.contract = options.context.contract;
970
+ if (state) this.state = state;
971
+ }
972
+ from(table) {
973
+ return new SelectBuilderImpl({ context: this.context }, {
974
+ ...this.state,
975
+ from: table
976
+ });
977
+ }
978
+ innerJoin(table, on) {
979
+ return this._addJoin("inner", table, on);
980
+ }
981
+ leftJoin(table, on) {
982
+ return this._addJoin("left", table, on);
983
+ }
984
+ rightJoin(table, on) {
985
+ return this._addJoin("right", table, on);
986
+ }
987
+ fullJoin(table, on) {
988
+ return this._addJoin("full", table, on);
989
+ }
990
+ includeMany(childTable, on, childBuilder, options) {
991
+ checkIncludeCapabilities(this.contract);
992
+ if (!this.contract.storage.tables[childTable.name]) errorUnknownTable(childTable.name);
993
+ const onPredicate = on(createJoinOnBuilder());
994
+ const onLeft = onPredicate.left;
995
+ const onRight = onPredicate.right;
996
+ if (onLeft.table === onRight.table) errorSelfJoinNotSupported();
997
+ const childState = childBuilder(new IncludeChildBuilderImpl(this.contract, childTable)).getState();
998
+ if (childState.childProjection.aliases.length === 0) errorChildProjectionEmpty();
999
+ const alias = options?.alias ?? childTable.name;
1000
+ if (this.state.projection) {
1001
+ if (this.state.projection.aliases.includes(alias)) errorIncludeAliasCollision(alias, "projection");
1002
+ }
1003
+ const existingIncludes = this.state.includes ?? [];
1004
+ if (existingIncludes.some((inc) => inc.alias === alias)) errorIncludeAliasCollision(alias, "include");
1005
+ const includeState = {
1006
+ alias,
1007
+ table: childTable,
1008
+ on: onPredicate,
1009
+ childProjection: childState.childProjection,
1010
+ ...childState.childWhere !== void 0 ? { childWhere: childState.childWhere } : {},
1011
+ ...childState.childOrderBy !== void 0 ? { childOrderBy: childState.childOrderBy } : {},
1012
+ ...childState.childLimit !== void 0 ? { childLimit: childState.childLimit } : {}
1013
+ };
1014
+ const newIncludes = [...existingIncludes, includeState];
1015
+ return new SelectBuilderImpl({ context: this.context }, {
1016
+ ...this.state,
1017
+ includes: newIncludes
1018
+ });
1019
+ }
1020
+ _addJoin(joinType, table, on) {
1021
+ const fromTable = this.ensureFrom();
1022
+ if (!this.contract.storage.tables[table.name]) errorUnknownTable(table.name);
1023
+ if (table.name === fromTable.name) errorSelfJoinNotSupported();
1024
+ const joinState = {
1025
+ joinType,
1026
+ table,
1027
+ on: on(createJoinOnBuilder())
1028
+ };
1029
+ const newJoins = [...this.state.joins ?? [], joinState];
1030
+ return new SelectBuilderImpl({ context: this.context }, {
1031
+ ...this.state,
1032
+ joins: newJoins
1033
+ });
1034
+ }
1035
+ where(expr) {
1036
+ return new SelectBuilderImpl({ context: this.context }, {
1037
+ ...this.state,
1038
+ where: expr
1039
+ });
1040
+ }
1041
+ select(projection) {
1042
+ const projectionState = buildProjectionState(this.ensureFrom(), projection, this.state.includes);
1043
+ return new SelectBuilderImpl({ context: this.context }, {
1044
+ ...this.state,
1045
+ projection: projectionState
1046
+ });
1047
+ }
1048
+ orderBy(order) {
1049
+ return new SelectBuilderImpl({ context: this.context }, {
1050
+ ...this.state,
1051
+ orderBy: order
1052
+ });
1053
+ }
1054
+ limit(count) {
1055
+ if (!Number.isInteger(count) || count < 0) errorLimitMustBeNonNegativeInteger();
1056
+ return new SelectBuilderImpl({ context: this.context }, {
1057
+ ...this.state,
1058
+ limit: count
1059
+ });
1060
+ }
1061
+ build(options) {
1062
+ const table = this.ensureFrom();
1063
+ const projection = this.ensureProjection();
1064
+ const paramsMap = options?.params ?? {};
1065
+ if (!this.contract.storage.tables[table.name]) errorUnknownTable(table.name);
1066
+ const whereExpr = (this.state.where ? buildWhereExpr(this.contract, this.state.where, paramsMap) : void 0)?.expr;
1067
+ const orderByClause = this.state.orderBy ? (() => {
1068
+ const orderBy = this.state.orderBy;
1069
+ return [new OrderByItem(orderBy.expr, orderBy.dir)];
1070
+ })() : void 0;
1071
+ const joins = this.state.joins?.map((join) => buildJoinAst(join)) ?? [];
1072
+ const includeArtifacts = this.state.includes?.map((include) => buildIncludeJoinArtifact(include, this.contract, paramsMap)) ?? [];
1073
+ const includeProjectionByAlias = new Map(includeArtifacts.map((artifact) => [artifact.projection.alias, artifact.projection]));
1074
+ const projectEntries = [];
1075
+ for (let i = 0; i < projection.aliases.length; i++) {
1076
+ const alias = projection.aliases[i];
1077
+ if (!alias) errorMissingAlias(i);
1078
+ const column = projection.columns[i];
1079
+ const includeProjection = includeProjectionByAlias.get(alias);
1080
+ if (includeProjection) projectEntries.push(includeProjection);
1081
+ else if (column && isExpressionBuilder(column)) projectEntries.push(ProjectionItem.of(alias, column.expr));
1082
+ else if (column) projectEntries.push(ProjectionItem.of(alias, column.toExpr()));
1083
+ }
1084
+ let ast = SelectAst.from(TableSource.named(table.name, table.alias)).withProjection(projectEntries).withWhere(whereExpr);
1085
+ const allJoins = [...joins, ...includeArtifacts.map((artifact) => artifact.join)];
1086
+ if (allJoins.length > 0) ast = ast.withJoins(allJoins);
1087
+ if (orderByClause) ast = ast.withOrderBy(orderByClause);
1088
+ if (this.state.limit !== void 0) ast = ast.withLimit(this.state.limit);
1089
+ const { paramValues, paramDescriptors } = deriveParamsFromAst(ast);
1090
+ const planMeta = buildMeta({
1091
+ contract: this.contract,
1092
+ table,
1093
+ projection,
1094
+ joins: this.state.joins,
1095
+ includes: this.state.includes,
1096
+ paramDescriptors,
1097
+ where: this.state.where,
1098
+ orderBy: this.state.orderBy,
1099
+ limit: this.state.limit
1100
+ });
1101
+ return Object.freeze({
1102
+ ast,
1103
+ params: paramValues,
1104
+ meta: planMeta
1105
+ });
1106
+ }
1107
+ ensureFrom() {
1108
+ if (!this.state.from) errorFromMustBeCalled();
1109
+ return this.state.from;
1110
+ }
1111
+ ensureProjection() {
1112
+ if (!this.state.projection) errorSelectMustBeCalled();
1113
+ return this.state.projection;
1114
+ }
1115
+ };
1116
+
1117
+ //#endregion
1118
+ //#region src/sql/builder.ts
1119
+ function sql(options) {
1120
+ const builder = new SelectBuilderImpl(options);
1121
+ const rawFactory = createRawFactory(options.context.contract);
1122
+ Object.defineProperty(builder, "raw", {
1123
+ value: rawFactory,
1124
+ enumerable: true,
1125
+ configurable: false
1126
+ });
1127
+ Object.defineProperty(builder, "insert", {
1128
+ value: (table, values) => {
1129
+ return new InsertBuilderImpl(options, table, values);
1130
+ },
1131
+ enumerable: true,
1132
+ configurable: false
1133
+ });
1134
+ Object.defineProperty(builder, "update", {
1135
+ value: (table, set) => {
1136
+ return new UpdateBuilderImpl(options, table, set);
1137
+ },
1138
+ enumerable: true,
1139
+ configurable: false
1140
+ });
1141
+ Object.defineProperty(builder, "delete", {
1142
+ value: (table) => {
1143
+ return new DeleteBuilderImpl(options, table);
1144
+ },
1145
+ enumerable: true,
1146
+ configurable: false
1147
+ });
1148
+ return builder;
1149
+ }
1150
+
1151
+ //#endregion
1152
+ export { sql as n, rawOptions as r, createJoinOnBuilder$1 as t };
1153
+ //# sourceMappingURL=builder-MYJh5-Gn.mjs.map