@uwdata/mosaic-sql 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +19 -0
- package/dist/mosaic-sql.js +232 -27
- package/dist/mosaic-sql.min.js +1 -1
- package/package.json +3 -3
- package/src/Query.js +126 -2
- package/src/aggregates.js +51 -5
- package/src/desc.js +2 -2
- package/src/expression.js +14 -3
- package/src/index.js +2 -1
- package/src/load/load.js +1 -1
- package/src/load/sql-from.js +7 -0
- package/src/ref.js +4 -4
- package/src/scales.js +1 -1
- package/src/windows.js +43 -1
package/LICENSE
CHANGED
|
@@ -26,3 +26,22 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
|
26
26
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
27
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
28
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
Portions of this software are derived from Observable Plot, which is released
|
|
33
|
+
under the ISC license.
|
|
34
|
+
|
|
35
|
+
Copyright 2020-2023 Observable, Inc.
|
|
36
|
+
|
|
37
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose
|
|
38
|
+
with or without fee is hereby granted, provided that the above copyright notice
|
|
39
|
+
and this permission notice appear in all copies.
|
|
40
|
+
|
|
41
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
42
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
43
|
+
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
44
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
45
|
+
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
46
|
+
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
|
47
|
+
THIS SOFTWARE.
|
package/dist/mosaic-sql.js
CHANGED
|
@@ -3,13 +3,11 @@ var Ref = class {
|
|
|
3
3
|
/**
|
|
4
4
|
* Create a new Ref instance.
|
|
5
5
|
* @param {string|Ref|null} table The table name.
|
|
6
|
-
* @param {string|null} column The column name.
|
|
6
|
+
* @param {string|null} [column] The column name.
|
|
7
7
|
*/
|
|
8
8
|
constructor(table, column2) {
|
|
9
|
-
if (table)
|
|
10
|
-
|
|
11
|
-
if (column2)
|
|
12
|
-
this.column = column2;
|
|
9
|
+
if (table) this.table = String(table);
|
|
10
|
+
if (column2) this.column = column2;
|
|
13
11
|
}
|
|
14
12
|
/**
|
|
15
13
|
* Get the list of referenced columns. Either a single element array
|
|
@@ -48,7 +46,7 @@ function asRelation(value) {
|
|
|
48
46
|
function relation(name) {
|
|
49
47
|
return new Ref(name);
|
|
50
48
|
}
|
|
51
|
-
function column(table, column2) {
|
|
49
|
+
function column(table, column2 = null) {
|
|
52
50
|
if (arguments.length === 1) {
|
|
53
51
|
column2 = table;
|
|
54
52
|
table = null;
|
|
@@ -76,8 +74,7 @@ function literalToSQL(value) {
|
|
|
76
74
|
return "NULL";
|
|
77
75
|
} else if (value instanceof Date) {
|
|
78
76
|
const ts = +value;
|
|
79
|
-
if (Number.isNaN(ts))
|
|
80
|
-
return "NULL";
|
|
77
|
+
if (Number.isNaN(ts)) return "NULL";
|
|
81
78
|
const y2 = value.getUTCFullYear();
|
|
82
79
|
const m = value.getUTCMonth();
|
|
83
80
|
const d = value.getUTCDate();
|
|
@@ -98,7 +95,7 @@ function isSQLExpression(value) {
|
|
|
98
95
|
var SQLExpression = class {
|
|
99
96
|
/**
|
|
100
97
|
* Create a new SQL expression instance.
|
|
101
|
-
* @param {(string|SQLExpression|Ref)[]} parts The parts of the expression.
|
|
98
|
+
* @param {(string | ParamLike | SQLExpression | import('./ref.js').Ref)[]} parts The parts of the expression.
|
|
102
99
|
* @param {string[]} [columns=[]] The column dependencies
|
|
103
100
|
* @param {object} [props] Additional properties for this expression.
|
|
104
101
|
*/
|
|
@@ -290,6 +287,16 @@ var isInfinite = functionCall("ISINF");
|
|
|
290
287
|
|
|
291
288
|
// src/windows.js
|
|
292
289
|
var WindowFunction = class _WindowFunction extends SQLExpression {
|
|
290
|
+
/**
|
|
291
|
+
* Create a new WindowFunction instance.
|
|
292
|
+
* @param {string} op The window operation indicator.
|
|
293
|
+
* @param {*} func The window function expression.
|
|
294
|
+
* @param {*} [type] The SQL data type to cast to.
|
|
295
|
+
* @param {string} [name] The window definition name.
|
|
296
|
+
* @param {*} [group] Grouping (partition by) expressions.
|
|
297
|
+
* @param {*} [order] Sorting (order by) expressions.
|
|
298
|
+
* @param {*} [frame] The window frame definition.
|
|
299
|
+
*/
|
|
293
300
|
constructor(op, func, type, name, group = "", order = "", frame = "") {
|
|
294
301
|
let expr;
|
|
295
302
|
const noWindowParams = !(group || order || frame);
|
|
@@ -304,7 +311,14 @@ var WindowFunction = class _WindowFunction extends SQLExpression {
|
|
|
304
311
|
expr = sql`(${expr})::${type}`;
|
|
305
312
|
}
|
|
306
313
|
const { _expr, _deps } = expr;
|
|
307
|
-
super(_expr, _deps
|
|
314
|
+
super(_expr, _deps);
|
|
315
|
+
this.window = op;
|
|
316
|
+
this.func = func;
|
|
317
|
+
this.type = type;
|
|
318
|
+
this.name = name;
|
|
319
|
+
this.group = group;
|
|
320
|
+
this.order = order;
|
|
321
|
+
this.frame = frame;
|
|
308
322
|
}
|
|
309
323
|
get basis() {
|
|
310
324
|
return this.column;
|
|
@@ -313,10 +327,20 @@ var WindowFunction = class _WindowFunction extends SQLExpression {
|
|
|
313
327
|
const { func } = this;
|
|
314
328
|
return func.label ?? func.toString();
|
|
315
329
|
}
|
|
330
|
+
/**
|
|
331
|
+
* Return an updated window function over a named window definition.
|
|
332
|
+
* @param {string} name The window definition name.
|
|
333
|
+
* @returns {WindowFunction} A new window function.
|
|
334
|
+
*/
|
|
316
335
|
over(name) {
|
|
317
336
|
const { window: op, func, type, group, order, frame } = this;
|
|
318
337
|
return new _WindowFunction(op, func, type, name, group, order, frame);
|
|
319
338
|
}
|
|
339
|
+
/**
|
|
340
|
+
* Return an updated window function with the given partitioning.
|
|
341
|
+
* @param {*} expr The grouping (partition by) criteria for the window function.
|
|
342
|
+
* @returns {WindowFunction} A new window function.
|
|
343
|
+
*/
|
|
320
344
|
partitionby(...expr) {
|
|
321
345
|
const exprs = expr.flat().filter((x2) => x2).map(asColumn);
|
|
322
346
|
const group = sql(
|
|
@@ -326,6 +350,11 @@ var WindowFunction = class _WindowFunction extends SQLExpression {
|
|
|
326
350
|
const { window: op, func, type, name, order, frame } = this;
|
|
327
351
|
return new _WindowFunction(op, func, type, name, group, order, frame);
|
|
328
352
|
}
|
|
353
|
+
/**
|
|
354
|
+
* Return an updated window function with the given ordering.
|
|
355
|
+
* @param {*} expr The sorting (order by) criteria for the window function.
|
|
356
|
+
* @returns {WindowFunction} A new window function.
|
|
357
|
+
*/
|
|
329
358
|
orderby(...expr) {
|
|
330
359
|
const exprs = expr.flat().filter((x2) => x2).map(asColumn);
|
|
331
360
|
const order = sql(
|
|
@@ -335,11 +364,21 @@ var WindowFunction = class _WindowFunction extends SQLExpression {
|
|
|
335
364
|
const { window: op, func, type, name, group, frame } = this;
|
|
336
365
|
return new _WindowFunction(op, func, type, name, group, order, frame);
|
|
337
366
|
}
|
|
367
|
+
/**
|
|
368
|
+
* Return an updated window function with the given rows frame.
|
|
369
|
+
* @param {(number|null)[] | import('./expression.js').ParamLike} expr The row-based window frame.
|
|
370
|
+
* @returns {WindowFunction} A new window function.
|
|
371
|
+
*/
|
|
338
372
|
rows(expr) {
|
|
339
373
|
const frame = windowFrame("ROWS", expr);
|
|
340
374
|
const { window: op, func, type, name, group, order } = this;
|
|
341
375
|
return new _WindowFunction(op, func, type, name, group, order, frame);
|
|
342
376
|
}
|
|
377
|
+
/**
|
|
378
|
+
* Return an updated window function with the given range frame.
|
|
379
|
+
* @param {(number|null)[] | import('./expression.js').ParamLike} expr The range-based window frame.
|
|
380
|
+
* @returns {WindowFunction} A new window function.
|
|
381
|
+
*/
|
|
343
382
|
range(expr) {
|
|
344
383
|
const frame = windowFrame("RANGE", expr);
|
|
345
384
|
const { window: op, func, type, name, group, order } = this;
|
|
@@ -383,11 +422,24 @@ function agg(strings, ...exprs) {
|
|
|
383
422
|
return sql(strings, ...exprs).annotate({ aggregate: true });
|
|
384
423
|
}
|
|
385
424
|
var AggregateFunction = class _AggregateFunction extends SQLExpression {
|
|
425
|
+
/**
|
|
426
|
+
* Create a new AggregateFunction instance.
|
|
427
|
+
* @param {*} op The aggregate operation.
|
|
428
|
+
* @param {*} [args] The aggregate function arguments.
|
|
429
|
+
* @param {*} [type] The SQL data type to cast to.
|
|
430
|
+
* @param {boolean} [isDistinct] Flag indicating if this is a distinct value aggregate.
|
|
431
|
+
* @param {*} [filter] Filtering expression to apply prior to aggregation.
|
|
432
|
+
*/
|
|
386
433
|
constructor(op, args, type, isDistinct2, filter) {
|
|
387
434
|
args = (args || []).map(asColumn);
|
|
388
435
|
const { strings, exprs } = aggExpr(op, args, type, isDistinct2, filter);
|
|
389
436
|
const { spans, cols } = parseSQL(strings, exprs);
|
|
390
|
-
super(spans, cols
|
|
437
|
+
super(spans, cols);
|
|
438
|
+
this.aggregate = op;
|
|
439
|
+
this.args = args;
|
|
440
|
+
this.type = type;
|
|
441
|
+
this.isDistinct = isDistinct2;
|
|
442
|
+
this.filter = filter;
|
|
391
443
|
}
|
|
392
444
|
get basis() {
|
|
393
445
|
return this.column;
|
|
@@ -398,30 +450,63 @@ var AggregateFunction = class _AggregateFunction extends SQLExpression {
|
|
|
398
450
|
const tail = args.length ? `(${dist}${args.map(unquoted).join(", ")})` : "";
|
|
399
451
|
return `${op.toLowerCase()}${tail}`;
|
|
400
452
|
}
|
|
453
|
+
/**
|
|
454
|
+
* Return a new derived aggregate function over distinct values.
|
|
455
|
+
* @returns {AggregateFunction} A new aggregate function.
|
|
456
|
+
*/
|
|
401
457
|
distinct() {
|
|
402
458
|
const { aggregate: op, args, type, filter } = this;
|
|
403
459
|
return new _AggregateFunction(op, args, type, true, filter);
|
|
404
460
|
}
|
|
461
|
+
/**
|
|
462
|
+
* Return a new derived aggregate function that filters values.
|
|
463
|
+
* @param {*} filter The filter expresion.
|
|
464
|
+
* @returns {AggregateFunction} A new aggregate function.
|
|
465
|
+
*/
|
|
405
466
|
where(filter) {
|
|
406
467
|
const { aggregate: op, args, type, isDistinct: isDistinct2 } = this;
|
|
407
468
|
return new _AggregateFunction(op, args, type, isDistinct2, filter);
|
|
408
469
|
}
|
|
470
|
+
/**
|
|
471
|
+
* Return a new window function over this aggregate.
|
|
472
|
+
* @returns {WindowFunction} A new aggregate function.
|
|
473
|
+
*/
|
|
409
474
|
window() {
|
|
410
475
|
const { aggregate: op, args, type, isDistinct: isDistinct2 } = this;
|
|
411
476
|
const func = new _AggregateFunction(op, args, null, isDistinct2);
|
|
412
477
|
return new WindowFunction(op, func, type);
|
|
413
478
|
}
|
|
479
|
+
/**
|
|
480
|
+
* Return a window function over this aggregate with the given partitioning.
|
|
481
|
+
* @param {*} expr The grouping (partition by) criteria for the window function.
|
|
482
|
+
* @returns {WindowFunction} A new window function.
|
|
483
|
+
*/
|
|
414
484
|
partitionby(...expr) {
|
|
415
485
|
return this.window().partitionby(...expr);
|
|
416
486
|
}
|
|
487
|
+
/**
|
|
488
|
+
* Return a window function over this aggregate with the given ordering.
|
|
489
|
+
* @param {*} expr The sorting (order by) criteria for the window function.
|
|
490
|
+
* @returns {WindowFunction} A new window function.
|
|
491
|
+
*/
|
|
417
492
|
orderby(...expr) {
|
|
418
493
|
return this.window().orderby(...expr);
|
|
419
494
|
}
|
|
420
|
-
|
|
421
|
-
|
|
495
|
+
/**
|
|
496
|
+
* Return a window function over this aggregate with the given row frame.
|
|
497
|
+
* @param {(number|null)[] | import('./expression.js').ParamLike} frame The row-based window frame.
|
|
498
|
+
* @returns {WindowFunction} A new window function.
|
|
499
|
+
*/
|
|
500
|
+
rows(frame) {
|
|
501
|
+
return this.window().rows(frame);
|
|
422
502
|
}
|
|
423
|
-
|
|
424
|
-
|
|
503
|
+
/**
|
|
504
|
+
* Return a window function over this aggregate with the given range frame.
|
|
505
|
+
* @param {(number|null)[] | import('./expression.js').ParamLike} frame The range-based window frame.
|
|
506
|
+
* @returns {WindowFunction} A new window function.
|
|
507
|
+
*/
|
|
508
|
+
range(frame) {
|
|
509
|
+
return this.window().range(frame);
|
|
425
510
|
}
|
|
426
511
|
};
|
|
427
512
|
function aggExpr(op, args, type, isDistinct2, filter) {
|
|
@@ -552,6 +637,15 @@ var Query = class _Query {
|
|
|
552
637
|
static except(...queries) {
|
|
553
638
|
return new SetOperation("EXCEPT", queries.flat());
|
|
554
639
|
}
|
|
640
|
+
static describe(query) {
|
|
641
|
+
const q = query.clone();
|
|
642
|
+
const { clone, toString } = q;
|
|
643
|
+
return Object.assign(q, {
|
|
644
|
+
describe: true,
|
|
645
|
+
clone: () => _Query.describe(clone.call(q)),
|
|
646
|
+
toString: () => `DESCRIBE ${toString.call(q)}`
|
|
647
|
+
});
|
|
648
|
+
}
|
|
555
649
|
constructor() {
|
|
556
650
|
this.query = {
|
|
557
651
|
with: [],
|
|
@@ -564,12 +658,22 @@ var Query = class _Query {
|
|
|
564
658
|
qualify: [],
|
|
565
659
|
orderby: []
|
|
566
660
|
};
|
|
661
|
+
this.cteFor = null;
|
|
567
662
|
}
|
|
568
663
|
clone() {
|
|
569
664
|
const q = new _Query();
|
|
570
665
|
q.query = { ...this.query };
|
|
571
666
|
return q;
|
|
572
667
|
}
|
|
668
|
+
/**
|
|
669
|
+
* Retrieve current WITH common table expressions (CTEs).
|
|
670
|
+
* @returns {any[]}
|
|
671
|
+
*/
|
|
672
|
+
/**
|
|
673
|
+
* Add WITH common table expressions (CTEs).
|
|
674
|
+
* @param {...any} expr Expressions to add.
|
|
675
|
+
* @returns {this}
|
|
676
|
+
*/
|
|
573
677
|
with(...expr) {
|
|
574
678
|
const { query } = this;
|
|
575
679
|
if (expr.length === 0) {
|
|
@@ -595,6 +699,15 @@ var Query = class _Query {
|
|
|
595
699
|
return this;
|
|
596
700
|
}
|
|
597
701
|
}
|
|
702
|
+
/**
|
|
703
|
+
* Retrieve current SELECT expressions.
|
|
704
|
+
* @returns {any[]}
|
|
705
|
+
*/
|
|
706
|
+
/**
|
|
707
|
+
* Add SELECT expressions.
|
|
708
|
+
* @param {...any} expr Expressions to add.
|
|
709
|
+
* @returns {this}
|
|
710
|
+
*/
|
|
598
711
|
select(...expr) {
|
|
599
712
|
const { query } = this;
|
|
600
713
|
if (expr.length === 0) {
|
|
@@ -627,6 +740,15 @@ var Query = class _Query {
|
|
|
627
740
|
this.query.distinct = !!value;
|
|
628
741
|
return this;
|
|
629
742
|
}
|
|
743
|
+
/**
|
|
744
|
+
* Retrieve current from expressions.
|
|
745
|
+
* @returns {any[]}
|
|
746
|
+
*/
|
|
747
|
+
/**
|
|
748
|
+
* Provide table from expressions.
|
|
749
|
+
* @param {...any} expr
|
|
750
|
+
* @returns {this}
|
|
751
|
+
*/
|
|
630
752
|
from(...expr) {
|
|
631
753
|
const { query } = this;
|
|
632
754
|
if (expr.length === 0) {
|
|
@@ -657,6 +779,16 @@ var Query = class _Query {
|
|
|
657
779
|
this.query.from = [];
|
|
658
780
|
return this.from(...expr);
|
|
659
781
|
}
|
|
782
|
+
/**
|
|
783
|
+
* Retrieve current SAMPLE settings.
|
|
784
|
+
* @returns {any[]}
|
|
785
|
+
*/
|
|
786
|
+
/**
|
|
787
|
+
* Set SAMPLE settings.
|
|
788
|
+
* @param {number|object} value The percentage or number of rows to sample.
|
|
789
|
+
* @param {string} [method] The sampling method to use.
|
|
790
|
+
* @returns {this}
|
|
791
|
+
*/
|
|
660
792
|
sample(value, method) {
|
|
661
793
|
const { query } = this;
|
|
662
794
|
if (arguments.length === 0) {
|
|
@@ -670,6 +802,15 @@ var Query = class _Query {
|
|
|
670
802
|
return this;
|
|
671
803
|
}
|
|
672
804
|
}
|
|
805
|
+
/**
|
|
806
|
+
* Retrieve current WHERE expressions.
|
|
807
|
+
* @returns {any[]}
|
|
808
|
+
*/
|
|
809
|
+
/**
|
|
810
|
+
* Add WHERE expressions.
|
|
811
|
+
* @param {...any} expr Expressions to add.
|
|
812
|
+
* @returns {this}
|
|
813
|
+
*/
|
|
673
814
|
where(...expr) {
|
|
674
815
|
const { query } = this;
|
|
675
816
|
if (expr.length === 0) {
|
|
@@ -685,6 +826,15 @@ var Query = class _Query {
|
|
|
685
826
|
this.query.where = [];
|
|
686
827
|
return this.where(...expr);
|
|
687
828
|
}
|
|
829
|
+
/**
|
|
830
|
+
* Retrieve current GROUP BY expressions.
|
|
831
|
+
* @returns {any[]}
|
|
832
|
+
*/
|
|
833
|
+
/**
|
|
834
|
+
* Add GROUP BY expressions.
|
|
835
|
+
* @param {...any} expr Expressions to add.
|
|
836
|
+
* @returns {this}
|
|
837
|
+
*/
|
|
688
838
|
groupby(...expr) {
|
|
689
839
|
const { query } = this;
|
|
690
840
|
if (expr.length === 0) {
|
|
@@ -700,6 +850,15 @@ var Query = class _Query {
|
|
|
700
850
|
this.query.groupby = [];
|
|
701
851
|
return this.groupby(...expr);
|
|
702
852
|
}
|
|
853
|
+
/**
|
|
854
|
+
* Retrieve current HAVING expressions.
|
|
855
|
+
* @returns {any[]}
|
|
856
|
+
*/
|
|
857
|
+
/**
|
|
858
|
+
* Add HAVING expressions.
|
|
859
|
+
* @param {...any} expr Expressions to add.
|
|
860
|
+
* @returns {this}
|
|
861
|
+
*/
|
|
703
862
|
having(...expr) {
|
|
704
863
|
const { query } = this;
|
|
705
864
|
if (expr.length === 0) {
|
|
@@ -711,6 +870,15 @@ var Query = class _Query {
|
|
|
711
870
|
return this;
|
|
712
871
|
}
|
|
713
872
|
}
|
|
873
|
+
/**
|
|
874
|
+
* Retrieve current WINDOW definitions.
|
|
875
|
+
* @returns {any[]}
|
|
876
|
+
*/
|
|
877
|
+
/**
|
|
878
|
+
* Add WINDOW definitions.
|
|
879
|
+
* @param {...any} expr Expressions to add.
|
|
880
|
+
* @returns {this}
|
|
881
|
+
*/
|
|
714
882
|
window(...expr) {
|
|
715
883
|
const { query } = this;
|
|
716
884
|
if (expr.length === 0) {
|
|
@@ -729,6 +897,15 @@ var Query = class _Query {
|
|
|
729
897
|
return this;
|
|
730
898
|
}
|
|
731
899
|
}
|
|
900
|
+
/**
|
|
901
|
+
* Retrieve current QUALIFY expressions.
|
|
902
|
+
* @returns {any[]}
|
|
903
|
+
*/
|
|
904
|
+
/**
|
|
905
|
+
* Add QUALIFY expressions.
|
|
906
|
+
* @param {...any} expr Expressions to add.
|
|
907
|
+
* @returns {this}
|
|
908
|
+
*/
|
|
732
909
|
qualify(...expr) {
|
|
733
910
|
const { query } = this;
|
|
734
911
|
if (expr.length === 0) {
|
|
@@ -740,6 +917,15 @@ var Query = class _Query {
|
|
|
740
917
|
return this;
|
|
741
918
|
}
|
|
742
919
|
}
|
|
920
|
+
/**
|
|
921
|
+
* Retrieve current ORDER BY expressions.
|
|
922
|
+
* @returns {any[]}
|
|
923
|
+
*/
|
|
924
|
+
/**
|
|
925
|
+
* Add ORDER BY expressions.
|
|
926
|
+
* @param {...any} expr Expressions to add.
|
|
927
|
+
* @returns {this}
|
|
928
|
+
*/
|
|
743
929
|
orderby(...expr) {
|
|
744
930
|
const { query } = this;
|
|
745
931
|
if (expr.length === 0) {
|
|
@@ -751,6 +937,15 @@ var Query = class _Query {
|
|
|
751
937
|
return this;
|
|
752
938
|
}
|
|
753
939
|
}
|
|
940
|
+
/**
|
|
941
|
+
* Retrieve current LIMIT value.
|
|
942
|
+
* @returns {number|null}
|
|
943
|
+
*/
|
|
944
|
+
/**
|
|
945
|
+
* Set the query result LIMIT.
|
|
946
|
+
* @param {number} value The limit value.
|
|
947
|
+
* @returns {this}
|
|
948
|
+
*/
|
|
754
949
|
limit(value) {
|
|
755
950
|
const { query } = this;
|
|
756
951
|
if (arguments.length === 0) {
|
|
@@ -760,6 +955,15 @@ var Query = class _Query {
|
|
|
760
955
|
return this;
|
|
761
956
|
}
|
|
762
957
|
}
|
|
958
|
+
/**
|
|
959
|
+
* Retrieve current OFFSET value.
|
|
960
|
+
* @returns {number|null}
|
|
961
|
+
*/
|
|
962
|
+
/**
|
|
963
|
+
* Set the query result OFFSET.
|
|
964
|
+
* @param {number} value The offset value.
|
|
965
|
+
* @returns {this}
|
|
966
|
+
*/
|
|
763
967
|
offset(value) {
|
|
764
968
|
const { query } = this;
|
|
765
969
|
if (arguments.length === 0) {
|
|
@@ -786,6 +990,7 @@ var Query = class _Query {
|
|
|
786
990
|
}
|
|
787
991
|
toString() {
|
|
788
992
|
const {
|
|
993
|
+
with: cte,
|
|
789
994
|
select,
|
|
790
995
|
distinct,
|
|
791
996
|
from,
|
|
@@ -797,8 +1002,7 @@ var Query = class _Query {
|
|
|
797
1002
|
qualify,
|
|
798
1003
|
orderby,
|
|
799
1004
|
limit,
|
|
800
|
-
offset
|
|
801
|
-
with: cte
|
|
1005
|
+
offset
|
|
802
1006
|
} = this.query;
|
|
803
1007
|
const sql2 = [];
|
|
804
1008
|
if (cte.length) {
|
|
@@ -818,8 +1022,7 @@ var Query = class _Query {
|
|
|
818
1022
|
}
|
|
819
1023
|
if (where.length) {
|
|
820
1024
|
const clauses = where.map(String).filter((x2) => x2).join(" AND ");
|
|
821
|
-
if (clauses)
|
|
822
|
-
sql2.push(`WHERE ${clauses}`);
|
|
1025
|
+
if (clauses) sql2.push(`WHERE ${clauses}`);
|
|
823
1026
|
}
|
|
824
1027
|
if (sample) {
|
|
825
1028
|
const { rows, perc, method, seed } = sample;
|
|
@@ -832,8 +1035,7 @@ var Query = class _Query {
|
|
|
832
1035
|
}
|
|
833
1036
|
if (having.length) {
|
|
834
1037
|
const clauses = having.map(String).filter((x2) => x2).join(" AND ");
|
|
835
|
-
if (clauses)
|
|
836
|
-
sql2.push(`HAVING ${clauses}`);
|
|
1038
|
+
if (clauses) sql2.push(`HAVING ${clauses}`);
|
|
837
1039
|
}
|
|
838
1040
|
if (window.length) {
|
|
839
1041
|
const windows = window.map(({ as, expr }) => `"${as}" AS (${expr})`);
|
|
@@ -841,8 +1043,7 @@ var Query = class _Query {
|
|
|
841
1043
|
}
|
|
842
1044
|
if (qualify.length) {
|
|
843
1045
|
const clauses = qualify.map(String).filter((x2) => x2).join(" AND ");
|
|
844
|
-
if (clauses)
|
|
845
|
-
sql2.push(`QUALIFY ${clauses}`);
|
|
1046
|
+
if (clauses) sql2.push(`QUALIFY ${clauses}`);
|
|
846
1047
|
}
|
|
847
1048
|
if (orderby.length) {
|
|
848
1049
|
sql2.push(`ORDER BY ${orderby.join(", ")}`);
|
|
@@ -861,6 +1062,7 @@ var SetOperation = class _SetOperation {
|
|
|
861
1062
|
this.op = op;
|
|
862
1063
|
this.queries = queries.map((q) => q.clone());
|
|
863
1064
|
this.query = { orderby: [] };
|
|
1065
|
+
this.cteFor = null;
|
|
864
1066
|
}
|
|
865
1067
|
clone() {
|
|
866
1068
|
const q = new _SetOperation(this.op, this.queries);
|
|
@@ -898,8 +1100,7 @@ var SetOperation = class _SetOperation {
|
|
|
898
1100
|
}
|
|
899
1101
|
get subqueries() {
|
|
900
1102
|
const { queries, cteFor } = this;
|
|
901
|
-
if (cteFor)
|
|
902
|
-
queries.forEach((q) => q.cteFor = cteFor);
|
|
1103
|
+
if (cteFor) queries.forEach((q) => q.cteFor = cteFor);
|
|
903
1104
|
return queries;
|
|
904
1105
|
}
|
|
905
1106
|
toString() {
|
|
@@ -920,6 +1121,9 @@ var SetOperation = class _SetOperation {
|
|
|
920
1121
|
function isQuery(value) {
|
|
921
1122
|
return value instanceof Query || value instanceof SetOperation;
|
|
922
1123
|
}
|
|
1124
|
+
function isDescribeQuery(value) {
|
|
1125
|
+
return isQuery(value) && value.describe;
|
|
1126
|
+
}
|
|
923
1127
|
function unquote(s) {
|
|
924
1128
|
return isDoubleQuoted(s) ? s.slice(1, -1) : s;
|
|
925
1129
|
}
|
|
@@ -937,7 +1141,7 @@ function scaleLinear() {
|
|
|
937
1141
|
sqlInvert: identity
|
|
938
1142
|
};
|
|
939
1143
|
}
|
|
940
|
-
function scaleLog({ base } = {}) {
|
|
1144
|
+
function scaleLog({ base = null } = {}) {
|
|
941
1145
|
if (base == null || base === Math.E) {
|
|
942
1146
|
return {
|
|
943
1147
|
apply: Math.log,
|
|
@@ -1068,7 +1272,7 @@ function loadSpatial(tableName, fileName, options = {}) {
|
|
|
1068
1272
|
const { options: opt, ...rest } = options;
|
|
1069
1273
|
if (opt) {
|
|
1070
1274
|
const open = Array.isArray(opt) ? opt.join(", ") : typeof opt === "string" ? opt : Object.entries(opt).map(([key, value]) => `${key}=${value}`).join(", ");
|
|
1071
|
-
rest
|
|
1275
|
+
Object.assign(rest, { open_options: open.toUpperCase() });
|
|
1072
1276
|
}
|
|
1073
1277
|
return load("st_read", tableName, fileName, rest);
|
|
1074
1278
|
}
|
|
@@ -1139,6 +1343,7 @@ export {
|
|
|
1139
1343
|
gt,
|
|
1140
1344
|
gte,
|
|
1141
1345
|
isBetween,
|
|
1346
|
+
isDescribeQuery,
|
|
1142
1347
|
isDistinct,
|
|
1143
1348
|
isFinite,
|
|
1144
1349
|
isInfinite,
|
package/dist/mosaic-sql.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var N=class{constructor(t,e){t&&(this.table=String(t)),e&&(this.column=e)}get columns(){return this.column?[this.column]:[]}toString(){let{table:t,column:e}=this;if(e){let n=e.startsWith("*")?e:`"${e}"`;return`${t?`${V(t)}.`:""}${n}`}else return t?V(t):"NULL"}};function V(r){return r.split(".").map(e=>`"${e}"`).join(".")}function k(r,t){return r instanceof N&&r.column===t}function u(r){return typeof r=="string"?K(r):r}function O(r){return typeof r=="string"?H(r):r}function H(r){return new N(r)}function K(r,t){return arguments.length===1&&(t=r,r=null),new N(r,t)}function ut(r){return new N(r,"*")}function lt(r){return typeof r=="string"?`"${r}"`:$(r)}function $(r){switch(typeof r){case"boolean":return r?"TRUE":"FALSE";case"string":return`'${r}'`;case"number":return Number.isFinite(r)?String(r):"NULL";default:if(r==null)return"NULL";if(r instanceof Date){let t=+r;if(Number.isNaN(t))return"NULL";let e=r.getUTCFullYear(),n=r.getUTCMonth(),o=r.getUTCDate();return t===Date.UTC(e,n,o)?`MAKE_DATE(${e}, ${n+1}, ${o})`:`EPOCH_MS(${t})`}else return r instanceof RegExp?`'${r.source}'`:String(r)}}var T=r=>typeof r?.addEventListener=="function";function M(r){return r instanceof S}var S=class{constructor(t,e,n){this._expr=Array.isArray(t)?t:[t],this._deps=e||[],this.annotate(n);let o=this._expr.filter(s=>T(s));o.length>0?(this._params=Array.from(new Set(o)),this._params.forEach(s=>{s.addEventListener("value",()=>pt(this,this.map?.get("value")))})):this.addEventListener=void 0}get value(){return this}get columns(){let{_params:t,_deps:e}=this;if(t){let n=new Set(t.flatMap(o=>{let s=o.value?.columns;return Array.isArray(s)?s:[]}));if(n.size){let o=new Set(e);return n.forEach(s=>o.add(s)),Array.from(o)}}return e}get column(){return this._deps.length?this._deps[0]:this.columns[0]}annotate(...t){return Object.assign(this,...t)}toString(){return this._expr.map(t=>T(t)&&!M(t)?$(t.value):t).join("")}addEventListener(t,e){let n=this.map||(this.map=new Map);(n.get(t)||(n.set(t,new Set),n.get(t))).add(e)}};function pt(r,t){if(t?.size)return Promise.allSettled(Array.from(t,e=>e(r)))}function W(r,t){let e=[r[0]],n=new Set,o=t.length;for(let s=0,i=0;s<o;){let a=t[s];T(a)?e[++i]=a:(Array.isArray(a?.columns)&&a.columns.forEach(d=>n.add(d)),e[i]+=typeof a=="string"?a:$(a));let p=r[++s];T(e[i])?e[++i]=p:e[i]+=p}return{spans:e,cols:Array.from(n)}}function c(r,...t){let{spans:e,cols:n}=W(r,t);return new S(e,n)}function ft(r){let t=u(r);return c`${t} DESC NULLS LAST`.annotate({label:t?.label,desc:!0})}var ht=r=>({value:r,toString:()=>$(r)});function D(r){r(this.op,this),this.children?.forEach(t=>t.visit(r))}function z(r,t){let e=t.filter(o=>o!=null).map(u),n=e.map((o,s)=>s?` ${r} `:"");return e.length===1?n.push(""):e.length>1&&(n[0]="(",n.push(")")),c(n,...e).annotate({op:r,children:e,visit:D})}var mt=(...r)=>z("AND",r.flat()),gt=(...r)=>z("OR",r.flat()),dt=r=>t=>c`(${r} ${u(t)})`.annotate({op:r,a:t,visit:D}),xt=dt("NOT"),J=r=>t=>c`(${u(t)} ${r})`.annotate({op:r,a:t,visit:D}),$t=J("IS NULL"),Et=J("IS NOT NULL"),w=r=>(t,e)=>c`(${u(t)} ${r} ${u(e)})`.annotate({op:r,a:t,b:e,visit:D}),yt=w("="),Nt=w("<>"),St=w("<"),wt=w(">"),At=w("<="),Tt=w(">="),Rt=w("IS DISTINCT FROM"),qt=w("IS NOT DISTINCT FROM");function Z(r,t,e,n){t=u(t);let o=r.startsWith("NOT ")?"NOT ":"";return(e?n?c`${o}(${e[0]} <= ${t} AND ${t} < ${e[1]})`:c`(${t} ${r} ${e[0]} AND ${e[1]})`:c``).annotate({op:r,visit:D,field:t,range:e})}var bt=(r,t,e)=>Z("BETWEEN",r,t,e),It=(r,t,e)=>Z("NOT BETWEEN",r,t,e);function R(r,t){return Array.from({length:r},()=>t)}function m(r,t){return(...e)=>{let n=e.map(u),o=t?`::${t}`:"";return(n.length?c([`${r}(`,...R(n.length-1,", "),`)${o}`],...n):c`${r}()${o}`).annotate({func:r,args:n})}}var Lt=m("REGEXP_MATCHES"),Ot=m("CONTAINS"),Dt=m("PREFIX"),_t=m("SUFFIX"),Mt=m("LOWER"),Ct=m("UPPER"),Pt=m("LENGTH"),Ft=m("ISNAN"),Gt=m("ISFINITE"),Ut=m("ISINF");var _=class r extends S{constructor(t,e,n,o,s="",i="",a=""){let p;if(o&&!(s||i||a))p=o?c`${e} OVER "${o}"`:c`${e} OVER ()`;else{let b=s&&i?" ":"",I=(s||i)&&a?" ":"";p=c`${e} OVER (${o?`"${o}" `:""}${s}${b}${i}${I}${a})`}n&&(p=c`(${p})::${n}`);let{_expr:y,_deps:A}=p;super(y,A,{window:t,func:e,type:n,name:o,group:s,order:i,frame:a})}get basis(){return this.column}get label(){let{func:t}=this;return t.label??t.toString()}over(t){let{window:e,func:n,type:o,group:s,order:i,frame:a}=this;return new r(e,n,o,t,s,i,a)}partitionby(...t){let e=t.flat().filter(y=>y).map(u),n=c(["PARTITION BY ",R(e.length-1,", "),""],...e),{window:o,func:s,type:i,name:a,order:p,frame:d}=this;return new r(o,s,i,a,n,p,d)}orderby(...t){let e=t.flat().filter(y=>y).map(u),n=c(["ORDER BY ",R(e.length-1,", "),""],...e),{window:o,func:s,type:i,name:a,group:p,frame:d}=this;return new r(o,s,i,a,p,n,d)}rows(t){let e=tt("ROWS",t),{window:n,func:o,type:s,name:i,group:a,order:p}=this;return new r(n,o,s,i,a,p,e)}range(t){let e=tt("RANGE",t),{window:n,func:o,type:s,name:i,group:a,order:p}=this;return new r(n,o,s,i,a,p,e)}};function tt(r,t){if(T(t)){let e=c`${t}`;return e.toString=()=>`${r} ${et(t.value)}`,e}return`${r} ${et(t)}`}function et(r){let[t,e]=r,n=t===0?"CURRENT ROW":Number.isFinite(t)?`${Math.abs(t)} PRECEDING`:"UNBOUNDED PRECEDING",o=e===0?"CURRENT ROW":Number.isFinite(e)?`${Math.abs(e)} FOLLOWING`:"UNBOUNDED FOLLOWING";return`BETWEEN ${n} AND ${o}`}function E(r,t){return(...e)=>{let n=m(r)(...e);return new _(r,n,t)}}var jt=E("ROW_NUMBER","INTEGER"),Wt=E("RANK","INTEGER"),Yt=E("DENSE_RANK","INTEGER"),vt=E("PERCENT_RANK"),Bt=E("CUME_DIST"),Xt=E("NTILE"),Qt=E("LAG"),Vt=E("LEAD"),kt=E("FIRST_VALUE"),Ht=E("LAST_VALUE"),Kt=E("NTH_VALUE");function zt(r,...t){return c(r,...t).annotate({aggregate:!0})}var Y=class r extends S{constructor(t,e,n,o,s){e=(e||[]).map(u);let{strings:i,exprs:a}=Jt(t,e,n,o,s),{spans:p,cols:d}=W(i,a);super(p,d,{aggregate:t,args:e,type:n,isDistinct:o,filter:s})}get basis(){return this.column}get label(){let{aggregate:t,args:e,isDistinct:n}=this,o=n?"DISTINCT"+(e.length?" ":""):"",s=e.length?`(${o}${e.map(Zt).join(", ")})`:"";return`${t.toLowerCase()}${s}`}distinct(){let{aggregate:t,args:e,type:n,filter:o}=this;return new r(t,e,n,!0,o)}where(t){let{aggregate:e,args:n,type:o,isDistinct:s}=this;return new r(e,n,o,s,t)}window(){let{aggregate:t,args:e,type:n,isDistinct:o}=this,s=new r(t,e,null,o);return new _(t,s,n)}partitionby(...t){return this.window().partitionby(...t)}orderby(...t){return this.window().orderby(...t)}rows(t,e){return this.window().rows(t,e)}range(t,e){return this.window().range(t,e)}};function Jt(r,t,e,n,o){let s=`)${e?`::${e}`:""}`,i=[`${r}(${n?"DISTINCT ":""}`],a=[];return t.length?(i=i.concat([...R(t.length-1,", "),`${s}${o?" FILTER (WHERE ":""}`,...o?[")"]:[]]),a=[...t,...o?[o]:[]]):i[0]+="*"+s,{exprs:a,strings:i}}function Zt(r){let t=$(r);return t&&t.startsWith('"')&&t.endsWith('"')?t.slice(1,-1):t}function l(r,t){return(...e)=>new Y(r,e,t)}var te=l("COUNT","INTEGER"),ee=l("AVG"),re=l("AVG"),ne=l("MAD"),oe=l("MAX"),se=l("MIN"),ie=l("SUM","DOUBLE"),ce=l("PRODUCT"),ae=l("MEDIAN"),ue=l("QUANTILE"),le=l("MODE"),pe=l("VARIANCE"),fe=l("STDDEV"),he=l("SKEWNESS"),me=l("KURTOSIS"),ge=l("ENTROPY"),de=l("VAR_POP"),xe=l("STDDEV_POP"),$e=l("CORR"),Ee=l("COVAR_POP"),ye=l("REGR_INTERCEPT"),Ne=l("REGR_SLOPE"),Se=l("REGR_COUNT"),we=l("REGR_R2"),Ae=l("REGR_SYY"),Te=l("REGR_SXX"),Re=l("REGR_SXY"),qe=l("REGR_AVGX"),be=l("REGR_AVGY"),Ie=l("FIRST"),Le=l("LAST"),Oe=l("ARG_MIN"),De=l("ARG_MAX"),_e=l("STRING_AGG"),Me=l("ARRAY_AGG");function v(r,t){let e=u(r),n=c`CAST(${e} AS ${t})`;return Object.defineProperty(n,"label",{enumerable:!0,get(){return r.label}}),Object.defineProperty(n,"aggregate",{enumerable:!0,get(){return r.aggregate||!1}}),n}var Ce=r=>v(r,"DOUBLE"),Pe=r=>v(r,"INTEGER");var B=r=>c`epoch_ms(${u(r)})`,Fe=r=>{let t=u(r);return c`MAKE_DATE(2012, MONTH(${t}), 1)`.annotate({label:"month"})},Ge=r=>{let t=u(r);return c`MAKE_DATE(2012, MONTH(${t}), DAY(${t}))`.annotate({label:"date"})},Ue=r=>{let t=u(r);return c`MAKE_DATE(2012, 1, DAY(${t}))`.annotate({label:"date"})};var je=m("ST_AsGeoJSON"),rt=m("ST_X"),nt=m("ST_Y"),X=m("ST_CENTROID"),We=r=>rt(X(r)),Ye=r=>nt(X(r));var F=class r{static select(...t){return new r().select(...t)}static from(...t){return new r().from(...t)}static with(...t){return new r().with(...t)}static union(...t){return new q("UNION",t.flat())}static unionAll(...t){return new q("UNION ALL",t.flat())}static intersect(...t){return new q("INTERSECT",t.flat())}static except(...t){return new q("EXCEPT",t.flat())}constructor(){this.query={with:[],select:[],from:[],where:[],groupby:[],having:[],window:[],qualify:[],orderby:[]}}clone(){let t=new r;return t.query={...this.query},t}with(...t){let{query:e}=this;if(t.length===0)return e.with;{let n=[],o=(s,i)=>{let a=i.clone();a.cteFor=this,n.push({as:s,query:a})};return t.flat().forEach(s=>{if(s!=null)if(s.as&&s.query)o(s.as,s.query);else for(let i in s)o(i,s[i])}),e.with=e.with.concat(n),this}}select(...t){let{query:e}=this;if(t.length===0)return e.select;{let n=[];for(let o of t.flat())if(o!=null)if(typeof o=="string")n.push({as:o,expr:u(o)});else if(o instanceof N)n.push({as:o.column,expr:o});else if(Array.isArray(o))n.push({as:o[0],expr:o[1]});else for(let s in o)n.push({as:C(s),expr:u(o[s])});return e.select=e.select.concat(n),this}}$select(...t){return this.query.select=[],this.select(...t)}distinct(t=!0){return this.query.distinct=!!t,this}from(...t){let{query:e}=this;if(t.length===0)return e.from;{let n=[];return t.flat().forEach(o=>{if(o!=null)if(typeof o=="string")n.push({as:o,from:O(o)});else if(o instanceof N)n.push({as:o.table,from:o});else if(P(o)||M(o))n.push({from:o});else if(Array.isArray(o))n.push({as:C(o[0]),from:O(o[1])});else for(let s in o)n.push({as:C(s),from:O(o[s])})}),e.from=e.from.concat(n),this}}$from(...t){return this.query.from=[],this.from(...t)}sample(t,e){let{query:n}=this;if(arguments.length===0)return n.sample;{let o=t;return typeof t=="number"&&(o=t>0&&t<1?{perc:100*t,method:e}:{rows:Math.round(t),method:e}),n.sample=o,this}}where(...t){let{query:e}=this;return t.length===0?e.where:(e.where=e.where.concat(t.flat().filter(n=>n)),this)}$where(...t){return this.query.where=[],this.where(...t)}groupby(...t){let{query:e}=this;return t.length===0?e.groupby:(e.groupby=e.groupby.concat(t.flat().filter(n=>n).map(u)),this)}$groupby(...t){return this.query.groupby=[],this.groupby(...t)}having(...t){let{query:e}=this;return t.length===0?e.having:(e.having=e.having.concat(t.flat().filter(n=>n)),this)}window(...t){let{query:e}=this;if(t.length===0)return e.window;{let n=[];return t.flat().forEach(o=>{if(o!=null)for(let s in o)n.push({as:C(s),expr:o[s]})}),e.window=e.window.concat(n),this}}qualify(...t){let{query:e}=this;return t.length===0?e.qualify:(e.qualify=e.qualify.concat(t.flat().filter(n=>n)),this)}orderby(...t){let{query:e}=this;return t.length===0?e.orderby:(e.orderby=e.orderby.concat(t.flat().filter(n=>n).map(u)),this)}limit(t){let{query:e}=this;return arguments.length===0?e.limit:(e.limit=Number.isFinite(t)?t:void 0,this)}offset(t){let{query:e}=this;return arguments.length===0?e.offset:(e.offset=Number.isFinite(t)?t:void 0,this)}get subqueries(){let{query:t,cteFor:e}=this,o=(e?.query||t).with?.reduce((i,{as:a,query:p})=>(i[a]=p,i),{}),s=[];return t.from.forEach(({from:i})=>{if(P(i))s.push(i);else if(o[i.table]){let a=o[i.table];s.push(a)}}),s}toString(){let{select:t,distinct:e,from:n,sample:o,where:s,groupby:i,having:a,window:p,qualify:d,orderby:y,limit:A,offset:b,with:I}=this.query,g=[];if(I.length){let f=I.map(({as:h,query:x})=>`"${h}" AS (${x})`);g.push(`WITH ${f.join(", ")}`)}let it=t.map(({as:f,expr:h})=>k(h,f)&&!h.table?`${h}`:`${h} AS "${f}"`);if(g.push(`SELECT${e?" DISTINCT":""} ${it.join(", ")}`),n.length){let f=n.map(({as:h,from:x})=>{let L=P(x)?`(${x})`:`${x}`;return!h||h===x.table?L:`${L} AS "${h}"`});g.push(`FROM ${f.join(", ")}`)}if(s.length){let f=s.map(String).filter(h=>h).join(" AND ");f&&g.push(`WHERE ${f}`)}if(o){let{rows:f,perc:h,method:x,seed:L}=o,ct=f?`${f} ROWS`:`${h} PERCENT`,at=x?` (${x}${L!=null?`, ${L}`:""})`:"";g.push(`USING SAMPLE ${ct}${at}`)}if(i.length&&g.push(`GROUP BY ${i.join(", ")}`),a.length){let f=a.map(String).filter(h=>h).join(" AND ");f&&g.push(`HAVING ${f}`)}if(p.length){let f=p.map(({as:h,expr:x})=>`"${h}" AS (${x})`);g.push(`WINDOW ${f.join(", ")}`)}if(d.length){let f=d.map(String).filter(h=>h).join(" AND ");f&&g.push(`QUALIFY ${f}`)}return y.length&&g.push(`ORDER BY ${y.join(", ")}`),Number.isFinite(A)&&g.push(`LIMIT ${A}`),Number.isFinite(b)&&g.push(`OFFSET ${b}`),g.join(" ")}},q=class r{constructor(t,e){this.op=t,this.queries=e.map(n=>n.clone()),this.query={orderby:[]}}clone(){let t=new r(this.op,this.queries);return t.query={...this.query},t}orderby(...t){let{query:e}=this;return t.length===0?e.orderby:(e.orderby=e.orderby.concat(t.flat().filter(n=>n).map(u)),this)}limit(t){let{query:e}=this;return arguments.length===0?e.limit:(e.limit=Number.isFinite(t)?t:void 0,this)}offset(t){let{query:e}=this;return arguments.length===0?e.offset:(e.offset=Number.isFinite(t)?t:void 0,this)}get subqueries(){let{queries:t,cteFor:e}=this;return e&&t.forEach(n=>n.cteFor=e),t}toString(){let{op:t,queries:e,query:{orderby:n,limit:o,offset:s}}=this,i=[e.join(` ${t} `)];return n.length&&i.push(`ORDER BY ${n.join(", ")}`),Number.isFinite(o)&&i.push(`LIMIT ${o}`),Number.isFinite(s)&&i.push(`OFFSET ${s}`),i.join(" ")}};function P(r){return r instanceof F||r instanceof q}function C(r){return ve(r)?r.slice(1,-1):r}function ve(r){return r[0]==='"'&&r[r.length-1]==='"'}var G=r=>r;function Be(){return{apply:G,invert:G,sqlApply:u,sqlInvert:G}}function Xe({base:r}={}){if(r==null||r===Math.E)return{apply:Math.log,invert:Math.exp,sqlApply:t=>c`LN(${u(t)})`,sqlInvert:t=>c`EXP(${t})`};if(r===10)return{apply:Math.log10,invert:t=>Math.pow(10,t),sqlApply:t=>c`LOG(${u(t)})`,sqlInvert:t=>c`POW(10, ${t})`};{let t=+r;return{apply:e=>Math.log(e)/Math.log(t),invert:e=>Math.pow(t,e),sqlApply:e=>c`LN(${u(e)}) / LN(${t})`,sqlInvert:e=>c`POW(${t}, ${e})`}}}function Qe({constant:r=1}={}){let t=+r;return{apply:e=>Math.sign(e)*Math.log1p(Math.abs(e)),invert:e=>Math.sign(e)*Math.exp(Math.abs(e)-t),sqlApply:e=>(e=u(e),c`SIGN(${e}) * LN(${t} + ABS(${e}))`),sqlInvert:e=>c`SIGN(${e}) * (EXP(ABS(${e})) - ${t})`}}function Ve(){return{apply:r=>Math.sign(r)*Math.sqrt(Math.abs(r)),invert:r=>Math.sign(r)*r*r,sqlApply:r=>(r=u(r),c`SIGN(${r}) * SQRT(ABS(${r}))`),sqlInvert:r=>c`SIGN(${r}) * (${r}) ** 2`}}function ke({exponent:r=1}={}){let t=+r;return{apply:e=>Math.sign(e)*Math.pow(Math.abs(e),t),invert:e=>Math.sign(e)*Math.pow(Math.abs(e),1/t),sqlApply:e=>(e=u(e),c`SIGN(${e}) * POW(ABS(${e}), ${t})`),sqlInvert:e=>c`SIGN(${e}) * POW(ABS(${e}), 1/${t})`}}function ot(){return{apply:r=>+r,invert:r=>new Date(r),sqlApply:r=>r instanceof Date?+r:B(u(r)),sqlInvert:G}}var He={linear:Be,log:Xe,symlog:Qe,sqrt:Ve,pow:ke,time:ot,utc:ot};function Ke(r){let t=He[r.type];return t?{...r,...t(r)}:null}function U(r,t,{replace:e=!1,temp:n=!0,view:o=!1}={}){return"CREATE"+(e?" OR REPLACE ":" ")+(n?"TEMP ":"")+(o?"VIEW":"TABLE")+(e?" ":" IF NOT EXISTS ")+r+" AS "+t}function ze(r){return`INSTALL ${r}; LOAD ${r}`}function st(r,{columns:t=Object.keys(r?.[0]||{})}={}){let e=[];if(Array.isArray(t)?(e=t,t=e.reduce((o,s)=>(o[s]=s,o),{})):t&&(e=Object.keys(t)),!e.length)throw new Error("Can not create table from empty column set.");let n=[];for(let o of r){let s=e.map(i=>`${$(o[i])} AS "${t[i]}"`);n.push(`(SELECT ${s.join(", ")})`)}return n.join(" UNION ALL ")}function j(r,t,e,n={},o={}){let{select:s=["*"],where:i,view:a,temp:p,replace:d,...y}=n,A=nr({...o,...y}),b=`${r}('${e}'${A?", "+A:""})`,I=i?` WHERE ${i}`:"",g=`SELECT ${s.join(", ")} FROM ${b}${I}`;return U(t,g,{view:a,temp:p,replace:d})}function Je(r,t,e){return j("read_csv",r,t,e,{auto_detect:!0,sample_size:-1})}function Ze(r,t,e){return j("read_json",r,t,e,{auto_detect:!0,json_format:"auto"})}function tr(r,t,e){return j("read_parquet",r,t,e)}function er(r,t,e={}){let{options:n,...o}=e;if(n){let s=Array.isArray(n)?n.join(", "):typeof n=="string"?n:Object.entries(n).map(([i,a])=>`${i}=${a}`).join(", ");o.open_options=s.toUpperCase()}return j("st_read",r,t,o)}function rr(r,t,e={}){let{select:n=["*"],...o}=e,s=st(t),i=n.length===1&&n[0]==="*"?s:`SELECT ${n} FROM ${s}`;return U(r,i,o)}function nr(r){return Object.entries(r).map(([t,e])=>`${t}=${Q(e)}`).join(", ")}function Q(r){switch(typeof r){case"boolean":return String(r);case"string":return`'${r}'`;case"undefined":case"object":return r==null?"NULL":Array.isArray(r)?"["+r.map(t=>Q(t)).join(", ")+"]":"{"+Object.entries(r).map(([t,e])=>`'${t}': ${Q(e)}`).join(", ")+"}";default:return r}}export{F as Query,N as Ref,zt as agg,ut as all,mt as and,De as argmax,Oe as argmin,Me as arrayAgg,u as asColumn,O as asRelation,ee as avg,v as cast,Ce as castDouble,Pe as castInteger,X as centroid,We as centroidX,Ye as centroidY,K as column,Ot as contains,$e as corr,te as count,Ee as covarPop,U as create,Bt as cume_dist,Ue as dateDay,Fe as dateMonth,Ge as dateMonthDay,Yt as dense_rank,ft as desc,ge as entropy,B as epoch_ms,yt as eq,Ie as first,kt as first_value,je as geojson,wt as gt,Tt as gte,bt as isBetween,Rt as isDistinct,Gt as isFinite,Ut as isInfinite,Ft as isNaN,It as isNotBetween,qt as isNotDistinct,Et as isNotNull,$t as isNull,T as isParamLike,P as isQuery,M as isSQLExpression,me as kurtosis,Qt as lag,Le as last,Ht as last_value,Vt as lead,Pt as length,ht as literal,$ as literalToSQL,Je as loadCSV,ze as loadExtension,Ze as loadJSON,rr as loadObjects,tr as loadParquet,er as loadSpatial,Mt as lower,St as lt,At as lte,ne as mad,oe as max,re as mean,ae as median,se as min,le as mode,Nt as neq,xt as not,Kt as nth_value,Xt as ntile,gt as or,vt as percent_rank,Dt as prefix,ce as product,ue as quantile,Wt as rank,Lt as regexp_matches,qe as regrAvgX,be as regrAvgY,Se as regrCount,ye as regrIntercept,we as regrR2,Te as regrSXX,Re as regrSXY,Ae as regrSYY,Ne as regrSlope,H as relation,jt as row_number,Ke as scaleTransform,he as skewness,c as sql,fe as stddev,xe as stddevPop,_e as stringAgg,_t as suffix,ie as sum,lt as toSQL,Ct as upper,de as varPop,pe as variance,rt as x,nt as y};
|
|
1
|
+
var S=class{constructor(t,e){t&&(this.table=String(t)),e&&(this.column=e)}get columns(){return this.column?[this.column]:[]}toString(){let{table:t,column:e}=this;if(e){let n=e.startsWith("*")?e:`"${e}"`;return`${t?`${V(t)}.`:""}${n}`}else return t?V(t):"NULL"}};function V(r){return r.split(".").map(e=>`"${e}"`).join(".")}function k(r,t){return r instanceof S&&r.column===t}function u(r){return typeof r=="string"?K(r):r}function O(r){return typeof r=="string"?H(r):r}function H(r){return new S(r)}function K(r,t=null){return arguments.length===1&&(t=r,r=null),new S(r,t)}function ut(r){return new S(r,"*")}function lt(r){return typeof r=="string"?`"${r}"`:$(r)}function $(r){switch(typeof r){case"boolean":return r?"TRUE":"FALSE";case"string":return`'${r}'`;case"number":return Number.isFinite(r)?String(r):"NULL";default:if(r==null)return"NULL";if(r instanceof Date){let t=+r;if(Number.isNaN(t))return"NULL";let e=r.getUTCFullYear(),n=r.getUTCMonth(),o=r.getUTCDate();return t===Date.UTC(e,n,o)?`MAKE_DATE(${e}, ${n+1}, ${o})`:`EPOCH_MS(${t})`}else return r instanceof RegExp?`'${r.source}'`:String(r)}}var T=r=>typeof r?.addEventListener=="function";function _(r){return r instanceof N}var N=class{constructor(t,e,n){this._expr=Array.isArray(t)?t:[t],this._deps=e||[],this.annotate(n);let o=this._expr.filter(s=>T(s));o.length>0?(this._params=Array.from(new Set(o)),this._params.forEach(s=>{s.addEventListener("value",()=>pt(this,this.map?.get("value")))})):this.addEventListener=void 0}get value(){return this}get columns(){let{_params:t,_deps:e}=this;if(t){let n=new Set(t.flatMap(o=>{let s=o.value?.columns;return Array.isArray(s)?s:[]}));if(n.size){let o=new Set(e);return n.forEach(s=>o.add(s)),Array.from(o)}}return e}get column(){return this._deps.length?this._deps[0]:this.columns[0]}annotate(...t){return Object.assign(this,...t)}toString(){return this._expr.map(t=>T(t)&&!_(t)?$(t.value):t).join("")}addEventListener(t,e){let n=this.map||(this.map=new Map);(n.get(t)||(n.set(t,new Set),n.get(t))).add(e)}};function pt(r,t){if(t?.size)return Promise.allSettled(Array.from(t,e=>e(r)))}function W(r,t){let e=[r[0]],n=new Set,o=t.length;for(let s=0,i=0;s<o;){let a=t[s];T(a)?e[++i]=a:(Array.isArray(a?.columns)&&a.columns.forEach(d=>n.add(d)),e[i]+=typeof a=="string"?a:$(a));let p=r[++s];T(e[i])?e[++i]=p:e[i]+=p}return{spans:e,cols:Array.from(n)}}function c(r,...t){let{spans:e,cols:n}=W(r,t);return new N(e,n)}function ft(r){let t=u(r);return c`${t} DESC NULLS LAST`.annotate({label:t?.label,desc:!0})}var ht=r=>({value:r,toString:()=>$(r)});function D(r){r(this.op,this),this.children?.forEach(t=>t.visit(r))}function z(r,t){let e=t.filter(o=>o!=null).map(u),n=e.map((o,s)=>s?` ${r} `:"");return e.length===1?n.push(""):e.length>1&&(n[0]="(",n.push(")")),c(n,...e).annotate({op:r,children:e,visit:D})}var mt=(...r)=>z("AND",r.flat()),gt=(...r)=>z("OR",r.flat()),dt=r=>t=>c`(${r} ${u(t)})`.annotate({op:r,a:t,visit:D}),xt=dt("NOT"),J=r=>t=>c`(${u(t)} ${r})`.annotate({op:r,a:t,visit:D}),$t=J("IS NULL"),Et=J("IS NOT NULL"),w=r=>(t,e)=>c`(${u(t)} ${r} ${u(e)})`.annotate({op:r,a:t,b:e,visit:D}),yt=w("="),St=w("<>"),Nt=w("<"),wt=w(">"),At=w("<="),Tt=w(">="),Rt=w("IS DISTINCT FROM"),qt=w("IS NOT DISTINCT FROM");function Z(r,t,e,n){t=u(t);let o=r.startsWith("NOT ")?"NOT ":"";return(e?n?c`${o}(${e[0]} <= ${t} AND ${t} < ${e[1]})`:c`(${t} ${r} ${e[0]} AND ${e[1]})`:c``).annotate({op:r,visit:D,field:t,range:e})}var bt=(r,t,e)=>Z("BETWEEN",r,t,e),It=(r,t,e)=>Z("NOT BETWEEN",r,t,e);function R(r,t){return Array.from({length:r},()=>t)}function m(r,t){return(...e)=>{let n=e.map(u),o=t?`::${t}`:"";return(n.length?c([`${r}(`,...R(n.length-1,", "),`)${o}`],...n):c`${r}()${o}`).annotate({func:r,args:n})}}var Lt=m("REGEXP_MATCHES"),Ot=m("CONTAINS"),Dt=m("PREFIX"),Ct=m("SUFFIX"),Mt=m("LOWER"),_t=m("UPPER"),Pt=m("LENGTH"),Ft=m("ISNAN"),Gt=m("ISFINITE"),jt=m("ISINF");var C=class r extends N{constructor(t,e,n,o,s="",i="",a=""){let p;if(o&&!(s||i||a))p=o?c`${e} OVER "${o}"`:c`${e} OVER ()`;else{let b=s&&i?" ":"",I=(s||i)&&a?" ":"";p=c`${e} OVER (${o?`"${o}" `:""}${s}${b}${i}${I}${a})`}n&&(p=c`(${p})::${n}`);let{_expr:y,_deps:A}=p;super(y,A),this.window=t,this.func=e,this.type=n,this.name=o,this.group=s,this.order=i,this.frame=a}get basis(){return this.column}get label(){let{func:t}=this;return t.label??t.toString()}over(t){let{window:e,func:n,type:o,group:s,order:i,frame:a}=this;return new r(e,n,o,t,s,i,a)}partitionby(...t){let e=t.flat().filter(y=>y).map(u),n=c(["PARTITION BY ",R(e.length-1,", "),""],...e),{window:o,func:s,type:i,name:a,order:p,frame:d}=this;return new r(o,s,i,a,n,p,d)}orderby(...t){let e=t.flat().filter(y=>y).map(u),n=c(["ORDER BY ",R(e.length-1,", "),""],...e),{window:o,func:s,type:i,name:a,group:p,frame:d}=this;return new r(o,s,i,a,p,n,d)}rows(t){let e=tt("ROWS",t),{window:n,func:o,type:s,name:i,group:a,order:p}=this;return new r(n,o,s,i,a,p,e)}range(t){let e=tt("RANGE",t),{window:n,func:o,type:s,name:i,group:a,order:p}=this;return new r(n,o,s,i,a,p,e)}};function tt(r,t){if(T(t)){let e=c`${t}`;return e.toString=()=>`${r} ${et(t.value)}`,e}return`${r} ${et(t)}`}function et(r){let[t,e]=r,n=t===0?"CURRENT ROW":Number.isFinite(t)?`${Math.abs(t)} PRECEDING`:"UNBOUNDED PRECEDING",o=e===0?"CURRENT ROW":Number.isFinite(e)?`${Math.abs(e)} FOLLOWING`:"UNBOUNDED FOLLOWING";return`BETWEEN ${n} AND ${o}`}function E(r,t){return(...e)=>{let n=m(r)(...e);return new C(r,n,t)}}var Ut=E("ROW_NUMBER","INTEGER"),Wt=E("RANK","INTEGER"),Yt=E("DENSE_RANK","INTEGER"),Bt=E("PERCENT_RANK"),Xt=E("CUME_DIST"),vt=E("NTILE"),Qt=E("LAG"),Vt=E("LEAD"),kt=E("FIRST_VALUE"),Ht=E("LAST_VALUE"),Kt=E("NTH_VALUE");function zt(r,...t){return c(r,...t).annotate({aggregate:!0})}var Y=class r extends N{constructor(t,e,n,o,s){e=(e||[]).map(u);let{strings:i,exprs:a}=Jt(t,e,n,o,s),{spans:p,cols:d}=W(i,a);super(p,d),this.aggregate=t,this.args=e,this.type=n,this.isDistinct=o,this.filter=s}get basis(){return this.column}get label(){let{aggregate:t,args:e,isDistinct:n}=this,o=n?"DISTINCT"+(e.length?" ":""):"",s=e.length?`(${o}${e.map(Zt).join(", ")})`:"";return`${t.toLowerCase()}${s}`}distinct(){let{aggregate:t,args:e,type:n,filter:o}=this;return new r(t,e,n,!0,o)}where(t){let{aggregate:e,args:n,type:o,isDistinct:s}=this;return new r(e,n,o,s,t)}window(){let{aggregate:t,args:e,type:n,isDistinct:o}=this,s=new r(t,e,null,o);return new C(t,s,n)}partitionby(...t){return this.window().partitionby(...t)}orderby(...t){return this.window().orderby(...t)}rows(t){return this.window().rows(t)}range(t){return this.window().range(t)}};function Jt(r,t,e,n,o){let s=`)${e?`::${e}`:""}`,i=[`${r}(${n?"DISTINCT ":""}`],a=[];return t.length?(i=i.concat([...R(t.length-1,", "),`${s}${o?" FILTER (WHERE ":""}`,...o?[")"]:[]]),a=[...t,...o?[o]:[]]):i[0]+="*"+s,{exprs:a,strings:i}}function Zt(r){let t=$(r);return t&&t.startsWith('"')&&t.endsWith('"')?t.slice(1,-1):t}function l(r,t){return(...e)=>new Y(r,e,t)}var te=l("COUNT","INTEGER"),ee=l("AVG"),re=l("AVG"),ne=l("MAD"),oe=l("MAX"),se=l("MIN"),ie=l("SUM","DOUBLE"),ce=l("PRODUCT"),ae=l("MEDIAN"),ue=l("QUANTILE"),le=l("MODE"),pe=l("VARIANCE"),fe=l("STDDEV"),he=l("SKEWNESS"),me=l("KURTOSIS"),ge=l("ENTROPY"),de=l("VAR_POP"),xe=l("STDDEV_POP"),$e=l("CORR"),Ee=l("COVAR_POP"),ye=l("REGR_INTERCEPT"),Se=l("REGR_SLOPE"),Ne=l("REGR_COUNT"),we=l("REGR_R2"),Ae=l("REGR_SYY"),Te=l("REGR_SXX"),Re=l("REGR_SXY"),qe=l("REGR_AVGX"),be=l("REGR_AVGY"),Ie=l("FIRST"),Le=l("LAST"),Oe=l("ARG_MIN"),De=l("ARG_MAX"),Ce=l("STRING_AGG"),Me=l("ARRAY_AGG");function B(r,t){let e=u(r),n=c`CAST(${e} AS ${t})`;return Object.defineProperty(n,"label",{enumerable:!0,get(){return r.label}}),Object.defineProperty(n,"aggregate",{enumerable:!0,get(){return r.aggregate||!1}}),n}var _e=r=>B(r,"DOUBLE"),Pe=r=>B(r,"INTEGER");var X=r=>c`epoch_ms(${u(r)})`,Fe=r=>{let t=u(r);return c`MAKE_DATE(2012, MONTH(${t}), 1)`.annotate({label:"month"})},Ge=r=>{let t=u(r);return c`MAKE_DATE(2012, MONTH(${t}), DAY(${t}))`.annotate({label:"date"})},je=r=>{let t=u(r);return c`MAKE_DATE(2012, 1, DAY(${t}))`.annotate({label:"date"})};var Ue=m("ST_AsGeoJSON"),rt=m("ST_X"),nt=m("ST_Y"),v=m("ST_CENTROID"),We=r=>rt(v(r)),Ye=r=>nt(v(r));var F=class r{static select(...t){return new r().select(...t)}static from(...t){return new r().from(...t)}static with(...t){return new r().with(...t)}static union(...t){return new q("UNION",t.flat())}static unionAll(...t){return new q("UNION ALL",t.flat())}static intersect(...t){return new q("INTERSECT",t.flat())}static except(...t){return new q("EXCEPT",t.flat())}static describe(t){let e=t.clone(),{clone:n,toString:o}=e;return Object.assign(e,{describe:!0,clone:()=>r.describe(n.call(e)),toString:()=>`DESCRIBE ${o.call(e)}`})}constructor(){this.query={with:[],select:[],from:[],where:[],groupby:[],having:[],window:[],qualify:[],orderby:[]},this.cteFor=null}clone(){let t=new r;return t.query={...this.query},t}with(...t){let{query:e}=this;if(t.length===0)return e.with;{let n=[],o=(s,i)=>{let a=i.clone();a.cteFor=this,n.push({as:s,query:a})};return t.flat().forEach(s=>{if(s!=null)if(s.as&&s.query)o(s.as,s.query);else for(let i in s)o(i,s[i])}),e.with=e.with.concat(n),this}}select(...t){let{query:e}=this;if(t.length===0)return e.select;{let n=[];for(let o of t.flat())if(o!=null)if(typeof o=="string")n.push({as:o,expr:u(o)});else if(o instanceof S)n.push({as:o.column,expr:o});else if(Array.isArray(o))n.push({as:o[0],expr:o[1]});else for(let s in o)n.push({as:P(s),expr:u(o[s])});return e.select=e.select.concat(n),this}}$select(...t){return this.query.select=[],this.select(...t)}distinct(t=!0){return this.query.distinct=!!t,this}from(...t){let{query:e}=this;if(t.length===0)return e.from;{let n=[];return t.flat().forEach(o=>{if(o!=null)if(typeof o=="string")n.push({as:o,from:O(o)});else if(o instanceof S)n.push({as:o.table,from:o});else if(M(o)||_(o))n.push({from:o});else if(Array.isArray(o))n.push({as:P(o[0]),from:O(o[1])});else for(let s in o)n.push({as:P(s),from:O(o[s])})}),e.from=e.from.concat(n),this}}$from(...t){return this.query.from=[],this.from(...t)}sample(t,e){let{query:n}=this;if(arguments.length===0)return n.sample;{let o=t;return typeof t=="number"&&(o=t>0&&t<1?{perc:100*t,method:e}:{rows:Math.round(t),method:e}),n.sample=o,this}}where(...t){let{query:e}=this;return t.length===0?e.where:(e.where=e.where.concat(t.flat().filter(n=>n)),this)}$where(...t){return this.query.where=[],this.where(...t)}groupby(...t){let{query:e}=this;return t.length===0?e.groupby:(e.groupby=e.groupby.concat(t.flat().filter(n=>n).map(u)),this)}$groupby(...t){return this.query.groupby=[],this.groupby(...t)}having(...t){let{query:e}=this;return t.length===0?e.having:(e.having=e.having.concat(t.flat().filter(n=>n)),this)}window(...t){let{query:e}=this;if(t.length===0)return e.window;{let n=[];return t.flat().forEach(o=>{if(o!=null)for(let s in o)n.push({as:P(s),expr:o[s]})}),e.window=e.window.concat(n),this}}qualify(...t){let{query:e}=this;return t.length===0?e.qualify:(e.qualify=e.qualify.concat(t.flat().filter(n=>n)),this)}orderby(...t){let{query:e}=this;return t.length===0?e.orderby:(e.orderby=e.orderby.concat(t.flat().filter(n=>n).map(u)),this)}limit(t){let{query:e}=this;return arguments.length===0?e.limit:(e.limit=Number.isFinite(t)?t:void 0,this)}offset(t){let{query:e}=this;return arguments.length===0?e.offset:(e.offset=Number.isFinite(t)?t:void 0,this)}get subqueries(){let{query:t,cteFor:e}=this,o=(e?.query||t).with?.reduce((i,{as:a,query:p})=>(i[a]=p,i),{}),s=[];return t.from.forEach(({from:i})=>{if(M(i))s.push(i);else if(o[i.table]){let a=o[i.table];s.push(a)}}),s}toString(){let{with:t,select:e,distinct:n,from:o,sample:s,where:i,groupby:a,having:p,window:d,qualify:y,orderby:A,limit:b,offset:I}=this.query,g=[];if(t.length){let f=t.map(({as:h,query:x})=>`"${h}" AS (${x})`);g.push(`WITH ${f.join(", ")}`)}let it=e.map(({as:f,expr:h})=>k(h,f)&&!h.table?`${h}`:`${h} AS "${f}"`);if(g.push(`SELECT${n?" DISTINCT":""} ${it.join(", ")}`),o.length){let f=o.map(({as:h,from:x})=>{let L=M(x)?`(${x})`:`${x}`;return!h||h===x.table?L:`${L} AS "${h}"`});g.push(`FROM ${f.join(", ")}`)}if(i.length){let f=i.map(String).filter(h=>h).join(" AND ");f&&g.push(`WHERE ${f}`)}if(s){let{rows:f,perc:h,method:x,seed:L}=s,ct=f?`${f} ROWS`:`${h} PERCENT`,at=x?` (${x}${L!=null?`, ${L}`:""})`:"";g.push(`USING SAMPLE ${ct}${at}`)}if(a.length&&g.push(`GROUP BY ${a.join(", ")}`),p.length){let f=p.map(String).filter(h=>h).join(" AND ");f&&g.push(`HAVING ${f}`)}if(d.length){let f=d.map(({as:h,expr:x})=>`"${h}" AS (${x})`);g.push(`WINDOW ${f.join(", ")}`)}if(y.length){let f=y.map(String).filter(h=>h).join(" AND ");f&&g.push(`QUALIFY ${f}`)}return A.length&&g.push(`ORDER BY ${A.join(", ")}`),Number.isFinite(b)&&g.push(`LIMIT ${b}`),Number.isFinite(I)&&g.push(`OFFSET ${I}`),g.join(" ")}},q=class r{constructor(t,e){this.op=t,this.queries=e.map(n=>n.clone()),this.query={orderby:[]},this.cteFor=null}clone(){let t=new r(this.op,this.queries);return t.query={...this.query},t}orderby(...t){let{query:e}=this;return t.length===0?e.orderby:(e.orderby=e.orderby.concat(t.flat().filter(n=>n).map(u)),this)}limit(t){let{query:e}=this;return arguments.length===0?e.limit:(e.limit=Number.isFinite(t)?t:void 0,this)}offset(t){let{query:e}=this;return arguments.length===0?e.offset:(e.offset=Number.isFinite(t)?t:void 0,this)}get subqueries(){let{queries:t,cteFor:e}=this;return e&&t.forEach(n=>n.cteFor=e),t}toString(){let{op:t,queries:e,query:{orderby:n,limit:o,offset:s}}=this,i=[e.join(` ${t} `)];return n.length&&i.push(`ORDER BY ${n.join(", ")}`),Number.isFinite(o)&&i.push(`LIMIT ${o}`),Number.isFinite(s)&&i.push(`OFFSET ${s}`),i.join(" ")}};function M(r){return r instanceof F||r instanceof q}function Be(r){return M(r)&&r.describe}function P(r){return Xe(r)?r.slice(1,-1):r}function Xe(r){return r[0]==='"'&&r[r.length-1]==='"'}var G=r=>r;function ve(){return{apply:G,invert:G,sqlApply:u,sqlInvert:G}}function Qe({base:r=null}={}){if(r==null||r===Math.E)return{apply:Math.log,invert:Math.exp,sqlApply:t=>c`LN(${u(t)})`,sqlInvert:t=>c`EXP(${t})`};if(r===10)return{apply:Math.log10,invert:t=>Math.pow(10,t),sqlApply:t=>c`LOG(${u(t)})`,sqlInvert:t=>c`POW(10, ${t})`};{let t=+r;return{apply:e=>Math.log(e)/Math.log(t),invert:e=>Math.pow(t,e),sqlApply:e=>c`LN(${u(e)}) / LN(${t})`,sqlInvert:e=>c`POW(${t}, ${e})`}}}function Ve({constant:r=1}={}){let t=+r;return{apply:e=>Math.sign(e)*Math.log1p(Math.abs(e)),invert:e=>Math.sign(e)*Math.exp(Math.abs(e)-t),sqlApply:e=>(e=u(e),c`SIGN(${e}) * LN(${t} + ABS(${e}))`),sqlInvert:e=>c`SIGN(${e}) * (EXP(ABS(${e})) - ${t})`}}function ke(){return{apply:r=>Math.sign(r)*Math.sqrt(Math.abs(r)),invert:r=>Math.sign(r)*r*r,sqlApply:r=>(r=u(r),c`SIGN(${r}) * SQRT(ABS(${r}))`),sqlInvert:r=>c`SIGN(${r}) * (${r}) ** 2`}}function He({exponent:r=1}={}){let t=+r;return{apply:e=>Math.sign(e)*Math.pow(Math.abs(e),t),invert:e=>Math.sign(e)*Math.pow(Math.abs(e),1/t),sqlApply:e=>(e=u(e),c`SIGN(${e}) * POW(ABS(${e}), ${t})`),sqlInvert:e=>c`SIGN(${e}) * POW(ABS(${e}), 1/${t})`}}function ot(){return{apply:r=>+r,invert:r=>new Date(r),sqlApply:r=>r instanceof Date?+r:X(u(r)),sqlInvert:G}}var Ke={linear:ve,log:Qe,symlog:Ve,sqrt:ke,pow:He,time:ot,utc:ot};function ze(r){let t=Ke[r.type];return t?{...r,...t(r)}:null}function j(r,t,{replace:e=!1,temp:n=!0,view:o=!1}={}){return"CREATE"+(e?" OR REPLACE ":" ")+(n?"TEMP ":"")+(o?"VIEW":"TABLE")+(e?" ":" IF NOT EXISTS ")+r+" AS "+t}function Je(r){return`INSTALL ${r}; LOAD ${r}`}function st(r,{columns:t=Object.keys(r?.[0]||{})}={}){let e=[];if(Array.isArray(t)?(e=t,t=e.reduce((o,s)=>(o[s]=s,o),{})):t&&(e=Object.keys(t)),!e.length)throw new Error("Can not create table from empty column set.");let n=[];for(let o of r){let s=e.map(i=>`${$(o[i])} AS "${t[i]}"`);n.push(`(SELECT ${s.join(", ")})`)}return n.join(" UNION ALL ")}function U(r,t,e,n={},o={}){let{select:s=["*"],where:i,view:a,temp:p,replace:d,...y}=n,A=or({...o,...y}),b=`${r}('${e}'${A?", "+A:""})`,I=i?` WHERE ${i}`:"",g=`SELECT ${s.join(", ")} FROM ${b}${I}`;return j(t,g,{view:a,temp:p,replace:d})}function Ze(r,t,e){return U("read_csv",r,t,e,{auto_detect:!0,sample_size:-1})}function tr(r,t,e){return U("read_json",r,t,e,{auto_detect:!0,json_format:"auto"})}function er(r,t,e){return U("read_parquet",r,t,e)}function rr(r,t,e={}){let{options:n,...o}=e;if(n){let s=Array.isArray(n)?n.join(", "):typeof n=="string"?n:Object.entries(n).map(([i,a])=>`${i}=${a}`).join(", ");Object.assign(o,{open_options:s.toUpperCase()})}return U("st_read",r,t,o)}function nr(r,t,e={}){let{select:n=["*"],...o}=e,s=st(t),i=n.length===1&&n[0]==="*"?s:`SELECT ${n} FROM ${s}`;return j(r,i,o)}function or(r){return Object.entries(r).map(([t,e])=>`${t}=${Q(e)}`).join(", ")}function Q(r){switch(typeof r){case"boolean":return String(r);case"string":return`'${r}'`;case"undefined":case"object":return r==null?"NULL":Array.isArray(r)?"["+r.map(t=>Q(t)).join(", ")+"]":"{"+Object.entries(r).map(([t,e])=>`'${t}': ${Q(e)}`).join(", ")+"}";default:return r}}export{F as Query,S as Ref,zt as agg,ut as all,mt as and,De as argmax,Oe as argmin,Me as arrayAgg,u as asColumn,O as asRelation,ee as avg,B as cast,_e as castDouble,Pe as castInteger,v as centroid,We as centroidX,Ye as centroidY,K as column,Ot as contains,$e as corr,te as count,Ee as covarPop,j as create,Xt as cume_dist,je as dateDay,Fe as dateMonth,Ge as dateMonthDay,Yt as dense_rank,ft as desc,ge as entropy,X as epoch_ms,yt as eq,Ie as first,kt as first_value,Ue as geojson,wt as gt,Tt as gte,bt as isBetween,Be as isDescribeQuery,Rt as isDistinct,Gt as isFinite,jt as isInfinite,Ft as isNaN,It as isNotBetween,qt as isNotDistinct,Et as isNotNull,$t as isNull,T as isParamLike,M as isQuery,_ as isSQLExpression,me as kurtosis,Qt as lag,Le as last,Ht as last_value,Vt as lead,Pt as length,ht as literal,$ as literalToSQL,Ze as loadCSV,Je as loadExtension,tr as loadJSON,nr as loadObjects,er as loadParquet,rr as loadSpatial,Mt as lower,Nt as lt,At as lte,ne as mad,oe as max,re as mean,ae as median,se as min,le as mode,St as neq,xt as not,Kt as nth_value,vt as ntile,gt as or,Bt as percent_rank,Dt as prefix,ce as product,ue as quantile,Wt as rank,Lt as regexp_matches,qe as regrAvgX,be as regrAvgY,Ne as regrCount,ye as regrIntercept,we as regrR2,Te as regrSXX,Re as regrSXY,Ae as regrSYY,Se as regrSlope,H as relation,Ut as row_number,ze as scaleTransform,he as skewness,c as sql,fe as stddev,xe as stddevPop,Ce as stringAgg,Ct as suffix,ie as sum,lt as toSQL,_t as upper,de as varPop,pe as variance,rt as x,nt as y};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uwdata/mosaic-sql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "SQL query construction and analysis.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sql",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"scripts": {
|
|
22
22
|
"prebuild": "rimraf dist && mkdir dist",
|
|
23
23
|
"build": "node ../../esbuild.js mosaic-sql",
|
|
24
|
-
"lint": "eslint src test
|
|
24
|
+
"lint": "eslint src test",
|
|
25
25
|
"test": "mocha 'test/**/*-test.js'",
|
|
26
26
|
"prepublishOnly": "npm run test && npm run lint && npm run build"
|
|
27
27
|
},
|
|
28
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "a24b4c9f7dfa1c38c6af96ec17e075326c1af9b0"
|
|
29
29
|
}
|
package/src/Query.js
CHANGED
|
@@ -31,6 +31,16 @@ export class Query {
|
|
|
31
31
|
return new SetOperation('EXCEPT', queries.flat());
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
static describe(query) {
|
|
35
|
+
const q = query.clone();
|
|
36
|
+
const { clone, toString } = q;
|
|
37
|
+
return Object.assign(q, {
|
|
38
|
+
describe: true,
|
|
39
|
+
clone: () => Query.describe(clone.call(q)),
|
|
40
|
+
toString: () => `DESCRIBE ${toString.call(q)}`
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
34
44
|
constructor() {
|
|
35
45
|
this.query = {
|
|
36
46
|
with: [],
|
|
@@ -43,6 +53,7 @@ export class Query {
|
|
|
43
53
|
qualify: [],
|
|
44
54
|
orderby: []
|
|
45
55
|
};
|
|
56
|
+
this.cteFor = null;
|
|
46
57
|
}
|
|
47
58
|
|
|
48
59
|
clone() {
|
|
@@ -51,9 +62,18 @@ export class Query {
|
|
|
51
62
|
return q;
|
|
52
63
|
}
|
|
53
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Retrieve current WITH common table expressions (CTEs).
|
|
67
|
+
* @returns {any[]}
|
|
68
|
+
*//**
|
|
69
|
+
* Add WITH common table expressions (CTEs).
|
|
70
|
+
* @param {...any} expr Expressions to add.
|
|
71
|
+
* @returns {this}
|
|
72
|
+
*/
|
|
54
73
|
with(...expr) {
|
|
55
74
|
const { query } = this;
|
|
56
75
|
if (expr.length === 0) {
|
|
76
|
+
// @ts-ignore
|
|
57
77
|
return query.with;
|
|
58
78
|
} else {
|
|
59
79
|
const list = [];
|
|
@@ -78,9 +98,18 @@ export class Query {
|
|
|
78
98
|
}
|
|
79
99
|
}
|
|
80
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Retrieve current SELECT expressions.
|
|
103
|
+
* @returns {any[]}
|
|
104
|
+
*//**
|
|
105
|
+
* Add SELECT expressions.
|
|
106
|
+
* @param {...any} expr Expressions to add.
|
|
107
|
+
* @returns {this}
|
|
108
|
+
*/
|
|
81
109
|
select(...expr) {
|
|
82
110
|
const { query } = this;
|
|
83
111
|
if (expr.length === 0) {
|
|
112
|
+
// @ts-ignore
|
|
84
113
|
return query.select;
|
|
85
114
|
} else {
|
|
86
115
|
const list = [];
|
|
@@ -114,9 +143,18 @@ export class Query {
|
|
|
114
143
|
return this;
|
|
115
144
|
}
|
|
116
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Retrieve current from expressions.
|
|
148
|
+
* @returns {any[]}
|
|
149
|
+
*//**
|
|
150
|
+
* Provide table from expressions.
|
|
151
|
+
* @param {...any} expr
|
|
152
|
+
* @returns {this}
|
|
153
|
+
*/
|
|
117
154
|
from(...expr) {
|
|
118
155
|
const { query } = this;
|
|
119
156
|
if (expr.length === 0) {
|
|
157
|
+
// @ts-ignore
|
|
120
158
|
return query.from;
|
|
121
159
|
} else {
|
|
122
160
|
const list = [];
|
|
@@ -147,9 +185,19 @@ export class Query {
|
|
|
147
185
|
return this.from(...expr);
|
|
148
186
|
}
|
|
149
187
|
|
|
188
|
+
/**
|
|
189
|
+
* Retrieve current SAMPLE settings.
|
|
190
|
+
* @returns {any[]}
|
|
191
|
+
*//**
|
|
192
|
+
* Set SAMPLE settings.
|
|
193
|
+
* @param {number|object} value The percentage or number of rows to sample.
|
|
194
|
+
* @param {string} [method] The sampling method to use.
|
|
195
|
+
* @returns {this}
|
|
196
|
+
*/
|
|
150
197
|
sample(value, method) {
|
|
151
198
|
const { query } = this;
|
|
152
199
|
if (arguments.length === 0) {
|
|
200
|
+
// @ts-ignore
|
|
153
201
|
return query.sample;
|
|
154
202
|
} else {
|
|
155
203
|
let spec = value;
|
|
@@ -163,9 +211,18 @@ export class Query {
|
|
|
163
211
|
}
|
|
164
212
|
}
|
|
165
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Retrieve current WHERE expressions.
|
|
216
|
+
* @returns {any[]}
|
|
217
|
+
*//**
|
|
218
|
+
* Add WHERE expressions.
|
|
219
|
+
* @param {...any} expr Expressions to add.
|
|
220
|
+
* @returns {this}
|
|
221
|
+
*/
|
|
166
222
|
where(...expr) {
|
|
167
223
|
const { query } = this;
|
|
168
224
|
if (expr.length === 0) {
|
|
225
|
+
// @ts-ignore
|
|
169
226
|
return query.where;
|
|
170
227
|
} else {
|
|
171
228
|
query.where = query.where.concat(
|
|
@@ -180,9 +237,18 @@ export class Query {
|
|
|
180
237
|
return this.where(...expr);
|
|
181
238
|
}
|
|
182
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Retrieve current GROUP BY expressions.
|
|
242
|
+
* @returns {any[]}
|
|
243
|
+
*//**
|
|
244
|
+
* Add GROUP BY expressions.
|
|
245
|
+
* @param {...any} expr Expressions to add.
|
|
246
|
+
* @returns {this}
|
|
247
|
+
*/
|
|
183
248
|
groupby(...expr) {
|
|
184
249
|
const { query } = this;
|
|
185
250
|
if (expr.length === 0) {
|
|
251
|
+
// @ts-ignore
|
|
186
252
|
return query.groupby;
|
|
187
253
|
} else {
|
|
188
254
|
query.groupby = query.groupby.concat(
|
|
@@ -197,9 +263,18 @@ export class Query {
|
|
|
197
263
|
return this.groupby(...expr);
|
|
198
264
|
}
|
|
199
265
|
|
|
266
|
+
/**
|
|
267
|
+
* Retrieve current HAVING expressions.
|
|
268
|
+
* @returns {any[]}
|
|
269
|
+
*//**
|
|
270
|
+
* Add HAVING expressions.
|
|
271
|
+
* @param {...any} expr Expressions to add.
|
|
272
|
+
* @returns {this}
|
|
273
|
+
*/
|
|
200
274
|
having(...expr) {
|
|
201
275
|
const { query } = this;
|
|
202
276
|
if (expr.length === 0) {
|
|
277
|
+
// @ts-ignore
|
|
203
278
|
return query.having;
|
|
204
279
|
} else {
|
|
205
280
|
query.having = query.having.concat(
|
|
@@ -209,9 +284,18 @@ export class Query {
|
|
|
209
284
|
}
|
|
210
285
|
}
|
|
211
286
|
|
|
287
|
+
/**
|
|
288
|
+
* Retrieve current WINDOW definitions.
|
|
289
|
+
* @returns {any[]}
|
|
290
|
+
*//**
|
|
291
|
+
* Add WINDOW definitions.
|
|
292
|
+
* @param {...any} expr Expressions to add.
|
|
293
|
+
* @returns {this}
|
|
294
|
+
*/
|
|
212
295
|
window(...expr) {
|
|
213
296
|
const { query } = this;
|
|
214
297
|
if (expr.length === 0) {
|
|
298
|
+
// @ts-ignore
|
|
215
299
|
return query.window;
|
|
216
300
|
} else {
|
|
217
301
|
const list = [];
|
|
@@ -229,9 +313,18 @@ export class Query {
|
|
|
229
313
|
}
|
|
230
314
|
}
|
|
231
315
|
|
|
316
|
+
/**
|
|
317
|
+
* Retrieve current QUALIFY expressions.
|
|
318
|
+
* @returns {any[]}
|
|
319
|
+
*//**
|
|
320
|
+
* Add QUALIFY expressions.
|
|
321
|
+
* @param {...any} expr Expressions to add.
|
|
322
|
+
* @returns {this}
|
|
323
|
+
*/
|
|
232
324
|
qualify(...expr) {
|
|
233
325
|
const { query } = this;
|
|
234
326
|
if (expr.length === 0) {
|
|
327
|
+
// @ts-ignore
|
|
235
328
|
return query.qualify;
|
|
236
329
|
} else {
|
|
237
330
|
query.qualify = query.qualify.concat(
|
|
@@ -241,9 +334,18 @@ export class Query {
|
|
|
241
334
|
}
|
|
242
335
|
}
|
|
243
336
|
|
|
337
|
+
/**
|
|
338
|
+
* Retrieve current ORDER BY expressions.
|
|
339
|
+
* @returns {any[]}
|
|
340
|
+
*//**
|
|
341
|
+
* Add ORDER BY expressions.
|
|
342
|
+
* @param {...any} expr Expressions to add.
|
|
343
|
+
* @returns {this}
|
|
344
|
+
*/
|
|
244
345
|
orderby(...expr) {
|
|
245
346
|
const { query } = this;
|
|
246
347
|
if (expr.length === 0) {
|
|
348
|
+
// @ts-ignore
|
|
247
349
|
return query.orderby;
|
|
248
350
|
} else {
|
|
249
351
|
query.orderby = query.orderby.concat(
|
|
@@ -253,6 +355,14 @@ export class Query {
|
|
|
253
355
|
}
|
|
254
356
|
}
|
|
255
357
|
|
|
358
|
+
/**
|
|
359
|
+
* Retrieve current LIMIT value.
|
|
360
|
+
* @returns {number|null}
|
|
361
|
+
*//**
|
|
362
|
+
* Set the query result LIMIT.
|
|
363
|
+
* @param {number} value The limit value.
|
|
364
|
+
* @returns {this}
|
|
365
|
+
*/
|
|
256
366
|
limit(value) {
|
|
257
367
|
const { query } = this;
|
|
258
368
|
if (arguments.length === 0) {
|
|
@@ -263,6 +373,14 @@ export class Query {
|
|
|
263
373
|
}
|
|
264
374
|
}
|
|
265
375
|
|
|
376
|
+
/**
|
|
377
|
+
* Retrieve current OFFSET value.
|
|
378
|
+
* @returns {number|null}
|
|
379
|
+
*//**
|
|
380
|
+
* Set the query result OFFSET.
|
|
381
|
+
* @param {number} value The offset value.
|
|
382
|
+
* @returns {this}
|
|
383
|
+
*/
|
|
266
384
|
offset(value) {
|
|
267
385
|
const { query } = this;
|
|
268
386
|
if (arguments.length === 0) {
|
|
@@ -291,8 +409,8 @@ export class Query {
|
|
|
291
409
|
|
|
292
410
|
toString() {
|
|
293
411
|
const {
|
|
294
|
-
select, distinct, from, sample, where, groupby,
|
|
295
|
-
having, window, qualify, orderby, limit, offset
|
|
412
|
+
with: cte, select, distinct, from, sample, where, groupby,
|
|
413
|
+
having, window, qualify, orderby, limit, offset
|
|
296
414
|
} = this.query;
|
|
297
415
|
|
|
298
416
|
const sql = [];
|
|
@@ -381,6 +499,7 @@ export class SetOperation {
|
|
|
381
499
|
this.op = op;
|
|
382
500
|
this.queries = queries.map(q => q.clone());
|
|
383
501
|
this.query = { orderby: [] };
|
|
502
|
+
this.cteFor = null;
|
|
384
503
|
}
|
|
385
504
|
|
|
386
505
|
clone() {
|
|
@@ -430,6 +549,7 @@ export class SetOperation {
|
|
|
430
549
|
toString() {
|
|
431
550
|
const { op, queries, query: { orderby, limit, offset } } = this;
|
|
432
551
|
|
|
552
|
+
// SUBQUERIES
|
|
433
553
|
const sql = [ queries.join(` ${op} `) ];
|
|
434
554
|
|
|
435
555
|
// ORDER BY
|
|
@@ -455,6 +575,10 @@ export function isQuery(value) {
|
|
|
455
575
|
return value instanceof Query || value instanceof SetOperation;
|
|
456
576
|
}
|
|
457
577
|
|
|
578
|
+
export function isDescribeQuery(value) {
|
|
579
|
+
return isQuery(value) && value.describe;
|
|
580
|
+
}
|
|
581
|
+
|
|
458
582
|
function unquote(s) {
|
|
459
583
|
return isDoubleQuoted(s) ? s.slice(1, -1) : s;
|
|
460
584
|
}
|
package/src/aggregates.js
CHANGED
|
@@ -19,11 +19,24 @@ export function agg(strings, ...exprs) {
|
|
|
19
19
|
* rather than instantiate this class.
|
|
20
20
|
*/
|
|
21
21
|
export class AggregateFunction extends SQLExpression {
|
|
22
|
+
/**
|
|
23
|
+
* Create a new AggregateFunction instance.
|
|
24
|
+
* @param {*} op The aggregate operation.
|
|
25
|
+
* @param {*} [args] The aggregate function arguments.
|
|
26
|
+
* @param {*} [type] The SQL data type to cast to.
|
|
27
|
+
* @param {boolean} [isDistinct] Flag indicating if this is a distinct value aggregate.
|
|
28
|
+
* @param {*} [filter] Filtering expression to apply prior to aggregation.
|
|
29
|
+
*/
|
|
22
30
|
constructor(op, args, type, isDistinct, filter) {
|
|
23
31
|
args = (args || []).map(asColumn);
|
|
24
32
|
const { strings, exprs } = aggExpr(op, args, type, isDistinct, filter);
|
|
25
33
|
const { spans, cols } = parseSQL(strings, exprs);
|
|
26
|
-
super(spans, cols
|
|
34
|
+
super(spans, cols);
|
|
35
|
+
this.aggregate = op;
|
|
36
|
+
this.args = args;
|
|
37
|
+
this.type = type;
|
|
38
|
+
this.isDistinct = isDistinct;
|
|
39
|
+
this.filter = filter;
|
|
27
40
|
}
|
|
28
41
|
|
|
29
42
|
get basis() {
|
|
@@ -37,36 +50,69 @@ export class AggregateFunction extends SQLExpression {
|
|
|
37
50
|
return `${op.toLowerCase()}${tail}`;
|
|
38
51
|
}
|
|
39
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Return a new derived aggregate function over distinct values.
|
|
55
|
+
* @returns {AggregateFunction} A new aggregate function.
|
|
56
|
+
*/
|
|
40
57
|
distinct() {
|
|
41
58
|
const { aggregate: op, args, type, filter } = this;
|
|
42
59
|
return new AggregateFunction(op, args, type, true, filter);
|
|
43
60
|
}
|
|
44
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Return a new derived aggregate function that filters values.
|
|
64
|
+
* @param {*} filter The filter expresion.
|
|
65
|
+
* @returns {AggregateFunction} A new aggregate function.
|
|
66
|
+
*/
|
|
45
67
|
where(filter) {
|
|
46
68
|
const { aggregate: op, args, type, isDistinct } = this;
|
|
47
69
|
return new AggregateFunction(op, args, type, isDistinct, filter);
|
|
48
70
|
}
|
|
49
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Return a new window function over this aggregate.
|
|
74
|
+
* @returns {WindowFunction} A new aggregate function.
|
|
75
|
+
*/
|
|
50
76
|
window() {
|
|
51
77
|
const { aggregate: op, args, type, isDistinct } = this;
|
|
52
78
|
const func = new AggregateFunction(op, args, null, isDistinct);
|
|
53
79
|
return new WindowFunction(op, func, type);
|
|
54
80
|
}
|
|
55
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Return a window function over this aggregate with the given partitioning.
|
|
84
|
+
* @param {*} expr The grouping (partition by) criteria for the window function.
|
|
85
|
+
* @returns {WindowFunction} A new window function.
|
|
86
|
+
*/
|
|
56
87
|
partitionby(...expr) {
|
|
57
88
|
return this.window().partitionby(...expr);
|
|
58
89
|
}
|
|
59
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Return a window function over this aggregate with the given ordering.
|
|
93
|
+
* @param {*} expr The sorting (order by) criteria for the window function.
|
|
94
|
+
* @returns {WindowFunction} A new window function.
|
|
95
|
+
*/
|
|
60
96
|
orderby(...expr) {
|
|
61
97
|
return this.window().orderby(...expr);
|
|
62
98
|
}
|
|
63
99
|
|
|
64
|
-
|
|
65
|
-
|
|
100
|
+
/**
|
|
101
|
+
* Return a window function over this aggregate with the given row frame.
|
|
102
|
+
* @param {(number|null)[] | import('./expression.js').ParamLike} frame The row-based window frame.
|
|
103
|
+
* @returns {WindowFunction} A new window function.
|
|
104
|
+
*/
|
|
105
|
+
rows(frame) {
|
|
106
|
+
return this.window().rows(frame);
|
|
66
107
|
}
|
|
67
108
|
|
|
68
|
-
|
|
69
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Return a window function over this aggregate with the given range frame.
|
|
111
|
+
* @param {(number|null)[] | import('./expression.js').ParamLike} frame The range-based window frame.
|
|
112
|
+
* @returns {WindowFunction} A new window function.
|
|
113
|
+
*/
|
|
114
|
+
range(frame) {
|
|
115
|
+
return this.window().range(frame);
|
|
70
116
|
}
|
|
71
117
|
}
|
|
72
118
|
|
package/src/desc.js
CHANGED
|
@@ -4,8 +4,8 @@ import { asColumn } from './ref.js';
|
|
|
4
4
|
/**
|
|
5
5
|
* Annotate an expression to indicate descending sort order.
|
|
6
6
|
* Null values are ordered last.
|
|
7
|
-
* @param {SQLExpression|string} expr A SQL expression or column name string.
|
|
8
|
-
* @returns {SQLExpression} An expression with descending order.
|
|
7
|
+
* @param {import('./expression.js').SQLExpression|string} expr A SQL expression or column name string.
|
|
8
|
+
* @returns {import('./expression.js').SQLExpression} An expression with descending order.
|
|
9
9
|
*/
|
|
10
10
|
export function desc(expr) {
|
|
11
11
|
const e = asColumn(expr);
|
package/src/expression.js
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
import { literalToSQL } from './to-sql.js';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {{
|
|
5
|
+
* value: any;
|
|
6
|
+
* addEventListener(type: string, callback: Function): any;
|
|
7
|
+
* column?: string,
|
|
8
|
+
* columns?: string[]
|
|
9
|
+
* }} ParamLike
|
|
10
|
+
*/
|
|
11
|
+
|
|
3
12
|
/**
|
|
4
13
|
* Test if a value is parameter-like. Parameters have addEventListener methods.
|
|
5
14
|
* @param {*} value The value to test.
|
|
6
|
-
* @returns True if the value is param-like, false otherwise.
|
|
15
|
+
* @returns {value is ParamLike} True if the value is param-like, false otherwise.
|
|
7
16
|
*/
|
|
8
17
|
export const isParamLike = value => typeof value?.addEventListener === 'function';
|
|
9
18
|
|
|
10
19
|
/**
|
|
11
20
|
* Test if a value is a SQL expression instance.
|
|
12
21
|
* @param {*} value The value to test.
|
|
13
|
-
* @returns {
|
|
22
|
+
* @returns {value is SQLExpression} True if value is a SQL expression, false otherwise.
|
|
14
23
|
*/
|
|
15
24
|
export function isSQLExpression(value) {
|
|
16
25
|
return value instanceof SQLExpression;
|
|
@@ -24,7 +33,7 @@ export class SQLExpression {
|
|
|
24
33
|
|
|
25
34
|
/**
|
|
26
35
|
* Create a new SQL expression instance.
|
|
27
|
-
* @param {(string|SQLExpression|Ref)[]} parts The parts of the expression.
|
|
36
|
+
* @param {(string | ParamLike | SQLExpression | import('./ref.js').Ref)[]} parts The parts of the expression.
|
|
28
37
|
* @param {string[]} [columns=[]] The column dependencies
|
|
29
38
|
* @param {object} [props] Additional properties for this expression.
|
|
30
39
|
*/
|
|
@@ -35,6 +44,8 @@ export class SQLExpression {
|
|
|
35
44
|
|
|
36
45
|
const params = this._expr.filter(part => isParamLike(part));
|
|
37
46
|
if (params.length > 0) {
|
|
47
|
+
/** @type {ParamLike[]} */
|
|
48
|
+
// @ts-ignore
|
|
38
49
|
this._params = Array.from(new Set(params));
|
|
39
50
|
this._params.forEach(param => {
|
|
40
51
|
param.addEventListener('value', () => update(this, this.map?.get('value')));
|
package/src/index.js
CHANGED
package/src/load/load.js
CHANGED
|
@@ -38,7 +38,7 @@ export function loadSpatial(tableName, fileName, options = {}) {
|
|
|
38
38
|
: Object.entries(opt)
|
|
39
39
|
.map(([key, value]) => `${key}=${value}`)
|
|
40
40
|
.join(', ');
|
|
41
|
-
rest
|
|
41
|
+
Object.assign(rest, { open_options: open.toUpperCase() });
|
|
42
42
|
}
|
|
43
43
|
// TODO: handle box_2d for spatial_filter_box option
|
|
44
44
|
// TODO: handle wkb_blob for spatial_filter option
|
package/src/load/sql-from.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { literalToSQL } from '../to-sql.js';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Create a SQL query that embeds the given data for loading.
|
|
5
|
+
* @param {*} data The dataset
|
|
6
|
+
* @param {object} [options] Loading options
|
|
7
|
+
* @param {string[]|object} [options.columns] The columns to include
|
|
8
|
+
* @returns {string} SQL query string to load data
|
|
9
|
+
*/
|
|
3
10
|
export function sqlFrom(data, {
|
|
4
11
|
columns = Object.keys(data?.[0] || {})
|
|
5
12
|
} = {}) {
|
package/src/ref.js
CHANGED
|
@@ -5,7 +5,7 @@ export class Ref {
|
|
|
5
5
|
/**
|
|
6
6
|
* Create a new Ref instance.
|
|
7
7
|
* @param {string|Ref|null} table The table name.
|
|
8
|
-
* @param {string|null} column The column name.
|
|
8
|
+
* @param {string|null} [column] The column name.
|
|
9
9
|
*/
|
|
10
10
|
constructor(table, column) {
|
|
11
11
|
if (table) this.table = String(table);
|
|
@@ -87,11 +87,11 @@ export function relation(name) {
|
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
89
|
* Create a column reference.
|
|
90
|
-
* @param {string}
|
|
91
|
-
* @param {string} column The column name.
|
|
90
|
+
* @param {string} table The table name (optional).
|
|
91
|
+
* @param {string} [column] The column name.
|
|
92
92
|
* @returns {Ref} The generated column reference.
|
|
93
93
|
*/
|
|
94
|
-
export function column(table, column) {
|
|
94
|
+
export function column(table, column = null) {
|
|
95
95
|
if (arguments.length === 1) {
|
|
96
96
|
column = table;
|
|
97
97
|
table = null;
|
package/src/scales.js
CHANGED
package/src/windows.js
CHANGED
|
@@ -9,6 +9,16 @@ import { repeat } from './repeat.js';
|
|
|
9
9
|
* rather than instantiate this class.
|
|
10
10
|
*/
|
|
11
11
|
export class WindowFunction extends SQLExpression {
|
|
12
|
+
/**
|
|
13
|
+
* Create a new WindowFunction instance.
|
|
14
|
+
* @param {string} op The window operation indicator.
|
|
15
|
+
* @param {*} func The window function expression.
|
|
16
|
+
* @param {*} [type] The SQL data type to cast to.
|
|
17
|
+
* @param {string} [name] The window definition name.
|
|
18
|
+
* @param {*} [group] Grouping (partition by) expressions.
|
|
19
|
+
* @param {*} [order] Sorting (order by) expressions.
|
|
20
|
+
* @param {*} [frame] The window frame definition.
|
|
21
|
+
*/
|
|
12
22
|
constructor(op, func, type, name, group = '', order = '', frame = '') {
|
|
13
23
|
// build and parse expression
|
|
14
24
|
let expr;
|
|
@@ -24,7 +34,14 @@ export class WindowFunction extends SQLExpression {
|
|
|
24
34
|
expr = sql`(${expr})::${type}`;
|
|
25
35
|
}
|
|
26
36
|
const { _expr, _deps } = expr;
|
|
27
|
-
super(_expr, _deps
|
|
37
|
+
super(_expr, _deps);
|
|
38
|
+
this.window = op;
|
|
39
|
+
this.func = func;
|
|
40
|
+
this.type = type;
|
|
41
|
+
this.name = name;
|
|
42
|
+
this.group = group;
|
|
43
|
+
this.order = order;
|
|
44
|
+
this.frame = frame;
|
|
28
45
|
}
|
|
29
46
|
|
|
30
47
|
get basis() {
|
|
@@ -36,11 +53,21 @@ export class WindowFunction extends SQLExpression {
|
|
|
36
53
|
return func.label ?? func.toString();
|
|
37
54
|
}
|
|
38
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Return an updated window function over a named window definition.
|
|
58
|
+
* @param {string} name The window definition name.
|
|
59
|
+
* @returns {WindowFunction} A new window function.
|
|
60
|
+
*/
|
|
39
61
|
over(name) {
|
|
40
62
|
const { window: op, func, type, group, order, frame } = this;
|
|
41
63
|
return new WindowFunction(op, func, type, name, group, order, frame);
|
|
42
64
|
}
|
|
43
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Return an updated window function with the given partitioning.
|
|
68
|
+
* @param {*} expr The grouping (partition by) criteria for the window function.
|
|
69
|
+
* @returns {WindowFunction} A new window function.
|
|
70
|
+
*/
|
|
44
71
|
partitionby(...expr) {
|
|
45
72
|
const exprs = expr.flat().filter(x => x).map(asColumn);
|
|
46
73
|
const group = sql(
|
|
@@ -51,6 +78,11 @@ export class WindowFunction extends SQLExpression {
|
|
|
51
78
|
return new WindowFunction(op, func, type, name, group, order, frame);
|
|
52
79
|
}
|
|
53
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Return an updated window function with the given ordering.
|
|
83
|
+
* @param {*} expr The sorting (order by) criteria for the window function.
|
|
84
|
+
* @returns {WindowFunction} A new window function.
|
|
85
|
+
*/
|
|
54
86
|
orderby(...expr) {
|
|
55
87
|
const exprs = expr.flat().filter(x => x).map(asColumn);
|
|
56
88
|
const order = sql(
|
|
@@ -61,12 +93,22 @@ export class WindowFunction extends SQLExpression {
|
|
|
61
93
|
return new WindowFunction(op, func, type, name, group, order, frame);
|
|
62
94
|
}
|
|
63
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Return an updated window function with the given rows frame.
|
|
98
|
+
* @param {(number|null)[] | import('./expression.js').ParamLike} expr The row-based window frame.
|
|
99
|
+
* @returns {WindowFunction} A new window function.
|
|
100
|
+
*/
|
|
64
101
|
rows(expr) {
|
|
65
102
|
const frame = windowFrame('ROWS', expr);
|
|
66
103
|
const { window: op, func, type, name, group, order } = this;
|
|
67
104
|
return new WindowFunction(op, func, type, name, group, order, frame);
|
|
68
105
|
}
|
|
69
106
|
|
|
107
|
+
/**
|
|
108
|
+
* Return an updated window function with the given range frame.
|
|
109
|
+
* @param {(number|null)[] | import('./expression.js').ParamLike} expr The range-based window frame.
|
|
110
|
+
* @returns {WindowFunction} A new window function.
|
|
111
|
+
*/
|
|
70
112
|
range(expr) {
|
|
71
113
|
const frame = windowFrame('RANGE', expr);
|
|
72
114
|
const { window: op, func, type, name, group, order } = this;
|