@uwdata/mosaic-inputs 0.11.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/mosaic-inputs.js +2282 -1539
- package/dist/mosaic-inputs.min.js +2 -2
- package/package.json +4 -4
- package/src/Menu.js +11 -0
- package/src/Search.js +18 -3
- package/src/Slider.js +40 -21
- package/src/Table.js +14 -4
package/dist/mosaic-inputs.js
CHANGED
|
@@ -5,7 +5,8 @@ function throttle(callback, debounce = false) {
|
|
|
5
5
|
let next;
|
|
6
6
|
let pending = NIL;
|
|
7
7
|
function invoke(event) {
|
|
8
|
-
curr = callback(event).
|
|
8
|
+
curr = callback(event).catch(() => {
|
|
9
|
+
}).finally(() => {
|
|
9
10
|
if (next) {
|
|
10
11
|
const { value } = next;
|
|
11
12
|
next = null;
|
|
@@ -66,11 +67,12 @@ var MosaicClient = class {
|
|
|
66
67
|
return this._filterBy;
|
|
67
68
|
}
|
|
68
69
|
/**
|
|
69
|
-
* Return a boolean indicating if the client query can be
|
|
70
|
-
*
|
|
71
|
-
* groupby domain of the client
|
|
70
|
+
* Return a boolean indicating if the client query can be sped up with
|
|
71
|
+
* materialized views of pre-aggregated data. Should return true if changes to
|
|
72
|
+
* the filterBy selection does not change the groupby domain of the client
|
|
73
|
+
* query.
|
|
72
74
|
*/
|
|
73
|
-
get
|
|
75
|
+
get filterStable() {
|
|
74
76
|
return true;
|
|
75
77
|
}
|
|
76
78
|
/**
|
|
@@ -737,8 +739,8 @@ function toNumber(value) {
|
|
|
737
739
|
}
|
|
738
740
|
return Number(value);
|
|
739
741
|
}
|
|
740
|
-
function divide(num,
|
|
741
|
-
return Number(num /
|
|
742
|
+
function divide(num, div2) {
|
|
743
|
+
return Number(num / div2) + Number(num % div2) / Number(div2);
|
|
742
744
|
}
|
|
743
745
|
var asUint64 = (v) => BigInt.asUintN(64, v);
|
|
744
746
|
function fromDecimal128(buf2, offset) {
|
|
@@ -1056,14 +1058,14 @@ var Float16Batch = class extends NumberBatch {
|
|
|
1056
1058
|
);
|
|
1057
1059
|
const expo = (v & 31744) >> 10;
|
|
1058
1060
|
const sigf = (v & 1023) / 1024;
|
|
1059
|
-
const
|
|
1061
|
+
const sign2 = (-1) ** ((v & 32768) >> 15);
|
|
1060
1062
|
switch (expo) {
|
|
1061
1063
|
case 31:
|
|
1062
|
-
return
|
|
1064
|
+
return sign2 * (sigf ? Number.NaN : 1 / 0);
|
|
1063
1065
|
case 0:
|
|
1064
|
-
return
|
|
1066
|
+
return sign2 * (sigf ? 6103515625e-14 * sigf : 0);
|
|
1065
1067
|
}
|
|
1066
|
-
return
|
|
1068
|
+
return sign2 * 2 ** (expo - 15) * (1 + sigf);
|
|
1067
1069
|
}
|
|
1068
1070
|
};
|
|
1069
1071
|
var BoolBatch = class extends ArrayBatch {
|
|
@@ -1729,8 +1731,8 @@ var Table = class _Table {
|
|
|
1729
1731
|
* @returns {Table} A new table with columns matching the specified names.
|
|
1730
1732
|
*/
|
|
1731
1733
|
select(names, as) {
|
|
1732
|
-
const
|
|
1733
|
-
const indices = names.map((name) =>
|
|
1734
|
+
const all = this.names;
|
|
1735
|
+
const indices = names.map((name) => all.indexOf(name));
|
|
1734
1736
|
return this.selectAt(indices, as);
|
|
1735
1737
|
}
|
|
1736
1738
|
/**
|
|
@@ -2485,7 +2487,9 @@ function socketConnector(uri = "ws://localhost:3000/") {
|
|
|
2485
2487
|
* Query the DuckDB server.
|
|
2486
2488
|
* @param {object} query
|
|
2487
2489
|
* @param {'exec' | 'arrow' | 'json' | 'create-bundle' | 'load-bundle'} [query.type] The query type.
|
|
2488
|
-
* @param {string} query.sql A SQL query string.
|
|
2490
|
+
* @param {string} [query.sql] A SQL query string.
|
|
2491
|
+
* @param {string[]} [query.queries] The queries used to create a bundle.
|
|
2492
|
+
* @param {string} [query.name] The name of a bundle to create or load.
|
|
2489
2493
|
* @returns the query result
|
|
2490
2494
|
*/
|
|
2491
2495
|
query(query) {
|
|
@@ -2496,71 +2500,82 @@ function socketConnector(uri = "ws://localhost:3000/") {
|
|
|
2496
2500
|
};
|
|
2497
2501
|
}
|
|
2498
2502
|
|
|
2499
|
-
// ../sql/src/
|
|
2500
|
-
var
|
|
2503
|
+
// ../sql/src/constants.js
|
|
2504
|
+
var COLUMN_REF = "COLUMN_REF";
|
|
2505
|
+
var COLUMN_PARAM = "COLUMN_PARAM";
|
|
2506
|
+
var TABLE_REF = "TABLE_REF";
|
|
2507
|
+
var LITERAL = "LITERAL";
|
|
2508
|
+
var ORDER_BY = "ORDER_BY";
|
|
2509
|
+
var CAST = "CAST";
|
|
2510
|
+
var CASE = "CASE";
|
|
2511
|
+
var WHEN = "WHEN";
|
|
2512
|
+
var UNARY_OPERATOR = "UNARY";
|
|
2513
|
+
var UNARY_POSTFIX_OPERATOR = "UNARY_POSTFIX";
|
|
2514
|
+
var BINARY_OPERATOR = "BINARY";
|
|
2515
|
+
var BETWEEN_OPERATOR = "BETWEEN";
|
|
2516
|
+
var NOT_BETWEEN_OPERATOR = "NOT_BETWEEN";
|
|
2517
|
+
var LOGICAL_OPERATOR = "LOGICAL_OPERATOR";
|
|
2518
|
+
var IN_OPERATOR = "IN";
|
|
2519
|
+
var FUNCTION = "FUNCTION";
|
|
2520
|
+
var AGGREGATE = "AGGREGATE";
|
|
2521
|
+
var WINDOW = "WINDOW";
|
|
2522
|
+
var WINDOW_DEF = "WINDOW_DEF";
|
|
2523
|
+
var WINDOW_FRAME = "WINDOW_FRAME";
|
|
2524
|
+
var EXPRESSION = "EXPRESSION";
|
|
2525
|
+
var FRAGMENT = "FRAGMENT";
|
|
2526
|
+
var VERBATIM = "VERBATIM";
|
|
2527
|
+
var PARAM = "PARAM";
|
|
2528
|
+
var WITH_CLAUSE = "WITH_CLAUSE";
|
|
2529
|
+
var SELECT_CLAUSE = "SELECT_CLAUSE";
|
|
2530
|
+
var FROM_CLAUSE = "FROM_CLAUSE";
|
|
2531
|
+
var SAMPLE_CLAUSE = "SAMPLE_CLAUSE";
|
|
2532
|
+
var WINDOW_CLAUSE = "WINDOW_CLAUSE";
|
|
2533
|
+
var SELECT_QUERY = "SELECT_QUERY";
|
|
2534
|
+
var DESCRIBE_QUERY = "DESCRIBE_QUERY";
|
|
2535
|
+
var SET_OPERATION = "SET_OPERATION";
|
|
2536
|
+
|
|
2537
|
+
// ../sql/src/ast/node.js
|
|
2538
|
+
function isNode(value) {
|
|
2539
|
+
return value instanceof SQLNode;
|
|
2540
|
+
}
|
|
2541
|
+
var SQLNode = class {
|
|
2501
2542
|
/**
|
|
2502
|
-
*
|
|
2503
|
-
* @param {string
|
|
2504
|
-
* @param {string|null} [column] The column name.
|
|
2543
|
+
* Instantiate a SQL AST node.
|
|
2544
|
+
* @param {string} type The SQL AST node type.
|
|
2505
2545
|
*/
|
|
2506
|
-
constructor(
|
|
2507
|
-
|
|
2508
|
-
if (column2) this.column = column2;
|
|
2546
|
+
constructor(type) {
|
|
2547
|
+
this.type = type;
|
|
2509
2548
|
}
|
|
2549
|
+
};
|
|
2550
|
+
var ExprNode = class extends SQLNode {
|
|
2551
|
+
};
|
|
2552
|
+
|
|
2553
|
+
// ../sql/src/ast/literal.js
|
|
2554
|
+
var LiteralNode = class extends ExprNode {
|
|
2510
2555
|
/**
|
|
2511
|
-
*
|
|
2512
|
-
*
|
|
2556
|
+
* Instantiate an literal node.
|
|
2557
|
+
* @param {*} value The literal value.
|
|
2513
2558
|
*/
|
|
2514
|
-
|
|
2515
|
-
|
|
2559
|
+
constructor(value) {
|
|
2560
|
+
super(LITERAL);
|
|
2561
|
+
this.value = value;
|
|
2516
2562
|
}
|
|
2517
2563
|
/**
|
|
2518
|
-
* Generate a SQL string for this
|
|
2519
|
-
* @returns {string}
|
|
2564
|
+
* Generate a SQL query string for this node.
|
|
2565
|
+
* @returns {string}
|
|
2520
2566
|
*/
|
|
2521
2567
|
toString() {
|
|
2522
|
-
|
|
2523
|
-
if (column2) {
|
|
2524
|
-
const col = column2.startsWith("*") ? column2 : `"${column2}"`;
|
|
2525
|
-
return `${table2 ? `${quoteTableName(table2)}.` : ""}${col}`;
|
|
2526
|
-
} else {
|
|
2527
|
-
return table2 ? quoteTableName(table2) : "NULL";
|
|
2528
|
-
}
|
|
2568
|
+
return literalToSQL(this.value);
|
|
2529
2569
|
}
|
|
2530
2570
|
};
|
|
2531
|
-
function quoteTableName(table2) {
|
|
2532
|
-
const pieces = table2.split(".");
|
|
2533
|
-
return pieces.map((p) => `"${p}"`).join(".");
|
|
2534
|
-
}
|
|
2535
|
-
function isColumnRefFor(ref, name) {
|
|
2536
|
-
return ref instanceof Ref && ref.column === name;
|
|
2537
|
-
}
|
|
2538
|
-
function asColumn(value) {
|
|
2539
|
-
return typeof value === "string" ? column(value) : value;
|
|
2540
|
-
}
|
|
2541
|
-
function asRelation(value) {
|
|
2542
|
-
return typeof value === "string" ? relation(value) : value;
|
|
2543
|
-
}
|
|
2544
|
-
function relation(name) {
|
|
2545
|
-
return new Ref(name);
|
|
2546
|
-
}
|
|
2547
|
-
function column(table2, column2 = null) {
|
|
2548
|
-
if (arguments.length === 1) {
|
|
2549
|
-
column2 = table2;
|
|
2550
|
-
table2 = null;
|
|
2551
|
-
}
|
|
2552
|
-
return new Ref(table2, column2);
|
|
2553
|
-
}
|
|
2554
|
-
|
|
2555
|
-
// ../sql/src/to-sql.js
|
|
2556
2571
|
function literalToSQL(value) {
|
|
2557
2572
|
switch (typeof value) {
|
|
2558
|
-
case "
|
|
2559
|
-
return value ?
|
|
2573
|
+
case "number":
|
|
2574
|
+
return Number.isFinite(value) ? `${value}` : "NULL";
|
|
2560
2575
|
case "string":
|
|
2561
2576
|
return `'${value.replace(`'`, `''`)}'`;
|
|
2562
|
-
case "
|
|
2563
|
-
return
|
|
2577
|
+
case "boolean":
|
|
2578
|
+
return value ? "TRUE" : "FALSE";
|
|
2564
2579
|
default:
|
|
2565
2580
|
if (value == null) {
|
|
2566
2581
|
return "NULL";
|
|
@@ -2570,1032 +2585,1681 @@ function literalToSQL(value) {
|
|
|
2570
2585
|
const y2 = value.getUTCFullYear();
|
|
2571
2586
|
const m = value.getUTCMonth();
|
|
2572
2587
|
const d = value.getUTCDate();
|
|
2573
|
-
return ts === Date.UTC(y2, m, d) ? `
|
|
2588
|
+
return ts === Date.UTC(y2, m, d) ? `DATE '${y2}-${m + 1}-${d}'` : `epoch_ms(${ts})`;
|
|
2574
2589
|
} else if (value instanceof RegExp) {
|
|
2575
2590
|
return `'${value.source}'`;
|
|
2576
2591
|
} else {
|
|
2577
|
-
return
|
|
2592
|
+
return `${value}`;
|
|
2578
2593
|
}
|
|
2579
2594
|
}
|
|
2580
2595
|
}
|
|
2581
2596
|
|
|
2582
|
-
// ../sql/src/
|
|
2583
|
-
var
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
}
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
* @param {string[]} [columns=[]] The column dependencies
|
|
2592
|
-
* @param {object} [props] Additional properties for this expression.
|
|
2593
|
-
*/
|
|
2594
|
-
constructor(parts, columns, props) {
|
|
2595
|
-
this._expr = Array.isArray(parts) ? parts : [parts];
|
|
2596
|
-
this._deps = columns || [];
|
|
2597
|
-
this.annotate(props);
|
|
2598
|
-
const params = this._expr.filter((part) => isParamLike(part));
|
|
2599
|
-
if (params.length > 0) {
|
|
2600
|
-
this._params = Array.from(new Set(params));
|
|
2601
|
-
this._params.forEach((param) => {
|
|
2602
|
-
param.addEventListener("value", () => update(this, this.map?.get("value")));
|
|
2603
|
-
});
|
|
2604
|
-
} else {
|
|
2605
|
-
this.addEventListener = void 0;
|
|
2606
|
-
}
|
|
2597
|
+
// ../sql/src/ast/param.js
|
|
2598
|
+
var ParamNode = class extends ExprNode {
|
|
2599
|
+
/**
|
|
2600
|
+
* Instantiate a param node with a dynamic parameter.
|
|
2601
|
+
* @param {import('../types.js').ParamLike} param The dynamic parameter.
|
|
2602
|
+
*/
|
|
2603
|
+
constructor(param) {
|
|
2604
|
+
super(PARAM);
|
|
2605
|
+
this.param = param;
|
|
2607
2606
|
}
|
|
2608
2607
|
/**
|
|
2609
|
-
*
|
|
2610
|
-
*
|
|
2608
|
+
* Returns the current parameter value.
|
|
2609
|
+
* @returns {*}
|
|
2611
2610
|
*/
|
|
2612
2611
|
get value() {
|
|
2613
|
-
return this;
|
|
2612
|
+
return this.param.value;
|
|
2614
2613
|
}
|
|
2615
2614
|
/**
|
|
2616
|
-
*
|
|
2617
|
-
* @returns {string
|
|
2618
|
-
*/
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
if (_params) {
|
|
2622
|
-
const pset = new Set(_params.flatMap((p) => {
|
|
2623
|
-
const cols = p.value?.columns;
|
|
2624
|
-
return Array.isArray(cols) ? cols : [];
|
|
2625
|
-
}));
|
|
2626
|
-
if (pset.size) {
|
|
2627
|
-
const set = new Set(_deps);
|
|
2628
|
-
pset.forEach((col) => set.add(col));
|
|
2629
|
-
return Array.from(set);
|
|
2630
|
-
}
|
|
2631
|
-
}
|
|
2632
|
-
return _deps;
|
|
2615
|
+
* Generate a SQL query string for this node.
|
|
2616
|
+
* @returns {string}
|
|
2617
|
+
*/
|
|
2618
|
+
toString() {
|
|
2619
|
+
return literalToSQL(this.value);
|
|
2633
2620
|
}
|
|
2621
|
+
};
|
|
2622
|
+
|
|
2623
|
+
// ../sql/src/util/string.js
|
|
2624
|
+
function parseIdentifier(id) {
|
|
2625
|
+
return id.split(".");
|
|
2626
|
+
}
|
|
2627
|
+
function quoteIdentifier(value) {
|
|
2628
|
+
return `"${value}"`;
|
|
2629
|
+
}
|
|
2630
|
+
function unquote(s) {
|
|
2631
|
+
return s && isDoubleQuoted(s) ? s.slice(1, -1) : s;
|
|
2632
|
+
}
|
|
2633
|
+
function isDoubleQuoted(s) {
|
|
2634
|
+
return s[0] === '"' && s[s.length - 1] === '"';
|
|
2635
|
+
}
|
|
2636
|
+
|
|
2637
|
+
// ../sql/src/ast/table-ref.js
|
|
2638
|
+
function isTableRef(value) {
|
|
2639
|
+
return value instanceof TableRefNode;
|
|
2640
|
+
}
|
|
2641
|
+
var TableRefNode = class extends ExprNode {
|
|
2634
2642
|
/**
|
|
2635
|
-
*
|
|
2636
|
-
* @
|
|
2643
|
+
* Instantiate a table reference node.
|
|
2644
|
+
* @param {string | string[]} table The table name.
|
|
2637
2645
|
*/
|
|
2638
|
-
|
|
2639
|
-
|
|
2646
|
+
constructor(table2) {
|
|
2647
|
+
super(TABLE_REF);
|
|
2648
|
+
this.table = [table2].flat();
|
|
2640
2649
|
}
|
|
2641
2650
|
/**
|
|
2642
|
-
*
|
|
2643
|
-
* @
|
|
2644
|
-
* @returns This SQL expression.
|
|
2651
|
+
* The table name without database or schema namespaces.
|
|
2652
|
+
* @returns {string}
|
|
2645
2653
|
*/
|
|
2646
|
-
|
|
2647
|
-
return
|
|
2654
|
+
get name() {
|
|
2655
|
+
return this.table[this.table.length - 1];
|
|
2648
2656
|
}
|
|
2649
2657
|
/**
|
|
2650
|
-
* Generate a SQL
|
|
2651
|
-
* @returns {string}
|
|
2658
|
+
* Generate a SQL query string for this node.
|
|
2659
|
+
* @returns {string}
|
|
2652
2660
|
*/
|
|
2653
2661
|
toString() {
|
|
2654
|
-
return this.
|
|
2662
|
+
return this.table.map((t) => quoteIdentifier(t)).join(".");
|
|
2655
2663
|
}
|
|
2664
|
+
};
|
|
2665
|
+
|
|
2666
|
+
// ../sql/src/ast/function.js
|
|
2667
|
+
var FunctionNode = class extends ExprNode {
|
|
2656
2668
|
/**
|
|
2657
|
-
*
|
|
2658
|
-
* @param {string}
|
|
2659
|
-
* @param {
|
|
2660
|
-
* invoke upon updates. A callback may optionally return a Promise that
|
|
2661
|
-
* upstream listeners may await before proceeding.
|
|
2669
|
+
* Instantiate a function node.
|
|
2670
|
+
* @param {string} name The function name.
|
|
2671
|
+
* @param {ExprNode[]} [args=[]] The function arguments.
|
|
2662
2672
|
*/
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2673
|
+
constructor(name, args = []) {
|
|
2674
|
+
super(FUNCTION);
|
|
2675
|
+
this.name = name;
|
|
2676
|
+
this.args = args;
|
|
2667
2677
|
}
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2678
|
+
/**
|
|
2679
|
+
* Generate a SQL query string for this node.
|
|
2680
|
+
* @returns {string}
|
|
2681
|
+
*/
|
|
2682
|
+
toString() {
|
|
2683
|
+
const { name, args } = this;
|
|
2684
|
+
return `${name}(${args.join(", ")})`;
|
|
2672
2685
|
}
|
|
2686
|
+
};
|
|
2687
|
+
|
|
2688
|
+
// ../sql/src/util/function.js
|
|
2689
|
+
function fn(name, ...args) {
|
|
2690
|
+
return new FunctionNode(name, argsList(args).map(asNode));
|
|
2673
2691
|
}
|
|
2674
|
-
function
|
|
2675
|
-
|
|
2676
|
-
const cols = /* @__PURE__ */ new Set();
|
|
2677
|
-
const n = exprs.length;
|
|
2678
|
-
for (let i = 0, k = 0; i < n; ) {
|
|
2679
|
-
const e = exprs[i];
|
|
2680
|
-
if (isParamLike(e)) {
|
|
2681
|
-
spans[++k] = e;
|
|
2682
|
-
} else {
|
|
2683
|
-
if (Array.isArray(e?.columns)) {
|
|
2684
|
-
e.columns.forEach((col) => cols.add(col));
|
|
2685
|
-
}
|
|
2686
|
-
spans[k] += typeof e === "string" ? e : literalToSQL(e);
|
|
2687
|
-
}
|
|
2688
|
-
const s = strings[++i];
|
|
2689
|
-
if (isParamLike(spans[k])) {
|
|
2690
|
-
spans[++k] = s;
|
|
2691
|
-
} else {
|
|
2692
|
-
spans[k] += s;
|
|
2693
|
-
}
|
|
2694
|
-
}
|
|
2695
|
-
return { spans, cols: Array.from(cols) };
|
|
2692
|
+
function aggFn(name, ...args) {
|
|
2693
|
+
return new AggregateNode(name, argsList(args).map(asNode));
|
|
2696
2694
|
}
|
|
2697
|
-
function
|
|
2698
|
-
|
|
2699
|
-
return new SQLExpression(spans, cols);
|
|
2695
|
+
function exprList(list2, cast2 = asNode) {
|
|
2696
|
+
return list2.flat().filter((x2) => x2 != null).map((x2) => cast2(x2));
|
|
2700
2697
|
}
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
return
|
|
2698
|
+
function argsList(list2) {
|
|
2699
|
+
const n = list2.length;
|
|
2700
|
+
let i = n;
|
|
2701
|
+
for (; i > 0 && list2[i - 1] === void 0; --i) ;
|
|
2702
|
+
return i < n ? list2.slice(0, i) : list2;
|
|
2706
2703
|
}
|
|
2707
2704
|
|
|
2708
|
-
// ../sql/src/
|
|
2709
|
-
|
|
2710
|
-
value
|
|
2711
|
-
toString: () => literalToSQL(value)
|
|
2712
|
-
});
|
|
2713
|
-
|
|
2714
|
-
// ../sql/src/operators.js
|
|
2715
|
-
function visit2(callback) {
|
|
2716
|
-
callback(this.op, this);
|
|
2717
|
-
this.children?.forEach((v) => v.visit(callback));
|
|
2718
|
-
}
|
|
2719
|
-
function logical(op, clauses) {
|
|
2720
|
-
const children = clauses.filter((x2) => x2 != null).map(asColumn);
|
|
2721
|
-
const strings = children.map((c, i) => i ? ` ${op} ` : "");
|
|
2722
|
-
if (children.length === 1) {
|
|
2723
|
-
strings.push("");
|
|
2724
|
-
} else if (children.length > 1) {
|
|
2725
|
-
strings[0] = "(";
|
|
2726
|
-
strings.push(")");
|
|
2727
|
-
}
|
|
2728
|
-
return sql(strings, ...children).annotate({ op, children, visit: visit2 });
|
|
2729
|
-
}
|
|
2730
|
-
var and = (...clauses) => logical("AND", clauses.flat());
|
|
2731
|
-
var or = (...clauses) => logical("OR", clauses.flat());
|
|
2732
|
-
var unaryOp = (op) => (a) => sql`(${op} ${asColumn(a)})`.annotate({ op, a, visit: visit2 });
|
|
2733
|
-
var not = unaryOp("NOT");
|
|
2734
|
-
var unaryPostOp = (op) => (a) => sql`(${asColumn(a)} ${op})`.annotate({ op, a, visit: visit2 });
|
|
2735
|
-
var isNull = unaryPostOp("IS NULL");
|
|
2736
|
-
var isNotNull = unaryPostOp("IS NOT NULL");
|
|
2737
|
-
var binaryOp = (op) => (a, b) => sql`(${asColumn(a)} ${op} ${asColumn(b)})`.annotate({ op, a, b, visit: visit2 });
|
|
2738
|
-
var eq = binaryOp("=");
|
|
2739
|
-
var neq = binaryOp("<>");
|
|
2740
|
-
var lt = binaryOp("<");
|
|
2741
|
-
var gt = binaryOp(">");
|
|
2742
|
-
var lte = binaryOp("<=");
|
|
2743
|
-
var gte = binaryOp(">=");
|
|
2744
|
-
var isDistinct = binaryOp("IS DISTINCT FROM");
|
|
2745
|
-
var isNotDistinct = binaryOp("IS NOT DISTINCT FROM");
|
|
2746
|
-
function rangeOp(op, a, range, exclusive) {
|
|
2747
|
-
a = asColumn(a);
|
|
2748
|
-
const prefix2 = op.startsWith("NOT ") ? "NOT " : "";
|
|
2749
|
-
const expr = !range ? sql`` : exclusive ? sql`${prefix2}(${range[0]} <= ${a} AND ${a} < ${range[1]})` : sql`(${a} ${op} ${range[0]} AND ${range[1]})`;
|
|
2750
|
-
return expr.annotate({ op, visit: visit2, field: a, range });
|
|
2751
|
-
}
|
|
2752
|
-
var isBetween = (a, range, exclusive) => rangeOp("BETWEEN", a, range, exclusive);
|
|
2753
|
-
|
|
2754
|
-
// ../sql/src/repeat.js
|
|
2755
|
-
function repeat(length2, str) {
|
|
2756
|
-
return Array.from({ length: length2 }, () => str);
|
|
2705
|
+
// ../sql/src/util/type-check.js
|
|
2706
|
+
function isString(value) {
|
|
2707
|
+
return typeof value === "string";
|
|
2757
2708
|
}
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
const cast2 = type ? `::${type}` : "";
|
|
2764
|
-
const expr = args.length ? sql([`${op}(`, ...repeat(args.length - 1, ", "), `)${cast2}`], ...args) : sql`${op}()${cast2}`;
|
|
2765
|
-
return expr.annotate({ func: op, args });
|
|
2766
|
-
};
|
|
2709
|
+
function isArray2(value) {
|
|
2710
|
+
return Array.isArray(value);
|
|
2711
|
+
}
|
|
2712
|
+
function isParamLike(value) {
|
|
2713
|
+
return value && typeof value.addEventListener === "function" && value.dynamic !== false && "value" in value;
|
|
2767
2714
|
}
|
|
2768
|
-
var regexp_matches = functionCall("REGEXP_MATCHES");
|
|
2769
|
-
var contains = functionCall("CONTAINS");
|
|
2770
|
-
var prefix = functionCall("PREFIX");
|
|
2771
|
-
var suffix = functionCall("SUFFIX");
|
|
2772
|
-
var lower = functionCall("LOWER");
|
|
2773
|
-
var upper = functionCall("UPPER");
|
|
2774
|
-
var length = functionCall("LENGTH");
|
|
2775
|
-
var isNaN2 = functionCall("ISNAN");
|
|
2776
|
-
var isFinite = functionCall("ISFINITE");
|
|
2777
|
-
var isInfinite = functionCall("ISINF");
|
|
2778
2715
|
|
|
2779
|
-
// ../sql/src/
|
|
2780
|
-
var
|
|
2781
|
-
/**
|
|
2782
|
-
*
|
|
2783
|
-
* @param {string}
|
|
2784
|
-
* @param {
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
* @param {*} [order] Sorting (order by) expressions.
|
|
2789
|
-
* @param {*} [frame] The window frame definition.
|
|
2790
|
-
*/
|
|
2791
|
-
constructor(op, func, type, name, group = "", order = "", frame = "") {
|
|
2792
|
-
let expr;
|
|
2793
|
-
const noWindowParams = !(group || order || frame);
|
|
2794
|
-
if (name && noWindowParams) {
|
|
2795
|
-
expr = name ? sql`${func} OVER "${name}"` : sql`${func} OVER ()`;
|
|
2796
|
-
} else {
|
|
2797
|
-
const s1 = group && order ? " " : "";
|
|
2798
|
-
const s2 = (group || order) && frame ? " " : "";
|
|
2799
|
-
expr = sql`${func} OVER (${name ? `"${name}" ` : ""}${group}${s1}${order}${s2}${frame})`;
|
|
2800
|
-
}
|
|
2801
|
-
if (type) {
|
|
2802
|
-
expr = sql`(${expr})::${type}`;
|
|
2803
|
-
}
|
|
2804
|
-
const { _expr, _deps } = expr;
|
|
2805
|
-
super(_expr, _deps);
|
|
2806
|
-
this.window = op;
|
|
2807
|
-
this.func = func;
|
|
2808
|
-
this.type = type;
|
|
2716
|
+
// ../sql/src/ast/window.js
|
|
2717
|
+
var WindowClauseNode = class extends SQLNode {
|
|
2718
|
+
/**
|
|
2719
|
+
* Instantiate a window clause node.
|
|
2720
|
+
* @param {string} name The window name.
|
|
2721
|
+
* @param {WindowDefNode} def The window definition.
|
|
2722
|
+
*/
|
|
2723
|
+
constructor(name, def) {
|
|
2724
|
+
super(WINDOW_CLAUSE);
|
|
2809
2725
|
this.name = name;
|
|
2810
|
-
this.
|
|
2811
|
-
this.order = order;
|
|
2812
|
-
this.frame = frame;
|
|
2726
|
+
this.def = def;
|
|
2813
2727
|
}
|
|
2814
|
-
|
|
2815
|
-
return this.
|
|
2728
|
+
toString() {
|
|
2729
|
+
return `${quoteIdentifier(this.name)} AS ${this.def}`;
|
|
2816
2730
|
}
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2731
|
+
};
|
|
2732
|
+
var WindowNode = class _WindowNode extends ExprNode {
|
|
2733
|
+
/**
|
|
2734
|
+
* Instantiate a window node.
|
|
2735
|
+
* @param {WindowFunctionNode | AggregateNode} func The window function call.
|
|
2736
|
+
* @param {WindowDefNode} [over] The window definition or name.
|
|
2737
|
+
*/
|
|
2738
|
+
constructor(func, over2 = new WindowDefNode()) {
|
|
2739
|
+
super(WINDOW);
|
|
2740
|
+
this.func = func;
|
|
2741
|
+
this.def = over2;
|
|
2820
2742
|
}
|
|
2821
2743
|
/**
|
|
2822
|
-
* Return an updated window
|
|
2744
|
+
* Return an updated window over a named window definition.
|
|
2823
2745
|
* @param {string} name The window definition name.
|
|
2824
|
-
* @returns {
|
|
2746
|
+
* @returns {WindowNode} A new window node.
|
|
2825
2747
|
*/
|
|
2826
2748
|
over(name) {
|
|
2827
|
-
|
|
2828
|
-
return new _WindowFunction(op, func, type, name, group, order, frame);
|
|
2749
|
+
return new _WindowNode(this.func, this.def.over(name));
|
|
2829
2750
|
}
|
|
2830
2751
|
/**
|
|
2831
|
-
* Return an updated window
|
|
2832
|
-
* @param {
|
|
2833
|
-
* @returns {
|
|
2752
|
+
* Return an updated window with the given partitions.
|
|
2753
|
+
* @param {...import('../types.js').ExprVarArgs} expr The partition by criteria.
|
|
2754
|
+
* @returns {WindowNode} A new window node.
|
|
2834
2755
|
*/
|
|
2835
2756
|
partitionby(...expr) {
|
|
2836
|
-
|
|
2837
|
-
const group = sql(
|
|
2838
|
-
["PARTITION BY ", repeat(exprs.length - 1, ", "), ""],
|
|
2839
|
-
...exprs
|
|
2840
|
-
);
|
|
2841
|
-
const { window: op, func, type, name, order, frame } = this;
|
|
2842
|
-
return new _WindowFunction(op, func, type, name, group, order, frame);
|
|
2757
|
+
return new _WindowNode(this.func, this.def.partitionby(...expr));
|
|
2843
2758
|
}
|
|
2844
2759
|
/**
|
|
2845
|
-
* Return an updated window
|
|
2846
|
-
* @param {
|
|
2847
|
-
* @returns {
|
|
2760
|
+
* Return an updated window with the given ordering.
|
|
2761
|
+
* @param {...import('../types.js').ExprVarArgs} expr The order by criteria.
|
|
2762
|
+
* @returns {WindowNode} A new window node.
|
|
2848
2763
|
*/
|
|
2849
2764
|
orderby(...expr) {
|
|
2850
|
-
|
|
2851
|
-
const order = sql(
|
|
2852
|
-
["ORDER BY ", repeat(exprs.length - 1, ", "), ""],
|
|
2853
|
-
...exprs
|
|
2854
|
-
);
|
|
2855
|
-
const { window: op, func, type, name, group, frame } = this;
|
|
2856
|
-
return new _WindowFunction(op, func, type, name, group, order, frame);
|
|
2765
|
+
return new _WindowNode(this.func, this.def.orderby(...expr));
|
|
2857
2766
|
}
|
|
2858
2767
|
/**
|
|
2859
|
-
* Return an updated window
|
|
2860
|
-
* @param {
|
|
2861
|
-
* @returns {
|
|
2768
|
+
* Return an updated window with the given rows frame.
|
|
2769
|
+
* @param {FrameExtent} extent The row-based window frame extent.
|
|
2770
|
+
* @returns {WindowNode} A new window node.
|
|
2862
2771
|
*/
|
|
2863
|
-
rows(
|
|
2864
|
-
|
|
2865
|
-
const { window: op, func, type, name, group, order } = this;
|
|
2866
|
-
return new _WindowFunction(op, func, type, name, group, order, frame);
|
|
2772
|
+
rows(extent) {
|
|
2773
|
+
return new _WindowNode(this.func, this.def.rows(extent));
|
|
2867
2774
|
}
|
|
2868
2775
|
/**
|
|
2869
|
-
* Return an updated window
|
|
2870
|
-
* @param {
|
|
2871
|
-
* @returns {
|
|
2776
|
+
* Return an updated window with the given range frame.
|
|
2777
|
+
* @param {FrameExtent} extent The range-based window frame extent.
|
|
2778
|
+
* @returns {WindowNode} A new window node.
|
|
2872
2779
|
*/
|
|
2873
|
-
range(
|
|
2874
|
-
|
|
2875
|
-
const { window: op, func, type, name, group, order } = this;
|
|
2876
|
-
return new _WindowFunction(op, func, type, name, group, order, frame);
|
|
2877
|
-
}
|
|
2878
|
-
};
|
|
2879
|
-
function windowFrame(type, frame) {
|
|
2880
|
-
if (isParamLike(frame)) {
|
|
2881
|
-
const expr = sql`${frame}`;
|
|
2882
|
-
expr.toString = () => `${type} ${frameToSQL(frame.value)}`;
|
|
2883
|
-
return expr;
|
|
2884
|
-
}
|
|
2885
|
-
return `${type} ${frameToSQL(frame)}`;
|
|
2886
|
-
}
|
|
2887
|
-
function frameToSQL(frame) {
|
|
2888
|
-
const [prev, next] = frame;
|
|
2889
|
-
const a = prev === 0 ? "CURRENT ROW" : Number.isFinite(prev) ? `${Math.abs(prev)} PRECEDING` : "UNBOUNDED PRECEDING";
|
|
2890
|
-
const b = next === 0 ? "CURRENT ROW" : Number.isFinite(next) ? `${Math.abs(next)} FOLLOWING` : "UNBOUNDED FOLLOWING";
|
|
2891
|
-
return `BETWEEN ${a} AND ${b}`;
|
|
2892
|
-
}
|
|
2893
|
-
function winf(op, type) {
|
|
2894
|
-
return (...values) => {
|
|
2895
|
-
const func = functionCall(op)(...values);
|
|
2896
|
-
return new WindowFunction(op, func, type);
|
|
2897
|
-
};
|
|
2898
|
-
}
|
|
2899
|
-
var row_number = winf("ROW_NUMBER", "INTEGER");
|
|
2900
|
-
var rank = winf("RANK", "INTEGER");
|
|
2901
|
-
var dense_rank = winf("DENSE_RANK", "INTEGER");
|
|
2902
|
-
var percent_rank = winf("PERCENT_RANK");
|
|
2903
|
-
var cume_dist = winf("CUME_DIST");
|
|
2904
|
-
var ntile = winf("NTILE");
|
|
2905
|
-
var lag = winf("LAG");
|
|
2906
|
-
var lead = winf("LEAD");
|
|
2907
|
-
var first_value = winf("FIRST_VALUE");
|
|
2908
|
-
var last_value = winf("LAST_VALUE");
|
|
2909
|
-
var nth_value = winf("NTH_VALUE");
|
|
2910
|
-
|
|
2911
|
-
// ../sql/src/aggregates.js
|
|
2912
|
-
function agg(strings, ...exprs) {
|
|
2913
|
-
return sql(strings, ...exprs).annotate({ aggregate: true });
|
|
2914
|
-
}
|
|
2915
|
-
var AggregateFunction = class _AggregateFunction extends SQLExpression {
|
|
2916
|
-
/**
|
|
2917
|
-
* Create a new AggregateFunction instance.
|
|
2918
|
-
* @param {*} op The aggregate operation.
|
|
2919
|
-
* @param {*} [args] The aggregate function arguments.
|
|
2920
|
-
* @param {*} [type] The SQL data type to cast to.
|
|
2921
|
-
* @param {boolean} [isDistinct] Flag indicating if this is a distinct value aggregate.
|
|
2922
|
-
* @param {*} [filter] Filtering expression to apply prior to aggregation.
|
|
2923
|
-
*/
|
|
2924
|
-
constructor(op, args, type, isDistinct2, filter) {
|
|
2925
|
-
args = (args || []).map(asColumn);
|
|
2926
|
-
const { strings, exprs } = aggExpr(op, args, type, isDistinct2, filter);
|
|
2927
|
-
const { spans, cols } = parseSQL(strings, exprs);
|
|
2928
|
-
super(spans, cols);
|
|
2929
|
-
this.aggregate = op;
|
|
2930
|
-
this.args = args;
|
|
2931
|
-
this.type = type;
|
|
2932
|
-
this.isDistinct = isDistinct2;
|
|
2933
|
-
this.filter = filter;
|
|
2934
|
-
}
|
|
2935
|
-
get basis() {
|
|
2936
|
-
return this.column;
|
|
2937
|
-
}
|
|
2938
|
-
get label() {
|
|
2939
|
-
const { aggregate: op, args, isDistinct: isDistinct2 } = this;
|
|
2940
|
-
const dist = isDistinct2 ? "DISTINCT" + (args.length ? " " : "") : "";
|
|
2941
|
-
const tail = args.length ? `(${dist}${args.map(unquoted).join(", ")})` : "";
|
|
2942
|
-
return `${op.toLowerCase()}${tail}`;
|
|
2780
|
+
range(extent) {
|
|
2781
|
+
return new _WindowNode(this.func, this.def.range(extent));
|
|
2943
2782
|
}
|
|
2944
2783
|
/**
|
|
2945
|
-
*
|
|
2946
|
-
* @returns {
|
|
2784
|
+
* Generate a SQL query string for this node.
|
|
2785
|
+
* @returns {string}
|
|
2947
2786
|
*/
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
return new _AggregateFunction(op, args, type, true, filter);
|
|
2787
|
+
toString() {
|
|
2788
|
+
return `${this.func} OVER ${this.def}`;
|
|
2951
2789
|
}
|
|
2790
|
+
};
|
|
2791
|
+
var WindowDefNode = class extends SQLNode {
|
|
2952
2792
|
/**
|
|
2953
|
-
*
|
|
2954
|
-
* @param {
|
|
2955
|
-
* @
|
|
2793
|
+
* Instantiate a window definition node.
|
|
2794
|
+
* @param {string} [name] The base window definition name.
|
|
2795
|
+
* @param {ExprNode[]} [partition] The partition by criteria.
|
|
2796
|
+
* @param {ExprNode[]} [order] The order by criteria.
|
|
2797
|
+
* @param {WindowFrameNode} [frame] The window frame definition.
|
|
2956
2798
|
*/
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2799
|
+
constructor(name, partition, order, frame) {
|
|
2800
|
+
super(WINDOW_DEF);
|
|
2801
|
+
this.name = name;
|
|
2802
|
+
this.partition = partition;
|
|
2803
|
+
this.order = order;
|
|
2804
|
+
this.frame = frame;
|
|
2960
2805
|
}
|
|
2961
2806
|
/**
|
|
2962
|
-
* Return
|
|
2963
|
-
* @
|
|
2807
|
+
* Return an updated window definition with the given base name.
|
|
2808
|
+
* @param {string} name The base window definition name.
|
|
2809
|
+
* @returns {WindowDefNode} A new window definition node.
|
|
2964
2810
|
*/
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
const func = new _AggregateFunction(op, args, null, isDistinct2);
|
|
2968
|
-
return new WindowFunction(op, func, type);
|
|
2811
|
+
over(name) {
|
|
2812
|
+
return deriveDef(this, { name });
|
|
2969
2813
|
}
|
|
2970
2814
|
/**
|
|
2971
|
-
* Return
|
|
2972
|
-
* @param {
|
|
2973
|
-
* @returns {
|
|
2815
|
+
* Return an updated window definition with the given partitions.
|
|
2816
|
+
* @param {...import('../types.js').ExprVarArgs} expr The partition by criteria.
|
|
2817
|
+
* @returns {WindowDefNode} A new window definition node.
|
|
2974
2818
|
*/
|
|
2975
2819
|
partitionby(...expr) {
|
|
2976
|
-
return this
|
|
2820
|
+
return deriveDef(this, { partition: exprList(expr) });
|
|
2977
2821
|
}
|
|
2978
2822
|
/**
|
|
2979
|
-
* Return
|
|
2980
|
-
* @param {
|
|
2981
|
-
* @returns {
|
|
2823
|
+
* Return an updated window definition with the given ordering.
|
|
2824
|
+
* @param {...import('../types.js').ExprVarArgs} expr The order by criteria.
|
|
2825
|
+
* @returns {WindowDefNode} A new window definition node.
|
|
2982
2826
|
*/
|
|
2983
2827
|
orderby(...expr) {
|
|
2984
|
-
return this
|
|
2828
|
+
return deriveDef(this, { order: exprList(expr) });
|
|
2985
2829
|
}
|
|
2986
2830
|
/**
|
|
2987
|
-
* Return
|
|
2988
|
-
* @param {
|
|
2989
|
-
* @returns {
|
|
2831
|
+
* Return an updated window definition with the given rows frame.
|
|
2832
|
+
* @param {FrameExtent} extent The row-based window frame extent.
|
|
2833
|
+
* @returns {WindowDefNode} A new window definition node.
|
|
2990
2834
|
*/
|
|
2991
|
-
rows(
|
|
2992
|
-
return this
|
|
2835
|
+
rows(extent) {
|
|
2836
|
+
return deriveDef(this, { frame: new WindowFrameNode(extent) });
|
|
2993
2837
|
}
|
|
2994
2838
|
/**
|
|
2995
|
-
* Return
|
|
2996
|
-
* @param {
|
|
2997
|
-
* @returns {
|
|
2839
|
+
* Return an updated window definition with the given range frame.
|
|
2840
|
+
* @param {FrameExtent} extent The range-based window frame extent.
|
|
2841
|
+
* @returns {WindowDefNode} A new window definition node.
|
|
2998
2842
|
*/
|
|
2999
|
-
range(
|
|
3000
|
-
return this
|
|
3001
|
-
}
|
|
3002
|
-
};
|
|
3003
|
-
function aggExpr(op, args, type, isDistinct2, filter) {
|
|
3004
|
-
const close = `)${type ? `::${type}` : ""}`;
|
|
3005
|
-
let strings = [`${op}(${isDistinct2 ? "DISTINCT " : ""}`];
|
|
3006
|
-
let exprs = [];
|
|
3007
|
-
if (args.length) {
|
|
3008
|
-
strings = strings.concat([
|
|
3009
|
-
...repeat(args.length - 1, ", "),
|
|
3010
|
-
`${close}${filter ? " FILTER (WHERE " : ""}`,
|
|
3011
|
-
...filter ? [")"] : []
|
|
3012
|
-
]);
|
|
3013
|
-
exprs = [...args, ...filter ? [filter] : []];
|
|
3014
|
-
} else {
|
|
3015
|
-
strings[0] += "*" + close;
|
|
3016
|
-
}
|
|
3017
|
-
return { exprs, strings };
|
|
3018
|
-
}
|
|
3019
|
-
function unquoted(value) {
|
|
3020
|
-
const s = literalToSQL(value);
|
|
3021
|
-
return s && s.startsWith('"') && s.endsWith('"') ? s.slice(1, -1) : s;
|
|
3022
|
-
}
|
|
3023
|
-
function aggf(op, type) {
|
|
3024
|
-
return (...args) => new AggregateFunction(op, args, type);
|
|
3025
|
-
}
|
|
3026
|
-
var count = aggf("COUNT", "INTEGER");
|
|
3027
|
-
var avg = aggf("AVG");
|
|
3028
|
-
var mean = aggf("AVG");
|
|
3029
|
-
var mad = aggf("MAD");
|
|
3030
|
-
var max = aggf("MAX");
|
|
3031
|
-
var min = aggf("MIN");
|
|
3032
|
-
var sum = aggf("SUM", "DOUBLE");
|
|
3033
|
-
var product = aggf("PRODUCT");
|
|
3034
|
-
var median = aggf("MEDIAN");
|
|
3035
|
-
var quantile = aggf("QUANTILE");
|
|
3036
|
-
var mode = aggf("MODE");
|
|
3037
|
-
var variance = aggf("VARIANCE");
|
|
3038
|
-
var stddev = aggf("STDDEV");
|
|
3039
|
-
var skewness = aggf("SKEWNESS");
|
|
3040
|
-
var kurtosis = aggf("KURTOSIS");
|
|
3041
|
-
var entropy = aggf("ENTROPY");
|
|
3042
|
-
var varPop = aggf("VAR_POP");
|
|
3043
|
-
var stddevPop = aggf("STDDEV_POP");
|
|
3044
|
-
var corr = aggf("CORR");
|
|
3045
|
-
var covariance = aggf("COVAR_SAMP");
|
|
3046
|
-
var covarPop = aggf("COVAR_POP");
|
|
3047
|
-
var regrIntercept = aggf("REGR_INTERCEPT");
|
|
3048
|
-
var regrSlope = aggf("REGR_SLOPE");
|
|
3049
|
-
var regrCount = aggf("REGR_COUNT");
|
|
3050
|
-
var regrR2 = aggf("REGR_R2");
|
|
3051
|
-
var regrSYY = aggf("REGR_SYY");
|
|
3052
|
-
var regrSXX = aggf("REGR_SXX");
|
|
3053
|
-
var regrSXY = aggf("REGR_SXY");
|
|
3054
|
-
var regrAvgX = aggf("REGR_AVGX");
|
|
3055
|
-
var regrAvgY = aggf("REGR_AVGY");
|
|
3056
|
-
var first = aggf("FIRST");
|
|
3057
|
-
var last = aggf("LAST");
|
|
3058
|
-
var argmin = aggf("ARG_MIN");
|
|
3059
|
-
var argmax = aggf("ARG_MAX");
|
|
3060
|
-
var stringAgg = aggf("STRING_AGG");
|
|
3061
|
-
var arrayAgg = aggf("ARRAY_AGG");
|
|
3062
|
-
|
|
3063
|
-
// ../sql/src/datetime.js
|
|
3064
|
-
var epoch_ms = (expr) => {
|
|
3065
|
-
return sql`epoch_ms(${asColumn(expr)})`;
|
|
3066
|
-
};
|
|
3067
|
-
|
|
3068
|
-
// ../sql/src/spatial.js
|
|
3069
|
-
var geojson = functionCall("ST_AsGeoJSON");
|
|
3070
|
-
var x = functionCall("ST_X");
|
|
3071
|
-
var y = functionCall("ST_Y");
|
|
3072
|
-
var centroid = functionCall("ST_CENTROID");
|
|
3073
|
-
|
|
3074
|
-
// ../sql/src/Query.js
|
|
3075
|
-
var Query = class _Query {
|
|
3076
|
-
static select(...expr) {
|
|
3077
|
-
return new _Query().select(...expr);
|
|
3078
|
-
}
|
|
3079
|
-
static from(...expr) {
|
|
3080
|
-
return new _Query().from(...expr);
|
|
3081
|
-
}
|
|
3082
|
-
static with(...expr) {
|
|
3083
|
-
return new _Query().with(...expr);
|
|
3084
|
-
}
|
|
3085
|
-
static union(...queries) {
|
|
3086
|
-
return new SetOperation("UNION", queries.flat());
|
|
3087
|
-
}
|
|
3088
|
-
static unionAll(...queries) {
|
|
3089
|
-
return new SetOperation("UNION ALL", queries.flat());
|
|
3090
|
-
}
|
|
3091
|
-
static intersect(...queries) {
|
|
3092
|
-
return new SetOperation("INTERSECT", queries.flat());
|
|
3093
|
-
}
|
|
3094
|
-
static except(...queries) {
|
|
3095
|
-
return new SetOperation("EXCEPT", queries.flat());
|
|
3096
|
-
}
|
|
3097
|
-
static describe(query) {
|
|
3098
|
-
const q = query.clone();
|
|
3099
|
-
const { clone, toString } = q;
|
|
3100
|
-
return Object.assign(q, {
|
|
3101
|
-
describe: true,
|
|
3102
|
-
clone: () => _Query.describe(clone.call(q)),
|
|
3103
|
-
toString: () => `DESCRIBE ${toString.call(q)}`
|
|
3104
|
-
});
|
|
3105
|
-
}
|
|
3106
|
-
constructor() {
|
|
3107
|
-
this.query = {
|
|
3108
|
-
with: [],
|
|
3109
|
-
select: [],
|
|
3110
|
-
from: [],
|
|
3111
|
-
where: [],
|
|
3112
|
-
groupby: [],
|
|
3113
|
-
having: [],
|
|
3114
|
-
window: [],
|
|
3115
|
-
qualify: [],
|
|
3116
|
-
orderby: []
|
|
3117
|
-
};
|
|
3118
|
-
this.cteFor = null;
|
|
3119
|
-
}
|
|
3120
|
-
clone() {
|
|
3121
|
-
const q = new _Query();
|
|
3122
|
-
q.query = { ...this.query };
|
|
3123
|
-
return q;
|
|
2843
|
+
range(extent) {
|
|
2844
|
+
return deriveDef(this, { frame: new WindowFrameNode(extent, true) });
|
|
3124
2845
|
}
|
|
3125
2846
|
/**
|
|
3126
|
-
*
|
|
3127
|
-
* @returns {
|
|
2847
|
+
* Generate a SQL query string for this node.
|
|
2848
|
+
* @returns {string}
|
|
3128
2849
|
*/
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
const list2 = [];
|
|
3140
|
-
const add = (as, q) => {
|
|
3141
|
-
const query2 = q.clone();
|
|
3142
|
-
query2.cteFor = this;
|
|
3143
|
-
list2.push({ as, query: query2 });
|
|
3144
|
-
};
|
|
3145
|
-
expr.flat().forEach((e) => {
|
|
3146
|
-
if (e == null) {
|
|
3147
|
-
} else if (e.as && e.query) {
|
|
3148
|
-
add(e.as, e.query);
|
|
3149
|
-
} else {
|
|
3150
|
-
for (const as in e) {
|
|
3151
|
-
add(as, e[as]);
|
|
3152
|
-
}
|
|
3153
|
-
}
|
|
3154
|
-
});
|
|
3155
|
-
query.with = query.with.concat(list2);
|
|
3156
|
-
return this;
|
|
3157
|
-
}
|
|
2850
|
+
toString() {
|
|
2851
|
+
const { name, partition, order, frame } = this;
|
|
2852
|
+
const base = name && quoteIdentifier(name);
|
|
2853
|
+
const def = [
|
|
2854
|
+
base,
|
|
2855
|
+
partition?.length && `PARTITION BY ${partition.join(", ")}`,
|
|
2856
|
+
order?.length && `ORDER BY ${order.join(", ")}`,
|
|
2857
|
+
frame
|
|
2858
|
+
].filter((x2) => x2);
|
|
2859
|
+
return base && def.length < 2 ? base : `(${def.join(" ")})`;
|
|
3158
2860
|
}
|
|
2861
|
+
};
|
|
2862
|
+
var WindowFrameNode = class extends SQLNode {
|
|
3159
2863
|
/**
|
|
3160
|
-
*
|
|
3161
|
-
* @
|
|
2864
|
+
* Instantiate a window frame definition node.
|
|
2865
|
+
* @param {FrameExtent} extent The frame extent as [preceding, following]
|
|
2866
|
+
* row or interval offsets.
|
|
2867
|
+
* @param {boolean} [range] The frame type: `true` for range, otherwise rows.
|
|
2868
|
+
* @param {ExprNode} [exclude] The window exclusion criteria.
|
|
3162
2869
|
*/
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
select(...expr) {
|
|
3169
|
-
const { query } = this;
|
|
3170
|
-
if (expr.length === 0) {
|
|
3171
|
-
return query.select;
|
|
3172
|
-
} else {
|
|
3173
|
-
const list2 = [];
|
|
3174
|
-
for (const e of expr.flat()) {
|
|
3175
|
-
if (e == null) {
|
|
3176
|
-
} else if (typeof e === "string") {
|
|
3177
|
-
list2.push({ as: e, expr: asColumn(e) });
|
|
3178
|
-
} else if (e instanceof Ref) {
|
|
3179
|
-
list2.push({ as: e.column, expr: e });
|
|
3180
|
-
} else if (Array.isArray(e)) {
|
|
3181
|
-
list2.push({ as: e[0], expr: e[1] });
|
|
3182
|
-
} else {
|
|
3183
|
-
for (const as in e) {
|
|
3184
|
-
list2.push({ as: unquote(as), expr: asColumn(e[as]) });
|
|
3185
|
-
}
|
|
3186
|
-
}
|
|
3187
|
-
}
|
|
3188
|
-
const keys = new Set(list2.map((x2) => x2.as));
|
|
3189
|
-
query.select = query.select.filter((x2) => !keys.has(x2.as)).concat(list2.filter((x2) => x2.expr));
|
|
3190
|
-
return this;
|
|
3191
|
-
}
|
|
3192
|
-
}
|
|
3193
|
-
$select(...expr) {
|
|
3194
|
-
this.query.select = [];
|
|
3195
|
-
return this.select(...expr);
|
|
3196
|
-
}
|
|
3197
|
-
distinct(value = true) {
|
|
3198
|
-
this.query.distinct = !!value;
|
|
3199
|
-
return this;
|
|
2870
|
+
constructor(extent, range = false, exclude = void 0) {
|
|
2871
|
+
super(WINDOW_FRAME);
|
|
2872
|
+
this.extent = isParamLike(extent) ? new ParamNode(extent) : extent;
|
|
2873
|
+
this.range = range;
|
|
2874
|
+
this.exclude = exclude;
|
|
3200
2875
|
}
|
|
3201
2876
|
/**
|
|
3202
|
-
*
|
|
3203
|
-
* @returns {
|
|
2877
|
+
* Generate a SQL query string for this node.
|
|
2878
|
+
* @returns {string}
|
|
3204
2879
|
*/
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
if (expr.length === 0) {
|
|
3213
|
-
return query.from;
|
|
3214
|
-
} else {
|
|
3215
|
-
const list2 = [];
|
|
3216
|
-
expr.flat().forEach((e) => {
|
|
3217
|
-
if (e == null) {
|
|
3218
|
-
} else if (typeof e === "string") {
|
|
3219
|
-
list2.push({ as: e, from: asRelation(e) });
|
|
3220
|
-
} else if (e instanceof Ref) {
|
|
3221
|
-
list2.push({ as: e.table, from: e });
|
|
3222
|
-
} else if (isQuery(e) || isSQLExpression(e)) {
|
|
3223
|
-
list2.push({ from: e });
|
|
3224
|
-
} else if (Array.isArray(e)) {
|
|
3225
|
-
list2.push({ as: unquote(e[0]), from: asRelation(e[1]) });
|
|
3226
|
-
} else {
|
|
3227
|
-
for (const as in e) {
|
|
3228
|
-
list2.push({ as: unquote(as), from: asRelation(e[as]) });
|
|
3229
|
-
}
|
|
3230
|
-
}
|
|
3231
|
-
});
|
|
3232
|
-
query.from = query.from.concat(list2);
|
|
3233
|
-
return this;
|
|
3234
|
-
}
|
|
3235
|
-
}
|
|
3236
|
-
$from(...expr) {
|
|
3237
|
-
this.query.from = [];
|
|
3238
|
-
return this.from(...expr);
|
|
2880
|
+
toString() {
|
|
2881
|
+
const { range, exclude, extent } = this;
|
|
2882
|
+
const type = range ? "RANGE" : "ROWS";
|
|
2883
|
+
const [prev, next] = isNode(extent) ? extent.value : extent;
|
|
2884
|
+
const a = frameValue(prev, "PRECEDING");
|
|
2885
|
+
const b = frameValue(next, "FOLLOWING");
|
|
2886
|
+
return `${type} BETWEEN ${a} AND ${b}${exclude ? ` ${exclude}` : ""}`;
|
|
3239
2887
|
}
|
|
2888
|
+
};
|
|
2889
|
+
function deriveDef(def, options) {
|
|
2890
|
+
return new WindowDefNode(
|
|
2891
|
+
options.name ?? def.name,
|
|
2892
|
+
options.partition ?? def.partition,
|
|
2893
|
+
options.order ?? def.order,
|
|
2894
|
+
options.frame ?? def.frame
|
|
2895
|
+
);
|
|
2896
|
+
}
|
|
2897
|
+
function frameValue(value, order) {
|
|
2898
|
+
return value === 0 ? "CURRENT ROW" : Number.isFinite(value) ? `${Math.abs(value)} ${order}` : `UNBOUNDED ${order}`;
|
|
2899
|
+
}
|
|
2900
|
+
|
|
2901
|
+
// ../sql/src/ast/column-ref.js
|
|
2902
|
+
function isColumnRef(value) {
|
|
2903
|
+
return value instanceof ColumnRefNode;
|
|
2904
|
+
}
|
|
2905
|
+
var ColumnRefNode = class extends ExprNode {
|
|
3240
2906
|
/**
|
|
3241
|
-
*
|
|
3242
|
-
* @
|
|
2907
|
+
* Instantiate a column reference node.
|
|
2908
|
+
* @param {import('./table-ref.js').TableRefNode} [table] The table reference.
|
|
3243
2909
|
*/
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
* @param {string} [method] The sampling method to use.
|
|
3248
|
-
* @returns {this}
|
|
3249
|
-
*/
|
|
3250
|
-
sample(value, method) {
|
|
3251
|
-
const { query } = this;
|
|
3252
|
-
if (arguments.length === 0) {
|
|
3253
|
-
return query.sample;
|
|
3254
|
-
} else {
|
|
3255
|
-
let spec = value;
|
|
3256
|
-
if (typeof value === "number") {
|
|
3257
|
-
spec = value > 0 && value < 1 ? { perc: 100 * value, method } : { rows: Math.round(value), method };
|
|
3258
|
-
}
|
|
3259
|
-
query.sample = spec;
|
|
3260
|
-
return this;
|
|
3261
|
-
}
|
|
2910
|
+
constructor(type, table2) {
|
|
2911
|
+
super(type);
|
|
2912
|
+
this.table = table2;
|
|
3262
2913
|
}
|
|
3263
2914
|
/**
|
|
3264
|
-
*
|
|
3265
|
-
* @returns {
|
|
2915
|
+
* Returns the column name.
|
|
2916
|
+
* @returns {string}
|
|
3266
2917
|
*/
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
* @param {...any} expr Expressions to add.
|
|
3270
|
-
* @returns {this}
|
|
3271
|
-
*/
|
|
3272
|
-
where(...expr) {
|
|
3273
|
-
const { query } = this;
|
|
3274
|
-
if (expr.length === 0) {
|
|
3275
|
-
return query.where;
|
|
3276
|
-
} else {
|
|
3277
|
-
query.where = query.where.concat(
|
|
3278
|
-
expr.flat().filter((x2) => x2)
|
|
3279
|
-
);
|
|
3280
|
-
return this;
|
|
3281
|
-
}
|
|
3282
|
-
}
|
|
3283
|
-
$where(...expr) {
|
|
3284
|
-
this.query.where = [];
|
|
3285
|
-
return this.where(...expr);
|
|
2918
|
+
get column() {
|
|
2919
|
+
return null;
|
|
3286
2920
|
}
|
|
3287
2921
|
/**
|
|
3288
|
-
*
|
|
3289
|
-
* @returns {
|
|
2922
|
+
* Generate a SQL query string for this node.
|
|
2923
|
+
* @returns {string}
|
|
3290
2924
|
*/
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
groupby(...expr) {
|
|
3297
|
-
const { query } = this;
|
|
3298
|
-
if (expr.length === 0) {
|
|
3299
|
-
return query.groupby;
|
|
3300
|
-
} else {
|
|
3301
|
-
query.groupby = query.groupby.concat(
|
|
3302
|
-
expr.flat().filter((x2) => x2).map(asColumn)
|
|
3303
|
-
);
|
|
3304
|
-
return this;
|
|
3305
|
-
}
|
|
3306
|
-
}
|
|
3307
|
-
$groupby(...expr) {
|
|
3308
|
-
this.query.groupby = [];
|
|
3309
|
-
return this.groupby(...expr);
|
|
2925
|
+
toString() {
|
|
2926
|
+
const { column: column2, table: table2 } = this;
|
|
2927
|
+
const tref = `${table2 ?? ""}`;
|
|
2928
|
+
const id = column2 === "*" ? "*" : quoteIdentifier(column2);
|
|
2929
|
+
return (tref ? tref + "." : "") + id;
|
|
3310
2930
|
}
|
|
2931
|
+
};
|
|
2932
|
+
var ColumnNameRefNode = class extends ColumnRefNode {
|
|
3311
2933
|
/**
|
|
3312
|
-
*
|
|
3313
|
-
* @
|
|
2934
|
+
* Instantiate a column reference node.
|
|
2935
|
+
* @param {string} name The column name.
|
|
2936
|
+
* @param {import('./table-ref.js').TableRefNode} [table] The table reference.
|
|
3314
2937
|
*/
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
* @returns {this}
|
|
3319
|
-
*/
|
|
3320
|
-
having(...expr) {
|
|
3321
|
-
const { query } = this;
|
|
3322
|
-
if (expr.length === 0) {
|
|
3323
|
-
return query.having;
|
|
3324
|
-
} else {
|
|
3325
|
-
query.having = query.having.concat(
|
|
3326
|
-
expr.flat().filter((x2) => x2)
|
|
3327
|
-
);
|
|
3328
|
-
return this;
|
|
3329
|
-
}
|
|
2938
|
+
constructor(name, table2) {
|
|
2939
|
+
super(COLUMN_REF, table2);
|
|
2940
|
+
this.name = name;
|
|
3330
2941
|
}
|
|
3331
2942
|
/**
|
|
3332
|
-
*
|
|
3333
|
-
* @returns {
|
|
2943
|
+
* Returns the column name.
|
|
2944
|
+
* @returns {string}
|
|
3334
2945
|
*/
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
* @param {...any} expr Expressions to add.
|
|
3338
|
-
* @returns {this}
|
|
3339
|
-
*/
|
|
3340
|
-
window(...expr) {
|
|
3341
|
-
const { query } = this;
|
|
3342
|
-
if (expr.length === 0) {
|
|
3343
|
-
return query.window;
|
|
3344
|
-
} else {
|
|
3345
|
-
const list2 = [];
|
|
3346
|
-
expr.flat().forEach((e) => {
|
|
3347
|
-
if (e == null) {
|
|
3348
|
-
} else {
|
|
3349
|
-
for (const as in e) {
|
|
3350
|
-
list2.push({ as: unquote(as), expr: e[as] });
|
|
3351
|
-
}
|
|
3352
|
-
}
|
|
3353
|
-
});
|
|
3354
|
-
query.window = query.window.concat(list2);
|
|
3355
|
-
return this;
|
|
3356
|
-
}
|
|
2946
|
+
get column() {
|
|
2947
|
+
return this.name;
|
|
3357
2948
|
}
|
|
2949
|
+
};
|
|
2950
|
+
|
|
2951
|
+
// ../sql/src/ast/column-param.js
|
|
2952
|
+
var ColumnParamNode = class extends ColumnRefNode {
|
|
3358
2953
|
/**
|
|
3359
|
-
*
|
|
3360
|
-
* @
|
|
2954
|
+
* Instantiate a column param node.
|
|
2955
|
+
* @param {import('./param.js').ParamNode} param The column name as a
|
|
2956
|
+
* parameter node.
|
|
2957
|
+
* @param {import('./table-ref.js').TableRefNode} [table] The table
|
|
2958
|
+
* reference.
|
|
3361
2959
|
*/
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
* @returns {this}
|
|
3366
|
-
*/
|
|
3367
|
-
qualify(...expr) {
|
|
3368
|
-
const { query } = this;
|
|
3369
|
-
if (expr.length === 0) {
|
|
3370
|
-
return query.qualify;
|
|
3371
|
-
} else {
|
|
3372
|
-
query.qualify = query.qualify.concat(
|
|
3373
|
-
expr.flat().filter((x2) => x2)
|
|
3374
|
-
);
|
|
3375
|
-
return this;
|
|
3376
|
-
}
|
|
2960
|
+
constructor(param, table2) {
|
|
2961
|
+
super(COLUMN_PARAM, table2);
|
|
2962
|
+
this.param = param;
|
|
3377
2963
|
}
|
|
3378
2964
|
/**
|
|
3379
|
-
*
|
|
3380
|
-
* @returns {
|
|
2965
|
+
* Returns the column name.
|
|
2966
|
+
* @returns {string}
|
|
3381
2967
|
*/
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
* @param {...any} expr Expressions to add.
|
|
3385
|
-
* @returns {this}
|
|
3386
|
-
*/
|
|
3387
|
-
orderby(...expr) {
|
|
3388
|
-
const { query } = this;
|
|
3389
|
-
if (expr.length === 0) {
|
|
3390
|
-
return query.orderby;
|
|
3391
|
-
} else {
|
|
3392
|
-
query.orderby = query.orderby.concat(
|
|
3393
|
-
expr.flat().filter((x2) => x2).map(asColumn)
|
|
3394
|
-
);
|
|
3395
|
-
return this;
|
|
3396
|
-
}
|
|
2968
|
+
get column() {
|
|
2969
|
+
return `${this.param.value}`;
|
|
3397
2970
|
}
|
|
2971
|
+
};
|
|
2972
|
+
|
|
2973
|
+
// ../sql/src/functions/column.js
|
|
2974
|
+
function column(name, table2) {
|
|
2975
|
+
const tref = asTableRef(table2);
|
|
2976
|
+
return isParamLike(name) ? new ColumnParamNode(new ParamNode(name), tref) : new ColumnNameRefNode(name, tref);
|
|
2977
|
+
}
|
|
2978
|
+
|
|
2979
|
+
// ../sql/src/ast/verbatim.js
|
|
2980
|
+
var VerbatimNode = class extends ExprNode {
|
|
3398
2981
|
/**
|
|
3399
|
-
*
|
|
3400
|
-
* @
|
|
2982
|
+
* Instantiate a raw node with verbatim content.
|
|
2983
|
+
* @param {string} value The verbatim content to include.
|
|
3401
2984
|
*/
|
|
2985
|
+
constructor(value) {
|
|
2986
|
+
super(VERBATIM);
|
|
2987
|
+
this.value = value;
|
|
2988
|
+
}
|
|
3402
2989
|
/**
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
2990
|
+
* Generate a SQL query string for this node.
|
|
2991
|
+
* @returns {string}
|
|
2992
|
+
*/
|
|
2993
|
+
toString() {
|
|
2994
|
+
return this.value;
|
|
2995
|
+
}
|
|
2996
|
+
};
|
|
2997
|
+
|
|
2998
|
+
// ../sql/src/functions/literal.js
|
|
2999
|
+
function literal(value) {
|
|
3000
|
+
return new LiteralNode(value);
|
|
3001
|
+
}
|
|
3002
|
+
function verbatim(value) {
|
|
3003
|
+
return new VerbatimNode(value);
|
|
3004
|
+
}
|
|
3005
|
+
|
|
3006
|
+
// ../sql/src/functions/table-ref.js
|
|
3007
|
+
function tableRef(...ids) {
|
|
3008
|
+
const args = exprList(ids, String);
|
|
3009
|
+
return args?.length ? new TableRefNode(args) : void 0;
|
|
3010
|
+
}
|
|
3011
|
+
|
|
3012
|
+
// ../sql/src/util/ast.js
|
|
3013
|
+
function asNode(value) {
|
|
3014
|
+
return isString(value) ? parseColumnRef(value) : asLiteral(value);
|
|
3015
|
+
}
|
|
3016
|
+
function asVerbatim(value) {
|
|
3017
|
+
return isString(value) ? verbatim(value) : asLiteral(value);
|
|
3018
|
+
}
|
|
3019
|
+
function asLiteral(value) {
|
|
3020
|
+
return value instanceof ExprNode ? value : isParamLike(value) ? new ParamNode(value) : literal(value);
|
|
3021
|
+
}
|
|
3022
|
+
function asTableRef(value) {
|
|
3023
|
+
return isString(value) ? parseTableRef(value) : isArray2(value) ? tableRef(value) : value;
|
|
3024
|
+
}
|
|
3025
|
+
function parseColumnRef(ref) {
|
|
3026
|
+
const ids = parseIdentifier(ref);
|
|
3027
|
+
return column(ids.pop(), tableRef(ids));
|
|
3028
|
+
}
|
|
3029
|
+
function parseTableRef(ref) {
|
|
3030
|
+
return tableRef(parseIdentifier(ref));
|
|
3031
|
+
}
|
|
3032
|
+
|
|
3033
|
+
// ../sql/src/ast/aggregate.js
|
|
3034
|
+
var AggregateNode = class _AggregateNode extends ExprNode {
|
|
3035
|
+
/**
|
|
3036
|
+
* Instantiate an aggregate function node.
|
|
3037
|
+
* @param {string} name The aggregate function name.
|
|
3038
|
+
* @param {ExprNode[]} args The aggregate function arguments.
|
|
3039
|
+
* @param {boolean} [distinct] The distinct flag.
|
|
3040
|
+
* @param {ExprNode} [filter] Filter expression.
|
|
3041
|
+
*/
|
|
3042
|
+
constructor(name, args, distinct2, filter) {
|
|
3043
|
+
super(AGGREGATE);
|
|
3044
|
+
this.name = name;
|
|
3045
|
+
this.args = args;
|
|
3046
|
+
this.isDistinct = distinct2;
|
|
3047
|
+
this.filter = filter;
|
|
3048
|
+
}
|
|
3049
|
+
/**
|
|
3050
|
+
* Return a new derived aggregate over distinct values.
|
|
3051
|
+
* @param {boolean} [isDistinct=true] The distinct flag.
|
|
3052
|
+
* @returns {AggregateNode} A new aggregate node.
|
|
3053
|
+
*/
|
|
3054
|
+
distinct(isDistinct2 = true) {
|
|
3055
|
+
return new _AggregateNode(this.name, this.args, isDistinct2, this.filter);
|
|
3056
|
+
}
|
|
3057
|
+
/**
|
|
3058
|
+
* Return a new derived aggregate function that filters values.
|
|
3059
|
+
* @param {ExprNode | string} filter The filter expression.
|
|
3060
|
+
* @returns {AggregateNode} A new aggregate node.
|
|
3061
|
+
*/
|
|
3062
|
+
where(filter) {
|
|
3063
|
+
if (isString(filter)) filter = asVerbatim(filter);
|
|
3064
|
+
return new _AggregateNode(this.name, this.args, this.isDistinct, filter);
|
|
3065
|
+
}
|
|
3066
|
+
/**
|
|
3067
|
+
* Return a new window function over this aggregate.
|
|
3068
|
+
* @returns {WindowNode} A new window node.
|
|
3069
|
+
*/
|
|
3070
|
+
window() {
|
|
3071
|
+
return new WindowNode(this);
|
|
3072
|
+
}
|
|
3073
|
+
/**
|
|
3074
|
+
* Return a new window function over this aggregate with the given partitions.
|
|
3075
|
+
* @param {...import('../types.js').ExprVarArgs} expr The partition by criteria.
|
|
3076
|
+
* @returns {WindowNode} A new window node.
|
|
3077
|
+
*/
|
|
3078
|
+
partitionby(...expr) {
|
|
3079
|
+
return this.window().partitionby(...expr);
|
|
3415
3080
|
}
|
|
3416
3081
|
/**
|
|
3417
|
-
*
|
|
3418
|
-
* @
|
|
3082
|
+
* Return a new window function over this aggregate with the given ordering.
|
|
3083
|
+
* @param {...import('../types.js').ExprVarArgs} expr The order by criteria.
|
|
3084
|
+
* @returns {WindowNode} A new window node.
|
|
3419
3085
|
*/
|
|
3086
|
+
orderby(...expr) {
|
|
3087
|
+
return this.window().orderby(...expr);
|
|
3088
|
+
}
|
|
3089
|
+
/**
|
|
3090
|
+
* Generate a SQL query string for this node.
|
|
3091
|
+
* @returns {string}
|
|
3092
|
+
*/
|
|
3093
|
+
toString() {
|
|
3094
|
+
const { name, args, isDistinct: isDistinct2, filter } = this;
|
|
3095
|
+
const dist = isDistinct2 ? "DISTINCT " : "";
|
|
3096
|
+
const arg = args?.length ? args.join(", ") : "*";
|
|
3097
|
+
const filt = filter ? ` FILTER (WHERE ${filter})` : "";
|
|
3098
|
+
return `${name}(${dist}${arg})${filt}`;
|
|
3099
|
+
}
|
|
3100
|
+
};
|
|
3101
|
+
var aggregateNames = [
|
|
3102
|
+
"any_value",
|
|
3103
|
+
"approx_count_distinct",
|
|
3104
|
+
"approx_quantile",
|
|
3105
|
+
"arbitrary",
|
|
3106
|
+
"arg_max",
|
|
3107
|
+
"arg_max_null",
|
|
3108
|
+
"arg_min",
|
|
3109
|
+
"arg_min_null",
|
|
3110
|
+
"array_agg",
|
|
3111
|
+
"avg",
|
|
3112
|
+
"bit_and",
|
|
3113
|
+
"bit_or",
|
|
3114
|
+
"bit_xor",
|
|
3115
|
+
"bitstring_agg",
|
|
3116
|
+
"bool_and",
|
|
3117
|
+
"bool_or",
|
|
3118
|
+
"corr",
|
|
3119
|
+
"count",
|
|
3120
|
+
"covar_pop",
|
|
3121
|
+
"covar_samp",
|
|
3122
|
+
"entropy",
|
|
3123
|
+
"favg",
|
|
3124
|
+
"first",
|
|
3125
|
+
"fsum",
|
|
3126
|
+
"geomean",
|
|
3127
|
+
"kurtosis_pop",
|
|
3128
|
+
"kurtosis",
|
|
3129
|
+
"last",
|
|
3130
|
+
"mad",
|
|
3131
|
+
"max",
|
|
3132
|
+
"max_by",
|
|
3133
|
+
"median",
|
|
3134
|
+
"min",
|
|
3135
|
+
"min_by",
|
|
3136
|
+
"mode",
|
|
3137
|
+
"product",
|
|
3138
|
+
"quantile",
|
|
3139
|
+
"quantile_cont",
|
|
3140
|
+
"quantile_disc",
|
|
3141
|
+
"regr_avgx",
|
|
3142
|
+
"regr_avgy",
|
|
3143
|
+
"regr_count",
|
|
3144
|
+
"regr_intercept",
|
|
3145
|
+
"regr_r2",
|
|
3146
|
+
"regr_sxx",
|
|
3147
|
+
"regr_sxy",
|
|
3148
|
+
"regr_syy",
|
|
3149
|
+
"regr_slope",
|
|
3150
|
+
"reservoir_quantile",
|
|
3151
|
+
"skewness",
|
|
3152
|
+
"stddev",
|
|
3153
|
+
"stddev_pop",
|
|
3154
|
+
"stddev_samp",
|
|
3155
|
+
"string_agg",
|
|
3156
|
+
"sum",
|
|
3157
|
+
"variance",
|
|
3158
|
+
"var_pop",
|
|
3159
|
+
"var_samp"
|
|
3160
|
+
];
|
|
3161
|
+
|
|
3162
|
+
// ../sql/src/ast/between-op.js
|
|
3163
|
+
var AbstractBetweenOpNode = class extends ExprNode {
|
|
3164
|
+
/**
|
|
3165
|
+
* Instantiate an abstract between operator node.
|
|
3166
|
+
* @param {string} type The node type.
|
|
3167
|
+
* @param {ExprNode} expr The input expression.
|
|
3168
|
+
* @param {[ExprNode, ExprNode]} extent The range extent.
|
|
3169
|
+
*/
|
|
3170
|
+
constructor(type, expr, extent) {
|
|
3171
|
+
super(type);
|
|
3172
|
+
this.expr = expr;
|
|
3173
|
+
this.extent = extent;
|
|
3174
|
+
}
|
|
3175
|
+
/**
|
|
3176
|
+
* Generate a SQL query string for this node.
|
|
3177
|
+
* @returns {string}
|
|
3178
|
+
*/
|
|
3179
|
+
toSQL(op) {
|
|
3180
|
+
const { extent: r, expr } = this;
|
|
3181
|
+
return r ? `(${expr} ${op} ${r[0]} AND ${r[1]})` : "";
|
|
3182
|
+
}
|
|
3183
|
+
};
|
|
3184
|
+
var BetweenOpNode = class extends AbstractBetweenOpNode {
|
|
3185
|
+
/**
|
|
3186
|
+
* Instantiate a between operator node.
|
|
3187
|
+
* @param {ExprNode} expr The input expression.
|
|
3188
|
+
* @param {[ExprNode, ExprNode]} extent
|
|
3189
|
+
* The range extent.
|
|
3190
|
+
*/
|
|
3191
|
+
constructor(expr, extent) {
|
|
3192
|
+
super(BETWEEN_OPERATOR, expr, extent);
|
|
3193
|
+
}
|
|
3194
|
+
/**
|
|
3195
|
+
* Generate a SQL query string for this node.
|
|
3196
|
+
* @returns {string}
|
|
3197
|
+
*/
|
|
3198
|
+
toString() {
|
|
3199
|
+
return super.toSQL("BETWEEN");
|
|
3200
|
+
}
|
|
3201
|
+
};
|
|
3202
|
+
var NotBetweenOpNode = class extends AbstractBetweenOpNode {
|
|
3203
|
+
/**
|
|
3204
|
+
* Instantiate a not between operator node.
|
|
3205
|
+
* @param {ExprNode} expr The input expression.
|
|
3206
|
+
* @param {[ExprNode, ExprNode]} extent
|
|
3207
|
+
* The range extent.
|
|
3208
|
+
*/
|
|
3209
|
+
constructor(expr, extent) {
|
|
3210
|
+
super(NOT_BETWEEN_OPERATOR, expr, extent);
|
|
3211
|
+
}
|
|
3420
3212
|
/**
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3213
|
+
* Generate a SQL query string for this node.
|
|
3214
|
+
* @returns {string}
|
|
3215
|
+
*/
|
|
3216
|
+
toString() {
|
|
3217
|
+
return super.toSQL("NOT BETWEEN");
|
|
3218
|
+
}
|
|
3219
|
+
};
|
|
3220
|
+
|
|
3221
|
+
// ../sql/src/ast/binary-op.js
|
|
3222
|
+
var BinaryOpNode = class extends ExprNode {
|
|
3223
|
+
/**
|
|
3224
|
+
* Instantiate a binary operator node.
|
|
3225
|
+
* @param {string} op The operator type.
|
|
3226
|
+
* @param {ExprNode} left The left input expression.
|
|
3227
|
+
* @param {ExprNode} right The right input expression.
|
|
3228
|
+
*/
|
|
3229
|
+
constructor(op, left, right) {
|
|
3230
|
+
super(BINARY_OPERATOR);
|
|
3231
|
+
this.op = op;
|
|
3232
|
+
this.left = left;
|
|
3233
|
+
this.right = right;
|
|
3234
|
+
}
|
|
3235
|
+
/**
|
|
3236
|
+
* Generate a SQL query string for this node.
|
|
3237
|
+
* @returns {string}
|
|
3238
|
+
*/
|
|
3239
|
+
toString() {
|
|
3240
|
+
return `(${this.left} ${this.op} ${this.right})`;
|
|
3241
|
+
}
|
|
3242
|
+
};
|
|
3243
|
+
|
|
3244
|
+
// ../sql/src/ast/cast.js
|
|
3245
|
+
var CastNode = class extends ExprNode {
|
|
3246
|
+
/**
|
|
3247
|
+
* Instantiate a cast node.
|
|
3248
|
+
* @param {ExprNode} expr The expression to type cast.
|
|
3249
|
+
* @param {string} type The type to cast to.
|
|
3250
|
+
*/
|
|
3251
|
+
constructor(expr, type) {
|
|
3252
|
+
super(CAST);
|
|
3253
|
+
this.expr = expr;
|
|
3254
|
+
this.cast = type;
|
|
3255
|
+
}
|
|
3256
|
+
/**
|
|
3257
|
+
* Generate a SQL query string for this node.
|
|
3258
|
+
* @returns {string}
|
|
3259
|
+
*/
|
|
3260
|
+
toString() {
|
|
3261
|
+
return `(${this.expr})::${this.cast}`;
|
|
3262
|
+
}
|
|
3263
|
+
};
|
|
3264
|
+
|
|
3265
|
+
// ../sql/src/ast/fragment.js
|
|
3266
|
+
var FragmentNode = class extends ExprNode {
|
|
3267
|
+
/**
|
|
3268
|
+
* Instantiate a fragment node with arbitrary content.
|
|
3269
|
+
* @param {ExprNode[]} spans The consecutive parts making up the fragment.
|
|
3270
|
+
*/
|
|
3271
|
+
constructor(spans) {
|
|
3272
|
+
super(FRAGMENT);
|
|
3273
|
+
this.spans = spans;
|
|
3274
|
+
}
|
|
3275
|
+
/**
|
|
3276
|
+
* Generate a SQL query string for this node.
|
|
3277
|
+
* @returns {string}
|
|
3278
|
+
*/
|
|
3279
|
+
toString() {
|
|
3280
|
+
return this.spans.join("");
|
|
3281
|
+
}
|
|
3282
|
+
};
|
|
3283
|
+
|
|
3284
|
+
// ../sql/src/ast/sample.js
|
|
3285
|
+
var SampleClauseNode = class extends SQLNode {
|
|
3286
|
+
/**
|
|
3287
|
+
* Instantiate a sample clause node.
|
|
3288
|
+
* @param {number} size The sample size as either a row count or percentage.
|
|
3289
|
+
* @param {boolean} [perc=false] Flag indicating if the sampling unit is
|
|
3290
|
+
* rows (`false`) or a percentage (`true`).
|
|
3291
|
+
* @param {SampleMethod} [method] The sampling method. If unspecified,
|
|
3292
|
+
* a default method is applied based on the sampling unit.
|
|
3293
|
+
* @param {number} [seed] The random seed.
|
|
3294
|
+
*/
|
|
3295
|
+
constructor(size, perc = false, method = void 0, seed = void 0) {
|
|
3296
|
+
super(SAMPLE_CLAUSE);
|
|
3297
|
+
this.size = size;
|
|
3298
|
+
this.perc = perc;
|
|
3299
|
+
this.method = method;
|
|
3300
|
+
this.seed = seed;
|
|
3301
|
+
}
|
|
3302
|
+
toString() {
|
|
3303
|
+
const { size, perc, method, seed } = this;
|
|
3304
|
+
const unit = perc ? "%" : " ROWS";
|
|
3305
|
+
const s = seed != null ? `, ${seed}` : "";
|
|
3306
|
+
return `${size}${unit}${method ? ` (${method}${s})` : ""}`;
|
|
3307
|
+
}
|
|
3308
|
+
};
|
|
3309
|
+
|
|
3310
|
+
// ../sql/src/ast/select.js
|
|
3311
|
+
var SelectClauseNode = class extends SQLNode {
|
|
3312
|
+
/**
|
|
3313
|
+
* Instantiate a select node.
|
|
3314
|
+
* @param {ExprNode} expr The select expression.
|
|
3315
|
+
* @param {string} alias The output name.
|
|
3316
|
+
*/
|
|
3317
|
+
constructor(expr, alias) {
|
|
3318
|
+
super(SELECT_CLAUSE);
|
|
3319
|
+
this.expr = expr;
|
|
3320
|
+
this.alias = alias;
|
|
3321
|
+
}
|
|
3322
|
+
/**
|
|
3323
|
+
* Generate a SQL query string for this node.
|
|
3324
|
+
* @returns {string}
|
|
3325
|
+
*/
|
|
3326
|
+
toString() {
|
|
3327
|
+
const { expr, alias } = this;
|
|
3328
|
+
return !alias || isColumnRefFor(expr, alias) ? `${expr}` : `${expr} AS ${quoteIdentifier(alias)}`;
|
|
3329
|
+
}
|
|
3330
|
+
};
|
|
3331
|
+
function isColumnRefFor(expr, name) {
|
|
3332
|
+
return expr instanceof ColumnRefNode && expr.table == null && expr.column === name;
|
|
3333
|
+
}
|
|
3334
|
+
|
|
3335
|
+
// ../sql/src/ast/with.js
|
|
3336
|
+
var WithClauseNode = class extends SQLNode {
|
|
3337
|
+
/**
|
|
3338
|
+
* Instantiate a with clause node for a common table expression (CTE).
|
|
3339
|
+
* @param {string} name The common table expression (CTE) name.
|
|
3340
|
+
* @param {Query} query The common table expression (CTE) query.
|
|
3341
|
+
*/
|
|
3342
|
+
constructor(name, query) {
|
|
3343
|
+
super(WITH_CLAUSE);
|
|
3344
|
+
this.name = name;
|
|
3345
|
+
this.query = query;
|
|
3346
|
+
}
|
|
3347
|
+
toString() {
|
|
3348
|
+
return `"${this.name}" AS (${this.query})`;
|
|
3349
|
+
}
|
|
3350
|
+
};
|
|
3351
|
+
|
|
3352
|
+
// ../sql/src/ast/query.js
|
|
3353
|
+
function isQuery(value) {
|
|
3354
|
+
return value instanceof Query;
|
|
3355
|
+
}
|
|
3356
|
+
function isSelectQuery(value) {
|
|
3357
|
+
return value instanceof SelectQuery;
|
|
3358
|
+
}
|
|
3359
|
+
function isDescribeQuery(value) {
|
|
3360
|
+
return value instanceof DescribeQuery;
|
|
3361
|
+
}
|
|
3362
|
+
var Query = class extends ExprNode {
|
|
3363
|
+
/**
|
|
3364
|
+
* Create a new select query with the given SELECT expressions.
|
|
3365
|
+
* @param {...import('../types.js').SelectExpr} expr The SELECT expressions.
|
|
3366
|
+
* @returns {SelectQuery}
|
|
3367
|
+
*/
|
|
3368
|
+
static select(...expr) {
|
|
3369
|
+
return new SelectQuery().select(...expr);
|
|
3370
|
+
}
|
|
3371
|
+
/**
|
|
3372
|
+
* Create a new select query with the given FROM expressions.
|
|
3373
|
+
* @param {...import('../types.js').FromExpr} expr The FROM expressions.
|
|
3374
|
+
* @returns {SelectQuery}
|
|
3375
|
+
*/
|
|
3376
|
+
static from(...expr) {
|
|
3377
|
+
return new SelectQuery().from(...expr);
|
|
3378
|
+
}
|
|
3379
|
+
/**
|
|
3380
|
+
* Create a new select query with the given WITH CTE queries.
|
|
3381
|
+
* @param {...import('../types.js').WithExpr} expr The WITH CTE queries.
|
|
3382
|
+
* @returns {SelectQuery}
|
|
3383
|
+
*/
|
|
3384
|
+
static with(...expr) {
|
|
3385
|
+
return new SelectQuery().with(...expr);
|
|
3386
|
+
}
|
|
3387
|
+
/**
|
|
3388
|
+
* Create a new UNION set operation over the given queries.
|
|
3389
|
+
* @param {...Query} queries The queries.
|
|
3390
|
+
* @returns {SetOperation}
|
|
3391
|
+
*/
|
|
3392
|
+
static union(...queries) {
|
|
3393
|
+
return new SetOperation("UNION", queries.flat());
|
|
3394
|
+
}
|
|
3395
|
+
/**
|
|
3396
|
+
* Create a new UNION ALL set operation over the given queries.
|
|
3397
|
+
* @param {...Query} queries The queries.
|
|
3398
|
+
* @returns {SetOperation}
|
|
3399
|
+
*/
|
|
3400
|
+
static unionAll(...queries) {
|
|
3401
|
+
return new SetOperation("UNION ALL", queries.flat());
|
|
3402
|
+
}
|
|
3403
|
+
/**
|
|
3404
|
+
* Create a new INTERSECT set operation over the given queries.
|
|
3405
|
+
* @param {...Query} queries The queries.
|
|
3406
|
+
* @returns {SetOperation}
|
|
3407
|
+
*/
|
|
3408
|
+
static intersect(...queries) {
|
|
3409
|
+
return new SetOperation("INTERSECT", queries.flat());
|
|
3410
|
+
}
|
|
3411
|
+
/**
|
|
3412
|
+
* Create a new EXCEPT set operation over the given queries.
|
|
3413
|
+
* @param {...Query} queries The queries.
|
|
3414
|
+
* @returns {SetOperation}
|
|
3415
|
+
*/
|
|
3416
|
+
static except(...queries) {
|
|
3417
|
+
return new SetOperation("EXCEPT", queries.flat());
|
|
3418
|
+
}
|
|
3419
|
+
/**
|
|
3420
|
+
* Create a new describe query for the given input query.
|
|
3421
|
+
* @param {Query} query The query to describe.
|
|
3422
|
+
* @returns {DescribeQuery}
|
|
3423
|
+
*/
|
|
3424
|
+
static describe(query) {
|
|
3425
|
+
return new DescribeQuery(query);
|
|
3426
|
+
}
|
|
3427
|
+
/**
|
|
3428
|
+
* Instantiate a new query.
|
|
3429
|
+
*/
|
|
3430
|
+
constructor(type) {
|
|
3431
|
+
super(type);
|
|
3432
|
+
this._orderby = [];
|
|
3433
|
+
this._limit = void 0;
|
|
3434
|
+
this._offset = void 0;
|
|
3435
|
+
this.cteFor = null;
|
|
3436
|
+
}
|
|
3437
|
+
/**
|
|
3438
|
+
* Return a list of subqueries.
|
|
3439
|
+
* @returns {Query[]}
|
|
3440
|
+
*/
|
|
3441
|
+
get subqueries() {
|
|
3442
|
+
return [];
|
|
3443
|
+
}
|
|
3444
|
+
/**
|
|
3445
|
+
* Clone this query.
|
|
3446
|
+
* @returns {Query}
|
|
3447
|
+
*/
|
|
3448
|
+
clone() {
|
|
3449
|
+
return this;
|
|
3450
|
+
}
|
|
3451
|
+
/**
|
|
3452
|
+
* Add ORDER BY expressions.
|
|
3453
|
+
* @param {...import('../types.js').OrderByExpr} expr Expressions to add.
|
|
3454
|
+
* @returns
|
|
3455
|
+
*/
|
|
3456
|
+
orderby(...expr) {
|
|
3457
|
+
this._orderby = this._orderby.concat(exprList(expr));
|
|
3458
|
+
return this;
|
|
3459
|
+
}
|
|
3460
|
+
/**
|
|
3461
|
+
* Set the query result LIMIT.
|
|
3462
|
+
* @param {number} value The limit value.
|
|
3463
|
+
* @returns {this}
|
|
3464
|
+
*/
|
|
3465
|
+
limit(value) {
|
|
3466
|
+
this._limit = Number.isFinite(value) ? value : void 0;
|
|
3467
|
+
return this;
|
|
3468
|
+
}
|
|
3469
|
+
/**
|
|
3470
|
+
* Set the query result OFFSET.
|
|
3471
|
+
* @param {number} value The offset value.
|
|
3472
|
+
* @returns {this}
|
|
3473
|
+
*/
|
|
3425
3474
|
offset(value) {
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3475
|
+
this._offset = Number.isFinite(value) ? value : void 0;
|
|
3476
|
+
return this;
|
|
3477
|
+
}
|
|
3478
|
+
};
|
|
3479
|
+
var SelectQuery = class _SelectQuery extends Query {
|
|
3480
|
+
/**
|
|
3481
|
+
* Instantiate a new select query.
|
|
3482
|
+
*/
|
|
3483
|
+
constructor() {
|
|
3484
|
+
super(SELECT_QUERY);
|
|
3485
|
+
this._with = [];
|
|
3486
|
+
this._select = [];
|
|
3487
|
+
this._from = [];
|
|
3488
|
+
this._where = [];
|
|
3489
|
+
this._sample = void 0;
|
|
3490
|
+
this._groupby = [];
|
|
3491
|
+
this._having = [];
|
|
3492
|
+
this._window = [];
|
|
3493
|
+
this._qualify = [];
|
|
3494
|
+
}
|
|
3495
|
+
/**
|
|
3496
|
+
* Return a list of subqueries.
|
|
3497
|
+
* @returns {Query[]}
|
|
3498
|
+
*/
|
|
3499
|
+
get subqueries() {
|
|
3500
|
+
const q = this.cteFor || this;
|
|
3501
|
+
const w = q instanceof _SelectQuery ? q._with : [];
|
|
3502
|
+
const cte = w.reduce((obj, c) => (obj[c.name] = c.query, obj), {});
|
|
3503
|
+
const queries = [];
|
|
3504
|
+
this._from.forEach(({ expr }) => {
|
|
3505
|
+
if (isQuery(expr)) {
|
|
3506
|
+
queries.push(expr);
|
|
3507
|
+
} else if (isTableRef(expr)) {
|
|
3508
|
+
const subq = cte[expr.name];
|
|
3509
|
+
if (subq) queries.push(subq);
|
|
3510
|
+
}
|
|
3511
|
+
});
|
|
3512
|
+
return queries;
|
|
3513
|
+
}
|
|
3514
|
+
/**
|
|
3515
|
+
* Clone this query.
|
|
3516
|
+
* @returns {SelectQuery}
|
|
3517
|
+
*/
|
|
3518
|
+
clone() {
|
|
3519
|
+
return Object.assign(new _SelectQuery(), this);
|
|
3520
|
+
}
|
|
3521
|
+
/**
|
|
3522
|
+
* Add WITH common table expressions (CTEs).
|
|
3523
|
+
* @param {...import('../types.js').WithExpr} expr Expressions to add.
|
|
3524
|
+
* @returns {this}
|
|
3525
|
+
*/
|
|
3526
|
+
with(...expr) {
|
|
3527
|
+
const list2 = [];
|
|
3528
|
+
const add2 = (name, q) => {
|
|
3529
|
+
const query = q.clone();
|
|
3530
|
+
query.cteFor = this;
|
|
3531
|
+
list2.push(new WithClauseNode(name, query));
|
|
3532
|
+
};
|
|
3533
|
+
expr.flat().forEach((e) => {
|
|
3534
|
+
if (e != null) for (const name in e) add2(name, e[name]);
|
|
3535
|
+
});
|
|
3536
|
+
this._with = this._with.concat(list2);
|
|
3537
|
+
return this;
|
|
3538
|
+
}
|
|
3539
|
+
/**
|
|
3540
|
+
* Add SELECT expressions.
|
|
3541
|
+
* @param {...import('../types.js').SelectExpr} expr Expressions to add.
|
|
3542
|
+
* @returns {this}
|
|
3543
|
+
*/
|
|
3544
|
+
select(...expr) {
|
|
3545
|
+
const list2 = [];
|
|
3546
|
+
const add2 = (v, as) => list2.push(
|
|
3547
|
+
new SelectClauseNode(v == null ? v : asNode(v), unquote(as))
|
|
3548
|
+
);
|
|
3549
|
+
expr.flat().forEach((e) => {
|
|
3550
|
+
if (e == null) return;
|
|
3551
|
+
else if (isString(e)) add2(e, e);
|
|
3552
|
+
else if (isColumnRef(e)) add2(e, e.column);
|
|
3553
|
+
else if (isArray2(e)) add2(e[1], e[0]);
|
|
3554
|
+
else for (const alias in e) add2(e[alias], alias);
|
|
3555
|
+
});
|
|
3556
|
+
const keys = new Set(list2.map((x2) => x2.alias));
|
|
3557
|
+
this._select = this._select.filter((x2) => !keys.has(x2.alias)).concat(list2.filter((x2) => x2.expr));
|
|
3558
|
+
return this;
|
|
3559
|
+
}
|
|
3560
|
+
/**
|
|
3561
|
+
* Set SELECT expressions, replacing any prior expressions.
|
|
3562
|
+
* @param {...import('../types.js').SelectExpr} expr Expressions to add.
|
|
3563
|
+
* @returns {this}
|
|
3564
|
+
*/
|
|
3565
|
+
setSelect(...expr) {
|
|
3566
|
+
this._select = [];
|
|
3567
|
+
return this.select(...expr);
|
|
3568
|
+
}
|
|
3569
|
+
/**
|
|
3570
|
+
* Indicate if this query should retrieve distinct values only.
|
|
3571
|
+
* @param {boolean} value The distinct flag
|
|
3572
|
+
* @returns {this}
|
|
3573
|
+
*/
|
|
3574
|
+
distinct(value = true) {
|
|
3575
|
+
this._distinct = !!value;
|
|
3576
|
+
return this;
|
|
3577
|
+
}
|
|
3578
|
+
/**
|
|
3579
|
+
* Add table FROM expressions.
|
|
3580
|
+
* @param {...import('../types.js').FromExpr} expr Expressions to add.
|
|
3581
|
+
* @returns {this}
|
|
3582
|
+
*/
|
|
3583
|
+
from(...expr) {
|
|
3584
|
+
const list2 = [];
|
|
3585
|
+
const add2 = (v, as) => list2.push(new FromClauseNode(asTableRef(v), unquote(as)));
|
|
3586
|
+
expr.flat().forEach((e) => {
|
|
3587
|
+
if (e == null) return;
|
|
3588
|
+
else if (isString(e)) add2(e, e);
|
|
3589
|
+
else if (isTableRef(e)) add2(e, e.name);
|
|
3590
|
+
else if (isNode(e)) add2(e);
|
|
3591
|
+
else if (isArray2(e)) add2(e[1], e[0]);
|
|
3592
|
+
else for (const alias in e) add2(e[alias], alias);
|
|
3593
|
+
});
|
|
3594
|
+
this._from = this._from.concat(list2);
|
|
3595
|
+
return this;
|
|
3596
|
+
}
|
|
3597
|
+
/**
|
|
3598
|
+
* Set FROM expressions, replacing any prior expressions.
|
|
3599
|
+
* @param {...import('../types.js').FromExpr} expr Expressions to add.
|
|
3600
|
+
* @returns {this}
|
|
3601
|
+
*/
|
|
3602
|
+
setFrom(...expr) {
|
|
3603
|
+
this._from = [];
|
|
3604
|
+
return this.from(...expr);
|
|
3605
|
+
}
|
|
3606
|
+
/**
|
|
3607
|
+
* Set SAMPLE settings.
|
|
3608
|
+
* @param {number | SampleClauseNode} value Either a sample clause node
|
|
3609
|
+
* or the sample size as either a row count or percentage.
|
|
3610
|
+
* @param {import('./sample.js').SampleMethod} [method] The sampling method
|
|
3611
|
+
* to use.
|
|
3612
|
+
* @param {number} [seed] The random seed.
|
|
3613
|
+
* @returns {this}
|
|
3614
|
+
*/
|
|
3615
|
+
sample(value, method, seed) {
|
|
3616
|
+
let clause;
|
|
3617
|
+
if (typeof value === "number") {
|
|
3618
|
+
const perc = value > 0 && value < 1;
|
|
3619
|
+
const size = perc ? value * 100 : Math.floor(value);
|
|
3620
|
+
clause = new SampleClauseNode(size, perc, method, seed);
|
|
3429
3621
|
} else {
|
|
3430
|
-
|
|
3431
|
-
return this;
|
|
3622
|
+
clause = value;
|
|
3432
3623
|
}
|
|
3624
|
+
this._sample = clause;
|
|
3625
|
+
return this;
|
|
3433
3626
|
}
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3627
|
+
/**
|
|
3628
|
+
* Add WHERE expressions.
|
|
3629
|
+
* @param {...import('../types.js').FilterExpr} expr Expressions to add.
|
|
3630
|
+
* @returns {this}
|
|
3631
|
+
*/
|
|
3632
|
+
where(...expr) {
|
|
3633
|
+
this._where = this._where.concat(exprList(expr, asVerbatim));
|
|
3634
|
+
return this;
|
|
3635
|
+
}
|
|
3636
|
+
/**
|
|
3637
|
+
* Set WHERE expressions, replacing any prior expressions.
|
|
3638
|
+
* @param {...import('../types.js').FilterExpr} expr Expressions to add.
|
|
3639
|
+
* @returns {this}
|
|
3640
|
+
*/
|
|
3641
|
+
setWhere(...expr) {
|
|
3642
|
+
this._where = [];
|
|
3643
|
+
return this.where(...expr);
|
|
3644
|
+
}
|
|
3645
|
+
/**
|
|
3646
|
+
* Add GROUP BY expressions.
|
|
3647
|
+
* @param {...import('../types.js').GroupByExpr} expr Expressions to add.
|
|
3648
|
+
* @returns {this}
|
|
3649
|
+
*/
|
|
3650
|
+
groupby(...expr) {
|
|
3651
|
+
this._groupby = this._groupby.concat(exprList(expr));
|
|
3652
|
+
return this;
|
|
3653
|
+
}
|
|
3654
|
+
/**
|
|
3655
|
+
* Set GROUP BY expressions, replacing any prior expressions.
|
|
3656
|
+
* @param {...import('../types.js').GroupByExpr} expr Expressions to add.
|
|
3657
|
+
* @returns {this}
|
|
3658
|
+
*/
|
|
3659
|
+
setGroupby(...expr) {
|
|
3660
|
+
this._groupby = [];
|
|
3661
|
+
return this.groupby(...expr);
|
|
3662
|
+
}
|
|
3663
|
+
/**
|
|
3664
|
+
* Add HAVING expressions.
|
|
3665
|
+
* @param {...import('../types.js').FilterExpr} expr Expressions to add.
|
|
3666
|
+
* @returns {this}
|
|
3667
|
+
*/
|
|
3668
|
+
having(...expr) {
|
|
3669
|
+
this._having = this._having.concat(exprList(expr, asVerbatim));
|
|
3670
|
+
return this;
|
|
3671
|
+
}
|
|
3672
|
+
/**
|
|
3673
|
+
* Add WINDOW definitions.
|
|
3674
|
+
* @param {...any} expr Expressions to add.
|
|
3675
|
+
* @returns {this}
|
|
3676
|
+
*/
|
|
3677
|
+
window(...expr) {
|
|
3678
|
+
const list2 = [];
|
|
3679
|
+
expr.flat().forEach((e) => {
|
|
3680
|
+
if (e != null) for (const name in e) {
|
|
3681
|
+
list2.push(new WindowClauseNode(unquote(name), e[name]));
|
|
3445
3682
|
}
|
|
3446
3683
|
});
|
|
3447
|
-
|
|
3684
|
+
this._window = this._window.concat(list2);
|
|
3685
|
+
return this;
|
|
3686
|
+
}
|
|
3687
|
+
/**
|
|
3688
|
+
* Add QUALIFY expressions.
|
|
3689
|
+
* @param {...import('../types.js').FilterExpr} expr Expressions to add.
|
|
3690
|
+
* @returns {this}
|
|
3691
|
+
*/
|
|
3692
|
+
qualify(...expr) {
|
|
3693
|
+
this._qualify = this._qualify.concat(exprList(expr, asVerbatim));
|
|
3694
|
+
return this;
|
|
3448
3695
|
}
|
|
3696
|
+
/**
|
|
3697
|
+
* Generate a SQL query string.
|
|
3698
|
+
* @returns {string}
|
|
3699
|
+
*/
|
|
3449
3700
|
toString() {
|
|
3450
3701
|
const {
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
} = this
|
|
3702
|
+
_with,
|
|
3703
|
+
_select,
|
|
3704
|
+
_distinct,
|
|
3705
|
+
_from,
|
|
3706
|
+
_sample,
|
|
3707
|
+
_where,
|
|
3708
|
+
_groupby,
|
|
3709
|
+
_having,
|
|
3710
|
+
_window,
|
|
3711
|
+
_qualify,
|
|
3712
|
+
_orderby,
|
|
3713
|
+
_limit,
|
|
3714
|
+
_offset
|
|
3715
|
+
} = this;
|
|
3465
3716
|
const sql2 = [];
|
|
3466
|
-
if (
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
({ as, expr }) => isColumnRefFor(expr, as) && !expr.table ? `${expr}` : `${expr} AS "${as}"`
|
|
3472
|
-
);
|
|
3473
|
-
sql2.push(`SELECT${distinct2 ? " DISTINCT" : ""} ${sels.join(", ")}`);
|
|
3474
|
-
if (from.length) {
|
|
3475
|
-
const rels = from.map(({ as, from: from2 }) => {
|
|
3476
|
-
const rel = isQuery(from2) ? `(${from2})` : `${from2}`;
|
|
3477
|
-
return !as || as === from2.table ? rel : `${rel} AS "${as}"`;
|
|
3478
|
-
});
|
|
3479
|
-
sql2.push(`FROM ${rels.join(", ")}`);
|
|
3480
|
-
}
|
|
3481
|
-
if (where.length) {
|
|
3482
|
-
const clauses = where.map(String).filter((x2) => x2).join(" AND ");
|
|
3717
|
+
if (_with.length) sql2.push(`WITH ${_with.join(", ")}`);
|
|
3718
|
+
sql2.push(`SELECT${_distinct ? " DISTINCT" : ""} ${_select.join(", ")}`);
|
|
3719
|
+
if (_from.length) sql2.push(`FROM ${_from.join(", ")}`);
|
|
3720
|
+
if (_where.length) {
|
|
3721
|
+
const clauses = _where.map(String).filter((x2) => x2).join(" AND ");
|
|
3483
3722
|
if (clauses) sql2.push(`WHERE ${clauses}`);
|
|
3484
3723
|
}
|
|
3485
|
-
if (
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
const how = method ? ` (${method}${seed != null ? `, ${seed}` : ""})` : "";
|
|
3489
|
-
sql2.push(`USING SAMPLE ${size}${how}`);
|
|
3724
|
+
if (_sample) sql2.push(`USING SAMPLE ${_sample}`);
|
|
3725
|
+
if (_groupby.length) {
|
|
3726
|
+
sql2.push(`GROUP BY ${_groupby.join(", ")}`);
|
|
3490
3727
|
}
|
|
3491
|
-
if (
|
|
3492
|
-
|
|
3493
|
-
}
|
|
3494
|
-
if (having.length) {
|
|
3495
|
-
const clauses = having.map(String).filter((x2) => x2).join(" AND ");
|
|
3728
|
+
if (_having.length) {
|
|
3729
|
+
const clauses = _having.map(String).filter((x2) => x2).join(" AND ");
|
|
3496
3730
|
if (clauses) sql2.push(`HAVING ${clauses}`);
|
|
3497
3731
|
}
|
|
3498
|
-
if (
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
}
|
|
3502
|
-
if (qualify.length) {
|
|
3503
|
-
const clauses = qualify.map(String).filter((x2) => x2).join(" AND ");
|
|
3732
|
+
if (_window.length) sql2.push(`WINDOW ${_window.join(", ")}`);
|
|
3733
|
+
if (_qualify.length) {
|
|
3734
|
+
const clauses = _qualify.map(String).filter((x2) => x2).join(" AND ");
|
|
3504
3735
|
if (clauses) sql2.push(`QUALIFY ${clauses}`);
|
|
3505
3736
|
}
|
|
3506
|
-
if (
|
|
3507
|
-
|
|
3508
|
-
}
|
|
3509
|
-
if (Number.isFinite(limit)) {
|
|
3510
|
-
sql2.push(`LIMIT ${limit}`);
|
|
3511
|
-
}
|
|
3512
|
-
if (Number.isFinite(offset)) {
|
|
3513
|
-
sql2.push(`OFFSET ${offset}`);
|
|
3514
|
-
}
|
|
3737
|
+
if (_orderby.length) sql2.push(`ORDER BY ${_orderby.join(", ")}`);
|
|
3738
|
+
if (Number.isFinite(_limit)) sql2.push(`LIMIT ${_limit}`);
|
|
3739
|
+
if (Number.isFinite(_offset)) sql2.push(`OFFSET ${_offset}`);
|
|
3515
3740
|
return sql2.join(" ");
|
|
3516
3741
|
}
|
|
3517
3742
|
};
|
|
3518
|
-
var
|
|
3743
|
+
var DescribeQuery = class _DescribeQuery extends SQLNode {
|
|
3744
|
+
/**
|
|
3745
|
+
* Instantiate a describe query.
|
|
3746
|
+
*/
|
|
3747
|
+
constructor(query) {
|
|
3748
|
+
super(DESCRIBE_QUERY);
|
|
3749
|
+
this.query = query;
|
|
3750
|
+
}
|
|
3751
|
+
/**
|
|
3752
|
+
* Clone this describe query.
|
|
3753
|
+
* @returns {DescribeQuery}
|
|
3754
|
+
*/
|
|
3755
|
+
clone() {
|
|
3756
|
+
return new _DescribeQuery(this.query.clone());
|
|
3757
|
+
}
|
|
3758
|
+
/**
|
|
3759
|
+
* Generate a SQL query string.
|
|
3760
|
+
* @returns {string}
|
|
3761
|
+
*/
|
|
3762
|
+
toString() {
|
|
3763
|
+
return `DESCRIBE ${this.query}`;
|
|
3764
|
+
}
|
|
3765
|
+
};
|
|
3766
|
+
var SetOperation = class _SetOperation extends Query {
|
|
3767
|
+
/**
|
|
3768
|
+
* Instantiate a new set operation instance.
|
|
3769
|
+
* @param {string} op The set operation.
|
|
3770
|
+
* @param {Query[]} queries The subqueries.
|
|
3771
|
+
*/
|
|
3519
3772
|
constructor(op, queries) {
|
|
3773
|
+
super(SET_OPERATION);
|
|
3520
3774
|
this.op = op;
|
|
3521
|
-
this.queries = queries
|
|
3522
|
-
this.query = { orderby: [] };
|
|
3523
|
-
this.cteFor = null;
|
|
3775
|
+
this.queries = queries;
|
|
3524
3776
|
}
|
|
3777
|
+
/**
|
|
3778
|
+
* Return a list of subqueries.
|
|
3779
|
+
* @returns {Query[]}
|
|
3780
|
+
*/
|
|
3781
|
+
get subqueries() {
|
|
3782
|
+
const { queries, cteFor } = this;
|
|
3783
|
+
if (cteFor) queries.forEach((q) => q.cteFor = cteFor);
|
|
3784
|
+
return queries;
|
|
3785
|
+
}
|
|
3786
|
+
/**
|
|
3787
|
+
* Clone this set operation.
|
|
3788
|
+
* @returns {SetOperation}
|
|
3789
|
+
*/
|
|
3525
3790
|
clone() {
|
|
3526
|
-
const
|
|
3527
|
-
|
|
3528
|
-
return q;
|
|
3791
|
+
const { op, queries, ...rest } = this;
|
|
3792
|
+
return Object.assign(new _SetOperation(op, queries), rest);
|
|
3529
3793
|
}
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3794
|
+
/**
|
|
3795
|
+
* Generate a SQL query string.
|
|
3796
|
+
* @returns {string}
|
|
3797
|
+
*/
|
|
3798
|
+
toString() {
|
|
3799
|
+
const { op, queries, _orderby, _limit, _offset } = this;
|
|
3800
|
+
const sql2 = [queries.join(` ${op} `)];
|
|
3801
|
+
if (_orderby.length) sql2.push(`ORDER BY ${_orderby.join(", ")}`);
|
|
3802
|
+
if (Number.isFinite(_limit)) sql2.push(`LIMIT ${_limit}`);
|
|
3803
|
+
if (Number.isFinite(_offset)) sql2.push(`OFFSET ${_offset}`);
|
|
3804
|
+
return sql2.join(" ");
|
|
3805
|
+
}
|
|
3806
|
+
};
|
|
3807
|
+
|
|
3808
|
+
// ../sql/src/ast/from.js
|
|
3809
|
+
var FromClauseNode = class extends SQLNode {
|
|
3810
|
+
/**
|
|
3811
|
+
* Instantiate a from node.
|
|
3812
|
+
* @param {SQLNode} expr The from expression.
|
|
3813
|
+
* @param {string} alias The output name.
|
|
3814
|
+
*/
|
|
3815
|
+
constructor(expr, alias) {
|
|
3816
|
+
super(FROM_CLAUSE);
|
|
3817
|
+
this.expr = expr;
|
|
3818
|
+
this.alias = alias;
|
|
3819
|
+
}
|
|
3820
|
+
/**
|
|
3821
|
+
* Generate a SQL query string for this node.
|
|
3822
|
+
* @returns {string}
|
|
3823
|
+
*/
|
|
3824
|
+
toString() {
|
|
3825
|
+
const { expr, alias } = this;
|
|
3826
|
+
const ref = isQuery(expr) ? `(${expr})` : `${expr}`;
|
|
3827
|
+
return alias && !(isTableRef(expr) && expr.table.join(".") === alias) ? `${ref} AS ${quoteIdentifier(alias)}` : `${ref}`;
|
|
3828
|
+
}
|
|
3829
|
+
};
|
|
3830
|
+
|
|
3831
|
+
// ../sql/src/ast/in-op.js
|
|
3832
|
+
var InOpNode = class extends ExprNode {
|
|
3833
|
+
/**
|
|
3834
|
+
* Instantiate an in operator node.
|
|
3835
|
+
* @param {ExprNode} expr The input expression.
|
|
3836
|
+
* @param {ExprNode[]} values The value set.
|
|
3837
|
+
*/
|
|
3838
|
+
constructor(expr, values) {
|
|
3839
|
+
super(IN_OPERATOR);
|
|
3840
|
+
this.expr = expr;
|
|
3841
|
+
this.values = values;
|
|
3842
|
+
}
|
|
3843
|
+
/**
|
|
3844
|
+
* Generate a SQL query string for this node.
|
|
3845
|
+
* @returns {string}
|
|
3846
|
+
*/
|
|
3847
|
+
toString() {
|
|
3848
|
+
return `(${this.expr} IN (${this.values.join(", ")}))`;
|
|
3849
|
+
}
|
|
3850
|
+
};
|
|
3851
|
+
|
|
3852
|
+
// ../sql/src/ast/logical-op.js
|
|
3853
|
+
var LogicalOpNode = class extends ExprNode {
|
|
3854
|
+
/**
|
|
3855
|
+
* Instantiate a logical operator node.
|
|
3856
|
+
* @param {string} op The logical operation.
|
|
3857
|
+
* @param {T[]} clauses The input clause expressions.
|
|
3858
|
+
*/
|
|
3859
|
+
constructor(op, clauses) {
|
|
3860
|
+
super(LOGICAL_OPERATOR);
|
|
3861
|
+
this.op = op;
|
|
3862
|
+
this.clauses = clauses;
|
|
3863
|
+
}
|
|
3864
|
+
/**
|
|
3865
|
+
* Generate a SQL query string for this node.
|
|
3866
|
+
* @returns {string}
|
|
3867
|
+
*/
|
|
3868
|
+
toString() {
|
|
3869
|
+
const c = this.clauses;
|
|
3870
|
+
return c.length === 0 ? "" : c.length === 1 ? `${c[0]}` : `(${c.join(` ${this.op} `)})`;
|
|
3871
|
+
}
|
|
3872
|
+
};
|
|
3873
|
+
var AndNode = class extends LogicalOpNode {
|
|
3874
|
+
/**
|
|
3875
|
+
* Instantiate a logical AND operator node.
|
|
3876
|
+
* @param {T[]} clauses The input clause expressions.
|
|
3877
|
+
*/
|
|
3878
|
+
constructor(clauses) {
|
|
3879
|
+
super("AND", clauses);
|
|
3880
|
+
}
|
|
3881
|
+
};
|
|
3882
|
+
var OrNode = class extends LogicalOpNode {
|
|
3883
|
+
/**
|
|
3884
|
+
* Instantiate a logical OR operator node.
|
|
3885
|
+
* @param {T[]} clauses The input clause expressions.
|
|
3886
|
+
*/
|
|
3887
|
+
constructor(clauses) {
|
|
3888
|
+
super("OR", clauses);
|
|
3889
|
+
}
|
|
3890
|
+
};
|
|
3891
|
+
|
|
3892
|
+
// ../sql/src/ast/order-by.js
|
|
3893
|
+
var OrderByNode = class extends ExprNode {
|
|
3894
|
+
/**
|
|
3895
|
+
* Instantiate an order by entry node.
|
|
3896
|
+
* @param {ExprNode} expr The expression to order by.
|
|
3897
|
+
* @param {boolean | undefined} [desc] Flag indicating descending order.
|
|
3898
|
+
* @param {boolean | undefined} [nullsFirst] Flag indicating if null
|
|
3899
|
+
* values should be sorted first.
|
|
3900
|
+
*/
|
|
3901
|
+
constructor(expr, desc2, nullsFirst) {
|
|
3902
|
+
super(ORDER_BY);
|
|
3903
|
+
this.expr = expr;
|
|
3904
|
+
this.desc = desc2;
|
|
3905
|
+
this.nullsFirst = nullsFirst;
|
|
3906
|
+
}
|
|
3907
|
+
/**
|
|
3908
|
+
* Generate a SQL query string for this node.
|
|
3909
|
+
* @returns {string}
|
|
3910
|
+
*/
|
|
3911
|
+
toString() {
|
|
3912
|
+
const { expr, desc: desc2, nullsFirst } = this;
|
|
3913
|
+
const dir = desc2 ? " DESC" : desc2 === false ? " ASC" : "";
|
|
3914
|
+
const nf = nullsFirst ? " NULLS FIRST" : nullsFirst === false ? " NULLS LAST" : "";
|
|
3915
|
+
return `${expr}${dir}${nf}`;
|
|
3916
|
+
}
|
|
3917
|
+
};
|
|
3918
|
+
|
|
3919
|
+
// ../sql/src/ast/unary-op.js
|
|
3920
|
+
var AbstractUnaryOpNode = class extends ExprNode {
|
|
3921
|
+
/**
|
|
3922
|
+
* Instantiate an abstract unary operator node.
|
|
3923
|
+
* @param {string} type The node type.
|
|
3924
|
+
* @param {string} op The operator type.
|
|
3925
|
+
* @param {ExprNode} expr The input expression.
|
|
3926
|
+
*/
|
|
3927
|
+
constructor(type, op, expr) {
|
|
3928
|
+
super(type);
|
|
3929
|
+
this.op = op;
|
|
3930
|
+
this.expr = expr;
|
|
3931
|
+
}
|
|
3932
|
+
};
|
|
3933
|
+
var UnaryPosftixOpNode = class extends AbstractUnaryOpNode {
|
|
3934
|
+
/**
|
|
3935
|
+
* Instantiate a unary operator node.
|
|
3936
|
+
* @param {string} op The operator type.
|
|
3937
|
+
* @param {ExprNode} expr The input expression.
|
|
3938
|
+
*/
|
|
3939
|
+
constructor(op, expr) {
|
|
3940
|
+
super(UNARY_POSTFIX_OPERATOR, op, expr);
|
|
3941
|
+
}
|
|
3942
|
+
/**
|
|
3943
|
+
* Generate a SQL query string for this node.
|
|
3944
|
+
* @returns {string}
|
|
3945
|
+
*/
|
|
3946
|
+
toString() {
|
|
3947
|
+
return `(${this.expr} ${this.op})`;
|
|
3948
|
+
}
|
|
3949
|
+
};
|
|
3950
|
+
|
|
3951
|
+
// ../sql/src/functions/aggregate.js
|
|
3952
|
+
function argmax(y2, x2) {
|
|
3953
|
+
return aggFn("arg_max", y2, x2);
|
|
3954
|
+
}
|
|
3955
|
+
function argmin(y2, x2) {
|
|
3956
|
+
return aggFn("arg_min", y2, x2);
|
|
3957
|
+
}
|
|
3958
|
+
function count(expr) {
|
|
3959
|
+
return aggFn("count", expr);
|
|
3960
|
+
}
|
|
3961
|
+
function max(expr) {
|
|
3962
|
+
return aggFn("max", expr);
|
|
3963
|
+
}
|
|
3964
|
+
function min(expr) {
|
|
3965
|
+
return aggFn("min", expr);
|
|
3966
|
+
}
|
|
3967
|
+
function regrAvgX(x2, y2) {
|
|
3968
|
+
return aggFn("regr_avgx", x2, y2);
|
|
3969
|
+
}
|
|
3970
|
+
function regrAvgY(x2, y2) {
|
|
3971
|
+
return aggFn("regr_avgy", x2, y2);
|
|
3972
|
+
}
|
|
3973
|
+
function regrCount(x2, y2) {
|
|
3974
|
+
return aggFn("regr_count", x2, y2);
|
|
3975
|
+
}
|
|
3976
|
+
function sum(expr) {
|
|
3977
|
+
return aggFn("sum", expr);
|
|
3978
|
+
}
|
|
3979
|
+
|
|
3980
|
+
// ../sql/src/functions/cast.js
|
|
3981
|
+
function cast(expr, type) {
|
|
3982
|
+
return new CastNode(asNode(expr), type);
|
|
3983
|
+
}
|
|
3984
|
+
function int322(expr) {
|
|
3985
|
+
return cast(expr, "INTEGER");
|
|
3986
|
+
}
|
|
3987
|
+
function float642(expr) {
|
|
3988
|
+
return cast(expr, "DOUBLE");
|
|
3989
|
+
}
|
|
3990
|
+
|
|
3991
|
+
// ../sql/src/functions/datetime.js
|
|
3992
|
+
function epoch_ms(expr) {
|
|
3993
|
+
return fn("epoch_ms", expr);
|
|
3994
|
+
}
|
|
3995
|
+
|
|
3996
|
+
// ../sql/src/functions/numeric.js
|
|
3997
|
+
function exp(expr) {
|
|
3998
|
+
return fn("exp", expr);
|
|
3999
|
+
}
|
|
4000
|
+
function log(expr) {
|
|
4001
|
+
return fn("log", expr);
|
|
4002
|
+
}
|
|
4003
|
+
function ln(expr) {
|
|
4004
|
+
return fn("ln", expr);
|
|
4005
|
+
}
|
|
4006
|
+
function sign(expr) {
|
|
4007
|
+
return fn("sign", expr);
|
|
4008
|
+
}
|
|
4009
|
+
function abs(expr) {
|
|
4010
|
+
return fn("abs", expr);
|
|
4011
|
+
}
|
|
4012
|
+
function sqrt(expr) {
|
|
4013
|
+
return fn("sqrt", expr);
|
|
4014
|
+
}
|
|
4015
|
+
function ceil(expr) {
|
|
4016
|
+
return fn("ceil", expr);
|
|
4017
|
+
}
|
|
4018
|
+
function floor(expr) {
|
|
4019
|
+
return fn("floor", expr);
|
|
4020
|
+
}
|
|
4021
|
+
function round(expr, places) {
|
|
4022
|
+
return fn("round", expr, places);
|
|
4023
|
+
}
|
|
4024
|
+
|
|
4025
|
+
// ../sql/src/functions/operators.js
|
|
4026
|
+
function unaryPostfixOp(op, expr) {
|
|
4027
|
+
return new UnaryPosftixOpNode(op, asNode(expr));
|
|
4028
|
+
}
|
|
4029
|
+
function binaryOp(op, left, right) {
|
|
4030
|
+
return new BinaryOpNode(op, asNode(left), asNode(right));
|
|
4031
|
+
}
|
|
4032
|
+
function betweenOp(expr, extent, negate = false) {
|
|
4033
|
+
const Op = negate ? NotBetweenOpNode : BetweenOpNode;
|
|
4034
|
+
return new Op(asNode(expr), extent?.map(asNode));
|
|
4035
|
+
}
|
|
4036
|
+
function and(...clauses) {
|
|
4037
|
+
return new AndNode(exprList(clauses));
|
|
4038
|
+
}
|
|
4039
|
+
function or(...clauses) {
|
|
4040
|
+
return new OrNode(exprList(clauses));
|
|
4041
|
+
}
|
|
4042
|
+
function isNull(expr) {
|
|
4043
|
+
return unaryPostfixOp("IS NULL", expr);
|
|
4044
|
+
}
|
|
4045
|
+
function isNotNull(expr) {
|
|
4046
|
+
return unaryPostfixOp("IS NOT NULL", expr);
|
|
4047
|
+
}
|
|
4048
|
+
function add(left, right) {
|
|
4049
|
+
return binaryOp("+", left, right);
|
|
4050
|
+
}
|
|
4051
|
+
function sub(left, right) {
|
|
4052
|
+
return binaryOp("-", left, right);
|
|
4053
|
+
}
|
|
4054
|
+
function mul(left, right) {
|
|
4055
|
+
return binaryOp("*", left, right);
|
|
4056
|
+
}
|
|
4057
|
+
function div(left, right) {
|
|
4058
|
+
return binaryOp("/", left, right);
|
|
4059
|
+
}
|
|
4060
|
+
function pow(left, right) {
|
|
4061
|
+
return binaryOp("**", left, right);
|
|
4062
|
+
}
|
|
4063
|
+
function isNotDistinct(left, right) {
|
|
4064
|
+
return binaryOp("IS NOT DISTINCT FROM", left, right);
|
|
4065
|
+
}
|
|
4066
|
+
function isBetween(expr, extent) {
|
|
4067
|
+
return betweenOp(expr, extent, false);
|
|
4068
|
+
}
|
|
4069
|
+
function isIn(expr, values) {
|
|
4070
|
+
return new InOpNode(asNode(expr), values.map(asNode));
|
|
4071
|
+
}
|
|
4072
|
+
|
|
4073
|
+
// ../sql/src/functions/order-by.js
|
|
4074
|
+
function desc(expr, nullsFirst) {
|
|
4075
|
+
return new OrderByNode(asNode(expr), true, nullsFirst);
|
|
4076
|
+
}
|
|
4077
|
+
|
|
4078
|
+
// ../sql/src/functions/sql-template-tag.js
|
|
4079
|
+
function sql(strings, ...exprs) {
|
|
4080
|
+
return new FragmentNode(parseSQL(strings, exprs));
|
|
4081
|
+
}
|
|
4082
|
+
function parseSQL(strings, exprs) {
|
|
4083
|
+
const spans = [strings[0]];
|
|
4084
|
+
const n = exprs.length;
|
|
4085
|
+
for (let i = 0, k = 0; i < n; ) {
|
|
4086
|
+
const e = exprs[i];
|
|
4087
|
+
if (isNode(e)) {
|
|
4088
|
+
spans[++k] = e;
|
|
4089
|
+
} else if (isParamLike(e)) {
|
|
4090
|
+
spans[++k] = new ParamNode(e);
|
|
3534
4091
|
} else {
|
|
3535
|
-
|
|
3536
|
-
expr.flat().filter((x2) => x2).map(asColumn)
|
|
3537
|
-
);
|
|
3538
|
-
return this;
|
|
4092
|
+
spans[k] += isString(e) ? e : literal(e);
|
|
3539
4093
|
}
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
if (arguments.length === 0) {
|
|
3544
|
-
return query.limit;
|
|
4094
|
+
const s = strings[++i];
|
|
4095
|
+
if (isNode(spans[k])) {
|
|
4096
|
+
spans[++k] = s;
|
|
3545
4097
|
} else {
|
|
3546
|
-
|
|
3547
|
-
return this;
|
|
4098
|
+
spans[k] += s;
|
|
3548
4099
|
}
|
|
3549
4100
|
}
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
4101
|
+
return spans.filter((s) => s).map((s) => isString(s) ? new VerbatimNode(s) : s);
|
|
4102
|
+
}
|
|
4103
|
+
|
|
4104
|
+
// ../sql/src/functions/string.js
|
|
4105
|
+
function strFn(name, expr, ...args) {
|
|
4106
|
+
return fn(name, expr, ...argsList(args).map(asLiteral));
|
|
4107
|
+
}
|
|
4108
|
+
function regexp_matches(string, pattern, options) {
|
|
4109
|
+
return strFn("regexp_matches", string, pattern, options);
|
|
4110
|
+
}
|
|
4111
|
+
function contains(string, search_string) {
|
|
4112
|
+
return strFn("contains", string, search_string);
|
|
4113
|
+
}
|
|
4114
|
+
function prefix(string, search_string) {
|
|
4115
|
+
return strFn("starts_with", string, search_string);
|
|
4116
|
+
}
|
|
4117
|
+
function suffix(string, search_string) {
|
|
4118
|
+
return strFn("ends_with", string, search_string);
|
|
4119
|
+
}
|
|
4120
|
+
|
|
4121
|
+
// ../sql/src/visit/recurse.js
|
|
4122
|
+
var recurse = {
|
|
4123
|
+
[AGGREGATE]: ["args", "filter"],
|
|
4124
|
+
[BETWEEN_OPERATOR]: ["expr", "extent"],
|
|
4125
|
+
[BINARY_OPERATOR]: ["left", "right"],
|
|
4126
|
+
[CASE]: ["expr", "_when", "_else"],
|
|
4127
|
+
[CAST]: ["expr"],
|
|
4128
|
+
[COLUMN_PARAM]: ["param", "table"],
|
|
4129
|
+
[COLUMN_REF]: ["table"],
|
|
4130
|
+
[DESCRIBE_QUERY]: ["query"],
|
|
4131
|
+
[EXPRESSION]: ["node"],
|
|
4132
|
+
[FRAGMENT]: ["spans"],
|
|
4133
|
+
[FROM_CLAUSE]: ["expr"],
|
|
4134
|
+
[FUNCTION]: ["args"],
|
|
4135
|
+
[IN_OPERATOR]: ["expr", "values"],
|
|
4136
|
+
[LOGICAL_OPERATOR]: ["clauses"],
|
|
4137
|
+
[NOT_BETWEEN_OPERATOR]: ["expr", "extent"],
|
|
4138
|
+
[ORDER_BY]: ["expr"],
|
|
4139
|
+
[PARAM]: ["value"],
|
|
4140
|
+
[SELECT_CLAUSE]: ["expr"],
|
|
4141
|
+
[SELECT_QUERY]: ["_with", "_select", "_from", "_where", "_sample", "_groupby", "_having", "_window", "_qualify", "_orderby"],
|
|
4142
|
+
[SET_OPERATION]: ["subqueries", "_orderby"],
|
|
4143
|
+
[UNARY_OPERATOR]: ["expr"],
|
|
4144
|
+
[WHEN]: ["when", "then"],
|
|
4145
|
+
[WINDOW]: ["func", "def"],
|
|
4146
|
+
[WINDOW_CLAUSE]: ["def"],
|
|
4147
|
+
[WINDOW_DEF]: ["partition", "order", "frame"],
|
|
4148
|
+
[WINDOW_FRAME]: ["extent"]
|
|
4149
|
+
};
|
|
4150
|
+
|
|
4151
|
+
// ../sql/src/visit/rewrite.js
|
|
4152
|
+
function rewrite(node, map2) {
|
|
4153
|
+
if (map2.has(node)) {
|
|
4154
|
+
return map2.get(node);
|
|
4155
|
+
} else if (isNode(node)) {
|
|
4156
|
+
const props = recurse[node.type];
|
|
4157
|
+
const n = props?.length ?? 0;
|
|
4158
|
+
for (let i = 0; i < n; ++i) {
|
|
4159
|
+
const prop = props[i];
|
|
4160
|
+
const child = node[prop];
|
|
4161
|
+
if (Array.isArray(child)) {
|
|
4162
|
+
const m = child.length;
|
|
4163
|
+
for (let j = 0; j < m; ++j) {
|
|
4164
|
+
child[j] = rewrite(child[j], map2);
|
|
4165
|
+
}
|
|
4166
|
+
} else if (child) {
|
|
4167
|
+
node[prop] = rewrite(child, map2);
|
|
4168
|
+
}
|
|
3557
4169
|
}
|
|
3558
4170
|
}
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
4171
|
+
return node;
|
|
4172
|
+
}
|
|
4173
|
+
|
|
4174
|
+
// ../sql/src/visit/walk.js
|
|
4175
|
+
function walk(node, visit2) {
|
|
4176
|
+
if (!isNode(node)) return;
|
|
4177
|
+
const result = visit2(node);
|
|
4178
|
+
if (result) return result;
|
|
4179
|
+
const props = recurse[node.type];
|
|
4180
|
+
const n = props?.length ?? 0;
|
|
4181
|
+
for (let i = 0; i < n; ++i) {
|
|
4182
|
+
const value = node[props[i]];
|
|
4183
|
+
if (Array.isArray(value)) {
|
|
4184
|
+
const m = value.length;
|
|
4185
|
+
for (let j = 0; j < m; ++j) {
|
|
4186
|
+
if (value[j] && +walk(value[j], visit2) < 0) {
|
|
4187
|
+
return result;
|
|
4188
|
+
}
|
|
4189
|
+
}
|
|
4190
|
+
} else if (value && +walk(value, visit2) < 0) {
|
|
4191
|
+
return -1;
|
|
3575
4192
|
}
|
|
3576
|
-
return sql2.join(" ");
|
|
3577
4193
|
}
|
|
3578
|
-
};
|
|
3579
|
-
function isQuery(value) {
|
|
3580
|
-
return value instanceof Query || value instanceof SetOperation;
|
|
3581
4194
|
}
|
|
3582
|
-
|
|
3583
|
-
|
|
4195
|
+
|
|
4196
|
+
// ../sql/src/visit/visitors.js
|
|
4197
|
+
var aggrRegExp = new RegExp(`^(${aggregateNames.join("|")})$`);
|
|
4198
|
+
var funcRegExp = /(\\'|\\"|"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|\w+\()/g;
|
|
4199
|
+
function hasVerbatimAggregate(s) {
|
|
4200
|
+
return s.split(funcRegExp).some((tok) => tok.endsWith("(") && aggrRegExp.test(tok.slice(0, -1)));
|
|
4201
|
+
}
|
|
4202
|
+
function isAggregateExpression(root) {
|
|
4203
|
+
let agg = 0;
|
|
4204
|
+
walk(root, (node) => {
|
|
4205
|
+
switch (node.type) {
|
|
4206
|
+
case WINDOW:
|
|
4207
|
+
return -1;
|
|
4208
|
+
// aggs can't include windows
|
|
4209
|
+
case AGGREGATE:
|
|
4210
|
+
agg |= 1;
|
|
4211
|
+
return -1;
|
|
4212
|
+
case FRAGMENT:
|
|
4213
|
+
case VERBATIM: {
|
|
4214
|
+
let s = `${node}`.toLowerCase();
|
|
4215
|
+
const sub2 = s.indexOf("(select ");
|
|
4216
|
+
if (sub2 >= 0) s = s.slice(0, sub2);
|
|
4217
|
+
if (s.includes(") over ")) return -1;
|
|
4218
|
+
if (hasVerbatimAggregate(s)) {
|
|
4219
|
+
agg |= 2;
|
|
4220
|
+
return -1;
|
|
4221
|
+
}
|
|
4222
|
+
return 1;
|
|
4223
|
+
}
|
|
4224
|
+
}
|
|
4225
|
+
});
|
|
4226
|
+
return agg;
|
|
3584
4227
|
}
|
|
3585
|
-
function
|
|
3586
|
-
|
|
4228
|
+
function collectAggregates(root) {
|
|
4229
|
+
const aggs = /* @__PURE__ */ new Set();
|
|
4230
|
+
walk(root, (node) => {
|
|
4231
|
+
if (node.type === AGGREGATE) {
|
|
4232
|
+
aggs.add(node);
|
|
4233
|
+
}
|
|
4234
|
+
});
|
|
4235
|
+
return Array.from(aggs);
|
|
3587
4236
|
}
|
|
3588
|
-
function
|
|
3589
|
-
|
|
4237
|
+
function collectColumns(root) {
|
|
4238
|
+
const cols = {};
|
|
4239
|
+
walk(root, (node) => {
|
|
4240
|
+
if (node.type === COLUMN_REF) {
|
|
4241
|
+
cols[node] = node;
|
|
4242
|
+
}
|
|
4243
|
+
});
|
|
4244
|
+
return Object.values(cols);
|
|
4245
|
+
}
|
|
4246
|
+
|
|
4247
|
+
// ../sql/src/load/create.js
|
|
4248
|
+
function createTable2(name, query, {
|
|
4249
|
+
replace = false,
|
|
4250
|
+
temp = false,
|
|
4251
|
+
view = false
|
|
4252
|
+
} = {}) {
|
|
4253
|
+
return "CREATE" + (replace ? " OR REPLACE " : " ") + (temp ? "TEMP " : "") + (view ? "VIEW" : "TABLE") + (replace ? " " : " IF NOT EXISTS ") + name + " AS " + query;
|
|
3590
4254
|
}
|
|
3591
4255
|
|
|
3592
|
-
// ../sql/src/scales.js
|
|
4256
|
+
// ../sql/src/transforms/scales.js
|
|
3593
4257
|
var identity = (x2) => x2;
|
|
3594
4258
|
function scaleLinear() {
|
|
3595
4259
|
return {
|
|
3596
4260
|
apply: identity,
|
|
3597
4261
|
invert: identity,
|
|
3598
|
-
sqlApply:
|
|
4262
|
+
sqlApply: asNode,
|
|
3599
4263
|
sqlInvert: identity
|
|
3600
4264
|
};
|
|
3601
4265
|
}
|
|
@@ -3604,23 +4268,23 @@ function scaleLog({ base = null } = {}) {
|
|
|
3604
4268
|
return {
|
|
3605
4269
|
apply: Math.log,
|
|
3606
4270
|
invert: Math.exp,
|
|
3607
|
-
sqlApply: (c) =>
|
|
3608
|
-
sqlInvert: (c) =>
|
|
4271
|
+
sqlApply: (c) => ln(c),
|
|
4272
|
+
sqlInvert: (c) => exp(c)
|
|
3609
4273
|
};
|
|
3610
4274
|
} else if (base === 10) {
|
|
3611
4275
|
return {
|
|
3612
4276
|
apply: Math.log10,
|
|
3613
4277
|
invert: (x2) => Math.pow(10, x2),
|
|
3614
|
-
sqlApply: (c) =>
|
|
3615
|
-
sqlInvert: (c) =>
|
|
4278
|
+
sqlApply: (c) => log(c),
|
|
4279
|
+
sqlInvert: (c) => pow(10, c)
|
|
3616
4280
|
};
|
|
3617
4281
|
} else {
|
|
3618
4282
|
const b = +base;
|
|
3619
4283
|
return {
|
|
3620
4284
|
apply: (x2) => Math.log(x2) / Math.log(b),
|
|
3621
4285
|
invert: (x2) => Math.pow(b, x2),
|
|
3622
|
-
sqlApply: (c) =>
|
|
3623
|
-
sqlInvert: (c) =>
|
|
4286
|
+
sqlApply: (c) => div(ln(c), ln(b)),
|
|
4287
|
+
sqlInvert: (c) => pow(b, c)
|
|
3624
4288
|
};
|
|
3625
4289
|
}
|
|
3626
4290
|
}
|
|
@@ -3629,16 +4293,16 @@ function scaleSymlog({ constant = 1 } = {}) {
|
|
|
3629
4293
|
return {
|
|
3630
4294
|
apply: (x2) => Math.sign(x2) * Math.log1p(Math.abs(x2)),
|
|
3631
4295
|
invert: (x2) => Math.sign(x2) * Math.exp(Math.abs(x2) - _),
|
|
3632
|
-
sqlApply: (c) => (c =
|
|
3633
|
-
sqlInvert: (c) =>
|
|
4296
|
+
sqlApply: (c) => (c = asNode(c), mul(sign(c), ln(add(_, abs(c))))),
|
|
4297
|
+
sqlInvert: (c) => mul(sign(c), sub(exp(abs(c)), _))
|
|
3634
4298
|
};
|
|
3635
4299
|
}
|
|
3636
4300
|
function scaleSqrt() {
|
|
3637
4301
|
return {
|
|
3638
4302
|
apply: (x2) => Math.sign(x2) * Math.sqrt(Math.abs(x2)),
|
|
3639
4303
|
invert: (x2) => Math.sign(x2) * x2 * x2,
|
|
3640
|
-
sqlApply: (c) => (c =
|
|
3641
|
-
sqlInvert: (c) =>
|
|
4304
|
+
sqlApply: (c) => (c = asNode(c), mul(sign(c), sqrt(abs(c)))),
|
|
4305
|
+
sqlInvert: (c) => mul(sign(c), pow(c, 2))
|
|
3642
4306
|
};
|
|
3643
4307
|
}
|
|
3644
4308
|
function scalePow({ exponent = 1 } = {}) {
|
|
@@ -3646,15 +4310,15 @@ function scalePow({ exponent = 1 } = {}) {
|
|
|
3646
4310
|
return {
|
|
3647
4311
|
apply: (x2) => Math.sign(x2) * Math.pow(Math.abs(x2), e),
|
|
3648
4312
|
invert: (x2) => Math.sign(x2) * Math.pow(Math.abs(x2), 1 / e),
|
|
3649
|
-
sqlApply: (c) => (c =
|
|
3650
|
-
sqlInvert: (c) =>
|
|
4313
|
+
sqlApply: (c) => (c = asNode(c), mul(sign(c), pow(abs(c), e))),
|
|
4314
|
+
sqlInvert: (c) => mul(sign(c), pow(abs(c), div(1, e)))
|
|
3651
4315
|
};
|
|
3652
4316
|
}
|
|
3653
4317
|
function scaleTime() {
|
|
3654
4318
|
return {
|
|
3655
4319
|
apply: (x2) => +x2,
|
|
3656
4320
|
invert: (x2) => new Date(x2),
|
|
3657
|
-
sqlApply: (c) => c instanceof Date ? +c :
|
|
4321
|
+
sqlApply: (c) => c instanceof Date ? literal(+c) : isDateLiteral(c) ? literal(+c.value) : epoch_ms(c),
|
|
3658
4322
|
sqlInvert: identity
|
|
3659
4323
|
};
|
|
3660
4324
|
}
|
|
@@ -3672,259 +4336,8 @@ function scaleTransform(options) {
|
|
|
3672
4336
|
const scale = scales[options.type];
|
|
3673
4337
|
return scale ? { ...options, ...scale(options) } : null;
|
|
3674
4338
|
}
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
function create(name, query, {
|
|
3678
|
-
replace = false,
|
|
3679
|
-
temp = true,
|
|
3680
|
-
view = false
|
|
3681
|
-
} = {}) {
|
|
3682
|
-
return "CREATE" + (replace ? " OR REPLACE " : " ") + (temp ? "TEMP " : "") + (view ? "VIEW" : "TABLE") + (replace ? " " : " IF NOT EXISTS ") + name + " AS " + query;
|
|
3683
|
-
}
|
|
3684
|
-
|
|
3685
|
-
// ../core/src/util/index-columns.js
|
|
3686
|
-
function indexColumns(client) {
|
|
3687
|
-
if (!client.filterIndexable) return null;
|
|
3688
|
-
const q = client.query();
|
|
3689
|
-
const from = getBase(q, (q2) => q2.from()?.[0].from.table);
|
|
3690
|
-
if (typeof from !== "string" || !q.select) return null;
|
|
3691
|
-
const aggr = [];
|
|
3692
|
-
const dims = [];
|
|
3693
|
-
const aux = {};
|
|
3694
|
-
const avg2 = (ref) => {
|
|
3695
|
-
const name = ref.column;
|
|
3696
|
-
const expr = getBase(q, (q2) => q2.select().find((c) => c.as === name)?.expr);
|
|
3697
|
-
return `(SELECT AVG(${expr ?? ref}) FROM "${from}")`;
|
|
3698
|
-
};
|
|
3699
|
-
for (const entry of q.select()) {
|
|
3700
|
-
const { as, expr: { aggregate, args } } = entry;
|
|
3701
|
-
const op = aggregate?.toUpperCase?.();
|
|
3702
|
-
switch (op) {
|
|
3703
|
-
case "COUNT":
|
|
3704
|
-
case "SUM":
|
|
3705
|
-
aggr.push({ [as]: agg`SUM("${as}")::DOUBLE` });
|
|
3706
|
-
break;
|
|
3707
|
-
case "AVG":
|
|
3708
|
-
aggr.push({ [as]: avgExpr(aux, as, args[0]) });
|
|
3709
|
-
break;
|
|
3710
|
-
case "ARG_MAX":
|
|
3711
|
-
aggr.push({ [as]: argmaxExpr(aux, as, args) });
|
|
3712
|
-
break;
|
|
3713
|
-
case "ARG_MIN":
|
|
3714
|
-
aggr.push({ [as]: argminExpr(aux, as, args) });
|
|
3715
|
-
break;
|
|
3716
|
-
// variance statistics drop the original aggregate operation
|
|
3717
|
-
// in favor of tracking auxiliary sufficient statistics
|
|
3718
|
-
case "VARIANCE":
|
|
3719
|
-
case "VAR_SAMP":
|
|
3720
|
-
aux[as] = null;
|
|
3721
|
-
aggr.push({ [as]: varianceExpr(aux, args[0], avg2) });
|
|
3722
|
-
break;
|
|
3723
|
-
case "VAR_POP":
|
|
3724
|
-
aux[as] = null;
|
|
3725
|
-
aggr.push({ [as]: varianceExpr(aux, args[0], avg2, false) });
|
|
3726
|
-
break;
|
|
3727
|
-
case "STDDEV":
|
|
3728
|
-
case "STDDEV_SAMP":
|
|
3729
|
-
aux[as] = null;
|
|
3730
|
-
aggr.push({ [as]: agg`SQRT(${varianceExpr(aux, args[0], avg2)})` });
|
|
3731
|
-
break;
|
|
3732
|
-
case "STDDEV_POP":
|
|
3733
|
-
aux[as] = null;
|
|
3734
|
-
aggr.push({ [as]: agg`SQRT(${varianceExpr(aux, args[0], avg2, false)})` });
|
|
3735
|
-
break;
|
|
3736
|
-
case "COVAR_SAMP":
|
|
3737
|
-
aux[as] = null;
|
|
3738
|
-
aggr.push({ [as]: covarianceExpr(aux, args, avg2) });
|
|
3739
|
-
break;
|
|
3740
|
-
case "COVAR_POP":
|
|
3741
|
-
aux[as] = null;
|
|
3742
|
-
aggr.push({ [as]: covarianceExpr(aux, args, avg2, false) });
|
|
3743
|
-
break;
|
|
3744
|
-
case "CORR":
|
|
3745
|
-
aux[as] = null;
|
|
3746
|
-
aggr.push({ [as]: corrExpr(aux, args, avg2) });
|
|
3747
|
-
break;
|
|
3748
|
-
// regression statistics
|
|
3749
|
-
case "REGR_COUNT":
|
|
3750
|
-
aux[as] = null;
|
|
3751
|
-
aggr.push({ [as]: agg`${regrCountExpr(aux, args)}::DOUBLE` });
|
|
3752
|
-
break;
|
|
3753
|
-
case "REGR_AVGX":
|
|
3754
|
-
aux[as] = null;
|
|
3755
|
-
aggr.push({ [as]: regrAvgXExpr(aux, args) });
|
|
3756
|
-
break;
|
|
3757
|
-
case "REGR_AVGY":
|
|
3758
|
-
aux[as] = null;
|
|
3759
|
-
aggr.push({ [as]: regrAvgYExpr(aux, args) });
|
|
3760
|
-
break;
|
|
3761
|
-
case "REGR_SYY":
|
|
3762
|
-
aux[as] = null;
|
|
3763
|
-
aggr.push({ [as]: regrVarExpr(aux, 0, args, avg2) });
|
|
3764
|
-
break;
|
|
3765
|
-
case "REGR_SXX":
|
|
3766
|
-
aux[as] = null;
|
|
3767
|
-
aggr.push({ [as]: regrVarExpr(aux, 1, args, avg2) });
|
|
3768
|
-
break;
|
|
3769
|
-
case "REGR_SXY":
|
|
3770
|
-
aux[as] = null;
|
|
3771
|
-
aggr.push({ [as]: covarianceExpr(aux, args, avg2, null) });
|
|
3772
|
-
break;
|
|
3773
|
-
case "REGR_SLOPE":
|
|
3774
|
-
aux[as] = null;
|
|
3775
|
-
aggr.push({ [as]: regrSlopeExpr(aux, args, avg2) });
|
|
3776
|
-
break;
|
|
3777
|
-
case "REGR_INTERCEPT":
|
|
3778
|
-
aux[as] = null;
|
|
3779
|
-
aggr.push({ [as]: regrInterceptExpr(aux, args, avg2) });
|
|
3780
|
-
break;
|
|
3781
|
-
case "REGR_R2":
|
|
3782
|
-
aux[as] = null;
|
|
3783
|
-
aggr.push({ [as]: agg`(${corrExpr(aux, args, avg2)}) ** 2` });
|
|
3784
|
-
break;
|
|
3785
|
-
// aggregates that commute directly
|
|
3786
|
-
case "MAX":
|
|
3787
|
-
case "MIN":
|
|
3788
|
-
case "BIT_AND":
|
|
3789
|
-
case "BIT_OR":
|
|
3790
|
-
case "BIT_XOR":
|
|
3791
|
-
case "BOOL_AND":
|
|
3792
|
-
case "BOOL_OR":
|
|
3793
|
-
case "PRODUCT":
|
|
3794
|
-
aggr.push({ [as]: agg`${op}("${as}")` });
|
|
3795
|
-
break;
|
|
3796
|
-
// otherwise, check if dimension
|
|
3797
|
-
default:
|
|
3798
|
-
if (!aggregate) dims.push(as);
|
|
3799
|
-
else return null;
|
|
3800
|
-
}
|
|
3801
|
-
}
|
|
3802
|
-
if (!aggr.length) return null;
|
|
3803
|
-
return { from, dims, aggr, aux };
|
|
3804
|
-
}
|
|
3805
|
-
function auxName(type, ...args) {
|
|
3806
|
-
const cols = args.length ? "_" + args.map(sanitize).join("_") : "";
|
|
3807
|
-
return `__${type}${cols}__`;
|
|
3808
|
-
}
|
|
3809
|
-
function sanitize(col) {
|
|
3810
|
-
return `${col}`.replaceAll('"', "").replaceAll(" ", "_");
|
|
3811
|
-
}
|
|
3812
|
-
function getBase(query, get) {
|
|
3813
|
-
const subq = query.subqueries;
|
|
3814
|
-
if (query.select && subq.length === 0) {
|
|
3815
|
-
return get(query);
|
|
3816
|
-
}
|
|
3817
|
-
const base = getBase(subq[0], get);
|
|
3818
|
-
for (let i = 1; i < subq.length; ++i) {
|
|
3819
|
-
const value = getBase(subq[i], get);
|
|
3820
|
-
if (value === void 0) continue;
|
|
3821
|
-
if (value !== base) return NaN;
|
|
3822
|
-
}
|
|
3823
|
-
return base;
|
|
3824
|
-
}
|
|
3825
|
-
function countExpr(aux, arg) {
|
|
3826
|
-
const n = auxName("count", arg);
|
|
3827
|
-
aux[n] = agg`COUNT(${arg})`;
|
|
3828
|
-
return agg`SUM(${n})`.annotate({ name: n });
|
|
3829
|
-
}
|
|
3830
|
-
function avgExpr(aux, as, arg) {
|
|
3831
|
-
const n = countExpr(aux, arg);
|
|
3832
|
-
return agg`(SUM("${as}" * ${n.name}) / ${n})`;
|
|
3833
|
-
}
|
|
3834
|
-
function argmaxExpr(aux, as, [, y2]) {
|
|
3835
|
-
const max2 = auxName("max", y2);
|
|
3836
|
-
aux[max2] = agg`MAX(${y2})`;
|
|
3837
|
-
return agg`ARG_MAX("${as}", ${max2})`;
|
|
3838
|
-
}
|
|
3839
|
-
function argminExpr(aux, as, [, y2]) {
|
|
3840
|
-
const min2 = auxName("min", y2);
|
|
3841
|
-
aux[min2] = agg`MIN(${y2})`;
|
|
3842
|
-
return agg`ARG_MIN("${as}", ${min2})`;
|
|
3843
|
-
}
|
|
3844
|
-
function varianceExpr(aux, x2, avg2, correction = true) {
|
|
3845
|
-
const n = countExpr(aux, x2);
|
|
3846
|
-
const ssq = auxName("rssq", x2);
|
|
3847
|
-
const sum2 = auxName("rsum", x2);
|
|
3848
|
-
const delta = sql`${x2} - ${avg2(x2)}`;
|
|
3849
|
-
aux[ssq] = agg`SUM((${delta}) ** 2)`;
|
|
3850
|
-
aux[sum2] = agg`SUM(${delta})`;
|
|
3851
|
-
const adj = correction ? ` - 1` : "";
|
|
3852
|
-
return agg`(SUM(${ssq}) - (SUM(${sum2}) ** 2 / ${n})) / (${n}${adj})`;
|
|
3853
|
-
}
|
|
3854
|
-
function covarianceExpr(aux, args, avg2, correction = true) {
|
|
3855
|
-
const n = regrCountExpr(aux, args);
|
|
3856
|
-
const sxy = regrSumXYExpr(aux, args, avg2);
|
|
3857
|
-
const sx = regrSumExpr(aux, 1, args, avg2);
|
|
3858
|
-
const sy = regrSumExpr(aux, 0, args, avg2);
|
|
3859
|
-
const adj = correction === null ? "" : correction ? ` / (${n} - 1)` : ` / ${n}`;
|
|
3860
|
-
return agg`(${sxy} - ${sx} * ${sy} / ${n})${adj}`;
|
|
3861
|
-
}
|
|
3862
|
-
function corrExpr(aux, args, avg2) {
|
|
3863
|
-
const n = regrCountExpr(aux, args);
|
|
3864
|
-
const sxy = regrSumXYExpr(aux, args, avg2);
|
|
3865
|
-
const sxx = regrSumSqExpr(aux, 1, args, avg2);
|
|
3866
|
-
const syy = regrSumSqExpr(aux, 0, args, avg2);
|
|
3867
|
-
const sx = regrSumExpr(aux, 1, args, avg2);
|
|
3868
|
-
const sy = regrSumExpr(aux, 0, args, avg2);
|
|
3869
|
-
const vx = agg`(${sxx} - (${sx} ** 2) / ${n})`;
|
|
3870
|
-
const vy = agg`(${syy} - (${sy} ** 2) / ${n})`;
|
|
3871
|
-
return agg`(${sxy} - ${sx} * ${sy} / ${n}) / SQRT(${vx} * ${vy})`;
|
|
3872
|
-
}
|
|
3873
|
-
function regrCountExpr(aux, [y2, x2]) {
|
|
3874
|
-
const n = auxName("count", y2, x2);
|
|
3875
|
-
aux[n] = agg`REGR_COUNT(${y2}, ${x2})`;
|
|
3876
|
-
return agg`SUM(${n})`.annotate({ name: n });
|
|
3877
|
-
}
|
|
3878
|
-
function regrSumExpr(aux, i, args, avg2) {
|
|
3879
|
-
const v = args[i];
|
|
3880
|
-
const o = args[1 - i];
|
|
3881
|
-
const sum2 = auxName("rs", v);
|
|
3882
|
-
aux[sum2] = agg`SUM(${v} - ${avg2(v)}) FILTER (${o} IS NOT NULL)`;
|
|
3883
|
-
return agg`SUM(${sum2})`;
|
|
3884
|
-
}
|
|
3885
|
-
function regrSumSqExpr(aux, i, args, avg2) {
|
|
3886
|
-
const v = args[i];
|
|
3887
|
-
const u = args[1 - i];
|
|
3888
|
-
const ssq = auxName("rss", v);
|
|
3889
|
-
aux[ssq] = agg`SUM((${v} - ${avg2(v)}) ** 2) FILTER (${u} IS NOT NULL)`;
|
|
3890
|
-
return agg`SUM(${ssq})`;
|
|
3891
|
-
}
|
|
3892
|
-
function regrSumXYExpr(aux, args, avg2) {
|
|
3893
|
-
const [y2, x2] = args;
|
|
3894
|
-
const sxy = auxName("sxy", y2, x2);
|
|
3895
|
-
aux[sxy] = agg`SUM((${x2} - ${avg2(x2)}) * (${y2} - ${avg2(y2)}))`;
|
|
3896
|
-
return agg`SUM(${sxy})`;
|
|
3897
|
-
}
|
|
3898
|
-
function regrAvgXExpr(aux, args) {
|
|
3899
|
-
const [y2, x2] = args;
|
|
3900
|
-
const n = regrCountExpr(aux, args);
|
|
3901
|
-
const a = auxName("avg", x2, y2);
|
|
3902
|
-
aux[a] = agg`REGR_AVGX(${y2}, ${x2})`;
|
|
3903
|
-
return agg`(SUM(${a} * ${n.name}) / ${n})`;
|
|
3904
|
-
}
|
|
3905
|
-
function regrAvgYExpr(aux, args) {
|
|
3906
|
-
const [y2, x2] = args;
|
|
3907
|
-
const n = regrCountExpr(aux, args);
|
|
3908
|
-
const a = auxName("avg", y2, x2);
|
|
3909
|
-
aux[a] = agg`REGR_AVGY(${y2}, ${x2})`;
|
|
3910
|
-
return agg`(SUM(${a} * ${n.name}) / ${n})`;
|
|
3911
|
-
}
|
|
3912
|
-
function regrVarExpr(aux, i, args, avg2) {
|
|
3913
|
-
const n = regrCountExpr(aux, args);
|
|
3914
|
-
const sum2 = regrSumExpr(aux, i, args, avg2);
|
|
3915
|
-
const ssq = regrSumSqExpr(aux, i, args, avg2);
|
|
3916
|
-
return agg`(${ssq} - (${sum2} ** 2 / ${n}))`;
|
|
3917
|
-
}
|
|
3918
|
-
function regrSlopeExpr(aux, args, avg2) {
|
|
3919
|
-
const cov = covarianceExpr(aux, args, avg2, null);
|
|
3920
|
-
const varx = regrVarExpr(aux, 1, args, avg2);
|
|
3921
|
-
return agg`(${cov}) / ${varx}`;
|
|
3922
|
-
}
|
|
3923
|
-
function regrInterceptExpr(aux, args, avg2) {
|
|
3924
|
-
const ax = regrAvgXExpr(aux, args);
|
|
3925
|
-
const ay = regrAvgYExpr(aux, args);
|
|
3926
|
-
const m = regrSlopeExpr(aux, args, avg2);
|
|
3927
|
-
return agg`${ay} - (${m}) * ${ax}`;
|
|
4339
|
+
function isDateLiteral(x2) {
|
|
4340
|
+
return x2 instanceof LiteralNode && x2.value instanceof Date;
|
|
3928
4341
|
}
|
|
3929
4342
|
|
|
3930
4343
|
// ../core/src/util/hash.js
|
|
@@ -3936,7 +4349,7 @@ function fnv_hash(v) {
|
|
|
3936
4349
|
if (d) a = fnv_multiply(a ^ d >> 8);
|
|
3937
4350
|
a = fnv_multiply(a ^ c & 255);
|
|
3938
4351
|
}
|
|
3939
|
-
return fnv_mix(a);
|
|
4352
|
+
return fnv_mix(a) >>> 0;
|
|
3940
4353
|
}
|
|
3941
4354
|
function fnv_multiply(a) {
|
|
3942
4355
|
return a + (a << 1) + (a << 4) + (a << 7) + (a << 8) + (a << 24);
|
|
@@ -3950,28 +4363,267 @@ function fnv_mix(a) {
|
|
|
3950
4363
|
return a & 4294967295;
|
|
3951
4364
|
}
|
|
3952
4365
|
|
|
3953
|
-
// ../core/src/
|
|
4366
|
+
// ../core/src/preagg/sufficient-statistics.js
|
|
4367
|
+
function sufficientStatistics(node, preagg, avg2) {
|
|
4368
|
+
switch (node.name) {
|
|
4369
|
+
case "count":
|
|
4370
|
+
case "sum":
|
|
4371
|
+
return sumExpr(preagg, node);
|
|
4372
|
+
case "avg":
|
|
4373
|
+
return avgExpr(preagg, node);
|
|
4374
|
+
case "arg_max":
|
|
4375
|
+
return argmaxExpr(preagg, node);
|
|
4376
|
+
case "arg_min":
|
|
4377
|
+
return argminExpr(preagg, node);
|
|
4378
|
+
// variance statistics drop the original aggregate operation
|
|
4379
|
+
// in favor of tracking sufficient statistics
|
|
4380
|
+
case "variance":
|
|
4381
|
+
case "var_samp":
|
|
4382
|
+
return varianceExpr(preagg, node, avg2);
|
|
4383
|
+
case "var_pop":
|
|
4384
|
+
return varianceExpr(preagg, node, avg2, false);
|
|
4385
|
+
case "stddev":
|
|
4386
|
+
case "stddev_samp":
|
|
4387
|
+
return sqrt(varianceExpr(preagg, node, avg2));
|
|
4388
|
+
case "stddev_pop":
|
|
4389
|
+
return sqrt(varianceExpr(preagg, node, avg2, false));
|
|
4390
|
+
case "covar_samp":
|
|
4391
|
+
return covarianceExpr(preagg, node, avg2);
|
|
4392
|
+
case "covar_pop":
|
|
4393
|
+
return covarianceExpr(preagg, node, avg2, false);
|
|
4394
|
+
case "corr":
|
|
4395
|
+
return corrExpr(preagg, node, avg2);
|
|
4396
|
+
// regression statistics
|
|
4397
|
+
case "regr_count":
|
|
4398
|
+
return regrCountExpr(preagg, node).expr;
|
|
4399
|
+
case "regr_avgx":
|
|
4400
|
+
return regrAvgXExpr(preagg, node);
|
|
4401
|
+
case "regr_avgy":
|
|
4402
|
+
return regrAvgYExpr(preagg, node);
|
|
4403
|
+
case "regr_syy":
|
|
4404
|
+
return regrVarExpr(preagg, 0, node, avg2);
|
|
4405
|
+
case "regr_sxx":
|
|
4406
|
+
return regrVarExpr(preagg, 1, node, avg2);
|
|
4407
|
+
case "regr_sxy":
|
|
4408
|
+
return covarianceExpr(preagg, node, avg2, null);
|
|
4409
|
+
case "regr_slope":
|
|
4410
|
+
return regrSlopeExpr(preagg, node, avg2);
|
|
4411
|
+
case "regr_intercept":
|
|
4412
|
+
return regrInterceptExpr(preagg, node, avg2);
|
|
4413
|
+
case "regr_r2":
|
|
4414
|
+
return pow(corrExpr(preagg, node, avg2), 2);
|
|
4415
|
+
// aggregates that commute directly
|
|
4416
|
+
case "max":
|
|
4417
|
+
case "min":
|
|
4418
|
+
case "bit_and":
|
|
4419
|
+
case "bit_or":
|
|
4420
|
+
case "bit_xor":
|
|
4421
|
+
case "bool_and":
|
|
4422
|
+
case "bool_or":
|
|
4423
|
+
case "product": {
|
|
4424
|
+
const name = colName(node);
|
|
4425
|
+
preagg[name] = node;
|
|
4426
|
+
return sql`${node.name}("${name}")`;
|
|
4427
|
+
}
|
|
4428
|
+
// unsupported aggregate, return null to indicate failure
|
|
4429
|
+
default:
|
|
4430
|
+
return null;
|
|
4431
|
+
}
|
|
4432
|
+
}
|
|
4433
|
+
function colName(node) {
|
|
4434
|
+
return "pre_" + fnv_hash(`${node}`).toString(16);
|
|
4435
|
+
}
|
|
4436
|
+
function addStat(preagg, expr, node) {
|
|
4437
|
+
const filter = node?.filter;
|
|
4438
|
+
if (filter) {
|
|
4439
|
+
expr = expr.filter ? expr.where(and(filter, expr.filter)) : expr.where(filter);
|
|
4440
|
+
}
|
|
4441
|
+
const name = colName(expr);
|
|
4442
|
+
preagg[name] = expr;
|
|
4443
|
+
return name;
|
|
4444
|
+
}
|
|
4445
|
+
function countExpr(preagg, node) {
|
|
4446
|
+
const name = addStat(preagg, count(node.args[0]), node);
|
|
4447
|
+
return { expr: sum(name), name };
|
|
4448
|
+
}
|
|
4449
|
+
function sumExpr(preagg, node) {
|
|
4450
|
+
return sum(addStat(preagg, node));
|
|
4451
|
+
}
|
|
4452
|
+
function avgExpr(preagg, node) {
|
|
4453
|
+
const as = addStat(preagg, node);
|
|
4454
|
+
const { expr, name } = countExpr(preagg, node);
|
|
4455
|
+
return div(sum(mul(as, name)), expr);
|
|
4456
|
+
}
|
|
4457
|
+
function argmaxExpr(preagg, node) {
|
|
4458
|
+
const expr = addStat(preagg, node);
|
|
4459
|
+
const maxy = addStat(preagg, max(node.args[1]), node);
|
|
4460
|
+
return argmax(expr, maxy);
|
|
4461
|
+
}
|
|
4462
|
+
function argminExpr(preagg, node) {
|
|
4463
|
+
const expr = addStat(preagg, node);
|
|
4464
|
+
const miny = addStat(preagg, min(node.args[1]), node);
|
|
4465
|
+
return argmin(expr, miny);
|
|
4466
|
+
}
|
|
4467
|
+
function varianceExpr(preagg, node, avg2, correction = true) {
|
|
4468
|
+
const x2 = node.args[0];
|
|
4469
|
+
const { expr: n } = countExpr(preagg, node);
|
|
4470
|
+
const delta = sub(x2, avg2(x2));
|
|
4471
|
+
const rssq = addStat(preagg, sum(pow(delta, 2)), node);
|
|
4472
|
+
const rsum = addStat(preagg, sum(delta), node);
|
|
4473
|
+
const denom = correction ? sub(n, 1) : n;
|
|
4474
|
+
return div(sub(sum(rssq), div(pow(sum(rsum), 2), n)), denom);
|
|
4475
|
+
}
|
|
4476
|
+
function covarianceExpr(preagg, node, avg2, correction = true) {
|
|
4477
|
+
const { expr: n } = regrCountExpr(preagg, node);
|
|
4478
|
+
const sxy = regrSumXYExpr(preagg, node, avg2);
|
|
4479
|
+
const sx = regrSumExpr(preagg, 1, node, avg2);
|
|
4480
|
+
const sy = regrSumExpr(preagg, 0, node, avg2);
|
|
4481
|
+
const num = sub(sxy, div(mul(sx, sy), n));
|
|
4482
|
+
return correction === null ? num : correction ? div(num, sub(n, 1)) : div(num, n);
|
|
4483
|
+
}
|
|
4484
|
+
function corrExpr(preagg, node, avg2) {
|
|
4485
|
+
const { expr: n } = regrCountExpr(preagg, node);
|
|
4486
|
+
const sxy = regrSumXYExpr(preagg, node, avg2);
|
|
4487
|
+
const sxx = regrSumSqExpr(preagg, 1, node, avg2);
|
|
4488
|
+
const syy = regrSumSqExpr(preagg, 0, node, avg2);
|
|
4489
|
+
const sx = regrSumExpr(preagg, 1, node, avg2);
|
|
4490
|
+
const sy = regrSumExpr(preagg, 0, node, avg2);
|
|
4491
|
+
const vx = sub(sxx, div(pow(sx, 2), n));
|
|
4492
|
+
const vy = sub(syy, div(pow(sy, 2), n));
|
|
4493
|
+
return div(
|
|
4494
|
+
sub(sxy, div(mul(sx, sy), n)),
|
|
4495
|
+
sqrt(mul(vx, vy))
|
|
4496
|
+
);
|
|
4497
|
+
}
|
|
4498
|
+
function regrCountExpr(preagg, node) {
|
|
4499
|
+
const [x2, y2] = node.args;
|
|
4500
|
+
const n = addStat(preagg, regrCount(x2, y2), node);
|
|
4501
|
+
return { expr: sum(n), name: n };
|
|
4502
|
+
}
|
|
4503
|
+
function regrSumExpr(preagg, i, node, avg2) {
|
|
4504
|
+
const args = node.args;
|
|
4505
|
+
const v = args[i];
|
|
4506
|
+
const o = args[1 - i];
|
|
4507
|
+
const rsum = sum(sub(v, avg2(v))).where(isNotNull(o));
|
|
4508
|
+
return sum(addStat(preagg, rsum, node));
|
|
4509
|
+
}
|
|
4510
|
+
function regrSumSqExpr(preagg, i, node, avg2) {
|
|
4511
|
+
const args = node.args;
|
|
4512
|
+
const v = args[i];
|
|
4513
|
+
const u = args[1 - i];
|
|
4514
|
+
const ssq = sum(pow(sub(v, avg2(v)), 2)).where(isNotNull(u));
|
|
4515
|
+
return sum(addStat(preagg, ssq, node));
|
|
4516
|
+
}
|
|
4517
|
+
function regrSumXYExpr(preagg, node, avg2) {
|
|
4518
|
+
const [y2, x2] = node.args;
|
|
4519
|
+
const sxy = sum(mul(sub(x2, avg2(x2)), sub(y2, avg2(y2))));
|
|
4520
|
+
return sum(addStat(preagg, sxy, node));
|
|
4521
|
+
}
|
|
4522
|
+
function regrAvgXExpr(preagg, node) {
|
|
4523
|
+
const [y2, x2] = node.args;
|
|
4524
|
+
const { expr: n, name } = regrCountExpr(preagg, node);
|
|
4525
|
+
const a = addStat(preagg, regrAvgX(y2, x2), node);
|
|
4526
|
+
return div(sum(mul(a, name)), n);
|
|
4527
|
+
}
|
|
4528
|
+
function regrAvgYExpr(preagg, node) {
|
|
4529
|
+
const [y2, x2] = node.args;
|
|
4530
|
+
const { expr: n, name } = regrCountExpr(preagg, node);
|
|
4531
|
+
const a = addStat(preagg, regrAvgY(y2, x2), node);
|
|
4532
|
+
return div(sum(mul(a, name)), n);
|
|
4533
|
+
}
|
|
4534
|
+
function regrVarExpr(preagg, i, node, avg2) {
|
|
4535
|
+
const { expr: n } = regrCountExpr(preagg, node);
|
|
4536
|
+
const sum2 = regrSumExpr(preagg, i, node, avg2);
|
|
4537
|
+
const ssq = regrSumSqExpr(preagg, i, node, avg2);
|
|
4538
|
+
return sub(ssq, div(pow(sum2, 2), n));
|
|
4539
|
+
}
|
|
4540
|
+
function regrSlopeExpr(preagg, node, avg2) {
|
|
4541
|
+
const cov = covarianceExpr(preagg, node, avg2, null);
|
|
4542
|
+
const varx = regrVarExpr(preagg, 1, node, avg2);
|
|
4543
|
+
return div(cov, varx);
|
|
4544
|
+
}
|
|
4545
|
+
function regrInterceptExpr(preagg, node, avg2) {
|
|
4546
|
+
const ax = regrAvgXExpr(preagg, node);
|
|
4547
|
+
const ay = regrAvgYExpr(preagg, node);
|
|
4548
|
+
const m = regrSlopeExpr(preagg, node, avg2);
|
|
4549
|
+
return sub(ay, mul(m, ax));
|
|
4550
|
+
}
|
|
4551
|
+
|
|
4552
|
+
// ../core/src/preagg/preagg-columns.js
|
|
4553
|
+
function preaggColumns(client) {
|
|
4554
|
+
if (!client.filterStable) return null;
|
|
4555
|
+
const q = client.query();
|
|
4556
|
+
if (!isSelectQuery(q)) return null;
|
|
4557
|
+
const from = getBase(q, (q2) => {
|
|
4558
|
+
const ref = q2._from[0]?.expr;
|
|
4559
|
+
return isTableRef(ref) ? ref.name : ref;
|
|
4560
|
+
});
|
|
4561
|
+
if (typeof from !== "string") return null;
|
|
4562
|
+
const aggrs = /* @__PURE__ */ new Map();
|
|
4563
|
+
const preagg = {};
|
|
4564
|
+
const output = {};
|
|
4565
|
+
const group = [];
|
|
4566
|
+
const avg2 = (ref) => {
|
|
4567
|
+
const name = ref.column;
|
|
4568
|
+
const expr = getBase(q, (q2) => q2._select.find((c) => c.alias === name)?.expr);
|
|
4569
|
+
return sql`(SELECT avg(${expr ?? ref}) FROM "${from}")`;
|
|
4570
|
+
};
|
|
4571
|
+
for (const { alias, expr } of q._select) {
|
|
4572
|
+
if (isAggregateExpression(expr) > 1) return null;
|
|
4573
|
+
const nodes = collectAggregates(expr);
|
|
4574
|
+
if (nodes.length === 0) {
|
|
4575
|
+
group.push(alias);
|
|
4576
|
+
preagg[alias] = expr;
|
|
4577
|
+
} else {
|
|
4578
|
+
for (const node of nodes) {
|
|
4579
|
+
if (node.isDistinct) return null;
|
|
4580
|
+
const agg = sufficientStatistics(node, preagg, avg2);
|
|
4581
|
+
if (!agg) return null;
|
|
4582
|
+
aggrs.set(node, agg);
|
|
4583
|
+
}
|
|
4584
|
+
output[alias] = rewrite(expr, aggrs);
|
|
4585
|
+
}
|
|
4586
|
+
}
|
|
4587
|
+
if (!aggrs.size) return null;
|
|
4588
|
+
return { group, preagg, output };
|
|
4589
|
+
}
|
|
4590
|
+
function getBase(query, get) {
|
|
4591
|
+
const subq = query.subqueries;
|
|
4592
|
+
if (isSelectQuery(query) && subq.length === 0) {
|
|
4593
|
+
return get(query);
|
|
4594
|
+
}
|
|
4595
|
+
const base = getBase(subq[0], get);
|
|
4596
|
+
for (let i = 1; i < subq.length; ++i) {
|
|
4597
|
+
const value = getBase(subq[i], get);
|
|
4598
|
+
if (value === void 0) continue;
|
|
4599
|
+
if (value !== base) return NaN;
|
|
4600
|
+
}
|
|
4601
|
+
return base;
|
|
4602
|
+
}
|
|
4603
|
+
|
|
4604
|
+
// ../core/src/preagg/PreAggregator.js
|
|
3954
4605
|
var Skip = { skip: true, result: null };
|
|
3955
|
-
var
|
|
4606
|
+
var PreAggregator = class {
|
|
3956
4607
|
/**
|
|
3957
|
-
* Create a new
|
|
3958
|
-
* @param {import('
|
|
3959
|
-
* @param {
|
|
4608
|
+
* Create a new manager of materialized views of pre-aggregated data.
|
|
4609
|
+
* @param {import('../Coordinator.js').Coordinator} coordinator A Mosaic coordinator.
|
|
4610
|
+
* @param {PreAggregateOptions} [options] Pre-aggregation options.
|
|
3960
4611
|
*/
|
|
3961
4612
|
constructor(coordinator2, {
|
|
3962
4613
|
schema = "mosaic",
|
|
3963
4614
|
enabled = true
|
|
3964
4615
|
} = {}) {
|
|
3965
|
-
this.
|
|
4616
|
+
this.entries = /* @__PURE__ */ new Map();
|
|
3966
4617
|
this.active = null;
|
|
3967
4618
|
this.mc = coordinator2;
|
|
3968
4619
|
this._schema = schema;
|
|
3969
4620
|
this._enabled = enabled;
|
|
3970
4621
|
}
|
|
3971
4622
|
/**
|
|
3972
|
-
* Set the enabled state of this
|
|
3973
|
-
* cleared and subsequent
|
|
3974
|
-
* This method has no effect on any
|
|
4623
|
+
* Set the enabled state of this manager. If false, any local state is
|
|
4624
|
+
* cleared and subsequent request calls will return null until re-enabled.
|
|
4625
|
+
* This method has no effect on any pre-aggregated tables already in the
|
|
4626
|
+
* database.
|
|
3975
4627
|
* @param {boolean} [state] The enabled state to set.
|
|
3976
4628
|
*/
|
|
3977
4629
|
set enabled(state) {
|
|
@@ -3981,17 +4633,17 @@ var DataCubeIndexer = class {
|
|
|
3981
4633
|
}
|
|
3982
4634
|
}
|
|
3983
4635
|
/**
|
|
3984
|
-
* Get the enabled state of this
|
|
4636
|
+
* Get the enabled state of this manager.
|
|
3985
4637
|
* @returns {boolean} The current enabled state.
|
|
3986
4638
|
*/
|
|
3987
4639
|
get enabled() {
|
|
3988
4640
|
return this._enabled;
|
|
3989
4641
|
}
|
|
3990
4642
|
/**
|
|
3991
|
-
* Set the database schema used
|
|
3992
|
-
* state is cleared. This method does _not_ drop any
|
|
3993
|
-
*
|
|
3994
|
-
* existing
|
|
4643
|
+
* Set the database schema used for pre-aggregated materialized view tables.
|
|
4644
|
+
* Upon changes, any local state is cleared. This method does _not_ drop any
|
|
4645
|
+
* existing materialized views, use `dropSchema` before changing the schema
|
|
4646
|
+
* to also remove existing materalized views in the database.
|
|
3995
4647
|
* @param {string} [schema] The schema name to set.
|
|
3996
4648
|
*/
|
|
3997
4649
|
set schema(schema) {
|
|
@@ -4001,52 +4653,52 @@ var DataCubeIndexer = class {
|
|
|
4001
4653
|
}
|
|
4002
4654
|
}
|
|
4003
4655
|
/**
|
|
4004
|
-
* Get the database schema used
|
|
4656
|
+
* Get the database schema used for pre-aggregated materialized view tables.
|
|
4005
4657
|
* @returns {string} The current schema name.
|
|
4006
4658
|
*/
|
|
4007
4659
|
get schema() {
|
|
4008
4660
|
return this._schema;
|
|
4009
4661
|
}
|
|
4010
4662
|
/**
|
|
4011
|
-
* Issues a query through the coordinator to drop the current
|
|
4012
|
-
*
|
|
4013
|
-
*
|
|
4014
|
-
*
|
|
4015
|
-
* method with care! Once dropped,
|
|
4016
|
-
*
|
|
4663
|
+
* Issues a query through the coordinator to drop the current schema for
|
|
4664
|
+
* pre-aggregated materialized views. *All* materialized view tables in the
|
|
4665
|
+
* schema will be removed and local state is cleared. Call this method if
|
|
4666
|
+
* the underlying base tables have been updated, causing materialized view
|
|
4667
|
+
* to become stale and inaccurate. Use this method with care! Once dropped,
|
|
4668
|
+
* the schema will be repopulated by future pre-aggregation requests.
|
|
4017
4669
|
* @returns A query result promise.
|
|
4018
4670
|
*/
|
|
4019
|
-
|
|
4671
|
+
dropSchema() {
|
|
4020
4672
|
this.clear();
|
|
4021
4673
|
return this.mc.exec(`DROP SCHEMA IF EXISTS "${this.schema}" CASCADE`);
|
|
4022
4674
|
}
|
|
4023
4675
|
/**
|
|
4024
|
-
* Clear the cache of
|
|
4025
|
-
* selection clause. This method does _not_ drop any existing
|
|
4026
|
-
*
|
|
4027
|
-
* database.
|
|
4676
|
+
* Clear the cache of pre-aggregation entries for the current active
|
|
4677
|
+
* selection clause. This method does _not_ drop any existing materialized
|
|
4678
|
+
* views. Use `dropSchema` to remove existing materialized view tables from
|
|
4679
|
+
* the database.
|
|
4028
4680
|
*/
|
|
4029
4681
|
clear() {
|
|
4030
|
-
this.
|
|
4682
|
+
this.entries.clear();
|
|
4031
4683
|
this.active = null;
|
|
4032
4684
|
}
|
|
4033
4685
|
/**
|
|
4034
|
-
* Return
|
|
4035
|
-
* client-selection pair, or null if the client
|
|
4036
|
-
* method has multiple possible side effects, including
|
|
4037
|
-
*
|
|
4038
|
-
* @param {import('
|
|
4039
|
-
* @param {import('
|
|
4686
|
+
* Return pre-aggregation information for the active state of a
|
|
4687
|
+
* client-selection pair, or null if the client has unstable filters.
|
|
4688
|
+
* This method has multiple possible side effects, including materialized
|
|
4689
|
+
* view creation and updating internal caches.
|
|
4690
|
+
* @param {import('../MosaicClient.js').MosaicClient} client A Mosaic client.
|
|
4691
|
+
* @param {import('../Selection.js').Selection} selection A Mosaic selection
|
|
4040
4692
|
* to filter the client by.
|
|
4041
|
-
* @param {import('
|
|
4693
|
+
* @param {import('../util/selection-types.js').SelectionClause} activeClause
|
|
4042
4694
|
* A representative active selection clause for which to (possibly) generate
|
|
4043
|
-
*
|
|
4044
|
-
* @returns {
|
|
4045
|
-
*
|
|
4695
|
+
* materialized views of pre-aggregates.
|
|
4696
|
+
* @returns {PreAggregateInfo | Skip | null} Information and query generator
|
|
4697
|
+
* for pre-aggregated tables, or null if the client has unstable filters.
|
|
4046
4698
|
*/
|
|
4047
|
-
|
|
4699
|
+
request(client, selection, activeClause) {
|
|
4048
4700
|
if (!this.enabled) return null;
|
|
4049
|
-
const {
|
|
4701
|
+
const { entries, mc, schema } = this;
|
|
4050
4702
|
const { source } = activeClause;
|
|
4051
4703
|
if (!source) return null;
|
|
4052
4704
|
if (this.active) {
|
|
@@ -4058,32 +4710,32 @@ var DataCubeIndexer = class {
|
|
|
4058
4710
|
this.active = active = activeColumns(activeClause);
|
|
4059
4711
|
if (active.source === null) return null;
|
|
4060
4712
|
}
|
|
4061
|
-
if (
|
|
4062
|
-
return
|
|
4713
|
+
if (entries.has(client)) {
|
|
4714
|
+
return entries.get(client);
|
|
4063
4715
|
}
|
|
4064
|
-
const
|
|
4716
|
+
const preaggCols = preaggColumns(client);
|
|
4065
4717
|
let info;
|
|
4066
|
-
if (!
|
|
4718
|
+
if (!preaggCols) {
|
|
4067
4719
|
info = null;
|
|
4068
4720
|
} else if (selection.skip(client, activeClause)) {
|
|
4069
4721
|
info = Skip;
|
|
4070
4722
|
} else {
|
|
4071
4723
|
const filter = selection.remove(source).predicate(client);
|
|
4072
|
-
info =
|
|
4724
|
+
info = preaggregateInfo(client.query(filter), active, preaggCols, schema);
|
|
4073
4725
|
info.result = mc.exec([
|
|
4074
4726
|
`CREATE SCHEMA IF NOT EXISTS ${schema}`,
|
|
4075
|
-
|
|
4727
|
+
createTable2(info.table, info.create, { temp: false })
|
|
4076
4728
|
]);
|
|
4077
4729
|
info.result.catch((e) => mc.logger().error(e));
|
|
4078
4730
|
}
|
|
4079
|
-
|
|
4731
|
+
entries.set(client, info);
|
|
4080
4732
|
return info;
|
|
4081
4733
|
}
|
|
4082
4734
|
};
|
|
4083
4735
|
function activeColumns(clause) {
|
|
4084
4736
|
const { source, meta } = clause;
|
|
4085
4737
|
const clausePred = clause.predicate;
|
|
4086
|
-
const clauseCols = clausePred
|
|
4738
|
+
const clauseCols = collectColumns(clausePred).map((c) => c.column);
|
|
4087
4739
|
let predicate;
|
|
4088
4740
|
let columns;
|
|
4089
4741
|
if (!meta || !clauseCols) {
|
|
@@ -4093,92 +4745,206 @@ function activeColumns(clause) {
|
|
|
4093
4745
|
if (type === "point") {
|
|
4094
4746
|
predicate = (x2) => x2;
|
|
4095
4747
|
columns = Object.fromEntries(
|
|
4096
|
-
clauseCols.map((col) => [`${col}`,
|
|
4748
|
+
clauseCols.map((col) => [`${col}`, asNode(col)])
|
|
4097
4749
|
);
|
|
4098
4750
|
} else if (type === "interval" && scales2) {
|
|
4099
4751
|
const bins = scales2.map((s) => binInterval(s, pixelSize, bin));
|
|
4100
4752
|
if (bins.some((b) => !b)) {
|
|
4101
4753
|
} else if (bins.length === 1) {
|
|
4102
|
-
predicate = (p) => p ? isBetween("active0", p.
|
|
4103
|
-
columns = { active0: bins[0](clausePred.
|
|
4754
|
+
predicate = (p) => p ? isBetween("active0", p.extent.map(bins[0])) : [];
|
|
4755
|
+
columns = { active0: bins[0](clausePred.expr) };
|
|
4104
4756
|
} else {
|
|
4105
|
-
predicate = (p) => p ? and(p.
|
|
4106
|
-
(
|
|
4757
|
+
predicate = (p) => p ? and(p.clauses.map(
|
|
4758
|
+
(c, i) => isBetween(`active${i}`, c.extent.map(bins[i]))
|
|
4107
4759
|
)) : [];
|
|
4108
4760
|
columns = Object.fromEntries(
|
|
4109
4761
|
// @ts-ignore
|
|
4110
|
-
clausePred.
|
|
4762
|
+
clausePred.clauses.map((p, i) => [`active${i}`, bins[i](p.expr)])
|
|
4111
4763
|
);
|
|
4112
4764
|
}
|
|
4113
4765
|
}
|
|
4114
4766
|
return { source: columns ? source : null, columns, predicate };
|
|
4115
4767
|
}
|
|
4116
|
-
var BIN = { ceil
|
|
4768
|
+
var BIN = { ceil, round };
|
|
4117
4769
|
function binInterval(scale, pixelSize, bin) {
|
|
4118
4770
|
const { type, domain, range, apply, sqlApply } = scaleTransform(scale);
|
|
4119
4771
|
if (!apply) return;
|
|
4120
|
-
const
|
|
4772
|
+
const binFn = BIN[`${bin}`.toLowerCase()] || floor;
|
|
4121
4773
|
const lo = apply(Math.min(...domain));
|
|
4122
4774
|
const hi = apply(Math.max(...domain));
|
|
4123
|
-
const
|
|
4124
|
-
const
|
|
4125
|
-
const
|
|
4126
|
-
return (value) =>
|
|
4775
|
+
const s = (type === "identity" ? 1 : Math.abs(range[1] - range[0]) / (hi - lo)) / pixelSize;
|
|
4776
|
+
const scalar = s === 1 ? (x2) => x2 : (x2) => mul(float642(s), x2);
|
|
4777
|
+
const diff = lo === 0 ? (x2) => x2 : (x2) => sub(x2, float642(lo));
|
|
4778
|
+
return (value) => int322(binFn(scalar(diff(sqlApply(value)))));
|
|
4779
|
+
}
|
|
4780
|
+
function preaggregateInfo(clientQuery, active, preaggCols, schema) {
|
|
4781
|
+
const { group, output, preagg } = preaggCols;
|
|
4782
|
+
const { columns } = active;
|
|
4783
|
+
const query = clientQuery.setSelect({ ...preagg, ...columns }).groupby(Object.keys(columns));
|
|
4784
|
+
const [subq] = query.subqueries;
|
|
4785
|
+
if (subq) {
|
|
4786
|
+
const cols = Object.values(columns).flatMap((c) => collectColumns(c).map((c2) => c2.column));
|
|
4787
|
+
subqueryPushdown(subq, cols);
|
|
4788
|
+
}
|
|
4789
|
+
const having = query._having;
|
|
4790
|
+
const order = query._orderby;
|
|
4791
|
+
query._having = [];
|
|
4792
|
+
query._orderby = [];
|
|
4793
|
+
const create2 = query.toString();
|
|
4794
|
+
const id = (fnv_hash(create2) >>> 0).toString(16);
|
|
4795
|
+
const table2 = `${schema}.preagg_${id}`;
|
|
4796
|
+
const select = Query.select(group, output).from(table2).groupby(group).having(having).orderby(order);
|
|
4797
|
+
return new PreAggregateInfo({ table: table2, create: create2, active, select });
|
|
4798
|
+
}
|
|
4799
|
+
function subqueryPushdown(query, cols) {
|
|
4800
|
+
const memo = /* @__PURE__ */ new Set();
|
|
4801
|
+
const pushdown = (q) => {
|
|
4802
|
+
if (memo.has(q)) return;
|
|
4803
|
+
memo.add(q);
|
|
4804
|
+
if (isSelectQuery(q) && q._from.length) {
|
|
4805
|
+
q.select(cols);
|
|
4806
|
+
}
|
|
4807
|
+
q.subqueries.forEach(pushdown);
|
|
4808
|
+
};
|
|
4809
|
+
pushdown(query);
|
|
4810
|
+
}
|
|
4811
|
+
var PreAggregateInfo = class {
|
|
4812
|
+
/**
|
|
4813
|
+
* Create a new pre-aggregation information instance.
|
|
4814
|
+
* @param {object} options Options object.
|
|
4815
|
+
* @param {string} options.table The materialized view table name.
|
|
4816
|
+
* @param {string} options.create The table creation query.
|
|
4817
|
+
* @param {*} options.active Active column information.
|
|
4818
|
+
* @param {SelectQuery} options.select Base query for requesting updates
|
|
4819
|
+
* using a pre-aggregated materialized view.
|
|
4820
|
+
*/
|
|
4821
|
+
constructor({ table: table2, create: create2, active, select }) {
|
|
4822
|
+
this.table = table2;
|
|
4823
|
+
this.create = create2;
|
|
4824
|
+
this.result = null;
|
|
4825
|
+
this.active = active;
|
|
4826
|
+
this.select = select;
|
|
4827
|
+
this.skip = false;
|
|
4828
|
+
}
|
|
4829
|
+
/**
|
|
4830
|
+
* Generate a materialized view query for the given predicate.
|
|
4831
|
+
* @param {import('@uwdata/mosaic-sql').ExprNode} predicate The current
|
|
4832
|
+
* active clause predicate.
|
|
4833
|
+
* @returns {SelectQuery} A materialized view query.
|
|
4834
|
+
*/
|
|
4835
|
+
query(predicate) {
|
|
4836
|
+
return this.select.clone().where(this.active.predicate(predicate));
|
|
4837
|
+
}
|
|
4838
|
+
};
|
|
4839
|
+
|
|
4840
|
+
// ../core/src/util/js-type.js
|
|
4841
|
+
function jsType(type) {
|
|
4842
|
+
switch (type) {
|
|
4843
|
+
case "BIGINT":
|
|
4844
|
+
case "HUGEINT":
|
|
4845
|
+
case "INTEGER":
|
|
4846
|
+
case "SMALLINT":
|
|
4847
|
+
case "TINYINT":
|
|
4848
|
+
case "UBIGINT":
|
|
4849
|
+
case "UINTEGER":
|
|
4850
|
+
case "USMALLINT":
|
|
4851
|
+
case "UTINYINT":
|
|
4852
|
+
// integers
|
|
4853
|
+
case "DOUBLE":
|
|
4854
|
+
case "FLOAT":
|
|
4855
|
+
case "REAL":
|
|
4856
|
+
return "number";
|
|
4857
|
+
case "DATE":
|
|
4858
|
+
case "TIMESTAMP":
|
|
4859
|
+
case "TIMESTAMPTZ":
|
|
4860
|
+
case "TIMESTAMP WITH TIME ZONE":
|
|
4861
|
+
case "TIME":
|
|
4862
|
+
case "TIMESTAMP_NS":
|
|
4863
|
+
return "date";
|
|
4864
|
+
case "BOOLEAN":
|
|
4865
|
+
return "boolean";
|
|
4866
|
+
case "VARCHAR":
|
|
4867
|
+
case "UUID":
|
|
4868
|
+
case "JSON":
|
|
4869
|
+
return "string";
|
|
4870
|
+
case "ARRAY":
|
|
4871
|
+
case "LIST":
|
|
4872
|
+
return "array";
|
|
4873
|
+
case "BLOB":
|
|
4874
|
+
case "STRUCT":
|
|
4875
|
+
case "MAP":
|
|
4876
|
+
case "GEOMETRY":
|
|
4877
|
+
return "object";
|
|
4878
|
+
default:
|
|
4879
|
+
if (type.startsWith("DECIMAL")) {
|
|
4880
|
+
return "number";
|
|
4881
|
+
} else if (type.startsWith("STRUCT") || type.startsWith("MAP")) {
|
|
4882
|
+
return "object";
|
|
4883
|
+
} else if (type.endsWith("]")) {
|
|
4884
|
+
return "array";
|
|
4885
|
+
}
|
|
4886
|
+
throw new Error(`Unsupported type: ${type}`);
|
|
4887
|
+
}
|
|
4888
|
+
}
|
|
4889
|
+
|
|
4890
|
+
// ../core/src/util/field-info.js
|
|
4891
|
+
var Count = "count";
|
|
4892
|
+
var Nulls = "nulls";
|
|
4893
|
+
var Max = "max";
|
|
4894
|
+
var Min = "min";
|
|
4895
|
+
var Distinct = "distinct";
|
|
4896
|
+
var statMap = {
|
|
4897
|
+
[Count]: count,
|
|
4898
|
+
[Distinct]: (column2) => count(column2).distinct(),
|
|
4899
|
+
[Max]: max,
|
|
4900
|
+
[Min]: min,
|
|
4901
|
+
[Nulls]: (column2) => count().where(isNull(column2))
|
|
4902
|
+
};
|
|
4903
|
+
function summarize(table2, column2, stats) {
|
|
4904
|
+
return Query.from(table2).select(Array.from(stats, (s) => ({ [s]: statMap[s](column2) })));
|
|
4127
4905
|
}
|
|
4128
|
-
function
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
if (subq) {
|
|
4134
|
-
const cols = Object.values(columns).flatMap((c) => c.columns);
|
|
4135
|
-
subqueryPushdown(subq, cols);
|
|
4906
|
+
async function queryFieldInfo(mc, fields) {
|
|
4907
|
+
if (fields.length === 1 && fields[0].column === "*") {
|
|
4908
|
+
return getTableInfo(mc, fields[0].table);
|
|
4909
|
+
} else {
|
|
4910
|
+
return (await Promise.all(fields.map((f) => getFieldInfo(mc, f)))).filter((x2) => x2);
|
|
4136
4911
|
}
|
|
4137
|
-
const order = query.orderby();
|
|
4138
|
-
query.query.orderby = [];
|
|
4139
|
-
const create3 = query.toString();
|
|
4140
|
-
const id = (fnv_hash(create3) >>> 0).toString(16);
|
|
4141
|
-
const table2 = `${schema}.cube_${id}`;
|
|
4142
|
-
const select = Query.select(dims, aggr).from(table2).groupby(dims).orderby(order);
|
|
4143
|
-
return new DataCubeInfo({ id, table: table2, create: create3, active, select });
|
|
4144
4912
|
}
|
|
4145
|
-
function
|
|
4146
|
-
const
|
|
4147
|
-
const
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4913
|
+
async function getFieldInfo(mc, { table: table2, column: column2, stats }) {
|
|
4914
|
+
const q = Query.from({ source: table2 }).select({ column: column2 }).groupby(column2.aggregate ? sql`ALL` : []);
|
|
4915
|
+
const [desc2] = Array.from(await mc.query(Query.describe(q)));
|
|
4916
|
+
const info = {
|
|
4917
|
+
table: table2,
|
|
4918
|
+
column: `${column2}`,
|
|
4919
|
+
sqlType: desc2.column_type,
|
|
4920
|
+
type: jsType(desc2.column_type),
|
|
4921
|
+
nullable: desc2.null === "YES"
|
|
4154
4922
|
};
|
|
4155
|
-
|
|
4923
|
+
if (!(stats?.length || stats?.size)) return info;
|
|
4924
|
+
const [result] = await mc.query(
|
|
4925
|
+
summarize(table2, column2, stats),
|
|
4926
|
+
{ persist: true }
|
|
4927
|
+
);
|
|
4928
|
+
return Object.assign(info, result);
|
|
4929
|
+
}
|
|
4930
|
+
async function getTableInfo(mc, table2) {
|
|
4931
|
+
const result = await mc.query(`DESCRIBE ${asTableRef(table2)}`);
|
|
4932
|
+
return Array.from(result).map((desc2) => ({
|
|
4933
|
+
table: table2,
|
|
4934
|
+
column: desc2.column_name,
|
|
4935
|
+
sqlType: desc2.column_type,
|
|
4936
|
+
type: jsType(desc2.column_type),
|
|
4937
|
+
nullable: desc2.null === "YES"
|
|
4938
|
+
}));
|
|
4156
4939
|
}
|
|
4157
|
-
var DataCubeInfo = class {
|
|
4158
|
-
/**
|
|
4159
|
-
* Create a new DataCubeInfo instance.
|
|
4160
|
-
* @param {object} options
|
|
4161
|
-
*/
|
|
4162
|
-
constructor({ table: table2, create: create3, active, select } = {}) {
|
|
4163
|
-
this.table = table2;
|
|
4164
|
-
this.create = create3;
|
|
4165
|
-
this.result = null;
|
|
4166
|
-
this.active = active;
|
|
4167
|
-
this.select = select;
|
|
4168
|
-
this.skip = false;
|
|
4169
|
-
}
|
|
4170
|
-
/**
|
|
4171
|
-
* Generate a data cube index table query for the given predicate.
|
|
4172
|
-
* @param {import('@uwdata/mosaic-sql').SQLExpression} predicate The current
|
|
4173
|
-
* active clause predicate.
|
|
4174
|
-
* @returns {Query} A data cube index table query.
|
|
4175
|
-
*/
|
|
4176
|
-
query(predicate) {
|
|
4177
|
-
return this.select.clone().where(this.active.predicate(predicate));
|
|
4178
|
-
}
|
|
4179
|
-
};
|
|
4180
4940
|
|
|
4181
4941
|
// ../core/src/util/query-result.js
|
|
4942
|
+
var QueryState = Object.freeze({
|
|
4943
|
+
pending: Symbol("pending"),
|
|
4944
|
+
ready: Symbol("ready"),
|
|
4945
|
+
error: Symbol("error"),
|
|
4946
|
+
done: Symbol("done")
|
|
4947
|
+
});
|
|
4182
4948
|
var QueryResult = class extends Promise {
|
|
4183
4949
|
/**
|
|
4184
4950
|
* Create a new query result Promise.
|
|
@@ -4192,14 +4958,37 @@ var QueryResult = class extends Promise {
|
|
|
4192
4958
|
});
|
|
4193
4959
|
this._resolve = resolve;
|
|
4194
4960
|
this._reject = reject;
|
|
4961
|
+
this._state = QueryState.pending;
|
|
4962
|
+
this._value = void 0;
|
|
4195
4963
|
}
|
|
4196
4964
|
/**
|
|
4197
|
-
* Resolve the result Promise with the provided value.
|
|
4965
|
+
* Resolve the result Promise with a prepared value or the provided value.
|
|
4966
|
+
* This method will only succeed if either a value is provided or the promise is ready.
|
|
4198
4967
|
* @param {*} value The result value.
|
|
4199
4968
|
* @returns {this}
|
|
4200
4969
|
*/
|
|
4201
4970
|
fulfill(value) {
|
|
4202
|
-
this.
|
|
4971
|
+
if (this._value !== void 0) {
|
|
4972
|
+
if (value !== void 0) {
|
|
4973
|
+
throw Error("Promise is ready and fulfill has a provided value");
|
|
4974
|
+
}
|
|
4975
|
+
this._resolve(this._value);
|
|
4976
|
+
} else if (value === void 0) {
|
|
4977
|
+
throw Error("Promise is neither ready nor has provided value");
|
|
4978
|
+
} else {
|
|
4979
|
+
this._resolve(value);
|
|
4980
|
+
}
|
|
4981
|
+
this._state = QueryState.done;
|
|
4982
|
+
return this;
|
|
4983
|
+
}
|
|
4984
|
+
/**
|
|
4985
|
+
* Prepare to resolve with the provided value.
|
|
4986
|
+
* @param {*} value The result value.
|
|
4987
|
+
* @returns {this}
|
|
4988
|
+
*/
|
|
4989
|
+
ready(value) {
|
|
4990
|
+
this._state = QueryState.ready;
|
|
4991
|
+
this._value = value;
|
|
4203
4992
|
return this;
|
|
4204
4993
|
}
|
|
4205
4994
|
/**
|
|
@@ -4208,18 +4997,42 @@ var QueryResult = class extends Promise {
|
|
|
4208
4997
|
* @returns {this}
|
|
4209
4998
|
*/
|
|
4210
4999
|
reject(error) {
|
|
5000
|
+
this._state = QueryState.error;
|
|
4211
5001
|
this._reject(error);
|
|
4212
5002
|
return this;
|
|
4213
5003
|
}
|
|
5004
|
+
/**
|
|
5005
|
+
* Returns the state of this query result.
|
|
5006
|
+
* @returns {symbol}
|
|
5007
|
+
*/
|
|
5008
|
+
get state() {
|
|
5009
|
+
return this._state;
|
|
5010
|
+
}
|
|
4214
5011
|
};
|
|
4215
5012
|
QueryResult.prototype.constructor = Promise;
|
|
4216
5013
|
|
|
5014
|
+
// ../core/src/util/void-logger.js
|
|
5015
|
+
function voidLogger() {
|
|
5016
|
+
return {
|
|
5017
|
+
debug(..._) {
|
|
5018
|
+
},
|
|
5019
|
+
info(..._) {
|
|
5020
|
+
},
|
|
5021
|
+
log(..._) {
|
|
5022
|
+
},
|
|
5023
|
+
warn(..._) {
|
|
5024
|
+
},
|
|
5025
|
+
error(..._) {
|
|
5026
|
+
}
|
|
5027
|
+
};
|
|
5028
|
+
}
|
|
5029
|
+
|
|
4217
5030
|
// ../core/src/QueryConsolidator.js
|
|
4218
5031
|
function wait(callback) {
|
|
4219
5032
|
const method = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : typeof setImmediate !== "undefined" ? setImmediate : setTimeout;
|
|
4220
5033
|
return method(callback);
|
|
4221
5034
|
}
|
|
4222
|
-
function consolidator(enqueue, cache
|
|
5035
|
+
function consolidator(enqueue, cache) {
|
|
4223
5036
|
let pending = [];
|
|
4224
5037
|
let id = 0;
|
|
4225
5038
|
function run() {
|
|
@@ -4227,7 +5040,7 @@ function consolidator(enqueue, cache, record) {
|
|
|
4227
5040
|
pending = [];
|
|
4228
5041
|
id = 0;
|
|
4229
5042
|
for (const group of groups) {
|
|
4230
|
-
consolidate(group, enqueue
|
|
5043
|
+
consolidate(group, enqueue);
|
|
4231
5044
|
processResults(group, cache);
|
|
4232
5045
|
}
|
|
4233
5046
|
}
|
|
@@ -4259,36 +5072,31 @@ function entryGroups(entries, cache) {
|
|
|
4259
5072
|
}
|
|
4260
5073
|
function consolidationKey(query, cache) {
|
|
4261
5074
|
const sql2 = `${query}`;
|
|
4262
|
-
if (query
|
|
4263
|
-
if (
|
|
4264
|
-
// @ts-ignore
|
|
4265
|
-
query.orderby().length || query.where().length || // @ts-ignore
|
|
4266
|
-
query.qualify().length || query.having().length
|
|
4267
|
-
) {
|
|
5075
|
+
if (isSelectQuery(query) && !cache.get(sql2)) {
|
|
5076
|
+
if (query._orderby.length || query._where.length || query._qualify.length || query._having.length) {
|
|
4268
5077
|
return sql2;
|
|
4269
5078
|
}
|
|
4270
|
-
const q = query.clone()
|
|
4271
|
-
const groupby = query.
|
|
5079
|
+
const q = query.clone().setSelect("*");
|
|
5080
|
+
const groupby = query._groupby;
|
|
4272
5081
|
if (groupby.length) {
|
|
4273
5082
|
const map2 = {};
|
|
4274
|
-
query.
|
|
4275
|
-
q
|
|
4276
|
-
} else if (query.
|
|
4277
|
-
q
|
|
5083
|
+
query._select.forEach(({ alias, expr }) => map2[alias] = expr);
|
|
5084
|
+
q.setGroupby(groupby.map((e) => isColumnRef(e) && map2[e.column] || e));
|
|
5085
|
+
} else if (query._select.some((e) => isAggregateExpression(e.expr))) {
|
|
5086
|
+
q.setGroupby("ALL");
|
|
4278
5087
|
}
|
|
4279
5088
|
return `${q}`;
|
|
4280
5089
|
} else {
|
|
4281
5090
|
return sql2;
|
|
4282
5091
|
}
|
|
4283
5092
|
}
|
|
4284
|
-
function consolidate(group, enqueue
|
|
5093
|
+
function consolidate(group, enqueue) {
|
|
4285
5094
|
if (shouldConsolidate(group)) {
|
|
4286
5095
|
enqueue({
|
|
4287
5096
|
request: {
|
|
4288
5097
|
type: "arrow",
|
|
4289
5098
|
cache: false,
|
|
4290
|
-
|
|
4291
|
-
query: group.query = consolidatedQuery(group, record)
|
|
5099
|
+
query: group.query = consolidatedQuery(group)
|
|
4292
5100
|
},
|
|
4293
5101
|
result: group.result = new QueryResult()
|
|
4294
5102
|
});
|
|
@@ -4309,31 +5117,30 @@ function shouldConsolidate(group) {
|
|
|
4309
5117
|
}
|
|
4310
5118
|
return false;
|
|
4311
5119
|
}
|
|
4312
|
-
function consolidatedQuery(group
|
|
5120
|
+
function consolidatedQuery(group) {
|
|
4313
5121
|
const maps = group.maps = [];
|
|
4314
5122
|
const fields = /* @__PURE__ */ new Map();
|
|
4315
5123
|
for (const item of group) {
|
|
4316
5124
|
const { query: query2 } = item.entry.request;
|
|
4317
5125
|
const fieldMap = [];
|
|
4318
5126
|
maps.push(fieldMap);
|
|
4319
|
-
for (const {
|
|
5127
|
+
for (const { alias, expr } of query2._select) {
|
|
4320
5128
|
const e = `${expr}`;
|
|
4321
5129
|
if (!fields.has(e)) {
|
|
4322
5130
|
fields.set(e, [`col${fields.size}`, expr]);
|
|
4323
5131
|
}
|
|
4324
5132
|
const [name] = fields.get(e);
|
|
4325
|
-
fieldMap.push([name,
|
|
5133
|
+
fieldMap.push([name, alias]);
|
|
4326
5134
|
}
|
|
4327
|
-
record(`${query2}`);
|
|
4328
5135
|
}
|
|
4329
5136
|
const query = group[0].entry.request.query.clone();
|
|
4330
|
-
const groupby = query.
|
|
5137
|
+
const groupby = query._groupby;
|
|
4331
5138
|
if (groupby.length) {
|
|
4332
5139
|
const map2 = {};
|
|
4333
5140
|
group.maps[0].forEach(([name, as]) => map2[as] = name);
|
|
4334
|
-
query
|
|
5141
|
+
query.setGroupby(groupby.map((e) => isColumnRef(e) && map2[e.column] || e));
|
|
4335
5142
|
}
|
|
4336
|
-
return query
|
|
5143
|
+
return query.setSelect(Array.from(fields.values()));
|
|
4337
5144
|
}
|
|
4338
5145
|
async function processResults(group, cache) {
|
|
4339
5146
|
const { maps, query, result } = group;
|
|
@@ -4505,48 +5312,65 @@ var PriorityQueue = class {
|
|
|
4505
5312
|
};
|
|
4506
5313
|
|
|
4507
5314
|
// ../core/src/QueryManager.js
|
|
4508
|
-
var Priority = { High: 0, Normal: 1, Low: 2 };
|
|
5315
|
+
var Priority = Object.freeze({ High: 0, Normal: 1, Low: 2 });
|
|
4509
5316
|
var QueryManager = class {
|
|
4510
|
-
constructor() {
|
|
5317
|
+
constructor(maxConcurrentRequests = 32) {
|
|
4511
5318
|
this.queue = new PriorityQueue(3);
|
|
4512
5319
|
this.db = null;
|
|
4513
5320
|
this.clientCache = null;
|
|
4514
|
-
this._logger =
|
|
5321
|
+
this._logger = voidLogger();
|
|
4515
5322
|
this._logQueries = false;
|
|
4516
|
-
this.recorders = [];
|
|
4517
|
-
this.pending = null;
|
|
4518
5323
|
this._consolidate = null;
|
|
5324
|
+
this.pendingResults = [];
|
|
5325
|
+
this.maxConcurrentRequests = maxConcurrentRequests;
|
|
5326
|
+
this.pendingExec = false;
|
|
4519
5327
|
}
|
|
4520
5328
|
next() {
|
|
4521
|
-
if (this.
|
|
5329
|
+
if (this.queue.isEmpty() || this.pendingResults.length > this.maxConcurrentRequests || this.pendingExec) {
|
|
5330
|
+
return;
|
|
5331
|
+
}
|
|
4522
5332
|
const { request, result } = this.queue.next();
|
|
4523
|
-
this.
|
|
4524
|
-
|
|
4525
|
-
|
|
5333
|
+
this.pendingResults.push(result);
|
|
5334
|
+
if (request.type === "exec") this.pendingExec = true;
|
|
5335
|
+
this.submit(request, result).finally(() => {
|
|
5336
|
+
while (this.pendingResults.length && this.pendingResults[0].state !== QueryState.pending) {
|
|
5337
|
+
const result2 = this.pendingResults.shift();
|
|
5338
|
+
if (result2.state === QueryState.ready) {
|
|
5339
|
+
result2.fulfill();
|
|
5340
|
+
} else if (result2.state === QueryState.done) {
|
|
5341
|
+
this._logger.warn("Found resolved query in pending results.");
|
|
5342
|
+
}
|
|
5343
|
+
}
|
|
5344
|
+
if (request.type === "exec") this.pendingExec = false;
|
|
4526
5345
|
this.next();
|
|
4527
5346
|
});
|
|
4528
5347
|
}
|
|
5348
|
+
/**
|
|
5349
|
+
* Add an entry to the query queue with a priority.
|
|
5350
|
+
* @param {object} entry The entry to add.
|
|
5351
|
+
* @param {*} [entry.request] The query request.
|
|
5352
|
+
* @param {QueryResult} [entry.result] The query result.
|
|
5353
|
+
* @param {number} priority The query priority, defaults to `Priority.Normal`.
|
|
5354
|
+
*/
|
|
4529
5355
|
enqueue(entry, priority = Priority.Normal) {
|
|
4530
5356
|
this.queue.insert(entry, priority);
|
|
4531
5357
|
this.next();
|
|
4532
5358
|
}
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
5359
|
+
/**
|
|
5360
|
+
* Submit the query to the connector.
|
|
5361
|
+
* @param {*} request The request.
|
|
5362
|
+
* @param {QueryResult} result The query result.
|
|
5363
|
+
*/
|
|
4538
5364
|
async submit(request, result) {
|
|
4539
5365
|
try {
|
|
4540
|
-
const { query, type, cache = false,
|
|
5366
|
+
const { query, type, cache = false, options } = request;
|
|
4541
5367
|
const sql2 = query ? `${query}` : null;
|
|
4542
|
-
if (record) {
|
|
4543
|
-
this.recordQuery(sql2);
|
|
4544
|
-
}
|
|
4545
5368
|
if (cache) {
|
|
4546
5369
|
const cached = this.clientCache.get(sql2);
|
|
4547
5370
|
if (cached) {
|
|
5371
|
+
const data2 = await cached;
|
|
4548
5372
|
this._logger.debug("Cache");
|
|
4549
|
-
result.
|
|
5373
|
+
result.ready(data2);
|
|
4550
5374
|
return;
|
|
4551
5375
|
}
|
|
4552
5376
|
}
|
|
@@ -4554,10 +5378,12 @@ var QueryManager = class {
|
|
|
4554
5378
|
if (this._logQueries) {
|
|
4555
5379
|
this._logger.debug("Query", { type, sql: sql2, ...options });
|
|
4556
5380
|
}
|
|
4557
|
-
const
|
|
5381
|
+
const promise = this.db.query({ type, sql: sql2, ...options });
|
|
5382
|
+
if (cache) this.clientCache.set(sql2, promise);
|
|
5383
|
+
const data = await promise;
|
|
4558
5384
|
if (cache) this.clientCache.set(sql2, data);
|
|
4559
5385
|
this._logger.debug(`Request: ${(performance.now() - t0).toFixed(1)}`);
|
|
4560
|
-
result.
|
|
5386
|
+
result.ready(type === "exec" ? null : data);
|
|
4561
5387
|
} catch (err) {
|
|
4562
5388
|
result.reject(err);
|
|
4563
5389
|
}
|
|
@@ -4576,11 +5402,17 @@ var QueryManager = class {
|
|
|
4576
5402
|
}
|
|
4577
5403
|
consolidate(flag) {
|
|
4578
5404
|
if (flag && !this._consolidate) {
|
|
4579
|
-
this._consolidate = consolidator(this.enqueue.bind(this), this.clientCache
|
|
5405
|
+
this._consolidate = consolidator(this.enqueue.bind(this), this.clientCache);
|
|
4580
5406
|
} else if (!flag && this._consolidate) {
|
|
4581
5407
|
this._consolidate = null;
|
|
4582
5408
|
}
|
|
4583
5409
|
}
|
|
5410
|
+
/**
|
|
5411
|
+
* Request a query result.
|
|
5412
|
+
* @param {*} request The request.
|
|
5413
|
+
* @param {number} priority The query priority, defaults to `Priority.Normal`.
|
|
5414
|
+
* @returns {QueryResult} A query result promise.
|
|
5415
|
+
*/
|
|
4584
5416
|
request(request, priority = Priority.Normal) {
|
|
4585
5417
|
const result = new QueryResult();
|
|
4586
5418
|
const entry = { request, result };
|
|
@@ -4601,6 +5433,11 @@ var QueryManager = class {
|
|
|
4601
5433
|
}
|
|
4602
5434
|
return false;
|
|
4603
5435
|
});
|
|
5436
|
+
for (const result of this.pendingResults) {
|
|
5437
|
+
if (set.has(result)) {
|
|
5438
|
+
result.reject("Canceled");
|
|
5439
|
+
}
|
|
5440
|
+
}
|
|
4604
5441
|
}
|
|
4605
5442
|
}
|
|
4606
5443
|
clear() {
|
|
@@ -4608,145 +5445,12 @@ var QueryManager = class {
|
|
|
4608
5445
|
result.reject("Cleared");
|
|
4609
5446
|
return true;
|
|
4610
5447
|
});
|
|
5448
|
+
for (const result of this.pendingResults) {
|
|
5449
|
+
result.reject("Cleared");
|
|
5450
|
+
}
|
|
5451
|
+
this.pendingResults = [];
|
|
4611
5452
|
}
|
|
4612
|
-
record() {
|
|
4613
|
-
let state = [];
|
|
4614
|
-
const recorder = {
|
|
4615
|
-
add(query) {
|
|
4616
|
-
state.push(query);
|
|
4617
|
-
},
|
|
4618
|
-
reset() {
|
|
4619
|
-
state = [];
|
|
4620
|
-
},
|
|
4621
|
-
snapshot() {
|
|
4622
|
-
return state.slice();
|
|
4623
|
-
},
|
|
4624
|
-
stop() {
|
|
4625
|
-
this.recorders = this.recorders.filter((x2) => x2 !== recorder);
|
|
4626
|
-
return state;
|
|
4627
|
-
}
|
|
4628
|
-
};
|
|
4629
|
-
this.recorders.push(recorder);
|
|
4630
|
-
return recorder;
|
|
4631
|
-
}
|
|
4632
|
-
};
|
|
4633
|
-
|
|
4634
|
-
// ../core/src/util/js-type.js
|
|
4635
|
-
function jsType(type) {
|
|
4636
|
-
switch (type) {
|
|
4637
|
-
case "BIGINT":
|
|
4638
|
-
case "HUGEINT":
|
|
4639
|
-
case "INTEGER":
|
|
4640
|
-
case "SMALLINT":
|
|
4641
|
-
case "TINYINT":
|
|
4642
|
-
case "UBIGINT":
|
|
4643
|
-
case "UINTEGER":
|
|
4644
|
-
case "USMALLINT":
|
|
4645
|
-
case "UTINYINT":
|
|
4646
|
-
// integers
|
|
4647
|
-
case "DOUBLE":
|
|
4648
|
-
case "FLOAT":
|
|
4649
|
-
case "REAL":
|
|
4650
|
-
return "number";
|
|
4651
|
-
case "DATE":
|
|
4652
|
-
case "TIMESTAMP":
|
|
4653
|
-
case "TIMESTAMPTZ":
|
|
4654
|
-
case "TIMESTAMP WITH TIME ZONE":
|
|
4655
|
-
case "TIME":
|
|
4656
|
-
case "TIMESTAMP_NS":
|
|
4657
|
-
return "date";
|
|
4658
|
-
case "BOOLEAN":
|
|
4659
|
-
return "boolean";
|
|
4660
|
-
case "VARCHAR":
|
|
4661
|
-
case "UUID":
|
|
4662
|
-
case "JSON":
|
|
4663
|
-
return "string";
|
|
4664
|
-
case "ARRAY":
|
|
4665
|
-
case "LIST":
|
|
4666
|
-
return "array";
|
|
4667
|
-
case "BLOB":
|
|
4668
|
-
case "STRUCT":
|
|
4669
|
-
case "MAP":
|
|
4670
|
-
case "GEOMETRY":
|
|
4671
|
-
return "object";
|
|
4672
|
-
default:
|
|
4673
|
-
if (type.startsWith("DECIMAL")) {
|
|
4674
|
-
return "number";
|
|
4675
|
-
} else if (type.startsWith("STRUCT") || type.startsWith("MAP")) {
|
|
4676
|
-
return "object";
|
|
4677
|
-
} else if (type.endsWith("]")) {
|
|
4678
|
-
return "array";
|
|
4679
|
-
}
|
|
4680
|
-
throw new Error(`Unsupported type: ${type}`);
|
|
4681
|
-
}
|
|
4682
|
-
}
|
|
4683
|
-
|
|
4684
|
-
// ../core/src/util/field-info.js
|
|
4685
|
-
var Count = "count";
|
|
4686
|
-
var Nulls = "nulls";
|
|
4687
|
-
var Max = "max";
|
|
4688
|
-
var Min = "min";
|
|
4689
|
-
var Distinct = "distinct";
|
|
4690
|
-
var statMap = {
|
|
4691
|
-
[Count]: count,
|
|
4692
|
-
[Distinct]: (column2) => count(column2).distinct(),
|
|
4693
|
-
[Max]: max,
|
|
4694
|
-
[Min]: min,
|
|
4695
|
-
[Nulls]: (column2) => count().where(isNull(column2))
|
|
4696
5453
|
};
|
|
4697
|
-
function summarize(table2, column2, stats) {
|
|
4698
|
-
return Query.from(table2).select(Array.from(stats, (s) => [s, statMap[s](column2)]));
|
|
4699
|
-
}
|
|
4700
|
-
async function queryFieldInfo(mc, fields) {
|
|
4701
|
-
if (fields.length === 1 && `${fields[0].column}` === "*") {
|
|
4702
|
-
return getTableInfo(mc, fields[0].table);
|
|
4703
|
-
} else {
|
|
4704
|
-
return (await Promise.all(fields.map((f) => getFieldInfo(mc, f)))).filter((x2) => x2);
|
|
4705
|
-
}
|
|
4706
|
-
}
|
|
4707
|
-
async function getFieldInfo(mc, { table: table2, column: column2, stats }) {
|
|
4708
|
-
const q = Query.from({ source: table2 }).select({ column: column2 }).groupby(column2.aggregate ? sql`ALL` : []);
|
|
4709
|
-
const [desc2] = Array.from(await mc.query(Query.describe(q)));
|
|
4710
|
-
const info = {
|
|
4711
|
-
table: table2,
|
|
4712
|
-
column: `${column2}`,
|
|
4713
|
-
sqlType: desc2.column_type,
|
|
4714
|
-
type: jsType(desc2.column_type),
|
|
4715
|
-
nullable: desc2.null === "YES"
|
|
4716
|
-
};
|
|
4717
|
-
if (!(stats?.length || stats?.size)) return info;
|
|
4718
|
-
const [result] = await mc.query(
|
|
4719
|
-
summarize(table2, column2, stats),
|
|
4720
|
-
{ persist: true }
|
|
4721
|
-
);
|
|
4722
|
-
return Object.assign(info, result);
|
|
4723
|
-
}
|
|
4724
|
-
async function getTableInfo(mc, table2) {
|
|
4725
|
-
const result = await mc.query(`DESCRIBE ${asRelation(table2)}`);
|
|
4726
|
-
return Array.from(result).map((desc2) => ({
|
|
4727
|
-
table: table2,
|
|
4728
|
-
column: desc2.column_name,
|
|
4729
|
-
sqlType: desc2.column_type,
|
|
4730
|
-
type: jsType(desc2.column_type),
|
|
4731
|
-
nullable: desc2.null === "YES"
|
|
4732
|
-
}));
|
|
4733
|
-
}
|
|
4734
|
-
|
|
4735
|
-
// ../core/src/util/void-logger.js
|
|
4736
|
-
function voidLogger() {
|
|
4737
|
-
return {
|
|
4738
|
-
debug() {
|
|
4739
|
-
},
|
|
4740
|
-
info() {
|
|
4741
|
-
},
|
|
4742
|
-
log() {
|
|
4743
|
-
},
|
|
4744
|
-
warn() {
|
|
4745
|
-
},
|
|
4746
|
-
error() {
|
|
4747
|
-
}
|
|
4748
|
-
};
|
|
4749
|
-
}
|
|
4750
5454
|
|
|
4751
5455
|
// ../core/src/Coordinator.js
|
|
4752
5456
|
var _instance;
|
|
@@ -4764,7 +5468,7 @@ var Coordinator = class {
|
|
|
4764
5468
|
manager = new QueryManager(),
|
|
4765
5469
|
cache = true,
|
|
4766
5470
|
consolidate: consolidate2 = true,
|
|
4767
|
-
|
|
5471
|
+
preagg = {}
|
|
4768
5472
|
} = {}) {
|
|
4769
5473
|
this.manager = manager;
|
|
4770
5474
|
this.manager.cache(cache);
|
|
@@ -4772,7 +5476,7 @@ var Coordinator = class {
|
|
|
4772
5476
|
this.databaseConnector(db);
|
|
4773
5477
|
this.logger(logger);
|
|
4774
5478
|
this.clear();
|
|
4775
|
-
this.
|
|
5479
|
+
this.preaggregator = new PreAggregator(this, preagg);
|
|
4776
5480
|
}
|
|
4777
5481
|
/**
|
|
4778
5482
|
* Clear the coordinator state.
|
|
@@ -4910,12 +5614,12 @@ var Coordinator = class {
|
|
|
4910
5614
|
/**
|
|
4911
5615
|
* Issue a query request for a client. If the query is null or undefined,
|
|
4912
5616
|
* the client is simply updated. Otherwise `updateClient` is called. As a
|
|
4913
|
-
* side effect, this method clears the current
|
|
5617
|
+
* side effect, this method clears the current preaggregator state.
|
|
4914
5618
|
* @param {MosaicClient} client The client to update.
|
|
4915
5619
|
* @param {QueryType | null} [query] The query to issue.
|
|
4916
5620
|
*/
|
|
4917
5621
|
requestQuery(client, query) {
|
|
4918
|
-
this.
|
|
5622
|
+
this.preaggregator.clear();
|
|
4919
5623
|
return query ? this.updateClient(client, query) : Promise.resolve(client.update());
|
|
4920
5624
|
}
|
|
4921
5625
|
/**
|
|
@@ -4975,18 +5679,18 @@ function connectSelection(mc, selection, client) {
|
|
|
4975
5679
|
entry.clients.add(client);
|
|
4976
5680
|
}
|
|
4977
5681
|
function activateSelection(mc, selection, clause) {
|
|
4978
|
-
const {
|
|
5682
|
+
const { preaggregator, filterGroups } = mc;
|
|
4979
5683
|
const { clients } = filterGroups.get(selection);
|
|
4980
5684
|
for (const client of clients) {
|
|
4981
|
-
|
|
5685
|
+
preaggregator.request(client, selection, clause);
|
|
4982
5686
|
}
|
|
4983
5687
|
}
|
|
4984
5688
|
function updateSelection(mc, selection) {
|
|
4985
|
-
const {
|
|
5689
|
+
const { preaggregator, filterGroups } = mc;
|
|
4986
5690
|
const { clients } = filterGroups.get(selection);
|
|
4987
5691
|
const { active } = selection;
|
|
4988
5692
|
return Promise.allSettled(Array.from(clients, (client) => {
|
|
4989
|
-
const info =
|
|
5693
|
+
const info = preaggregator.request(client, selection, active);
|
|
4990
5694
|
const filter = info ? null : selection.predicate(client);
|
|
4991
5695
|
if (info?.skip || !info && !filter) return;
|
|
4992
5696
|
const query = info?.query(active.predicate) ?? client.query(filter);
|
|
@@ -5204,11 +5908,11 @@ var Param = class _Param extends AsyncDispatch {
|
|
|
5204
5908
|
static array(values) {
|
|
5205
5909
|
if (values.some((v) => isParam(v))) {
|
|
5206
5910
|
const p = new _Param();
|
|
5207
|
-
const
|
|
5911
|
+
const update = () => {
|
|
5208
5912
|
p.update(values.map((v) => isParam(v) ? v.value : v));
|
|
5209
5913
|
};
|
|
5210
|
-
|
|
5211
|
-
values.forEach((v) => isParam(v) ? v.addEventListener("value",
|
|
5914
|
+
update();
|
|
5915
|
+
values.forEach((v) => isParam(v) ? v.addEventListener("value", update) : 0);
|
|
5212
5916
|
return p;
|
|
5213
5917
|
}
|
|
5214
5918
|
return new _Param(values);
|
|
@@ -5255,7 +5959,7 @@ var Param = class _Param extends AsyncDispatch {
|
|
|
5255
5959
|
function isSelection(x2) {
|
|
5256
5960
|
return x2 instanceof Selection;
|
|
5257
5961
|
}
|
|
5258
|
-
function
|
|
5962
|
+
function create(options, include) {
|
|
5259
5963
|
return new Selection(
|
|
5260
5964
|
new SelectionResolver(options),
|
|
5261
5965
|
include ? [include].flat() : include
|
|
@@ -5278,7 +5982,7 @@ var Selection = class _Selection extends Param {
|
|
|
5278
5982
|
* @returns {Selection} The new Selection instance.
|
|
5279
5983
|
*/
|
|
5280
5984
|
static intersect({ cross = false, empty = false, include = [] } = {}) {
|
|
5281
|
-
return
|
|
5985
|
+
return create({ cross, empty }, include);
|
|
5282
5986
|
}
|
|
5283
5987
|
/**
|
|
5284
5988
|
* Create a new Selection instance with a
|
|
@@ -5296,7 +6000,7 @@ var Selection = class _Selection extends Param {
|
|
|
5296
6000
|
* @returns {Selection} The new Selection instance.
|
|
5297
6001
|
*/
|
|
5298
6002
|
static union({ cross = false, empty = false, include = [] } = {}) {
|
|
5299
|
-
return
|
|
6003
|
+
return create({ cross, empty, union: true }, include);
|
|
5300
6004
|
}
|
|
5301
6005
|
/**
|
|
5302
6006
|
* Create a new Selection instance with a singular resolution strategy
|
|
@@ -5314,7 +6018,7 @@ var Selection = class _Selection extends Param {
|
|
|
5314
6018
|
* @returns {Selection} The new Selection instance.
|
|
5315
6019
|
*/
|
|
5316
6020
|
static single({ cross = false, empty = false, include = [] } = {}) {
|
|
5317
|
-
return
|
|
6021
|
+
return create({ cross, empty, single: true }, include);
|
|
5318
6022
|
}
|
|
5319
6023
|
/**
|
|
5320
6024
|
* Create a new Selection instance with a
|
|
@@ -5329,7 +6033,7 @@ var Selection = class _Selection extends Param {
|
|
|
5329
6033
|
* @returns {Selection} The new Selection instance.
|
|
5330
6034
|
*/
|
|
5331
6035
|
static crossfilter({ empty = false, include = [] } = {}) {
|
|
5332
|
-
return
|
|
6036
|
+
return create({ cross: true, empty }, include);
|
|
5333
6037
|
}
|
|
5334
6038
|
/**
|
|
5335
6039
|
* Create a new Selection instance.
|
|
@@ -5524,16 +6228,18 @@ var SelectionResolver = class {
|
|
|
5524
6228
|
}
|
|
5525
6229
|
/**
|
|
5526
6230
|
* Return a selection query predicate for the given client.
|
|
5527
|
-
* @param {
|
|
5528
|
-
*
|
|
5529
|
-
* @param {
|
|
6231
|
+
* @param {import('./util/selection-types.js').SelectionClause[]} clauseList
|
|
6232
|
+
* An array of selection clauses.
|
|
6233
|
+
* @param {import('./util/selection-types.js').SelectionClause} active
|
|
6234
|
+
* The current active selection clause.
|
|
6235
|
+
* @param {MosaicClient} client The client whose data may be filtered.
|
|
5530
6236
|
* @returns {*} The query predicate for filtering client data,
|
|
5531
6237
|
* based on the current state of this selection.
|
|
5532
6238
|
*/
|
|
5533
6239
|
predicate(clauseList, active, client) {
|
|
5534
6240
|
const { empty, union: union2 } = this;
|
|
5535
6241
|
if (empty && !clauseList.length) {
|
|
5536
|
-
return [
|
|
6242
|
+
return [literal(false)];
|
|
5537
6243
|
}
|
|
5538
6244
|
if (this.skip(client, active)) return void 0;
|
|
5539
6245
|
const predicates = clauseList.filter((clause) => !this.skip(client, clause)).map((clause) => clause.predicate);
|
|
@@ -5559,7 +6265,7 @@ function clausePoint(field2, value, {
|
|
|
5559
6265
|
source,
|
|
5560
6266
|
clients = source ? /* @__PURE__ */ new Set([source]) : void 0
|
|
5561
6267
|
}) {
|
|
5562
|
-
const predicate = value !== void 0 ?
|
|
6268
|
+
const predicate = value !== void 0 ? isIn(field2, [literal(value)]) : null;
|
|
5563
6269
|
return {
|
|
5564
6270
|
meta: { type: "point" },
|
|
5565
6271
|
source,
|
|
@@ -5574,11 +6280,8 @@ function clausePoints(fields, value, {
|
|
|
5574
6280
|
}) {
|
|
5575
6281
|
let predicate = null;
|
|
5576
6282
|
if (value) {
|
|
5577
|
-
const clauses = value.map((
|
|
5578
|
-
|
|
5579
|
-
return list2.length > 1 ? and(list2) : list2[0];
|
|
5580
|
-
});
|
|
5581
|
-
predicate = clauses.length > 1 ? or(clauses) : clauses[0];
|
|
6283
|
+
const clauses = value.length && fields.length === 1 ? [isIn(fields[0], value.map((v) => literal(v[0])))] : value.map((v) => and(v.map((_, i) => isNotDistinct(fields[i], literal(_)))));
|
|
6284
|
+
predicate = value.length === 0 ? literal(false) : clauses.length > 1 ? or(clauses) : clauses[0];
|
|
5582
6285
|
}
|
|
5583
6286
|
return {
|
|
5584
6287
|
meta: { type: "point" },
|
|
@@ -5605,8 +6308,8 @@ function clauseMatch(field2, value, {
|
|
|
5605
6308
|
clients = void 0,
|
|
5606
6309
|
method = "contains"
|
|
5607
6310
|
}) {
|
|
5608
|
-
let
|
|
5609
|
-
const predicate = value ?
|
|
6311
|
+
let fn2 = MATCH_METHODS[method];
|
|
6312
|
+
const predicate = value ? fn2(field2, literal(value)) : null;
|
|
5610
6313
|
const meta = { type: "match", method };
|
|
5611
6314
|
return { meta, source, clients, value, predicate };
|
|
5612
6315
|
}
|
|
@@ -5726,6 +6429,11 @@ var Menu = class extends MosaicClient {
|
|
|
5726
6429
|
this.selectedValue(value2);
|
|
5727
6430
|
}
|
|
5728
6431
|
});
|
|
6432
|
+
} else {
|
|
6433
|
+
this.select.addEventListener("pointerenter", (evt) => {
|
|
6434
|
+
if (!evt.buttons) this.activate();
|
|
6435
|
+
});
|
|
6436
|
+
this.select.addEventListener("focus", () => this.activate());
|
|
5729
6437
|
}
|
|
5730
6438
|
}
|
|
5731
6439
|
}
|
|
@@ -5745,6 +6453,9 @@ var Menu = class extends MosaicClient {
|
|
|
5745
6453
|
reset() {
|
|
5746
6454
|
this.select.selectedIndex = this.from ? 0 : -1;
|
|
5747
6455
|
}
|
|
6456
|
+
activate() {
|
|
6457
|
+
this.selection.activate(clausePoint(this.field, 0, { source: this }));
|
|
6458
|
+
}
|
|
5748
6459
|
publish(value) {
|
|
5749
6460
|
const { selection, field: field2 } = this;
|
|
5750
6461
|
if (isSelection(selection)) {
|
|
@@ -5851,17 +6562,28 @@ var Search = class extends MosaicClient {
|
|
|
5851
6562
|
this.searchbox.value = value;
|
|
5852
6563
|
}
|
|
5853
6564
|
});
|
|
6565
|
+
} else {
|
|
6566
|
+
this.searchbox.addEventListener("pointerenter", (evt) => {
|
|
6567
|
+
if (!evt.buttons) this.activate();
|
|
6568
|
+
});
|
|
6569
|
+
this.searchbox.addEventListener("focus", () => this.activate());
|
|
5854
6570
|
}
|
|
5855
6571
|
}
|
|
5856
6572
|
}
|
|
5857
6573
|
reset() {
|
|
5858
6574
|
this.searchbox.value = "";
|
|
5859
6575
|
}
|
|
6576
|
+
clause(value) {
|
|
6577
|
+
const { field: field2, type } = this;
|
|
6578
|
+
return clauseMatch(field2, value, { source: this, method: type });
|
|
6579
|
+
}
|
|
6580
|
+
activate() {
|
|
6581
|
+
this.selection.activate(this.clause(""));
|
|
6582
|
+
}
|
|
5860
6583
|
publish(value) {
|
|
5861
|
-
const { selection
|
|
6584
|
+
const { selection } = this;
|
|
5862
6585
|
if (isSelection(selection)) {
|
|
5863
|
-
|
|
5864
|
-
selection.update(clause);
|
|
6586
|
+
selection.update(this.clause(value));
|
|
5865
6587
|
} else if (isParam(selection)) {
|
|
5866
6588
|
selection.update(value);
|
|
5867
6589
|
}
|
|
@@ -5981,13 +6703,20 @@ var Slider = class extends MosaicClient {
|
|
|
5981
6703
|
this.curval.innerText = value2;
|
|
5982
6704
|
if (this.selection) this.publish(+value2);
|
|
5983
6705
|
});
|
|
5984
|
-
if (this.selection
|
|
5985
|
-
this.selection
|
|
5986
|
-
|
|
5987
|
-
this.slider.value
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
6706
|
+
if (this.selection) {
|
|
6707
|
+
if (!isSelection(this.selection)) {
|
|
6708
|
+
this.selection.addEventListener("value", (value2) => {
|
|
6709
|
+
if (value2 !== +this.slider.value) {
|
|
6710
|
+
this.slider.value = value2;
|
|
6711
|
+
this.curval.innerText = value2;
|
|
6712
|
+
}
|
|
6713
|
+
});
|
|
6714
|
+
} else {
|
|
6715
|
+
this.slider.addEventListener("pointerenter", (evt) => {
|
|
6716
|
+
if (!evt.buttons) this.activate();
|
|
6717
|
+
});
|
|
6718
|
+
this.slider.addEventListener("focus", () => this.activate());
|
|
6719
|
+
}
|
|
5991
6720
|
}
|
|
5992
6721
|
}
|
|
5993
6722
|
query(filter = []) {
|
|
@@ -6011,20 +6740,27 @@ var Slider = class extends MosaicClient {
|
|
|
6011
6740
|
}
|
|
6012
6741
|
return this;
|
|
6013
6742
|
}
|
|
6743
|
+
clause(value) {
|
|
6744
|
+
const { field: field2, selectionType } = this;
|
|
6745
|
+
if (selectionType === "interval") {
|
|
6746
|
+
const domain = [this.min ?? 0, value];
|
|
6747
|
+
return clauseInterval(field2, domain, {
|
|
6748
|
+
source: this,
|
|
6749
|
+
bin: "ceil",
|
|
6750
|
+
scale: { type: "identity", domain },
|
|
6751
|
+
pixelSize: this.step
|
|
6752
|
+
});
|
|
6753
|
+
} else {
|
|
6754
|
+
return clausePoint(field2, value, { source: this });
|
|
6755
|
+
}
|
|
6756
|
+
}
|
|
6757
|
+
activate() {
|
|
6758
|
+
this.selection.activate(this.clause(0));
|
|
6759
|
+
}
|
|
6014
6760
|
publish(value) {
|
|
6015
|
-
const {
|
|
6761
|
+
const { selection } = this;
|
|
6016
6762
|
if (isSelection(selection)) {
|
|
6017
|
-
|
|
6018
|
-
const domain = [this.min ?? 0, value];
|
|
6019
|
-
selection.update(clauseInterval(field2, domain, {
|
|
6020
|
-
source: this,
|
|
6021
|
-
bin: "ceil",
|
|
6022
|
-
scale: { type: "identity", domain },
|
|
6023
|
-
pixelSize: this.step
|
|
6024
|
-
}));
|
|
6025
|
-
} else {
|
|
6026
|
-
selection.update(clausePoint(field2, value, { source: this }));
|
|
6027
|
-
}
|
|
6763
|
+
selection.update(this.clause(value));
|
|
6028
6764
|
} else if (isParam(this.selection)) {
|
|
6029
6765
|
selection.update(value);
|
|
6030
6766
|
}
|
|
@@ -6095,6 +6831,9 @@ var Table2 = class extends MosaicClient {
|
|
|
6095
6831
|
this.format = format2;
|
|
6096
6832
|
this.align = align2;
|
|
6097
6833
|
this.widths = typeof width === "object" ? width : {};
|
|
6834
|
+
if (isParam(from)) {
|
|
6835
|
+
from.addEventListener("value", () => this.initialize());
|
|
6836
|
+
}
|
|
6098
6837
|
this.offset = 0;
|
|
6099
6838
|
this.limit = +rowBatch;
|
|
6100
6839
|
this.pending = false;
|
|
@@ -6144,6 +6883,9 @@ var Table2 = class extends MosaicClient {
|
|
|
6144
6883
|
this.style = document.createElement("style");
|
|
6145
6884
|
this.element.appendChild(this.style);
|
|
6146
6885
|
}
|
|
6886
|
+
sourceTable() {
|
|
6887
|
+
return isParam(this.from) ? this.from.value : this.from;
|
|
6888
|
+
}
|
|
6147
6889
|
clause(rows = []) {
|
|
6148
6890
|
const { data, limit, schema } = this;
|
|
6149
6891
|
const fields = schema.map((s) => s.column);
|
|
@@ -6160,7 +6902,8 @@ var Table2 = class extends MosaicClient {
|
|
|
6160
6902
|
coordinator().prefetch(query.clone().offset(offset + this.limit));
|
|
6161
6903
|
}
|
|
6162
6904
|
fields() {
|
|
6163
|
-
|
|
6905
|
+
const from = this.sourceTable();
|
|
6906
|
+
return this.columns.map((name) => column(name, from));
|
|
6164
6907
|
}
|
|
6165
6908
|
fieldInfo(info) {
|
|
6166
6909
|
this.schema = info;
|
|
@@ -6184,8 +6927,8 @@ var Table2 = class extends MosaicClient {
|
|
|
6184
6927
|
return this;
|
|
6185
6928
|
}
|
|
6186
6929
|
query(filter = []) {
|
|
6187
|
-
const {
|
|
6188
|
-
return Query.from(
|
|
6930
|
+
const { limit, offset, schema, sortColumn, sortDesc } = this;
|
|
6931
|
+
return Query.from(this.sourceTable()).select(schema.map((s) => s.column)).where(filter).orderby(sortColumn ? sortDesc ? desc(sortColumn) : sortColumn : []).limit(limit).offset(offset);
|
|
6189
6932
|
}
|
|
6190
6933
|
queryResult(data) {
|
|
6191
6934
|
if (!this.pending) {
|