@uwdata/mosaic-sql 0.11.0 → 0.12.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/README.md +2 -0
- package/dist/mosaic-sql.js +2242 -1064
- package/dist/mosaic-sql.min.js +1 -1
- package/dist/types/ast/aggregate.d.ts +70 -0
- package/dist/types/ast/between-op.d.ts +46 -0
- package/dist/types/ast/binary-op.d.ts +28 -0
- package/dist/types/ast/case.d.ts +68 -0
- package/dist/types/ast/cast.d.ts +21 -0
- package/dist/types/ast/column-param.d.ts +17 -0
- package/dist/types/ast/column-ref.d.ts +39 -0
- package/dist/types/ast/fragment.d.ts +14 -0
- package/dist/types/ast/from.d.ts +21 -0
- package/dist/types/ast/function.d.ts +21 -0
- package/dist/types/ast/in-op.d.ts +21 -0
- package/dist/types/ast/interval.d.ts +21 -0
- package/dist/types/ast/literal.d.ts +15 -0
- package/dist/types/ast/logical-op.d.ts +46 -0
- package/dist/types/ast/node.d.ts +24 -0
- package/dist/types/ast/order-by.d.ts +29 -0
- package/dist/types/ast/param.d.ts +19 -0
- package/dist/types/ast/query.d.ts +268 -0
- package/dist/types/ast/sample.d.ts +42 -0
- package/dist/types/ast/select.d.ts +22 -0
- package/dist/types/ast/table-ref.d.ts +25 -0
- package/dist/types/ast/unary-op.d.ts +39 -0
- package/dist/types/ast/verbatim.d.ts +9 -0
- package/dist/types/ast/window.d.ts +177 -0
- package/dist/types/ast/with.d.ts +22 -0
- package/dist/types/constants.d.ts +38 -0
- package/dist/types/functions/aggregate.d.ts +229 -0
- package/dist/types/functions/case.d.ts +15 -0
- package/dist/types/functions/cast.d.ts +26 -0
- package/dist/types/functions/column.d.ts +9 -0
- package/dist/types/functions/datetime.d.ts +44 -0
- package/dist/types/functions/literal.d.ts +16 -0
- package/dist/types/functions/numeric.d.ts +93 -0
- package/dist/types/functions/operators.d.ts +198 -0
- package/dist/types/functions/order-by.d.ts +17 -0
- package/dist/types/functions/spatial.d.ts +37 -0
- package/dist/types/functions/sql-template-tag.d.ts +16 -0
- package/dist/types/functions/string.d.ts +55 -0
- package/dist/types/functions/table-ref.d.ts +9 -0
- package/dist/types/functions/window.d.ts +87 -0
- package/dist/types/index-types.d.ts +2 -0
- package/dist/types/index.d.ts +53 -0
- package/dist/types/load/create.d.ts +8 -0
- package/dist/types/load/extension.d.ts +1 -0
- package/dist/types/load/load.d.ts +12 -0
- package/dist/types/load/sql-from.d.ts +11 -0
- package/dist/types/transforms/bin-1d.d.ts +14 -0
- package/dist/types/transforms/bin-2d.d.ts +18 -0
- package/dist/types/transforms/bin-linear-1d.d.ts +9 -0
- package/dist/types/transforms/bin-linear-2d.d.ts +18 -0
- package/dist/types/transforms/line-density.d.ts +23 -0
- package/dist/types/transforms/m4.d.ts +18 -0
- package/dist/types/transforms/scales.d.ts +1 -0
- package/dist/types/types.d.ts +59 -0
- package/dist/types/util/ast.d.ts +60 -0
- package/dist/types/util/function.d.ts +54 -0
- package/dist/types/util/string.d.ts +3 -0
- package/dist/types/util/type-check.d.ts +18 -0
- package/dist/types/visit/recurse.d.ts +28 -0
- package/dist/types/visit/rewrite.d.ts +10 -0
- package/dist/types/visit/visitors.d.ts +33 -0
- package/dist/types/visit/walk.d.ts +7 -0
- package/jsconfig.json +11 -0
- package/package.json +6 -4
- package/src/ast/aggregate.js +164 -0
- package/src/ast/between-op.js +75 -0
- package/src/ast/binary-op.js +40 -0
- package/src/ast/case.js +105 -0
- package/src/ast/cast.js +34 -0
- package/src/ast/column-param.js +29 -0
- package/src/ast/column-ref.js +72 -0
- package/src/ast/fragment.js +26 -0
- package/src/ast/from.js +40 -0
- package/src/ast/function.js +34 -0
- package/src/ast/in-op.js +33 -0
- package/src/ast/interval.js +33 -0
- package/src/ast/literal.js +55 -0
- package/src/ast/logical-op.js +67 -0
- package/src/ast/node.js +29 -0
- package/src/ast/order-by.js +48 -0
- package/src/ast/param.js +35 -0
- package/src/ast/query.js +578 -0
- package/src/ast/sample.js +53 -0
- package/src/ast/select.js +44 -0
- package/src/ast/table-ref.js +44 -0
- package/src/ast/unary-op.js +64 -0
- package/src/ast/verbatim.js +26 -0
- package/src/ast/window.js +290 -0
- package/src/ast/with.js +30 -0
- package/src/constants.js +44 -0
- package/src/functions/aggregate.js +335 -0
- package/src/functions/case.js +21 -0
- package/src/functions/cast.js +39 -0
- package/src/functions/column.js +20 -0
- package/src/functions/datetime.js +65 -0
- package/src/functions/literal.js +22 -0
- package/src/functions/numeric.js +139 -0
- package/src/functions/operators.js +298 -0
- package/src/functions/order-by.js +24 -0
- package/src/functions/spatial.js +56 -0
- package/src/functions/sql-template-tag.js +51 -0
- package/src/functions/string.js +82 -0
- package/src/functions/table-ref.js +14 -0
- package/src/functions/window.js +121 -0
- package/src/index-types.ts +2 -0
- package/src/index.js +57 -155
- package/src/load/create.js +10 -2
- package/src/load/load.js +4 -4
- package/src/load/sql-from.js +7 -6
- package/src/transforms/bin-1d.js +21 -0
- package/src/transforms/bin-2d.js +29 -0
- package/src/transforms/bin-linear-1d.js +26 -0
- package/src/transforms/bin-linear-2d.js +71 -0
- package/src/transforms/line-density.js +113 -0
- package/src/transforms/m4.js +38 -0
- package/src/{scales.js → transforms/scales.js} +31 -17
- package/src/types.ts +96 -0
- package/src/util/ast.js +96 -0
- package/src/util/function.js +78 -0
- package/src/util/string.js +16 -0
- package/src/util/type-check.js +29 -0
- package/src/visit/recurse.js +57 -0
- package/src/visit/rewrite.js +32 -0
- package/src/visit/visitors.js +108 -0
- package/src/visit/walk.js +30 -0
- package/tsconfig.json +12 -0
- package/src/Query.js +0 -593
- package/src/aggregates.js +0 -185
- package/src/cast.js +0 -19
- package/src/datetime.js +0 -31
- package/src/desc.js +0 -13
- package/src/expression.js +0 -170
- package/src/functions.js +0 -25
- package/src/literal.js +0 -6
- package/src/operators.js +0 -54
- package/src/ref.js +0 -109
- package/src/repeat.js +0 -3
- package/src/spatial.js +0 -10
- package/src/to-sql.js +0 -52
- package/src/windows.js +0 -239
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export namespace recurse {
|
|
2
|
+
let AGGREGATE: string[];
|
|
3
|
+
let BETWEEN: string[];
|
|
4
|
+
let BINARY: string[];
|
|
5
|
+
let CASE: string[];
|
|
6
|
+
let CAST: string[];
|
|
7
|
+
let COLUMN_PARAM: string[];
|
|
8
|
+
let COLUMN_REF: string[];
|
|
9
|
+
let DESCRIBE_QUERY: string[];
|
|
10
|
+
let EXPRESSION: string[];
|
|
11
|
+
let FRAGMENT: string[];
|
|
12
|
+
let FROM_CLAUSE: string[];
|
|
13
|
+
let FUNCTION: string[];
|
|
14
|
+
let IN: string[];
|
|
15
|
+
let LOGICAL_OPERATOR: string[];
|
|
16
|
+
let NOT_BETWEEN: string[];
|
|
17
|
+
let ORDER_BY: string[];
|
|
18
|
+
let PARAM: string[];
|
|
19
|
+
let SELECT_CLAUSE: string[];
|
|
20
|
+
let SELECT_QUERY: string[];
|
|
21
|
+
let SET_OPERATION: string[];
|
|
22
|
+
let UNARY: string[];
|
|
23
|
+
let WHEN: string[];
|
|
24
|
+
let WINDOW: string[];
|
|
25
|
+
let WINDOW_CLAUSE: string[];
|
|
26
|
+
let WINDOW_DEF: string[];
|
|
27
|
+
let WINDOW_FRAME: string[];
|
|
28
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rewrite a SQL expression, based on a map of nodes to replace.
|
|
3
|
+
* This method updates the expression in place.
|
|
4
|
+
* @param {ExprNode} node The root AST node of the expression.
|
|
5
|
+
* @param {Map<ExprNode, ExprNode>} map The rewrite map.
|
|
6
|
+
* When encountered, key nodes are replaced by value nodes.
|
|
7
|
+
* @returns {ExprNode}
|
|
8
|
+
*/
|
|
9
|
+
export function rewrite(node: ExprNode, map: Map<ExprNode, ExprNode>): ExprNode;
|
|
10
|
+
import { ExprNode } from '../ast/node.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Indicate if the input AST contains an aggregate expression.
|
|
3
|
+
* The string content of verbatim nodes is analyzed to try to identify
|
|
4
|
+
* unparsed aggregate functions calls within SQL strings.
|
|
5
|
+
* @param {SQLNode} root The root of the AST to search.
|
|
6
|
+
* @returns {number} Return 0 if no aggregate functions are found.
|
|
7
|
+
* Sets bit 1 if an AggregateFunction instance is found.
|
|
8
|
+
* Sets bit 2 if an aggregate embedded in verbatim text is found.
|
|
9
|
+
*/
|
|
10
|
+
export function isAggregateExpression(root: SQLNode): number;
|
|
11
|
+
/**
|
|
12
|
+
* Collect all aggregate function nodes.
|
|
13
|
+
* @param {SQLNode} root The root of the AST to search.
|
|
14
|
+
* @returns {AggregateNode[]}
|
|
15
|
+
*/
|
|
16
|
+
export function collectAggregates(root: SQLNode): AggregateNode[];
|
|
17
|
+
/**
|
|
18
|
+
* Collect all unique column references.
|
|
19
|
+
* Multiple references to the same column are de-duplicated, even if
|
|
20
|
+
* they are not object-equal node instances.
|
|
21
|
+
* @param {SQLNode} root The root of the AST to search.
|
|
22
|
+
* @returns {ColumnRefNode[]}
|
|
23
|
+
*/
|
|
24
|
+
export function collectColumns(root: SQLNode): ColumnRefNode[];
|
|
25
|
+
/**
|
|
26
|
+
* Collect all unique dynamic parameter instances.
|
|
27
|
+
* @param {SQLNode} root The root of the AST to search.
|
|
28
|
+
* @returns {import('../types.js').ParamLike[]}
|
|
29
|
+
*/
|
|
30
|
+
export function collectParams(root: SQLNode): import("../types.js").ParamLike[];
|
|
31
|
+
import { SQLNode } from '../ast/node.js';
|
|
32
|
+
import { AggregateNode } from '../ast/aggregate.js';
|
|
33
|
+
import { ColumnRefNode } from '../ast/column-ref.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Perform a traversal of a SQL expression AST.
|
|
3
|
+
* @param {import('../ast/node.js').SQLNode} node Root node for AST traversal.
|
|
4
|
+
* @param {import('../types.js').VisitorCallback} visit Visitor callback function.
|
|
5
|
+
* @return {import('../types.js').VisitorResult}
|
|
6
|
+
*/
|
|
7
|
+
export function walk(node: import("../ast/node.js").SQLNode, visit: import("../types.js").VisitorCallback): import("../types.js").VisitorResult;
|
package/jsconfig.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uwdata/mosaic-sql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "SQL query construction and analysis.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sql",
|
|
@@ -14,16 +14,18 @@
|
|
|
14
14
|
"module": "src/index.js",
|
|
15
15
|
"jsdelivr": "dist/mosaic-sql.min.js",
|
|
16
16
|
"unpkg": "dist/mosaic-sql.min.js",
|
|
17
|
+
"types": "dist/types/index-types.d.ts",
|
|
17
18
|
"repository": {
|
|
18
19
|
"type": "git",
|
|
19
20
|
"url": "https://github.com/uwdata/mosaic.git"
|
|
20
21
|
},
|
|
21
22
|
"scripts": {
|
|
22
23
|
"prebuild": "rimraf dist && mkdir dist",
|
|
23
|
-
"build": "node ../../esbuild.js mosaic-sql",
|
|
24
|
+
"build": "npm run types && node ../../esbuild.js mosaic-sql",
|
|
25
|
+
"types": "tsc",
|
|
24
26
|
"lint": "eslint src test",
|
|
25
|
-
"test": "vitest run",
|
|
27
|
+
"test": "vitest run && tsc -p jsconfig.json",
|
|
26
28
|
"prepublishOnly": "npm run test && npm run lint && npm run build"
|
|
27
29
|
},
|
|
28
|
-
"gitHead": "
|
|
30
|
+
"gitHead": "fe3a7c34352da54ec36a1ebf557846f46a649782"
|
|
29
31
|
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { AGGREGATE } from '../constants.js';
|
|
2
|
+
import { asVerbatim } from '../util/ast.js';
|
|
3
|
+
import { isString } from '../util/type-check.js';
|
|
4
|
+
import { ExprNode } from './node.js';
|
|
5
|
+
import { WindowNode } from './window.js';
|
|
6
|
+
|
|
7
|
+
export class AggregateNode extends ExprNode {
|
|
8
|
+
/**
|
|
9
|
+
* Instantiate an aggregate function node.
|
|
10
|
+
* @param {string} name The aggregate function name.
|
|
11
|
+
* @param {ExprNode[]} args The aggregate function arguments.
|
|
12
|
+
* @param {boolean} [distinct] The distinct flag.
|
|
13
|
+
* @param {ExprNode} [filter] Filter expression.
|
|
14
|
+
*/
|
|
15
|
+
constructor(name, args, distinct, filter) {
|
|
16
|
+
super(AGGREGATE);
|
|
17
|
+
/**
|
|
18
|
+
* The aggregate function name.
|
|
19
|
+
* @type {string}
|
|
20
|
+
* @readonly
|
|
21
|
+
*/
|
|
22
|
+
this.name = name;
|
|
23
|
+
/**
|
|
24
|
+
* The aggregate function arguments.
|
|
25
|
+
* @type {ExprNode[]}
|
|
26
|
+
* @readonly
|
|
27
|
+
*/
|
|
28
|
+
this.args = args;
|
|
29
|
+
/**
|
|
30
|
+
* The distinct flag.
|
|
31
|
+
* @type {boolean}
|
|
32
|
+
* @readonly
|
|
33
|
+
*/
|
|
34
|
+
this.isDistinct = distinct;
|
|
35
|
+
/**
|
|
36
|
+
* Filter criteria.
|
|
37
|
+
* @type {ExprNode}
|
|
38
|
+
* @readonly
|
|
39
|
+
*/
|
|
40
|
+
this.filter = filter;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Return a new derived aggregate over distinct values.
|
|
45
|
+
* @param {boolean} [isDistinct=true] The distinct flag.
|
|
46
|
+
* @returns {AggregateNode} A new aggregate node.
|
|
47
|
+
*/
|
|
48
|
+
distinct(isDistinct = true) {
|
|
49
|
+
return new AggregateNode(this.name, this.args, isDistinct, this.filter);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Return a new derived aggregate function that filters values.
|
|
54
|
+
* @param {ExprNode | string} filter The filter expression.
|
|
55
|
+
* @returns {AggregateNode} A new aggregate node.
|
|
56
|
+
*/
|
|
57
|
+
where(filter) {
|
|
58
|
+
if (isString(filter)) filter = asVerbatim(filter);
|
|
59
|
+
return new AggregateNode(this.name, this.args, this.isDistinct, filter);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Return a new window function over this aggregate.
|
|
64
|
+
* @returns {WindowNode} A new window node.
|
|
65
|
+
*/
|
|
66
|
+
window() {
|
|
67
|
+
return new WindowNode(this);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Return a new window function over this aggregate with the given partitions.
|
|
72
|
+
* @param {...import('../types.js').ExprVarArgs} expr The partition by criteria.
|
|
73
|
+
* @returns {WindowNode} A new window node.
|
|
74
|
+
*/
|
|
75
|
+
partitionby(...expr) {
|
|
76
|
+
return this.window().partitionby(...expr);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Return a new window function over this aggregate with the given ordering.
|
|
81
|
+
* @param {...import('../types.js').ExprVarArgs} expr The order by criteria.
|
|
82
|
+
* @returns {WindowNode} A new window node.
|
|
83
|
+
*/
|
|
84
|
+
orderby(...expr) {
|
|
85
|
+
return this.window().orderby(...expr);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Generate a SQL query string for this node.
|
|
90
|
+
* @returns {string}
|
|
91
|
+
*/
|
|
92
|
+
toString() {
|
|
93
|
+
const { name, args, isDistinct, filter } = this;
|
|
94
|
+
const dist = isDistinct ? 'DISTINCT ' : '';
|
|
95
|
+
const arg = args?.length ? args.join(', ') : '*';
|
|
96
|
+
const filt = filter ? ` FILTER (WHERE ${filter})` : '';
|
|
97
|
+
return `${name}(${dist}${arg})${filt}`;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* An array of known aggregate function names.
|
|
103
|
+
* From https://duckdb.org/docs/sql/functions/aggregates.html.
|
|
104
|
+
*/
|
|
105
|
+
export const aggregateNames = [
|
|
106
|
+
'any_value',
|
|
107
|
+
'approx_count_distinct',
|
|
108
|
+
'approx_quantile',
|
|
109
|
+
'arbitrary',
|
|
110
|
+
'arg_max',
|
|
111
|
+
'arg_max_null',
|
|
112
|
+
'arg_min',
|
|
113
|
+
'arg_min_null',
|
|
114
|
+
'array_agg',
|
|
115
|
+
'avg',
|
|
116
|
+
'bit_and',
|
|
117
|
+
'bit_or',
|
|
118
|
+
'bit_xor',
|
|
119
|
+
'bitstring_agg',
|
|
120
|
+
'bool_and',
|
|
121
|
+
'bool_or',
|
|
122
|
+
'corr',
|
|
123
|
+
'count',
|
|
124
|
+
'covar_pop',
|
|
125
|
+
'covar_samp',
|
|
126
|
+
'entropy',
|
|
127
|
+
'favg',
|
|
128
|
+
'first',
|
|
129
|
+
'fsum',
|
|
130
|
+
'geomean',
|
|
131
|
+
'kurtosis_pop',
|
|
132
|
+
'kurtosis',
|
|
133
|
+
'last',
|
|
134
|
+
'mad',
|
|
135
|
+
'max',
|
|
136
|
+
'max_by',
|
|
137
|
+
'median',
|
|
138
|
+
'min',
|
|
139
|
+
'min_by',
|
|
140
|
+
'mode',
|
|
141
|
+
'product',
|
|
142
|
+
'quantile',
|
|
143
|
+
'quantile_cont',
|
|
144
|
+
'quantile_disc',
|
|
145
|
+
'regr_avgx',
|
|
146
|
+
'regr_avgy',
|
|
147
|
+
'regr_count',
|
|
148
|
+
'regr_intercept',
|
|
149
|
+
'regr_r2',
|
|
150
|
+
'regr_sxx',
|
|
151
|
+
'regr_sxy',
|
|
152
|
+
'regr_syy',
|
|
153
|
+
'regr_slope',
|
|
154
|
+
'reservoir_quantile',
|
|
155
|
+
'skewness',
|
|
156
|
+
'stddev',
|
|
157
|
+
'stddev_pop',
|
|
158
|
+
'stddev_samp',
|
|
159
|
+
'string_agg',
|
|
160
|
+
'sum',
|
|
161
|
+
'variance',
|
|
162
|
+
'var_pop',
|
|
163
|
+
'var_samp'
|
|
164
|
+
];
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { BETWEEN_OPERATOR, NOT_BETWEEN_OPERATOR } from '../constants.js';
|
|
2
|
+
import { ExprNode } from './node.js';
|
|
3
|
+
|
|
4
|
+
class AbstractBetweenOpNode extends ExprNode {
|
|
5
|
+
/**
|
|
6
|
+
* Instantiate an abstract between operator node.
|
|
7
|
+
* @param {string} type The node type.
|
|
8
|
+
* @param {ExprNode} expr The input expression.
|
|
9
|
+
* @param {[ExprNode, ExprNode]} extent The range extent.
|
|
10
|
+
*/
|
|
11
|
+
constructor(type, expr, extent) {
|
|
12
|
+
super(type);
|
|
13
|
+
/**
|
|
14
|
+
* The input expression.
|
|
15
|
+
* @type {ExprNode}
|
|
16
|
+
* @readonly
|
|
17
|
+
*/
|
|
18
|
+
this.expr = expr;
|
|
19
|
+
/**
|
|
20
|
+
* The range extent.
|
|
21
|
+
* @type {[ExprNode, ExprNode]}
|
|
22
|
+
* @readonly
|
|
23
|
+
*/
|
|
24
|
+
this.extent = extent;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Generate a SQL query string for this node.
|
|
29
|
+
* @returns {string}
|
|
30
|
+
*/
|
|
31
|
+
toSQL(op) {
|
|
32
|
+
const { extent: r, expr } = this;
|
|
33
|
+
return r ? `(${expr} ${op} ${r[0]} AND ${r[1]})` : '';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export class BetweenOpNode extends AbstractBetweenOpNode {
|
|
38
|
+
/**
|
|
39
|
+
* Instantiate a between operator node.
|
|
40
|
+
* @param {ExprNode} expr The input expression.
|
|
41
|
+
* @param {[ExprNode, ExprNode]} extent
|
|
42
|
+
* The range extent.
|
|
43
|
+
*/
|
|
44
|
+
constructor(expr, extent) {
|
|
45
|
+
super(BETWEEN_OPERATOR, expr, extent);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Generate a SQL query string for this node.
|
|
50
|
+
* @returns {string}
|
|
51
|
+
*/
|
|
52
|
+
toString() {
|
|
53
|
+
return super.toSQL('BETWEEN');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class NotBetweenOpNode extends AbstractBetweenOpNode {
|
|
58
|
+
/**
|
|
59
|
+
* Instantiate a not between operator node.
|
|
60
|
+
* @param {ExprNode} expr The input expression.
|
|
61
|
+
* @param {[ExprNode, ExprNode]} extent
|
|
62
|
+
* The range extent.
|
|
63
|
+
*/
|
|
64
|
+
constructor(expr, extent) {
|
|
65
|
+
super(NOT_BETWEEN_OPERATOR, expr, extent);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Generate a SQL query string for this node.
|
|
70
|
+
* @returns {string}
|
|
71
|
+
*/
|
|
72
|
+
toString() {
|
|
73
|
+
return super.toSQL('NOT BETWEEN');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { BINARY_OPERATOR } from '../constants.js';
|
|
2
|
+
import { ExprNode } from './node.js';
|
|
3
|
+
|
|
4
|
+
export class BinaryOpNode extends ExprNode {
|
|
5
|
+
/**
|
|
6
|
+
* Instantiate a binary operator node.
|
|
7
|
+
* @param {string} op The operator type.
|
|
8
|
+
* @param {ExprNode} left The left input expression.
|
|
9
|
+
* @param {ExprNode} right The right input expression.
|
|
10
|
+
*/
|
|
11
|
+
constructor(op, left, right) {
|
|
12
|
+
super(BINARY_OPERATOR);
|
|
13
|
+
/**
|
|
14
|
+
* The operator type.
|
|
15
|
+
* @type {string}
|
|
16
|
+
* @readonly
|
|
17
|
+
*/
|
|
18
|
+
this.op = op;
|
|
19
|
+
/**
|
|
20
|
+
* The left input expression.
|
|
21
|
+
* @type {ExprNode}
|
|
22
|
+
* @readonly
|
|
23
|
+
*/
|
|
24
|
+
this.left = left;
|
|
25
|
+
/**
|
|
26
|
+
* The right input expression.
|
|
27
|
+
* @type {ExprNode}
|
|
28
|
+
* @readonly
|
|
29
|
+
*/
|
|
30
|
+
this.right = right;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Generate a SQL query string for this node.
|
|
35
|
+
* @returns {string}
|
|
36
|
+
*/
|
|
37
|
+
toString() {
|
|
38
|
+
return `(${this.left} ${this.op} ${this.right})`;
|
|
39
|
+
}
|
|
40
|
+
}
|
package/src/ast/case.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { CASE, WHEN } from '../constants.js';
|
|
2
|
+
import { asNode } from '../util/ast.js';
|
|
3
|
+
import { ExprNode, SQLNode } from './node.js';
|
|
4
|
+
|
|
5
|
+
export class CaseNode extends ExprNode {
|
|
6
|
+
/**
|
|
7
|
+
* Instantiate a case node.
|
|
8
|
+
* @param {ExprNode} [expr] An optional base expression, that comes
|
|
9
|
+
* immediately after the CASE keyword. If specified, this case statement
|
|
10
|
+
* acts like a switch statement, with WHEN expressions as values to
|
|
11
|
+
* match against the switch value rather than boolean conditions.
|
|
12
|
+
* @param {WhenNode[]} [when] An array of WHEN/THEN expression nodes.
|
|
13
|
+
* @param {ExprNode} [elseExpr] An ELSE expression.
|
|
14
|
+
*/
|
|
15
|
+
constructor(expr = undefined, when = [], elseExpr = undefined) {
|
|
16
|
+
super(CASE);
|
|
17
|
+
/**
|
|
18
|
+
* The optional base expression.
|
|
19
|
+
* @type {ExprNode}
|
|
20
|
+
* @readonly
|
|
21
|
+
*/
|
|
22
|
+
this.expr = expr;
|
|
23
|
+
/**
|
|
24
|
+
* An array of WHEN/THEN expression nodes.
|
|
25
|
+
* @type {WhenNode[]}
|
|
26
|
+
* @readonly
|
|
27
|
+
*/
|
|
28
|
+
this._when = when;
|
|
29
|
+
/**
|
|
30
|
+
* An ELSE expression.
|
|
31
|
+
* @type {ExprNode}
|
|
32
|
+
* @readonly
|
|
33
|
+
*/
|
|
34
|
+
this._else = elseExpr;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Return a new case node with the given conditional added as
|
|
39
|
+
* the last WHEN / THEN pair.
|
|
40
|
+
* @param {import('../types.js').ExprValue} cond
|
|
41
|
+
* The WHEN condition expression.
|
|
42
|
+
* @param {import('../types.js').ExprValue} value
|
|
43
|
+
* The THEN value expression.
|
|
44
|
+
* @returns {CaseNode}
|
|
45
|
+
*/
|
|
46
|
+
when(cond, value) {
|
|
47
|
+
return new CaseNode(
|
|
48
|
+
this.expr,
|
|
49
|
+
this._when.concat(new WhenNode(asNode(cond), asNode(value))),
|
|
50
|
+
this._else
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Return a new case node with the given ELSE expression.
|
|
56
|
+
* @param {import('../types.js').ExprValue} expr The ELSE expression.
|
|
57
|
+
* @returns {CaseNode}
|
|
58
|
+
*/
|
|
59
|
+
else(expr) {
|
|
60
|
+
return new CaseNode(this.expr, this._when, asNode(expr));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Generate a SQL query string for this node.
|
|
65
|
+
* @returns {string}
|
|
66
|
+
*/
|
|
67
|
+
toString() {
|
|
68
|
+
return 'CASE '
|
|
69
|
+
+ (this.expr ? `${this.expr} ` : '')
|
|
70
|
+
+ this._when.join(' ')
|
|
71
|
+
+ (this._else ? ` ELSE ${this._else}` : '')
|
|
72
|
+
+ ' END';
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export class WhenNode extends SQLNode {
|
|
77
|
+
/**
|
|
78
|
+
* Instantiate a case node.
|
|
79
|
+
* @param {ExprNode} when The WHEN condition expression.
|
|
80
|
+
* @param {ExprNode} then The THEN value expression.
|
|
81
|
+
*/
|
|
82
|
+
constructor(when, then) {
|
|
83
|
+
super(WHEN);
|
|
84
|
+
/**
|
|
85
|
+
* The condition expression.
|
|
86
|
+
* @type {ExprNode}
|
|
87
|
+
* @readonly
|
|
88
|
+
*/
|
|
89
|
+
this.when = when;
|
|
90
|
+
/**
|
|
91
|
+
* The value expression.
|
|
92
|
+
* @type {ExprNode}
|
|
93
|
+
* @readonly
|
|
94
|
+
*/
|
|
95
|
+
this.then = then;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Generate a SQL query string for this node.
|
|
100
|
+
* @returns {string}
|
|
101
|
+
*/
|
|
102
|
+
toString() {
|
|
103
|
+
return `WHEN ${this.when} THEN ${this.then}`;
|
|
104
|
+
}
|
|
105
|
+
}
|
package/src/ast/cast.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { CAST } from '../constants.js';
|
|
2
|
+
import { ExprNode } from './node.js';
|
|
3
|
+
|
|
4
|
+
export class CastNode extends ExprNode {
|
|
5
|
+
/**
|
|
6
|
+
* Instantiate a cast node.
|
|
7
|
+
* @param {ExprNode} expr The expression to type cast.
|
|
8
|
+
* @param {string} type The type to cast to.
|
|
9
|
+
*/
|
|
10
|
+
constructor(expr, type) {
|
|
11
|
+
super(CAST);
|
|
12
|
+
/**
|
|
13
|
+
* The expression to type cast.
|
|
14
|
+
* @type {ExprNode}
|
|
15
|
+
* @readonly
|
|
16
|
+
*/
|
|
17
|
+
this.expr = expr;
|
|
18
|
+
/**
|
|
19
|
+
* The type to cast to.
|
|
20
|
+
* @type {string}
|
|
21
|
+
* @readonly
|
|
22
|
+
*/
|
|
23
|
+
this.cast = type;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Generate a SQL query string for this node.
|
|
28
|
+
* @returns {string}
|
|
29
|
+
*/
|
|
30
|
+
toString() {
|
|
31
|
+
// TODO? could include check to see if parens are necessary
|
|
32
|
+
return `(${this.expr})::${this.cast}`;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { COLUMN_PARAM } from '../constants.js';
|
|
2
|
+
import { ColumnRefNode } from './column-ref.js';
|
|
3
|
+
|
|
4
|
+
export class ColumnParamNode extends ColumnRefNode {
|
|
5
|
+
/**
|
|
6
|
+
* Instantiate a column param node.
|
|
7
|
+
* @param {import('./param.js').ParamNode} param The column name as a
|
|
8
|
+
* parameter node.
|
|
9
|
+
* @param {import('./table-ref.js').TableRefNode} [table] The table
|
|
10
|
+
* reference.
|
|
11
|
+
*/
|
|
12
|
+
constructor(param, table) {
|
|
13
|
+
super(COLUMN_PARAM, table);
|
|
14
|
+
/**
|
|
15
|
+
* The column name as a parameter node.
|
|
16
|
+
* @type {import('./param.js').ParamNode}
|
|
17
|
+
* @readonly
|
|
18
|
+
*/
|
|
19
|
+
this.param = param;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Returns the column name.
|
|
24
|
+
* @returns {string}
|
|
25
|
+
*/
|
|
26
|
+
get column() {
|
|
27
|
+
return `${this.param.value}`;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { COLUMN_REF } from '../constants.js';
|
|
2
|
+
import { quoteIdentifier } from '../util/string.js';
|
|
3
|
+
import { ExprNode } from './node.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Check if a value is a column reference node.
|
|
7
|
+
* @param {*} value The value to check.
|
|
8
|
+
* @returns {value is ColumnRefNode}
|
|
9
|
+
*/
|
|
10
|
+
export function isColumnRef(value) {
|
|
11
|
+
return value instanceof ColumnRefNode;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class ColumnRefNode extends ExprNode {
|
|
15
|
+
/**
|
|
16
|
+
* Instantiate a column reference node.
|
|
17
|
+
* @param {import('./table-ref.js').TableRefNode} [table] The table reference.
|
|
18
|
+
*/
|
|
19
|
+
constructor(type, table) {
|
|
20
|
+
super(type);
|
|
21
|
+
/**
|
|
22
|
+
* The table reference.
|
|
23
|
+
* @type {import('./table-ref.js').TableRefNode}
|
|
24
|
+
* @readonly
|
|
25
|
+
*/
|
|
26
|
+
this.table = table;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Returns the column name.
|
|
31
|
+
* @returns {string}
|
|
32
|
+
*/
|
|
33
|
+
get column() {
|
|
34
|
+
return null; // subclasses to override
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Generate a SQL query string for this node.
|
|
39
|
+
* @returns {string}
|
|
40
|
+
*/
|
|
41
|
+
toString() {
|
|
42
|
+
const { column, table } = this;
|
|
43
|
+
const tref = `${table ?? ''}`;
|
|
44
|
+
const id = column === '*' ? '*' : quoteIdentifier(column);
|
|
45
|
+
return (tref ? (tref + '.') : '') + id;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export class ColumnNameRefNode extends ColumnRefNode {
|
|
50
|
+
/**
|
|
51
|
+
* Instantiate a column reference node.
|
|
52
|
+
* @param {string} name The column name.
|
|
53
|
+
* @param {import('./table-ref.js').TableRefNode} [table] The table reference.
|
|
54
|
+
*/
|
|
55
|
+
constructor(name, table) {
|
|
56
|
+
super(COLUMN_REF, table);
|
|
57
|
+
/**
|
|
58
|
+
* The column name.
|
|
59
|
+
* @type {string}
|
|
60
|
+
* @readonly
|
|
61
|
+
*/
|
|
62
|
+
this.name = name;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Returns the column name.
|
|
67
|
+
* @returns {string}
|
|
68
|
+
*/
|
|
69
|
+
get column() {
|
|
70
|
+
return this.name;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { FRAGMENT } from '../constants.js';
|
|
2
|
+
import { ExprNode } from './node.js';
|
|
3
|
+
|
|
4
|
+
export class FragmentNode extends ExprNode {
|
|
5
|
+
/**
|
|
6
|
+
* Instantiate a fragment node with arbitrary content.
|
|
7
|
+
* @param {ExprNode[]} spans The consecutive parts making up the fragment.
|
|
8
|
+
*/
|
|
9
|
+
constructor(spans) {
|
|
10
|
+
super(FRAGMENT);
|
|
11
|
+
/**
|
|
12
|
+
* The consecutive parts making up the fragment.
|
|
13
|
+
* @type {ExprNode[]}
|
|
14
|
+
* @readonly
|
|
15
|
+
*/
|
|
16
|
+
this.spans = spans;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Generate a SQL query string for this node.
|
|
21
|
+
* @returns {string}
|
|
22
|
+
*/
|
|
23
|
+
toString() {
|
|
24
|
+
return this.spans.join('');
|
|
25
|
+
}
|
|
26
|
+
}
|