rado 0.2.23 → 0.2.24

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.
@@ -0,0 +1,2 @@
1
+ import { Query, QueryData } from './Query';
2
+ export declare function makeRecursiveUnion<T extends Query<any>>(initial: QueryData.Select, createUnion: (target: any) => T, operator: QueryData.UnionOperation): QueryData.Select;
@@ -0,0 +1,51 @@
1
+ // src/define/CTE.ts
2
+ import { Expr, ExprData, ExprType } from "./Expr.js";
3
+ import { Query, QueryData } from "./Query.js";
4
+ import { virtualTable } from "./Table.js";
5
+ import { Target, TargetType } from "./Target.js";
6
+ var { keys, create, fromEntries } = Object;
7
+ function columnsOf(expr) {
8
+ switch (expr.type) {
9
+ case ExprType.Record:
10
+ return keys(expr.fields);
11
+ case ExprType.Row:
12
+ switch (expr.target.type) {
13
+ case TargetType.Table:
14
+ return keys(expr.target.table.columns);
15
+ default:
16
+ throw new Error("Could not retrieve CTE columns");
17
+ }
18
+ default:
19
+ throw new Error("Could not retrieve CTE columns");
20
+ }
21
+ }
22
+ function makeRecursiveUnion(initial, createUnion, operator) {
23
+ let name;
24
+ const alias = new Proxy(create(null), {
25
+ get(_, key) {
26
+ name = key;
27
+ return virtualTable(name);
28
+ }
29
+ });
30
+ const right = createUnion(alias)[Query.Data];
31
+ if (!name)
32
+ throw new TypeError("No CTE name provided");
33
+ const cte = alias[name];
34
+ const cols = columnsOf(initial.selection);
35
+ const selection = new ExprData.Record(
36
+ fromEntries(cols.map((col) => [col, cte[col][Expr.Data]]))
37
+ );
38
+ const union = new QueryData.Union({
39
+ a: initial,
40
+ operator,
41
+ b: right
42
+ });
43
+ const from = new Target.CTE(name, union);
44
+ return new QueryData.Select({
45
+ selection,
46
+ from
47
+ });
48
+ }
49
+ export {
50
+ makeRecursiveUnion
51
+ };
@@ -1,7 +1,9 @@
1
1
  // src/define/Functions.ts
2
2
  import { Expr, ExprData } from "./Expr.js";
3
- function get(_, method) {
4
- return (...args) => {
3
+ function get(target, method) {
4
+ if (method in target)
5
+ return target[method];
6
+ return target[method] = (...args) => {
5
7
  return new Expr(new ExprData.Call(method, args.map(ExprData.create)));
6
8
  };
7
9
  }
@@ -11,6 +11,7 @@ declare const DATA: unique symbol;
11
11
  export declare enum QueryType {
12
12
  Insert = "QueryData.Insert",
13
13
  Select = "QueryData.Select",
14
+ Union = "QueryData.Union",
14
15
  Update = "QueryData.Update",
15
16
  Delete = "QueryData.Delete",
16
17
  CreateTable = "QueryData.CreateTable",
@@ -22,7 +23,7 @@ export declare enum QueryType {
22
23
  Transaction = "QueryData.Transaction",
23
24
  Raw = "QueryData.Raw"
24
25
  }
25
- export type QueryData = QueryData.Insert | QueryData.Select | QueryData.Update | QueryData.Delete | QueryData.CreateTable | QueryData.AlterTable | QueryData.DropTable | QueryData.CreateIndex | QueryData.DropIndex | QueryData.Batch | QueryData.Transaction | QueryData.Raw;
26
+ export type QueryData = QueryData.Insert | QueryData.Select | QueryData.Union | QueryData.Update | QueryData.Delete | QueryData.CreateTable | QueryData.AlterTable | QueryData.DropTable | QueryData.CreateIndex | QueryData.DropIndex | QueryData.Batch | QueryData.Transaction | QueryData.Raw;
26
27
  export declare namespace QueryData {
27
28
  abstract class Data<T> {
28
29
  abstract type: QueryType;
@@ -35,12 +36,29 @@ export declare namespace QueryData {
35
36
  selection?: ExprData;
36
37
  singleResult?: boolean;
37
38
  validate?: boolean;
38
- constructor(data: Omit<T, 'type'>);
39
+ constructor(data: Omit<T, 'type' | 'with'>);
40
+ with(data: Partial<T>): any;
41
+ }
42
+ export enum UnionOperation {
43
+ Union = "Union",
44
+ UnionAll = "UnionAll",
45
+ Intersect = "Intersect",
46
+ Except = "Except"
47
+ }
48
+ export class Union extends Data<Union> {
49
+ type: QueryType.Union;
50
+ a: Select | Union;
51
+ operator: UnionOperation;
52
+ b: Select | Union;
39
53
  }
40
54
  export class Select extends Data<Select> {
41
55
  type: QueryType.Select;
42
56
  selection: ExprData;
43
57
  from?: Target;
58
+ union?: Select;
59
+ unionAll?: Select;
60
+ intersect?: Select;
61
+ except?: Select;
44
62
  }
45
63
  export class Insert extends Data<Insert> {
46
64
  type: QueryType.Insert;
@@ -113,7 +131,7 @@ export declare namespace QueryData {
113
131
  expectedReturn?: 'row' | 'rows';
114
132
  strings: ReadonlyArray<string>;
115
133
  params: Array<any>;
116
- constructor(data: Omit<Raw, 'type'>);
134
+ constructor(data: Omit<Raw, 'type' | 'with'>);
117
135
  }
118
136
  export {};
119
137
  }
@@ -171,9 +189,17 @@ export declare namespace Query {
171
189
  constructor(queries: Array<QueryData>);
172
190
  next<T>(cursor: Query<T>): Query<T>;
173
191
  }
174
- class SelectMultiple<Row> extends Query<Array<Row>> {
192
+ class Union<Row> extends Query<Array<Row>> {
193
+ [DATA]: QueryData.Union | QueryData.Select;
194
+ union(query: SelectMultiple<Row> | Union<Row>): Union<Row>;
195
+ unionAll(query: SelectMultiple<Row> | Union<Row>): Union<Row>;
196
+ except(query: SelectMultiple<Row> | Union<Row>): Union<Row>;
197
+ intersect(query: SelectMultiple<Row> | Union<Row>): Union<Row>;
198
+ }
199
+ class SelectMultiple<Row> extends Union<Row> {
175
200
  [DATA]: QueryData.Select;
176
201
  constructor(query: QueryData.Select);
202
+ from(table: Table<any>): SelectMultiple<Row>;
177
203
  leftJoin<C>(that: Table<C> | TableSelect<C>, ...on: Array<EV<boolean>>): SelectMultiple<Row>;
178
204
  innerJoin<C>(that: Table<C> | TableSelect<C>, ...on: Array<EV<boolean>>): SelectMultiple<Row>;
179
205
  select<X extends Selection>(selection: X): SelectMultiple<Selection.Infer<X>>;
@@ -185,6 +211,8 @@ export declare namespace Query {
185
211
  where(...where: Array<EV<boolean>>): SelectMultiple<Row>;
186
212
  take(limit: number | undefined): SelectMultiple<Row>;
187
213
  skip(offset: number | undefined): SelectMultiple<Row>;
214
+ recursiveUnion<T extends {}>(this: SelectMultiple<T>, create: (fields: Record<string, Table.Of<T>>) => SelectMultiple<T> | Union<T>): SelectMultiple<T>;
215
+ recursiveUnionAll<T extends {}>(this: SelectMultiple<T>, create: (fields: Record<string, Table.Of<T>>) => SelectMultiple<T> | Union<T>): SelectMultiple<T>;
188
216
  [Expr.ToExpr](): Expr<Row>;
189
217
  }
190
218
  class TableSelect<Definition> extends SelectMultiple<Table.Select<Definition>> {
@@ -203,6 +231,7 @@ export declare namespace Query {
203
231
  class SelectSingle<Row> extends Query<Row> {
204
232
  [DATA]: QueryData.Select;
205
233
  constructor(query: QueryData.Select);
234
+ from(table: Table<any>): SelectMultiple<Row>;
206
235
  leftJoin<C>(that: Table<C> | TableSelect<C>, ...on: Array<EV<boolean>>): SelectSingle<Row>;
207
236
  innerJoin<C>(that: Table<C> | TableSelect<C>, ...on: Array<EV<boolean>>): SelectSingle<Row>;
208
237
  select<X extends Selection>(selection: X): SelectSingle<Selection.Infer<X>>;
@@ -1,14 +1,16 @@
1
1
  // src/define/Query.ts
2
+ import { makeRecursiveUnion } from "./CTE.js";
2
3
  import { Expr, ExprData } from "./Expr.js";
3
4
  import { Functions } from "./Functions.js";
4
5
  import { Schema } from "./Schema.js";
5
- import { Table, createTable } from "./Table.js";
6
+ import { createTable, Table } from "./Table.js";
6
7
  import { Target } from "./Target.js";
7
8
  var { assign } = Object;
8
9
  var DATA = Symbol("Query.Data");
9
10
  var QueryType = /* @__PURE__ */ ((QueryType2) => {
10
11
  QueryType2["Insert"] = "QueryData.Insert";
11
12
  QueryType2["Select"] = "QueryData.Select";
13
+ QueryType2["Union"] = "QueryData.Union";
12
14
  QueryType2["Update"] = "QueryData.Update";
13
15
  QueryType2["Delete"] = "QueryData.Delete";
14
16
  QueryType2["CreateTable"] = "QueryData.CreateTable";
@@ -27,7 +29,21 @@ var QueryData;
27
29
  constructor(data) {
28
30
  assign(this, data);
29
31
  }
32
+ with(data) {
33
+ return new this.constructor({ ...this, ...data });
34
+ }
35
+ }
36
+ let UnionOperation;
37
+ ((UnionOperation2) => {
38
+ UnionOperation2["Union"] = "Union";
39
+ UnionOperation2["UnionAll"] = "UnionAll";
40
+ UnionOperation2["Intersect"] = "Intersect";
41
+ UnionOperation2["Except"] = "Except";
42
+ })(UnionOperation = QueryData2.UnionOperation || (QueryData2.UnionOperation = {}));
43
+ class Union extends Data {
44
+ type = "QueryData.Union" /* Union */;
30
45
  }
46
+ QueryData2.Union = Union;
31
47
  class Select extends Data {
32
48
  type = "QueryData.Select" /* Select */;
33
49
  }
@@ -100,9 +116,11 @@ var Query = class {
100
116
  }
101
117
  next(cursor) {
102
118
  return new Query(
103
- new QueryData.Batch({
104
- queries: [this[DATA], cursor[DATA]]
105
- })
119
+ new QueryData.Batch(
120
+ this[DATA].with({
121
+ queries: [this[DATA], cursor[DATA]]
122
+ })
123
+ )
106
124
  );
107
125
  }
108
126
  on(driver) {
@@ -119,36 +137,33 @@ function addWhere(query, where) {
119
137
  const conditions = where.slice();
120
138
  if (query.where)
121
139
  conditions.push(new Expr(query.where));
122
- return {
123
- ...query,
124
- where: Expr.and(...conditions)[Expr.Data]
125
- };
140
+ return Expr.and(...conditions)[Expr.Data];
126
141
  }
127
142
  ((Query2) => {
128
143
  class Delete extends Query2 {
129
144
  where(...where) {
130
- return new Delete(addWhere(this[DATA], where));
145
+ return new Delete(this[DATA].with({ where: addWhere(this[DATA], where) }));
131
146
  }
132
147
  take(limit) {
133
- return new Delete({ ...this[DATA], limit });
148
+ return new Delete(this[DATA].with({ limit }));
134
149
  }
135
150
  skip(offset) {
136
- return new Delete({ ...this[DATA], offset });
151
+ return new Delete(this[DATA].with({ offset }));
137
152
  }
138
153
  }
139
154
  Query2.Delete = Delete;
140
155
  class Update extends Query2 {
141
156
  set(set) {
142
- return new Update({ ...this[DATA], set });
157
+ return new Update(this[DATA].with({ set }));
143
158
  }
144
159
  where(...where) {
145
- return new Update(addWhere(this[DATA], where));
160
+ return new Update(this[DATA].with({ where: addWhere(this[DATA], where) }));
146
161
  }
147
162
  take(limit) {
148
- return new Update({ ...this[DATA], limit });
163
+ return new Update(this[DATA].with({ limit }));
149
164
  }
150
165
  skip(offset) {
151
- return new Update({ ...this[DATA], offset });
166
+ return new Update(this[DATA].with({ offset }));
152
167
  }
153
168
  }
154
169
  Query2.Update = Update;
@@ -204,6 +219,45 @@ function addWhere(query, where) {
204
219
  }
205
220
  }
206
221
  Query2.Batch = Batch;
222
+ class Union extends Query2 {
223
+ union(query) {
224
+ return new Union(
225
+ new QueryData.Union({
226
+ a: this[DATA],
227
+ operator: "Union" /* Union */,
228
+ b: query[DATA]
229
+ })
230
+ );
231
+ }
232
+ unionAll(query) {
233
+ return new Union(
234
+ new QueryData.Union({
235
+ a: this[DATA],
236
+ operator: "UnionAll" /* UnionAll */,
237
+ b: query[DATA]
238
+ })
239
+ );
240
+ }
241
+ except(query) {
242
+ return new Union(
243
+ new QueryData.Union({
244
+ a: this[DATA],
245
+ operator: "Except" /* Except */,
246
+ b: query[DATA]
247
+ })
248
+ );
249
+ }
250
+ intersect(query) {
251
+ return new Union(
252
+ new QueryData.Union({
253
+ a: this[DATA],
254
+ operator: "Intersect" /* Intersect */,
255
+ b: query[DATA]
256
+ })
257
+ );
258
+ }
259
+ }
260
+ Query2.Union = Union;
207
261
  function joinTarget(joinType, query, to, on) {
208
262
  const toQuery = Query2.isQuery(to) ? to[DATA] : void 0;
209
263
  const target = toQuery ? toQuery.from : new Target.Table(to[Table.Data]);
@@ -222,69 +276,99 @@ function addWhere(query, where) {
222
276
  Expr.and(...conditions)[Expr.Data]
223
277
  );
224
278
  }
225
- class SelectMultiple extends Query2 {
279
+ class SelectMultiple extends Union {
226
280
  constructor(query) {
227
281
  super(query);
228
282
  }
283
+ from(table) {
284
+ return new SelectMultiple(
285
+ this[DATA].with({ from: new Target.Table(table) })
286
+ );
287
+ }
229
288
  leftJoin(that, ...on) {
230
289
  const query = this[DATA];
231
- return new SelectMultiple({
232
- ...query,
233
- from: joinTarget("left", query, that, on)
234
- });
290
+ return new SelectMultiple(
291
+ this[DATA].with({
292
+ from: joinTarget("left", query, that, on)
293
+ })
294
+ );
235
295
  }
236
296
  innerJoin(that, ...on) {
237
297
  const query = this[DATA];
238
- return new SelectMultiple({
239
- ...query,
240
- from: joinTarget("inner", query, that, on)
241
- });
298
+ return new SelectMultiple(
299
+ this[DATA].with({
300
+ from: joinTarget("inner", query, that, on)
301
+ })
302
+ );
242
303
  }
243
304
  select(selection) {
244
- return new SelectMultiple({
245
- ...this[DATA],
246
- selection: ExprData.create(selection)
247
- });
305
+ return new SelectMultiple(
306
+ this[DATA].with({
307
+ selection: ExprData.create(selection)
308
+ })
309
+ );
248
310
  }
249
311
  count() {
250
- return new SelectSingle({
251
- ...this[DATA],
252
- selection: Functions.count()[Expr.Data],
253
- singleResult: true
254
- });
312
+ return new SelectSingle(
313
+ this[DATA].with({
314
+ selection: Functions.count()[Expr.Data],
315
+ singleResult: true
316
+ })
317
+ );
255
318
  }
256
319
  orderBy(...orderBy) {
257
- return new SelectMultiple({
258
- ...this[DATA],
259
- orderBy: orderBy.map((e) => {
260
- return Expr.isExpr(e) ? e.asc() : e;
320
+ return new SelectMultiple(
321
+ this[DATA].with({
322
+ orderBy: orderBy.map((e) => {
323
+ return Expr.isExpr(e) ? e.asc() : e;
324
+ })
261
325
  })
262
- });
326
+ );
263
327
  }
264
328
  groupBy(...groupBy) {
265
- return new SelectMultiple({
266
- ...this[DATA],
267
- groupBy: groupBy.map(ExprData.create)
268
- });
329
+ return new SelectMultiple(
330
+ this[DATA].with({
331
+ groupBy: groupBy.map(ExprData.create)
332
+ })
333
+ );
269
334
  }
270
335
  maybeFirst() {
271
- return new SelectSingle({ ...this[DATA], singleResult: true });
336
+ return new SelectSingle(this[DATA].with({ singleResult: true }));
272
337
  }
273
338
  first() {
274
- return new SelectSingle({
275
- ...this[DATA],
276
- singleResult: true,
277
- validate: true
278
- });
339
+ return new SelectSingle(
340
+ this[DATA].with({
341
+ singleResult: true,
342
+ validate: true
343
+ })
344
+ );
279
345
  }
280
346
  where(...where) {
281
- return new SelectMultiple(addWhere(this[DATA], where));
347
+ return new SelectMultiple(
348
+ this[DATA].with({
349
+ where: addWhere(this[DATA], where)
350
+ })
351
+ );
282
352
  }
283
353
  take(limit) {
284
- return new SelectMultiple({ ...this[DATA], limit });
354
+ return new SelectMultiple(this[DATA].with({ limit }));
285
355
  }
286
356
  skip(offset) {
287
- return new SelectMultiple({ ...this[DATA], offset });
357
+ return new SelectMultiple(this[DATA].with({ offset }));
358
+ }
359
+ recursiveUnion(create) {
360
+ return new SelectMultiple(
361
+ makeRecursiveUnion(this[DATA], create, "Union" /* Union */)
362
+ );
363
+ }
364
+ recursiveUnionAll(create) {
365
+ return new SelectMultiple(
366
+ makeRecursiveUnion(
367
+ this[DATA],
368
+ create,
369
+ "UnionAll" /* UnionAll */
370
+ )
371
+ );
288
372
  }
289
373
  [Expr.ToExpr]() {
290
374
  return new Expr(new ExprData.Query(this[DATA]));
@@ -354,49 +438,63 @@ function addWhere(query, where) {
354
438
  constructor(query) {
355
439
  super(query);
356
440
  }
441
+ from(table) {
442
+ return new SelectMultiple(
443
+ this[DATA].with({ from: new Target.Table(table) })
444
+ );
445
+ }
357
446
  leftJoin(that, ...on) {
358
447
  const query = this[DATA];
359
- return new SelectSingle({
360
- ...query,
361
- from: joinTarget("left", query, that, on)
362
- });
448
+ return new SelectSingle(
449
+ this[DATA].with({
450
+ from: joinTarget("left", query, that, on)
451
+ })
452
+ );
363
453
  }
364
454
  innerJoin(that, ...on) {
365
455
  const query = this[DATA];
366
- return new SelectSingle({
367
- ...query,
368
- from: joinTarget("inner", query, that, on)
369
- });
456
+ return new SelectSingle(
457
+ this[DATA].with({
458
+ from: joinTarget("inner", query, that, on)
459
+ })
460
+ );
370
461
  }
371
462
  select(selection) {
372
- return new SelectSingle({
373
- ...this[DATA],
374
- selection: ExprData.create(selection)
375
- });
463
+ return new SelectSingle(
464
+ this[DATA].with({
465
+ selection: ExprData.create(selection)
466
+ })
467
+ );
376
468
  }
377
469
  orderBy(...orderBy) {
378
- return new SelectSingle({
379
- ...this[DATA],
380
- orderBy
381
- });
470
+ return new SelectSingle(
471
+ this[DATA].with({
472
+ orderBy
473
+ })
474
+ );
382
475
  }
383
476
  groupBy(...groupBy) {
384
- return new SelectSingle({
385
- ...this[DATA],
386
- groupBy: groupBy.map(ExprData.create)
387
- });
477
+ return new SelectSingle(
478
+ this[DATA].with({
479
+ groupBy: groupBy.map(ExprData.create)
480
+ })
481
+ );
388
482
  }
389
483
  where(...where) {
390
- return new SelectSingle(addWhere(this[DATA], where));
484
+ return new SelectSingle(
485
+ this[DATA].with({
486
+ where: addWhere(this[DATA], where)
487
+ })
488
+ );
391
489
  }
392
490
  take(limit) {
393
- return new SelectSingle({ ...this[DATA], limit });
491
+ return new SelectSingle(this[DATA].with({ limit }));
394
492
  }
395
493
  skip(offset) {
396
- return new SelectSingle({ ...this[DATA], offset });
494
+ return new SelectSingle(this[DATA].with({ offset }));
397
495
  }
398
496
  all() {
399
- return new SelectMultiple({ ...this[DATA], singleResult: false });
497
+ return new SelectMultiple(this[DATA].with({ singleResult: false }));
400
498
  }
401
499
  [Expr.ToExpr]() {
402
500
  return new Expr(new ExprData.Query(this[DATA]));
@@ -1,5 +1,6 @@
1
1
  import { Column, ColumnData, OptionalColumn, PrimaryColumn } from './Column';
2
2
  import { EV } from './Expr';
3
+ import { Fields } from './Fields';
3
4
  import { Index, IndexData } from './Index';
4
5
  import { Query } from './Query';
5
6
  import { Selection } from './Selection';
@@ -38,7 +39,7 @@ export declare namespace Table {
38
39
  export const Data: typeof DATA;
39
40
  export const Meta: typeof META;
40
41
  export type Of<Row> = Table<{
41
- [K in keyof Row as K extends string ? K : never]: Column<Row[K]>;
42
+ [K in keyof Row as K extends string ? K : never]: Fields<Row[K]>;
42
43
  }>;
43
44
  export type Select<Definition> = {
44
45
  [K in keyof Definition as Definition[K] extends Column<any> ? K : never]: Definition[K] extends Column<infer T> ? T : never;
@@ -61,6 +62,7 @@ interface Define<T> {
61
62
  new (): T;
62
63
  }
63
64
  export type table<T> = T extends Table<infer D> ? Table.Select<D> : never;
65
+ export declare function virtualTable<Definition>(name: string): Table<Definition>;
64
66
  export declare function createTable<Definition>(data: TableData): Table<Definition>;
65
67
  export declare function table<T extends {}>(define: Record<string, T | Define<T>>): Table<T>;
66
68
  export declare namespace table {
@@ -8,6 +8,7 @@ import { Query } from "./Query.js";
8
8
  import { Target } from "./Target.js";
9
9
  var {
10
10
  assign,
11
+ create,
11
12
  keys,
12
13
  entries,
13
14
  fromEntries,
@@ -28,6 +29,42 @@ var Table;
28
29
  Table2.Data = DATA;
29
30
  Table2.Meta = META;
30
31
  })(Table || (Table = {}));
32
+ function virtualTable(name) {
33
+ const data = new TableData({
34
+ name,
35
+ columns: {},
36
+ definition: create(null),
37
+ meta: () => ({ indexes: {} })
38
+ });
39
+ const target = new Target.Table(data);
40
+ const cache = create(null);
41
+ function call(...args) {
42
+ const isConditionalRecord = args.length === 1 && !Expr.isExpr(args[0]);
43
+ const conditions = isConditionalRecord ? entries(args[0]).map(([key, value]) => {
44
+ return new Expr(
45
+ new ExprData.BinOp(
46
+ BinOpType.Equals,
47
+ new ExprData.Field(new ExprData.Row(target), key),
48
+ ExprData.create(value)
49
+ )
50
+ );
51
+ }) : args;
52
+ return new Query.TableSelect(data, conditions);
53
+ }
54
+ return new Proxy(call, {
55
+ get(_, column) {
56
+ if (column === DATA)
57
+ return data;
58
+ if (column === Expr.ToExpr)
59
+ return new Expr(new ExprData.Row(target));
60
+ if (column in cache)
61
+ return cache[column];
62
+ return (cache[column] = new Expr(
63
+ new ExprData.Field(new ExprData.Row(target), column)
64
+ )).dynamic();
65
+ }
66
+ });
67
+ }
31
68
  function createTable(data) {
32
69
  const target = new Target.Table(data);
33
70
  const call = {
@@ -123,5 +160,6 @@ export {
123
160
  Table,
124
161
  TableData,
125
162
  createTable,
126
- table
163
+ table,
164
+ virtualTable
127
165
  };
@@ -3,12 +3,19 @@ import type { QueryData } from './Query';
3
3
  import type { TableData } from './Table';
4
4
  export declare enum TargetType {
5
5
  Expr = "Target.Expr",
6
+ CTE = "Target.CTE",
6
7
  Query = "Target.Query",
7
8
  Table = "Target.Table",
8
9
  Join = "Target.Join"
9
10
  }
10
- export type Target = Target.Expr | Target.Query | Target.Table | Target.Join;
11
+ export type Target = Target.Expr | Target.CTE | Target.Query | Target.Table | Target.Join;
11
12
  export declare namespace Target {
13
+ class CTE {
14
+ name: string;
15
+ union: QueryData.Union;
16
+ type: TargetType.CTE;
17
+ constructor(name: string, union: QueryData.Union);
18
+ }
12
19
  class Expr {
13
20
  expr: ExprData;
14
21
  alias?: string | undefined;
@@ -1,6 +1,7 @@
1
1
  // src/define/Target.ts
2
2
  var TargetType = /* @__PURE__ */ ((TargetType2) => {
3
3
  TargetType2["Expr"] = "Target.Expr";
4
+ TargetType2["CTE"] = "Target.CTE";
4
5
  TargetType2["Query"] = "Target.Query";
5
6
  TargetType2["Table"] = "Target.Table";
6
7
  TargetType2["Join"] = "Target.Join";
@@ -8,6 +9,14 @@ var TargetType = /* @__PURE__ */ ((TargetType2) => {
8
9
  })(TargetType || {});
9
10
  var Target;
10
11
  ((Target2) => {
12
+ class CTE {
13
+ constructor(name, union) {
14
+ this.name = name;
15
+ this.union = union;
16
+ }
17
+ type = "Target.CTE" /* CTE */;
18
+ }
19
+ Target2.CTE = CTE;
11
20
  class Expr {
12
21
  constructor(expr, alias) {
13
22
  this.expr = expr;
@@ -109,7 +109,7 @@ var SyncDriver = class extends DriverBase {
109
109
  const compiled = stmt ? void 0 : this.formatter.compile(query);
110
110
  stmt = stmt || this.prepareStatement(compiled, true);
111
111
  params = params || compiled.params();
112
- if ("selection" in query) {
112
+ if ("selection" in query || query.type === QueryType.Union) {
113
113
  const res = stmt.all(params).map((row) => JSON.parse(row.result).result);
114
114
  if (query.singleResult) {
115
115
  const row = res[0];
@@ -229,7 +229,7 @@ var AsyncDriver = class extends DriverBase {
229
229
  const compiled = stmt ? void 0 : this.formatter.compile(query);
230
230
  stmt = stmt || this.prepareStatement(compiled, true);
231
231
  params = params || compiled.params();
232
- if ("selection" in query) {
232
+ if ("selection" in query || query.type === QueryType.Union) {
233
233
  const res = (await stmt.all(params)).map(
234
234
  (item) => JSON.parse(item.result).result
235
235
  );
@@ -49,6 +49,7 @@ export declare abstract class Formatter implements Sanitizer {
49
49
  };
50
50
  format(ctx: FormatContext, query: QueryData): Statement;
51
51
  formatSelect({ topLevel, ...ctx }: FormatContext, query: QueryData.Select): Statement;
52
+ formatUnion(ctx: FormatContext, { a, operator, b }: QueryData.Union): Statement;
52
53
  formatInsert(ctx: FormatContext, query: QueryData.Insert): Statement;
53
54
  formatUpdate(ctx: FormatContext, query: QueryData.Update): Statement;
54
55
  formatDelete(ctx: FormatContext, query: QueryData.Delete): Statement;
@@ -31,6 +31,12 @@ var joins = {
31
31
  left: "LEFT",
32
32
  inner: "INNER"
33
33
  };
34
+ var unions = {
35
+ [QueryData.UnionOperation.Union]: "UNION",
36
+ [QueryData.UnionOperation.UnionAll]: "UNION ALL",
37
+ [QueryData.UnionOperation.Intersect]: "INTERSECT",
38
+ [QueryData.UnionOperation.Except]: "EXCEPT"
39
+ };
34
40
  function formatAsResultObject(stmt, mkSubject) {
35
41
  stmt.raw("json_object('result', ");
36
42
  mkSubject();
@@ -53,6 +59,8 @@ var Formatter = class {
53
59
  switch (query.type) {
54
60
  case QueryType.Select:
55
61
  return this.formatSelect(ctx, query);
62
+ case QueryType.Union:
63
+ return this.formatUnion(ctx, query);
56
64
  case QueryType.Insert:
57
65
  return this.formatInsert(ctx, query);
58
66
  case QueryType.Update:
@@ -79,21 +87,38 @@ var Formatter = class {
79
87
  }
80
88
  formatSelect({ topLevel, ...ctx }, query) {
81
89
  const { stmt } = ctx;
82
- stmt.raw("SELECT").space();
83
- this.formatSelection(
84
- ctx,
85
- query.selection,
86
- topLevel ? formatAsResultObject : void 0
87
- );
88
- if (query.from) {
89
- stmt.addLine("FROM").space();
90
- this.formatTarget(ctx, query.from);
90
+ switch (query.from?.type) {
91
+ case TargetType.CTE:
92
+ stmt.add("WITH RECURSIVE").addIdentifier(query.from.name).add("AS").space().openParenthesis();
93
+ this.formatUnion(
94
+ { ...ctx, topLevel: false, selectAsColumns: true },
95
+ query.from.union
96
+ );
97
+ stmt.closeParenthesis().space();
98
+ default:
99
+ stmt.raw("SELECT").space();
100
+ this.formatSelection(
101
+ ctx,
102
+ query.selection,
103
+ topLevel ? formatAsResultObject : void 0
104
+ );
105
+ if (query.from) {
106
+ stmt.addLine("FROM").space();
107
+ this.formatTarget(ctx, query.from);
108
+ }
109
+ this.formatWhere(ctx, query.where);
110
+ this.formatGroupBy(ctx, query.groupBy);
111
+ this.formatHaving(ctx, query.having);
112
+ this.formatOrderBy(ctx, query.orderBy);
113
+ this.formatLimit(ctx, query);
114
+ return stmt;
91
115
  }
92
- this.formatWhere(ctx, query.where);
93
- this.formatGroupBy(ctx, query.groupBy);
94
- this.formatHaving(ctx, query.having);
95
- this.formatOrderBy(ctx, query.orderBy);
96
- this.formatLimit(ctx, query);
116
+ }
117
+ formatUnion(ctx, { a, operator, b }) {
118
+ const { stmt } = ctx;
119
+ this.format(ctx, a);
120
+ stmt.add(unions[operator]).space();
121
+ this.format(ctx, b);
97
122
  return stmt;
98
123
  }
99
124
  formatInsert(ctx, query) {
@@ -377,6 +402,8 @@ var Formatter = class {
377
402
  if (target.alias)
378
403
  stmt.add("AS").addIdentifier(target.alias);
379
404
  return stmt;
405
+ case TargetType.CTE:
406
+ return stmt.addIdentifier(target.name);
380
407
  case TargetType.Expr:
381
408
  throw new Error("Cannot format expression as target");
382
409
  }
@@ -685,6 +712,7 @@ var Formatter = class {
685
712
  const inner = { ...ctx, selectAsColumns: false };
686
713
  for (const [key, value] of stmt.separate(Object.entries(expr.fields))) {
687
714
  this.formatExprJson(inner, value);
715
+ stmt.add("AS").addIdentifier(key);
688
716
  }
689
717
  return stmt;
690
718
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rado",
3
- "version": "0.2.23",
3
+ "version": "0.2.24",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",