@uwdata/mosaic-sql 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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;
@@ -76,8 +74,7 @@ function literalToSQL(value) {
76
74
  return "NULL";
77
75
  } else if (value instanceof Date) {
78
76
  const ts = +value;
79
- if (Number.isNaN(ts))
80
- return "NULL";
77
+ if (Number.isNaN(ts)) return "NULL";
81
78
  const y2 = value.getUTCFullYear();
82
79
  const m = value.getUTCMonth();
83
80
  const d = value.getUTCDate();
@@ -98,7 +95,7 @@ function isSQLExpression(value) {
98
95
  var SQLExpression = class {
99
96
  /**
100
97
  * Create a new SQL expression instance.
101
- * @param {(string|SQLExpression|Ref)[]} parts The parts of the expression.
98
+ * @param {(string | ParamLike | SQLExpression | import('./ref.js').Ref)[]} parts The parts of the expression.
102
99
  * @param {string[]} [columns=[]] The column dependencies
103
100
  * @param {object} [props] Additional properties for this expression.
104
101
  */
@@ -290,6 +287,16 @@ var isInfinite = functionCall("ISINF");
290
287
 
291
288
  // src/windows.js
292
289
  var WindowFunction = class _WindowFunction extends SQLExpression {
290
+ /**
291
+ * Create a new WindowFunction instance.
292
+ * @param {string} op The window operation indicator.
293
+ * @param {*} func The window function expression.
294
+ * @param {*} [type] The SQL data type to cast to.
295
+ * @param {string} [name] The window definition name.
296
+ * @param {*} [group] Grouping (partition by) expressions.
297
+ * @param {*} [order] Sorting (order by) expressions.
298
+ * @param {*} [frame] The window frame definition.
299
+ */
293
300
  constructor(op, func, type, name, group = "", order = "", frame = "") {
294
301
  let expr;
295
302
  const noWindowParams = !(group || order || frame);
@@ -304,7 +311,14 @@ var WindowFunction = class _WindowFunction extends SQLExpression {
304
311
  expr = sql`(${expr})::${type}`;
305
312
  }
306
313
  const { _expr, _deps } = expr;
307
- super(_expr, _deps, { 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) {
@@ -573,12 +658,22 @@ var Query = class _Query {
573
658
  qualify: [],
574
659
  orderby: []
575
660
  };
661
+ this.cteFor = null;
576
662
  }
577
663
  clone() {
578
664
  const q = new _Query();
579
665
  q.query = { ...this.query };
580
666
  return q;
581
667
  }
668
+ /**
669
+ * Retrieve current WITH common table expressions (CTEs).
670
+ * @returns {any[]}
671
+ */
672
+ /**
673
+ * Add WITH common table expressions (CTEs).
674
+ * @param {...any} expr Expressions to add.
675
+ * @returns {this}
676
+ */
582
677
  with(...expr) {
583
678
  const { query } = this;
584
679
  if (expr.length === 0) {
@@ -604,6 +699,15 @@ var Query = class _Query {
604
699
  return this;
605
700
  }
606
701
  }
702
+ /**
703
+ * Retrieve current SELECT expressions.
704
+ * @returns {any[]}
705
+ */
706
+ /**
707
+ * Add SELECT expressions.
708
+ * @param {...any} expr Expressions to add.
709
+ * @returns {this}
710
+ */
607
711
  select(...expr) {
608
712
  const { query } = this;
609
713
  if (expr.length === 0) {
@@ -636,6 +740,15 @@ var Query = class _Query {
636
740
  this.query.distinct = !!value;
637
741
  return this;
638
742
  }
743
+ /**
744
+ * Retrieve current from expressions.
745
+ * @returns {any[]}
746
+ */
747
+ /**
748
+ * Provide table from expressions.
749
+ * @param {...any} expr
750
+ * @returns {this}
751
+ */
639
752
  from(...expr) {
640
753
  const { query } = this;
641
754
  if (expr.length === 0) {
@@ -666,6 +779,16 @@ var Query = class _Query {
666
779
  this.query.from = [];
667
780
  return this.from(...expr);
668
781
  }
782
+ /**
783
+ * Retrieve current SAMPLE settings.
784
+ * @returns {any[]}
785
+ */
786
+ /**
787
+ * Set SAMPLE settings.
788
+ * @param {number|object} value The percentage or number of rows to sample.
789
+ * @param {string} [method] The sampling method to use.
790
+ * @returns {this}
791
+ */
669
792
  sample(value, method) {
670
793
  const { query } = this;
671
794
  if (arguments.length === 0) {
@@ -679,6 +802,15 @@ var Query = class _Query {
679
802
  return this;
680
803
  }
681
804
  }
805
+ /**
806
+ * Retrieve current WHERE expressions.
807
+ * @returns {any[]}
808
+ */
809
+ /**
810
+ * Add WHERE expressions.
811
+ * @param {...any} expr Expressions to add.
812
+ * @returns {this}
813
+ */
682
814
  where(...expr) {
683
815
  const { query } = this;
684
816
  if (expr.length === 0) {
@@ -694,6 +826,15 @@ var Query = class _Query {
694
826
  this.query.where = [];
695
827
  return this.where(...expr);
696
828
  }
829
+ /**
830
+ * Retrieve current GROUP BY expressions.
831
+ * @returns {any[]}
832
+ */
833
+ /**
834
+ * Add GROUP BY expressions.
835
+ * @param {...any} expr Expressions to add.
836
+ * @returns {this}
837
+ */
697
838
  groupby(...expr) {
698
839
  const { query } = this;
699
840
  if (expr.length === 0) {
@@ -709,6 +850,15 @@ var Query = class _Query {
709
850
  this.query.groupby = [];
710
851
  return this.groupby(...expr);
711
852
  }
853
+ /**
854
+ * Retrieve current HAVING expressions.
855
+ * @returns {any[]}
856
+ */
857
+ /**
858
+ * Add HAVING expressions.
859
+ * @param {...any} expr Expressions to add.
860
+ * @returns {this}
861
+ */
712
862
  having(...expr) {
713
863
  const { query } = this;
714
864
  if (expr.length === 0) {
@@ -720,6 +870,15 @@ var Query = class _Query {
720
870
  return this;
721
871
  }
722
872
  }
873
+ /**
874
+ * Retrieve current WINDOW definitions.
875
+ * @returns {any[]}
876
+ */
877
+ /**
878
+ * Add WINDOW definitions.
879
+ * @param {...any} expr Expressions to add.
880
+ * @returns {this}
881
+ */
723
882
  window(...expr) {
724
883
  const { query } = this;
725
884
  if (expr.length === 0) {
@@ -738,6 +897,15 @@ var Query = class _Query {
738
897
  return this;
739
898
  }
740
899
  }
900
+ /**
901
+ * Retrieve current QUALIFY expressions.
902
+ * @returns {any[]}
903
+ */
904
+ /**
905
+ * Add QUALIFY expressions.
906
+ * @param {...any} expr Expressions to add.
907
+ * @returns {this}
908
+ */
741
909
  qualify(...expr) {
742
910
  const { query } = this;
743
911
  if (expr.length === 0) {
@@ -749,6 +917,15 @@ var Query = class _Query {
749
917
  return this;
750
918
  }
751
919
  }
920
+ /**
921
+ * Retrieve current ORDER BY expressions.
922
+ * @returns {any[]}
923
+ */
924
+ /**
925
+ * Add ORDER BY expressions.
926
+ * @param {...any} expr Expressions to add.
927
+ * @returns {this}
928
+ */
752
929
  orderby(...expr) {
753
930
  const { query } = this;
754
931
  if (expr.length === 0) {
@@ -760,6 +937,15 @@ var Query = class _Query {
760
937
  return this;
761
938
  }
762
939
  }
940
+ /**
941
+ * Retrieve current LIMIT value.
942
+ * @returns {number|null}
943
+ */
944
+ /**
945
+ * Set the query result LIMIT.
946
+ * @param {number} value The limit value.
947
+ * @returns {this}
948
+ */
763
949
  limit(value) {
764
950
  const { query } = this;
765
951
  if (arguments.length === 0) {
@@ -769,6 +955,15 @@ var Query = class _Query {
769
955
  return this;
770
956
  }
771
957
  }
958
+ /**
959
+ * Retrieve current OFFSET value.
960
+ * @returns {number|null}
961
+ */
962
+ /**
963
+ * Set the query result OFFSET.
964
+ * @param {number} value The offset value.
965
+ * @returns {this}
966
+ */
772
967
  offset(value) {
773
968
  const { query } = this;
774
969
  if (arguments.length === 0) {
@@ -827,8 +1022,7 @@ var Query = class _Query {
827
1022
  }
828
1023
  if (where.length) {
829
1024
  const clauses = where.map(String).filter((x2) => x2).join(" AND ");
830
- if (clauses)
831
- sql2.push(`WHERE ${clauses}`);
1025
+ if (clauses) sql2.push(`WHERE ${clauses}`);
832
1026
  }
833
1027
  if (sample) {
834
1028
  const { rows, perc, method, seed } = sample;
@@ -841,8 +1035,7 @@ var Query = class _Query {
841
1035
  }
842
1036
  if (having.length) {
843
1037
  const clauses = having.map(String).filter((x2) => x2).join(" AND ");
844
- if (clauses)
845
- sql2.push(`HAVING ${clauses}`);
1038
+ if (clauses) sql2.push(`HAVING ${clauses}`);
846
1039
  }
847
1040
  if (window.length) {
848
1041
  const windows = window.map(({ as, expr }) => `"${as}" AS (${expr})`);
@@ -850,8 +1043,7 @@ var Query = class _Query {
850
1043
  }
851
1044
  if (qualify.length) {
852
1045
  const clauses = qualify.map(String).filter((x2) => x2).join(" AND ");
853
- if (clauses)
854
- sql2.push(`QUALIFY ${clauses}`);
1046
+ if (clauses) sql2.push(`QUALIFY ${clauses}`);
855
1047
  }
856
1048
  if (orderby.length) {
857
1049
  sql2.push(`ORDER BY ${orderby.join(", ")}`);
@@ -870,6 +1062,7 @@ var SetOperation = class _SetOperation {
870
1062
  this.op = op;
871
1063
  this.queries = queries.map((q) => q.clone());
872
1064
  this.query = { orderby: [] };
1065
+ this.cteFor = null;
873
1066
  }
874
1067
  clone() {
875
1068
  const q = new _SetOperation(this.op, this.queries);
@@ -907,8 +1100,7 @@ var SetOperation = class _SetOperation {
907
1100
  }
908
1101
  get subqueries() {
909
1102
  const { queries, cteFor } = this;
910
- if (cteFor)
911
- queries.forEach((q) => q.cteFor = cteFor);
1103
+ if (cteFor) queries.forEach((q) => q.cteFor = cteFor);
912
1104
  return queries;
913
1105
  }
914
1106
  toString() {
@@ -949,7 +1141,7 @@ function scaleLinear() {
949
1141
  sqlInvert: identity
950
1142
  };
951
1143
  }
952
- function scaleLog({ base } = {}) {
1144
+ function scaleLog({ base = null } = {}) {
953
1145
  if (base == null || base === Math.E) {
954
1146
  return {
955
1147
  apply: Math.log,
@@ -1080,7 +1272,7 @@ function loadSpatial(tableName, fileName, options = {}) {
1080
1272
  const { options: opt, ...rest } = options;
1081
1273
  if (opt) {
1082
1274
  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();
1275
+ Object.assign(rest, { open_options: open.toUpperCase() });
1084
1276
  }
1085
1277
  return load("st_read", tableName, fileName, rest);
1086
1278
  }
@@ -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 ut(r){return new S(r,"*")}function lt(r){return typeof r=="string"?`"${r}"`:$(r)}function $(r){switch(typeof r){case"boolean":return r?"TRUE":"FALSE";case"string":return`'${r}'`;case"number":return Number.isFinite(r)?String(r):"NULL";default:if(r==null)return"NULL";if(r instanceof Date){let t=+r;if(Number.isNaN(t))return"NULL";let e=r.getUTCFullYear(),n=r.getUTCMonth(),o=r.getUTCDate();return t===Date.UTC(e,n,o)?`MAKE_DATE(${e}, ${n+1}, ${o})`:`EPOCH_MS(${t})`}else return r instanceof RegExp?`'${r.source}'`:String(r)}}var T=r=>typeof r?.addEventListener=="function";function _(r){return r instanceof N}var N=class{constructor(t,e,n){this._expr=Array.isArray(t)?t:[t],this._deps=e||[],this.annotate(n);let o=this._expr.filter(s=>T(s));o.length>0?(this._params=Array.from(new Set(o)),this._params.forEach(s=>{s.addEventListener("value",()=>pt(this,this.map?.get("value")))})):this.addEventListener=void 0}get value(){return this}get columns(){let{_params:t,_deps:e}=this;if(t){let n=new Set(t.flatMap(o=>{let s=o.value?.columns;return Array.isArray(s)?s:[]}));if(n.size){let o=new Set(e);return n.forEach(s=>o.add(s)),Array.from(o)}}return e}get column(){return this._deps.length?this._deps[0]:this.columns[0]}annotate(...t){return Object.assign(this,...t)}toString(){return this._expr.map(t=>T(t)&&!_(t)?$(t.value):t).join("")}addEventListener(t,e){let n=this.map||(this.map=new Map);(n.get(t)||(n.set(t,new Set),n.get(t))).add(e)}};function pt(r,t){if(t?.size)return Promise.allSettled(Array.from(t,e=>e(r)))}function W(r,t){let e=[r[0]],n=new Set,o=t.length;for(let s=0,i=0;s<o;){let a=t[s];T(a)?e[++i]=a:(Array.isArray(a?.columns)&&a.columns.forEach(d=>n.add(d)),e[i]+=typeof a=="string"?a:$(a));let p=r[++s];T(e[i])?e[++i]=p:e[i]+=p}return{spans:e,cols:Array.from(n)}}function c(r,...t){let{spans:e,cols:n}=W(r,t);return new N(e,n)}function ft(r){let t=u(r);return c`${t} DESC NULLS LAST`.annotate({label:t?.label,desc:!0})}var ht=r=>({value:r,toString:()=>$(r)});function D(r){r(this.op,this),this.children?.forEach(t=>t.visit(r))}function z(r,t){let e=t.filter(o=>o!=null).map(u),n=e.map((o,s)=>s?` ${r} `:"");return e.length===1?n.push(""):e.length>1&&(n[0]="(",n.push(")")),c(n,...e).annotate({op:r,children:e,visit:D})}var mt=(...r)=>z("AND",r.flat()),gt=(...r)=>z("OR",r.flat()),dt=r=>t=>c`(${r} ${u(t)})`.annotate({op:r,a:t,visit:D}),xt=dt("NOT"),J=r=>t=>c`(${u(t)} ${r})`.annotate({op:r,a:t,visit:D}),$t=J("IS NULL"),Et=J("IS NOT NULL"),w=r=>(t,e)=>c`(${u(t)} ${r} ${u(e)})`.annotate({op:r,a:t,b:e,visit:D}),yt=w("="),St=w("<>"),Nt=w("<"),wt=w(">"),At=w("<="),Tt=w(">="),Rt=w("IS DISTINCT FROM"),qt=w("IS NOT DISTINCT FROM");function Z(r,t,e,n){t=u(t);let o=r.startsWith("NOT ")?"NOT ":"";return(e?n?c`${o}(${e[0]} <= ${t} AND ${t} < ${e[1]})`:c`(${t} ${r} ${e[0]} AND ${e[1]})`:c``).annotate({op:r,visit:D,field:t,range:e})}var bt=(r,t,e)=>Z("BETWEEN",r,t,e),It=(r,t,e)=>Z("NOT BETWEEN",r,t,e);function R(r,t){return Array.from({length:r},()=>t)}function m(r,t){return(...e)=>{let n=e.map(u),o=t?`::${t}`:"";return(n.length?c([`${r}(`,...R(n.length-1,", "),`)${o}`],...n):c`${r}()${o}`).annotate({func:r,args:n})}}var Lt=m("REGEXP_MATCHES"),Ot=m("CONTAINS"),Dt=m("PREFIX"),Ct=m("SUFFIX"),Mt=m("LOWER"),_t=m("UPPER"),Pt=m("LENGTH"),Ft=m("ISNAN"),Gt=m("ISFINITE"),jt=m("ISINF");var C=class r extends N{constructor(t,e,n,o,s="",i="",a=""){let p;if(o&&!(s||i||a))p=o?c`${e} OVER "${o}"`:c`${e} OVER ()`;else{let b=s&&i?" ":"",I=(s||i)&&a?" ":"";p=c`${e} OVER (${o?`"${o}" `:""}${s}${b}${i}${I}${a})`}n&&(p=c`(${p})::${n}`);let{_expr:y,_deps:A}=p;super(y,A),this.window=t,this.func=e,this.type=n,this.name=o,this.group=s,this.order=i,this.frame=a}get basis(){return this.column}get label(){let{func:t}=this;return t.label??t.toString()}over(t){let{window:e,func:n,type:o,group:s,order:i,frame:a}=this;return new r(e,n,o,t,s,i,a)}partitionby(...t){let e=t.flat().filter(y=>y).map(u),n=c(["PARTITION BY ",R(e.length-1,", "),""],...e),{window:o,func:s,type:i,name:a,order:p,frame:d}=this;return new r(o,s,i,a,n,p,d)}orderby(...t){let e=t.flat().filter(y=>y).map(u),n=c(["ORDER BY ",R(e.length-1,", "),""],...e),{window:o,func:s,type:i,name:a,group:p,frame:d}=this;return new r(o,s,i,a,p,n,d)}rows(t){let e=tt("ROWS",t),{window:n,func:o,type:s,name:i,group:a,order:p}=this;return new r(n,o,s,i,a,p,e)}range(t){let e=tt("RANGE",t),{window:n,func:o,type:s,name:i,group:a,order:p}=this;return new r(n,o,s,i,a,p,e)}};function tt(r,t){if(T(t)){let e=c`${t}`;return e.toString=()=>`${r} ${et(t.value)}`,e}return`${r} ${et(t)}`}function et(r){let[t,e]=r,n=t===0?"CURRENT ROW":Number.isFinite(t)?`${Math.abs(t)} PRECEDING`:"UNBOUNDED PRECEDING",o=e===0?"CURRENT ROW":Number.isFinite(e)?`${Math.abs(e)} FOLLOWING`:"UNBOUNDED FOLLOWING";return`BETWEEN ${n} AND ${o}`}function E(r,t){return(...e)=>{let n=m(r)(...e);return new C(r,n,t)}}var Ut=E("ROW_NUMBER","INTEGER"),Wt=E("RANK","INTEGER"),Yt=E("DENSE_RANK","INTEGER"),Bt=E("PERCENT_RANK"),Xt=E("CUME_DIST"),vt=E("NTILE"),Qt=E("LAG"),Vt=E("LEAD"),kt=E("FIRST_VALUE"),Ht=E("LAST_VALUE"),Kt=E("NTH_VALUE");function zt(r,...t){return c(r,...t).annotate({aggregate:!0})}var Y=class r extends N{constructor(t,e,n,o,s){e=(e||[]).map(u);let{strings:i,exprs:a}=Jt(t,e,n,o,s),{spans:p,cols:d}=W(i,a);super(p,d),this.aggregate=t,this.args=e,this.type=n,this.isDistinct=o,this.filter=s}get basis(){return this.column}get label(){let{aggregate:t,args:e,isDistinct:n}=this,o=n?"DISTINCT"+(e.length?" ":""):"",s=e.length?`(${o}${e.map(Zt).join(", ")})`:"";return`${t.toLowerCase()}${s}`}distinct(){let{aggregate:t,args:e,type:n,filter:o}=this;return new r(t,e,n,!0,o)}where(t){let{aggregate:e,args:n,type:o,isDistinct:s}=this;return new r(e,n,o,s,t)}window(){let{aggregate:t,args:e,type:n,isDistinct:o}=this,s=new r(t,e,null,o);return new C(t,s,n)}partitionby(...t){return this.window().partitionby(...t)}orderby(...t){return this.window().orderby(...t)}rows(t){return this.window().rows(t)}range(t){return this.window().range(t)}};function Jt(r,t,e,n,o){let s=`)${e?`::${e}`:""}`,i=[`${r}(${n?"DISTINCT ":""}`],a=[];return t.length?(i=i.concat([...R(t.length-1,", "),`${s}${o?" FILTER (WHERE ":""}`,...o?[")"]:[]]),a=[...t,...o?[o]:[]]):i[0]+="*"+s,{exprs:a,strings:i}}function Zt(r){let t=$(r);return t&&t.startsWith('"')&&t.endsWith('"')?t.slice(1,-1):t}function l(r,t){return(...e)=>new Y(r,e,t)}var te=l("COUNT","INTEGER"),ee=l("AVG"),re=l("AVG"),ne=l("MAD"),oe=l("MAX"),se=l("MIN"),ie=l("SUM","DOUBLE"),ce=l("PRODUCT"),ae=l("MEDIAN"),ue=l("QUANTILE"),le=l("MODE"),pe=l("VARIANCE"),fe=l("STDDEV"),he=l("SKEWNESS"),me=l("KURTOSIS"),ge=l("ENTROPY"),de=l("VAR_POP"),xe=l("STDDEV_POP"),$e=l("CORR"),Ee=l("COVAR_POP"),ye=l("REGR_INTERCEPT"),Se=l("REGR_SLOPE"),Ne=l("REGR_COUNT"),we=l("REGR_R2"),Ae=l("REGR_SYY"),Te=l("REGR_SXX"),Re=l("REGR_SXY"),qe=l("REGR_AVGX"),be=l("REGR_AVGY"),Ie=l("FIRST"),Le=l("LAST"),Oe=l("ARG_MIN"),De=l("ARG_MAX"),Ce=l("STRING_AGG"),Me=l("ARRAY_AGG");function B(r,t){let e=u(r),n=c`CAST(${e} AS ${t})`;return Object.defineProperty(n,"label",{enumerable:!0,get(){return r.label}}),Object.defineProperty(n,"aggregate",{enumerable:!0,get(){return r.aggregate||!1}}),n}var _e=r=>B(r,"DOUBLE"),Pe=r=>B(r,"INTEGER");var X=r=>c`epoch_ms(${u(r)})`,Fe=r=>{let t=u(r);return c`MAKE_DATE(2012, MONTH(${t}), 1)`.annotate({label:"month"})},Ge=r=>{let t=u(r);return c`MAKE_DATE(2012, MONTH(${t}), DAY(${t}))`.annotate({label:"date"})},je=r=>{let t=u(r);return c`MAKE_DATE(2012, 1, DAY(${t}))`.annotate({label:"date"})};var Ue=m("ST_AsGeoJSON"),rt=m("ST_X"),nt=m("ST_Y"),v=m("ST_CENTROID"),We=r=>rt(v(r)),Ye=r=>nt(v(r));var F=class r{static select(...t){return new r().select(...t)}static from(...t){return new r().from(...t)}static with(...t){return new r().with(...t)}static union(...t){return new q("UNION",t.flat())}static unionAll(...t){return new q("UNION ALL",t.flat())}static intersect(...t){return new q("INTERSECT",t.flat())}static except(...t){return new q("EXCEPT",t.flat())}static describe(t){let e=t.clone(),{clone:n,toString:o}=e;return Object.assign(e,{describe:!0,clone:()=>r.describe(n.call(e)),toString:()=>`DESCRIBE ${o.call(e)}`})}constructor(){this.query={with:[],select:[],from:[],where:[],groupby:[],having:[],window:[],qualify:[],orderby:[]},this.cteFor=null}clone(){let t=new r;return t.query={...this.query},t}with(...t){let{query:e}=this;if(t.length===0)return e.with;{let n=[],o=(s,i)=>{let a=i.clone();a.cteFor=this,n.push({as:s,query:a})};return t.flat().forEach(s=>{if(s!=null)if(s.as&&s.query)o(s.as,s.query);else for(let i in s)o(i,s[i])}),e.with=e.with.concat(n),this}}select(...t){let{query:e}=this;if(t.length===0)return e.select;{let n=[];for(let o of t.flat())if(o!=null)if(typeof o=="string")n.push({as:o,expr:u(o)});else if(o instanceof S)n.push({as:o.column,expr:o});else if(Array.isArray(o))n.push({as:o[0],expr:o[1]});else for(let s in o)n.push({as:P(s),expr:u(o[s])});return e.select=e.select.concat(n),this}}$select(...t){return this.query.select=[],this.select(...t)}distinct(t=!0){return this.query.distinct=!!t,this}from(...t){let{query:e}=this;if(t.length===0)return e.from;{let n=[];return t.flat().forEach(o=>{if(o!=null)if(typeof o=="string")n.push({as:o,from:O(o)});else if(o instanceof S)n.push({as:o.table,from:o});else if(M(o)||_(o))n.push({from:o});else if(Array.isArray(o))n.push({as:P(o[0]),from:O(o[1])});else for(let s in o)n.push({as:P(s),from:O(o[s])})}),e.from=e.from.concat(n),this}}$from(...t){return this.query.from=[],this.from(...t)}sample(t,e){let{query:n}=this;if(arguments.length===0)return n.sample;{let o=t;return typeof t=="number"&&(o=t>0&&t<1?{perc:100*t,method:e}:{rows:Math.round(t),method:e}),n.sample=o,this}}where(...t){let{query:e}=this;return t.length===0?e.where:(e.where=e.where.concat(t.flat().filter(n=>n)),this)}$where(...t){return this.query.where=[],this.where(...t)}groupby(...t){let{query:e}=this;return t.length===0?e.groupby:(e.groupby=e.groupby.concat(t.flat().filter(n=>n).map(u)),this)}$groupby(...t){return this.query.groupby=[],this.groupby(...t)}having(...t){let{query:e}=this;return t.length===0?e.having:(e.having=e.having.concat(t.flat().filter(n=>n)),this)}window(...t){let{query:e}=this;if(t.length===0)return e.window;{let n=[];return t.flat().forEach(o=>{if(o!=null)for(let s in o)n.push({as:P(s),expr:o[s]})}),e.window=e.window.concat(n),this}}qualify(...t){let{query:e}=this;return t.length===0?e.qualify:(e.qualify=e.qualify.concat(t.flat().filter(n=>n)),this)}orderby(...t){let{query:e}=this;return t.length===0?e.orderby:(e.orderby=e.orderby.concat(t.flat().filter(n=>n).map(u)),this)}limit(t){let{query:e}=this;return arguments.length===0?e.limit:(e.limit=Number.isFinite(t)?t:void 0,this)}offset(t){let{query:e}=this;return arguments.length===0?e.offset:(e.offset=Number.isFinite(t)?t:void 0,this)}get subqueries(){let{query:t,cteFor:e}=this,o=(e?.query||t).with?.reduce((i,{as:a,query:p})=>(i[a]=p,i),{}),s=[];return t.from.forEach(({from:i})=>{if(M(i))s.push(i);else if(o[i.table]){let a=o[i.table];s.push(a)}}),s}toString(){let{with:t,select:e,distinct:n,from:o,sample:s,where:i,groupby:a,having:p,window:d,qualify:y,orderby:A,limit:b,offset:I}=this.query,g=[];if(t.length){let f=t.map(({as:h,query:x})=>`"${h}" AS (${x})`);g.push(`WITH ${f.join(", ")}`)}let it=e.map(({as:f,expr:h})=>k(h,f)&&!h.table?`${h}`:`${h} AS "${f}"`);if(g.push(`SELECT${n?" DISTINCT":""} ${it.join(", ")}`),o.length){let f=o.map(({as:h,from:x})=>{let L=M(x)?`(${x})`:`${x}`;return!h||h===x.table?L:`${L} AS "${h}"`});g.push(`FROM ${f.join(", ")}`)}if(i.length){let f=i.map(String).filter(h=>h).join(" AND ");f&&g.push(`WHERE ${f}`)}if(s){let{rows:f,perc:h,method:x,seed:L}=s,ct=f?`${f} ROWS`:`${h} PERCENT`,at=x?` (${x}${L!=null?`, ${L}`:""})`:"";g.push(`USING SAMPLE ${ct}${at}`)}if(a.length&&g.push(`GROUP BY ${a.join(", ")}`),p.length){let f=p.map(String).filter(h=>h).join(" AND ");f&&g.push(`HAVING ${f}`)}if(d.length){let f=d.map(({as:h,expr:x})=>`"${h}" AS (${x})`);g.push(`WINDOW ${f.join(", ")}`)}if(y.length){let f=y.map(String).filter(h=>h).join(" AND ");f&&g.push(`QUALIFY ${f}`)}return A.length&&g.push(`ORDER BY ${A.join(", ")}`),Number.isFinite(b)&&g.push(`LIMIT ${b}`),Number.isFinite(I)&&g.push(`OFFSET ${I}`),g.join(" ")}},q=class r{constructor(t,e){this.op=t,this.queries=e.map(n=>n.clone()),this.query={orderby:[]},this.cteFor=null}clone(){let t=new r(this.op,this.queries);return t.query={...this.query},t}orderby(...t){let{query:e}=this;return t.length===0?e.orderby:(e.orderby=e.orderby.concat(t.flat().filter(n=>n).map(u)),this)}limit(t){let{query:e}=this;return arguments.length===0?e.limit:(e.limit=Number.isFinite(t)?t:void 0,this)}offset(t){let{query:e}=this;return arguments.length===0?e.offset:(e.offset=Number.isFinite(t)?t:void 0,this)}get subqueries(){let{queries:t,cteFor:e}=this;return e&&t.forEach(n=>n.cteFor=e),t}toString(){let{op:t,queries:e,query:{orderby:n,limit:o,offset:s}}=this,i=[e.join(` ${t} `)];return n.length&&i.push(`ORDER BY ${n.join(", ")}`),Number.isFinite(o)&&i.push(`LIMIT ${o}`),Number.isFinite(s)&&i.push(`OFFSET ${s}`),i.join(" ")}};function M(r){return r instanceof F||r instanceof q}function Be(r){return M(r)&&r.describe}function P(r){return Xe(r)?r.slice(1,-1):r}function Xe(r){return r[0]==='"'&&r[r.length-1]==='"'}var G=r=>r;function ve(){return{apply:G,invert:G,sqlApply:u,sqlInvert:G}}function Qe({base:r=null}={}){if(r==null||r===Math.E)return{apply:Math.log,invert:Math.exp,sqlApply:t=>c`LN(${u(t)})`,sqlInvert:t=>c`EXP(${t})`};if(r===10)return{apply:Math.log10,invert:t=>Math.pow(10,t),sqlApply:t=>c`LOG(${u(t)})`,sqlInvert:t=>c`POW(10, ${t})`};{let t=+r;return{apply:e=>Math.log(e)/Math.log(t),invert:e=>Math.pow(t,e),sqlApply:e=>c`LN(${u(e)}) / LN(${t})`,sqlInvert:e=>c`POW(${t}, ${e})`}}}function Ve({constant:r=1}={}){let t=+r;return{apply:e=>Math.sign(e)*Math.log1p(Math.abs(e)),invert:e=>Math.sign(e)*Math.exp(Math.abs(e)-t),sqlApply:e=>(e=u(e),c`SIGN(${e}) * LN(${t} + ABS(${e}))`),sqlInvert:e=>c`SIGN(${e}) * (EXP(ABS(${e})) - ${t})`}}function ke(){return{apply:r=>Math.sign(r)*Math.sqrt(Math.abs(r)),invert:r=>Math.sign(r)*r*r,sqlApply:r=>(r=u(r),c`SIGN(${r}) * SQRT(ABS(${r}))`),sqlInvert:r=>c`SIGN(${r}) * (${r}) ** 2`}}function He({exponent:r=1}={}){let t=+r;return{apply:e=>Math.sign(e)*Math.pow(Math.abs(e),t),invert:e=>Math.sign(e)*Math.pow(Math.abs(e),1/t),sqlApply:e=>(e=u(e),c`SIGN(${e}) * POW(ABS(${e}), ${t})`),sqlInvert:e=>c`SIGN(${e}) * POW(ABS(${e}), 1/${t})`}}function ot(){return{apply:r=>+r,invert:r=>new Date(r),sqlApply:r=>r instanceof Date?+r:X(u(r)),sqlInvert:G}}var Ke={linear:ve,log:Qe,symlog:Ve,sqrt:ke,pow:He,time:ot,utc:ot};function ze(r){let t=Ke[r.type];return t?{...r,...t(r)}:null}function j(r,t,{replace:e=!1,temp:n=!0,view:o=!1}={}){return"CREATE"+(e?" OR REPLACE ":" ")+(n?"TEMP ":"")+(o?"VIEW":"TABLE")+(e?" ":" IF NOT EXISTS ")+r+" AS "+t}function Je(r){return`INSTALL ${r}; LOAD ${r}`}function st(r,{columns:t=Object.keys(r?.[0]||{})}={}){let e=[];if(Array.isArray(t)?(e=t,t=e.reduce((o,s)=>(o[s]=s,o),{})):t&&(e=Object.keys(t)),!e.length)throw new Error("Can not create table from empty column set.");let n=[];for(let o of r){let s=e.map(i=>`${$(o[i])} AS "${t[i]}"`);n.push(`(SELECT ${s.join(", ")})`)}return n.join(" UNION ALL ")}function U(r,t,e,n={},o={}){let{select:s=["*"],where:i,view:a,temp:p,replace:d,...y}=n,A=or({...o,...y}),b=`${r}('${e}'${A?", "+A:""})`,I=i?` WHERE ${i}`:"",g=`SELECT ${s.join(", ")} FROM ${b}${I}`;return j(t,g,{view:a,temp:p,replace:d})}function Ze(r,t,e){return U("read_csv",r,t,e,{auto_detect:!0,sample_size:-1})}function tr(r,t,e){return U("read_json",r,t,e,{auto_detect:!0,json_format:"auto"})}function er(r,t,e){return U("read_parquet",r,t,e)}function rr(r,t,e={}){let{options:n,...o}=e;if(n){let s=Array.isArray(n)?n.join(", "):typeof n=="string"?n:Object.entries(n).map(([i,a])=>`${i}=${a}`).join(", ");Object.assign(o,{open_options:s.toUpperCase()})}return U("st_read",r,t,o)}function nr(r,t,e={}){let{select:n=["*"],...o}=e,s=st(t),i=n.length===1&&n[0]==="*"?s:`SELECT ${n} FROM ${s}`;return j(r,i,o)}function or(r){return Object.entries(r).map(([t,e])=>`${t}=${Q(e)}`).join(", ")}function Q(r){switch(typeof r){case"boolean":return String(r);case"string":return`'${r}'`;case"undefined":case"object":return r==null?"NULL":Array.isArray(r)?"["+r.map(t=>Q(t)).join(", ")+"]":"{"+Object.entries(r).map(([t,e])=>`'${t}': ${Q(e)}`).join(", ")+"}";default:return r}}export{F as Query,S as Ref,zt as agg,ut as all,mt as and,De as argmax,Oe as argmin,Me as arrayAgg,u as asColumn,O as asRelation,ee as avg,B as cast,_e as castDouble,Pe as castInteger,v as centroid,We as centroidX,Ye as centroidY,K as column,Ot as contains,$e as corr,te as count,Ee as covarPop,j as create,Xt as cume_dist,je as dateDay,Fe as dateMonth,Ge as dateMonthDay,Yt as dense_rank,ft as desc,ge as entropy,X as epoch_ms,yt as eq,Ie as first,kt as first_value,Ue as geojson,wt as gt,Tt as gte,bt as isBetween,Be as isDescribeQuery,Rt as isDistinct,Gt as isFinite,jt as isInfinite,Ft as isNaN,It as isNotBetween,qt as isNotDistinct,Et as isNotNull,$t as isNull,T as isParamLike,M as isQuery,_ as isSQLExpression,me as kurtosis,Qt as lag,Le as last,Ht as last_value,Vt as lead,Pt as length,ht as literal,$ as literalToSQL,Ze as loadCSV,Je as loadExtension,tr as loadJSON,nr as loadObjects,er as loadParquet,rr as loadSpatial,Mt as lower,Nt as lt,At as lte,ne as mad,oe as max,re as mean,ae as median,se as min,le as mode,St as neq,xt as not,Kt as nth_value,vt as ntile,gt as or,Bt as percent_rank,Dt as prefix,ce as product,ue as quantile,Wt as rank,Lt as regexp_matches,qe as regrAvgX,be as regrAvgY,Ne as regrCount,ye as regrIntercept,we as regrR2,Te as regrSXX,Re as regrSXY,Ae as regrSYY,Se as regrSlope,H as relation,Ut as row_number,ze as scaleTransform,he as skewness,c as sql,fe as stddev,xe as stddevPop,Ce as stringAgg,Ct as suffix,ie as sum,lt as toSQL,_t as upper,de as varPop,pe as variance,rt as x,nt as y};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uwdata/mosaic-sql",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "SQL query construction and analysis.",
5
5
  "keywords": [
6
6
  "sql",
@@ -21,9 +21,9 @@
21
21
  "scripts": {
22
22
  "prebuild": "rimraf dist && mkdir dist",
23
23
  "build": "node ../../esbuild.js mosaic-sql",
24
- "lint": "eslint src test --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": "a24b4c9f7dfa1c38c6af96ec17e075326c1af9b0"
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 = [];
@@ -124,9 +143,18 @@ export class Query {
124
143
  return this;
125
144
  }
126
145
 
146
+ /**
147
+ * Retrieve current from expressions.
148
+ * @returns {any[]}
149
+ *//**
150
+ * Provide table from expressions.
151
+ * @param {...any} expr
152
+ * @returns {this}
153
+ */
127
154
  from(...expr) {
128
155
  const { query } = this;
129
156
  if (expr.length === 0) {
157
+ // @ts-ignore
130
158
  return query.from;
131
159
  } else {
132
160
  const list = [];
@@ -157,9 +185,19 @@ export class Query {
157
185
  return this.from(...expr);
158
186
  }
159
187
 
188
+ /**
189
+ * Retrieve current SAMPLE settings.
190
+ * @returns {any[]}
191
+ *//**
192
+ * Set SAMPLE settings.
193
+ * @param {number|object} value The percentage or number of rows to sample.
194
+ * @param {string} [method] The sampling method to use.
195
+ * @returns {this}
196
+ */
160
197
  sample(value, method) {
161
198
  const { query } = this;
162
199
  if (arguments.length === 0) {
200
+ // @ts-ignore
163
201
  return query.sample;
164
202
  } else {
165
203
  let spec = value;
@@ -173,9 +211,18 @@ export class Query {
173
211
  }
174
212
  }
175
213
 
214
+ /**
215
+ * Retrieve current WHERE expressions.
216
+ * @returns {any[]}
217
+ *//**
218
+ * Add WHERE expressions.
219
+ * @param {...any} expr Expressions to add.
220
+ * @returns {this}
221
+ */
176
222
  where(...expr) {
177
223
  const { query } = this;
178
224
  if (expr.length === 0) {
225
+ // @ts-ignore
179
226
  return query.where;
180
227
  } else {
181
228
  query.where = query.where.concat(
@@ -190,9 +237,18 @@ export class Query {
190
237
  return this.where(...expr);
191
238
  }
192
239
 
240
+ /**
241
+ * Retrieve current GROUP BY expressions.
242
+ * @returns {any[]}
243
+ *//**
244
+ * Add GROUP BY expressions.
245
+ * @param {...any} expr Expressions to add.
246
+ * @returns {this}
247
+ */
193
248
  groupby(...expr) {
194
249
  const { query } = this;
195
250
  if (expr.length === 0) {
251
+ // @ts-ignore
196
252
  return query.groupby;
197
253
  } else {
198
254
  query.groupby = query.groupby.concat(
@@ -207,9 +263,18 @@ export class Query {
207
263
  return this.groupby(...expr);
208
264
  }
209
265
 
266
+ /**
267
+ * Retrieve current HAVING expressions.
268
+ * @returns {any[]}
269
+ *//**
270
+ * Add HAVING expressions.
271
+ * @param {...any} expr Expressions to add.
272
+ * @returns {this}
273
+ */
210
274
  having(...expr) {
211
275
  const { query } = this;
212
276
  if (expr.length === 0) {
277
+ // @ts-ignore
213
278
  return query.having;
214
279
  } else {
215
280
  query.having = query.having.concat(
@@ -219,9 +284,18 @@ export class Query {
219
284
  }
220
285
  }
221
286
 
287
+ /**
288
+ * Retrieve current WINDOW definitions.
289
+ * @returns {any[]}
290
+ *//**
291
+ * Add WINDOW definitions.
292
+ * @param {...any} expr Expressions to add.
293
+ * @returns {this}
294
+ */
222
295
  window(...expr) {
223
296
  const { query } = this;
224
297
  if (expr.length === 0) {
298
+ // @ts-ignore
225
299
  return query.window;
226
300
  } else {
227
301
  const list = [];
@@ -239,9 +313,18 @@ export class Query {
239
313
  }
240
314
  }
241
315
 
316
+ /**
317
+ * Retrieve current QUALIFY expressions.
318
+ * @returns {any[]}
319
+ *//**
320
+ * Add QUALIFY expressions.
321
+ * @param {...any} expr Expressions to add.
322
+ * @returns {this}
323
+ */
242
324
  qualify(...expr) {
243
325
  const { query } = this;
244
326
  if (expr.length === 0) {
327
+ // @ts-ignore
245
328
  return query.qualify;
246
329
  } else {
247
330
  query.qualify = query.qualify.concat(
@@ -251,9 +334,18 @@ export class Query {
251
334
  }
252
335
  }
253
336
 
337
+ /**
338
+ * Retrieve current ORDER BY expressions.
339
+ * @returns {any[]}
340
+ *//**
341
+ * Add ORDER BY expressions.
342
+ * @param {...any} expr Expressions to add.
343
+ * @returns {this}
344
+ */
254
345
  orderby(...expr) {
255
346
  const { query } = this;
256
347
  if (expr.length === 0) {
348
+ // @ts-ignore
257
349
  return query.orderby;
258
350
  } else {
259
351
  query.orderby = query.orderby.concat(
@@ -263,6 +355,14 @@ export class Query {
263
355
  }
264
356
  }
265
357
 
358
+ /**
359
+ * Retrieve current LIMIT value.
360
+ * @returns {number|null}
361
+ *//**
362
+ * Set the query result LIMIT.
363
+ * @param {number} value The limit value.
364
+ * @returns {this}
365
+ */
266
366
  limit(value) {
267
367
  const { query } = this;
268
368
  if (arguments.length === 0) {
@@ -273,6 +373,14 @@ export class Query {
273
373
  }
274
374
  }
275
375
 
376
+ /**
377
+ * Retrieve current OFFSET value.
378
+ * @returns {number|null}
379
+ *//**
380
+ * Set the query result OFFSET.
381
+ * @param {number} value The offset value.
382
+ * @returns {this}
383
+ */
276
384
  offset(value) {
277
385
  const { query } = this;
278
386
  if (arguments.length === 0) {
@@ -391,6 +499,7 @@ export class SetOperation {
391
499
  this.op = op;
392
500
  this.queries = queries.map(q => q.clone());
393
501
  this.query = { orderby: [] };
502
+ this.cteFor = null;
394
503
  }
395
504
 
396
505
  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
 
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')));
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,
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;