@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.
@@ -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
- this.table = String(table);
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 {this} This SQL expression.
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, { window: op, func, type, name, group, order, frame });
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, { aggregate: op, args, type, isDistinct: isDistinct2, filter });
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
- rows(prev, next) {
421
- return this.window().rows(prev, next);
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
- range(prev, next) {
424
- return this.window().range(prev, next);
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
- query.select = query.select.concat(list);
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.open_options = open.toUpperCase();
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,
@@ -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.7.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 --ext .js",
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": "4680b922f15579b7b527f31507ed71a12230ec35"
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
- query.select = query.select.concat(list);
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, { aggregate: op, args, type, isDistinct, filter });
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
- rows(prev, next) {
65
- return this.window().rows(prev, next);
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
- range(prev, next) {
69
- return this.window().range(prev, next);
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 {boolean} True if value is a SQL expression, false otherwise.
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 {this} This SQL expression.
101
+ * @returns This SQL expression.
91
102
  */
92
103
  annotate(...props) {
93
104
  return Object.assign(this, ...props);
package/src/index.js CHANGED
@@ -10,7 +10,8 @@ export {
10
10
  export {
11
11
  isSQLExpression,
12
12
  isParamLike,
13
- sql
13
+ sql,
14
+ SQLExpression
14
15
  } from './expression.js';
15
16
 
16
17
  export {
@@ -47,6 +48,7 @@ export {
47
48
  avg,
48
49
  corr,
49
50
  count,
51
+ covariance,
50
52
  covarPop,
51
53
  entropy,
52
54
  first,
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.open_options = open.toUpperCase();
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
@@ -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} [table] The table name (optional).
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, { window: op, func, type, name, group, order, frame });
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;