@uwdata/mosaic-sql 0.19.0 → 0.20.1
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 +0 -4
- package/dist/src/ast/list.d.ts.map +1 -1
- package/dist/src/ast/list.js +0 -6
- package/dist/src/ast/list.js.map +1 -1
- 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 +2 -14
- package/dist/src/ast/query.d.ts.map +1 -1
- package/dist/src/ast/query.js +14 -91
- 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 +0 -4
- package/dist/src/ast/unnest.d.ts.map +1 -1
- package/dist/src/ast/unnest.js +0 -8
- package/dist/src/ast/unnest.js.map +1 -1
- 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 +2 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +2 -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/index.d.ts +7 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +8 -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/bin-histogram.d.ts.map +1 -1
- package/dist/src/transforms/bin-histogram.js +7 -2
- package/dist/src/transforms/bin-histogram.js.map +1 -1
- 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/transforms/util/time-interval.d.ts.map +1 -1
- package/dist/src/transforms/util/time-interval.js +3 -0
- package/dist/src/transforms/util/time-interval.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 +2 -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 +0 -7
- 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 +14 -102
- 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 +0 -9
- 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 +2 -0
- package/src/functions/from.ts +18 -0
- package/src/functions/join.ts +101 -0
- package/src/index.ts +9 -1
- package/src/init.ts +5 -0
- package/src/transforms/bin-histogram.ts +8 -2
- package/src/transforms/filter-query.ts +2 -0
- package/src/transforms/util/time-interval.ts +4 -0
- package/src/visit/codegen/duckdb.ts +444 -0
- package/src/visit/codegen/sql.ts +213 -0
- package/src/visit/recurse.ts +2 -0
package/src/ast/case.ts
CHANGED
|
@@ -52,17 +52,6 @@ export class CaseNode extends ExprNode {
|
|
|
52
52
|
else(expr: ExprValue) {
|
|
53
53
|
return new CaseNode(this.expr, this._when, asNode(expr));
|
|
54
54
|
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Generate a SQL query string for this node.
|
|
58
|
-
*/
|
|
59
|
-
toString() {
|
|
60
|
-
return 'CASE '
|
|
61
|
-
+ (this.expr ? `${this.expr} ` : '')
|
|
62
|
-
+ this._when.join(' ')
|
|
63
|
-
+ (this._else ? ` ELSE ${this._else}` : '')
|
|
64
|
-
+ ' END';
|
|
65
|
-
}
|
|
66
55
|
}
|
|
67
56
|
|
|
68
57
|
export class WhenNode extends SQLNode {
|
|
@@ -81,11 +70,4 @@ export class WhenNode extends SQLNode {
|
|
|
81
70
|
this.when = when;
|
|
82
71
|
this.then = then;
|
|
83
72
|
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Generate a SQL query string for this node.
|
|
87
|
-
*/
|
|
88
|
-
toString() {
|
|
89
|
-
return `WHEN ${this.when} THEN ${this.then}`;
|
|
90
|
-
}
|
|
91
73
|
}
|
package/src/ast/cast.ts
CHANGED
|
@@ -17,12 +17,4 @@ export class CastNode extends ExprNode {
|
|
|
17
17
|
this.expr = expr;
|
|
18
18
|
this.cast = type;
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Generate a SQL query string for this node.
|
|
23
|
-
*/
|
|
24
|
-
toString() {
|
|
25
|
-
// TODO? could include check to see if parens are necessary
|
|
26
|
-
return `(${this.expr})::${this.cast}`;
|
|
27
|
-
}
|
|
28
20
|
}
|
package/src/ast/collate.ts
CHANGED
package/src/ast/column-ref.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { TableRefNode } from './table-ref.js';
|
|
2
2
|
import { COLUMN_REF } from '../constants.js';
|
|
3
|
-
import { quoteIdentifier } from '../util/string.js';
|
|
4
3
|
import { ExprNode } from './node.js';
|
|
5
4
|
|
|
6
5
|
/**
|
|
@@ -31,16 +30,6 @@ export class ColumnRefNode extends ExprNode {
|
|
|
31
30
|
get column() {
|
|
32
31
|
return ''; // subclasses to override
|
|
33
32
|
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Generate a SQL query string for this node.
|
|
37
|
-
*/
|
|
38
|
-
toString() {
|
|
39
|
-
const { column, table } = this;
|
|
40
|
-
const tref = `${table ?? ''}`;
|
|
41
|
-
const id = column === '*' ? '*' : quoteIdentifier(column);
|
|
42
|
-
return (tref ? (tref + '.') : '') + id;
|
|
43
|
-
}
|
|
44
33
|
}
|
|
45
34
|
|
|
46
35
|
export class ColumnNameRefNode extends ColumnRefNode {
|
package/src/ast/fragment.ts
CHANGED
package/src/ast/from.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import type { SampleClauseNode } from './sample.js';
|
|
2
2
|
import { FROM_CLAUSE } from '../constants.js';
|
|
3
|
-
import { quoteIdentifier } from '../util/string.js';
|
|
4
3
|
import { SQLNode } from './node.js';
|
|
5
|
-
import { isQuery } from './query.js';
|
|
6
|
-
import { isTableRef } from './table-ref.js';
|
|
7
4
|
|
|
8
|
-
|
|
5
|
+
/**
|
|
6
|
+
* AST node corresponding to a table source which can appear
|
|
7
|
+
* within a SQL `FROM` clause.
|
|
8
|
+
*/
|
|
9
|
+
export class FromNode extends SQLNode {
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class FromClauseNode extends FromNode {
|
|
9
13
|
/** The from expression. */
|
|
10
14
|
readonly expr: SQLNode;
|
|
11
15
|
/** The output name. */
|
|
@@ -27,14 +31,10 @@ export class FromClauseNode extends SQLNode {
|
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
/**
|
|
30
|
-
*
|
|
34
|
+
* Create a new from clause node that uses the given alias.
|
|
35
|
+
* @param string alias
|
|
31
36
|
*/
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const ref = isQuery(expr) ? `(${expr})` : `${expr}`;
|
|
35
|
-
const from = alias && !(isTableRef(expr) && expr.table.join('.') === alias)
|
|
36
|
-
? `${ref} AS ${quoteIdentifier(alias)}`
|
|
37
|
-
: `${ref}`;
|
|
38
|
-
return `${from}${sample ? ` TABLESAMPLE ${sample}` : ''}`;
|
|
37
|
+
as(alias: string) {
|
|
38
|
+
return new FromClauseNode(this.expr, alias, this.sample);
|
|
39
39
|
}
|
|
40
40
|
}
|
package/src/ast/function.ts
CHANGED
|
@@ -17,12 +17,4 @@ export class FunctionNode extends ExprNode {
|
|
|
17
17
|
this.name = name;
|
|
18
18
|
this.args = args;
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Generate a SQL query string for this node.
|
|
23
|
-
*/
|
|
24
|
-
toString() {
|
|
25
|
-
const { name, args } = this;
|
|
26
|
-
return `${name}(${args.join(', ')})`;
|
|
27
|
-
}
|
|
28
20
|
}
|
package/src/ast/in-op.ts
CHANGED
package/src/ast/interval.ts
CHANGED
package/src/ast/join.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { SampleClauseNode } from './sample.js';
|
|
2
|
+
import { JOIN_CLAUSE } from '../constants.js';
|
|
3
|
+
import { ColumnRefNode } from './column-ref.js';
|
|
4
|
+
import { FromNode } from './from.js';
|
|
5
|
+
import { ExprNode } from './node.js';
|
|
6
|
+
import { TableRefNode } from './table-ref.js';
|
|
7
|
+
|
|
8
|
+
/** The join variant. Determines what kind of join is performed. */
|
|
9
|
+
export type JoinVariant = 'REGULAR' | 'CROSS' | 'NATURAL' | 'POSITIONAL' | 'ASOF';
|
|
10
|
+
|
|
11
|
+
/** The join type. Determines which values are included in the join output. */
|
|
12
|
+
export type JoinType = 'INNER' | 'LEFT' | 'RIGHT' | 'FULL' | 'SEMI' | 'ANTI';
|
|
13
|
+
|
|
14
|
+
export class JoinNode extends FromNode {
|
|
15
|
+
/** The left table to join. */
|
|
16
|
+
readonly left: FromNode | TableRefNode;
|
|
17
|
+
/** The right table to join. */
|
|
18
|
+
readonly right: FromNode | TableRefNode;
|
|
19
|
+
/** The join variant (REGULAR, CROSS, NATURAL, POSITIONAL, ASOF). */
|
|
20
|
+
readonly joinVariant: JoinVariant;
|
|
21
|
+
/** The join type (INNER, LEFT, RIGHT, FULL, SEMI, ANTI). */
|
|
22
|
+
readonly joinType: JoinType;
|
|
23
|
+
/**
|
|
24
|
+
* The join condition as a boolean expression.
|
|
25
|
+
* If specified, *using* should be `undefined`.
|
|
26
|
+
*/
|
|
27
|
+
readonly condition?: ExprNode;
|
|
28
|
+
/**
|
|
29
|
+
* The join condition as shared columns to match on.
|
|
30
|
+
* If specified, *condition* should be `undefined`.
|
|
31
|
+
*/
|
|
32
|
+
readonly using?: ColumnRefNode[];
|
|
33
|
+
/** A table sample to apply to join output. */
|
|
34
|
+
readonly sample?: SampleClauseNode;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Instantiate a join node.
|
|
38
|
+
* @param left The left table to join.
|
|
39
|
+
* @param right The right table to join.
|
|
40
|
+
* @param variant The join variant (REGULAR, CROSS, NATURAL, POSITIONAL, ASOF).
|
|
41
|
+
* @param type The join type (INNER, LEFT, RIGHT, FULL, SEMI, ANTI).
|
|
42
|
+
* @param condition The join condition as a boolean expression.
|
|
43
|
+
* If specified, *using* should be `undefined`.
|
|
44
|
+
* @param using The join condition as shared columns to match on.
|
|
45
|
+
* If specified, *condition* should be `undefined`.
|
|
46
|
+
* @param sample A table sample to apply to join output.
|
|
47
|
+
*/
|
|
48
|
+
constructor(
|
|
49
|
+
left: FromNode | TableRefNode,
|
|
50
|
+
right: FromNode | TableRefNode,
|
|
51
|
+
variant: JoinVariant = 'NATURAL',
|
|
52
|
+
type: JoinType = 'INNER',
|
|
53
|
+
condition?: ExprNode,
|
|
54
|
+
using?: ColumnRefNode[],
|
|
55
|
+
sample?: SampleClauseNode
|
|
56
|
+
) {
|
|
57
|
+
super(JOIN_CLAUSE);
|
|
58
|
+
this.left = left;
|
|
59
|
+
this.right = right;
|
|
60
|
+
this.joinVariant = variant;
|
|
61
|
+
this.joinType = type;
|
|
62
|
+
this.condition = condition;
|
|
63
|
+
this.using = using;
|
|
64
|
+
this.sample = sample;
|
|
65
|
+
}
|
|
66
|
+
}
|
package/src/ast/list.ts
CHANGED
package/src/ast/literal.ts
CHANGED
|
@@ -13,13 +13,6 @@ export class LiteralNode extends ExprNode {
|
|
|
13
13
|
super(LITERAL);
|
|
14
14
|
this.value = value;
|
|
15
15
|
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Generate a SQL query string for this node.
|
|
19
|
-
*/
|
|
20
|
-
toString() {
|
|
21
|
-
return literalToSQL(this.value);
|
|
22
|
-
}
|
|
23
16
|
}
|
|
24
17
|
|
|
25
18
|
export function literalToSQL(value: unknown) {
|
package/src/ast/logical-op.ts
CHANGED
|
@@ -17,16 +17,6 @@ export class LogicalOpNode<T extends ExprNode> extends ExprNode {
|
|
|
17
17
|
this.op = op;
|
|
18
18
|
this.clauses = clauses;
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Generate a SQL query string for this node.
|
|
23
|
-
*/
|
|
24
|
-
toString() {
|
|
25
|
-
const c = this.clauses;
|
|
26
|
-
return c.length === 0 ? ''
|
|
27
|
-
: c.length === 1 ? `${c[0]}`
|
|
28
|
-
: `(${c.join(` ${this.op} `)})`;
|
|
29
|
-
}
|
|
30
20
|
}
|
|
31
21
|
|
|
32
22
|
export class AndNode<T extends ExprNode> extends LogicalOpNode<T> {
|
package/src/ast/node.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { SQLCodeGenerator } from '../visit/codegen/sql.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Check if a value is a SQL AST node.
|
|
3
5
|
* @param value The value to check.
|
|
@@ -6,6 +8,16 @@ export function isNode(value: unknown): value is SQLNode {
|
|
|
6
8
|
return value instanceof SQLNode;
|
|
7
9
|
}
|
|
8
10
|
|
|
11
|
+
let _defaultVisitor: SQLCodeGenerator | undefined;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Set the default visitor for toString operations.
|
|
15
|
+
* This is used when no visitor is explicitly provided.
|
|
16
|
+
*/
|
|
17
|
+
export function setDefaultVisitor(visitor: SQLCodeGenerator) {
|
|
18
|
+
_defaultVisitor = visitor;
|
|
19
|
+
}
|
|
20
|
+
|
|
9
21
|
export class SQLNode {
|
|
10
22
|
/** The SQL AST node type. */
|
|
11
23
|
readonly type: string;
|
|
@@ -23,13 +35,28 @@ export class SQLNode {
|
|
|
23
35
|
* @returns The shallow clone node.
|
|
24
36
|
*/
|
|
25
37
|
clone(): this {
|
|
26
|
-
// @ts-expect-error use constructor
|
|
27
|
-
const clone = new this.constructor();
|
|
38
|
+
// @ts-expect-error use constructor with type
|
|
39
|
+
const clone = new this.constructor(this.type);
|
|
28
40
|
for (const key in this) {
|
|
29
|
-
|
|
41
|
+
if (key !== 'type') { // Skip type since it's already set by constructor
|
|
42
|
+
clone[key] = this[key];
|
|
43
|
+
}
|
|
30
44
|
}
|
|
31
45
|
return clone;
|
|
32
46
|
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Generate a SQL query string for this node using a specific dialect visitor.
|
|
50
|
+
* @param visitor Optional SQL visitor to use for string generation.
|
|
51
|
+
* If not provided, uses the default visitor.
|
|
52
|
+
* @returns The SQL string representation.
|
|
53
|
+
*/
|
|
54
|
+
toString(visitor: SQLCodeGenerator | undefined = _defaultVisitor): string {
|
|
55
|
+
if (!visitor) {
|
|
56
|
+
throw new Error('No visitor provided and no default visitor set.');
|
|
57
|
+
}
|
|
58
|
+
return visitor.toString(this);
|
|
59
|
+
}
|
|
33
60
|
}
|
|
34
61
|
|
|
35
62
|
/**
|
package/src/ast/order-by.ts
CHANGED
|
@@ -21,18 +21,4 @@ export class OrderByNode extends ExprNode {
|
|
|
21
21
|
this.desc = desc;
|
|
22
22
|
this.nullsFirst = nullsFirst;
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Generate a SQL query string for this node.
|
|
27
|
-
*/
|
|
28
|
-
toString() {
|
|
29
|
-
const { expr, desc, nullsFirst } = this;
|
|
30
|
-
const dir = desc ? ' DESC'
|
|
31
|
-
: desc === false ? ' ASC'
|
|
32
|
-
: '';
|
|
33
|
-
const nf = nullsFirst ? ' NULLS FIRST'
|
|
34
|
-
: nullsFirst === false ? ' NULLS LAST'
|
|
35
|
-
: '';
|
|
36
|
-
return `${expr}${dir}${nf}`;
|
|
37
|
-
}
|
|
38
24
|
}
|
package/src/ast/param.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { ParamLike } from '../types.js';
|
|
2
2
|
import { PARAM } from '../constants.js';
|
|
3
|
-
import { literalToSQL } from './literal.js';
|
|
4
3
|
import { ExprNode } from './node.js';
|
|
5
4
|
|
|
6
5
|
export class ParamNode extends ExprNode {
|
|
@@ -22,11 +21,4 @@ export class ParamNode extends ExprNode {
|
|
|
22
21
|
get value() {
|
|
23
22
|
return this.param.value;
|
|
24
23
|
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Generate a SQL query string for this node.
|
|
28
|
-
*/
|
|
29
|
-
toString() {
|
|
30
|
-
return literalToSQL(this.value);
|
|
31
|
-
}
|
|
32
24
|
}
|
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';
|
|
@@ -231,7 +231,7 @@ export class Query extends ExprNode {
|
|
|
231
231
|
|
|
232
232
|
export class SelectQuery extends Query {
|
|
233
233
|
_select: SelectClauseNode[] = [];
|
|
234
|
-
_from:
|
|
234
|
+
_from: FromNode[] = [];
|
|
235
235
|
_where: ExprNode[] = [];
|
|
236
236
|
_sample?: SampleClauseNode;
|
|
237
237
|
_groupby: ExprNode[] = [];
|
|
@@ -261,13 +261,17 @@ export class SelectQuery extends Query {
|
|
|
261
261
|
|
|
262
262
|
// extract subqueries in FROM clause
|
|
263
263
|
// unused CTEs will be ignored
|
|
264
|
+
// WARNING: does not recurse into join inputs!
|
|
264
265
|
const queries: Query[] = [];
|
|
265
|
-
this._from.forEach(
|
|
266
|
-
if (
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
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
|
+
}
|
|
271
275
|
}
|
|
272
276
|
});
|
|
273
277
|
return queries;
|
|
@@ -330,7 +334,7 @@ export class SelectQuery extends Query {
|
|
|
330
334
|
* @param expr Expressions to add.
|
|
331
335
|
*/
|
|
332
336
|
from(...expr: FromExpr[]): this {
|
|
333
|
-
const list:
|
|
337
|
+
const list: FromNode[] = [];
|
|
334
338
|
|
|
335
339
|
const add = (v: string | string[] | SQLNode, as?: string) => {
|
|
336
340
|
list.push(new FromClauseNode(maybeTableRef(v), unquote(as)));
|
|
@@ -338,7 +342,7 @@ export class SelectQuery extends Query {
|
|
|
338
342
|
|
|
339
343
|
expr.flat().forEach(e => {
|
|
340
344
|
if (e == null) return;
|
|
341
|
-
else if (e instanceof
|
|
345
|
+
else if (e instanceof FromNode) list.push(e);
|
|
342
346
|
else if (isString(e)) add(e, e);
|
|
343
347
|
else if (isTableRef(e)) add(e, e.name);
|
|
344
348
|
else if (isNode(e)) add(e);
|
|
@@ -450,66 +454,6 @@ export class SelectQuery extends Query {
|
|
|
450
454
|
this._qualify = this._qualify.concat(exprList(expr, asVerbatim));
|
|
451
455
|
return this;
|
|
452
456
|
}
|
|
453
|
-
|
|
454
|
-
/**
|
|
455
|
-
* Generate a SQL query string.
|
|
456
|
-
*/
|
|
457
|
-
toString() {
|
|
458
|
-
const {
|
|
459
|
-
_with, _select, _distinct, _from, _sample, _where, _groupby,
|
|
460
|
-
_having, _window, _qualify, _orderby, _limitPerc, _limit, _offset
|
|
461
|
-
} = this;
|
|
462
|
-
const sql = [];
|
|
463
|
-
|
|
464
|
-
// WITH
|
|
465
|
-
if (_with.length) sql.push(`WITH ${_with.join(', ')}`);
|
|
466
|
-
|
|
467
|
-
// SELECT
|
|
468
|
-
sql.push(`SELECT${_distinct ? ' DISTINCT' : ''} ${_select.join(', ')}`);
|
|
469
|
-
|
|
470
|
-
// FROM
|
|
471
|
-
if (_from.length) sql.push(`FROM ${_from.join(', ')}`);
|
|
472
|
-
|
|
473
|
-
// WHERE
|
|
474
|
-
if (_where.length) {
|
|
475
|
-
const clauses = _where.map(String).filter(x => x).join(' AND ');
|
|
476
|
-
if (clauses) sql.push(`WHERE ${clauses}`);
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
// SAMPLE
|
|
480
|
-
if (_sample) sql.push(`USING SAMPLE ${_sample}`);
|
|
481
|
-
|
|
482
|
-
// GROUP BY
|
|
483
|
-
if (_groupby.length) {
|
|
484
|
-
sql.push(`GROUP BY ${_groupby.join(', ')}`);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
// HAVING
|
|
488
|
-
if (_having.length) {
|
|
489
|
-
const clauses = _having.map(String).filter(x => x).join(' AND ');
|
|
490
|
-
if (clauses) sql.push(`HAVING ${clauses}`);
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
// WINDOW
|
|
494
|
-
if (_window.length) sql.push(`WINDOW ${_window.join(', ')}`);
|
|
495
|
-
|
|
496
|
-
// QUALIFY
|
|
497
|
-
if (_qualify.length) {
|
|
498
|
-
const clauses = _qualify.map(String).filter(x => x).join(' AND ');
|
|
499
|
-
if (clauses) sql.push(`QUALIFY ${clauses}`);
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
// ORDER BY
|
|
503
|
-
if (_orderby.length) sql.push(`ORDER BY ${_orderby.join(', ')}`);
|
|
504
|
-
|
|
505
|
-
// LIMIT
|
|
506
|
-
if (_limit) sql.push(`LIMIT ${_limit}${_limitPerc ? '%' : ''}`);
|
|
507
|
-
|
|
508
|
-
// OFFSET
|
|
509
|
-
if (_offset) sql.push(`OFFSET ${_offset}`);
|
|
510
|
-
|
|
511
|
-
return sql.join(' ');
|
|
512
|
-
}
|
|
513
457
|
}
|
|
514
458
|
|
|
515
459
|
export class DescribeQuery extends SQLNode {
|
|
@@ -531,13 +475,6 @@ export class DescribeQuery extends SQLNode {
|
|
|
531
475
|
// @ts-expect-error creates describe query
|
|
532
476
|
return new DescribeQuery(this.query.clone());
|
|
533
477
|
}
|
|
534
|
-
|
|
535
|
-
/**
|
|
536
|
-
* Generate a SQL query string.
|
|
537
|
-
*/
|
|
538
|
-
toString() {
|
|
539
|
-
return `DESCRIBE ${this.query}`;
|
|
540
|
-
}
|
|
541
478
|
}
|
|
542
479
|
|
|
543
480
|
export class SetOperation extends Query {
|
|
@@ -582,31 +519,6 @@ export class SetOperation extends Query {
|
|
|
582
519
|
// @ts-expect-error creates set operation
|
|
583
520
|
return Object.assign(new SetOperation(op, queries), rest);
|
|
584
521
|
}
|
|
585
|
-
|
|
586
|
-
/**
|
|
587
|
-
* Generate a SQL query string.
|
|
588
|
-
*/
|
|
589
|
-
toString() {
|
|
590
|
-
const { op, queries, _with, _orderby, _limitPerc, _limit, _offset } = this;
|
|
591
|
-
const sql = [];
|
|
592
|
-
|
|
593
|
-
// WITH
|
|
594
|
-
if (_with.length) sql.push(`WITH ${_with.join(', ')}`);
|
|
595
|
-
|
|
596
|
-
// SUBQUERIES
|
|
597
|
-
sql.push(queries.join(` ${op} `));
|
|
598
|
-
|
|
599
|
-
// ORDER BY
|
|
600
|
-
if (_orderby.length) sql.push(`ORDER BY ${_orderby.join(', ')}`);
|
|
601
|
-
|
|
602
|
-
// LIMIT
|
|
603
|
-
if (_limit) sql.push(`LIMIT ${_limit}${_limitPerc ? '%' : ''}`);
|
|
604
|
-
|
|
605
|
-
// OFFSET
|
|
606
|
-
if (_offset) sql.push(`OFFSET ${_offset}`);
|
|
607
|
-
|
|
608
|
-
return sql.join(' ');
|
|
609
|
-
}
|
|
610
522
|
}
|
|
611
523
|
|
|
612
524
|
class WithClause {
|
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
|
}
|
package/src/ast/unnest.ts
CHANGED
|
@@ -19,13 +19,4 @@ export class UnnestNode extends ExprNode {
|
|
|
19
19
|
this.recursive = recursive;
|
|
20
20
|
this.maxDepth = maxDepth;
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Generate a SQL query string for this node.
|
|
25
|
-
*/
|
|
26
|
-
toString() {
|
|
27
|
-
const recursive = this.recursive ? ', recursive := true' : '';
|
|
28
|
-
const maxDepth = this.maxDepth > 0 ? `, max_depth := ${this.maxDepth}` : '';
|
|
29
|
-
return `UNNEST(${this.expr}${recursive}${maxDepth})`;
|
|
30
|
-
}
|
|
31
22
|
}
|