@uwdata/mosaic-sql 0.11.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/README.md +2 -0
  2. package/dist/mosaic-sql.js +2242 -1064
  3. package/dist/mosaic-sql.min.js +1 -1
  4. package/dist/types/ast/aggregate.d.ts +70 -0
  5. package/dist/types/ast/between-op.d.ts +46 -0
  6. package/dist/types/ast/binary-op.d.ts +28 -0
  7. package/dist/types/ast/case.d.ts +68 -0
  8. package/dist/types/ast/cast.d.ts +21 -0
  9. package/dist/types/ast/column-param.d.ts +17 -0
  10. package/dist/types/ast/column-ref.d.ts +39 -0
  11. package/dist/types/ast/fragment.d.ts +14 -0
  12. package/dist/types/ast/from.d.ts +21 -0
  13. package/dist/types/ast/function.d.ts +21 -0
  14. package/dist/types/ast/in-op.d.ts +21 -0
  15. package/dist/types/ast/interval.d.ts +21 -0
  16. package/dist/types/ast/literal.d.ts +15 -0
  17. package/dist/types/ast/logical-op.d.ts +46 -0
  18. package/dist/types/ast/node.d.ts +24 -0
  19. package/dist/types/ast/order-by.d.ts +29 -0
  20. package/dist/types/ast/param.d.ts +19 -0
  21. package/dist/types/ast/query.d.ts +268 -0
  22. package/dist/types/ast/sample.d.ts +42 -0
  23. package/dist/types/ast/select.d.ts +22 -0
  24. package/dist/types/ast/table-ref.d.ts +25 -0
  25. package/dist/types/ast/unary-op.d.ts +39 -0
  26. package/dist/types/ast/verbatim.d.ts +9 -0
  27. package/dist/types/ast/window.d.ts +177 -0
  28. package/dist/types/ast/with.d.ts +22 -0
  29. package/dist/types/constants.d.ts +38 -0
  30. package/dist/types/functions/aggregate.d.ts +229 -0
  31. package/dist/types/functions/case.d.ts +15 -0
  32. package/dist/types/functions/cast.d.ts +26 -0
  33. package/dist/types/functions/column.d.ts +9 -0
  34. package/dist/types/functions/datetime.d.ts +44 -0
  35. package/dist/types/functions/literal.d.ts +16 -0
  36. package/dist/types/functions/numeric.d.ts +93 -0
  37. package/dist/types/functions/operators.d.ts +198 -0
  38. package/dist/types/functions/order-by.d.ts +17 -0
  39. package/dist/types/functions/spatial.d.ts +37 -0
  40. package/dist/types/functions/sql-template-tag.d.ts +16 -0
  41. package/dist/types/functions/string.d.ts +55 -0
  42. package/dist/types/functions/table-ref.d.ts +9 -0
  43. package/dist/types/functions/window.d.ts +87 -0
  44. package/dist/types/index-types.d.ts +2 -0
  45. package/dist/types/index.d.ts +53 -0
  46. package/dist/types/load/create.d.ts +8 -0
  47. package/dist/types/load/extension.d.ts +1 -0
  48. package/dist/types/load/load.d.ts +12 -0
  49. package/dist/types/load/sql-from.d.ts +11 -0
  50. package/dist/types/transforms/bin-1d.d.ts +14 -0
  51. package/dist/types/transforms/bin-2d.d.ts +18 -0
  52. package/dist/types/transforms/bin-linear-1d.d.ts +9 -0
  53. package/dist/types/transforms/bin-linear-2d.d.ts +18 -0
  54. package/dist/types/transforms/line-density.d.ts +23 -0
  55. package/dist/types/transforms/m4.d.ts +18 -0
  56. package/dist/types/transforms/scales.d.ts +1 -0
  57. package/dist/types/types.d.ts +59 -0
  58. package/dist/types/util/ast.d.ts +60 -0
  59. package/dist/types/util/function.d.ts +54 -0
  60. package/dist/types/util/string.d.ts +3 -0
  61. package/dist/types/util/type-check.d.ts +18 -0
  62. package/dist/types/visit/recurse.d.ts +28 -0
  63. package/dist/types/visit/rewrite.d.ts +10 -0
  64. package/dist/types/visit/visitors.d.ts +33 -0
  65. package/dist/types/visit/walk.d.ts +7 -0
  66. package/jsconfig.json +11 -0
  67. package/package.json +6 -4
  68. package/src/ast/aggregate.js +164 -0
  69. package/src/ast/between-op.js +75 -0
  70. package/src/ast/binary-op.js +40 -0
  71. package/src/ast/case.js +105 -0
  72. package/src/ast/cast.js +34 -0
  73. package/src/ast/column-param.js +29 -0
  74. package/src/ast/column-ref.js +72 -0
  75. package/src/ast/fragment.js +26 -0
  76. package/src/ast/from.js +40 -0
  77. package/src/ast/function.js +34 -0
  78. package/src/ast/in-op.js +33 -0
  79. package/src/ast/interval.js +33 -0
  80. package/src/ast/literal.js +55 -0
  81. package/src/ast/logical-op.js +67 -0
  82. package/src/ast/node.js +29 -0
  83. package/src/ast/order-by.js +48 -0
  84. package/src/ast/param.js +35 -0
  85. package/src/ast/query.js +578 -0
  86. package/src/ast/sample.js +53 -0
  87. package/src/ast/select.js +44 -0
  88. package/src/ast/table-ref.js +44 -0
  89. package/src/ast/unary-op.js +64 -0
  90. package/src/ast/verbatim.js +26 -0
  91. package/src/ast/window.js +290 -0
  92. package/src/ast/with.js +30 -0
  93. package/src/constants.js +44 -0
  94. package/src/functions/aggregate.js +335 -0
  95. package/src/functions/case.js +21 -0
  96. package/src/functions/cast.js +39 -0
  97. package/src/functions/column.js +20 -0
  98. package/src/functions/datetime.js +65 -0
  99. package/src/functions/literal.js +22 -0
  100. package/src/functions/numeric.js +139 -0
  101. package/src/functions/operators.js +298 -0
  102. package/src/functions/order-by.js +24 -0
  103. package/src/functions/spatial.js +56 -0
  104. package/src/functions/sql-template-tag.js +51 -0
  105. package/src/functions/string.js +82 -0
  106. package/src/functions/table-ref.js +14 -0
  107. package/src/functions/window.js +121 -0
  108. package/src/index-types.ts +2 -0
  109. package/src/index.js +57 -155
  110. package/src/load/create.js +10 -2
  111. package/src/load/load.js +4 -4
  112. package/src/load/sql-from.js +7 -6
  113. package/src/transforms/bin-1d.js +21 -0
  114. package/src/transforms/bin-2d.js +29 -0
  115. package/src/transforms/bin-linear-1d.js +26 -0
  116. package/src/transforms/bin-linear-2d.js +71 -0
  117. package/src/transforms/line-density.js +113 -0
  118. package/src/transforms/m4.js +38 -0
  119. package/src/{scales.js → transforms/scales.js} +31 -17
  120. package/src/types.ts +96 -0
  121. package/src/util/ast.js +96 -0
  122. package/src/util/function.js +78 -0
  123. package/src/util/string.js +16 -0
  124. package/src/util/type-check.js +29 -0
  125. package/src/visit/recurse.js +57 -0
  126. package/src/visit/rewrite.js +32 -0
  127. package/src/visit/visitors.js +108 -0
  128. package/src/visit/walk.js +30 -0
  129. package/tsconfig.json +12 -0
  130. package/src/Query.js +0 -593
  131. package/src/aggregates.js +0 -185
  132. package/src/cast.js +0 -19
  133. package/src/datetime.js +0 -31
  134. package/src/desc.js +0 -13
  135. package/src/expression.js +0 -170
  136. package/src/functions.js +0 -25
  137. package/src/literal.js +0 -6
  138. package/src/operators.js +0 -54
  139. package/src/ref.js +0 -109
  140. package/src/repeat.js +0 -3
  141. package/src/spatial.js +0 -10
  142. package/src/to-sql.js +0 -52
  143. package/src/windows.js +0 -239
@@ -1,74 +1,80 @@
1
- // src/ref.js
2
- var Ref = class {
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
- * Create a new Ref instance.
5
- * @param {string|Ref|null} table The table name.
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(table, column2) {
9
- if (table) this.table = String(table);
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
- * Get the list of referenced columns. Either a single element array
14
- * if column is non-null, otherwise an empty array.
55
+ * Instantiate an literal node.
56
+ * @param {*} value The literal value.
15
57
  */
16
- get columns() {
17
- return this.column ? [this.column] : [];
58
+ constructor(value) {
59
+ super(LITERAL);
60
+ this.value = value;
18
61
  }
19
62
  /**
20
- * Generate a SQL string for this reference.
21
- * @returns {string} The SQL string.
63
+ * Generate a SQL query string for this node.
64
+ * @returns {string}
22
65
  */
23
66
  toString() {
24
- const { table, column: column2 } = this;
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 "boolean":
67
- return value ? "TRUE" : "FALSE";
72
+ case "number":
73
+ return Number.isFinite(value) ? `${value}` : "NULL";
68
74
  case "string":
69
75
  return `'${value.replace(`'`, `''`)}'`;
70
- case "number":
71
- return Number.isFinite(value) ? String(value) : "NULL";
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) ? `MAKE_DATE(${y2}, ${m + 1}, ${d})` : `EPOCH_MS(${ts})`;
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 String(value);
91
+ return `${value}`;
86
92
  }
87
93
  }
88
94
  }
89
95
 
90
- // src/expression.js
91
- var isParamLike = (value) => typeof value?.addEventListener === "function";
92
- function isSQLExpression(value) {
93
- return value instanceof SQLExpression;
94
- }
95
- var SQLExpression = class {
96
- /**
97
- * Create a new SQL expression instance.
98
- * @param {(string | ParamLike | SQLExpression | import('./ref.js').Ref)[]} parts The parts of the expression.
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
- * A reference to this expression.
118
- * Provides compatibility with param-like objects.
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
- * The column dependencies of this expression.
125
- * @returns {string[]} The columns dependencies.
126
- */
127
- get columns() {
128
- const { _params, _deps } = this;
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
- * The first column dependency in this expression, or undefined if none.
144
- * @returns {string} The first column dependency.
142
+ * Instantiate a table reference node.
143
+ * @param {string | string[]} table The table name.
145
144
  */
146
- get column() {
147
- return this._deps.length ? this._deps[0] : this.columns[0];
145
+ constructor(table) {
146
+ super(TABLE_REF);
147
+ this.table = [table].flat();
148
148
  }
149
149
  /**
150
- * Annotate this expression instance with additional properties.
151
- * @param {object[]} [props] One or more objects with properties to add.
152
- * @returns This SQL expression.
150
+ * The table name without database or schema namespaces.
151
+ * @returns {string}
153
152
  */
154
- annotate(...props) {
155
- return Object.assign(this, ...props);
153
+ get name() {
154
+ return this.table[this.table.length - 1];
156
155
  }
157
156
  /**
158
- * Generate a SQL code string corresponding to this expression.
159
- * @returns {string} A SQL code string.
157
+ * Generate a SQL query string for this node.
158
+ * @returns {string}
160
159
  */
161
160
  toString() {
162
- return this._expr.map((p) => isParamLike(p) && !isSQLExpression(p) ? literalToSQL(p.value) : p).join("");
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
- * Add an event listener callback for the provided event type.
166
- * @param {string} type The event type to listen for (for example, "value").
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
- addEventListener(type, callback) {
172
- const map = this.map || (this.map = /* @__PURE__ */ new Map());
173
- const set = map.get(type) || (map.set(type, /* @__PURE__ */ new Set()), map.get(type));
174
- set.add(callback);
181
+ toString() {
182
+ const { name, args } = this;
183
+ return `${name}(${args.join(", ")})`;
175
184
  }
176
185
  };
177
- function update(expr, callbacks) {
178
- if (callbacks?.size) {
179
- return Promise.allSettled(Array.from(callbacks, (fn) => fn(expr)));
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 parseSQL(strings, exprs) {
183
- const spans = [strings[0]];
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 sql(strings, ...exprs) {
206
- const { spans, cols } = parseSQL(strings, exprs);
207
- return new SQLExpression(spans, cols);
194
+ function winFn(name, ...args) {
195
+ return new WindowNode(
196
+ new WindowFunctionNode(name, argsList(args).map(asNode))
197
+ );
208
198
  }
209
-
210
- // src/desc.js
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
- // src/literal.js
217
- var literal = (value) => ({
218
- value,
219
- toString: () => literalToSQL(value)
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/functions.js
269
- function functionCall(op, type) {
270
- return (...values) => {
271
- const args = values.map(asColumn);
272
- const cast2 = type ? `::${type}` : "";
273
- const expr = args.length ? sql([`${op}(`, ...repeat(args.length - 1, ", "), `)${cast2}`], ...args) : sql`${op}()${cast2}`;
274
- return expr.annotate({ func: op, args });
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/windows.js
289
- var WindowFunction = class _WindowFunction extends SQLExpression {
290
- /**
291
- * Create a new WindowFunction instance.
292
- * @param {string} op The window operation indicator.
293
- * @param {*} func The window function expression.
294
- * @param {*} [type] The SQL data type to cast to.
295
- * @param {string} [name] The window definition name.
296
- * @param {*} [group] Grouping (partition by) expressions.
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.group = group;
320
- this.order = order;
321
- this.frame = frame;
230
+ this.def = def;
322
231
  }
323
- get basis() {
324
- return this.column;
232
+ toString() {
233
+ return `${quoteIdentifier(this.name)} AS ${this.def}`;
325
234
  }
326
- get label() {
327
- const { func } = this;
328
- return func.label ?? func.toString();
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 function over a named window definition.
248
+ * Return an updated window over a named window definition.
332
249
  * @param {string} name The window definition name.
333
- * @returns {WindowFunction} A new window function.
250
+ * @returns {WindowNode} A new window node.
334
251
  */
335
252
  over(name) {
336
- const { window: op, func, type, group, order, frame } = this;
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 function with the given partitioning.
341
- * @param {*} expr The grouping (partition by) criteria for the window function.
342
- * @returns {WindowFunction} A new window function.
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
- const exprs = expr.flat().filter((x2) => x2).map(asColumn);
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 function with the given ordering.
355
- * @param {*} expr The sorting (order by) criteria for the window function.
356
- * @returns {WindowFunction} A new window function.
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
- const exprs = expr.flat().filter((x2) => x2).map(asColumn);
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 function with the given rows frame.
369
- * @param {(number|null)[] | import('./expression.js').ParamLike} expr The row-based window frame.
370
- * @returns {WindowFunction} A new window function.
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(expr) {
373
- const frame = windowFrame("ROWS", expr);
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 function with the given range frame.
379
- * @param {(number|null)[] | import('./expression.js').ParamLike} expr The range-based window frame.
380
- * @returns {WindowFunction} A new window function.
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(expr) {
383
- const frame = windowFrame("RANGE", expr);
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
- get basis() {
445
- return this.column;
446
- }
447
- get label() {
448
- const { aggregate: op, args, isDistinct: isDistinct2 } = this;
449
- const dist = isDistinct2 ? "DISTINCT" + (args.length ? " " : "") : "";
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
- * Return a new derived aggregate function over distinct values.
455
- * @returns {AggregateFunction} A new aggregate function.
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
- distinct() {
458
- const { aggregate: op, args, type, filter } = this;
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
- * Return a new derived aggregate function that filters values.
463
- * @param {*} filter The filter expresion.
464
- * @returns {AggregateFunction} A new aggregate function.
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
- where(filter) {
467
- const { aggregate: op, args, type, isDistinct: isDistinct2 } = this;
468
- return new _AggregateFunction(op, args, type, isDistinct2, filter);
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 a new window function over this aggregate.
472
- * @returns {WindowFunction} A new aggregate function.
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
- window() {
475
- const { aggregate: op, args, type, isDistinct: isDistinct2 } = this;
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 a window function over this aggregate with the given partitioning.
481
- * @param {*} expr The grouping (partition by) criteria for the window function.
482
- * @returns {WindowFunction} A new window function.
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.window().partitionby(...expr);
334
+ return deriveDef(this, { partition: exprList(expr) });
486
335
  }
487
336
  /**
488
- * Return a window function over this aggregate with the given ordering.
489
- * @param {*} expr The sorting (order by) criteria for the window function.
490
- * @returns {WindowFunction} A new window function.
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.window().orderby(...expr);
342
+ return deriveDef(this, { order: exprList(expr) });
494
343
  }
495
344
  /**
496
- * Return a window function over this aggregate with the given row frame.
497
- * @param {(number|null)[] | import('./expression.js').ParamLike} frame The row-based window frame.
498
- * @returns {WindowFunction} A new window function.
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(frame) {
501
- return this.window().rows(frame);
349
+ rows(extent) {
350
+ return deriveDef(this, { frame: new WindowFrameNode(extent) });
502
351
  }
503
352
  /**
504
- * Return a window function over this aggregate with the given range frame.
505
- * @param {(number|null)[] | import('./expression.js').ParamLike} frame The range-based window frame.
506
- * @returns {WindowFunction} A new window function.
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(frame) {
509
- return this.window().range(frame);
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
- * Retrieve current WITH common table expressions (CTEs).
676
- * @returns {any[]}
361
+ * Generate a SQL query string for this node.
362
+ * @returns {string}
677
363
  */
678
- /**
679
- * Add WITH common table expressions (CTEs).
680
- * @param {...any} expr Expressions to add.
681
- * @returns {this}
682
- */
683
- with(...expr) {
684
- const { query } = this;
685
- if (expr.length === 0) {
686
- return query.with;
687
- } else {
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
- * Retrieve current SELECT expressions.
710
- * @returns {any[]}
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
- * Add SELECT expressions.
714
- * @param {...any} expr Expressions to add.
715
- * @returns {this}
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
- * Retrieve current from expressions.
752
- * @returns {any[]}
391
+ * Generate a SQL query string for this node.
392
+ * @returns {string}
753
393
  */
754
- /**
755
- * Provide table from expressions.
756
- * @param {...any} expr
757
- * @returns {this}
758
- */
759
- from(...expr) {
760
- const { query } = this;
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
- * Retrieve current SAMPLE settings.
791
- * @returns {any[]}
421
+ * Instantiate a column reference node.
422
+ * @param {import('./table-ref.js').TableRefNode} [table] The table reference.
792
423
  */
793
- /**
794
- * Set SAMPLE settings.
795
- * @param {number|object} value The percentage or number of rows to sample.
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
- * Retrieve current WHERE expressions.
814
- * @returns {any[]}
429
+ * Returns the column name.
430
+ * @returns {string}
815
431
  */
816
- /**
817
- * Add WHERE expressions.
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
- * Retrieve current GROUP BY expressions.
838
- * @returns {any[]}
436
+ * Generate a SQL query string for this node.
437
+ * @returns {string}
839
438
  */
840
- /**
841
- * Add GROUP BY expressions.
842
- * @param {...any} expr Expressions to add.
843
- * @returns {this}
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
- * Retrieve current HAVING expressions.
862
- * @returns {any[]}
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
- * Add HAVING expressions.
866
- * @param {...any} expr Expressions to add.
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
- * Retrieve current WINDOW definitions.
882
- * @returns {any[]}
457
+ * Returns the column name.
458
+ * @returns {string}
883
459
  */
884
- /**
885
- * Add WINDOW definitions.
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
- * Retrieve current QUALIFY expressions.
909
- * @returns {any[]}
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
- * Add QUALIFY expressions.
913
- * @param {...any} expr Expressions to add.
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
- * Retrieve current ORDER BY expressions.
929
- * @returns {any[]}
479
+ * Returns the column name.
480
+ * @returns {string}
930
481
  */
931
- /**
932
- * Add ORDER BY expressions.
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
- * Retrieve current LIMIT value.
949
- * @returns {number|null}
496
+ * Instantiate a raw node with verbatim content.
497
+ * @param {string} value The verbatim content to include.
950
498
  */
951
- /**
952
- * Set the query result LIMIT.
953
- * @param {number} value The limit value.
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
- * Retrieve current OFFSET value.
967
- * @returns {number|null}
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
- const {
1000
- with: cte,
1001
- select,
1002
- distinct,
1003
- from,
1004
- sample,
1005
- where,
1006
- groupby,
1007
- having,
1008
- window,
1009
- qualify,
1010
- orderby,
1011
- limit,
1012
- offset
1013
- } = this.query;
1014
- const sql2 = [];
1015
- if (cte.length) {
1016
- const list = cte.map(({ as, query }) => `"${as}" AS (${query})`);
1017
- sql2.push(`WITH ${list.join(", ")}`);
1018
- }
1019
- const sels = select.map(
1020
- ({ as, expr }) => isColumnRefFor(expr, as) && !expr.table ? `${expr}` : `${expr} AS "${as}"`
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
- sql2.push(`SELECT${distinct ? " DISTINCT" : ""} ${sels.join(", ")}`);
1023
- if (from.length) {
1024
- const rels = from.map(({ as, from: from2 }) => {
1025
- const rel = isQuery(from2) ? `(${from2})` : `${from2}`;
1026
- return !as || as === from2.table ? rel : `${rel} AS "${as}"`;
1027
- });
1028
- sql2.push(`FROM ${rels.join(", ")}`);
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
- if (where.length) {
1031
- const clauses = where.map(String).filter((x2) => x2).join(" AND ");
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 (sample) {
1035
- const { rows, perc, method, seed } = sample;
1036
- const size = rows ? `${rows} ROWS` : `${perc} PERCENT`;
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 (groupby.length) {
1041
- sql2.push(`GROUP BY ${groupby.join(", ")}`);
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 (window.length) {
1048
- const windows = window.map(({ as, expr }) => `"${as}" AS (${expr})`);
1049
- sql2.push(`WINDOW ${windows.join(", ")}`);
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 (orderby.length) {
1056
- sql2.push(`ORDER BY ${orderby.join(", ")}`);
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 SetOperation = class _SetOperation {
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.map((q) => q.clone());
1071
- this.query = { orderby: [] };
1072
- this.cteFor = null;
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 q = new _SetOperation(this.op, this.queries);
1076
- q.query = { ...this.query };
1077
- return q;
1377
+ const { op, queries, ...rest } = this;
1378
+ return Object.assign(new _SetOperation(op, queries), rest);
1078
1379
  }
1079
- orderby(...expr) {
1080
- const { query } = this;
1081
- if (expr.length === 0) {
1082
- return query.orderby;
1083
- } else {
1084
- query.orderby = query.orderby.concat(
1085
- expr.flat().filter((x2) => x2).map(asColumn)
1086
- );
1087
- return this;
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
- limit(value) {
1091
- const { query } = this;
1092
- if (arguments.length === 0) {
1093
- return query.limit;
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
- query.limit = Number.isFinite(value) ? value : void 0;
1096
- return this;
1910
+ spans[k] += isString(e) ? e : literal(e);
1097
1911
  }
1098
- }
1099
- offset(value) {
1100
- const { query } = this;
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
- query.offset = Number.isFinite(value) ? value : void 0;
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
- function isDescribeQuery(value) {
1132
- return isQuery(value) && value.describe;
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 unquote(s) {
1135
- return isDoubleQuoted(s) ? s.slice(1, -1) : s;
1926
+ function regexp_matches(string, pattern, options) {
1927
+ return strFn("regexp_matches", string, pattern, options);
1136
1928
  }
1137
- function isDoubleQuoted(s) {
1138
- return s[0] === '"' && s[s.length - 1] === '"';
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/scales.js
1142
- var identity = (x2) => x2;
1143
- function scaleLinear() {
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 scaleLog({ base = null } = {}) {
1152
- if (base == null || base === Math.E) {
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 scaleSymlog({ constant = 1 } = {}) {
1177
- const _ = +constant;
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 scaleSqrt() {
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 scalePow({ exponent = 1 } = {}) {
1194
- const e = +exponent;
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 scaleTime() {
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
- var scales = {
1211
- identity: scaleLinear,
1212
- linear: scaleLinear,
1213
- log: scaleLog,
1214
- symlog: scaleSymlog,
1215
- sqrt: scaleSqrt,
1216
- pow: scalePow,
1217
- time: scaleTime,
1218
- utc: scaleTime
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
- function scaleTransform(options) {
1221
- const scale = scales[options.type];
1222
- return scale ? { ...options, ...scale(options) } : null;
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 create(name, query, {
2122
+ function createTable(name, query, {
1227
2123
  replace = false,
1228
- temp = true,
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) => `${literalToSQL(datum[k])} AS "${columns[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 create(tableName, query, { view, temp, replace });
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, json_format: "auto" });
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 create(tableName, query, opt);
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
- Ref,
1318
- SQLExpression,
1319
- agg,
1320
- all,
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
- asColumn,
1326
- asRelation,
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
- castDouble,
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
- create,
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
- isSQLExpression,
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
- literalToSQL,
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
- relation,
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
- toSQL,
2599
+ trunc,
1423
2600
  upper,
1424
2601
  varPop,
1425
2602
  variance,
2603
+ walk,
1426
2604
  x,
1427
2605
  y
1428
2606
  };