@prisma-next/sql-lane 0.3.0-dev.4 → 0.3.0-dev.5

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 (55) hide show
  1. package/dist/exports/sql.d.ts +5 -5
  2. package/dist/exports/sql.d.ts.map +1 -0
  3. package/dist/index.d.ts +5 -116
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/raw.d.ts +11 -0
  6. package/dist/raw.d.ts.map +1 -0
  7. package/dist/sql/builder.d.ts +11 -0
  8. package/dist/sql/builder.d.ts.map +1 -0
  9. package/dist/sql/context.d.ts +5 -0
  10. package/dist/sql/context.d.ts.map +1 -0
  11. package/dist/sql/include-builder.d.ts +35 -0
  12. package/dist/sql/include-builder.d.ts.map +1 -0
  13. package/dist/sql/join-builder.d.ts +4 -0
  14. package/dist/sql/join-builder.d.ts.map +1 -0
  15. package/dist/sql/mutation-builder.d.ts +64 -0
  16. package/dist/sql/mutation-builder.d.ts.map +1 -0
  17. package/dist/sql/plan.d.ts +4 -0
  18. package/dist/sql/plan.d.ts.map +1 -0
  19. package/dist/sql/predicate-builder.d.ts +11 -0
  20. package/dist/sql/predicate-builder.d.ts.map +1 -0
  21. package/dist/sql/projection.d.ts +18 -0
  22. package/dist/sql/projection.d.ts.map +1 -0
  23. package/dist/sql/select-builder.d.ts +35 -0
  24. package/dist/sql/select-builder.d.ts.map +1 -0
  25. package/dist/types/internal.d.ts +35 -0
  26. package/dist/types/internal.d.ts.map +1 -0
  27. package/dist/types/public.d.ts +18 -0
  28. package/dist/types/public.d.ts.map +1 -0
  29. package/dist/utils/assertions.d.ts +28 -0
  30. package/dist/utils/assertions.d.ts.map +1 -0
  31. package/dist/utils/capabilities.d.ts +4 -0
  32. package/dist/utils/capabilities.d.ts.map +1 -0
  33. package/dist/utils/errors.d.ts +30 -0
  34. package/dist/utils/errors.d.ts.map +1 -0
  35. package/dist/utils/state.d.ts +30 -0
  36. package/dist/utils/state.d.ts.map +1 -0
  37. package/package.json +10 -9
  38. package/src/exports/sql.ts +12 -0
  39. package/src/index.ts +13 -0
  40. package/src/raw.ts +230 -0
  41. package/src/sql/builder.ts +66 -0
  42. package/src/sql/context.ts +10 -0
  43. package/src/sql/include-builder.ts +248 -0
  44. package/src/sql/join-builder.ts +18 -0
  45. package/src/sql/mutation-builder.ts +494 -0
  46. package/src/sql/plan.ts +289 -0
  47. package/src/sql/predicate-builder.ts +130 -0
  48. package/src/sql/projection.ts +112 -0
  49. package/src/sql/select-builder.ts +449 -0
  50. package/src/types/internal.ts +41 -0
  51. package/src/types/public.ts +36 -0
  52. package/src/utils/assertions.ts +34 -0
  53. package/src/utils/capabilities.ts +39 -0
  54. package/src/utils/errors.ts +168 -0
  55. package/src/utils/state.ts +40 -0
@@ -0,0 +1,494 @@
1
+ import type { ParamDescriptor } from '@prisma-next/contract/types';
2
+ import type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
3
+ import type { ColumnRef, ParamRef, TableRef } from '@prisma-next/sql-relational-core/ast';
4
+ import {
5
+ createColumnRef,
6
+ createDeleteAst,
7
+ createInsertAst,
8
+ createParamRef,
9
+ createTableRef,
10
+ createUpdateAst,
11
+ } from '@prisma-next/sql-relational-core/ast';
12
+ import type { SqlQueryPlan } from '@prisma-next/sql-relational-core/plan';
13
+ import type { QueryLaneContext } from '@prisma-next/sql-relational-core/query-lane-context';
14
+ import type {
15
+ AnyColumnBuilder,
16
+ BinaryBuilder,
17
+ BuildOptions,
18
+ InferReturningRow,
19
+ ParamPlaceholder,
20
+ SqlBuilderOptions,
21
+ } from '@prisma-next/sql-relational-core/types';
22
+ import { checkReturningCapability } from '../utils/capabilities';
23
+ import {
24
+ errorFailedToBuildWhereClause,
25
+ errorMissingParameter,
26
+ errorUnknownColumn,
27
+ errorUnknownTable,
28
+ errorWhereMustBeCalledForDelete,
29
+ errorWhereMustBeCalledForUpdate,
30
+ } from '../utils/errors';
31
+ import type { ProjectionState } from '../utils/state';
32
+ import { buildMeta } from './plan';
33
+ import { buildWhereExpr } from './predicate-builder';
34
+
35
+ export interface InsertBuilder<
36
+ TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
37
+ CodecTypes extends Record<string, { readonly output: unknown }> = Record<string, never>,
38
+ Row = unknown,
39
+ > {
40
+ returning<const Columns extends readonly AnyColumnBuilder[]>(
41
+ ...columns: Columns
42
+ ): InsertBuilder<TContract, CodecTypes, InferReturningRow<Columns>>;
43
+ build(options?: BuildOptions): SqlQueryPlan<Row>;
44
+ }
45
+
46
+ export interface UpdateBuilder<
47
+ TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
48
+ CodecTypes extends Record<string, { readonly output: unknown }> = Record<string, never>,
49
+ Row = unknown,
50
+ > {
51
+ where(predicate: BinaryBuilder): UpdateBuilder<TContract, CodecTypes, Row>;
52
+ returning<const Columns extends readonly AnyColumnBuilder[]>(
53
+ ...columns: Columns
54
+ ): UpdateBuilder<TContract, CodecTypes, InferReturningRow<Columns>>;
55
+ build(options?: BuildOptions): SqlQueryPlan<Row>;
56
+ }
57
+
58
+ export interface DeleteBuilder<
59
+ TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
60
+ CodecTypes extends Record<string, { readonly output: unknown }> = Record<string, never>,
61
+ Row = unknown,
62
+ > {
63
+ where(predicate: BinaryBuilder): DeleteBuilder<TContract, CodecTypes, Row>;
64
+ returning<const Columns extends readonly AnyColumnBuilder[]>(
65
+ ...columns: Columns
66
+ ): DeleteBuilder<TContract, CodecTypes, InferReturningRow<Columns>>;
67
+ build(options?: BuildOptions): SqlQueryPlan<Row>;
68
+ }
69
+
70
+ export class InsertBuilderImpl<
71
+ TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
72
+ CodecTypes extends Record<string, { readonly output: unknown }> = Record<string, never>,
73
+ Row = unknown,
74
+ > implements InsertBuilder<TContract, CodecTypes, Row>
75
+ {
76
+ private readonly contract: TContract;
77
+ private readonly context: QueryLaneContext<TContract>;
78
+ private readonly table: TableRef;
79
+ private readonly values: Record<string, ParamPlaceholder>;
80
+ private returningColumns: AnyColumnBuilder[] = [];
81
+
82
+ constructor(
83
+ options: SqlBuilderOptions<TContract>,
84
+ table: TableRef,
85
+ values: Record<string, ParamPlaceholder>,
86
+ ) {
87
+ this.context = options.context;
88
+ this.contract = options.context.contract;
89
+ this.table = table;
90
+ this.values = values;
91
+ }
92
+
93
+ returning<const Columns extends readonly AnyColumnBuilder[]>(
94
+ ...columns: Columns
95
+ ): InsertBuilder<TContract, CodecTypes, InferReturningRow<Columns>> {
96
+ checkReturningCapability(this.contract);
97
+
98
+ const builder = new InsertBuilderImpl<TContract, CodecTypes, InferReturningRow<Columns>>(
99
+ {
100
+ context: this.context,
101
+ },
102
+ this.table,
103
+ this.values,
104
+ );
105
+ builder.returningColumns = [...this.returningColumns, ...columns];
106
+ return builder;
107
+ }
108
+
109
+ build(options?: BuildOptions): SqlQueryPlan<Row> {
110
+ const paramsMap = (options?.params ?? {}) as Record<string, unknown>;
111
+ const paramDescriptors: ParamDescriptor[] = [];
112
+ const paramValues: unknown[] = [];
113
+ const paramCodecs: Record<string, string> = {};
114
+
115
+ const contractTable = this.contract.storage.tables[this.table.name];
116
+ if (!contractTable) {
117
+ errorUnknownTable(this.table.name);
118
+ }
119
+
120
+ const values: Record<string, ColumnRef | ParamRef> = {};
121
+ for (const [columnName, placeholder] of Object.entries(this.values)) {
122
+ if (!contractTable.columns[columnName]) {
123
+ errorUnknownColumn(columnName, this.table.name);
124
+ }
125
+
126
+ const paramName = placeholder.name;
127
+ if (!Object.hasOwn(paramsMap, paramName)) {
128
+ errorMissingParameter(paramName);
129
+ }
130
+
131
+ const value = paramsMap[paramName];
132
+ const index = paramValues.push(value);
133
+
134
+ const columnMeta = contractTable.columns[columnName];
135
+ const codecId = columnMeta?.codecId;
136
+ if (paramName && codecId) {
137
+ paramCodecs[paramName] = codecId;
138
+ }
139
+
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 } : {}),
147
+ });
148
+
149
+ values[columnName] = createParamRef(index, paramName);
150
+ }
151
+
152
+ const returning: ColumnRef[] = this.returningColumns.map((col) => {
153
+ // TypeScript can't narrow ColumnBuilder properly
154
+ const c = col as unknown as { table: string; column: string };
155
+ return createColumnRef(c.table, c.column);
156
+ });
157
+
158
+ const ast = createInsertAst({
159
+ table: createTableRef(this.table.name),
160
+ values,
161
+ returning,
162
+ });
163
+
164
+ const returningProjection: ProjectionState = {
165
+ aliases: this.returningColumns.map((col) => {
166
+ // TypeScript can't narrow ColumnBuilder properly
167
+ const c = col as unknown as { column: string };
168
+ return c.column;
169
+ }),
170
+ columns: this.returningColumns,
171
+ };
172
+
173
+ const planMeta = buildMeta({
174
+ contract: this.contract,
175
+ table: this.table,
176
+ projection: returning.length > 0 ? returningProjection : { aliases: [], columns: [] },
177
+ paramDescriptors,
178
+ ...(Object.keys(paramCodecs).length > 0 ? { paramCodecs } : {}),
179
+ });
180
+
181
+ const queryPlan: SqlQueryPlan<Row> = Object.freeze({
182
+ ast,
183
+ params: paramValues,
184
+ meta: {
185
+ ...planMeta,
186
+ lane: 'dsl',
187
+ annotations: {
188
+ ...planMeta.annotations,
189
+ intent: 'write',
190
+ isMutation: true,
191
+ },
192
+ },
193
+ });
194
+
195
+ return queryPlan;
196
+ }
197
+ }
198
+
199
+ export class UpdateBuilderImpl<
200
+ TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
201
+ CodecTypes extends Record<string, { readonly output: unknown }> = Record<string, never>,
202
+ Row = unknown,
203
+ > implements UpdateBuilder<TContract, CodecTypes, Row>
204
+ {
205
+ private readonly contract: TContract;
206
+ private readonly context: QueryLaneContext<TContract>;
207
+ private readonly table: TableRef;
208
+ private readonly set: Record<string, ParamPlaceholder>;
209
+ private wherePredicate?: BinaryBuilder;
210
+ private returningColumns: AnyColumnBuilder[] = [];
211
+
212
+ constructor(
213
+ options: SqlBuilderOptions<TContract>,
214
+ table: TableRef,
215
+ set: Record<string, ParamPlaceholder>,
216
+ ) {
217
+ this.context = options.context;
218
+ this.contract = options.context.contract;
219
+ this.table = table;
220
+ this.set = set;
221
+ }
222
+
223
+ where(predicate: BinaryBuilder): UpdateBuilder<TContract, CodecTypes, Row> {
224
+ const builder = new UpdateBuilderImpl<TContract, CodecTypes, Row>(
225
+ {
226
+ context: this.context,
227
+ },
228
+ this.table,
229
+ this.set,
230
+ );
231
+ builder.wherePredicate = predicate;
232
+ builder.returningColumns = [...this.returningColumns];
233
+ return builder;
234
+ }
235
+
236
+ returning<const Columns extends readonly AnyColumnBuilder[]>(
237
+ ...columns: Columns
238
+ ): UpdateBuilder<TContract, CodecTypes, InferReturningRow<Columns>> {
239
+ checkReturningCapability(this.contract);
240
+
241
+ const builder = new UpdateBuilderImpl<TContract, CodecTypes, InferReturningRow<Columns>>(
242
+ {
243
+ context: this.context,
244
+ },
245
+ this.table,
246
+ this.set,
247
+ );
248
+ if (this.wherePredicate) {
249
+ builder.wherePredicate = this.wherePredicate;
250
+ }
251
+ builder.returningColumns = [...this.returningColumns, ...columns];
252
+ return builder;
253
+ }
254
+
255
+ build(options?: BuildOptions): SqlQueryPlan<Row> {
256
+ if (!this.wherePredicate) {
257
+ errorWhereMustBeCalledForUpdate();
258
+ }
259
+
260
+ const paramsMap = (options?.params ?? {}) as Record<string, unknown>;
261
+ const paramDescriptors: ParamDescriptor[] = [];
262
+ const paramValues: unknown[] = [];
263
+ const paramCodecs: Record<string, string> = {};
264
+
265
+ const contractTable = this.contract.storage.tables[this.table.name];
266
+ if (!contractTable) {
267
+ errorUnknownTable(this.table.name);
268
+ }
269
+
270
+ const set: Record<string, ColumnRef | ParamRef> = {};
271
+ for (const [columnName, placeholder] of Object.entries(this.set)) {
272
+ if (!contractTable.columns[columnName]) {
273
+ errorUnknownColumn(columnName, this.table.name);
274
+ }
275
+
276
+ const paramName = placeholder.name;
277
+ if (!Object.hasOwn(paramsMap, paramName)) {
278
+ errorMissingParameter(paramName);
279
+ }
280
+
281
+ const value = paramsMap[paramName];
282
+ const index = paramValues.push(value);
283
+
284
+ const columnMeta = contractTable.columns[columnName];
285
+ const codecId = columnMeta?.codecId;
286
+ if (paramName && codecId) {
287
+ paramCodecs[paramName] = codecId;
288
+ }
289
+
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 } : {}),
297
+ });
298
+
299
+ set[columnName] = createParamRef(index, paramName);
300
+ }
301
+
302
+ const whereResult = buildWhereExpr(
303
+ this.contract,
304
+ this.wherePredicate,
305
+ paramsMap,
306
+ paramDescriptors,
307
+ paramValues,
308
+ );
309
+ const whereExpr = whereResult.expr;
310
+ if (!whereExpr) {
311
+ errorFailedToBuildWhereClause();
312
+ }
313
+
314
+ if (whereResult.codecId && whereResult.paramName) {
315
+ paramCodecs[whereResult.paramName] = whereResult.codecId;
316
+ }
317
+
318
+ const returning: ColumnRef[] = this.returningColumns.map((col) => {
319
+ // TypeScript can't narrow ColumnBuilder properly
320
+ const c = col as unknown as { table: string; column: string };
321
+ return createColumnRef(c.table, c.column);
322
+ });
323
+
324
+ const ast = createUpdateAst({
325
+ table: createTableRef(this.table.name),
326
+ set,
327
+ where: whereExpr,
328
+ returning,
329
+ });
330
+
331
+ const returningProjection: ProjectionState = {
332
+ aliases: this.returningColumns.map((col) => {
333
+ // TypeScript can't narrow ColumnBuilder properly
334
+ const c = col as unknown as { column: string };
335
+ return c.column;
336
+ }),
337
+ columns: this.returningColumns,
338
+ };
339
+
340
+ const planMeta = buildMeta({
341
+ contract: this.contract,
342
+ table: this.table,
343
+ projection: returning.length > 0 ? returningProjection : { aliases: [], columns: [] },
344
+ paramDescriptors,
345
+ ...(Object.keys(paramCodecs).length > 0 ? { paramCodecs } : {}),
346
+ where: this.wherePredicate,
347
+ });
348
+
349
+ const queryPlan: SqlQueryPlan<Row> = Object.freeze({
350
+ ast,
351
+ params: paramValues,
352
+ meta: {
353
+ ...planMeta,
354
+ lane: 'dsl',
355
+ annotations: {
356
+ ...planMeta.annotations,
357
+ intent: 'write',
358
+ isMutation: true,
359
+ hasWhere: true,
360
+ },
361
+ },
362
+ });
363
+
364
+ return queryPlan;
365
+ }
366
+ }
367
+
368
+ export class DeleteBuilderImpl<
369
+ TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
370
+ CodecTypes extends Record<string, { output: unknown }> = Record<string, never>,
371
+ Row = unknown,
372
+ > implements DeleteBuilder<TContract, CodecTypes, Row>
373
+ {
374
+ private readonly contract: TContract;
375
+ private readonly context: QueryLaneContext<TContract>;
376
+ private readonly table: TableRef;
377
+ private wherePredicate?: BinaryBuilder;
378
+ private returningColumns: AnyColumnBuilder[] = [];
379
+
380
+ constructor(options: SqlBuilderOptions<TContract>, table: TableRef) {
381
+ this.context = options.context;
382
+ this.contract = options.context.contract;
383
+ this.table = table;
384
+ }
385
+
386
+ where(predicate: BinaryBuilder): DeleteBuilder<TContract, CodecTypes, Row> {
387
+ const builder = new DeleteBuilderImpl<TContract, CodecTypes, Row>(
388
+ {
389
+ context: this.context,
390
+ },
391
+ this.table,
392
+ );
393
+ builder.wherePredicate = predicate;
394
+ builder.returningColumns = [...this.returningColumns];
395
+ return builder;
396
+ }
397
+
398
+ returning<const Columns extends readonly AnyColumnBuilder[]>(
399
+ ...columns: Columns
400
+ ): DeleteBuilder<TContract, CodecTypes, InferReturningRow<Columns>> {
401
+ checkReturningCapability(this.contract);
402
+
403
+ const builder = new DeleteBuilderImpl<TContract, CodecTypes, InferReturningRow<Columns>>(
404
+ {
405
+ context: this.context,
406
+ },
407
+ this.table,
408
+ );
409
+ if (this.wherePredicate) {
410
+ builder.wherePredicate = this.wherePredicate;
411
+ }
412
+ builder.returningColumns = [...this.returningColumns, ...columns];
413
+ return builder;
414
+ }
415
+
416
+ build(options?: BuildOptions): SqlQueryPlan<Row> {
417
+ if (!this.wherePredicate) {
418
+ errorWhereMustBeCalledForDelete();
419
+ }
420
+
421
+ const paramsMap = (options?.params ?? {}) as Record<string, unknown>;
422
+ const paramDescriptors: ParamDescriptor[] = [];
423
+ const paramValues: unknown[] = [];
424
+ const paramCodecs: Record<string, string> = {};
425
+
426
+ const contractTable = this.contract.storage.tables[this.table.name];
427
+ if (!contractTable) {
428
+ errorUnknownTable(this.table.name);
429
+ }
430
+
431
+ const whereResult = buildWhereExpr(
432
+ this.contract,
433
+ this.wherePredicate,
434
+ paramsMap,
435
+ paramDescriptors,
436
+ paramValues,
437
+ );
438
+ const whereExpr = whereResult.expr;
439
+ if (!whereExpr) {
440
+ errorFailedToBuildWhereClause();
441
+ }
442
+
443
+ if (whereResult.codecId && whereResult.paramName) {
444
+ paramCodecs[whereResult.paramName] = whereResult.codecId;
445
+ }
446
+
447
+ const returning: ColumnRef[] = this.returningColumns.map((col) => {
448
+ // TypeScript can't narrow ColumnBuilder properly
449
+ const c = col as unknown as { table: string; column: string };
450
+ return createColumnRef(c.table, c.column);
451
+ });
452
+
453
+ const ast = createDeleteAst({
454
+ table: createTableRef(this.table.name),
455
+ where: whereExpr,
456
+ returning,
457
+ });
458
+
459
+ const returningProjection: ProjectionState = {
460
+ aliases: this.returningColumns.map((col) => {
461
+ // TypeScript can't narrow ColumnBuilder properly
462
+ const c = col as unknown as { column: string };
463
+ return c.column;
464
+ }),
465
+ columns: this.returningColumns,
466
+ };
467
+
468
+ const planMeta = buildMeta({
469
+ contract: this.contract,
470
+ table: this.table,
471
+ projection: returning.length > 0 ? returningProjection : { aliases: [], columns: [] },
472
+ paramDescriptors,
473
+ ...(Object.keys(paramCodecs).length > 0 ? { paramCodecs } : {}),
474
+ where: this.wherePredicate,
475
+ });
476
+
477
+ const queryPlan: SqlQueryPlan<Row> = Object.freeze({
478
+ ast,
479
+ params: paramValues,
480
+ meta: {
481
+ ...planMeta,
482
+ lane: 'dsl',
483
+ annotations: {
484
+ ...planMeta.annotations,
485
+ intent: 'write',
486
+ isMutation: true,
487
+ hasWhere: true,
488
+ },
489
+ },
490
+ });
491
+
492
+ return queryPlan;
493
+ }
494
+ }