@uwdata/mosaic-sql 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mosaic-sql.js +225 -28
- package/dist/mosaic-sql.min.js +1 -1
- package/package.json +3 -3
- package/src/Query.js +114 -1
- package/src/aggregates.js +52 -5
- package/src/desc.js +2 -2
- package/src/expression.js +15 -4
- package/src/index.js +3 -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 +2 -1
- package/src/to-sql.js +1 -1
- package/src/windows.js +43 -1
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;
|
|
@@ -68,7 +66,7 @@ function literalToSQL(value) {
|
|
|
68
66
|
case "boolean":
|
|
69
67
|
return value ? "TRUE" : "FALSE";
|
|
70
68
|
case "string":
|
|
71
|
-
return `'${value}'`;
|
|
69
|
+
return `'${value.replace(`'`, `''`)}'`;
|
|
72
70
|
case "number":
|
|
73
71
|
return Number.isFinite(value) ? String(value) : "NULL";
|
|
74
72
|
default:
|
|
@@ -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
|
*/
|
|
@@ -152,7 +149,7 @@ var SQLExpression = class {
|
|
|
152
149
|
/**
|
|
153
150
|
* Annotate this expression instance with additional properties.
|
|
154
151
|
* @param {object[]} [props] One or more objects with properties to add.
|
|
155
|
-
* @returns
|
|
152
|
+
* @returns This SQL expression.
|
|
156
153
|
*/
|
|
157
154
|
annotate(...props) {
|
|
158
155
|
return Object.assign(this, ...props);
|
|
@@ -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) {
|
|
@@ -466,6 +551,7 @@ var entropy = aggf("ENTROPY");
|
|
|
466
551
|
var varPop = aggf("VAR_POP");
|
|
467
552
|
var stddevPop = aggf("STDDEV_POP");
|
|
468
553
|
var corr = aggf("CORR");
|
|
554
|
+
var covariance = aggf("COVAR_SAMP");
|
|
469
555
|
var covarPop = aggf("COVAR_POP");
|
|
470
556
|
var regrIntercept = aggf("REGR_INTERCEPT");
|
|
471
557
|
var regrSlope = aggf("REGR_SLOPE");
|
|
@@ -573,12 +659,22 @@ var Query = class _Query {
|
|
|
573
659
|
qualify: [],
|
|
574
660
|
orderby: []
|
|
575
661
|
};
|
|
662
|
+
this.cteFor = null;
|
|
576
663
|
}
|
|
577
664
|
clone() {
|
|
578
665
|
const q = new _Query();
|
|
579
666
|
q.query = { ...this.query };
|
|
580
667
|
return q;
|
|
581
668
|
}
|
|
669
|
+
/**
|
|
670
|
+
* Retrieve current WITH common table expressions (CTEs).
|
|
671
|
+
* @returns {any[]}
|
|
672
|
+
*/
|
|
673
|
+
/**
|
|
674
|
+
* Add WITH common table expressions (CTEs).
|
|
675
|
+
* @param {...any} expr Expressions to add.
|
|
676
|
+
* @returns {this}
|
|
677
|
+
*/
|
|
582
678
|
with(...expr) {
|
|
583
679
|
const { query } = this;
|
|
584
680
|
if (expr.length === 0) {
|
|
@@ -604,6 +700,15 @@ var Query = class _Query {
|
|
|
604
700
|
return this;
|
|
605
701
|
}
|
|
606
702
|
}
|
|
703
|
+
/**
|
|
704
|
+
* Retrieve current SELECT expressions.
|
|
705
|
+
* @returns {any[]}
|
|
706
|
+
*/
|
|
707
|
+
/**
|
|
708
|
+
* Add SELECT expressions.
|
|
709
|
+
* @param {...any} expr Expressions to add.
|
|
710
|
+
* @returns {this}
|
|
711
|
+
*/
|
|
607
712
|
select(...expr) {
|
|
608
713
|
const { query } = this;
|
|
609
714
|
if (expr.length === 0) {
|
|
@@ -624,7 +729,8 @@ var Query = class _Query {
|
|
|
624
729
|
}
|
|
625
730
|
}
|
|
626
731
|
}
|
|
627
|
-
|
|
732
|
+
const keys = new Set(list.map((x2) => x2.as));
|
|
733
|
+
query.select = query.select.filter((x2) => !keys.has(x2.as)).concat(list.filter((x2) => x2.expr));
|
|
628
734
|
return this;
|
|
629
735
|
}
|
|
630
736
|
}
|
|
@@ -636,6 +742,15 @@ var Query = class _Query {
|
|
|
636
742
|
this.query.distinct = !!value;
|
|
637
743
|
return this;
|
|
638
744
|
}
|
|
745
|
+
/**
|
|
746
|
+
* Retrieve current from expressions.
|
|
747
|
+
* @returns {any[]}
|
|
748
|
+
*/
|
|
749
|
+
/**
|
|
750
|
+
* Provide table from expressions.
|
|
751
|
+
* @param {...any} expr
|
|
752
|
+
* @returns {this}
|
|
753
|
+
*/
|
|
639
754
|
from(...expr) {
|
|
640
755
|
const { query } = this;
|
|
641
756
|
if (expr.length === 0) {
|
|
@@ -666,6 +781,16 @@ var Query = class _Query {
|
|
|
666
781
|
this.query.from = [];
|
|
667
782
|
return this.from(...expr);
|
|
668
783
|
}
|
|
784
|
+
/**
|
|
785
|
+
* Retrieve current SAMPLE settings.
|
|
786
|
+
* @returns {any[]}
|
|
787
|
+
*/
|
|
788
|
+
/**
|
|
789
|
+
* Set SAMPLE settings.
|
|
790
|
+
* @param {number|object} value The percentage or number of rows to sample.
|
|
791
|
+
* @param {string} [method] The sampling method to use.
|
|
792
|
+
* @returns {this}
|
|
793
|
+
*/
|
|
669
794
|
sample(value, method) {
|
|
670
795
|
const { query } = this;
|
|
671
796
|
if (arguments.length === 0) {
|
|
@@ -679,6 +804,15 @@ var Query = class _Query {
|
|
|
679
804
|
return this;
|
|
680
805
|
}
|
|
681
806
|
}
|
|
807
|
+
/**
|
|
808
|
+
* Retrieve current WHERE expressions.
|
|
809
|
+
* @returns {any[]}
|
|
810
|
+
*/
|
|
811
|
+
/**
|
|
812
|
+
* Add WHERE expressions.
|
|
813
|
+
* @param {...any} expr Expressions to add.
|
|
814
|
+
* @returns {this}
|
|
815
|
+
*/
|
|
682
816
|
where(...expr) {
|
|
683
817
|
const { query } = this;
|
|
684
818
|
if (expr.length === 0) {
|
|
@@ -694,6 +828,15 @@ var Query = class _Query {
|
|
|
694
828
|
this.query.where = [];
|
|
695
829
|
return this.where(...expr);
|
|
696
830
|
}
|
|
831
|
+
/**
|
|
832
|
+
* Retrieve current GROUP BY expressions.
|
|
833
|
+
* @returns {any[]}
|
|
834
|
+
*/
|
|
835
|
+
/**
|
|
836
|
+
* Add GROUP BY expressions.
|
|
837
|
+
* @param {...any} expr Expressions to add.
|
|
838
|
+
* @returns {this}
|
|
839
|
+
*/
|
|
697
840
|
groupby(...expr) {
|
|
698
841
|
const { query } = this;
|
|
699
842
|
if (expr.length === 0) {
|
|
@@ -709,6 +852,15 @@ var Query = class _Query {
|
|
|
709
852
|
this.query.groupby = [];
|
|
710
853
|
return this.groupby(...expr);
|
|
711
854
|
}
|
|
855
|
+
/**
|
|
856
|
+
* Retrieve current HAVING expressions.
|
|
857
|
+
* @returns {any[]}
|
|
858
|
+
*/
|
|
859
|
+
/**
|
|
860
|
+
* Add HAVING expressions.
|
|
861
|
+
* @param {...any} expr Expressions to add.
|
|
862
|
+
* @returns {this}
|
|
863
|
+
*/
|
|
712
864
|
having(...expr) {
|
|
713
865
|
const { query } = this;
|
|
714
866
|
if (expr.length === 0) {
|
|
@@ -720,6 +872,15 @@ var Query = class _Query {
|
|
|
720
872
|
return this;
|
|
721
873
|
}
|
|
722
874
|
}
|
|
875
|
+
/**
|
|
876
|
+
* Retrieve current WINDOW definitions.
|
|
877
|
+
* @returns {any[]}
|
|
878
|
+
*/
|
|
879
|
+
/**
|
|
880
|
+
* Add WINDOW definitions.
|
|
881
|
+
* @param {...any} expr Expressions to add.
|
|
882
|
+
* @returns {this}
|
|
883
|
+
*/
|
|
723
884
|
window(...expr) {
|
|
724
885
|
const { query } = this;
|
|
725
886
|
if (expr.length === 0) {
|
|
@@ -738,6 +899,15 @@ var Query = class _Query {
|
|
|
738
899
|
return this;
|
|
739
900
|
}
|
|
740
901
|
}
|
|
902
|
+
/**
|
|
903
|
+
* Retrieve current QUALIFY expressions.
|
|
904
|
+
* @returns {any[]}
|
|
905
|
+
*/
|
|
906
|
+
/**
|
|
907
|
+
* Add QUALIFY expressions.
|
|
908
|
+
* @param {...any} expr Expressions to add.
|
|
909
|
+
* @returns {this}
|
|
910
|
+
*/
|
|
741
911
|
qualify(...expr) {
|
|
742
912
|
const { query } = this;
|
|
743
913
|
if (expr.length === 0) {
|
|
@@ -749,6 +919,15 @@ var Query = class _Query {
|
|
|
749
919
|
return this;
|
|
750
920
|
}
|
|
751
921
|
}
|
|
922
|
+
/**
|
|
923
|
+
* Retrieve current ORDER BY expressions.
|
|
924
|
+
* @returns {any[]}
|
|
925
|
+
*/
|
|
926
|
+
/**
|
|
927
|
+
* Add ORDER BY expressions.
|
|
928
|
+
* @param {...any} expr Expressions to add.
|
|
929
|
+
* @returns {this}
|
|
930
|
+
*/
|
|
752
931
|
orderby(...expr) {
|
|
753
932
|
const { query } = this;
|
|
754
933
|
if (expr.length === 0) {
|
|
@@ -760,6 +939,15 @@ var Query = class _Query {
|
|
|
760
939
|
return this;
|
|
761
940
|
}
|
|
762
941
|
}
|
|
942
|
+
/**
|
|
943
|
+
* Retrieve current LIMIT value.
|
|
944
|
+
* @returns {number|null}
|
|
945
|
+
*/
|
|
946
|
+
/**
|
|
947
|
+
* Set the query result LIMIT.
|
|
948
|
+
* @param {number} value The limit value.
|
|
949
|
+
* @returns {this}
|
|
950
|
+
*/
|
|
763
951
|
limit(value) {
|
|
764
952
|
const { query } = this;
|
|
765
953
|
if (arguments.length === 0) {
|
|
@@ -769,6 +957,15 @@ var Query = class _Query {
|
|
|
769
957
|
return this;
|
|
770
958
|
}
|
|
771
959
|
}
|
|
960
|
+
/**
|
|
961
|
+
* Retrieve current OFFSET value.
|
|
962
|
+
* @returns {number|null}
|
|
963
|
+
*/
|
|
964
|
+
/**
|
|
965
|
+
* Set the query result OFFSET.
|
|
966
|
+
* @param {number} value The offset value.
|
|
967
|
+
* @returns {this}
|
|
968
|
+
*/
|
|
772
969
|
offset(value) {
|
|
773
970
|
const { query } = this;
|
|
774
971
|
if (arguments.length === 0) {
|
|
@@ -827,8 +1024,7 @@ var Query = class _Query {
|
|
|
827
1024
|
}
|
|
828
1025
|
if (where.length) {
|
|
829
1026
|
const clauses = where.map(String).filter((x2) => x2).join(" AND ");
|
|
830
|
-
if (clauses)
|
|
831
|
-
sql2.push(`WHERE ${clauses}`);
|
|
1027
|
+
if (clauses) sql2.push(`WHERE ${clauses}`);
|
|
832
1028
|
}
|
|
833
1029
|
if (sample) {
|
|
834
1030
|
const { rows, perc, method, seed } = sample;
|
|
@@ -841,8 +1037,7 @@ var Query = class _Query {
|
|
|
841
1037
|
}
|
|
842
1038
|
if (having.length) {
|
|
843
1039
|
const clauses = having.map(String).filter((x2) => x2).join(" AND ");
|
|
844
|
-
if (clauses)
|
|
845
|
-
sql2.push(`HAVING ${clauses}`);
|
|
1040
|
+
if (clauses) sql2.push(`HAVING ${clauses}`);
|
|
846
1041
|
}
|
|
847
1042
|
if (window.length) {
|
|
848
1043
|
const windows = window.map(({ as, expr }) => `"${as}" AS (${expr})`);
|
|
@@ -850,8 +1045,7 @@ var Query = class _Query {
|
|
|
850
1045
|
}
|
|
851
1046
|
if (qualify.length) {
|
|
852
1047
|
const clauses = qualify.map(String).filter((x2) => x2).join(" AND ");
|
|
853
|
-
if (clauses)
|
|
854
|
-
sql2.push(`QUALIFY ${clauses}`);
|
|
1048
|
+
if (clauses) sql2.push(`QUALIFY ${clauses}`);
|
|
855
1049
|
}
|
|
856
1050
|
if (orderby.length) {
|
|
857
1051
|
sql2.push(`ORDER BY ${orderby.join(", ")}`);
|
|
@@ -870,6 +1064,7 @@ var SetOperation = class _SetOperation {
|
|
|
870
1064
|
this.op = op;
|
|
871
1065
|
this.queries = queries.map((q) => q.clone());
|
|
872
1066
|
this.query = { orderby: [] };
|
|
1067
|
+
this.cteFor = null;
|
|
873
1068
|
}
|
|
874
1069
|
clone() {
|
|
875
1070
|
const q = new _SetOperation(this.op, this.queries);
|
|
@@ -907,8 +1102,7 @@ var SetOperation = class _SetOperation {
|
|
|
907
1102
|
}
|
|
908
1103
|
get subqueries() {
|
|
909
1104
|
const { queries, cteFor } = this;
|
|
910
|
-
if (cteFor)
|
|
911
|
-
queries.forEach((q) => q.cteFor = cteFor);
|
|
1105
|
+
if (cteFor) queries.forEach((q) => q.cteFor = cteFor);
|
|
912
1106
|
return queries;
|
|
913
1107
|
}
|
|
914
1108
|
toString() {
|
|
@@ -949,7 +1143,7 @@ function scaleLinear() {
|
|
|
949
1143
|
sqlInvert: identity
|
|
950
1144
|
};
|
|
951
1145
|
}
|
|
952
|
-
function scaleLog({ base } = {}) {
|
|
1146
|
+
function scaleLog({ base = null } = {}) {
|
|
953
1147
|
if (base == null || base === Math.E) {
|
|
954
1148
|
return {
|
|
955
1149
|
apply: Math.log,
|
|
@@ -1009,6 +1203,7 @@ function scaleTime() {
|
|
|
1009
1203
|
};
|
|
1010
1204
|
}
|
|
1011
1205
|
var scales = {
|
|
1206
|
+
identity: scaleLinear,
|
|
1012
1207
|
linear: scaleLinear,
|
|
1013
1208
|
log: scaleLog,
|
|
1014
1209
|
symlog: scaleSymlog,
|
|
@@ -1080,7 +1275,7 @@ function loadSpatial(tableName, fileName, options = {}) {
|
|
|
1080
1275
|
const { options: opt, ...rest } = options;
|
|
1081
1276
|
if (opt) {
|
|
1082
1277
|
const open = Array.isArray(opt) ? opt.join(", ") : typeof opt === "string" ? opt : Object.entries(opt).map(([key, value]) => `${key}=${value}`).join(", ");
|
|
1083
|
-
rest
|
|
1278
|
+
Object.assign(rest, { open_options: open.toUpperCase() });
|
|
1084
1279
|
}
|
|
1085
1280
|
return load("st_read", tableName, fileName, rest);
|
|
1086
1281
|
}
|
|
@@ -1115,6 +1310,7 @@ function toDuckDBValue(value) {
|
|
|
1115
1310
|
export {
|
|
1116
1311
|
Query,
|
|
1117
1312
|
Ref,
|
|
1313
|
+
SQLExpression,
|
|
1118
1314
|
agg,
|
|
1119
1315
|
all,
|
|
1120
1316
|
and,
|
|
@@ -1135,6 +1331,7 @@ export {
|
|
|
1135
1331
|
corr,
|
|
1136
1332
|
count,
|
|
1137
1333
|
covarPop,
|
|
1334
|
+
covariance,
|
|
1138
1335
|
create,
|
|
1139
1336
|
cume_dist,
|
|
1140
1337
|
dateDay,
|
package/dist/mosaic-sql.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
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){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"),Ut=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,{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 C(r,n,t)}}var jt=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,{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 C(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"),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"})},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"),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:[]}}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:[]}}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}={}){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 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 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 j(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 U(t,g,{view:a,temp:p,replace:d})}function Ze(r,t,e){return j("read_csv",r,t,e,{auto_detect:!0,sample_size:-1})}function tr(r,t,e){return j("read_json",r,t,e,{auto_detect:!0,json_format:"auto"})}function er(r,t,e){return j("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(", ");o.open_options=s.toUpperCase()}return j("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 U(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,U as create,Xt as cume_dist,Ue 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,je as geojson,wt as gt,Tt as gte,bt as isBetween,Be as isDescribeQuery,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,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,jt 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};
|
|
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 lt(r){return new S(r,"*")}function pt(r){return typeof r=="string"?`"${r}"`:$(r)}function $(r){switch(typeof r){case"boolean":return r?"TRUE":"FALSE";case"string":return`'${r.replace("'","''")}'`;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 R=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=>R(s));o.length>0?(this._params=Array.from(new Set(o)),this._params.forEach(s=>{s.addEventListener("value",()=>ft(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=>R(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 ft(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];R(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];R(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 ht(r){let t=u(r);return c`${t} DESC NULLS LAST`.annotate({label:t?.label,desc:!0})}var mt=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 gt=(...r)=>z("AND",r.flat()),dt=(...r)=>z("OR",r.flat()),xt=r=>t=>c`(${r} ${u(t)})`.annotate({op:r,a:t,visit:D}),$t=xt("NOT"),J=r=>t=>c`(${u(t)} ${r})`.annotate({op:r,a:t,visit:D}),Et=J("IS NULL"),yt=J("IS NOT NULL"),w=r=>(t,e)=>c`(${u(t)} ${r} ${u(e)})`.annotate({op:r,a:t,b:e,visit:D}),St=w("="),Nt=w("<>"),wt=w("<"),At=w(">"),Rt=w("<="),Tt=w(">="),qt=w("IS DISTINCT FROM"),bt=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 It=(r,t,e)=>Z("BETWEEN",r,t,e),Lt=(r,t,e)=>Z("NOT BETWEEN",r,t,e);function T(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}(`,...T(n.length-1,", "),`)${o}`],...n):c`${r}()${o}`).annotate({func:r,args:n})}}var Ot=m("REGEXP_MATCHES"),Dt=m("CONTAINS"),Ct=m("PREFIX"),Mt=m("SUFFIX"),_t=m("LOWER"),Pt=m("UPPER"),Ft=m("LENGTH"),Gt=m("ISNAN"),jt=m("ISFINITE"),Ut=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 ",T(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 ",T(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(R(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 Wt=E("ROW_NUMBER","INTEGER"),Yt=E("RANK","INTEGER"),vt=E("DENSE_RANK","INTEGER"),Bt=E("PERCENT_RANK"),Qt=E("CUME_DIST"),Xt=E("NTILE"),Vt=E("LAG"),kt=E("LEAD"),Ht=E("FIRST_VALUE"),Kt=E("LAST_VALUE"),zt=E("NTH_VALUE");function Jt(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}=Zt(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(te).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 Zt(r,t,e,n,o){let s=`)${e?`::${e}`:""}`,i=[`${r}(${n?"DISTINCT ":""}`],a=[];return t.length?(i=i.concat([...T(t.length-1,", "),`${s}${o?" FILTER (WHERE ":""}`,...o?[")"]:[]]),a=[...t,...o?[o]:[]]):i[0]+="*"+s,{exprs:a,strings:i}}function te(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 ee=l("COUNT","INTEGER"),re=l("AVG"),ne=l("AVG"),oe=l("MAD"),se=l("MAX"),ie=l("MIN"),ce=l("SUM","DOUBLE"),ae=l("PRODUCT"),ue=l("MEDIAN"),le=l("QUANTILE"),pe=l("MODE"),fe=l("VARIANCE"),he=l("STDDEV"),me=l("SKEWNESS"),ge=l("KURTOSIS"),de=l("ENTROPY"),xe=l("VAR_POP"),$e=l("STDDEV_POP"),Ee=l("CORR"),ye=l("COVAR_SAMP"),Se=l("COVAR_POP"),Ne=l("REGR_INTERCEPT"),we=l("REGR_SLOPE"),Ae=l("REGR_COUNT"),Re=l("REGR_R2"),Te=l("REGR_SYY"),qe=l("REGR_SXX"),be=l("REGR_SXY"),Ie=l("REGR_AVGX"),Le=l("REGR_AVGY"),Oe=l("FIRST"),De=l("LAST"),Ce=l("ARG_MIN"),Me=l("ARG_MAX"),_e=l("STRING_AGG"),Pe=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 Fe=r=>v(r,"DOUBLE"),Ge=r=>v(r,"INTEGER");var B=r=>c`epoch_ms(${u(r)})`,je=r=>{let t=u(r);return c`MAKE_DATE(2012, MONTH(${t}), 1)`.annotate({label:"month"})},Ue=r=>{let t=u(r);return c`MAKE_DATE(2012, MONTH(${t}), DAY(${t}))`.annotate({label:"date"})},We=r=>{let t=u(r);return c`MAKE_DATE(2012, 1, DAY(${t}))`.annotate({label:"date"})};var Ye=m("ST_AsGeoJSON"),rt=m("ST_X"),nt=m("ST_Y"),Q=m("ST_CENTROID"),ve=r=>rt(Q(r)),Be=r=>nt(Q(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 s of t.flat())if(s!=null)if(typeof s=="string")n.push({as:s,expr:u(s)});else if(s instanceof S)n.push({as:s.column,expr:s});else if(Array.isArray(s))n.push({as:s[0],expr:s[1]});else for(let i in s)n.push({as:P(i),expr:u(s[i])});let o=new Set(n.map(s=>s.as));return e.select=e.select.filter(s=>!o.has(s.as)).concat(n.filter(s=>s.expr)),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 ct=e.map(({as:f,expr:h})=>k(h,f)&&!h.table?`${h}`:`${h} AS "${f}"`);if(g.push(`SELECT${n?" DISTINCT":""} ${ct.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,at=f?`${f} ROWS`:`${h} PERCENT`,ut=x?` (${x}${L!=null?`, ${L}`:""})`:"";g.push(`USING SAMPLE ${at}${ut}`)}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 Qe(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 ot(){return{apply:G,invert:G,sqlApply:u,sqlInvert:G}}function Ve({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 ke({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 He(){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 st(){return{apply:r=>+r,invert:r=>new Date(r),sqlApply:r=>r instanceof Date?+r:B(u(r)),sqlInvert:G}}var ze={identity:ot,linear:ot,log:Ve,symlog:ke,sqrt:He,pow:Ke,time:st,utc:st};function Je(r){let t=ze[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 Ze(r){return`INSTALL ${r}; LOAD ${r}`}function it(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=sr({...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 tr(r,t,e){return U("read_csv",r,t,e,{auto_detect:!0,sample_size:-1})}function er(r,t,e){return U("read_json",r,t,e,{auto_detect:!0,json_format:"auto"})}function rr(r,t,e){return U("read_parquet",r,t,e)}function nr(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 or(r,t,e={}){let{select:n=["*"],...o}=e,s=it(t),i=n.length===1&&n[0]==="*"?s:`SELECT ${n} FROM ${s}`;return j(r,i,o)}function sr(r){return Object.entries(r).map(([t,e])=>`${t}=${X(e)}`).join(", ")}function X(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=>X(t)).join(", ")+"]":"{"+Object.entries(r).map(([t,e])=>`'${t}': ${X(e)}`).join(", ")+"}";default:return r}}export{F as Query,S as Ref,N as SQLExpression,Jt as agg,lt as all,gt as and,Me as argmax,Ce as argmin,Pe as arrayAgg,u as asColumn,O as asRelation,re as avg,v as cast,Fe as castDouble,Ge as castInteger,Q as centroid,ve as centroidX,Be as centroidY,K as column,Dt as contains,Ee as corr,ee as count,Se as covarPop,ye as covariance,j as create,Qt as cume_dist,We as dateDay,je as dateMonth,Ue as dateMonthDay,vt as dense_rank,ht as desc,de as entropy,B as epoch_ms,St as eq,Oe as first,Ht as first_value,Ye as geojson,At as gt,Tt as gte,It as isBetween,Qe as isDescribeQuery,qt as isDistinct,jt as isFinite,Ut as isInfinite,Gt as isNaN,Lt as isNotBetween,bt as isNotDistinct,yt as isNotNull,Et as isNull,R as isParamLike,M as isQuery,_ as isSQLExpression,ge as kurtosis,Vt as lag,De as last,Kt as last_value,kt as lead,Ft as length,mt as literal,$ as literalToSQL,tr as loadCSV,Ze as loadExtension,er as loadJSON,or as loadObjects,rr as loadParquet,nr as loadSpatial,_t as lower,wt as lt,Rt as lte,oe as mad,se as max,ne as mean,ue as median,ie as min,pe as mode,Nt as neq,$t as not,zt as nth_value,Xt as ntile,dt as or,Bt as percent_rank,Ct as prefix,ae as product,le as quantile,Yt as rank,Ot as regexp_matches,Ie as regrAvgX,Le as regrAvgY,Ae as regrCount,Ne as regrIntercept,Re as regrR2,qe as regrSXX,be as regrSXY,Te as regrSYY,we as regrSlope,H as relation,Wt as row_number,Je as scaleTransform,me as skewness,c as sql,he as stddev,$e as stddevPop,_e as stringAgg,Mt as suffix,ce as sum,pt as toSQL,Pt as upper,xe as varPop,fe 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.9.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": "89bb9b0dfa747aed691eaeba35379525a6764c61"
|
|
29
29
|
}
|
package/src/Query.js
CHANGED
|
@@ -53,6 +53,7 @@ export class Query {
|
|
|
53
53
|
qualify: [],
|
|
54
54
|
orderby: []
|
|
55
55
|
};
|
|
56
|
+
this.cteFor = null;
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
clone() {
|
|
@@ -61,9 +62,18 @@ export class Query {
|
|
|
61
62
|
return q;
|
|
62
63
|
}
|
|
63
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
|
+
*/
|
|
64
73
|
with(...expr) {
|
|
65
74
|
const { query } = this;
|
|
66
75
|
if (expr.length === 0) {
|
|
76
|
+
// @ts-ignore
|
|
67
77
|
return query.with;
|
|
68
78
|
} else {
|
|
69
79
|
const list = [];
|
|
@@ -88,9 +98,18 @@ export class Query {
|
|
|
88
98
|
}
|
|
89
99
|
}
|
|
90
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
|
+
*/
|
|
91
109
|
select(...expr) {
|
|
92
110
|
const { query } = this;
|
|
93
111
|
if (expr.length === 0) {
|
|
112
|
+
// @ts-ignore
|
|
94
113
|
return query.select;
|
|
95
114
|
} else {
|
|
96
115
|
const list = [];
|
|
@@ -109,7 +128,11 @@ export class Query {
|
|
|
109
128
|
}
|
|
110
129
|
}
|
|
111
130
|
}
|
|
112
|
-
|
|
131
|
+
|
|
132
|
+
const keys = new Set(list.map(x => x.as));
|
|
133
|
+
query.select = query.select
|
|
134
|
+
.filter(x => !keys.has(x.as))
|
|
135
|
+
.concat(list.filter(x => x.expr));
|
|
113
136
|
return this;
|
|
114
137
|
}
|
|
115
138
|
}
|
|
@@ -124,9 +147,18 @@ export class Query {
|
|
|
124
147
|
return this;
|
|
125
148
|
}
|
|
126
149
|
|
|
150
|
+
/**
|
|
151
|
+
* Retrieve current from expressions.
|
|
152
|
+
* @returns {any[]}
|
|
153
|
+
*//**
|
|
154
|
+
* Provide table from expressions.
|
|
155
|
+
* @param {...any} expr
|
|
156
|
+
* @returns {this}
|
|
157
|
+
*/
|
|
127
158
|
from(...expr) {
|
|
128
159
|
const { query } = this;
|
|
129
160
|
if (expr.length === 0) {
|
|
161
|
+
// @ts-ignore
|
|
130
162
|
return query.from;
|
|
131
163
|
} else {
|
|
132
164
|
const list = [];
|
|
@@ -157,9 +189,19 @@ export class Query {
|
|
|
157
189
|
return this.from(...expr);
|
|
158
190
|
}
|
|
159
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Retrieve current SAMPLE settings.
|
|
194
|
+
* @returns {any[]}
|
|
195
|
+
*//**
|
|
196
|
+
* Set SAMPLE settings.
|
|
197
|
+
* @param {number|object} value The percentage or number of rows to sample.
|
|
198
|
+
* @param {string} [method] The sampling method to use.
|
|
199
|
+
* @returns {this}
|
|
200
|
+
*/
|
|
160
201
|
sample(value, method) {
|
|
161
202
|
const { query } = this;
|
|
162
203
|
if (arguments.length === 0) {
|
|
204
|
+
// @ts-ignore
|
|
163
205
|
return query.sample;
|
|
164
206
|
} else {
|
|
165
207
|
let spec = value;
|
|
@@ -173,9 +215,18 @@ export class Query {
|
|
|
173
215
|
}
|
|
174
216
|
}
|
|
175
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Retrieve current WHERE expressions.
|
|
220
|
+
* @returns {any[]}
|
|
221
|
+
*//**
|
|
222
|
+
* Add WHERE expressions.
|
|
223
|
+
* @param {...any} expr Expressions to add.
|
|
224
|
+
* @returns {this}
|
|
225
|
+
*/
|
|
176
226
|
where(...expr) {
|
|
177
227
|
const { query } = this;
|
|
178
228
|
if (expr.length === 0) {
|
|
229
|
+
// @ts-ignore
|
|
179
230
|
return query.where;
|
|
180
231
|
} else {
|
|
181
232
|
query.where = query.where.concat(
|
|
@@ -190,9 +241,18 @@ export class Query {
|
|
|
190
241
|
return this.where(...expr);
|
|
191
242
|
}
|
|
192
243
|
|
|
244
|
+
/**
|
|
245
|
+
* Retrieve current GROUP BY expressions.
|
|
246
|
+
* @returns {any[]}
|
|
247
|
+
*//**
|
|
248
|
+
* Add GROUP BY expressions.
|
|
249
|
+
* @param {...any} expr Expressions to add.
|
|
250
|
+
* @returns {this}
|
|
251
|
+
*/
|
|
193
252
|
groupby(...expr) {
|
|
194
253
|
const { query } = this;
|
|
195
254
|
if (expr.length === 0) {
|
|
255
|
+
// @ts-ignore
|
|
196
256
|
return query.groupby;
|
|
197
257
|
} else {
|
|
198
258
|
query.groupby = query.groupby.concat(
|
|
@@ -207,9 +267,18 @@ export class Query {
|
|
|
207
267
|
return this.groupby(...expr);
|
|
208
268
|
}
|
|
209
269
|
|
|
270
|
+
/**
|
|
271
|
+
* Retrieve current HAVING expressions.
|
|
272
|
+
* @returns {any[]}
|
|
273
|
+
*//**
|
|
274
|
+
* Add HAVING expressions.
|
|
275
|
+
* @param {...any} expr Expressions to add.
|
|
276
|
+
* @returns {this}
|
|
277
|
+
*/
|
|
210
278
|
having(...expr) {
|
|
211
279
|
const { query } = this;
|
|
212
280
|
if (expr.length === 0) {
|
|
281
|
+
// @ts-ignore
|
|
213
282
|
return query.having;
|
|
214
283
|
} else {
|
|
215
284
|
query.having = query.having.concat(
|
|
@@ -219,9 +288,18 @@ export class Query {
|
|
|
219
288
|
}
|
|
220
289
|
}
|
|
221
290
|
|
|
291
|
+
/**
|
|
292
|
+
* Retrieve current WINDOW definitions.
|
|
293
|
+
* @returns {any[]}
|
|
294
|
+
*//**
|
|
295
|
+
* Add WINDOW definitions.
|
|
296
|
+
* @param {...any} expr Expressions to add.
|
|
297
|
+
* @returns {this}
|
|
298
|
+
*/
|
|
222
299
|
window(...expr) {
|
|
223
300
|
const { query } = this;
|
|
224
301
|
if (expr.length === 0) {
|
|
302
|
+
// @ts-ignore
|
|
225
303
|
return query.window;
|
|
226
304
|
} else {
|
|
227
305
|
const list = [];
|
|
@@ -239,9 +317,18 @@ export class Query {
|
|
|
239
317
|
}
|
|
240
318
|
}
|
|
241
319
|
|
|
320
|
+
/**
|
|
321
|
+
* Retrieve current QUALIFY expressions.
|
|
322
|
+
* @returns {any[]}
|
|
323
|
+
*//**
|
|
324
|
+
* Add QUALIFY expressions.
|
|
325
|
+
* @param {...any} expr Expressions to add.
|
|
326
|
+
* @returns {this}
|
|
327
|
+
*/
|
|
242
328
|
qualify(...expr) {
|
|
243
329
|
const { query } = this;
|
|
244
330
|
if (expr.length === 0) {
|
|
331
|
+
// @ts-ignore
|
|
245
332
|
return query.qualify;
|
|
246
333
|
} else {
|
|
247
334
|
query.qualify = query.qualify.concat(
|
|
@@ -251,9 +338,18 @@ export class Query {
|
|
|
251
338
|
}
|
|
252
339
|
}
|
|
253
340
|
|
|
341
|
+
/**
|
|
342
|
+
* Retrieve current ORDER BY expressions.
|
|
343
|
+
* @returns {any[]}
|
|
344
|
+
*//**
|
|
345
|
+
* Add ORDER BY expressions.
|
|
346
|
+
* @param {...any} expr Expressions to add.
|
|
347
|
+
* @returns {this}
|
|
348
|
+
*/
|
|
254
349
|
orderby(...expr) {
|
|
255
350
|
const { query } = this;
|
|
256
351
|
if (expr.length === 0) {
|
|
352
|
+
// @ts-ignore
|
|
257
353
|
return query.orderby;
|
|
258
354
|
} else {
|
|
259
355
|
query.orderby = query.orderby.concat(
|
|
@@ -263,6 +359,14 @@ export class Query {
|
|
|
263
359
|
}
|
|
264
360
|
}
|
|
265
361
|
|
|
362
|
+
/**
|
|
363
|
+
* Retrieve current LIMIT value.
|
|
364
|
+
* @returns {number|null}
|
|
365
|
+
*//**
|
|
366
|
+
* Set the query result LIMIT.
|
|
367
|
+
* @param {number} value The limit value.
|
|
368
|
+
* @returns {this}
|
|
369
|
+
*/
|
|
266
370
|
limit(value) {
|
|
267
371
|
const { query } = this;
|
|
268
372
|
if (arguments.length === 0) {
|
|
@@ -273,6 +377,14 @@ export class Query {
|
|
|
273
377
|
}
|
|
274
378
|
}
|
|
275
379
|
|
|
380
|
+
/**
|
|
381
|
+
* Retrieve current OFFSET value.
|
|
382
|
+
* @returns {number|null}
|
|
383
|
+
*//**
|
|
384
|
+
* Set the query result OFFSET.
|
|
385
|
+
* @param {number} value The offset value.
|
|
386
|
+
* @returns {this}
|
|
387
|
+
*/
|
|
276
388
|
offset(value) {
|
|
277
389
|
const { query } = this;
|
|
278
390
|
if (arguments.length === 0) {
|
|
@@ -391,6 +503,7 @@ export class SetOperation {
|
|
|
391
503
|
this.op = op;
|
|
392
504
|
this.queries = queries.map(q => q.clone());
|
|
393
505
|
this.query = { orderby: [] };
|
|
506
|
+
this.cteFor = null;
|
|
394
507
|
}
|
|
395
508
|
|
|
396
509
|
clone() {
|
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
|
|
|
@@ -117,6 +163,7 @@ export const varPop = aggf('VAR_POP');
|
|
|
117
163
|
export const stddevPop = aggf('STDDEV_POP');
|
|
118
164
|
|
|
119
165
|
export const corr = aggf('CORR');
|
|
166
|
+
export const covariance = aggf('COVAR_SAMP');
|
|
120
167
|
export const covarPop = aggf('COVAR_POP');
|
|
121
168
|
export const regrIntercept = aggf('REGR_INTERCEPT');
|
|
122
169
|
export const regrSlope = aggf('REGR_SLOPE');
|
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')));
|
|
@@ -87,7 +98,7 @@ export class SQLExpression {
|
|
|
87
98
|
/**
|
|
88
99
|
* Annotate this expression instance with additional properties.
|
|
89
100
|
* @param {object[]} [props] One or more objects with properties to add.
|
|
90
|
-
* @returns
|
|
101
|
+
* @returns This SQL expression.
|
|
91
102
|
*/
|
|
92
103
|
annotate(...props) {
|
|
93
104
|
return Object.assign(this, ...props);
|
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
|
@@ -13,7 +13,7 @@ function scaleLinear() {
|
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
function scaleLog({ base } = {}) {
|
|
16
|
+
function scaleLog({ base = null } = {}) {
|
|
17
17
|
if (base == null || base === Math.E) {
|
|
18
18
|
return {
|
|
19
19
|
apply: Math.log,
|
|
@@ -78,6 +78,7 @@ function scaleTime() {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
const scales = {
|
|
81
|
+
identity: scaleLinear,
|
|
81
82
|
linear: scaleLinear,
|
|
82
83
|
log: scaleLog,
|
|
83
84
|
symlog: scaleSymlog,
|
package/src/to-sql.js
CHANGED
|
@@ -27,7 +27,7 @@ export function literalToSQL(value) {
|
|
|
27
27
|
case 'boolean':
|
|
28
28
|
return value ? 'TRUE' : 'FALSE';
|
|
29
29
|
case 'string':
|
|
30
|
-
return `'${value}'`;
|
|
30
|
+
return `'${value.replace(`'`, `''`)}'`;
|
|
31
31
|
case 'number':
|
|
32
32
|
return Number.isFinite(value) ? String(value) : 'NULL';
|
|
33
33
|
default:
|
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;
|