@uwdata/mosaic-sql 0.10.0 → 0.12.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/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
package/dist/mosaic-sql.js
CHANGED
|
@@ -1,74 +1,80 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
var
|
|
1
|
+
// src/constants.js
|
|
2
|
+
var COLUMN_REF = "COLUMN_REF";
|
|
3
|
+
var COLUMN_PARAM = "COLUMN_PARAM";
|
|
4
|
+
var TABLE_REF = "TABLE_REF";
|
|
5
|
+
var LITERAL = "LITERAL";
|
|
6
|
+
var INTERVAL = "INTERVAL";
|
|
7
|
+
var ORDER_BY = "ORDER_BY";
|
|
8
|
+
var CAST = "CAST";
|
|
9
|
+
var CASE = "CASE";
|
|
10
|
+
var WHEN = "WHEN";
|
|
11
|
+
var UNARY_OPERATOR = "UNARY";
|
|
12
|
+
var UNARY_POSTFIX_OPERATOR = "UNARY_POSTFIX";
|
|
13
|
+
var BINARY_OPERATOR = "BINARY";
|
|
14
|
+
var BETWEEN_OPERATOR = "BETWEEN";
|
|
15
|
+
var NOT_BETWEEN_OPERATOR = "NOT_BETWEEN";
|
|
16
|
+
var LOGICAL_OPERATOR = "LOGICAL_OPERATOR";
|
|
17
|
+
var IN_OPERATOR = "IN";
|
|
18
|
+
var FUNCTION = "FUNCTION";
|
|
19
|
+
var AGGREGATE = "AGGREGATE";
|
|
20
|
+
var WINDOW = "WINDOW";
|
|
21
|
+
var WINDOW_DEF = "WINDOW_DEF";
|
|
22
|
+
var WINDOW_FRAME = "WINDOW_FRAME";
|
|
23
|
+
var EXPRESSION = "EXPRESSION";
|
|
24
|
+
var FRAGMENT = "FRAGMENT";
|
|
25
|
+
var VERBATIM = "VERBATIM";
|
|
26
|
+
var PARAM = "PARAM";
|
|
27
|
+
var WITH_CLAUSE = "WITH_CLAUSE";
|
|
28
|
+
var SELECT_CLAUSE = "SELECT_CLAUSE";
|
|
29
|
+
var FROM_CLAUSE = "FROM_CLAUSE";
|
|
30
|
+
var SAMPLE_CLAUSE = "SAMPLE_CLAUSE";
|
|
31
|
+
var WINDOW_CLAUSE = "WINDOW_CLAUSE";
|
|
32
|
+
var SELECT_QUERY = "SELECT_QUERY";
|
|
33
|
+
var DESCRIBE_QUERY = "DESCRIBE_QUERY";
|
|
34
|
+
var SET_OPERATION = "SET_OPERATION";
|
|
35
|
+
|
|
36
|
+
// src/ast/node.js
|
|
37
|
+
function isNode(value) {
|
|
38
|
+
return value instanceof SQLNode;
|
|
39
|
+
}
|
|
40
|
+
var SQLNode = class {
|
|
3
41
|
/**
|
|
4
|
-
*
|
|
5
|
-
* @param {string
|
|
6
|
-
* @param {string|null} [column] The column name.
|
|
42
|
+
* Instantiate a SQL AST node.
|
|
43
|
+
* @param {string} type The SQL AST node type.
|
|
7
44
|
*/
|
|
8
|
-
constructor(
|
|
9
|
-
|
|
10
|
-
if (column2) this.column = column2;
|
|
45
|
+
constructor(type) {
|
|
46
|
+
this.type = type;
|
|
11
47
|
}
|
|
48
|
+
};
|
|
49
|
+
var ExprNode = class extends SQLNode {
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// src/ast/literal.js
|
|
53
|
+
var LiteralNode = class extends ExprNode {
|
|
12
54
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
55
|
+
* Instantiate an literal node.
|
|
56
|
+
* @param {*} value The literal value.
|
|
15
57
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
58
|
+
constructor(value) {
|
|
59
|
+
super(LITERAL);
|
|
60
|
+
this.value = value;
|
|
18
61
|
}
|
|
19
62
|
/**
|
|
20
|
-
* Generate a SQL string for this
|
|
21
|
-
* @returns {string}
|
|
63
|
+
* Generate a SQL query string for this node.
|
|
64
|
+
* @returns {string}
|
|
22
65
|
*/
|
|
23
66
|
toString() {
|
|
24
|
-
|
|
25
|
-
if (column2) {
|
|
26
|
-
const col = column2.startsWith("*") ? column2 : `"${column2}"`;
|
|
27
|
-
return `${table ? `${quoteTableName(table)}.` : ""}${col}`;
|
|
28
|
-
} else {
|
|
29
|
-
return table ? quoteTableName(table) : "NULL";
|
|
30
|
-
}
|
|
67
|
+
return literalToSQL(this.value);
|
|
31
68
|
}
|
|
32
69
|
};
|
|
33
|
-
function quoteTableName(table) {
|
|
34
|
-
const pieces = table.split(".");
|
|
35
|
-
return pieces.map((p) => `"${p}"`).join(".");
|
|
36
|
-
}
|
|
37
|
-
function isColumnRefFor(ref, name) {
|
|
38
|
-
return ref instanceof Ref && ref.column === name;
|
|
39
|
-
}
|
|
40
|
-
function asColumn(value) {
|
|
41
|
-
return typeof value === "string" ? column(value) : value;
|
|
42
|
-
}
|
|
43
|
-
function asRelation(value) {
|
|
44
|
-
return typeof value === "string" ? relation(value) : value;
|
|
45
|
-
}
|
|
46
|
-
function relation(name) {
|
|
47
|
-
return new Ref(name);
|
|
48
|
-
}
|
|
49
|
-
function column(table, column2 = null) {
|
|
50
|
-
if (arguments.length === 1) {
|
|
51
|
-
column2 = table;
|
|
52
|
-
table = null;
|
|
53
|
-
}
|
|
54
|
-
return new Ref(table, column2);
|
|
55
|
-
}
|
|
56
|
-
function all(table) {
|
|
57
|
-
return new Ref(table, "*");
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// src/to-sql.js
|
|
61
|
-
function toSQL(value) {
|
|
62
|
-
return typeof value === "string" ? `"${value}"` : literalToSQL(value);
|
|
63
|
-
}
|
|
64
70
|
function literalToSQL(value) {
|
|
65
71
|
switch (typeof value) {
|
|
66
|
-
case "
|
|
67
|
-
return value ?
|
|
72
|
+
case "number":
|
|
73
|
+
return Number.isFinite(value) ? `${value}` : "NULL";
|
|
68
74
|
case "string":
|
|
69
75
|
return `'${value.replace(`'`, `''`)}'`;
|
|
70
|
-
case "
|
|
71
|
-
return
|
|
76
|
+
case "boolean":
|
|
77
|
+
return value ? "TRUE" : "FALSE";
|
|
72
78
|
default:
|
|
73
79
|
if (value == null) {
|
|
74
80
|
return "NULL";
|
|
@@ -78,1158 +84,2053 @@ function literalToSQL(value) {
|
|
|
78
84
|
const y2 = value.getUTCFullYear();
|
|
79
85
|
const m = value.getUTCMonth();
|
|
80
86
|
const d = value.getUTCDate();
|
|
81
|
-
return ts === Date.UTC(y2, m, d) ? `
|
|
87
|
+
return ts === Date.UTC(y2, m, d) ? `DATE '${y2}-${m + 1}-${d}'` : `epoch_ms(${ts})`;
|
|
82
88
|
} else if (value instanceof RegExp) {
|
|
83
89
|
return `'${value.source}'`;
|
|
84
90
|
} else {
|
|
85
|
-
return
|
|
91
|
+
return `${value}`;
|
|
86
92
|
}
|
|
87
93
|
}
|
|
88
94
|
}
|
|
89
95
|
|
|
90
|
-
// src/
|
|
91
|
-
var
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
* @param {string[]} [columns=[]] The column dependencies
|
|
100
|
-
* @param {object} [props] Additional properties for this expression.
|
|
101
|
-
*/
|
|
102
|
-
constructor(parts, columns, props) {
|
|
103
|
-
this._expr = Array.isArray(parts) ? parts : [parts];
|
|
104
|
-
this._deps = columns || [];
|
|
105
|
-
this.annotate(props);
|
|
106
|
-
const params = this._expr.filter((part) => isParamLike(part));
|
|
107
|
-
if (params.length > 0) {
|
|
108
|
-
this._params = Array.from(new Set(params));
|
|
109
|
-
this._params.forEach((param) => {
|
|
110
|
-
param.addEventListener("value", () => update(this, this.map?.get("value")));
|
|
111
|
-
});
|
|
112
|
-
} else {
|
|
113
|
-
this.addEventListener = void 0;
|
|
114
|
-
}
|
|
96
|
+
// src/ast/param.js
|
|
97
|
+
var ParamNode = class extends ExprNode {
|
|
98
|
+
/**
|
|
99
|
+
* Instantiate a param node with a dynamic parameter.
|
|
100
|
+
* @param {import('../types.js').ParamLike} param The dynamic parameter.
|
|
101
|
+
*/
|
|
102
|
+
constructor(param) {
|
|
103
|
+
super(PARAM);
|
|
104
|
+
this.param = param;
|
|
115
105
|
}
|
|
116
106
|
/**
|
|
117
|
-
*
|
|
118
|
-
*
|
|
107
|
+
* Returns the current parameter value.
|
|
108
|
+
* @returns {*}
|
|
119
109
|
*/
|
|
120
110
|
get value() {
|
|
121
|
-
return this;
|
|
111
|
+
return this.param.value;
|
|
122
112
|
}
|
|
123
113
|
/**
|
|
124
|
-
*
|
|
125
|
-
* @returns {string
|
|
126
|
-
*/
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if (_params) {
|
|
130
|
-
const pset = new Set(_params.flatMap((p) => {
|
|
131
|
-
const cols = p.value?.columns;
|
|
132
|
-
return Array.isArray(cols) ? cols : [];
|
|
133
|
-
}));
|
|
134
|
-
if (pset.size) {
|
|
135
|
-
const set = new Set(_deps);
|
|
136
|
-
pset.forEach((col) => set.add(col));
|
|
137
|
-
return Array.from(set);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
return _deps;
|
|
114
|
+
* Generate a SQL query string for this node.
|
|
115
|
+
* @returns {string}
|
|
116
|
+
*/
|
|
117
|
+
toString() {
|
|
118
|
+
return literalToSQL(this.value);
|
|
141
119
|
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// src/util/string.js
|
|
123
|
+
function parseIdentifier(id) {
|
|
124
|
+
return id.split(".");
|
|
125
|
+
}
|
|
126
|
+
function quoteIdentifier(value) {
|
|
127
|
+
return `"${value}"`;
|
|
128
|
+
}
|
|
129
|
+
function unquote(s) {
|
|
130
|
+
return s && isDoubleQuoted(s) ? s.slice(1, -1) : s;
|
|
131
|
+
}
|
|
132
|
+
function isDoubleQuoted(s) {
|
|
133
|
+
return s[0] === '"' && s[s.length - 1] === '"';
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/ast/table-ref.js
|
|
137
|
+
function isTableRef(value) {
|
|
138
|
+
return value instanceof TableRefNode;
|
|
139
|
+
}
|
|
140
|
+
var TableRefNode = class extends ExprNode {
|
|
142
141
|
/**
|
|
143
|
-
*
|
|
144
|
-
* @
|
|
142
|
+
* Instantiate a table reference node.
|
|
143
|
+
* @param {string | string[]} table The table name.
|
|
145
144
|
*/
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
constructor(table) {
|
|
146
|
+
super(TABLE_REF);
|
|
147
|
+
this.table = [table].flat();
|
|
148
148
|
}
|
|
149
149
|
/**
|
|
150
|
-
*
|
|
151
|
-
* @
|
|
152
|
-
* @returns This SQL expression.
|
|
150
|
+
* The table name without database or schema namespaces.
|
|
151
|
+
* @returns {string}
|
|
153
152
|
*/
|
|
154
|
-
|
|
155
|
-
return
|
|
153
|
+
get name() {
|
|
154
|
+
return this.table[this.table.length - 1];
|
|
156
155
|
}
|
|
157
156
|
/**
|
|
158
|
-
* Generate a SQL
|
|
159
|
-
* @returns {string}
|
|
157
|
+
* Generate a SQL query string for this node.
|
|
158
|
+
* @returns {string}
|
|
160
159
|
*/
|
|
161
160
|
toString() {
|
|
162
|
-
return this.
|
|
161
|
+
return this.table.map((t) => quoteIdentifier(t)).join(".");
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// src/ast/function.js
|
|
166
|
+
var FunctionNode = class extends ExprNode {
|
|
167
|
+
/**
|
|
168
|
+
* Instantiate a function node.
|
|
169
|
+
* @param {string} name The function name.
|
|
170
|
+
* @param {ExprNode[]} [args=[]] The function arguments.
|
|
171
|
+
*/
|
|
172
|
+
constructor(name, args = []) {
|
|
173
|
+
super(FUNCTION);
|
|
174
|
+
this.name = name;
|
|
175
|
+
this.args = args;
|
|
163
176
|
}
|
|
164
177
|
/**
|
|
165
|
-
*
|
|
166
|
-
* @
|
|
167
|
-
* @param {(a: SQLExpression) => Promise?} callback The callback function to
|
|
168
|
-
* invoke upon updates. A callback may optionally return a Promise that
|
|
169
|
-
* upstream listeners may await before proceeding.
|
|
178
|
+
* Generate a SQL query string for this node.
|
|
179
|
+
* @returns {string}
|
|
170
180
|
*/
|
|
171
|
-
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
set.add(callback);
|
|
181
|
+
toString() {
|
|
182
|
+
const { name, args } = this;
|
|
183
|
+
return `${name}(${args.join(", ")})`;
|
|
175
184
|
}
|
|
176
185
|
};
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
186
|
+
|
|
187
|
+
// src/util/function.js
|
|
188
|
+
function fn(name, ...args) {
|
|
189
|
+
return new FunctionNode(name, argsList(args).map(asNode));
|
|
181
190
|
}
|
|
182
|
-
function
|
|
183
|
-
|
|
184
|
-
const cols = /* @__PURE__ */ new Set();
|
|
185
|
-
const n = exprs.length;
|
|
186
|
-
for (let i = 0, k = 0; i < n; ) {
|
|
187
|
-
const e = exprs[i];
|
|
188
|
-
if (isParamLike(e)) {
|
|
189
|
-
spans[++k] = e;
|
|
190
|
-
} else {
|
|
191
|
-
if (Array.isArray(e?.columns)) {
|
|
192
|
-
e.columns.forEach((col) => cols.add(col));
|
|
193
|
-
}
|
|
194
|
-
spans[k] += typeof e === "string" ? e : literalToSQL(e);
|
|
195
|
-
}
|
|
196
|
-
const s = strings[++i];
|
|
197
|
-
if (isParamLike(spans[k])) {
|
|
198
|
-
spans[++k] = s;
|
|
199
|
-
} else {
|
|
200
|
-
spans[k] += s;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
return { spans, cols: Array.from(cols) };
|
|
191
|
+
function aggFn(name, ...args) {
|
|
192
|
+
return new AggregateNode(name, argsList(args).map(asNode));
|
|
204
193
|
}
|
|
205
|
-
function
|
|
206
|
-
|
|
207
|
-
|
|
194
|
+
function winFn(name, ...args) {
|
|
195
|
+
return new WindowNode(
|
|
196
|
+
new WindowFunctionNode(name, argsList(args).map(asNode))
|
|
197
|
+
);
|
|
208
198
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
function desc(expr) {
|
|
212
|
-
const e = asColumn(expr);
|
|
213
|
-
return sql`${e} DESC NULLS LAST`.annotate({ label: e?.label, desc: true });
|
|
199
|
+
function exprList(list, cast2 = asNode) {
|
|
200
|
+
return list.flat().filter((x2) => x2 != null).map((x2) => cast2(x2));
|
|
214
201
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
// src/operators.js
|
|
223
|
-
function visit(callback) {
|
|
224
|
-
callback(this.op, this);
|
|
225
|
-
this.children?.forEach((v) => v.visit(callback));
|
|
226
|
-
}
|
|
227
|
-
function logical(op, clauses) {
|
|
228
|
-
const children = clauses.filter((x2) => x2 != null).map(asColumn);
|
|
229
|
-
const strings = children.map((c, i) => i ? ` ${op} ` : "");
|
|
230
|
-
if (children.length === 1) {
|
|
231
|
-
strings.push("");
|
|
232
|
-
} else if (children.length > 1) {
|
|
233
|
-
strings[0] = "(";
|
|
234
|
-
strings.push(")");
|
|
235
|
-
}
|
|
236
|
-
return sql(strings, ...children).annotate({ op, children, visit });
|
|
237
|
-
}
|
|
238
|
-
var and = (...clauses) => logical("AND", clauses.flat());
|
|
239
|
-
var or = (...clauses) => logical("OR", clauses.flat());
|
|
240
|
-
var unaryOp = (op) => (a) => sql`(${op} ${asColumn(a)})`.annotate({ op, a, visit });
|
|
241
|
-
var not = unaryOp("NOT");
|
|
242
|
-
var unaryPostOp = (op) => (a) => sql`(${asColumn(a)} ${op})`.annotate({ op, a, visit });
|
|
243
|
-
var isNull = unaryPostOp("IS NULL");
|
|
244
|
-
var isNotNull = unaryPostOp("IS NOT NULL");
|
|
245
|
-
var binaryOp = (op) => (a, b) => sql`(${asColumn(a)} ${op} ${asColumn(b)})`.annotate({ op, a, b, visit });
|
|
246
|
-
var eq = binaryOp("=");
|
|
247
|
-
var neq = binaryOp("<>");
|
|
248
|
-
var lt = binaryOp("<");
|
|
249
|
-
var gt = binaryOp(">");
|
|
250
|
-
var lte = binaryOp("<=");
|
|
251
|
-
var gte = binaryOp(">=");
|
|
252
|
-
var isDistinct = binaryOp("IS DISTINCT FROM");
|
|
253
|
-
var isNotDistinct = binaryOp("IS NOT DISTINCT FROM");
|
|
254
|
-
function rangeOp(op, a, range, exclusive) {
|
|
255
|
-
a = asColumn(a);
|
|
256
|
-
const prefix2 = op.startsWith("NOT ") ? "NOT " : "";
|
|
257
|
-
const expr = !range ? sql`` : exclusive ? sql`${prefix2}(${range[0]} <= ${a} AND ${a} < ${range[1]})` : sql`(${a} ${op} ${range[0]} AND ${range[1]})`;
|
|
258
|
-
return expr.annotate({ op, visit, field: a, range });
|
|
259
|
-
}
|
|
260
|
-
var isBetween = (a, range, exclusive) => rangeOp("BETWEEN", a, range, exclusive);
|
|
261
|
-
var isNotBetween = (a, range, exclusive) => rangeOp("NOT BETWEEN", a, range, exclusive);
|
|
262
|
-
|
|
263
|
-
// src/repeat.js
|
|
264
|
-
function repeat(length2, str) {
|
|
265
|
-
return Array.from({ length: length2 }, () => str);
|
|
202
|
+
function argsList(list) {
|
|
203
|
+
const n = list.length;
|
|
204
|
+
let i = n;
|
|
205
|
+
for (; i > 0 && list[i - 1] === void 0; --i) ;
|
|
206
|
+
return i < n ? list.slice(0, i) : list;
|
|
266
207
|
}
|
|
267
208
|
|
|
268
|
-
// src/
|
|
269
|
-
function
|
|
270
|
-
return
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
209
|
+
// src/util/type-check.js
|
|
210
|
+
function isString(value) {
|
|
211
|
+
return typeof value === "string";
|
|
212
|
+
}
|
|
213
|
+
function isArray(value) {
|
|
214
|
+
return Array.isArray(value);
|
|
215
|
+
}
|
|
216
|
+
function isParamLike(value) {
|
|
217
|
+
return value && typeof value.addEventListener === "function" && value.dynamic !== false && "value" in value;
|
|
276
218
|
}
|
|
277
|
-
var regexp_matches = functionCall("REGEXP_MATCHES");
|
|
278
|
-
var contains = functionCall("CONTAINS");
|
|
279
|
-
var prefix = functionCall("PREFIX");
|
|
280
|
-
var suffix = functionCall("SUFFIX");
|
|
281
|
-
var lower = functionCall("LOWER");
|
|
282
|
-
var upper = functionCall("UPPER");
|
|
283
|
-
var length = functionCall("LENGTH");
|
|
284
|
-
var isNaN = functionCall("ISNAN");
|
|
285
|
-
var isFinite = functionCall("ISFINITE");
|
|
286
|
-
var isInfinite = functionCall("ISINF");
|
|
287
219
|
|
|
288
|
-
// src/
|
|
289
|
-
var
|
|
290
|
-
/**
|
|
291
|
-
*
|
|
292
|
-
* @param {string}
|
|
293
|
-
* @param {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
* @param {*} [order] Sorting (order by) expressions.
|
|
298
|
-
* @param {*} [frame] The window frame definition.
|
|
299
|
-
*/
|
|
300
|
-
constructor(op, func, type, name, group = "", order = "", frame = "") {
|
|
301
|
-
let expr;
|
|
302
|
-
const noWindowParams = !(group || order || frame);
|
|
303
|
-
if (name && noWindowParams) {
|
|
304
|
-
expr = name ? sql`${func} OVER "${name}"` : sql`${func} OVER ()`;
|
|
305
|
-
} else {
|
|
306
|
-
const s1 = group && order ? " " : "";
|
|
307
|
-
const s2 = (group || order) && frame ? " " : "";
|
|
308
|
-
expr = sql`${func} OVER (${name ? `"${name}" ` : ""}${group}${s1}${order}${s2}${frame})`;
|
|
309
|
-
}
|
|
310
|
-
if (type) {
|
|
311
|
-
expr = sql`(${expr})::${type}`;
|
|
312
|
-
}
|
|
313
|
-
const { _expr, _deps } = expr;
|
|
314
|
-
super(_expr, _deps);
|
|
315
|
-
this.window = op;
|
|
316
|
-
this.func = func;
|
|
317
|
-
this.type = type;
|
|
220
|
+
// src/ast/window.js
|
|
221
|
+
var WindowClauseNode = class extends SQLNode {
|
|
222
|
+
/**
|
|
223
|
+
* Instantiate a window clause node.
|
|
224
|
+
* @param {string} name The window name.
|
|
225
|
+
* @param {WindowDefNode} def The window definition.
|
|
226
|
+
*/
|
|
227
|
+
constructor(name, def) {
|
|
228
|
+
super(WINDOW_CLAUSE);
|
|
318
229
|
this.name = name;
|
|
319
|
-
this.
|
|
320
|
-
this.order = order;
|
|
321
|
-
this.frame = frame;
|
|
230
|
+
this.def = def;
|
|
322
231
|
}
|
|
323
|
-
|
|
324
|
-
return this.
|
|
232
|
+
toString() {
|
|
233
|
+
return `${quoteIdentifier(this.name)} AS ${this.def}`;
|
|
325
234
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
235
|
+
};
|
|
236
|
+
var WindowNode = class _WindowNode extends ExprNode {
|
|
237
|
+
/**
|
|
238
|
+
* Instantiate a window node.
|
|
239
|
+
* @param {WindowFunctionNode | AggregateNode} func The window function call.
|
|
240
|
+
* @param {WindowDefNode} [over] The window definition or name.
|
|
241
|
+
*/
|
|
242
|
+
constructor(func, over2 = new WindowDefNode()) {
|
|
243
|
+
super(WINDOW);
|
|
244
|
+
this.func = func;
|
|
245
|
+
this.def = over2;
|
|
329
246
|
}
|
|
330
247
|
/**
|
|
331
|
-
* Return an updated window
|
|
248
|
+
* Return an updated window over a named window definition.
|
|
332
249
|
* @param {string} name The window definition name.
|
|
333
|
-
* @returns {
|
|
250
|
+
* @returns {WindowNode} A new window node.
|
|
334
251
|
*/
|
|
335
252
|
over(name) {
|
|
336
|
-
|
|
337
|
-
return new _WindowFunction(op, func, type, name, group, order, frame);
|
|
253
|
+
return new _WindowNode(this.func, this.def.over(name));
|
|
338
254
|
}
|
|
339
255
|
/**
|
|
340
|
-
* Return an updated window
|
|
341
|
-
* @param {
|
|
342
|
-
* @returns {
|
|
256
|
+
* Return an updated window with the given partitions.
|
|
257
|
+
* @param {...import('../types.js').ExprVarArgs} expr The partition by criteria.
|
|
258
|
+
* @returns {WindowNode} A new window node.
|
|
343
259
|
*/
|
|
344
260
|
partitionby(...expr) {
|
|
345
|
-
|
|
346
|
-
const group = sql(
|
|
347
|
-
["PARTITION BY ", repeat(exprs.length - 1, ", "), ""],
|
|
348
|
-
...exprs
|
|
349
|
-
);
|
|
350
|
-
const { window: op, func, type, name, order, frame } = this;
|
|
351
|
-
return new _WindowFunction(op, func, type, name, group, order, frame);
|
|
261
|
+
return new _WindowNode(this.func, this.def.partitionby(...expr));
|
|
352
262
|
}
|
|
353
263
|
/**
|
|
354
|
-
* Return an updated window
|
|
355
|
-
* @param {
|
|
356
|
-
* @returns {
|
|
264
|
+
* Return an updated window with the given ordering.
|
|
265
|
+
* @param {...import('../types.js').ExprVarArgs} expr The order by criteria.
|
|
266
|
+
* @returns {WindowNode} A new window node.
|
|
357
267
|
*/
|
|
358
268
|
orderby(...expr) {
|
|
359
|
-
|
|
360
|
-
const order = sql(
|
|
361
|
-
["ORDER BY ", repeat(exprs.length - 1, ", "), ""],
|
|
362
|
-
...exprs
|
|
363
|
-
);
|
|
364
|
-
const { window: op, func, type, name, group, frame } = this;
|
|
365
|
-
return new _WindowFunction(op, func, type, name, group, order, frame);
|
|
269
|
+
return new _WindowNode(this.func, this.def.orderby(...expr));
|
|
366
270
|
}
|
|
367
271
|
/**
|
|
368
|
-
* Return an updated window
|
|
369
|
-
* @param {
|
|
370
|
-
* @returns {
|
|
272
|
+
* Return an updated window with the given rows frame.
|
|
273
|
+
* @param {FrameExtent} extent The row-based window frame extent.
|
|
274
|
+
* @returns {WindowNode} A new window node.
|
|
371
275
|
*/
|
|
372
|
-
rows(
|
|
373
|
-
|
|
374
|
-
const { window: op, func, type, name, group, order } = this;
|
|
375
|
-
return new _WindowFunction(op, func, type, name, group, order, frame);
|
|
276
|
+
rows(extent) {
|
|
277
|
+
return new _WindowNode(this.func, this.def.rows(extent));
|
|
376
278
|
}
|
|
377
279
|
/**
|
|
378
|
-
* Return an updated window
|
|
379
|
-
* @param {
|
|
380
|
-
* @returns {
|
|
280
|
+
* Return an updated window with the given range frame.
|
|
281
|
+
* @param {FrameExtent} extent The range-based window frame extent.
|
|
282
|
+
* @returns {WindowNode} A new window node.
|
|
381
283
|
*/
|
|
382
|
-
range(
|
|
383
|
-
|
|
384
|
-
const { window: op, func, type, name, group, order } = this;
|
|
385
|
-
return new _WindowFunction(op, func, type, name, group, order, frame);
|
|
386
|
-
}
|
|
387
|
-
};
|
|
388
|
-
function windowFrame(type, frame) {
|
|
389
|
-
if (isParamLike(frame)) {
|
|
390
|
-
const expr = sql`${frame}`;
|
|
391
|
-
expr.toString = () => `${type} ${frameToSQL(frame.value)}`;
|
|
392
|
-
return expr;
|
|
393
|
-
}
|
|
394
|
-
return `${type} ${frameToSQL(frame)}`;
|
|
395
|
-
}
|
|
396
|
-
function frameToSQL(frame) {
|
|
397
|
-
const [prev, next] = frame;
|
|
398
|
-
const a = prev === 0 ? "CURRENT ROW" : Number.isFinite(prev) ? `${Math.abs(prev)} PRECEDING` : "UNBOUNDED PRECEDING";
|
|
399
|
-
const b = next === 0 ? "CURRENT ROW" : Number.isFinite(next) ? `${Math.abs(next)} FOLLOWING` : "UNBOUNDED FOLLOWING";
|
|
400
|
-
return `BETWEEN ${a} AND ${b}`;
|
|
401
|
-
}
|
|
402
|
-
function winf(op, type) {
|
|
403
|
-
return (...values) => {
|
|
404
|
-
const func = functionCall(op)(...values);
|
|
405
|
-
return new WindowFunction(op, func, type);
|
|
406
|
-
};
|
|
407
|
-
}
|
|
408
|
-
var row_number = winf("ROW_NUMBER", "INTEGER");
|
|
409
|
-
var rank = winf("RANK", "INTEGER");
|
|
410
|
-
var dense_rank = winf("DENSE_RANK", "INTEGER");
|
|
411
|
-
var percent_rank = winf("PERCENT_RANK");
|
|
412
|
-
var cume_dist = winf("CUME_DIST");
|
|
413
|
-
var ntile = winf("NTILE");
|
|
414
|
-
var lag = winf("LAG");
|
|
415
|
-
var lead = winf("LEAD");
|
|
416
|
-
var first_value = winf("FIRST_VALUE");
|
|
417
|
-
var last_value = winf("LAST_VALUE");
|
|
418
|
-
var nth_value = winf("NTH_VALUE");
|
|
419
|
-
|
|
420
|
-
// src/aggregates.js
|
|
421
|
-
function agg(strings, ...exprs) {
|
|
422
|
-
return sql(strings, ...exprs).annotate({ aggregate: true });
|
|
423
|
-
}
|
|
424
|
-
var AggregateFunction = class _AggregateFunction extends SQLExpression {
|
|
425
|
-
/**
|
|
426
|
-
* Create a new AggregateFunction instance.
|
|
427
|
-
* @param {*} op The aggregate operation.
|
|
428
|
-
* @param {*} [args] The aggregate function arguments.
|
|
429
|
-
* @param {*} [type] The SQL data type to cast to.
|
|
430
|
-
* @param {boolean} [isDistinct] Flag indicating if this is a distinct value aggregate.
|
|
431
|
-
* @param {*} [filter] Filtering expression to apply prior to aggregation.
|
|
432
|
-
*/
|
|
433
|
-
constructor(op, args, type, isDistinct2, filter) {
|
|
434
|
-
args = (args || []).map(asColumn);
|
|
435
|
-
const { strings, exprs } = aggExpr(op, args, type, isDistinct2, filter);
|
|
436
|
-
const { spans, cols } = parseSQL(strings, exprs);
|
|
437
|
-
super(spans, cols);
|
|
438
|
-
this.aggregate = op;
|
|
439
|
-
this.args = args;
|
|
440
|
-
this.type = type;
|
|
441
|
-
this.isDistinct = isDistinct2;
|
|
442
|
-
this.filter = filter;
|
|
284
|
+
range(extent) {
|
|
285
|
+
return new _WindowNode(this.func, this.def.range(extent));
|
|
443
286
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
const tail = args.length ? `(${dist}${args.map(unquoted).join(", ")})` : "";
|
|
451
|
-
return `${op.toLowerCase()}${tail}`;
|
|
287
|
+
/**
|
|
288
|
+
* Generate a SQL query string for this node.
|
|
289
|
+
* @returns {string}
|
|
290
|
+
*/
|
|
291
|
+
toString() {
|
|
292
|
+
return `${this.func} OVER ${this.def}`;
|
|
452
293
|
}
|
|
294
|
+
};
|
|
295
|
+
var WindowFunctionNode = class extends FunctionNode {
|
|
453
296
|
/**
|
|
454
|
-
*
|
|
455
|
-
* @
|
|
297
|
+
* Instantiate a window function call node.
|
|
298
|
+
* @param {import('../types.js').WindowFunctionName} name The function name.
|
|
299
|
+
* @param {ExprNode[]} [args=[]] The function arguments.
|
|
456
300
|
*/
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
return new _AggregateFunction(op, args, type, true, filter);
|
|
301
|
+
constructor(name, args) {
|
|
302
|
+
super(name, args);
|
|
460
303
|
}
|
|
304
|
+
};
|
|
305
|
+
var WindowDefNode = class extends SQLNode {
|
|
461
306
|
/**
|
|
462
|
-
*
|
|
463
|
-
* @param {
|
|
464
|
-
* @
|
|
307
|
+
* Instantiate a window definition node.
|
|
308
|
+
* @param {string} [name] The base window definition name.
|
|
309
|
+
* @param {ExprNode[]} [partition] The partition by criteria.
|
|
310
|
+
* @param {ExprNode[]} [order] The order by criteria.
|
|
311
|
+
* @param {WindowFrameNode} [frame] The window frame definition.
|
|
465
312
|
*/
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
313
|
+
constructor(name, partition, order, frame) {
|
|
314
|
+
super(WINDOW_DEF);
|
|
315
|
+
this.name = name;
|
|
316
|
+
this.partition = partition;
|
|
317
|
+
this.order = order;
|
|
318
|
+
this.frame = frame;
|
|
469
319
|
}
|
|
470
320
|
/**
|
|
471
|
-
* Return
|
|
472
|
-
* @
|
|
321
|
+
* Return an updated window definition with the given base name.
|
|
322
|
+
* @param {string} name The base window definition name.
|
|
323
|
+
* @returns {WindowDefNode} A new window definition node.
|
|
473
324
|
*/
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
const func = new _AggregateFunction(op, args, null, isDistinct2);
|
|
477
|
-
return new WindowFunction(op, func, type);
|
|
325
|
+
over(name) {
|
|
326
|
+
return deriveDef(this, { name });
|
|
478
327
|
}
|
|
479
328
|
/**
|
|
480
|
-
* Return
|
|
481
|
-
* @param {
|
|
482
|
-
* @returns {
|
|
329
|
+
* Return an updated window definition with the given partitions.
|
|
330
|
+
* @param {...import('../types.js').ExprVarArgs} expr The partition by criteria.
|
|
331
|
+
* @returns {WindowDefNode} A new window definition node.
|
|
483
332
|
*/
|
|
484
333
|
partitionby(...expr) {
|
|
485
|
-
return this
|
|
334
|
+
return deriveDef(this, { partition: exprList(expr) });
|
|
486
335
|
}
|
|
487
336
|
/**
|
|
488
|
-
* Return
|
|
489
|
-
* @param {
|
|
490
|
-
* @returns {
|
|
337
|
+
* Return an updated window definition with the given ordering.
|
|
338
|
+
* @param {...import('../types.js').ExprVarArgs} expr The order by criteria.
|
|
339
|
+
* @returns {WindowDefNode} A new window definition node.
|
|
491
340
|
*/
|
|
492
341
|
orderby(...expr) {
|
|
493
|
-
return this
|
|
342
|
+
return deriveDef(this, { order: exprList(expr) });
|
|
494
343
|
}
|
|
495
344
|
/**
|
|
496
|
-
* Return
|
|
497
|
-
* @param {
|
|
498
|
-
* @returns {
|
|
345
|
+
* Return an updated window definition with the given rows frame.
|
|
346
|
+
* @param {FrameExtent} extent The row-based window frame extent.
|
|
347
|
+
* @returns {WindowDefNode} A new window definition node.
|
|
499
348
|
*/
|
|
500
|
-
rows(
|
|
501
|
-
return this
|
|
349
|
+
rows(extent) {
|
|
350
|
+
return deriveDef(this, { frame: new WindowFrameNode(extent) });
|
|
502
351
|
}
|
|
503
352
|
/**
|
|
504
|
-
* Return
|
|
505
|
-
* @param {
|
|
506
|
-
* @returns {
|
|
353
|
+
* Return an updated window definition with the given range frame.
|
|
354
|
+
* @param {FrameExtent} extent The range-based window frame extent.
|
|
355
|
+
* @returns {WindowDefNode} A new window definition node.
|
|
507
356
|
*/
|
|
508
|
-
range(
|
|
509
|
-
return this
|
|
510
|
-
}
|
|
511
|
-
};
|
|
512
|
-
function aggExpr(op, args, type, isDistinct2, filter) {
|
|
513
|
-
const close = `)${type ? `::${type}` : ""}`;
|
|
514
|
-
let strings = [`${op}(${isDistinct2 ? "DISTINCT " : ""}`];
|
|
515
|
-
let exprs = [];
|
|
516
|
-
if (args.length) {
|
|
517
|
-
strings = strings.concat([
|
|
518
|
-
...repeat(args.length - 1, ", "),
|
|
519
|
-
`${close}${filter ? " FILTER (WHERE " : ""}`,
|
|
520
|
-
...filter ? [")"] : []
|
|
521
|
-
]);
|
|
522
|
-
exprs = [...args, ...filter ? [filter] : []];
|
|
523
|
-
} else {
|
|
524
|
-
strings[0] += "*" + close;
|
|
525
|
-
}
|
|
526
|
-
return { exprs, strings };
|
|
527
|
-
}
|
|
528
|
-
function unquoted(value) {
|
|
529
|
-
const s = literalToSQL(value);
|
|
530
|
-
return s && s.startsWith('"') && s.endsWith('"') ? s.slice(1, -1) : s;
|
|
531
|
-
}
|
|
532
|
-
function aggf(op, type) {
|
|
533
|
-
return (...args) => new AggregateFunction(op, args, type);
|
|
534
|
-
}
|
|
535
|
-
var count = aggf("COUNT", "INTEGER");
|
|
536
|
-
var avg = aggf("AVG");
|
|
537
|
-
var mean = aggf("AVG");
|
|
538
|
-
var mad = aggf("MAD");
|
|
539
|
-
var max = aggf("MAX");
|
|
540
|
-
var min = aggf("MIN");
|
|
541
|
-
var sum = aggf("SUM", "DOUBLE");
|
|
542
|
-
var product = aggf("PRODUCT");
|
|
543
|
-
var median = aggf("MEDIAN");
|
|
544
|
-
var quantile = aggf("QUANTILE");
|
|
545
|
-
var mode = aggf("MODE");
|
|
546
|
-
var variance = aggf("VARIANCE");
|
|
547
|
-
var stddev = aggf("STDDEV");
|
|
548
|
-
var skewness = aggf("SKEWNESS");
|
|
549
|
-
var kurtosis = aggf("KURTOSIS");
|
|
550
|
-
var entropy = aggf("ENTROPY");
|
|
551
|
-
var varPop = aggf("VAR_POP");
|
|
552
|
-
var stddevPop = aggf("STDDEV_POP");
|
|
553
|
-
var corr = aggf("CORR");
|
|
554
|
-
var covariance = aggf("COVAR_SAMP");
|
|
555
|
-
var covarPop = aggf("COVAR_POP");
|
|
556
|
-
var regrIntercept = aggf("REGR_INTERCEPT");
|
|
557
|
-
var regrSlope = aggf("REGR_SLOPE");
|
|
558
|
-
var regrCount = aggf("REGR_COUNT");
|
|
559
|
-
var regrR2 = aggf("REGR_R2");
|
|
560
|
-
var regrSYY = aggf("REGR_SYY");
|
|
561
|
-
var regrSXX = aggf("REGR_SXX");
|
|
562
|
-
var regrSXY = aggf("REGR_SXY");
|
|
563
|
-
var regrAvgX = aggf("REGR_AVGX");
|
|
564
|
-
var regrAvgY = aggf("REGR_AVGY");
|
|
565
|
-
var first = aggf("FIRST");
|
|
566
|
-
var last = aggf("LAST");
|
|
567
|
-
var argmin = aggf("ARG_MIN");
|
|
568
|
-
var argmax = aggf("ARG_MAX");
|
|
569
|
-
var stringAgg = aggf("STRING_AGG");
|
|
570
|
-
var arrayAgg = aggf("ARRAY_AGG");
|
|
571
|
-
|
|
572
|
-
// src/cast.js
|
|
573
|
-
function cast(expr, type) {
|
|
574
|
-
const arg = asColumn(expr);
|
|
575
|
-
const e = sql`CAST(${arg} AS ${type})`;
|
|
576
|
-
Object.defineProperty(e, "label", {
|
|
577
|
-
enumerable: true,
|
|
578
|
-
get() {
|
|
579
|
-
return expr.label;
|
|
580
|
-
}
|
|
581
|
-
});
|
|
582
|
-
Object.defineProperty(e, "aggregate", {
|
|
583
|
-
enumerable: true,
|
|
584
|
-
get() {
|
|
585
|
-
return expr.aggregate || false;
|
|
586
|
-
}
|
|
587
|
-
});
|
|
588
|
-
return e;
|
|
589
|
-
}
|
|
590
|
-
var castDouble = (expr) => cast(expr, "DOUBLE");
|
|
591
|
-
var castInteger = (expr) => cast(expr, "INTEGER");
|
|
592
|
-
|
|
593
|
-
// src/datetime.js
|
|
594
|
-
var epoch_ms = (expr) => {
|
|
595
|
-
return sql`epoch_ms(${asColumn(expr)})`;
|
|
596
|
-
};
|
|
597
|
-
function dateBin(expr, interval, steps = 1) {
|
|
598
|
-
const i = `INTERVAL ${steps} ${interval}`;
|
|
599
|
-
const d = asColumn(expr);
|
|
600
|
-
return sql`TIME_BUCKET(${i}, ${d})`.annotate({ label: interval });
|
|
601
|
-
}
|
|
602
|
-
var dateMonth = (expr) => {
|
|
603
|
-
const d = asColumn(expr);
|
|
604
|
-
return sql`MAKE_DATE(2012, MONTH(${d}), 1)`.annotate({ label: "month" });
|
|
605
|
-
};
|
|
606
|
-
var dateMonthDay = (expr) => {
|
|
607
|
-
const d = asColumn(expr);
|
|
608
|
-
return sql`MAKE_DATE(2012, MONTH(${d}), DAY(${d}))`.annotate({ label: "date" });
|
|
609
|
-
};
|
|
610
|
-
var dateDay = (expr) => {
|
|
611
|
-
const d = asColumn(expr);
|
|
612
|
-
return sql`MAKE_DATE(2012, 1, DAY(${d}))`.annotate({ label: "date" });
|
|
613
|
-
};
|
|
614
|
-
|
|
615
|
-
// src/spatial.js
|
|
616
|
-
var geojson = functionCall("ST_AsGeoJSON");
|
|
617
|
-
var x = functionCall("ST_X");
|
|
618
|
-
var y = functionCall("ST_Y");
|
|
619
|
-
var centroid = functionCall("ST_CENTROID");
|
|
620
|
-
var centroidX = (geom) => x(centroid(geom));
|
|
621
|
-
var centroidY = (geom) => y(centroid(geom));
|
|
622
|
-
|
|
623
|
-
// src/Query.js
|
|
624
|
-
var Query = class _Query {
|
|
625
|
-
static select(...expr) {
|
|
626
|
-
return new _Query().select(...expr);
|
|
627
|
-
}
|
|
628
|
-
static from(...expr) {
|
|
629
|
-
return new _Query().from(...expr);
|
|
630
|
-
}
|
|
631
|
-
static with(...expr) {
|
|
632
|
-
return new _Query().with(...expr);
|
|
633
|
-
}
|
|
634
|
-
static union(...queries) {
|
|
635
|
-
return new SetOperation("UNION", queries.flat());
|
|
636
|
-
}
|
|
637
|
-
static unionAll(...queries) {
|
|
638
|
-
return new SetOperation("UNION ALL", queries.flat());
|
|
639
|
-
}
|
|
640
|
-
static intersect(...queries) {
|
|
641
|
-
return new SetOperation("INTERSECT", queries.flat());
|
|
642
|
-
}
|
|
643
|
-
static except(...queries) {
|
|
644
|
-
return new SetOperation("EXCEPT", queries.flat());
|
|
645
|
-
}
|
|
646
|
-
static describe(query) {
|
|
647
|
-
const q = query.clone();
|
|
648
|
-
const { clone, toString } = q;
|
|
649
|
-
return Object.assign(q, {
|
|
650
|
-
describe: true,
|
|
651
|
-
clone: () => _Query.describe(clone.call(q)),
|
|
652
|
-
toString: () => `DESCRIBE ${toString.call(q)}`
|
|
653
|
-
});
|
|
654
|
-
}
|
|
655
|
-
constructor() {
|
|
656
|
-
this.query = {
|
|
657
|
-
with: [],
|
|
658
|
-
select: [],
|
|
659
|
-
from: [],
|
|
660
|
-
where: [],
|
|
661
|
-
groupby: [],
|
|
662
|
-
having: [],
|
|
663
|
-
window: [],
|
|
664
|
-
qualify: [],
|
|
665
|
-
orderby: []
|
|
666
|
-
};
|
|
667
|
-
this.cteFor = null;
|
|
668
|
-
}
|
|
669
|
-
clone() {
|
|
670
|
-
const q = new _Query();
|
|
671
|
-
q.query = { ...this.query };
|
|
672
|
-
return q;
|
|
357
|
+
range(extent) {
|
|
358
|
+
return deriveDef(this, { frame: new WindowFrameNode(extent, true) });
|
|
673
359
|
}
|
|
674
360
|
/**
|
|
675
|
-
*
|
|
676
|
-
* @returns {
|
|
361
|
+
* Generate a SQL query string for this node.
|
|
362
|
+
* @returns {string}
|
|
677
363
|
*/
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
const list = [];
|
|
689
|
-
const add = (as, q) => {
|
|
690
|
-
const query2 = q.clone();
|
|
691
|
-
query2.cteFor = this;
|
|
692
|
-
list.push({ as, query: query2 });
|
|
693
|
-
};
|
|
694
|
-
expr.flat().forEach((e) => {
|
|
695
|
-
if (e == null) {
|
|
696
|
-
} else if (e.as && e.query) {
|
|
697
|
-
add(e.as, e.query);
|
|
698
|
-
} else {
|
|
699
|
-
for (const as in e) {
|
|
700
|
-
add(as, e[as]);
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
});
|
|
704
|
-
query.with = query.with.concat(list);
|
|
705
|
-
return this;
|
|
706
|
-
}
|
|
364
|
+
toString() {
|
|
365
|
+
const { name, partition, order, frame } = this;
|
|
366
|
+
const base = name && quoteIdentifier(name);
|
|
367
|
+
const def = [
|
|
368
|
+
base,
|
|
369
|
+
partition?.length && `PARTITION BY ${partition.join(", ")}`,
|
|
370
|
+
order?.length && `ORDER BY ${order.join(", ")}`,
|
|
371
|
+
frame
|
|
372
|
+
].filter((x2) => x2);
|
|
373
|
+
return base && def.length < 2 ? base : `(${def.join(" ")})`;
|
|
707
374
|
}
|
|
375
|
+
};
|
|
376
|
+
var WindowFrameNode = class extends SQLNode {
|
|
708
377
|
/**
|
|
709
|
-
*
|
|
710
|
-
* @
|
|
378
|
+
* Instantiate a window frame definition node.
|
|
379
|
+
* @param {FrameExtent} extent The frame extent as [preceding, following]
|
|
380
|
+
* row or interval offsets.
|
|
381
|
+
* @param {boolean} [range] The frame type: `true` for range, otherwise rows.
|
|
382
|
+
* @param {ExprNode} [exclude] The window exclusion criteria.
|
|
711
383
|
*/
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
select(...expr) {
|
|
718
|
-
const { query } = this;
|
|
719
|
-
if (expr.length === 0) {
|
|
720
|
-
return query.select;
|
|
721
|
-
} else {
|
|
722
|
-
const list = [];
|
|
723
|
-
for (const e of expr.flat()) {
|
|
724
|
-
if (e == null) {
|
|
725
|
-
} else if (typeof e === "string") {
|
|
726
|
-
list.push({ as: e, expr: asColumn(e) });
|
|
727
|
-
} else if (e instanceof Ref) {
|
|
728
|
-
list.push({ as: e.column, expr: e });
|
|
729
|
-
} else if (Array.isArray(e)) {
|
|
730
|
-
list.push({ as: e[0], expr: e[1] });
|
|
731
|
-
} else {
|
|
732
|
-
for (const as in e) {
|
|
733
|
-
list.push({ as: unquote(as), expr: asColumn(e[as]) });
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
const keys = new Set(list.map((x2) => x2.as));
|
|
738
|
-
query.select = query.select.filter((x2) => !keys.has(x2.as)).concat(list.filter((x2) => x2.expr));
|
|
739
|
-
return this;
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
$select(...expr) {
|
|
743
|
-
this.query.select = [];
|
|
744
|
-
return this.select(...expr);
|
|
745
|
-
}
|
|
746
|
-
distinct(value = true) {
|
|
747
|
-
this.query.distinct = !!value;
|
|
748
|
-
return this;
|
|
384
|
+
constructor(extent, range = false, exclude = void 0) {
|
|
385
|
+
super(WINDOW_FRAME);
|
|
386
|
+
this.extent = isParamLike(extent) ? new ParamNode(extent) : extent;
|
|
387
|
+
this.range = range;
|
|
388
|
+
this.exclude = exclude;
|
|
749
389
|
}
|
|
750
390
|
/**
|
|
751
|
-
*
|
|
752
|
-
* @returns {
|
|
391
|
+
* Generate a SQL query string for this node.
|
|
392
|
+
* @returns {string}
|
|
753
393
|
*/
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
if (expr.length === 0) {
|
|
762
|
-
return query.from;
|
|
763
|
-
} else {
|
|
764
|
-
const list = [];
|
|
765
|
-
expr.flat().forEach((e) => {
|
|
766
|
-
if (e == null) {
|
|
767
|
-
} else if (typeof e === "string") {
|
|
768
|
-
list.push({ as: e, from: asRelation(e) });
|
|
769
|
-
} else if (e instanceof Ref) {
|
|
770
|
-
list.push({ as: e.table, from: e });
|
|
771
|
-
} else if (isQuery(e) || isSQLExpression(e)) {
|
|
772
|
-
list.push({ from: e });
|
|
773
|
-
} else if (Array.isArray(e)) {
|
|
774
|
-
list.push({ as: unquote(e[0]), from: asRelation(e[1]) });
|
|
775
|
-
} else {
|
|
776
|
-
for (const as in e) {
|
|
777
|
-
list.push({ as: unquote(as), from: asRelation(e[as]) });
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
});
|
|
781
|
-
query.from = query.from.concat(list);
|
|
782
|
-
return this;
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
$from(...expr) {
|
|
786
|
-
this.query.from = [];
|
|
787
|
-
return this.from(...expr);
|
|
394
|
+
toString() {
|
|
395
|
+
const { range, exclude, extent } = this;
|
|
396
|
+
const type = range ? "RANGE" : "ROWS";
|
|
397
|
+
const [prev, next] = isNode(extent) ? extent.value : extent;
|
|
398
|
+
const a = frameValue(prev, "PRECEDING");
|
|
399
|
+
const b = frameValue(next, "FOLLOWING");
|
|
400
|
+
return `${type} BETWEEN ${a} AND ${b}${exclude ? ` ${exclude}` : ""}`;
|
|
788
401
|
}
|
|
402
|
+
};
|
|
403
|
+
function deriveDef(def, options) {
|
|
404
|
+
return new WindowDefNode(
|
|
405
|
+
options.name ?? def.name,
|
|
406
|
+
options.partition ?? def.partition,
|
|
407
|
+
options.order ?? def.order,
|
|
408
|
+
options.frame ?? def.frame
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
function frameValue(value, order) {
|
|
412
|
+
return value === 0 ? "CURRENT ROW" : Number.isFinite(value) ? `${Math.abs(value)} ${order}` : `UNBOUNDED ${order}`;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// src/ast/column-ref.js
|
|
416
|
+
function isColumnRef(value) {
|
|
417
|
+
return value instanceof ColumnRefNode;
|
|
418
|
+
}
|
|
419
|
+
var ColumnRefNode = class extends ExprNode {
|
|
789
420
|
/**
|
|
790
|
-
*
|
|
791
|
-
* @
|
|
421
|
+
* Instantiate a column reference node.
|
|
422
|
+
* @param {import('./table-ref.js').TableRefNode} [table] The table reference.
|
|
792
423
|
*/
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
* @param {string} [method] The sampling method to use.
|
|
797
|
-
* @returns {this}
|
|
798
|
-
*/
|
|
799
|
-
sample(value, method) {
|
|
800
|
-
const { query } = this;
|
|
801
|
-
if (arguments.length === 0) {
|
|
802
|
-
return query.sample;
|
|
803
|
-
} else {
|
|
804
|
-
let spec = value;
|
|
805
|
-
if (typeof value === "number") {
|
|
806
|
-
spec = value > 0 && value < 1 ? { perc: 100 * value, method } : { rows: Math.round(value), method };
|
|
807
|
-
}
|
|
808
|
-
query.sample = spec;
|
|
809
|
-
return this;
|
|
810
|
-
}
|
|
424
|
+
constructor(type, table) {
|
|
425
|
+
super(type);
|
|
426
|
+
this.table = table;
|
|
811
427
|
}
|
|
812
428
|
/**
|
|
813
|
-
*
|
|
814
|
-
* @returns {
|
|
429
|
+
* Returns the column name.
|
|
430
|
+
* @returns {string}
|
|
815
431
|
*/
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
* @param {...any} expr Expressions to add.
|
|
819
|
-
* @returns {this}
|
|
820
|
-
*/
|
|
821
|
-
where(...expr) {
|
|
822
|
-
const { query } = this;
|
|
823
|
-
if (expr.length === 0) {
|
|
824
|
-
return query.where;
|
|
825
|
-
} else {
|
|
826
|
-
query.where = query.where.concat(
|
|
827
|
-
expr.flat().filter((x2) => x2)
|
|
828
|
-
);
|
|
829
|
-
return this;
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
$where(...expr) {
|
|
833
|
-
this.query.where = [];
|
|
834
|
-
return this.where(...expr);
|
|
432
|
+
get column() {
|
|
433
|
+
return null;
|
|
835
434
|
}
|
|
836
435
|
/**
|
|
837
|
-
*
|
|
838
|
-
* @returns {
|
|
436
|
+
* Generate a SQL query string for this node.
|
|
437
|
+
* @returns {string}
|
|
839
438
|
*/
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
groupby(...expr) {
|
|
846
|
-
const { query } = this;
|
|
847
|
-
if (expr.length === 0) {
|
|
848
|
-
return query.groupby;
|
|
849
|
-
} else {
|
|
850
|
-
query.groupby = query.groupby.concat(
|
|
851
|
-
expr.flat().filter((x2) => x2).map(asColumn)
|
|
852
|
-
);
|
|
853
|
-
return this;
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
$groupby(...expr) {
|
|
857
|
-
this.query.groupby = [];
|
|
858
|
-
return this.groupby(...expr);
|
|
439
|
+
toString() {
|
|
440
|
+
const { column: column2, table } = this;
|
|
441
|
+
const tref = `${table ?? ""}`;
|
|
442
|
+
const id = column2 === "*" ? "*" : quoteIdentifier(column2);
|
|
443
|
+
return (tref ? tref + "." : "") + id;
|
|
859
444
|
}
|
|
445
|
+
};
|
|
446
|
+
var ColumnNameRefNode = class extends ColumnRefNode {
|
|
860
447
|
/**
|
|
861
|
-
*
|
|
862
|
-
* @
|
|
448
|
+
* Instantiate a column reference node.
|
|
449
|
+
* @param {string} name The column name.
|
|
450
|
+
* @param {import('./table-ref.js').TableRefNode} [table] The table reference.
|
|
863
451
|
*/
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
* @returns {this}
|
|
868
|
-
*/
|
|
869
|
-
having(...expr) {
|
|
870
|
-
const { query } = this;
|
|
871
|
-
if (expr.length === 0) {
|
|
872
|
-
return query.having;
|
|
873
|
-
} else {
|
|
874
|
-
query.having = query.having.concat(
|
|
875
|
-
expr.flat().filter((x2) => x2)
|
|
876
|
-
);
|
|
877
|
-
return this;
|
|
878
|
-
}
|
|
452
|
+
constructor(name, table) {
|
|
453
|
+
super(COLUMN_REF, table);
|
|
454
|
+
this.name = name;
|
|
879
455
|
}
|
|
880
456
|
/**
|
|
881
|
-
*
|
|
882
|
-
* @returns {
|
|
457
|
+
* Returns the column name.
|
|
458
|
+
* @returns {string}
|
|
883
459
|
*/
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
* @param {...any} expr Expressions to add.
|
|
887
|
-
* @returns {this}
|
|
888
|
-
*/
|
|
889
|
-
window(...expr) {
|
|
890
|
-
const { query } = this;
|
|
891
|
-
if (expr.length === 0) {
|
|
892
|
-
return query.window;
|
|
893
|
-
} else {
|
|
894
|
-
const list = [];
|
|
895
|
-
expr.flat().forEach((e) => {
|
|
896
|
-
if (e == null) {
|
|
897
|
-
} else {
|
|
898
|
-
for (const as in e) {
|
|
899
|
-
list.push({ as: unquote(as), expr: e[as] });
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
});
|
|
903
|
-
query.window = query.window.concat(list);
|
|
904
|
-
return this;
|
|
905
|
-
}
|
|
460
|
+
get column() {
|
|
461
|
+
return this.name;
|
|
906
462
|
}
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
// src/ast/column-param.js
|
|
466
|
+
var ColumnParamNode = class extends ColumnRefNode {
|
|
907
467
|
/**
|
|
908
|
-
*
|
|
909
|
-
* @
|
|
468
|
+
* Instantiate a column param node.
|
|
469
|
+
* @param {import('./param.js').ParamNode} param The column name as a
|
|
470
|
+
* parameter node.
|
|
471
|
+
* @param {import('./table-ref.js').TableRefNode} [table] The table
|
|
472
|
+
* reference.
|
|
910
473
|
*/
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
* @returns {this}
|
|
915
|
-
*/
|
|
916
|
-
qualify(...expr) {
|
|
917
|
-
const { query } = this;
|
|
918
|
-
if (expr.length === 0) {
|
|
919
|
-
return query.qualify;
|
|
920
|
-
} else {
|
|
921
|
-
query.qualify = query.qualify.concat(
|
|
922
|
-
expr.flat().filter((x2) => x2)
|
|
923
|
-
);
|
|
924
|
-
return this;
|
|
925
|
-
}
|
|
474
|
+
constructor(param, table) {
|
|
475
|
+
super(COLUMN_PARAM, table);
|
|
476
|
+
this.param = param;
|
|
926
477
|
}
|
|
927
478
|
/**
|
|
928
|
-
*
|
|
929
|
-
* @returns {
|
|
479
|
+
* Returns the column name.
|
|
480
|
+
* @returns {string}
|
|
930
481
|
*/
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
* @param {...any} expr Expressions to add.
|
|
934
|
-
* @returns {this}
|
|
935
|
-
*/
|
|
936
|
-
orderby(...expr) {
|
|
937
|
-
const { query } = this;
|
|
938
|
-
if (expr.length === 0) {
|
|
939
|
-
return query.orderby;
|
|
940
|
-
} else {
|
|
941
|
-
query.orderby = query.orderby.concat(
|
|
942
|
-
expr.flat().filter((x2) => x2).map(asColumn)
|
|
943
|
-
);
|
|
944
|
-
return this;
|
|
945
|
-
}
|
|
482
|
+
get column() {
|
|
483
|
+
return `${this.param.value}`;
|
|
946
484
|
}
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
// src/functions/column.js
|
|
488
|
+
function column(name, table) {
|
|
489
|
+
const tref = asTableRef(table);
|
|
490
|
+
return isParamLike(name) ? new ColumnParamNode(new ParamNode(name), tref) : new ColumnNameRefNode(name, tref);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// src/ast/verbatim.js
|
|
494
|
+
var VerbatimNode = class extends ExprNode {
|
|
947
495
|
/**
|
|
948
|
-
*
|
|
949
|
-
* @
|
|
496
|
+
* Instantiate a raw node with verbatim content.
|
|
497
|
+
* @param {string} value The verbatim content to include.
|
|
950
498
|
*/
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
* @returns {this}
|
|
955
|
-
*/
|
|
956
|
-
limit(value) {
|
|
957
|
-
const { query } = this;
|
|
958
|
-
if (arguments.length === 0) {
|
|
959
|
-
return query.limit;
|
|
960
|
-
} else {
|
|
961
|
-
query.limit = Number.isFinite(value) ? value : void 0;
|
|
962
|
-
return this;
|
|
963
|
-
}
|
|
499
|
+
constructor(value) {
|
|
500
|
+
super(VERBATIM);
|
|
501
|
+
this.value = value;
|
|
964
502
|
}
|
|
965
503
|
/**
|
|
966
|
-
*
|
|
967
|
-
* @returns {
|
|
504
|
+
* Generate a SQL query string for this node.
|
|
505
|
+
* @returns {string}
|
|
968
506
|
*/
|
|
969
|
-
/**
|
|
970
|
-
* Set the query result OFFSET.
|
|
971
|
-
* @param {number} value The offset value.
|
|
972
|
-
* @returns {this}
|
|
973
|
-
*/
|
|
974
|
-
offset(value) {
|
|
975
|
-
const { query } = this;
|
|
976
|
-
if (arguments.length === 0) {
|
|
977
|
-
return query.offset;
|
|
978
|
-
} else {
|
|
979
|
-
query.offset = Number.isFinite(value) ? value : void 0;
|
|
980
|
-
return this;
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
get subqueries() {
|
|
984
|
-
const { query, cteFor } = this;
|
|
985
|
-
const ctes = (cteFor?.query || query).with;
|
|
986
|
-
const cte = ctes?.reduce((o, { as, query: query2 }) => (o[as] = query2, o), {});
|
|
987
|
-
const q = [];
|
|
988
|
-
query.from.forEach(({ from }) => {
|
|
989
|
-
if (isQuery(from)) {
|
|
990
|
-
q.push(from);
|
|
991
|
-
} else if (cte[from.table]) {
|
|
992
|
-
const sub = cte[from.table];
|
|
993
|
-
q.push(sub);
|
|
994
|
-
}
|
|
995
|
-
});
|
|
996
|
-
return q;
|
|
997
|
-
}
|
|
998
507
|
toString() {
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
508
|
+
return this.value;
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
// src/functions/literal.js
|
|
513
|
+
function literal(value) {
|
|
514
|
+
return new LiteralNode(value);
|
|
515
|
+
}
|
|
516
|
+
function verbatim(value) {
|
|
517
|
+
return new VerbatimNode(value);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// src/functions/table-ref.js
|
|
521
|
+
function tableRef(...ids) {
|
|
522
|
+
const args = exprList(ids, String);
|
|
523
|
+
return args?.length ? new TableRefNode(args) : void 0;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// src/util/ast.js
|
|
527
|
+
function asNode(value) {
|
|
528
|
+
return isString(value) ? parseColumnRef(value) : asLiteral(value);
|
|
529
|
+
}
|
|
530
|
+
function asVerbatim(value) {
|
|
531
|
+
return isString(value) ? verbatim(value) : asLiteral(value);
|
|
532
|
+
}
|
|
533
|
+
function asLiteral(value) {
|
|
534
|
+
return value instanceof ExprNode ? value : isParamLike(value) ? new ParamNode(value) : literal(value);
|
|
535
|
+
}
|
|
536
|
+
function asTableRef(value) {
|
|
537
|
+
return isString(value) ? parseTableRef(value) : isArray(value) ? tableRef(value) : value;
|
|
538
|
+
}
|
|
539
|
+
function parseColumnRef(ref) {
|
|
540
|
+
const ids = parseIdentifier(ref);
|
|
541
|
+
return column(ids.pop(), tableRef(ids));
|
|
542
|
+
}
|
|
543
|
+
function parseTableRef(ref) {
|
|
544
|
+
return tableRef(parseIdentifier(ref));
|
|
545
|
+
}
|
|
546
|
+
function over() {
|
|
547
|
+
return new WindowDefNode();
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// src/ast/aggregate.js
|
|
551
|
+
var AggregateNode = class _AggregateNode extends ExprNode {
|
|
552
|
+
/**
|
|
553
|
+
* Instantiate an aggregate function node.
|
|
554
|
+
* @param {string} name The aggregate function name.
|
|
555
|
+
* @param {ExprNode[]} args The aggregate function arguments.
|
|
556
|
+
* @param {boolean} [distinct] The distinct flag.
|
|
557
|
+
* @param {ExprNode} [filter] Filter expression.
|
|
558
|
+
*/
|
|
559
|
+
constructor(name, args, distinct, filter) {
|
|
560
|
+
super(AGGREGATE);
|
|
561
|
+
this.name = name;
|
|
562
|
+
this.args = args;
|
|
563
|
+
this.isDistinct = distinct;
|
|
564
|
+
this.filter = filter;
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* Return a new derived aggregate over distinct values.
|
|
568
|
+
* @param {boolean} [isDistinct=true] The distinct flag.
|
|
569
|
+
* @returns {AggregateNode} A new aggregate node.
|
|
570
|
+
*/
|
|
571
|
+
distinct(isDistinct2 = true) {
|
|
572
|
+
return new _AggregateNode(this.name, this.args, isDistinct2, this.filter);
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Return a new derived aggregate function that filters values.
|
|
576
|
+
* @param {ExprNode | string} filter The filter expression.
|
|
577
|
+
* @returns {AggregateNode} A new aggregate node.
|
|
578
|
+
*/
|
|
579
|
+
where(filter) {
|
|
580
|
+
if (isString(filter)) filter = asVerbatim(filter);
|
|
581
|
+
return new _AggregateNode(this.name, this.args, this.isDistinct, filter);
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Return a new window function over this aggregate.
|
|
585
|
+
* @returns {WindowNode} A new window node.
|
|
586
|
+
*/
|
|
587
|
+
window() {
|
|
588
|
+
return new WindowNode(this);
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Return a new window function over this aggregate with the given partitions.
|
|
592
|
+
* @param {...import('../types.js').ExprVarArgs} expr The partition by criteria.
|
|
593
|
+
* @returns {WindowNode} A new window node.
|
|
594
|
+
*/
|
|
595
|
+
partitionby(...expr) {
|
|
596
|
+
return this.window().partitionby(...expr);
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Return a new window function over this aggregate with the given ordering.
|
|
600
|
+
* @param {...import('../types.js').ExprVarArgs} expr The order by criteria.
|
|
601
|
+
* @returns {WindowNode} A new window node.
|
|
602
|
+
*/
|
|
603
|
+
orderby(...expr) {
|
|
604
|
+
return this.window().orderby(...expr);
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Generate a SQL query string for this node.
|
|
608
|
+
* @returns {string}
|
|
609
|
+
*/
|
|
610
|
+
toString() {
|
|
611
|
+
const { name, args, isDistinct: isDistinct2, filter } = this;
|
|
612
|
+
const dist = isDistinct2 ? "DISTINCT " : "";
|
|
613
|
+
const arg = args?.length ? args.join(", ") : "*";
|
|
614
|
+
const filt = filter ? ` FILTER (WHERE ${filter})` : "";
|
|
615
|
+
return `${name}(${dist}${arg})${filt}`;
|
|
616
|
+
}
|
|
617
|
+
};
|
|
618
|
+
var aggregateNames = [
|
|
619
|
+
"any_value",
|
|
620
|
+
"approx_count_distinct",
|
|
621
|
+
"approx_quantile",
|
|
622
|
+
"arbitrary",
|
|
623
|
+
"arg_max",
|
|
624
|
+
"arg_max_null",
|
|
625
|
+
"arg_min",
|
|
626
|
+
"arg_min_null",
|
|
627
|
+
"array_agg",
|
|
628
|
+
"avg",
|
|
629
|
+
"bit_and",
|
|
630
|
+
"bit_or",
|
|
631
|
+
"bit_xor",
|
|
632
|
+
"bitstring_agg",
|
|
633
|
+
"bool_and",
|
|
634
|
+
"bool_or",
|
|
635
|
+
"corr",
|
|
636
|
+
"count",
|
|
637
|
+
"covar_pop",
|
|
638
|
+
"covar_samp",
|
|
639
|
+
"entropy",
|
|
640
|
+
"favg",
|
|
641
|
+
"first",
|
|
642
|
+
"fsum",
|
|
643
|
+
"geomean",
|
|
644
|
+
"kurtosis_pop",
|
|
645
|
+
"kurtosis",
|
|
646
|
+
"last",
|
|
647
|
+
"mad",
|
|
648
|
+
"max",
|
|
649
|
+
"max_by",
|
|
650
|
+
"median",
|
|
651
|
+
"min",
|
|
652
|
+
"min_by",
|
|
653
|
+
"mode",
|
|
654
|
+
"product",
|
|
655
|
+
"quantile",
|
|
656
|
+
"quantile_cont",
|
|
657
|
+
"quantile_disc",
|
|
658
|
+
"regr_avgx",
|
|
659
|
+
"regr_avgy",
|
|
660
|
+
"regr_count",
|
|
661
|
+
"regr_intercept",
|
|
662
|
+
"regr_r2",
|
|
663
|
+
"regr_sxx",
|
|
664
|
+
"regr_sxy",
|
|
665
|
+
"regr_syy",
|
|
666
|
+
"regr_slope",
|
|
667
|
+
"reservoir_quantile",
|
|
668
|
+
"skewness",
|
|
669
|
+
"stddev",
|
|
670
|
+
"stddev_pop",
|
|
671
|
+
"stddev_samp",
|
|
672
|
+
"string_agg",
|
|
673
|
+
"sum",
|
|
674
|
+
"variance",
|
|
675
|
+
"var_pop",
|
|
676
|
+
"var_samp"
|
|
677
|
+
];
|
|
678
|
+
|
|
679
|
+
// src/ast/between-op.js
|
|
680
|
+
var AbstractBetweenOpNode = class extends ExprNode {
|
|
681
|
+
/**
|
|
682
|
+
* Instantiate an abstract between operator node.
|
|
683
|
+
* @param {string} type The node type.
|
|
684
|
+
* @param {ExprNode} expr The input expression.
|
|
685
|
+
* @param {[ExprNode, ExprNode]} extent The range extent.
|
|
686
|
+
*/
|
|
687
|
+
constructor(type, expr, extent) {
|
|
688
|
+
super(type);
|
|
689
|
+
this.expr = expr;
|
|
690
|
+
this.extent = extent;
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Generate a SQL query string for this node.
|
|
694
|
+
* @returns {string}
|
|
695
|
+
*/
|
|
696
|
+
toSQL(op) {
|
|
697
|
+
const { extent: r, expr } = this;
|
|
698
|
+
return r ? `(${expr} ${op} ${r[0]} AND ${r[1]})` : "";
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
var BetweenOpNode = class extends AbstractBetweenOpNode {
|
|
702
|
+
/**
|
|
703
|
+
* Instantiate a between operator node.
|
|
704
|
+
* @param {ExprNode} expr The input expression.
|
|
705
|
+
* @param {[ExprNode, ExprNode]} extent
|
|
706
|
+
* The range extent.
|
|
707
|
+
*/
|
|
708
|
+
constructor(expr, extent) {
|
|
709
|
+
super(BETWEEN_OPERATOR, expr, extent);
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Generate a SQL query string for this node.
|
|
713
|
+
* @returns {string}
|
|
714
|
+
*/
|
|
715
|
+
toString() {
|
|
716
|
+
return super.toSQL("BETWEEN");
|
|
717
|
+
}
|
|
718
|
+
};
|
|
719
|
+
var NotBetweenOpNode = class extends AbstractBetweenOpNode {
|
|
720
|
+
/**
|
|
721
|
+
* Instantiate a not between operator node.
|
|
722
|
+
* @param {ExprNode} expr The input expression.
|
|
723
|
+
* @param {[ExprNode, ExprNode]} extent
|
|
724
|
+
* The range extent.
|
|
725
|
+
*/
|
|
726
|
+
constructor(expr, extent) {
|
|
727
|
+
super(NOT_BETWEEN_OPERATOR, expr, extent);
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* Generate a SQL query string for this node.
|
|
731
|
+
* @returns {string}
|
|
732
|
+
*/
|
|
733
|
+
toString() {
|
|
734
|
+
return super.toSQL("NOT BETWEEN");
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
|
|
738
|
+
// src/ast/binary-op.js
|
|
739
|
+
var BinaryOpNode = class extends ExprNode {
|
|
740
|
+
/**
|
|
741
|
+
* Instantiate a binary operator node.
|
|
742
|
+
* @param {string} op The operator type.
|
|
743
|
+
* @param {ExprNode} left The left input expression.
|
|
744
|
+
* @param {ExprNode} right The right input expression.
|
|
745
|
+
*/
|
|
746
|
+
constructor(op, left, right) {
|
|
747
|
+
super(BINARY_OPERATOR);
|
|
748
|
+
this.op = op;
|
|
749
|
+
this.left = left;
|
|
750
|
+
this.right = right;
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* Generate a SQL query string for this node.
|
|
754
|
+
* @returns {string}
|
|
755
|
+
*/
|
|
756
|
+
toString() {
|
|
757
|
+
return `(${this.left} ${this.op} ${this.right})`;
|
|
758
|
+
}
|
|
759
|
+
};
|
|
760
|
+
|
|
761
|
+
// src/ast/case.js
|
|
762
|
+
var CaseNode = class _CaseNode extends ExprNode {
|
|
763
|
+
/**
|
|
764
|
+
* Instantiate a case node.
|
|
765
|
+
* @param {ExprNode} [expr] An optional base expression, that comes
|
|
766
|
+
* immediately after the CASE keyword. If specified, this case statement
|
|
767
|
+
* acts like a switch statement, with WHEN expressions as values to
|
|
768
|
+
* match against the switch value rather than boolean conditions.
|
|
769
|
+
* @param {WhenNode[]} [when] An array of WHEN/THEN expression nodes.
|
|
770
|
+
* @param {ExprNode} [elseExpr] An ELSE expression.
|
|
771
|
+
*/
|
|
772
|
+
constructor(expr = void 0, when = [], elseExpr = void 0) {
|
|
773
|
+
super(CASE);
|
|
774
|
+
this.expr = expr;
|
|
775
|
+
this._when = when;
|
|
776
|
+
this._else = elseExpr;
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* Return a new case node with the given conditional added as
|
|
780
|
+
* the last WHEN / THEN pair.
|
|
781
|
+
* @param {import('../types.js').ExprValue} cond
|
|
782
|
+
* The WHEN condition expression.
|
|
783
|
+
* @param {import('../types.js').ExprValue} value
|
|
784
|
+
* The THEN value expression.
|
|
785
|
+
* @returns {CaseNode}
|
|
786
|
+
*/
|
|
787
|
+
when(cond2, value) {
|
|
788
|
+
return new _CaseNode(
|
|
789
|
+
this.expr,
|
|
790
|
+
this._when.concat(new WhenNode(asNode(cond2), asNode(value))),
|
|
791
|
+
this._else
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* Return a new case node with the given ELSE expression.
|
|
796
|
+
* @param {import('../types.js').ExprValue} expr The ELSE expression.
|
|
797
|
+
* @returns {CaseNode}
|
|
798
|
+
*/
|
|
799
|
+
else(expr) {
|
|
800
|
+
return new _CaseNode(this.expr, this._when, asNode(expr));
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* Generate a SQL query string for this node.
|
|
804
|
+
* @returns {string}
|
|
805
|
+
*/
|
|
806
|
+
toString() {
|
|
807
|
+
return "CASE " + (this.expr ? `${this.expr} ` : "") + this._when.join(" ") + (this._else ? ` ELSE ${this._else}` : "") + " END";
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
var WhenNode = class extends SQLNode {
|
|
811
|
+
/**
|
|
812
|
+
* Instantiate a case node.
|
|
813
|
+
* @param {ExprNode} when The WHEN condition expression.
|
|
814
|
+
* @param {ExprNode} then The THEN value expression.
|
|
815
|
+
*/
|
|
816
|
+
constructor(when, then) {
|
|
817
|
+
super(WHEN);
|
|
818
|
+
this.when = when;
|
|
819
|
+
this.then = then;
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Generate a SQL query string for this node.
|
|
823
|
+
* @returns {string}
|
|
824
|
+
*/
|
|
825
|
+
toString() {
|
|
826
|
+
return `WHEN ${this.when} THEN ${this.then}`;
|
|
827
|
+
}
|
|
828
|
+
};
|
|
829
|
+
|
|
830
|
+
// src/ast/cast.js
|
|
831
|
+
var CastNode = class extends ExprNode {
|
|
832
|
+
/**
|
|
833
|
+
* Instantiate a cast node.
|
|
834
|
+
* @param {ExprNode} expr The expression to type cast.
|
|
835
|
+
* @param {string} type The type to cast to.
|
|
836
|
+
*/
|
|
837
|
+
constructor(expr, type) {
|
|
838
|
+
super(CAST);
|
|
839
|
+
this.expr = expr;
|
|
840
|
+
this.cast = type;
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* Generate a SQL query string for this node.
|
|
844
|
+
* @returns {string}
|
|
845
|
+
*/
|
|
846
|
+
toString() {
|
|
847
|
+
return `(${this.expr})::${this.cast}`;
|
|
848
|
+
}
|
|
849
|
+
};
|
|
850
|
+
|
|
851
|
+
// src/ast/fragment.js
|
|
852
|
+
var FragmentNode = class extends ExprNode {
|
|
853
|
+
/**
|
|
854
|
+
* Instantiate a fragment node with arbitrary content.
|
|
855
|
+
* @param {ExprNode[]} spans The consecutive parts making up the fragment.
|
|
856
|
+
*/
|
|
857
|
+
constructor(spans) {
|
|
858
|
+
super(FRAGMENT);
|
|
859
|
+
this.spans = spans;
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* Generate a SQL query string for this node.
|
|
863
|
+
* @returns {string}
|
|
864
|
+
*/
|
|
865
|
+
toString() {
|
|
866
|
+
return this.spans.join("");
|
|
867
|
+
}
|
|
868
|
+
};
|
|
869
|
+
|
|
870
|
+
// src/ast/sample.js
|
|
871
|
+
var SampleClauseNode = class extends SQLNode {
|
|
872
|
+
/**
|
|
873
|
+
* Instantiate a sample clause node.
|
|
874
|
+
* @param {number} size The sample size as either a row count or percentage.
|
|
875
|
+
* @param {boolean} [perc=false] Flag indicating if the sampling unit is
|
|
876
|
+
* rows (`false`) or a percentage (`true`).
|
|
877
|
+
* @param {SampleMethod} [method] The sampling method. If unspecified,
|
|
878
|
+
* a default method is applied based on the sampling unit.
|
|
879
|
+
* @param {number} [seed] The random seed.
|
|
880
|
+
*/
|
|
881
|
+
constructor(size, perc = false, method = void 0, seed = void 0) {
|
|
882
|
+
super(SAMPLE_CLAUSE);
|
|
883
|
+
this.size = size;
|
|
884
|
+
this.perc = perc;
|
|
885
|
+
this.method = method;
|
|
886
|
+
this.seed = seed;
|
|
887
|
+
}
|
|
888
|
+
toString() {
|
|
889
|
+
const { size, perc, method, seed } = this;
|
|
890
|
+
const unit = perc ? "%" : " ROWS";
|
|
891
|
+
const s = seed != null ? `, ${seed}` : "";
|
|
892
|
+
return `${size}${unit}${method ? ` (${method}${s})` : ""}`;
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
|
|
896
|
+
// src/ast/select.js
|
|
897
|
+
var SelectClauseNode = class extends SQLNode {
|
|
898
|
+
/**
|
|
899
|
+
* Instantiate a select node.
|
|
900
|
+
* @param {ExprNode} expr The select expression.
|
|
901
|
+
* @param {string} alias The output name.
|
|
902
|
+
*/
|
|
903
|
+
constructor(expr, alias) {
|
|
904
|
+
super(SELECT_CLAUSE);
|
|
905
|
+
this.expr = expr;
|
|
906
|
+
this.alias = alias;
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* Generate a SQL query string for this node.
|
|
910
|
+
* @returns {string}
|
|
911
|
+
*/
|
|
912
|
+
toString() {
|
|
913
|
+
const { expr, alias } = this;
|
|
914
|
+
return !alias || isColumnRefFor(expr, alias) ? `${expr}` : `${expr} AS ${quoteIdentifier(alias)}`;
|
|
915
|
+
}
|
|
916
|
+
};
|
|
917
|
+
function isColumnRefFor(expr, name) {
|
|
918
|
+
return expr instanceof ColumnRefNode && expr.table == null && expr.column === name;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// src/ast/with.js
|
|
922
|
+
var WithClauseNode = class extends SQLNode {
|
|
923
|
+
/**
|
|
924
|
+
* Instantiate a with clause node for a common table expression (CTE).
|
|
925
|
+
* @param {string} name The common table expression (CTE) name.
|
|
926
|
+
* @param {Query} query The common table expression (CTE) query.
|
|
927
|
+
*/
|
|
928
|
+
constructor(name, query) {
|
|
929
|
+
super(WITH_CLAUSE);
|
|
930
|
+
this.name = name;
|
|
931
|
+
this.query = query;
|
|
932
|
+
}
|
|
933
|
+
toString() {
|
|
934
|
+
return `"${this.name}" AS (${this.query})`;
|
|
935
|
+
}
|
|
936
|
+
};
|
|
937
|
+
|
|
938
|
+
// src/ast/query.js
|
|
939
|
+
function isQuery(value) {
|
|
940
|
+
return value instanceof Query;
|
|
941
|
+
}
|
|
942
|
+
function isSelectQuery(value) {
|
|
943
|
+
return value instanceof SelectQuery;
|
|
944
|
+
}
|
|
945
|
+
function isDescribeQuery(value) {
|
|
946
|
+
return value instanceof DescribeQuery;
|
|
947
|
+
}
|
|
948
|
+
var Query = class extends ExprNode {
|
|
949
|
+
/**
|
|
950
|
+
* Create a new select query with the given SELECT expressions.
|
|
951
|
+
* @param {...import('../types.js').SelectExpr} expr The SELECT expressions.
|
|
952
|
+
* @returns {SelectQuery}
|
|
953
|
+
*/
|
|
954
|
+
static select(...expr) {
|
|
955
|
+
return new SelectQuery().select(...expr);
|
|
956
|
+
}
|
|
957
|
+
/**
|
|
958
|
+
* Create a new select query with the given FROM expressions.
|
|
959
|
+
* @param {...import('../types.js').FromExpr} expr The FROM expressions.
|
|
960
|
+
* @returns {SelectQuery}
|
|
961
|
+
*/
|
|
962
|
+
static from(...expr) {
|
|
963
|
+
return new SelectQuery().from(...expr);
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* Create a new select query with the given WITH CTE queries.
|
|
967
|
+
* @param {...import('../types.js').WithExpr} expr The WITH CTE queries.
|
|
968
|
+
* @returns {SelectQuery}
|
|
969
|
+
*/
|
|
970
|
+
static with(...expr) {
|
|
971
|
+
return new SelectQuery().with(...expr);
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* Create a new UNION set operation over the given queries.
|
|
975
|
+
* @param {...Query} queries The queries.
|
|
976
|
+
* @returns {SetOperation}
|
|
977
|
+
*/
|
|
978
|
+
static union(...queries) {
|
|
979
|
+
return new SetOperation("UNION", queries.flat());
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Create a new UNION ALL set operation over the given queries.
|
|
983
|
+
* @param {...Query} queries The queries.
|
|
984
|
+
* @returns {SetOperation}
|
|
985
|
+
*/
|
|
986
|
+
static unionAll(...queries) {
|
|
987
|
+
return new SetOperation("UNION ALL", queries.flat());
|
|
988
|
+
}
|
|
989
|
+
/**
|
|
990
|
+
* Create a new INTERSECT set operation over the given queries.
|
|
991
|
+
* @param {...Query} queries The queries.
|
|
992
|
+
* @returns {SetOperation}
|
|
993
|
+
*/
|
|
994
|
+
static intersect(...queries) {
|
|
995
|
+
return new SetOperation("INTERSECT", queries.flat());
|
|
996
|
+
}
|
|
997
|
+
/**
|
|
998
|
+
* Create a new EXCEPT set operation over the given queries.
|
|
999
|
+
* @param {...Query} queries The queries.
|
|
1000
|
+
* @returns {SetOperation}
|
|
1001
|
+
*/
|
|
1002
|
+
static except(...queries) {
|
|
1003
|
+
return new SetOperation("EXCEPT", queries.flat());
|
|
1004
|
+
}
|
|
1005
|
+
/**
|
|
1006
|
+
* Create a new describe query for the given input query.
|
|
1007
|
+
* @param {Query} query The query to describe.
|
|
1008
|
+
* @returns {DescribeQuery}
|
|
1009
|
+
*/
|
|
1010
|
+
static describe(query) {
|
|
1011
|
+
return new DescribeQuery(query);
|
|
1012
|
+
}
|
|
1013
|
+
/**
|
|
1014
|
+
* Instantiate a new query.
|
|
1015
|
+
*/
|
|
1016
|
+
constructor(type) {
|
|
1017
|
+
super(type);
|
|
1018
|
+
this._orderby = [];
|
|
1019
|
+
this._limit = void 0;
|
|
1020
|
+
this._offset = void 0;
|
|
1021
|
+
this.cteFor = null;
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Return a list of subqueries.
|
|
1025
|
+
* @returns {Query[]}
|
|
1026
|
+
*/
|
|
1027
|
+
get subqueries() {
|
|
1028
|
+
return [];
|
|
1029
|
+
}
|
|
1030
|
+
/**
|
|
1031
|
+
* Clone this query.
|
|
1032
|
+
* @returns {Query}
|
|
1033
|
+
*/
|
|
1034
|
+
clone() {
|
|
1035
|
+
return this;
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Add ORDER BY expressions.
|
|
1039
|
+
* @param {...import('../types.js').OrderByExpr} expr Expressions to add.
|
|
1040
|
+
* @returns
|
|
1041
|
+
*/
|
|
1042
|
+
orderby(...expr) {
|
|
1043
|
+
this._orderby = this._orderby.concat(exprList(expr));
|
|
1044
|
+
return this;
|
|
1045
|
+
}
|
|
1046
|
+
/**
|
|
1047
|
+
* Set the query result LIMIT.
|
|
1048
|
+
* @param {number} value The limit value.
|
|
1049
|
+
* @returns {this}
|
|
1050
|
+
*/
|
|
1051
|
+
limit(value) {
|
|
1052
|
+
this._limit = Number.isFinite(value) ? value : void 0;
|
|
1053
|
+
return this;
|
|
1054
|
+
}
|
|
1055
|
+
/**
|
|
1056
|
+
* Set the query result OFFSET.
|
|
1057
|
+
* @param {number} value The offset value.
|
|
1058
|
+
* @returns {this}
|
|
1059
|
+
*/
|
|
1060
|
+
offset(value) {
|
|
1061
|
+
this._offset = Number.isFinite(value) ? value : void 0;
|
|
1062
|
+
return this;
|
|
1063
|
+
}
|
|
1064
|
+
};
|
|
1065
|
+
var SelectQuery = class _SelectQuery extends Query {
|
|
1066
|
+
/**
|
|
1067
|
+
* Instantiate a new select query.
|
|
1068
|
+
*/
|
|
1069
|
+
constructor() {
|
|
1070
|
+
super(SELECT_QUERY);
|
|
1071
|
+
this._with = [];
|
|
1072
|
+
this._select = [];
|
|
1073
|
+
this._from = [];
|
|
1074
|
+
this._where = [];
|
|
1075
|
+
this._sample = void 0;
|
|
1076
|
+
this._groupby = [];
|
|
1077
|
+
this._having = [];
|
|
1078
|
+
this._window = [];
|
|
1079
|
+
this._qualify = [];
|
|
1080
|
+
}
|
|
1081
|
+
/**
|
|
1082
|
+
* Return a list of subqueries.
|
|
1083
|
+
* @returns {Query[]}
|
|
1084
|
+
*/
|
|
1085
|
+
get subqueries() {
|
|
1086
|
+
const q = this.cteFor || this;
|
|
1087
|
+
const w = q instanceof _SelectQuery ? q._with : [];
|
|
1088
|
+
const cte = w.reduce((obj, c) => (obj[c.name] = c.query, obj), {});
|
|
1089
|
+
const queries = [];
|
|
1090
|
+
this._from.forEach(({ expr }) => {
|
|
1091
|
+
if (isQuery(expr)) {
|
|
1092
|
+
queries.push(expr);
|
|
1093
|
+
} else if (isTableRef(expr)) {
|
|
1094
|
+
const subq = cte[expr.name];
|
|
1095
|
+
if (subq) queries.push(subq);
|
|
1096
|
+
}
|
|
1097
|
+
});
|
|
1098
|
+
return queries;
|
|
1099
|
+
}
|
|
1100
|
+
/**
|
|
1101
|
+
* Clone this query.
|
|
1102
|
+
* @returns {SelectQuery}
|
|
1103
|
+
*/
|
|
1104
|
+
clone() {
|
|
1105
|
+
return Object.assign(new _SelectQuery(), this);
|
|
1106
|
+
}
|
|
1107
|
+
/**
|
|
1108
|
+
* Add WITH common table expressions (CTEs).
|
|
1109
|
+
* @param {...import('../types.js').WithExpr} expr Expressions to add.
|
|
1110
|
+
* @returns {this}
|
|
1111
|
+
*/
|
|
1112
|
+
with(...expr) {
|
|
1113
|
+
const list = [];
|
|
1114
|
+
const add2 = (name, q) => {
|
|
1115
|
+
const query = q.clone();
|
|
1116
|
+
query.cteFor = this;
|
|
1117
|
+
list.push(new WithClauseNode(name, query));
|
|
1118
|
+
};
|
|
1119
|
+
expr.flat().forEach((e) => {
|
|
1120
|
+
if (e != null) for (const name in e) add2(name, e[name]);
|
|
1121
|
+
});
|
|
1122
|
+
this._with = this._with.concat(list);
|
|
1123
|
+
return this;
|
|
1124
|
+
}
|
|
1125
|
+
/**
|
|
1126
|
+
* Add SELECT expressions.
|
|
1127
|
+
* @param {...import('../types.js').SelectExpr} expr Expressions to add.
|
|
1128
|
+
* @returns {this}
|
|
1129
|
+
*/
|
|
1130
|
+
select(...expr) {
|
|
1131
|
+
const list = [];
|
|
1132
|
+
const add2 = (v, as) => list.push(
|
|
1133
|
+
new SelectClauseNode(v == null ? v : asNode(v), unquote(as))
|
|
1021
1134
|
);
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1135
|
+
expr.flat().forEach((e) => {
|
|
1136
|
+
if (e == null) return;
|
|
1137
|
+
else if (isString(e)) add2(e, e);
|
|
1138
|
+
else if (isColumnRef(e)) add2(e, e.column);
|
|
1139
|
+
else if (isArray(e)) add2(e[1], e[0]);
|
|
1140
|
+
else for (const alias in e) add2(e[alias], alias);
|
|
1141
|
+
});
|
|
1142
|
+
const keys = new Set(list.map((x2) => x2.alias));
|
|
1143
|
+
this._select = this._select.filter((x2) => !keys.has(x2.alias)).concat(list.filter((x2) => x2.expr));
|
|
1144
|
+
return this;
|
|
1145
|
+
}
|
|
1146
|
+
/**
|
|
1147
|
+
* Set SELECT expressions, replacing any prior expressions.
|
|
1148
|
+
* @param {...import('../types.js').SelectExpr} expr Expressions to add.
|
|
1149
|
+
* @returns {this}
|
|
1150
|
+
*/
|
|
1151
|
+
setSelect(...expr) {
|
|
1152
|
+
this._select = [];
|
|
1153
|
+
return this.select(...expr);
|
|
1154
|
+
}
|
|
1155
|
+
/**
|
|
1156
|
+
* Indicate if this query should retrieve distinct values only.
|
|
1157
|
+
* @param {boolean} value The distinct flag
|
|
1158
|
+
* @returns {this}
|
|
1159
|
+
*/
|
|
1160
|
+
distinct(value = true) {
|
|
1161
|
+
this._distinct = !!value;
|
|
1162
|
+
return this;
|
|
1163
|
+
}
|
|
1164
|
+
/**
|
|
1165
|
+
* Add table FROM expressions.
|
|
1166
|
+
* @param {...import('../types.js').FromExpr} expr Expressions to add.
|
|
1167
|
+
* @returns {this}
|
|
1168
|
+
*/
|
|
1169
|
+
from(...expr) {
|
|
1170
|
+
const list = [];
|
|
1171
|
+
const add2 = (v, as) => list.push(new FromClauseNode(asTableRef(v), unquote(as)));
|
|
1172
|
+
expr.flat().forEach((e) => {
|
|
1173
|
+
if (e == null) return;
|
|
1174
|
+
else if (isString(e)) add2(e, e);
|
|
1175
|
+
else if (isTableRef(e)) add2(e, e.name);
|
|
1176
|
+
else if (isNode(e)) add2(e);
|
|
1177
|
+
else if (isArray(e)) add2(e[1], e[0]);
|
|
1178
|
+
else for (const alias in e) add2(e[alias], alias);
|
|
1179
|
+
});
|
|
1180
|
+
this._from = this._from.concat(list);
|
|
1181
|
+
return this;
|
|
1182
|
+
}
|
|
1183
|
+
/**
|
|
1184
|
+
* Set FROM expressions, replacing any prior expressions.
|
|
1185
|
+
* @param {...import('../types.js').FromExpr} expr Expressions to add.
|
|
1186
|
+
* @returns {this}
|
|
1187
|
+
*/
|
|
1188
|
+
setFrom(...expr) {
|
|
1189
|
+
this._from = [];
|
|
1190
|
+
return this.from(...expr);
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* Set SAMPLE settings.
|
|
1194
|
+
* @param {number | SampleClauseNode} value Either a sample clause node
|
|
1195
|
+
* or the sample size as either a row count or percentage.
|
|
1196
|
+
* @param {import('./sample.js').SampleMethod} [method] The sampling method
|
|
1197
|
+
* to use.
|
|
1198
|
+
* @param {number} [seed] The random seed.
|
|
1199
|
+
* @returns {this}
|
|
1200
|
+
*/
|
|
1201
|
+
sample(value, method, seed) {
|
|
1202
|
+
let clause;
|
|
1203
|
+
if (typeof value === "number") {
|
|
1204
|
+
const perc = value > 0 && value < 1;
|
|
1205
|
+
const size = perc ? value * 100 : Math.floor(value);
|
|
1206
|
+
clause = new SampleClauseNode(size, perc, method, seed);
|
|
1207
|
+
} else {
|
|
1208
|
+
clause = value;
|
|
1029
1209
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1210
|
+
this._sample = clause;
|
|
1211
|
+
return this;
|
|
1212
|
+
}
|
|
1213
|
+
/**
|
|
1214
|
+
* Add WHERE expressions.
|
|
1215
|
+
* @param {...import('../types.js').FilterExpr} expr Expressions to add.
|
|
1216
|
+
* @returns {this}
|
|
1217
|
+
*/
|
|
1218
|
+
where(...expr) {
|
|
1219
|
+
this._where = this._where.concat(exprList(expr, asVerbatim));
|
|
1220
|
+
return this;
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Set WHERE expressions, replacing any prior expressions.
|
|
1224
|
+
* @param {...import('../types.js').FilterExpr} expr Expressions to add.
|
|
1225
|
+
* @returns {this}
|
|
1226
|
+
*/
|
|
1227
|
+
setWhere(...expr) {
|
|
1228
|
+
this._where = [];
|
|
1229
|
+
return this.where(...expr);
|
|
1230
|
+
}
|
|
1231
|
+
/**
|
|
1232
|
+
* Add GROUP BY expressions.
|
|
1233
|
+
* @param {...import('../types.js').GroupByExpr} expr Expressions to add.
|
|
1234
|
+
* @returns {this}
|
|
1235
|
+
*/
|
|
1236
|
+
groupby(...expr) {
|
|
1237
|
+
this._groupby = this._groupby.concat(exprList(expr));
|
|
1238
|
+
return this;
|
|
1239
|
+
}
|
|
1240
|
+
/**
|
|
1241
|
+
* Set GROUP BY expressions, replacing any prior expressions.
|
|
1242
|
+
* @param {...import('../types.js').GroupByExpr} expr Expressions to add.
|
|
1243
|
+
* @returns {this}
|
|
1244
|
+
*/
|
|
1245
|
+
setGroupby(...expr) {
|
|
1246
|
+
this._groupby = [];
|
|
1247
|
+
return this.groupby(...expr);
|
|
1248
|
+
}
|
|
1249
|
+
/**
|
|
1250
|
+
* Add HAVING expressions.
|
|
1251
|
+
* @param {...import('../types.js').FilterExpr} expr Expressions to add.
|
|
1252
|
+
* @returns {this}
|
|
1253
|
+
*/
|
|
1254
|
+
having(...expr) {
|
|
1255
|
+
this._having = this._having.concat(exprList(expr, asVerbatim));
|
|
1256
|
+
return this;
|
|
1257
|
+
}
|
|
1258
|
+
/**
|
|
1259
|
+
* Add WINDOW definitions.
|
|
1260
|
+
* @param {...any} expr Expressions to add.
|
|
1261
|
+
* @returns {this}
|
|
1262
|
+
*/
|
|
1263
|
+
window(...expr) {
|
|
1264
|
+
const list = [];
|
|
1265
|
+
expr.flat().forEach((e) => {
|
|
1266
|
+
if (e != null) for (const name in e) {
|
|
1267
|
+
list.push(new WindowClauseNode(unquote(name), e[name]));
|
|
1268
|
+
}
|
|
1269
|
+
});
|
|
1270
|
+
this._window = this._window.concat(list);
|
|
1271
|
+
return this;
|
|
1272
|
+
}
|
|
1273
|
+
/**
|
|
1274
|
+
* Add QUALIFY expressions.
|
|
1275
|
+
* @param {...import('../types.js').FilterExpr} expr Expressions to add.
|
|
1276
|
+
* @returns {this}
|
|
1277
|
+
*/
|
|
1278
|
+
qualify(...expr) {
|
|
1279
|
+
this._qualify = this._qualify.concat(exprList(expr, asVerbatim));
|
|
1280
|
+
return this;
|
|
1281
|
+
}
|
|
1282
|
+
/**
|
|
1283
|
+
* Generate a SQL query string.
|
|
1284
|
+
* @returns {string}
|
|
1285
|
+
*/
|
|
1286
|
+
toString() {
|
|
1287
|
+
const {
|
|
1288
|
+
_with,
|
|
1289
|
+
_select,
|
|
1290
|
+
_distinct,
|
|
1291
|
+
_from,
|
|
1292
|
+
_sample,
|
|
1293
|
+
_where,
|
|
1294
|
+
_groupby,
|
|
1295
|
+
_having,
|
|
1296
|
+
_window,
|
|
1297
|
+
_qualify,
|
|
1298
|
+
_orderby,
|
|
1299
|
+
_limit,
|
|
1300
|
+
_offset
|
|
1301
|
+
} = this;
|
|
1302
|
+
const sql2 = [];
|
|
1303
|
+
if (_with.length) sql2.push(`WITH ${_with.join(", ")}`);
|
|
1304
|
+
sql2.push(`SELECT${_distinct ? " DISTINCT" : ""} ${_select.join(", ")}`);
|
|
1305
|
+
if (_from.length) sql2.push(`FROM ${_from.join(", ")}`);
|
|
1306
|
+
if (_where.length) {
|
|
1307
|
+
const clauses = _where.map(String).filter((x2) => x2).join(" AND ");
|
|
1032
1308
|
if (clauses) sql2.push(`WHERE ${clauses}`);
|
|
1033
1309
|
}
|
|
1034
|
-
if (
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
const how = method ? ` (${method}${seed != null ? `, ${seed}` : ""})` : "";
|
|
1038
|
-
sql2.push(`USING SAMPLE ${size}${how}`);
|
|
1310
|
+
if (_sample) sql2.push(`USING SAMPLE ${_sample}`);
|
|
1311
|
+
if (_groupby.length) {
|
|
1312
|
+
sql2.push(`GROUP BY ${_groupby.join(", ")}`);
|
|
1039
1313
|
}
|
|
1040
|
-
if (
|
|
1041
|
-
|
|
1042
|
-
}
|
|
1043
|
-
if (having.length) {
|
|
1044
|
-
const clauses = having.map(String).filter((x2) => x2).join(" AND ");
|
|
1314
|
+
if (_having.length) {
|
|
1315
|
+
const clauses = _having.map(String).filter((x2) => x2).join(" AND ");
|
|
1045
1316
|
if (clauses) sql2.push(`HAVING ${clauses}`);
|
|
1046
1317
|
}
|
|
1047
|
-
if (
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
}
|
|
1051
|
-
if (qualify.length) {
|
|
1052
|
-
const clauses = qualify.map(String).filter((x2) => x2).join(" AND ");
|
|
1318
|
+
if (_window.length) sql2.push(`WINDOW ${_window.join(", ")}`);
|
|
1319
|
+
if (_qualify.length) {
|
|
1320
|
+
const clauses = _qualify.map(String).filter((x2) => x2).join(" AND ");
|
|
1053
1321
|
if (clauses) sql2.push(`QUALIFY ${clauses}`);
|
|
1054
1322
|
}
|
|
1055
|
-
if (
|
|
1056
|
-
|
|
1057
|
-
}
|
|
1058
|
-
if (Number.isFinite(limit)) {
|
|
1059
|
-
sql2.push(`LIMIT ${limit}`);
|
|
1060
|
-
}
|
|
1061
|
-
if (Number.isFinite(offset)) {
|
|
1062
|
-
sql2.push(`OFFSET ${offset}`);
|
|
1063
|
-
}
|
|
1323
|
+
if (_orderby.length) sql2.push(`ORDER BY ${_orderby.join(", ")}`);
|
|
1324
|
+
if (Number.isFinite(_limit)) sql2.push(`LIMIT ${_limit}`);
|
|
1325
|
+
if (Number.isFinite(_offset)) sql2.push(`OFFSET ${_offset}`);
|
|
1064
1326
|
return sql2.join(" ");
|
|
1065
1327
|
}
|
|
1066
1328
|
};
|
|
1067
|
-
var
|
|
1329
|
+
var DescribeQuery = class _DescribeQuery extends SQLNode {
|
|
1330
|
+
/**
|
|
1331
|
+
* Instantiate a describe query.
|
|
1332
|
+
*/
|
|
1333
|
+
constructor(query) {
|
|
1334
|
+
super(DESCRIBE_QUERY);
|
|
1335
|
+
this.query = query;
|
|
1336
|
+
}
|
|
1337
|
+
/**
|
|
1338
|
+
* Clone this describe query.
|
|
1339
|
+
* @returns {DescribeQuery}
|
|
1340
|
+
*/
|
|
1341
|
+
clone() {
|
|
1342
|
+
return new _DescribeQuery(this.query.clone());
|
|
1343
|
+
}
|
|
1344
|
+
/**
|
|
1345
|
+
* Generate a SQL query string.
|
|
1346
|
+
* @returns {string}
|
|
1347
|
+
*/
|
|
1348
|
+
toString() {
|
|
1349
|
+
return `DESCRIBE ${this.query}`;
|
|
1350
|
+
}
|
|
1351
|
+
};
|
|
1352
|
+
var SetOperation = class _SetOperation extends Query {
|
|
1353
|
+
/**
|
|
1354
|
+
* Instantiate a new set operation instance.
|
|
1355
|
+
* @param {string} op The set operation.
|
|
1356
|
+
* @param {Query[]} queries The subqueries.
|
|
1357
|
+
*/
|
|
1068
1358
|
constructor(op, queries) {
|
|
1359
|
+
super(SET_OPERATION);
|
|
1069
1360
|
this.op = op;
|
|
1070
|
-
this.queries = queries
|
|
1071
|
-
|
|
1072
|
-
|
|
1361
|
+
this.queries = queries;
|
|
1362
|
+
}
|
|
1363
|
+
/**
|
|
1364
|
+
* Return a list of subqueries.
|
|
1365
|
+
* @returns {Query[]}
|
|
1366
|
+
*/
|
|
1367
|
+
get subqueries() {
|
|
1368
|
+
const { queries, cteFor } = this;
|
|
1369
|
+
if (cteFor) queries.forEach((q) => q.cteFor = cteFor);
|
|
1370
|
+
return queries;
|
|
1073
1371
|
}
|
|
1372
|
+
/**
|
|
1373
|
+
* Clone this set operation.
|
|
1374
|
+
* @returns {SetOperation}
|
|
1375
|
+
*/
|
|
1074
1376
|
clone() {
|
|
1075
|
-
const
|
|
1076
|
-
|
|
1077
|
-
return q;
|
|
1377
|
+
const { op, queries, ...rest } = this;
|
|
1378
|
+
return Object.assign(new _SetOperation(op, queries), rest);
|
|
1078
1379
|
}
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
}
|
|
1380
|
+
/**
|
|
1381
|
+
* Generate a SQL query string.
|
|
1382
|
+
* @returns {string}
|
|
1383
|
+
*/
|
|
1384
|
+
toString() {
|
|
1385
|
+
const { op, queries, _orderby, _limit, _offset } = this;
|
|
1386
|
+
const sql2 = [queries.join(` ${op} `)];
|
|
1387
|
+
if (_orderby.length) sql2.push(`ORDER BY ${_orderby.join(", ")}`);
|
|
1388
|
+
if (Number.isFinite(_limit)) sql2.push(`LIMIT ${_limit}`);
|
|
1389
|
+
if (Number.isFinite(_offset)) sql2.push(`OFFSET ${_offset}`);
|
|
1390
|
+
return sql2.join(" ");
|
|
1089
1391
|
}
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1392
|
+
};
|
|
1393
|
+
|
|
1394
|
+
// src/ast/from.js
|
|
1395
|
+
var FromClauseNode = class extends SQLNode {
|
|
1396
|
+
/**
|
|
1397
|
+
* Instantiate a from node.
|
|
1398
|
+
* @param {SQLNode} expr The from expression.
|
|
1399
|
+
* @param {string} alias The output name.
|
|
1400
|
+
*/
|
|
1401
|
+
constructor(expr, alias) {
|
|
1402
|
+
super(FROM_CLAUSE);
|
|
1403
|
+
this.expr = expr;
|
|
1404
|
+
this.alias = alias;
|
|
1405
|
+
}
|
|
1406
|
+
/**
|
|
1407
|
+
* Generate a SQL query string for this node.
|
|
1408
|
+
* @returns {string}
|
|
1409
|
+
*/
|
|
1410
|
+
toString() {
|
|
1411
|
+
const { expr, alias } = this;
|
|
1412
|
+
const ref = isQuery(expr) ? `(${expr})` : `${expr}`;
|
|
1413
|
+
return alias && !(isTableRef(expr) && expr.table.join(".") === alias) ? `${ref} AS ${quoteIdentifier(alias)}` : `${ref}`;
|
|
1414
|
+
}
|
|
1415
|
+
};
|
|
1416
|
+
|
|
1417
|
+
// src/ast/in-op.js
|
|
1418
|
+
var InOpNode = class extends ExprNode {
|
|
1419
|
+
/**
|
|
1420
|
+
* Instantiate an in operator node.
|
|
1421
|
+
* @param {ExprNode} expr The input expression.
|
|
1422
|
+
* @param {ExprNode[]} values The value set.
|
|
1423
|
+
*/
|
|
1424
|
+
constructor(expr, values) {
|
|
1425
|
+
super(IN_OPERATOR);
|
|
1426
|
+
this.expr = expr;
|
|
1427
|
+
this.values = values;
|
|
1428
|
+
}
|
|
1429
|
+
/**
|
|
1430
|
+
* Generate a SQL query string for this node.
|
|
1431
|
+
* @returns {string}
|
|
1432
|
+
*/
|
|
1433
|
+
toString() {
|
|
1434
|
+
return `(${this.expr} IN (${this.values.join(", ")}))`;
|
|
1435
|
+
}
|
|
1436
|
+
};
|
|
1437
|
+
|
|
1438
|
+
// src/ast/interval.js
|
|
1439
|
+
var IntervalNode = class extends ExprNode {
|
|
1440
|
+
/**
|
|
1441
|
+
* Instantiate an interval node.
|
|
1442
|
+
* @param {string} name The interval name.
|
|
1443
|
+
* @param {number} [steps=1] The interval steps.
|
|
1444
|
+
*/
|
|
1445
|
+
constructor(name, steps = 1) {
|
|
1446
|
+
super(INTERVAL);
|
|
1447
|
+
this.name = name;
|
|
1448
|
+
this.steps = steps;
|
|
1449
|
+
}
|
|
1450
|
+
/**
|
|
1451
|
+
* Generate a SQL query string for this node.
|
|
1452
|
+
* @returns {string}
|
|
1453
|
+
*/
|
|
1454
|
+
toString() {
|
|
1455
|
+
return `INTERVAL ${this.steps} ${this.name}`;
|
|
1456
|
+
}
|
|
1457
|
+
};
|
|
1458
|
+
|
|
1459
|
+
// src/ast/logical-op.js
|
|
1460
|
+
var LogicalOpNode = class extends ExprNode {
|
|
1461
|
+
/**
|
|
1462
|
+
* Instantiate a logical operator node.
|
|
1463
|
+
* @param {string} op The logical operation.
|
|
1464
|
+
* @param {T[]} clauses The input clause expressions.
|
|
1465
|
+
*/
|
|
1466
|
+
constructor(op, clauses) {
|
|
1467
|
+
super(LOGICAL_OPERATOR);
|
|
1468
|
+
this.op = op;
|
|
1469
|
+
this.clauses = clauses;
|
|
1470
|
+
}
|
|
1471
|
+
/**
|
|
1472
|
+
* Generate a SQL query string for this node.
|
|
1473
|
+
* @returns {string}
|
|
1474
|
+
*/
|
|
1475
|
+
toString() {
|
|
1476
|
+
const c = this.clauses;
|
|
1477
|
+
return c.length === 0 ? "" : c.length === 1 ? `${c[0]}` : `(${c.join(` ${this.op} `)})`;
|
|
1478
|
+
}
|
|
1479
|
+
};
|
|
1480
|
+
var AndNode = class extends LogicalOpNode {
|
|
1481
|
+
/**
|
|
1482
|
+
* Instantiate a logical AND operator node.
|
|
1483
|
+
* @param {T[]} clauses The input clause expressions.
|
|
1484
|
+
*/
|
|
1485
|
+
constructor(clauses) {
|
|
1486
|
+
super("AND", clauses);
|
|
1487
|
+
}
|
|
1488
|
+
};
|
|
1489
|
+
var OrNode = class extends LogicalOpNode {
|
|
1490
|
+
/**
|
|
1491
|
+
* Instantiate a logical OR operator node.
|
|
1492
|
+
* @param {T[]} clauses The input clause expressions.
|
|
1493
|
+
*/
|
|
1494
|
+
constructor(clauses) {
|
|
1495
|
+
super("OR", clauses);
|
|
1496
|
+
}
|
|
1497
|
+
};
|
|
1498
|
+
|
|
1499
|
+
// src/ast/order-by.js
|
|
1500
|
+
var OrderByNode = class extends ExprNode {
|
|
1501
|
+
/**
|
|
1502
|
+
* Instantiate an order by entry node.
|
|
1503
|
+
* @param {ExprNode} expr The expression to order by.
|
|
1504
|
+
* @param {boolean | undefined} [desc] Flag indicating descending order.
|
|
1505
|
+
* @param {boolean | undefined} [nullsFirst] Flag indicating if null
|
|
1506
|
+
* values should be sorted first.
|
|
1507
|
+
*/
|
|
1508
|
+
constructor(expr, desc2, nullsFirst) {
|
|
1509
|
+
super(ORDER_BY);
|
|
1510
|
+
this.expr = expr;
|
|
1511
|
+
this.desc = desc2;
|
|
1512
|
+
this.nullsFirst = nullsFirst;
|
|
1513
|
+
}
|
|
1514
|
+
/**
|
|
1515
|
+
* Generate a SQL query string for this node.
|
|
1516
|
+
* @returns {string}
|
|
1517
|
+
*/
|
|
1518
|
+
toString() {
|
|
1519
|
+
const { expr, desc: desc2, nullsFirst } = this;
|
|
1520
|
+
const dir = desc2 ? " DESC" : desc2 === false ? " ASC" : "";
|
|
1521
|
+
const nf = nullsFirst ? " NULLS FIRST" : nullsFirst === false ? " NULLS LAST" : "";
|
|
1522
|
+
return `${expr}${dir}${nf}`;
|
|
1523
|
+
}
|
|
1524
|
+
};
|
|
1525
|
+
|
|
1526
|
+
// src/ast/unary-op.js
|
|
1527
|
+
var AbstractUnaryOpNode = class extends ExprNode {
|
|
1528
|
+
/**
|
|
1529
|
+
* Instantiate an abstract unary operator node.
|
|
1530
|
+
* @param {string} type The node type.
|
|
1531
|
+
* @param {string} op The operator type.
|
|
1532
|
+
* @param {ExprNode} expr The input expression.
|
|
1533
|
+
*/
|
|
1534
|
+
constructor(type, op, expr) {
|
|
1535
|
+
super(type);
|
|
1536
|
+
this.op = op;
|
|
1537
|
+
this.expr = expr;
|
|
1538
|
+
}
|
|
1539
|
+
};
|
|
1540
|
+
var UnaryOpNode = class extends AbstractUnaryOpNode {
|
|
1541
|
+
/**
|
|
1542
|
+
* Instantiate a unary operator node.
|
|
1543
|
+
* @param {string} op The operator type.
|
|
1544
|
+
* @param {ExprNode} expr The input expression.
|
|
1545
|
+
*/
|
|
1546
|
+
constructor(op, expr) {
|
|
1547
|
+
super(UNARY_OPERATOR, op, expr);
|
|
1548
|
+
}
|
|
1549
|
+
/**
|
|
1550
|
+
* Generate a SQL query string for this node.
|
|
1551
|
+
* @returns {string}
|
|
1552
|
+
*/
|
|
1553
|
+
toString() {
|
|
1554
|
+
return `(${this.op} ${this.expr})`;
|
|
1555
|
+
}
|
|
1556
|
+
};
|
|
1557
|
+
var UnaryPosftixOpNode = class extends AbstractUnaryOpNode {
|
|
1558
|
+
/**
|
|
1559
|
+
* Instantiate a unary operator node.
|
|
1560
|
+
* @param {string} op The operator type.
|
|
1561
|
+
* @param {ExprNode} expr The input expression.
|
|
1562
|
+
*/
|
|
1563
|
+
constructor(op, expr) {
|
|
1564
|
+
super(UNARY_POSTFIX_OPERATOR, op, expr);
|
|
1565
|
+
}
|
|
1566
|
+
/**
|
|
1567
|
+
* Generate a SQL query string for this node.
|
|
1568
|
+
* @returns {string}
|
|
1569
|
+
*/
|
|
1570
|
+
toString() {
|
|
1571
|
+
return `(${this.expr} ${this.op})`;
|
|
1572
|
+
}
|
|
1573
|
+
};
|
|
1574
|
+
|
|
1575
|
+
// src/functions/aggregate.js
|
|
1576
|
+
function argmax(y2, x2) {
|
|
1577
|
+
return aggFn("arg_max", y2, x2);
|
|
1578
|
+
}
|
|
1579
|
+
function argmin(y2, x2) {
|
|
1580
|
+
return aggFn("arg_min", y2, x2);
|
|
1581
|
+
}
|
|
1582
|
+
function arrayAgg(expr) {
|
|
1583
|
+
return aggFn("array_agg", expr);
|
|
1584
|
+
}
|
|
1585
|
+
function avg(expr) {
|
|
1586
|
+
return aggFn("avg", expr);
|
|
1587
|
+
}
|
|
1588
|
+
function corr(x2, y2) {
|
|
1589
|
+
return aggFn("corr", x2, y2);
|
|
1590
|
+
}
|
|
1591
|
+
function count(expr) {
|
|
1592
|
+
return aggFn("count", expr);
|
|
1593
|
+
}
|
|
1594
|
+
function covariance(x2, y2) {
|
|
1595
|
+
return aggFn("covar_samp", x2, y2);
|
|
1596
|
+
}
|
|
1597
|
+
function covarPop(x2, y2) {
|
|
1598
|
+
return aggFn("covar_pop", x2, y2);
|
|
1599
|
+
}
|
|
1600
|
+
function entropy(expr) {
|
|
1601
|
+
return aggFn("entropy", expr);
|
|
1602
|
+
}
|
|
1603
|
+
function first(expr) {
|
|
1604
|
+
return aggFn("first", expr);
|
|
1605
|
+
}
|
|
1606
|
+
function kurtosis(expr) {
|
|
1607
|
+
return aggFn("kurtosis", expr);
|
|
1608
|
+
}
|
|
1609
|
+
function mad(expr) {
|
|
1610
|
+
return aggFn("mad", expr);
|
|
1611
|
+
}
|
|
1612
|
+
function max(expr) {
|
|
1613
|
+
return aggFn("max", expr);
|
|
1614
|
+
}
|
|
1615
|
+
function median(expr) {
|
|
1616
|
+
return aggFn("median", expr);
|
|
1617
|
+
}
|
|
1618
|
+
function min(expr) {
|
|
1619
|
+
return aggFn("min", expr);
|
|
1620
|
+
}
|
|
1621
|
+
function mode(expr) {
|
|
1622
|
+
return aggFn("mode", expr);
|
|
1623
|
+
}
|
|
1624
|
+
function last(expr) {
|
|
1625
|
+
return aggFn("last", expr);
|
|
1626
|
+
}
|
|
1627
|
+
function product(expr) {
|
|
1628
|
+
return aggFn("product", expr);
|
|
1629
|
+
}
|
|
1630
|
+
function quantile(expr, p) {
|
|
1631
|
+
return aggFn("quantile", expr, p);
|
|
1632
|
+
}
|
|
1633
|
+
function regrAvgX(x2, y2) {
|
|
1634
|
+
return aggFn("regr_avgx", x2, y2);
|
|
1635
|
+
}
|
|
1636
|
+
function regrAvgY(x2, y2) {
|
|
1637
|
+
return aggFn("regr_avgy", x2, y2);
|
|
1638
|
+
}
|
|
1639
|
+
function regrCount(x2, y2) {
|
|
1640
|
+
return aggFn("regr_count", x2, y2);
|
|
1641
|
+
}
|
|
1642
|
+
function regrIntercept(x2, y2) {
|
|
1643
|
+
return aggFn("regr_intercept", x2, y2);
|
|
1644
|
+
}
|
|
1645
|
+
function regrR2(x2, y2) {
|
|
1646
|
+
return aggFn("regr_r2", x2, y2);
|
|
1647
|
+
}
|
|
1648
|
+
function regrSXX(x2, y2) {
|
|
1649
|
+
return aggFn("regr_sxx", x2, y2);
|
|
1650
|
+
}
|
|
1651
|
+
function regrSXY(x2, y2) {
|
|
1652
|
+
return aggFn("regr_sxy", x2, y2);
|
|
1653
|
+
}
|
|
1654
|
+
function regrSYY(x2, y2) {
|
|
1655
|
+
return aggFn("regr_syy", x2, y2);
|
|
1656
|
+
}
|
|
1657
|
+
function regrSlope(x2, y2) {
|
|
1658
|
+
return aggFn("regr_slope", x2, y2);
|
|
1659
|
+
}
|
|
1660
|
+
function skewness(expr) {
|
|
1661
|
+
return aggFn("skewness", expr);
|
|
1662
|
+
}
|
|
1663
|
+
function stddev(expr) {
|
|
1664
|
+
return aggFn("stddev", expr);
|
|
1665
|
+
}
|
|
1666
|
+
function stddevPop(expr) {
|
|
1667
|
+
return aggFn("stddev_pop", expr);
|
|
1668
|
+
}
|
|
1669
|
+
function stringAgg(expr) {
|
|
1670
|
+
return aggFn("string_agg", expr);
|
|
1671
|
+
}
|
|
1672
|
+
function sum(expr) {
|
|
1673
|
+
return aggFn("sum", expr);
|
|
1674
|
+
}
|
|
1675
|
+
function variance(expr) {
|
|
1676
|
+
return aggFn("var_samp", expr);
|
|
1677
|
+
}
|
|
1678
|
+
function varPop(expr) {
|
|
1679
|
+
return aggFn("var_pop", expr);
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
// src/functions/case.js
|
|
1683
|
+
function cond(when, then, other) {
|
|
1684
|
+
return when ? new CaseNode(void 0, [new WhenNode(asNode(when), asNode(then))], asNode(other)) : new CaseNode();
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
// src/functions/cast.js
|
|
1688
|
+
function cast(expr, type) {
|
|
1689
|
+
return new CastNode(asNode(expr), type);
|
|
1690
|
+
}
|
|
1691
|
+
function int32(expr) {
|
|
1692
|
+
return cast(expr, "INTEGER");
|
|
1693
|
+
}
|
|
1694
|
+
function float32(expr) {
|
|
1695
|
+
return cast(expr, "FLOAT");
|
|
1696
|
+
}
|
|
1697
|
+
function float64(expr) {
|
|
1698
|
+
return cast(expr, "DOUBLE");
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
// src/functions/datetime.js
|
|
1702
|
+
function interval(unit, steps) {
|
|
1703
|
+
return new IntervalNode(unit, steps);
|
|
1704
|
+
}
|
|
1705
|
+
function epoch_ms(expr) {
|
|
1706
|
+
return fn("epoch_ms", expr);
|
|
1707
|
+
}
|
|
1708
|
+
function dateBin(expr, unit, steps = 1) {
|
|
1709
|
+
return fn("time_bucket", interval(unit, steps), expr);
|
|
1710
|
+
}
|
|
1711
|
+
function dateMonth(expr) {
|
|
1712
|
+
return fn("make_date", 2012, fn("month", expr), 1);
|
|
1713
|
+
}
|
|
1714
|
+
function dateMonthDay(expr) {
|
|
1715
|
+
const d = asNode(expr);
|
|
1716
|
+
return fn("make_date", 2012, fn("month", d), fn("day", d));
|
|
1717
|
+
}
|
|
1718
|
+
function dateDay(expr) {
|
|
1719
|
+
return fn("make_date", 2012, 1, fn("day", expr));
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
// src/functions/numeric.js
|
|
1723
|
+
function isNaN(expr) {
|
|
1724
|
+
return fn("isnan", expr);
|
|
1725
|
+
}
|
|
1726
|
+
function isFinite(expr) {
|
|
1727
|
+
return fn("isfinite", expr);
|
|
1728
|
+
}
|
|
1729
|
+
function isInfinite(expr) {
|
|
1730
|
+
return fn("isinf", expr);
|
|
1731
|
+
}
|
|
1732
|
+
function greatest(...expr) {
|
|
1733
|
+
return fn("greatest", ...expr);
|
|
1734
|
+
}
|
|
1735
|
+
function least(...expr) {
|
|
1736
|
+
return fn("least", ...expr);
|
|
1737
|
+
}
|
|
1738
|
+
function exp(expr) {
|
|
1739
|
+
return fn("exp", expr);
|
|
1740
|
+
}
|
|
1741
|
+
function log(expr) {
|
|
1742
|
+
return fn("log", expr);
|
|
1743
|
+
}
|
|
1744
|
+
function ln(expr) {
|
|
1745
|
+
return fn("ln", expr);
|
|
1746
|
+
}
|
|
1747
|
+
function sign(expr) {
|
|
1748
|
+
return fn("sign", expr);
|
|
1749
|
+
}
|
|
1750
|
+
function abs(expr) {
|
|
1751
|
+
return fn("abs", expr);
|
|
1752
|
+
}
|
|
1753
|
+
function sqrt(expr) {
|
|
1754
|
+
return fn("sqrt", expr);
|
|
1755
|
+
}
|
|
1756
|
+
function ceil(expr) {
|
|
1757
|
+
return fn("ceil", expr);
|
|
1758
|
+
}
|
|
1759
|
+
function floor(expr) {
|
|
1760
|
+
return fn("floor", expr);
|
|
1761
|
+
}
|
|
1762
|
+
function round(expr, places) {
|
|
1763
|
+
return fn("round", expr, places);
|
|
1764
|
+
}
|
|
1765
|
+
function trunc(expr) {
|
|
1766
|
+
return fn("trunc", expr);
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
// src/functions/operators.js
|
|
1770
|
+
function unaryOp(op, expr) {
|
|
1771
|
+
return new UnaryOpNode(op, asNode(expr));
|
|
1772
|
+
}
|
|
1773
|
+
function unaryPostfixOp(op, expr) {
|
|
1774
|
+
return new UnaryPosftixOpNode(op, asNode(expr));
|
|
1775
|
+
}
|
|
1776
|
+
function binaryOp(op, left, right) {
|
|
1777
|
+
return new BinaryOpNode(op, asNode(left), asNode(right));
|
|
1778
|
+
}
|
|
1779
|
+
function betweenOp(expr, extent, negate = false) {
|
|
1780
|
+
const Op = negate ? NotBetweenOpNode : BetweenOpNode;
|
|
1781
|
+
return new Op(asNode(expr), extent?.map(asNode));
|
|
1782
|
+
}
|
|
1783
|
+
function and(...clauses) {
|
|
1784
|
+
return new AndNode(exprList(clauses));
|
|
1785
|
+
}
|
|
1786
|
+
function or(...clauses) {
|
|
1787
|
+
return new OrNode(exprList(clauses));
|
|
1788
|
+
}
|
|
1789
|
+
function not(expr) {
|
|
1790
|
+
return unaryOp("NOT", expr);
|
|
1791
|
+
}
|
|
1792
|
+
function isNull(expr) {
|
|
1793
|
+
return unaryPostfixOp("IS NULL", expr);
|
|
1794
|
+
}
|
|
1795
|
+
function isNotNull(expr) {
|
|
1796
|
+
return unaryPostfixOp("IS NOT NULL", expr);
|
|
1797
|
+
}
|
|
1798
|
+
function bitNot(expr) {
|
|
1799
|
+
return unaryOp("~", expr);
|
|
1800
|
+
}
|
|
1801
|
+
function bitAnd(left, right) {
|
|
1802
|
+
return binaryOp("&", left, right);
|
|
1803
|
+
}
|
|
1804
|
+
function bitOr(left, right) {
|
|
1805
|
+
return binaryOp("|", left, right);
|
|
1806
|
+
}
|
|
1807
|
+
function bitLeft(left, right) {
|
|
1808
|
+
return binaryOp("<<", left, right);
|
|
1809
|
+
}
|
|
1810
|
+
function bitRight(left, right) {
|
|
1811
|
+
return binaryOp(">>", left, right);
|
|
1812
|
+
}
|
|
1813
|
+
function add(left, right) {
|
|
1814
|
+
return binaryOp("+", left, right);
|
|
1815
|
+
}
|
|
1816
|
+
function sub(left, right) {
|
|
1817
|
+
return binaryOp("-", left, right);
|
|
1818
|
+
}
|
|
1819
|
+
function mul(left, right) {
|
|
1820
|
+
return binaryOp("*", left, right);
|
|
1821
|
+
}
|
|
1822
|
+
function div(left, right) {
|
|
1823
|
+
return binaryOp("/", left, right);
|
|
1824
|
+
}
|
|
1825
|
+
function idiv(left, right) {
|
|
1826
|
+
return binaryOp("//", left, right);
|
|
1827
|
+
}
|
|
1828
|
+
function mod(left, right) {
|
|
1829
|
+
return binaryOp("%", left, right);
|
|
1830
|
+
}
|
|
1831
|
+
function pow(left, right) {
|
|
1832
|
+
return binaryOp("**", left, right);
|
|
1833
|
+
}
|
|
1834
|
+
function eq(left, right) {
|
|
1835
|
+
return binaryOp("=", left, right);
|
|
1836
|
+
}
|
|
1837
|
+
function neq(left, right) {
|
|
1838
|
+
return binaryOp("<>", left, right);
|
|
1839
|
+
}
|
|
1840
|
+
function lt(left, right) {
|
|
1841
|
+
return binaryOp("<", left, right);
|
|
1842
|
+
}
|
|
1843
|
+
function gt(left, right) {
|
|
1844
|
+
return binaryOp(">", left, right);
|
|
1845
|
+
}
|
|
1846
|
+
function lte(left, right) {
|
|
1847
|
+
return binaryOp("<=", left, right);
|
|
1848
|
+
}
|
|
1849
|
+
function gte(left, right) {
|
|
1850
|
+
return binaryOp(">=", left, right);
|
|
1851
|
+
}
|
|
1852
|
+
function isDistinct(left, right) {
|
|
1853
|
+
return binaryOp("IS DISTINCT FROM", left, right);
|
|
1854
|
+
}
|
|
1855
|
+
function isNotDistinct(left, right) {
|
|
1856
|
+
return binaryOp("IS NOT DISTINCT FROM", left, right);
|
|
1857
|
+
}
|
|
1858
|
+
function isBetween(expr, extent) {
|
|
1859
|
+
return betweenOp(expr, extent, false);
|
|
1860
|
+
}
|
|
1861
|
+
function isNotBetween(expr, extent) {
|
|
1862
|
+
return betweenOp(expr, extent, true);
|
|
1863
|
+
}
|
|
1864
|
+
function isIn(expr, values) {
|
|
1865
|
+
return new InOpNode(asNode(expr), values.map(asNode));
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
// src/functions/order-by.js
|
|
1869
|
+
function asc(expr, nullsFirst) {
|
|
1870
|
+
return new OrderByNode(asNode(expr), false, nullsFirst);
|
|
1871
|
+
}
|
|
1872
|
+
function desc(expr, nullsFirst) {
|
|
1873
|
+
return new OrderByNode(asNode(expr), true, nullsFirst);
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
// src/functions/spatial.js
|
|
1877
|
+
function geojson(expr) {
|
|
1878
|
+
return fn("st_asgeojson", expr);
|
|
1879
|
+
}
|
|
1880
|
+
function x(expr) {
|
|
1881
|
+
return fn("st_x", expr);
|
|
1882
|
+
}
|
|
1883
|
+
function y(expr) {
|
|
1884
|
+
return fn("st_y", expr);
|
|
1885
|
+
}
|
|
1886
|
+
function centroid(expr) {
|
|
1887
|
+
return fn("st_centroid", expr);
|
|
1888
|
+
}
|
|
1889
|
+
function centroidX(expr) {
|
|
1890
|
+
return x(centroid(expr));
|
|
1891
|
+
}
|
|
1892
|
+
function centroidY(expr) {
|
|
1893
|
+
return y(centroid(expr));
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
// src/functions/sql-template-tag.js
|
|
1897
|
+
function sql(strings, ...exprs) {
|
|
1898
|
+
return new FragmentNode(parseSQL(strings, exprs));
|
|
1899
|
+
}
|
|
1900
|
+
function parseSQL(strings, exprs) {
|
|
1901
|
+
const spans = [strings[0]];
|
|
1902
|
+
const n = exprs.length;
|
|
1903
|
+
for (let i = 0, k = 0; i < n; ) {
|
|
1904
|
+
const e = exprs[i];
|
|
1905
|
+
if (isNode(e)) {
|
|
1906
|
+
spans[++k] = e;
|
|
1907
|
+
} else if (isParamLike(e)) {
|
|
1908
|
+
spans[++k] = new ParamNode(e);
|
|
1094
1909
|
} else {
|
|
1095
|
-
|
|
1096
|
-
return this;
|
|
1910
|
+
spans[k] += isString(e) ? e : literal(e);
|
|
1097
1911
|
}
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
if (arguments.length === 0) {
|
|
1102
|
-
return query.offset;
|
|
1912
|
+
const s = strings[++i];
|
|
1913
|
+
if (isNode(spans[k])) {
|
|
1914
|
+
spans[++k] = s;
|
|
1103
1915
|
} else {
|
|
1104
|
-
|
|
1105
|
-
return this;
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
get subqueries() {
|
|
1109
|
-
const { queries, cteFor } = this;
|
|
1110
|
-
if (cteFor) queries.forEach((q) => q.cteFor = cteFor);
|
|
1111
|
-
return queries;
|
|
1112
|
-
}
|
|
1113
|
-
toString() {
|
|
1114
|
-
const { op, queries, query: { orderby, limit, offset } } = this;
|
|
1115
|
-
const sql2 = [queries.join(` ${op} `)];
|
|
1116
|
-
if (orderby.length) {
|
|
1117
|
-
sql2.push(`ORDER BY ${orderby.join(", ")}`);
|
|
1118
|
-
}
|
|
1119
|
-
if (Number.isFinite(limit)) {
|
|
1120
|
-
sql2.push(`LIMIT ${limit}`);
|
|
1121
|
-
}
|
|
1122
|
-
if (Number.isFinite(offset)) {
|
|
1123
|
-
sql2.push(`OFFSET ${offset}`);
|
|
1916
|
+
spans[k] += s;
|
|
1124
1917
|
}
|
|
1125
|
-
return sql2.join(" ");
|
|
1126
1918
|
}
|
|
1127
|
-
|
|
1128
|
-
function isQuery(value) {
|
|
1129
|
-
return value instanceof Query || value instanceof SetOperation;
|
|
1919
|
+
return spans.filter((s) => s).map((s) => isString(s) ? new VerbatimNode(s) : s);
|
|
1130
1920
|
}
|
|
1131
|
-
|
|
1132
|
-
|
|
1921
|
+
|
|
1922
|
+
// src/functions/string.js
|
|
1923
|
+
function strFn(name, expr, ...args) {
|
|
1924
|
+
return fn(name, expr, ...argsList(args).map(asLiteral));
|
|
1133
1925
|
}
|
|
1134
|
-
function
|
|
1135
|
-
return
|
|
1926
|
+
function regexp_matches(string, pattern, options) {
|
|
1927
|
+
return strFn("regexp_matches", string, pattern, options);
|
|
1136
1928
|
}
|
|
1137
|
-
function
|
|
1138
|
-
return
|
|
1929
|
+
function contains(string, search_string) {
|
|
1930
|
+
return strFn("contains", string, search_string);
|
|
1931
|
+
}
|
|
1932
|
+
function prefix(string, search_string) {
|
|
1933
|
+
return strFn("starts_with", string, search_string);
|
|
1934
|
+
}
|
|
1935
|
+
function suffix(string, search_string) {
|
|
1936
|
+
return strFn("ends_with", string, search_string);
|
|
1937
|
+
}
|
|
1938
|
+
function lower(string) {
|
|
1939
|
+
return strFn("lower", string);
|
|
1940
|
+
}
|
|
1941
|
+
function upper(string) {
|
|
1942
|
+
return strFn("upper", string);
|
|
1943
|
+
}
|
|
1944
|
+
function length(value) {
|
|
1945
|
+
return strFn("length", value);
|
|
1139
1946
|
}
|
|
1140
1947
|
|
|
1141
|
-
// src/
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
return {
|
|
1145
|
-
apply: identity,
|
|
1146
|
-
invert: identity,
|
|
1147
|
-
sqlApply: asColumn,
|
|
1148
|
-
sqlInvert: identity
|
|
1149
|
-
};
|
|
1948
|
+
// src/functions/window.js
|
|
1949
|
+
function row_number() {
|
|
1950
|
+
return winFn("row_number");
|
|
1150
1951
|
}
|
|
1151
|
-
function
|
|
1152
|
-
|
|
1153
|
-
return {
|
|
1154
|
-
apply: Math.log,
|
|
1155
|
-
invert: Math.exp,
|
|
1156
|
-
sqlApply: (c) => sql`LN(${asColumn(c)})`,
|
|
1157
|
-
sqlInvert: (c) => sql`EXP(${c})`
|
|
1158
|
-
};
|
|
1159
|
-
} else if (base === 10) {
|
|
1160
|
-
return {
|
|
1161
|
-
apply: Math.log10,
|
|
1162
|
-
invert: (x2) => Math.pow(10, x2),
|
|
1163
|
-
sqlApply: (c) => sql`LOG(${asColumn(c)})`,
|
|
1164
|
-
sqlInvert: (c) => sql`POW(10, ${c})`
|
|
1165
|
-
};
|
|
1166
|
-
} else {
|
|
1167
|
-
const b = +base;
|
|
1168
|
-
return {
|
|
1169
|
-
apply: (x2) => Math.log(x2) / Math.log(b),
|
|
1170
|
-
invert: (x2) => Math.pow(b, x2),
|
|
1171
|
-
sqlApply: (c) => sql`LN(${asColumn(c)}) / LN(${b})`,
|
|
1172
|
-
sqlInvert: (c) => sql`POW(${b}, ${c})`
|
|
1173
|
-
};
|
|
1174
|
-
}
|
|
1952
|
+
function rank() {
|
|
1953
|
+
return winFn("rank");
|
|
1175
1954
|
}
|
|
1176
|
-
function
|
|
1177
|
-
|
|
1178
|
-
return {
|
|
1179
|
-
apply: (x2) => Math.sign(x2) * Math.log1p(Math.abs(x2)),
|
|
1180
|
-
invert: (x2) => Math.sign(x2) * Math.exp(Math.abs(x2) - _),
|
|
1181
|
-
sqlApply: (c) => (c = asColumn(c), sql`SIGN(${c}) * LN(${_} + ABS(${c}))`),
|
|
1182
|
-
sqlInvert: (c) => sql`SIGN(${c}) * (EXP(ABS(${c})) - ${_})`
|
|
1183
|
-
};
|
|
1955
|
+
function dense_rank() {
|
|
1956
|
+
return winFn("dense_rank");
|
|
1184
1957
|
}
|
|
1185
|
-
function
|
|
1186
|
-
return
|
|
1187
|
-
apply: (x2) => Math.sign(x2) * Math.sqrt(Math.abs(x2)),
|
|
1188
|
-
invert: (x2) => Math.sign(x2) * x2 * x2,
|
|
1189
|
-
sqlApply: (c) => (c = asColumn(c), sql`SIGN(${c}) * SQRT(ABS(${c}))`),
|
|
1190
|
-
sqlInvert: (c) => sql`SIGN(${c}) * (${c}) ** 2`
|
|
1191
|
-
};
|
|
1958
|
+
function percent_rank() {
|
|
1959
|
+
return winFn("percent_rank");
|
|
1192
1960
|
}
|
|
1193
|
-
function
|
|
1194
|
-
|
|
1195
|
-
return {
|
|
1196
|
-
apply: (x2) => Math.sign(x2) * Math.pow(Math.abs(x2), e),
|
|
1197
|
-
invert: (x2) => Math.sign(x2) * Math.pow(Math.abs(x2), 1 / e),
|
|
1198
|
-
sqlApply: (c) => (c = asColumn(c), sql`SIGN(${c}) * POW(ABS(${c}), ${e})`),
|
|
1199
|
-
sqlInvert: (c) => sql`SIGN(${c}) * POW(ABS(${c}), 1/${e})`
|
|
1200
|
-
};
|
|
1961
|
+
function cume_dist() {
|
|
1962
|
+
return winFn("cume_dist");
|
|
1201
1963
|
}
|
|
1202
|
-
function
|
|
1203
|
-
return
|
|
1204
|
-
apply: (x2) => +x2,
|
|
1205
|
-
invert: (x2) => new Date(x2),
|
|
1206
|
-
sqlApply: (c) => c instanceof Date ? +c : epoch_ms(asColumn(c)),
|
|
1207
|
-
sqlInvert: identity
|
|
1208
|
-
};
|
|
1964
|
+
function ntile(num_buckets) {
|
|
1965
|
+
return winFn("ntile", num_buckets);
|
|
1209
1966
|
}
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1967
|
+
function lag(expr, offset, defaultValue) {
|
|
1968
|
+
return winFn("lag", expr, offset, defaultValue);
|
|
1969
|
+
}
|
|
1970
|
+
function lead(expr, offset, defaultValue) {
|
|
1971
|
+
return winFn("lead", expr, offset, defaultValue);
|
|
1972
|
+
}
|
|
1973
|
+
function first_value(expr) {
|
|
1974
|
+
return winFn("first_value", expr);
|
|
1975
|
+
}
|
|
1976
|
+
function last_value(expr) {
|
|
1977
|
+
return winFn("last_value", expr);
|
|
1978
|
+
}
|
|
1979
|
+
function nth_value(expr, nth) {
|
|
1980
|
+
return winFn("nth_value", expr, nth);
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
// src/visit/recurse.js
|
|
1984
|
+
var recurse = {
|
|
1985
|
+
[AGGREGATE]: ["args", "filter"],
|
|
1986
|
+
[BETWEEN_OPERATOR]: ["expr", "extent"],
|
|
1987
|
+
[BINARY_OPERATOR]: ["left", "right"],
|
|
1988
|
+
[CASE]: ["expr", "_when", "_else"],
|
|
1989
|
+
[CAST]: ["expr"],
|
|
1990
|
+
[COLUMN_PARAM]: ["param", "table"],
|
|
1991
|
+
[COLUMN_REF]: ["table"],
|
|
1992
|
+
[DESCRIBE_QUERY]: ["query"],
|
|
1993
|
+
[EXPRESSION]: ["node"],
|
|
1994
|
+
[FRAGMENT]: ["spans"],
|
|
1995
|
+
[FROM_CLAUSE]: ["expr"],
|
|
1996
|
+
[FUNCTION]: ["args"],
|
|
1997
|
+
[IN_OPERATOR]: ["expr", "values"],
|
|
1998
|
+
[LOGICAL_OPERATOR]: ["clauses"],
|
|
1999
|
+
[NOT_BETWEEN_OPERATOR]: ["expr", "extent"],
|
|
2000
|
+
[ORDER_BY]: ["expr"],
|
|
2001
|
+
[PARAM]: ["value"],
|
|
2002
|
+
[SELECT_CLAUSE]: ["expr"],
|
|
2003
|
+
[SELECT_QUERY]: ["_with", "_select", "_from", "_where", "_sample", "_groupby", "_having", "_window", "_qualify", "_orderby"],
|
|
2004
|
+
[SET_OPERATION]: ["subqueries", "_orderby"],
|
|
2005
|
+
[UNARY_OPERATOR]: ["expr"],
|
|
2006
|
+
[WHEN]: ["when", "then"],
|
|
2007
|
+
[WINDOW]: ["func", "def"],
|
|
2008
|
+
[WINDOW_CLAUSE]: ["def"],
|
|
2009
|
+
[WINDOW_DEF]: ["partition", "order", "frame"],
|
|
2010
|
+
[WINDOW_FRAME]: ["extent"]
|
|
1219
2011
|
};
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
2012
|
+
|
|
2013
|
+
// src/visit/rewrite.js
|
|
2014
|
+
function rewrite(node, map) {
|
|
2015
|
+
if (map.has(node)) {
|
|
2016
|
+
return map.get(node);
|
|
2017
|
+
} else if (isNode(node)) {
|
|
2018
|
+
const props = recurse[node.type];
|
|
2019
|
+
const n = props?.length ?? 0;
|
|
2020
|
+
for (let i = 0; i < n; ++i) {
|
|
2021
|
+
const prop = props[i];
|
|
2022
|
+
const child = node[prop];
|
|
2023
|
+
if (Array.isArray(child)) {
|
|
2024
|
+
const m = child.length;
|
|
2025
|
+
for (let j = 0; j < m; ++j) {
|
|
2026
|
+
child[j] = rewrite(child[j], map);
|
|
2027
|
+
}
|
|
2028
|
+
} else if (child) {
|
|
2029
|
+
node[prop] = rewrite(child, map);
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
return node;
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
// src/visit/walk.js
|
|
2037
|
+
function walk(node, visit) {
|
|
2038
|
+
if (!isNode(node)) return;
|
|
2039
|
+
const result = visit(node);
|
|
2040
|
+
if (result) return result;
|
|
2041
|
+
const props = recurse[node.type];
|
|
2042
|
+
const n = props?.length ?? 0;
|
|
2043
|
+
for (let i = 0; i < n; ++i) {
|
|
2044
|
+
const value = node[props[i]];
|
|
2045
|
+
if (Array.isArray(value)) {
|
|
2046
|
+
const m = value.length;
|
|
2047
|
+
for (let j = 0; j < m; ++j) {
|
|
2048
|
+
if (value[j] && +walk(value[j], visit) < 0) {
|
|
2049
|
+
return result;
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
} else if (value && +walk(value, visit) < 0) {
|
|
2053
|
+
return -1;
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
// src/visit/visitors.js
|
|
2059
|
+
var aggrRegExp = new RegExp(`^(${aggregateNames.join("|")})$`);
|
|
2060
|
+
var funcRegExp = /(\\'|\\"|"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|\w+\()/g;
|
|
2061
|
+
function hasVerbatimAggregate(s) {
|
|
2062
|
+
return s.split(funcRegExp).some((tok) => tok.endsWith("(") && aggrRegExp.test(tok.slice(0, -1)));
|
|
2063
|
+
}
|
|
2064
|
+
function isAggregateExpression(root) {
|
|
2065
|
+
let agg = 0;
|
|
2066
|
+
walk(root, (node) => {
|
|
2067
|
+
switch (node.type) {
|
|
2068
|
+
case WINDOW:
|
|
2069
|
+
return -1;
|
|
2070
|
+
// aggs can't include windows
|
|
2071
|
+
case AGGREGATE:
|
|
2072
|
+
agg |= 1;
|
|
2073
|
+
return -1;
|
|
2074
|
+
case FRAGMENT:
|
|
2075
|
+
case VERBATIM: {
|
|
2076
|
+
let s = `${node}`.toLowerCase();
|
|
2077
|
+
const sub2 = s.indexOf("(select ");
|
|
2078
|
+
if (sub2 >= 0) s = s.slice(0, sub2);
|
|
2079
|
+
if (s.includes(") over ")) return -1;
|
|
2080
|
+
if (hasVerbatimAggregate(s)) {
|
|
2081
|
+
agg |= 2;
|
|
2082
|
+
return -1;
|
|
2083
|
+
}
|
|
2084
|
+
return 1;
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
});
|
|
2088
|
+
return agg;
|
|
2089
|
+
}
|
|
2090
|
+
function collectAggregates(root) {
|
|
2091
|
+
const aggs = /* @__PURE__ */ new Set();
|
|
2092
|
+
walk(root, (node) => {
|
|
2093
|
+
if (node.type === AGGREGATE) {
|
|
2094
|
+
aggs.add(node);
|
|
2095
|
+
}
|
|
2096
|
+
});
|
|
2097
|
+
return Array.from(aggs);
|
|
2098
|
+
}
|
|
2099
|
+
function collectColumns(root) {
|
|
2100
|
+
const cols = {};
|
|
2101
|
+
walk(root, (node) => {
|
|
2102
|
+
if (node.type === COLUMN_REF) {
|
|
2103
|
+
cols[node] = node;
|
|
2104
|
+
}
|
|
2105
|
+
});
|
|
2106
|
+
return Object.values(cols);
|
|
2107
|
+
}
|
|
2108
|
+
function collectParams(root) {
|
|
2109
|
+
const params = /* @__PURE__ */ new Set();
|
|
2110
|
+
walk(root, (node) => {
|
|
2111
|
+
if (node.type === PARAM) {
|
|
2112
|
+
params.add(
|
|
2113
|
+
/** @type {import('../ast/param.js').ParamNode} */
|
|
2114
|
+
node.param
|
|
2115
|
+
);
|
|
2116
|
+
}
|
|
2117
|
+
});
|
|
2118
|
+
return Array.from(params);
|
|
1223
2119
|
}
|
|
1224
2120
|
|
|
1225
2121
|
// src/load/create.js
|
|
1226
|
-
function
|
|
2122
|
+
function createTable(name, query, {
|
|
1227
2123
|
replace = false,
|
|
1228
|
-
temp =
|
|
2124
|
+
temp = false,
|
|
1229
2125
|
view = false
|
|
1230
2126
|
} = {}) {
|
|
1231
2127
|
return "CREATE" + (replace ? " OR REPLACE " : " ") + (temp ? "TEMP " : "") + (view ? "VIEW" : "TABLE") + (replace ? " " : " IF NOT EXISTS ") + name + " AS " + query;
|
|
1232
2128
|
}
|
|
2129
|
+
function createSchema(name, {
|
|
2130
|
+
strict = false
|
|
2131
|
+
} = {}) {
|
|
2132
|
+
return "CREATE SCHEMA " + (strict ? "" : "IF NOT EXISTS ") + name;
|
|
2133
|
+
}
|
|
1233
2134
|
|
|
1234
2135
|
// src/load/extension.js
|
|
1235
2136
|
function loadExtension(name) {
|
|
@@ -1252,7 +2153,7 @@ function sqlFrom(data, {
|
|
|
1252
2153
|
}
|
|
1253
2154
|
const subq = [];
|
|
1254
2155
|
for (const datum of data) {
|
|
1255
|
-
const sel = keys.map((k) => `${
|
|
2156
|
+
const sel = keys.map((k) => `${asLiteral(datum[k])} AS "${columns[k]}"`);
|
|
1256
2157
|
subq.push(`(SELECT ${sel.join(", ")})`);
|
|
1257
2158
|
}
|
|
1258
2159
|
return subq.join(" UNION ALL ");
|
|
@@ -1265,13 +2166,13 @@ function load(method, tableName, fileName, options = {}, defaults = {}) {
|
|
|
1265
2166
|
const read = `${method}('${fileName}'${params ? ", " + params : ""})`;
|
|
1266
2167
|
const filter = where ? ` WHERE ${where}` : "";
|
|
1267
2168
|
const query = `SELECT ${select.join(", ")} FROM ${read}${filter}`;
|
|
1268
|
-
return
|
|
2169
|
+
return createTable(tableName, query, { view, temp, replace });
|
|
1269
2170
|
}
|
|
1270
2171
|
function loadCSV(tableName, fileName, options) {
|
|
1271
2172
|
return load("read_csv", tableName, fileName, options, { auto_detect: true, sample_size: -1 });
|
|
1272
2173
|
}
|
|
1273
2174
|
function loadJSON(tableName, fileName, options) {
|
|
1274
|
-
return load("read_json", tableName, fileName, options, { auto_detect: true,
|
|
2175
|
+
return load("read_json", tableName, fileName, options, { auto_detect: true, format: "auto" });
|
|
1275
2176
|
}
|
|
1276
2177
|
function loadParquet(tableName, fileName, options) {
|
|
1277
2178
|
return load("read_parquet", tableName, fileName, options);
|
|
@@ -1288,7 +2189,7 @@ function loadObjects(tableName, data, options = {}) {
|
|
|
1288
2189
|
const { select = ["*"], ...opt } = options;
|
|
1289
2190
|
const values = sqlFrom(data);
|
|
1290
2191
|
const query = select.length === 1 && select[0] === "*" ? values : `SELECT ${select} FROM ${values}`;
|
|
1291
|
-
return
|
|
2192
|
+
return createTable(tableName, query, opt);
|
|
1292
2193
|
}
|
|
1293
2194
|
function parameters(options) {
|
|
1294
2195
|
return Object.entries(options).map(([key, value]) => `${key}=${toDuckDBValue(value)}`).join(", ");
|
|
@@ -1312,32 +2213,283 @@ function toDuckDBValue(value) {
|
|
|
1312
2213
|
return value;
|
|
1313
2214
|
}
|
|
1314
2215
|
}
|
|
2216
|
+
|
|
2217
|
+
// src/transforms/bin-1d.js
|
|
2218
|
+
function bin1d(x2, lo, hi, bins, reverse) {
|
|
2219
|
+
const diff = reverse ? sub(hi, float64(x2)) : sub(float64(x2), lo);
|
|
2220
|
+
const scale = hi === lo ? 0 : bins / (hi - lo);
|
|
2221
|
+
return scale ? mul(diff, float64(scale)) : diff;
|
|
2222
|
+
}
|
|
2223
|
+
|
|
2224
|
+
// src/transforms/bin-2d.js
|
|
2225
|
+
function bin2d(q, xp, yp, aggs, xn, groupby) {
|
|
2226
|
+
return q.select({
|
|
2227
|
+
index: add(int32(floor(xp)), mul(int32(floor(yp)), xn)),
|
|
2228
|
+
...aggs
|
|
2229
|
+
}).groupby("index", groupby);
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
// src/transforms/bin-linear-1d.js
|
|
2233
|
+
function binLinear1d(query, x2, weight) {
|
|
2234
|
+
const w = weight ? (x3) => mul(x3, weight) : (x3) => x3;
|
|
2235
|
+
const p0 = floor(x2);
|
|
2236
|
+
const p1 = add(p0, 1);
|
|
2237
|
+
return Query.from(Query.unionAll(
|
|
2238
|
+
query.clone().select({ i: int32(p0), w: w(sub(p1, x2)) }),
|
|
2239
|
+
query.clone().select({ i: int32(p1), w: w(sub(x2, p0)) })
|
|
2240
|
+
)).select({ index: "i", density: sum("w") }).groupby("index").having(neq("density", 0));
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
// src/transforms/bin-linear-2d.js
|
|
2244
|
+
function identity(x2) {
|
|
2245
|
+
return x2;
|
|
2246
|
+
}
|
|
2247
|
+
function binLinear2d(q, xp, yp, weight, xn, groupby) {
|
|
2248
|
+
const w = weight ? (x2) => mul(x2, weight) : identity;
|
|
2249
|
+
const subq = (i, w2) => q.clone().select({ xp, yp, i, w: w2 });
|
|
2250
|
+
const index = (x2, y2) => add(x2, mul(y2, xn));
|
|
2251
|
+
const xu = int32(floor(xp));
|
|
2252
|
+
const yu = int32(floor(yp));
|
|
2253
|
+
const xv = add(xu, 1);
|
|
2254
|
+
const yv = add(yu, 1);
|
|
2255
|
+
const xpu = sub(xp, xu);
|
|
2256
|
+
const xvp = sub(xv, xp);
|
|
2257
|
+
const ypu = sub(yp, yu);
|
|
2258
|
+
const yvp = sub(yv, yp);
|
|
2259
|
+
return Query.from(Query.unionAll(
|
|
2260
|
+
// grid[xu + yu * xn] += (xv - xp) * (yv - yp) * wi
|
|
2261
|
+
subq(index(xu, yu), w(mul(xvp, yvp))),
|
|
2262
|
+
// grid[xu + yv * xn] += (xv - xp) * (yp - yu) * wi
|
|
2263
|
+
subq(index(xu, yv), w(mul(xvp, ypu))),
|
|
2264
|
+
// grid[xv + yu * xn] += (xp - xu) * (yv - yp) * wi
|
|
2265
|
+
subq(index(xv, yu), w(mul(xpu, yvp))),
|
|
2266
|
+
// grid[xv + yv * xn] += (xp - xu) * (yp - yu) * wi
|
|
2267
|
+
subq(index(xv, yv), w(mul(xpu, ypu)))
|
|
2268
|
+
)).select({ index: "i", density: sum("w") }, groupby).groupby("index", groupby).having(neq("density", 0));
|
|
2269
|
+
}
|
|
2270
|
+
|
|
2271
|
+
// src/transforms/line-density.js
|
|
2272
|
+
function lineDensity(q, x2, y2, z, xn, yn, groupby = [], normalize = true) {
|
|
2273
|
+
q.select({
|
|
2274
|
+
x: int32(floor(x2)),
|
|
2275
|
+
y: int32(floor(y2))
|
|
2276
|
+
});
|
|
2277
|
+
const groups = groupby.concat(z);
|
|
2278
|
+
const pairs = Query.from(q).select(groups, {
|
|
2279
|
+
x0: "x",
|
|
2280
|
+
y0: "y",
|
|
2281
|
+
dx: sub(lead("x").over("sw"), "x"),
|
|
2282
|
+
dy: sub(lead("y").over("sw"), "y")
|
|
2283
|
+
}).window({
|
|
2284
|
+
sw: over().partitionby(groups).orderby(asc("x"))
|
|
2285
|
+
}).qualify([
|
|
2286
|
+
or(lt("x0", xn), lt(add("x0", "dx"), xn)),
|
|
2287
|
+
or(lt("y0", yn), lt(add("y0", "dy"), yn)),
|
|
2288
|
+
or(gt("x0", 0), gt(add("x0", "dx"), 0)),
|
|
2289
|
+
or(gt("y0", 0), gt(add("y0", "dy"), 0))
|
|
2290
|
+
]);
|
|
2291
|
+
const num = Query.select({ x: greatest(max(abs("dx")), max(abs("dy"))) }).from("pairs");
|
|
2292
|
+
const indices = Query.select({
|
|
2293
|
+
i: int32(sql`UNNEST(range((${num})))`)
|
|
2294
|
+
});
|
|
2295
|
+
const raster = Query.unionAll(
|
|
2296
|
+
Query.select(groups, {
|
|
2297
|
+
x: add("x0", "i"),
|
|
2298
|
+
y: add("y0", int32(round(div(mul("i", "dy"), "dx"))))
|
|
2299
|
+
}).from("pairs", "indices").where([lte(abs("dy"), abs("dx")), lt("i", abs("dx"))]),
|
|
2300
|
+
Query.select(groups, {
|
|
2301
|
+
x: add("x0", int32(round(div(mul(mul(sign("dy"), "i"), "dx"), "dy")))),
|
|
2302
|
+
y: add("y0", mul(sign("dy"), "i"))
|
|
2303
|
+
}).from("pairs", "indices").where([gt(abs("dy"), abs("dx")), lt("i", abs("dy"))]),
|
|
2304
|
+
Query.select(groups, { x: "x0", y: "y0" }).from("pairs").where(isNull("dx"))
|
|
2305
|
+
);
|
|
2306
|
+
const points = Query.from("raster").select(
|
|
2307
|
+
groups,
|
|
2308
|
+
"x",
|
|
2309
|
+
"y",
|
|
2310
|
+
normalize ? { w: div(1, count().partitionby(["x"].concat(groups))) } : null
|
|
2311
|
+
).where([lte(0, "x"), lt("x", xn), lte(0, "y"), lt("y", yn)]);
|
|
2312
|
+
return Query.with({ pairs, indices, raster, points }).from("points").select(groupby, {
|
|
2313
|
+
index: add("x", mul("y", int32(xn))),
|
|
2314
|
+
density: normalize ? sum("w") : count()
|
|
2315
|
+
}).groupby("index", groupby);
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2318
|
+
// src/transforms/m4.js
|
|
2319
|
+
function m4(input, bin, x2, y2, groups = []) {
|
|
2320
|
+
const pixel = int32(floor(bin));
|
|
2321
|
+
const q = (sel) => Query.from(input).select(sel).groupby(pixel, groups);
|
|
2322
|
+
return Query.union(
|
|
2323
|
+
q([{ [x2]: min(x2), [y2]: argmin(y2, x2) }, ...groups]),
|
|
2324
|
+
q([{ [x2]: max(x2), [y2]: argmax(y2, x2) }, ...groups]),
|
|
2325
|
+
q([{ [x2]: argmin(x2, y2), [y2]: min(y2) }, ...groups]),
|
|
2326
|
+
q([{ [x2]: argmax(x2, y2), [y2]: max(y2) }, ...groups])
|
|
2327
|
+
).orderby(groups, x2);
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2330
|
+
// src/transforms/scales.js
|
|
2331
|
+
var identity2 = (x2) => x2;
|
|
2332
|
+
function scaleLinear() {
|
|
2333
|
+
return {
|
|
2334
|
+
apply: identity2,
|
|
2335
|
+
invert: identity2,
|
|
2336
|
+
sqlApply: asNode,
|
|
2337
|
+
sqlInvert: identity2
|
|
2338
|
+
};
|
|
2339
|
+
}
|
|
2340
|
+
function scaleLog({ base = null } = {}) {
|
|
2341
|
+
if (base == null || base === Math.E) {
|
|
2342
|
+
return {
|
|
2343
|
+
apply: Math.log,
|
|
2344
|
+
invert: Math.exp,
|
|
2345
|
+
sqlApply: (c) => ln(c),
|
|
2346
|
+
sqlInvert: (c) => exp(c)
|
|
2347
|
+
};
|
|
2348
|
+
} else if (base === 10) {
|
|
2349
|
+
return {
|
|
2350
|
+
apply: Math.log10,
|
|
2351
|
+
invert: (x2) => Math.pow(10, x2),
|
|
2352
|
+
sqlApply: (c) => log(c),
|
|
2353
|
+
sqlInvert: (c) => pow(10, c)
|
|
2354
|
+
};
|
|
2355
|
+
} else {
|
|
2356
|
+
const b = +base;
|
|
2357
|
+
return {
|
|
2358
|
+
apply: (x2) => Math.log(x2) / Math.log(b),
|
|
2359
|
+
invert: (x2) => Math.pow(b, x2),
|
|
2360
|
+
sqlApply: (c) => div(ln(c), ln(b)),
|
|
2361
|
+
sqlInvert: (c) => pow(b, c)
|
|
2362
|
+
};
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
function scaleSymlog({ constant = 1 } = {}) {
|
|
2366
|
+
const _ = +constant;
|
|
2367
|
+
return {
|
|
2368
|
+
apply: (x2) => Math.sign(x2) * Math.log1p(Math.abs(x2)),
|
|
2369
|
+
invert: (x2) => Math.sign(x2) * Math.exp(Math.abs(x2) - _),
|
|
2370
|
+
sqlApply: (c) => (c = asNode(c), mul(sign(c), ln(add(_, abs(c))))),
|
|
2371
|
+
sqlInvert: (c) => mul(sign(c), sub(exp(abs(c)), _))
|
|
2372
|
+
};
|
|
2373
|
+
}
|
|
2374
|
+
function scaleSqrt() {
|
|
2375
|
+
return {
|
|
2376
|
+
apply: (x2) => Math.sign(x2) * Math.sqrt(Math.abs(x2)),
|
|
2377
|
+
invert: (x2) => Math.sign(x2) * x2 * x2,
|
|
2378
|
+
sqlApply: (c) => (c = asNode(c), mul(sign(c), sqrt(abs(c)))),
|
|
2379
|
+
sqlInvert: (c) => mul(sign(c), pow(c, 2))
|
|
2380
|
+
};
|
|
2381
|
+
}
|
|
2382
|
+
function scalePow({ exponent = 1 } = {}) {
|
|
2383
|
+
const e = +exponent;
|
|
2384
|
+
return {
|
|
2385
|
+
apply: (x2) => Math.sign(x2) * Math.pow(Math.abs(x2), e),
|
|
2386
|
+
invert: (x2) => Math.sign(x2) * Math.pow(Math.abs(x2), 1 / e),
|
|
2387
|
+
sqlApply: (c) => (c = asNode(c), mul(sign(c), pow(abs(c), e))),
|
|
2388
|
+
sqlInvert: (c) => mul(sign(c), pow(abs(c), div(1, e)))
|
|
2389
|
+
};
|
|
2390
|
+
}
|
|
2391
|
+
function scaleTime() {
|
|
2392
|
+
return {
|
|
2393
|
+
apply: (x2) => +x2,
|
|
2394
|
+
invert: (x2) => new Date(x2),
|
|
2395
|
+
sqlApply: (c) => c instanceof Date ? literal(+c) : isDateLiteral(c) ? literal(+c.value) : epoch_ms(c),
|
|
2396
|
+
sqlInvert: identity2
|
|
2397
|
+
};
|
|
2398
|
+
}
|
|
2399
|
+
var scales = {
|
|
2400
|
+
identity: scaleLinear,
|
|
2401
|
+
linear: scaleLinear,
|
|
2402
|
+
log: scaleLog,
|
|
2403
|
+
symlog: scaleSymlog,
|
|
2404
|
+
sqrt: scaleSqrt,
|
|
2405
|
+
pow: scalePow,
|
|
2406
|
+
time: scaleTime,
|
|
2407
|
+
utc: scaleTime
|
|
2408
|
+
};
|
|
2409
|
+
function scaleTransform(options) {
|
|
2410
|
+
const scale = scales[options.type];
|
|
2411
|
+
return scale ? { ...options, ...scale(options) } : null;
|
|
2412
|
+
}
|
|
2413
|
+
function isDateLiteral(x2) {
|
|
2414
|
+
return x2 instanceof LiteralNode && x2.value instanceof Date;
|
|
2415
|
+
}
|
|
1315
2416
|
export {
|
|
2417
|
+
AggregateNode,
|
|
2418
|
+
AndNode,
|
|
2419
|
+
BetweenOpNode,
|
|
2420
|
+
BinaryOpNode,
|
|
2421
|
+
CaseNode,
|
|
2422
|
+
CastNode,
|
|
2423
|
+
ColumnNameRefNode,
|
|
2424
|
+
ColumnParamNode,
|
|
2425
|
+
ColumnRefNode,
|
|
2426
|
+
DescribeQuery,
|
|
2427
|
+
ExprNode,
|
|
2428
|
+
FragmentNode,
|
|
2429
|
+
FromClauseNode,
|
|
2430
|
+
FunctionNode,
|
|
2431
|
+
InOpNode,
|
|
2432
|
+
IntervalNode,
|
|
2433
|
+
LiteralNode,
|
|
2434
|
+
NotBetweenOpNode,
|
|
2435
|
+
OrNode,
|
|
2436
|
+
OrderByNode,
|
|
2437
|
+
ParamNode,
|
|
1316
2438
|
Query,
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
2439
|
+
SQLNode,
|
|
2440
|
+
SampleClauseNode,
|
|
2441
|
+
SelectClauseNode,
|
|
2442
|
+
SelectQuery,
|
|
2443
|
+
SetOperation,
|
|
2444
|
+
TableRefNode,
|
|
2445
|
+
UnaryOpNode,
|
|
2446
|
+
UnaryPosftixOpNode,
|
|
2447
|
+
VerbatimNode,
|
|
2448
|
+
WhenNode,
|
|
2449
|
+
WindowClauseNode,
|
|
2450
|
+
WindowDefNode,
|
|
2451
|
+
WindowFrameNode,
|
|
2452
|
+
WindowFunctionNode,
|
|
2453
|
+
WindowNode,
|
|
2454
|
+
WithClauseNode,
|
|
2455
|
+
abs,
|
|
2456
|
+
add,
|
|
1321
2457
|
and,
|
|
1322
2458
|
argmax,
|
|
1323
2459
|
argmin,
|
|
1324
2460
|
arrayAgg,
|
|
1325
|
-
|
|
1326
|
-
|
|
2461
|
+
asLiteral,
|
|
2462
|
+
asNode,
|
|
2463
|
+
asTableRef,
|
|
2464
|
+
asVerbatim,
|
|
2465
|
+
asc,
|
|
1327
2466
|
avg,
|
|
2467
|
+
bin1d,
|
|
2468
|
+
bin2d,
|
|
2469
|
+
binLinear1d,
|
|
2470
|
+
binLinear2d,
|
|
2471
|
+
bitAnd,
|
|
2472
|
+
bitLeft,
|
|
2473
|
+
bitNot,
|
|
2474
|
+
bitOr,
|
|
2475
|
+
bitRight,
|
|
1328
2476
|
cast,
|
|
1329
|
-
|
|
1330
|
-
castInteger,
|
|
2477
|
+
ceil,
|
|
1331
2478
|
centroid,
|
|
1332
2479
|
centroidX,
|
|
1333
2480
|
centroidY,
|
|
2481
|
+
collectAggregates,
|
|
2482
|
+
collectColumns,
|
|
2483
|
+
collectParams,
|
|
1334
2484
|
column,
|
|
2485
|
+
cond,
|
|
1335
2486
|
contains,
|
|
1336
2487
|
corr,
|
|
1337
2488
|
count,
|
|
1338
2489
|
covarPop,
|
|
1339
2490
|
covariance,
|
|
1340
|
-
|
|
2491
|
+
createSchema,
|
|
2492
|
+
createTable,
|
|
1341
2493
|
cume_dist,
|
|
1342
2494
|
dateBin,
|
|
1343
2495
|
dateDay,
|
|
@@ -1345,56 +2497,77 @@ export {
|
|
|
1345
2497
|
dateMonthDay,
|
|
1346
2498
|
dense_rank,
|
|
1347
2499
|
desc,
|
|
2500
|
+
div,
|
|
1348
2501
|
entropy,
|
|
1349
2502
|
epoch_ms,
|
|
1350
2503
|
eq,
|
|
2504
|
+
exp,
|
|
1351
2505
|
first,
|
|
1352
2506
|
first_value,
|
|
2507
|
+
float32,
|
|
2508
|
+
float64,
|
|
2509
|
+
floor,
|
|
1353
2510
|
geojson,
|
|
2511
|
+
greatest,
|
|
1354
2512
|
gt,
|
|
1355
2513
|
gte,
|
|
2514
|
+
idiv,
|
|
2515
|
+
int32,
|
|
2516
|
+
interval,
|
|
2517
|
+
isAggregateExpression,
|
|
1356
2518
|
isBetween,
|
|
2519
|
+
isColumnRef,
|
|
1357
2520
|
isDescribeQuery,
|
|
1358
2521
|
isDistinct,
|
|
1359
2522
|
isFinite,
|
|
2523
|
+
isIn,
|
|
1360
2524
|
isInfinite,
|
|
1361
2525
|
isNaN,
|
|
2526
|
+
isNode,
|
|
1362
2527
|
isNotBetween,
|
|
1363
2528
|
isNotDistinct,
|
|
1364
2529
|
isNotNull,
|
|
1365
2530
|
isNull,
|
|
1366
2531
|
isParamLike,
|
|
1367
2532
|
isQuery,
|
|
1368
|
-
|
|
2533
|
+
isSelectQuery,
|
|
2534
|
+
isTableRef,
|
|
1369
2535
|
kurtosis,
|
|
1370
2536
|
lag,
|
|
1371
2537
|
last,
|
|
1372
2538
|
last_value,
|
|
1373
2539
|
lead,
|
|
2540
|
+
least,
|
|
1374
2541
|
length,
|
|
2542
|
+
lineDensity,
|
|
1375
2543
|
literal,
|
|
1376
|
-
|
|
2544
|
+
ln,
|
|
1377
2545
|
loadCSV,
|
|
1378
2546
|
loadExtension,
|
|
1379
2547
|
loadJSON,
|
|
1380
2548
|
loadObjects,
|
|
1381
2549
|
loadParquet,
|
|
1382
2550
|
loadSpatial,
|
|
2551
|
+
log,
|
|
1383
2552
|
lower,
|
|
1384
2553
|
lt,
|
|
1385
2554
|
lte,
|
|
2555
|
+
m4,
|
|
1386
2556
|
mad,
|
|
1387
2557
|
max,
|
|
1388
|
-
mean,
|
|
1389
2558
|
median,
|
|
1390
2559
|
min,
|
|
2560
|
+
mod,
|
|
1391
2561
|
mode,
|
|
2562
|
+
mul,
|
|
1392
2563
|
neq,
|
|
1393
2564
|
not,
|
|
1394
2565
|
nth_value,
|
|
1395
2566
|
ntile,
|
|
1396
2567
|
or,
|
|
2568
|
+
over,
|
|
1397
2569
|
percent_rank,
|
|
2570
|
+
pow,
|
|
1398
2571
|
prefix,
|
|
1399
2572
|
product,
|
|
1400
2573
|
quantile,
|
|
@@ -1409,20 +2582,25 @@ export {
|
|
|
1409
2582
|
regrSXY,
|
|
1410
2583
|
regrSYY,
|
|
1411
2584
|
regrSlope,
|
|
1412
|
-
|
|
2585
|
+
rewrite,
|
|
2586
|
+
round,
|
|
1413
2587
|
row_number,
|
|
1414
2588
|
scaleTransform,
|
|
2589
|
+
sign,
|
|
1415
2590
|
skewness,
|
|
1416
2591
|
sql,
|
|
2592
|
+
sqrt,
|
|
1417
2593
|
stddev,
|
|
1418
2594
|
stddevPop,
|
|
1419
2595
|
stringAgg,
|
|
2596
|
+
sub,
|
|
1420
2597
|
suffix,
|
|
1421
2598
|
sum,
|
|
1422
|
-
|
|
2599
|
+
trunc,
|
|
1423
2600
|
upper,
|
|
1424
2601
|
varPop,
|
|
1425
2602
|
variance,
|
|
2603
|
+
walk,
|
|
1426
2604
|
x,
|
|
1427
2605
|
y
|
|
1428
2606
|
};
|