@uwdata/mosaic-sql 0.18.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/ast/aggregate.d.ts +0 -4
- package/dist/src/ast/aggregate.d.ts.map +1 -1
- package/dist/src/ast/aggregate.js +0 -15
- package/dist/src/ast/aggregate.js.map +1 -1
- package/dist/src/ast/between-op.d.ts +0 -8
- package/dist/src/ast/between-op.d.ts.map +1 -1
- package/dist/src/ast/between-op.js +0 -12
- package/dist/src/ast/between-op.js.map +1 -1
- package/dist/src/ast/binary-op.d.ts +0 -4
- package/dist/src/ast/binary-op.d.ts.map +1 -1
- package/dist/src/ast/binary-op.js +0 -6
- package/dist/src/ast/binary-op.js.map +1 -1
- package/dist/src/ast/case.d.ts +0 -8
- package/dist/src/ast/case.d.ts.map +1 -1
- package/dist/src/ast/case.js +0 -16
- package/dist/src/ast/case.js.map +1 -1
- package/dist/src/ast/cast.d.ts +0 -4
- package/dist/src/ast/cast.d.ts.map +1 -1
- package/dist/src/ast/cast.js +0 -7
- package/dist/src/ast/cast.js.map +1 -1
- package/dist/src/ast/collate.d.ts +0 -4
- package/dist/src/ast/collate.d.ts.map +1 -1
- package/dist/src/ast/collate.js +0 -6
- package/dist/src/ast/collate.js.map +1 -1
- package/dist/src/ast/column-ref.d.ts +0 -4
- package/dist/src/ast/column-ref.d.ts.map +1 -1
- package/dist/src/ast/column-ref.js +0 -10
- package/dist/src/ast/column-ref.js.map +1 -1
- package/dist/src/ast/fragment.d.ts +0 -4
- package/dist/src/ast/fragment.d.ts.map +1 -1
- package/dist/src/ast/fragment.js +0 -6
- package/dist/src/ast/fragment.js.map +1 -1
- package/dist/src/ast/from.d.ts +10 -3
- package/dist/src/ast/from.d.ts.map +1 -1
- package/dist/src/ast/from.js +11 -12
- package/dist/src/ast/from.js.map +1 -1
- package/dist/src/ast/function.d.ts +0 -4
- package/dist/src/ast/function.d.ts.map +1 -1
- package/dist/src/ast/function.js +0 -7
- package/dist/src/ast/function.js.map +1 -1
- package/dist/src/ast/in-op.d.ts +0 -4
- package/dist/src/ast/in-op.d.ts.map +1 -1
- package/dist/src/ast/in-op.js +0 -6
- package/dist/src/ast/in-op.js.map +1 -1
- package/dist/src/ast/interval.d.ts +0 -4
- package/dist/src/ast/interval.d.ts.map +1 -1
- package/dist/src/ast/interval.js +0 -6
- package/dist/src/ast/interval.js.map +1 -1
- package/dist/src/ast/join.d.ts +45 -0
- package/dist/src/ast/join.d.ts.map +1 -0
- package/dist/src/ast/join.js +47 -0
- package/dist/src/ast/join.js.map +1 -0
- package/dist/src/ast/list.d.ts +11 -0
- package/dist/src/ast/list.d.ts.map +1 -0
- package/dist/src/ast/list.js +15 -0
- package/dist/src/ast/list.js.map +1 -0
- package/dist/src/ast/literal.d.ts +0 -4
- package/dist/src/ast/literal.d.ts.map +1 -1
- package/dist/src/ast/literal.js +0 -6
- package/dist/src/ast/literal.js.map +1 -1
- package/dist/src/ast/logical-op.d.ts +0 -4
- package/dist/src/ast/logical-op.d.ts.map +1 -1
- package/dist/src/ast/logical-op.js +0 -9
- package/dist/src/ast/logical-op.js.map +1 -1
- package/dist/src/ast/node.d.ts +13 -0
- package/dist/src/ast/node.d.ts.map +1 -1
- package/dist/src/ast/node.js +25 -3
- package/dist/src/ast/node.js.map +1 -1
- package/dist/src/ast/order-by.d.ts +0 -4
- package/dist/src/ast/order-by.d.ts.map +1 -1
- package/dist/src/ast/order-by.js +0 -13
- package/dist/src/ast/order-by.js.map +1 -1
- package/dist/src/ast/param.d.ts +0 -4
- package/dist/src/ast/param.d.ts.map +1 -1
- package/dist/src/ast/param.js +0 -7
- package/dist/src/ast/param.js.map +1 -1
- package/dist/src/ast/query.d.ts +43 -15
- package/dist/src/ast/query.d.ts.map +1 -1
- package/dist/src/ast/query.js +71 -92
- package/dist/src/ast/query.js.map +1 -1
- package/dist/src/ast/sample.d.ts +0 -4
- package/dist/src/ast/sample.d.ts.map +1 -1
- package/dist/src/ast/sample.js +0 -9
- package/dist/src/ast/sample.js.map +1 -1
- package/dist/src/ast/select.d.ts +0 -4
- package/dist/src/ast/select.d.ts.map +1 -1
- package/dist/src/ast/select.js +0 -16
- package/dist/src/ast/select.js.map +1 -1
- package/dist/src/ast/subquery.d.ts +0 -4
- package/dist/src/ast/subquery.d.ts.map +1 -1
- package/dist/src/ast/subquery.js +0 -6
- package/dist/src/ast/subquery.js.map +1 -1
- package/dist/src/ast/table-ref.d.ts +0 -4
- package/dist/src/ast/table-ref.d.ts.map +1 -1
- package/dist/src/ast/table-ref.js +0 -7
- package/dist/src/ast/table-ref.js.map +1 -1
- package/dist/src/ast/unary-op.d.ts +0 -8
- package/dist/src/ast/unary-op.d.ts.map +1 -1
- package/dist/src/ast/unary-op.js +0 -12
- package/dist/src/ast/unary-op.js.map +1 -1
- package/dist/src/ast/unnest.d.ts +15 -0
- package/dist/src/ast/unnest.d.ts.map +1 -0
- package/dist/src/ast/unnest.js +21 -0
- package/dist/src/ast/unnest.js.map +1 -0
- package/dist/src/ast/verbatim.d.ts +0 -4
- package/dist/src/ast/verbatim.d.ts.map +1 -1
- package/dist/src/ast/verbatim.js +0 -6
- package/dist/src/ast/verbatim.js.map +1 -1
- package/dist/src/ast/window-frame.d.ts +0 -8
- package/dist/src/ast/window-frame.d.ts.map +1 -1
- package/dist/src/ast/window-frame.js +1 -29
- package/dist/src/ast/window-frame.js.map +1 -1
- package/dist/src/ast/window.d.ts +0 -16
- package/dist/src/ast/window.d.ts.map +1 -1
- package/dist/src/ast/window.js +0 -39
- package/dist/src/ast/window.js.map +1 -1
- package/dist/src/ast/with.d.ts +0 -4
- package/dist/src/ast/with.d.ts.map +1 -1
- package/dist/src/ast/with.js +0 -10
- package/dist/src/ast/with.js.map +1 -1
- package/dist/src/constants.d.ts +4 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +4 -0
- package/dist/src/constants.js.map +1 -1
- package/dist/src/functions/from.d.ts +11 -0
- package/dist/src/functions/from.d.ts.map +1 -0
- package/dist/src/functions/from.js +12 -0
- package/dist/src/functions/from.js.map +1 -0
- package/dist/src/functions/join.d.ts +49 -0
- package/dist/src/functions/join.d.ts.map +1 -0
- package/dist/src/functions/join.js +50 -0
- package/dist/src/functions/join.js.map +1 -0
- package/dist/src/functions/list.d.ts +31 -0
- package/dist/src/functions/list.d.ts.map +1 -0
- package/dist/src/functions/list.js +49 -0
- package/dist/src/functions/list.js.map +1 -0
- package/dist/src/functions/unnest.d.ts +10 -0
- package/dist/src/functions/unnest.d.ts.map +1 -0
- package/dist/src/functions/unnest.js +12 -0
- package/dist/src/functions/unnest.js.map +1 -0
- package/dist/src/index.d.ts +11 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +12 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/init.d.ts +2 -0
- package/dist/src/init.d.ts.map +1 -0
- package/dist/src/init.js +5 -0
- package/dist/src/init.js.map +1 -0
- package/dist/src/transforms/filter-query.d.ts.map +1 -1
- package/dist/src/transforms/filter-query.js +2 -0
- package/dist/src/transforms/filter-query.js.map +1 -1
- package/dist/src/visit/codegen/duckdb.d.ts +49 -0
- package/dist/src/visit/codegen/duckdb.d.ts.map +1 -0
- package/dist/src/visit/codegen/duckdb.js +332 -0
- package/dist/src/visit/codegen/duckdb.js.map +1 -0
- package/dist/src/visit/codegen/sql.d.ts +60 -0
- package/dist/src/visit/codegen/sql.d.ts.map +1 -0
- package/dist/src/visit/codegen/sql.js +85 -0
- package/dist/src/visit/codegen/sql.js.map +1 -0
- package/dist/src/visit/duckdb-visitor.d.ts +50 -0
- package/dist/src/visit/duckdb-visitor.d.ts.map +1 -0
- package/dist/src/visit/duckdb-visitor.js +350 -0
- package/dist/src/visit/duckdb-visitor.js.map +1 -0
- package/dist/src/visit/recurse.d.ts.map +1 -1
- package/dist/src/visit/recurse.js +3 -1
- package/dist/src/visit/recurse.js.map +1 -1
- package/dist/src/visit/to-string-visitor.d.ts +60 -0
- package/dist/src/visit/to-string-visitor.d.ts.map +1 -0
- package/dist/src/visit/to-string-visitor.js +80 -0
- package/dist/src/visit/to-string-visitor.js.map +1 -0
- package/package.json +2 -2
- package/src/ast/aggregate.ts +0 -16
- package/src/ast/between-op.ts +0 -14
- package/src/ast/binary-op.ts +0 -7
- package/src/ast/case.ts +0 -18
- package/src/ast/cast.ts +0 -8
- package/src/ast/collate.ts +0 -7
- package/src/ast/column-ref.ts +0 -11
- package/src/ast/fragment.ts +0 -7
- package/src/ast/from.ts +12 -12
- package/src/ast/function.ts +0 -8
- package/src/ast/in-op.ts +0 -7
- package/src/ast/interval.ts +0 -7
- package/src/ast/join.ts +66 -0
- package/src/ast/list.ts +16 -0
- package/src/ast/literal.ts +0 -7
- package/src/ast/logical-op.ts +0 -10
- package/src/ast/node.ts +30 -3
- package/src/ast/order-by.ts +0 -14
- package/src/ast/param.ts +0 -8
- package/src/ast/query.ts +80 -104
- package/src/ast/sample.ts +0 -10
- package/src/ast/select.ts +0 -18
- package/src/ast/subquery.ts +0 -7
- package/src/ast/table-ref.ts +0 -8
- package/src/ast/unary-op.ts +0 -14
- package/src/ast/unnest.ts +22 -0
- package/src/ast/verbatim.ts +0 -7
- package/src/ast/window-frame.ts +1 -32
- package/src/ast/window.ts +0 -43
- package/src/ast/with.ts +0 -11
- package/src/constants.ts +4 -0
- package/src/functions/from.ts +18 -0
- package/src/functions/join.ts +101 -0
- package/src/functions/list.ts +63 -0
- package/src/functions/unnest.ts +13 -0
- package/src/index.ts +13 -1
- package/src/init.ts +5 -0
- package/src/transforms/filter-query.ts +2 -0
- package/src/visit/codegen/duckdb.ts +444 -0
- package/src/visit/codegen/sql.ts +213 -0
- package/src/visit/recurse.ts +4 -0
package/src/ast/query.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { exprList, nodeList } from '../util/function.js';
|
|
|
6
6
|
import { unquote } from '../util/string.js';
|
|
7
7
|
import { isArray, isString } from '../util/type-check.js';
|
|
8
8
|
import { isColumnRef } from './column-ref.js';
|
|
9
|
-
import { FromClauseNode } from './from.js';
|
|
9
|
+
import { FromClauseNode, FromNode } from './from.js';
|
|
10
10
|
import { ExprNode, SQLNode, isNode } from './node.js';
|
|
11
11
|
import { SampleClauseNode } from './sample.js';
|
|
12
12
|
import { SelectClauseNode } from './select.js';
|
|
@@ -71,6 +71,14 @@ export class Query extends ExprNode {
|
|
|
71
71
|
return new SetOperation('UNION', queries.flat());
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Create a new UNION BY NAME set operation over the given queries.
|
|
76
|
+
* @param queries The queries.
|
|
77
|
+
*/
|
|
78
|
+
static unionByName(...queries: MaybeArray<Query>[]) {
|
|
79
|
+
return new SetOperation('UNION BY NAME', queries.flat());
|
|
80
|
+
}
|
|
81
|
+
|
|
74
82
|
/**
|
|
75
83
|
* Create a new UNION ALL set operation over the given queries.
|
|
76
84
|
* @param queries The queries.
|
|
@@ -79,6 +87,14 @@ export class Query extends ExprNode {
|
|
|
79
87
|
return new SetOperation('UNION ALL', queries.flat());
|
|
80
88
|
}
|
|
81
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Create a new UNION ALL BY NAME set operation over the given queries.
|
|
92
|
+
* @param queries The queries.
|
|
93
|
+
*/
|
|
94
|
+
static unionAllByName(...queries: MaybeArray<Query>[]) {
|
|
95
|
+
return new SetOperation('UNION ALL BY NAME', queries.flat());
|
|
96
|
+
}
|
|
97
|
+
|
|
82
98
|
/**
|
|
83
99
|
* Create a new INTERSECT set operation over the given queries.
|
|
84
100
|
* @param queries The queries.
|
|
@@ -87,6 +103,14 @@ export class Query extends ExprNode {
|
|
|
87
103
|
return new SetOperation('INTERSECT', queries.flat());
|
|
88
104
|
}
|
|
89
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Create a new INTERSECT ALL set operation over the given queries.
|
|
108
|
+
* @param queries The queries.
|
|
109
|
+
*/
|
|
110
|
+
static intersectAll(...queries: MaybeArray<Query>[]) {
|
|
111
|
+
return new SetOperation('INTERSECT ALL', queries.flat());
|
|
112
|
+
}
|
|
113
|
+
|
|
90
114
|
/**
|
|
91
115
|
* Create a new EXCEPT set operation over the given queries.
|
|
92
116
|
* @param queries The queries.
|
|
@@ -95,6 +119,14 @@ export class Query extends ExprNode {
|
|
|
95
119
|
return new SetOperation('EXCEPT', queries.flat());
|
|
96
120
|
}
|
|
97
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Create a new EXCEPT ALL set operation over the given queries.
|
|
124
|
+
* @param queries The queries.
|
|
125
|
+
*/
|
|
126
|
+
static exceptAll(...queries: MaybeArray<Query>[]) {
|
|
127
|
+
return new SetOperation('EXCEPT ALL', queries.flat());
|
|
128
|
+
}
|
|
129
|
+
|
|
98
130
|
/**
|
|
99
131
|
* Create a new describe query for the given input query.
|
|
100
132
|
* @param query The query to describe.
|
|
@@ -199,7 +231,7 @@ export class Query extends ExprNode {
|
|
|
199
231
|
|
|
200
232
|
export class SelectQuery extends Query {
|
|
201
233
|
_select: SelectClauseNode[] = [];
|
|
202
|
-
_from:
|
|
234
|
+
_from: FromNode[] = [];
|
|
203
235
|
_where: ExprNode[] = [];
|
|
204
236
|
_sample?: SampleClauseNode;
|
|
205
237
|
_groupby: ExprNode[] = [];
|
|
@@ -229,13 +261,17 @@ export class SelectQuery extends Query {
|
|
|
229
261
|
|
|
230
262
|
// extract subqueries in FROM clause
|
|
231
263
|
// unused CTEs will be ignored
|
|
264
|
+
// WARNING: does not recurse into join inputs!
|
|
232
265
|
const queries: Query[] = [];
|
|
233
|
-
this._from.forEach(
|
|
234
|
-
if (
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if (
|
|
266
|
+
this._from.forEach(node => {
|
|
267
|
+
if (node instanceof FromClauseNode) {
|
|
268
|
+
const { expr } = node;
|
|
269
|
+
if (isQuery(expr)) {
|
|
270
|
+
queries.push(expr);
|
|
271
|
+
} else if (isTableRef(expr)) {
|
|
272
|
+
const subq = cte[expr.name];
|
|
273
|
+
if (subq) queries.push(subq);
|
|
274
|
+
}
|
|
239
275
|
}
|
|
240
276
|
});
|
|
241
277
|
return queries;
|
|
@@ -298,7 +334,7 @@ export class SelectQuery extends Query {
|
|
|
298
334
|
* @param expr Expressions to add.
|
|
299
335
|
*/
|
|
300
336
|
from(...expr: FromExpr[]): this {
|
|
301
|
-
const list:
|
|
337
|
+
const list: FromNode[] = [];
|
|
302
338
|
|
|
303
339
|
const add = (v: string | string[] | SQLNode, as?: string) => {
|
|
304
340
|
list.push(new FromClauseNode(maybeTableRef(v), unquote(as)));
|
|
@@ -306,7 +342,7 @@ export class SelectQuery extends Query {
|
|
|
306
342
|
|
|
307
343
|
expr.flat().forEach(e => {
|
|
308
344
|
if (e == null) return;
|
|
309
|
-
else if (e instanceof
|
|
345
|
+
else if (e instanceof FromNode) list.push(e);
|
|
310
346
|
else if (isString(e)) add(e, e);
|
|
311
347
|
else if (isTableRef(e)) add(e, e.name);
|
|
312
348
|
else if (isNode(e)) add(e);
|
|
@@ -334,7 +370,7 @@ export class SelectQuery extends Query {
|
|
|
334
370
|
* @param seed The random seed.
|
|
335
371
|
*/
|
|
336
372
|
sample(
|
|
337
|
-
value
|
|
373
|
+
value?: number | SampleClauseNode | null,
|
|
338
374
|
method?: SampleMethod,
|
|
339
375
|
seed?: number
|
|
340
376
|
): this {
|
|
@@ -346,7 +382,7 @@ export class SelectQuery extends Query {
|
|
|
346
382
|
} else {
|
|
347
383
|
clause = value;
|
|
348
384
|
}
|
|
349
|
-
this._sample = clause;
|
|
385
|
+
this._sample = clause ?? undefined;
|
|
350
386
|
return this;
|
|
351
387
|
}
|
|
352
388
|
|
|
@@ -418,66 +454,6 @@ export class SelectQuery extends Query {
|
|
|
418
454
|
this._qualify = this._qualify.concat(exprList(expr, asVerbatim));
|
|
419
455
|
return this;
|
|
420
456
|
}
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* Generate a SQL query string.
|
|
424
|
-
*/
|
|
425
|
-
toString() {
|
|
426
|
-
const {
|
|
427
|
-
_with, _select, _distinct, _from, _sample, _where, _groupby,
|
|
428
|
-
_having, _window, _qualify, _orderby, _limitPerc, _limit, _offset
|
|
429
|
-
} = this;
|
|
430
|
-
const sql = [];
|
|
431
|
-
|
|
432
|
-
// WITH
|
|
433
|
-
if (_with.length) sql.push(`WITH ${_with.join(', ')}`);
|
|
434
|
-
|
|
435
|
-
// SELECT
|
|
436
|
-
sql.push(`SELECT${_distinct ? ' DISTINCT' : ''} ${_select.join(', ')}`);
|
|
437
|
-
|
|
438
|
-
// FROM
|
|
439
|
-
if (_from.length) sql.push(`FROM ${_from.join(', ')}`);
|
|
440
|
-
|
|
441
|
-
// WHERE
|
|
442
|
-
if (_where.length) {
|
|
443
|
-
const clauses = _where.map(String).filter(x => x).join(' AND ');
|
|
444
|
-
if (clauses) sql.push(`WHERE ${clauses}`);
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// SAMPLE
|
|
448
|
-
if (_sample) sql.push(`USING SAMPLE ${_sample}`);
|
|
449
|
-
|
|
450
|
-
// GROUP BY
|
|
451
|
-
if (_groupby.length) {
|
|
452
|
-
sql.push(`GROUP BY ${_groupby.join(', ')}`);
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
// HAVING
|
|
456
|
-
if (_having.length) {
|
|
457
|
-
const clauses = _having.map(String).filter(x => x).join(' AND ');
|
|
458
|
-
if (clauses) sql.push(`HAVING ${clauses}`);
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
// WINDOW
|
|
462
|
-
if (_window.length) sql.push(`WINDOW ${_window.join(', ')}`);
|
|
463
|
-
|
|
464
|
-
// QUALIFY
|
|
465
|
-
if (_qualify.length) {
|
|
466
|
-
const clauses = _qualify.map(String).filter(x => x).join(' AND ');
|
|
467
|
-
if (clauses) sql.push(`QUALIFY ${clauses}`);
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
// ORDER BY
|
|
471
|
-
if (_orderby.length) sql.push(`ORDER BY ${_orderby.join(', ')}`);
|
|
472
|
-
|
|
473
|
-
// LIMIT
|
|
474
|
-
if (_limit) sql.push(`LIMIT ${_limit}${_limitPerc ? '%' : ''}`);
|
|
475
|
-
|
|
476
|
-
// OFFSET
|
|
477
|
-
if (_offset) sql.push(`OFFSET ${_offset}`);
|
|
478
|
-
|
|
479
|
-
return sql.join(' ');
|
|
480
|
-
}
|
|
481
457
|
}
|
|
482
458
|
|
|
483
459
|
export class DescribeQuery extends SQLNode {
|
|
@@ -499,13 +475,6 @@ export class DescribeQuery extends SQLNode {
|
|
|
499
475
|
// @ts-expect-error creates describe query
|
|
500
476
|
return new DescribeQuery(this.query.clone());
|
|
501
477
|
}
|
|
502
|
-
|
|
503
|
-
/**
|
|
504
|
-
* Generate a SQL query string.
|
|
505
|
-
*/
|
|
506
|
-
toString() {
|
|
507
|
-
return `DESCRIBE ${this.query}`;
|
|
508
|
-
}
|
|
509
478
|
}
|
|
510
479
|
|
|
511
480
|
export class SetOperation extends Query {
|
|
@@ -550,31 +519,6 @@ export class SetOperation extends Query {
|
|
|
550
519
|
// @ts-expect-error creates set operation
|
|
551
520
|
return Object.assign(new SetOperation(op, queries), rest);
|
|
552
521
|
}
|
|
553
|
-
|
|
554
|
-
/**
|
|
555
|
-
* Generate a SQL query string.
|
|
556
|
-
*/
|
|
557
|
-
toString() {
|
|
558
|
-
const { op, queries, _with, _orderby, _limitPerc, _limit, _offset } = this;
|
|
559
|
-
const sql = [];
|
|
560
|
-
|
|
561
|
-
// WITH
|
|
562
|
-
if (_with.length) sql.push(`WITH ${_with.join(', ')}`);
|
|
563
|
-
|
|
564
|
-
// SUBQUERIES
|
|
565
|
-
sql.push(queries.join(` ${op} `));
|
|
566
|
-
|
|
567
|
-
// ORDER BY
|
|
568
|
-
if (_orderby.length) sql.push(`ORDER BY ${_orderby.join(', ')}`);
|
|
569
|
-
|
|
570
|
-
// LIMIT
|
|
571
|
-
if (_limit) sql.push(`LIMIT ${_limit}${_limitPerc ? '%' : ''}`);
|
|
572
|
-
|
|
573
|
-
// OFFSET
|
|
574
|
-
if (_offset) sql.push(`OFFSET ${_offset}`);
|
|
575
|
-
|
|
576
|
-
return sql.join(' ');
|
|
577
|
-
}
|
|
578
522
|
}
|
|
579
523
|
|
|
580
524
|
class WithClause {
|
|
@@ -613,6 +557,14 @@ class WithClause {
|
|
|
613
557
|
return Query.union(...queries).with(...this._with);
|
|
614
558
|
}
|
|
615
559
|
|
|
560
|
+
/**
|
|
561
|
+
* Create a new UNION BY NAME set operation over the given queries.
|
|
562
|
+
* @param queries The queries.
|
|
563
|
+
*/
|
|
564
|
+
unionByName(...queries: Query[]) {
|
|
565
|
+
return Query.unionByName(...queries).with(...this._with);
|
|
566
|
+
}
|
|
567
|
+
|
|
616
568
|
/**
|
|
617
569
|
* Create a new UNION ALL set operation over the given queries.
|
|
618
570
|
* @param queries The queries.
|
|
@@ -621,6 +573,14 @@ class WithClause {
|
|
|
621
573
|
return Query.unionAll(...queries).with(...this._with);
|
|
622
574
|
}
|
|
623
575
|
|
|
576
|
+
/**
|
|
577
|
+
* Create a new UNION ALL BY NAME set operation over the given queries.
|
|
578
|
+
* @param queries The queries.
|
|
579
|
+
*/
|
|
580
|
+
unionAllByName(...queries: Query[]) {
|
|
581
|
+
return Query.unionAllByName(...queries).with(...this._with);
|
|
582
|
+
}
|
|
583
|
+
|
|
624
584
|
/**
|
|
625
585
|
* Create a new INTERSECT set operation over the given queries.
|
|
626
586
|
* @param queries The queries.
|
|
@@ -629,6 +589,14 @@ class WithClause {
|
|
|
629
589
|
return Query.intersect(...queries).with(...this._with);
|
|
630
590
|
}
|
|
631
591
|
|
|
592
|
+
/**
|
|
593
|
+
* Create a new INTERSECT ALL set operation over the given queries.
|
|
594
|
+
* @param queries The queries.
|
|
595
|
+
*/
|
|
596
|
+
intersectAll(...queries: Query[]) {
|
|
597
|
+
return Query.intersectAll(...queries).with(...this._with);
|
|
598
|
+
}
|
|
599
|
+
|
|
632
600
|
/**
|
|
633
601
|
* Create a new EXCEPT set operation over the given queries.
|
|
634
602
|
* @param queries The queries.
|
|
@@ -636,4 +604,12 @@ class WithClause {
|
|
|
636
604
|
except(...queries: Query[]) {
|
|
637
605
|
return Query.except(...queries).with(...this._with);
|
|
638
606
|
}
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Create a new EXCEPT ALL set operation over the given queries.
|
|
610
|
+
* @param queries The queries.
|
|
611
|
+
*/
|
|
612
|
+
exceptAll(...queries: Query[]) {
|
|
613
|
+
return Query.exceptAll(...queries).with(...this._with);
|
|
614
|
+
}
|
|
639
615
|
}
|
package/src/ast/sample.ts
CHANGED
|
@@ -34,14 +34,4 @@ export class SampleClauseNode extends SQLNode {
|
|
|
34
34
|
this.method = method;
|
|
35
35
|
this.seed = seed;
|
|
36
36
|
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Generate a SQL query string for this node.
|
|
40
|
-
*/
|
|
41
|
-
toString() {
|
|
42
|
-
const { size, perc, method, seed } = this;
|
|
43
|
-
const m = method ? `${method} ` : '';
|
|
44
|
-
const s = seed != null ? ` REPEATABLE (${seed})` : '';
|
|
45
|
-
return `${m}(${size}${perc ? '%' : ' ROWS'})${s}`;
|
|
46
|
-
}
|
|
47
37
|
}
|
package/src/ast/select.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { ExprNode } from './node.js';
|
|
2
2
|
import { SELECT_CLAUSE } from '../constants.js';
|
|
3
|
-
import { quoteIdentifier } from '../util/string.js';
|
|
4
|
-
import { ColumnRefNode } from './column-ref.js';
|
|
5
3
|
import { SQLNode } from './node.js';
|
|
6
4
|
|
|
7
5
|
export class SelectClauseNode extends SQLNode {
|
|
@@ -20,20 +18,4 @@ export class SelectClauseNode extends SQLNode {
|
|
|
20
18
|
this.expr = expr;
|
|
21
19
|
this.alias = alias;
|
|
22
20
|
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Generate a SQL query string for this node.
|
|
26
|
-
*/
|
|
27
|
-
toString() {
|
|
28
|
-
const { expr, alias } = this;
|
|
29
|
-
return !alias || isColumnRefFor(expr, alias)
|
|
30
|
-
? `${expr}`
|
|
31
|
-
: `${expr} AS ${quoteIdentifier(alias)}`;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function isColumnRefFor(expr: unknown, name: string): expr is ColumnRefNode {
|
|
36
|
-
return expr instanceof ColumnRefNode
|
|
37
|
-
&& expr.table == null
|
|
38
|
-
&& expr.column === name;
|
|
39
21
|
}
|
package/src/ast/subquery.ts
CHANGED
package/src/ast/table-ref.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { TABLE_REF } from '../constants.js';
|
|
2
|
-
import { quoteIdentifier } from '../util/string.js';
|
|
3
2
|
import { ExprNode } from './node.js';
|
|
4
3
|
|
|
5
4
|
/**
|
|
@@ -29,11 +28,4 @@ export class TableRefNode extends ExprNode {
|
|
|
29
28
|
get name() {
|
|
30
29
|
return this.table[this.table.length - 1];
|
|
31
30
|
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Generate a SQL query string for this node.
|
|
35
|
-
*/
|
|
36
|
-
toString() {
|
|
37
|
-
return this.table.map(t => quoteIdentifier(t)).join('.');
|
|
38
|
-
}
|
|
39
31
|
}
|
package/src/ast/unary-op.ts
CHANGED
|
@@ -29,13 +29,6 @@ export class UnaryOpNode extends AbstractUnaryOpNode {
|
|
|
29
29
|
constructor(op: string, expr: ExprNode) {
|
|
30
30
|
super(UNARY_OPERATOR, op, expr);
|
|
31
31
|
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Generate a SQL query string for this node.
|
|
35
|
-
*/
|
|
36
|
-
toString() {
|
|
37
|
-
return `(${this.op} ${this.expr})`;
|
|
38
|
-
}
|
|
39
32
|
}
|
|
40
33
|
|
|
41
34
|
export class UnaryPostfixOpNode extends AbstractUnaryOpNode {
|
|
@@ -47,11 +40,4 @@ export class UnaryPostfixOpNode extends AbstractUnaryOpNode {
|
|
|
47
40
|
constructor(op: string, expr: ExprNode) {
|
|
48
41
|
super(UNARY_POSTFIX_OPERATOR, op, expr);
|
|
49
42
|
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Generate a SQL query string for this node.
|
|
53
|
-
*/
|
|
54
|
-
toString() {
|
|
55
|
-
return `(${this.expr} ${this.op})`;
|
|
56
|
-
}
|
|
57
43
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { UNNEST } from '../constants.js';
|
|
2
|
+
import { ExprNode } from './node.js';
|
|
3
|
+
|
|
4
|
+
export class UnnestNode extends ExprNode {
|
|
5
|
+
/** An expression that resolves to a list or a struct */
|
|
6
|
+
readonly expr: ExprNode;
|
|
7
|
+
readonly recursive: boolean;
|
|
8
|
+
readonly maxDepth: number;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Instantiate an Unnest node.
|
|
12
|
+
* @param expr
|
|
13
|
+
* @param recursive
|
|
14
|
+
* @param maxDepth
|
|
15
|
+
*/
|
|
16
|
+
constructor(expr: ExprNode, recursive = false, maxDepth = 0) {
|
|
17
|
+
super(UNNEST);
|
|
18
|
+
this.expr = expr;
|
|
19
|
+
this.recursive = recursive;
|
|
20
|
+
this.maxDepth = maxDepth;
|
|
21
|
+
}
|
|
22
|
+
}
|
package/src/ast/verbatim.ts
CHANGED
package/src/ast/window-frame.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { WINDOW_EXTENT_EXPR, WINDOW_FRAME } from '../constants.js';
|
|
2
2
|
import { type ParamLike } from '../types.js';
|
|
3
3
|
import { isParamLike } from '../util/type-check.js';
|
|
4
|
-
import { type ExprNode,
|
|
4
|
+
import { type ExprNode, SQLNode } from './node.js';
|
|
5
5
|
import { ParamNode } from './param.js';
|
|
6
6
|
|
|
7
7
|
export type FrameValue = ExprNode | number | null;
|
|
@@ -42,27 +42,6 @@ export class WindowFrameNode extends SQLNode {
|
|
|
42
42
|
this.extent = isParamLike(extent) ? new ParamNode(extent) : extent;
|
|
43
43
|
this.exclude = exclude;
|
|
44
44
|
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Generate a SQL query string for this node.
|
|
48
|
-
*/
|
|
49
|
-
toString() {
|
|
50
|
-
const { frameType, exclude, extent } = this;
|
|
51
|
-
const [prev, next] = isNode(extent)
|
|
52
|
-
? extent.value as [unknown, unknown]
|
|
53
|
-
: extent;
|
|
54
|
-
const a = asFrameExpr(prev, PRECEDING);
|
|
55
|
-
const b = asFrameExpr(next, FOLLOWING);
|
|
56
|
-
return `${frameType} BETWEEN ${a} AND ${b}${exclude ? ` ${exclude}` : ''}`;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function asFrameExpr(value: unknown, scope: string) {
|
|
61
|
-
return value instanceof WindowFrameExprNode ? value
|
|
62
|
-
: value != null && typeof value !== 'number' ? `${value} ${scope}`
|
|
63
|
-
: value === 0 ? CURRENT_ROW
|
|
64
|
-
: !(value && Number.isFinite(value)) ? `${UNBOUNDED} ${scope}`
|
|
65
|
-
: `${Math.abs(value)} ${scope}`;
|
|
66
45
|
}
|
|
67
46
|
|
|
68
47
|
export class WindowFrameExprNode extends SQLNode {
|
|
@@ -84,14 +63,4 @@ export class WindowFrameExprNode extends SQLNode {
|
|
|
84
63
|
this.scope = scope;
|
|
85
64
|
this.expr = expr;
|
|
86
65
|
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Generate a SQL query string for this node.
|
|
90
|
-
*/
|
|
91
|
-
toString() {
|
|
92
|
-
const { scope, expr } = this;
|
|
93
|
-
return scope === CURRENT_ROW
|
|
94
|
-
? scope
|
|
95
|
-
: `${expr ?? UNBOUNDED} ${scope}`;
|
|
96
|
-
}
|
|
97
66
|
}
|
package/src/ast/window.ts
CHANGED
|
@@ -3,7 +3,6 @@ import type { AggregateNode } from './aggregate.js';
|
|
|
3
3
|
import type { WindowFrameNode } from './window-frame.js';
|
|
4
4
|
import { WINDOW, WINDOW_CLAUSE, WINDOW_DEF, WINDOW_FUNCTION } from '../constants.js';
|
|
5
5
|
import { nodeList } from '../util/function.js';
|
|
6
|
-
import { quoteIdentifier } from '../util/string.js';
|
|
7
6
|
import { ExprNode, SQLNode } from './node.js';
|
|
8
7
|
|
|
9
8
|
export class WindowClauseNode extends SQLNode {
|
|
@@ -22,13 +21,6 @@ export class WindowClauseNode extends SQLNode {
|
|
|
22
21
|
this.name = name;
|
|
23
22
|
this.def = def;
|
|
24
23
|
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Generate a SQL query string for this node.
|
|
28
|
-
*/
|
|
29
|
-
toString() {
|
|
30
|
-
return `${quoteIdentifier(this.name)} AS ${this.def}`;
|
|
31
|
-
}
|
|
32
24
|
}
|
|
33
25
|
|
|
34
26
|
export class WindowNode extends ExprNode {
|
|
@@ -84,13 +76,6 @@ export class WindowNode extends ExprNode {
|
|
|
84
76
|
frame(framedef: WindowFrameNode) {
|
|
85
77
|
return new WindowNode(this.func, this.def.frame(framedef));
|
|
86
78
|
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Generate a SQL query string for this node.
|
|
90
|
-
*/
|
|
91
|
-
toString() {
|
|
92
|
-
return `${this.func} OVER ${this.def}`;
|
|
93
|
-
}
|
|
94
79
|
}
|
|
95
80
|
|
|
96
81
|
export class WindowFunctionNode extends ExprNode {
|
|
@@ -123,19 +108,6 @@ export class WindowFunctionNode extends ExprNode {
|
|
|
123
108
|
this.ignoreNulls = ignoreNulls;
|
|
124
109
|
this.order = nodeList([argOrder]);
|
|
125
110
|
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Generate a SQL query string for this node.
|
|
129
|
-
*/
|
|
130
|
-
toString() {
|
|
131
|
-
const { name, args, ignoreNulls, order } = this;
|
|
132
|
-
const arg = [
|
|
133
|
-
args.join(', '),
|
|
134
|
-
order.length ? `ORDER BY ${order.join(', ')}` : '',
|
|
135
|
-
ignoreNulls ? 'IGNORE NULLS' : ''
|
|
136
|
-
].filter(x => x).join(' ');
|
|
137
|
-
return `${name}(${arg})`;
|
|
138
|
-
}
|
|
139
111
|
}
|
|
140
112
|
|
|
141
113
|
export class WindowDefNode extends SQLNode {
|
|
@@ -203,21 +175,6 @@ export class WindowDefNode extends SQLNode {
|
|
|
203
175
|
frame(framedef: WindowFrameNode) {
|
|
204
176
|
return deriveDef(this, { framedef });
|
|
205
177
|
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Generate a SQL query string for this node.
|
|
209
|
-
*/
|
|
210
|
-
toString() {
|
|
211
|
-
const { name, partition, order, framedef } = this;
|
|
212
|
-
const base = name && quoteIdentifier(name);
|
|
213
|
-
const def = [
|
|
214
|
-
base,
|
|
215
|
-
partition?.length && `PARTITION BY ${partition.join(', ')}`,
|
|
216
|
-
order?.length && `ORDER BY ${order.join(', ')}`,
|
|
217
|
-
framedef
|
|
218
|
-
].filter(x => x);
|
|
219
|
-
return base && def.length < 2 ? base : `(${def.join(' ')})`;
|
|
220
|
-
}
|
|
221
178
|
}
|
|
222
179
|
|
|
223
180
|
interface DeriveDefOptions {
|
package/src/ast/with.ts
CHANGED
|
@@ -29,15 +29,4 @@ export class WithClauseNode extends SQLNode {
|
|
|
29
29
|
this.query = query;
|
|
30
30
|
this.materialized = materialized;
|
|
31
31
|
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Generate a SQL query string for this node.
|
|
35
|
-
*/
|
|
36
|
-
toString() {
|
|
37
|
-
const flag = this.materialized;
|
|
38
|
-
const mat = flag === true ? ' MATERIALIZED'
|
|
39
|
-
: flag === false ? ' NOT MATERIALIZED'
|
|
40
|
-
: '';
|
|
41
|
-
return `"${this.name}" AS${mat} (${this.query})`;
|
|
42
|
-
}
|
|
43
32
|
}
|
package/src/constants.ts
CHANGED
|
@@ -3,6 +3,8 @@ export const COLUMN_PARAM = 'COLUMN_PARAM';
|
|
|
3
3
|
export const TABLE_REF = 'TABLE_REF';
|
|
4
4
|
export const LITERAL = 'LITERAL';
|
|
5
5
|
export const INTERVAL = 'INTERVAL';
|
|
6
|
+
export const LIST = 'LIST';
|
|
7
|
+
export const UNNEST = 'UNNEST';
|
|
6
8
|
|
|
7
9
|
export const ORDER_BY = 'ORDER_BY';
|
|
8
10
|
export const CAST = 'CAST';
|
|
@@ -25,6 +27,7 @@ export const WINDOW_FUNCTION = 'WINDOW_FUNCTION';
|
|
|
25
27
|
export const WINDOW_DEF = 'WINDOW_DEF';
|
|
26
28
|
export const WINDOW_FRAME = 'WINDOW_FRAME';
|
|
27
29
|
export const WINDOW_EXTENT_EXPR = 'WINDOW_EXTENT_EXPR';
|
|
30
|
+
export const CUSTOM = 'CUSTOM';
|
|
28
31
|
|
|
29
32
|
export const EXPRESSION = 'EXPRESSION';
|
|
30
33
|
export const FRAGMENT = 'FRAGMENT';
|
|
@@ -35,6 +38,7 @@ export const WITH_CLAUSE = 'WITH_CLAUSE';
|
|
|
35
38
|
export const WINDOW_CLAUSE = 'WINDOW_CLAUSE';
|
|
36
39
|
export const SELECT_CLAUSE = 'SELECT_CLAUSE';
|
|
37
40
|
export const FROM_CLAUSE = 'FROM_CLAUSE';
|
|
41
|
+
export const JOIN_CLAUSE = 'JOIN_CLAUSE';
|
|
38
42
|
export const SAMPLE_CLAUSE = 'SAMPLE_CLAUSE';
|
|
39
43
|
|
|
40
44
|
export const SELECT_QUERY = 'SELECT_QUERY';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FromClauseNode } from "../ast/from.js";
|
|
2
|
+
import { SampleClauseNode } from "../ast/sample.js";
|
|
3
|
+
import { TableRefNode } from "../ast/table-ref.js";
|
|
4
|
+
import { asTableRef } from "../util/ast.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Create a new table FROM reference, applicable in a query or join.
|
|
8
|
+
* @param table The table.
|
|
9
|
+
* @param alias An optional table alias.
|
|
10
|
+
* @param sample An optional table sample to apply.
|
|
11
|
+
*/
|
|
12
|
+
export function from(
|
|
13
|
+
table: string | string[] | TableRefNode,
|
|
14
|
+
alias?: string,
|
|
15
|
+
sample?: SampleClauseNode
|
|
16
|
+
) {
|
|
17
|
+
return new FromClauseNode(asTableRef(table)!, alias, sample);
|
|
18
|
+
}
|