@uwdata/mosaic-sql 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,5 @@
1
1
  # mosaic-sql
2
2
 
3
3
  An API for convenient construction and analysis of SQL queries. Query objects then coerce to SQL query strings.
4
+
5
+ Many `mosaic-sql` utilities are included as part of the [vgplot](https://github.com/uwdata/mosaic/tree/main/packages/vgplot) API.
@@ -78,10 +78,10 @@ function literalToSQL(value) {
78
78
  const ts = +value;
79
79
  if (Number.isNaN(ts))
80
80
  return "NULL";
81
- const y = value.getUTCFullYear();
81
+ const y2 = value.getUTCFullYear();
82
82
  const m = value.getUTCMonth();
83
83
  const d = value.getUTCDate();
84
- return ts === Date.UTC(y, m, d) ? `MAKE_DATE(${y}, ${m + 1}, ${d})` : `EPOCH_MS(${ts})`;
84
+ return ts === Date.UTC(y2, m, d) ? `MAKE_DATE(${y2}, ${m + 1}, ${d})` : `EPOCH_MS(${ts})`;
85
85
  } else if (value instanceof RegExp) {
86
86
  return `'${value.source}'`;
87
87
  } else {
@@ -228,7 +228,7 @@ function visit(callback) {
228
228
  this.children?.forEach((v) => v.visit(callback));
229
229
  }
230
230
  function logical(op, clauses) {
231
- const children = clauses.filter((x) => x != null).map(asColumn);
231
+ const children = clauses.filter((x2) => x2 != null).map(asColumn);
232
232
  const strings = children.map((c, i) => i ? ` ${op} ` : "");
233
233
  if (children.length === 1) {
234
234
  strings.push("");
@@ -318,7 +318,7 @@ var WindowFunction = class _WindowFunction extends SQLExpression {
318
318
  return new _WindowFunction(op, func, type, name, group, order, frame);
319
319
  }
320
320
  partitionby(...expr) {
321
- const exprs = expr.flat().filter((x) => x).map(asColumn);
321
+ const exprs = expr.flat().filter((x2) => x2).map(asColumn);
322
322
  const group = sql(
323
323
  ["PARTITION BY ", repeat(exprs.length - 1, ", "), ""],
324
324
  ...exprs
@@ -327,7 +327,7 @@ var WindowFunction = class _WindowFunction extends SQLExpression {
327
327
  return new _WindowFunction(op, func, type, name, group, order, frame);
328
328
  }
329
329
  orderby(...expr) {
330
- const exprs = expr.flat().filter((x) => x).map(asColumn);
330
+ const exprs = expr.flat().filter((x2) => x2).map(asColumn);
331
331
  const order = sql(
332
332
  ["ORDER BY ", repeat(exprs.length - 1, ", "), ""],
333
333
  ...exprs
@@ -506,8 +506,7 @@ var castInteger = (expr) => cast(expr, "INTEGER");
506
506
 
507
507
  // src/datetime.js
508
508
  var epoch_ms = (expr) => {
509
- const d = asColumn(expr);
510
- return sql`(1000 * (epoch(${d}) - second(${d})) + millisecond(${d}))::DOUBLE`;
509
+ return sql`epoch_ms(${asColumn(expr)})`;
511
510
  };
512
511
  var dateMonth = (expr) => {
513
512
  const d = asColumn(expr);
@@ -522,6 +521,14 @@ var dateDay = (expr) => {
522
521
  return sql`MAKE_DATE(2012, 1, DAY(${d}))`.annotate({ label: "date" });
523
522
  };
524
523
 
524
+ // src/spatial.js
525
+ var geojson = functionCall("ST_AsGeoJSON");
526
+ var x = functionCall("ST_X");
527
+ var y = functionCall("ST_Y");
528
+ var centroid = functionCall("ST_CENTROID");
529
+ var centroidX = (geom) => x(centroid(geom));
530
+ var centroidY = (geom) => y(centroid(geom));
531
+
525
532
  // src/Query.js
526
533
  var Query = class _Query {
527
534
  static select(...expr) {
@@ -669,7 +676,7 @@ var Query = class _Query {
669
676
  return query.where;
670
677
  } else {
671
678
  query.where = query.where.concat(
672
- expr.flat().filter((x) => x)
679
+ expr.flat().filter((x2) => x2)
673
680
  );
674
681
  return this;
675
682
  }
@@ -684,7 +691,7 @@ var Query = class _Query {
684
691
  return query.groupby;
685
692
  } else {
686
693
  query.groupby = query.groupby.concat(
687
- expr.flat().filter((x) => x).map(asColumn)
694
+ expr.flat().filter((x2) => x2).map(asColumn)
688
695
  );
689
696
  return this;
690
697
  }
@@ -699,7 +706,7 @@ var Query = class _Query {
699
706
  return query.having;
700
707
  } else {
701
708
  query.having = query.having.concat(
702
- expr.flat().filter((x) => x)
709
+ expr.flat().filter((x2) => x2)
703
710
  );
704
711
  return this;
705
712
  }
@@ -728,7 +735,7 @@ var Query = class _Query {
728
735
  return query.qualify;
729
736
  } else {
730
737
  query.qualify = query.qualify.concat(
731
- expr.flat().filter((x) => x)
738
+ expr.flat().filter((x2) => x2)
732
739
  );
733
740
  return this;
734
741
  }
@@ -739,7 +746,7 @@ var Query = class _Query {
739
746
  return query.orderby;
740
747
  } else {
741
748
  query.orderby = query.orderby.concat(
742
- expr.flat().filter((x) => x).map(asColumn)
749
+ expr.flat().filter((x2) => x2).map(asColumn)
743
750
  );
744
751
  return this;
745
752
  }
@@ -810,7 +817,7 @@ var Query = class _Query {
810
817
  sql2.push(`FROM ${rels.join(", ")}`);
811
818
  }
812
819
  if (where.length) {
813
- const clauses = where.map(String).filter((x) => x).join(" AND ");
820
+ const clauses = where.map(String).filter((x2) => x2).join(" AND ");
814
821
  if (clauses)
815
822
  sql2.push(`WHERE ${clauses}`);
816
823
  }
@@ -824,7 +831,7 @@ var Query = class _Query {
824
831
  sql2.push(`GROUP BY ${groupby.join(", ")}`);
825
832
  }
826
833
  if (having.length) {
827
- const clauses = having.map(String).filter((x) => x).join(" AND ");
834
+ const clauses = having.map(String).filter((x2) => x2).join(" AND ");
828
835
  if (clauses)
829
836
  sql2.push(`HAVING ${clauses}`);
830
837
  }
@@ -833,7 +840,7 @@ var Query = class _Query {
833
840
  sql2.push(`WINDOW ${windows.join(", ")}`);
834
841
  }
835
842
  if (qualify.length) {
836
- const clauses = qualify.map(String).filter((x) => x).join(" AND ");
843
+ const clauses = qualify.map(String).filter((x2) => x2).join(" AND ");
837
844
  if (clauses)
838
845
  sql2.push(`QUALIFY ${clauses}`);
839
846
  }
@@ -866,7 +873,7 @@ var SetOperation = class _SetOperation {
866
873
  return query.orderby;
867
874
  } else {
868
875
  query.orderby = query.orderby.concat(
869
- expr.flat().filter((x) => x).map(asColumn)
876
+ expr.flat().filter((x2) => x2).map(asColumn)
870
877
  );
871
878
  return this;
872
879
  }
@@ -920,6 +927,89 @@ function isDoubleQuoted(s) {
920
927
  return s[0] === '"' && s[s.length - 1] === '"';
921
928
  }
922
929
 
930
+ // src/scales.js
931
+ var identity = (x2) => x2;
932
+ function scaleLinear() {
933
+ return {
934
+ apply: identity,
935
+ invert: identity,
936
+ sqlApply: asColumn,
937
+ sqlInvert: identity
938
+ };
939
+ }
940
+ function scaleLog({ base } = {}) {
941
+ if (base == null || base === Math.E) {
942
+ return {
943
+ apply: Math.log,
944
+ invert: Math.exp,
945
+ sqlApply: (c) => sql`LN(${asColumn(c)})`,
946
+ sqlInvert: (c) => sql`EXP(${c})`
947
+ };
948
+ } else if (base === 10) {
949
+ return {
950
+ apply: Math.log10,
951
+ invert: (x2) => Math.pow(10, x2),
952
+ sqlApply: (c) => sql`LOG(${asColumn(c)})`,
953
+ sqlInvert: (c) => sql`POW(10, ${c})`
954
+ };
955
+ } else {
956
+ const b = +base;
957
+ return {
958
+ apply: (x2) => Math.log(x2) / Math.log(b),
959
+ invert: (x2) => Math.pow(b, x2),
960
+ sqlApply: (c) => sql`LN(${asColumn(c)}) / LN(${b})`,
961
+ sqlInvert: (c) => sql`POW(${b}, ${c})`
962
+ };
963
+ }
964
+ }
965
+ function scaleSymlog({ constant = 1 } = {}) {
966
+ const _ = +constant;
967
+ return {
968
+ apply: (x2) => Math.sign(x2) * Math.log1p(Math.abs(x2)),
969
+ invert: (x2) => Math.sign(x2) * Math.exp(Math.abs(x2) - _),
970
+ sqlApply: (c) => (c = asColumn(c), sql`SIGN(${c}) * LN(${_} + ABS(${c}))`),
971
+ sqlInvert: (c) => sql`SIGN(${c}) * (EXP(ABS(${c})) - ${_})`
972
+ };
973
+ }
974
+ function scaleSqrt() {
975
+ return {
976
+ apply: (x2) => Math.sign(x2) * Math.sqrt(Math.abs(x2)),
977
+ invert: (x2) => Math.sign(x2) * x2 * x2,
978
+ sqlApply: (c) => (c = asColumn(c), sql`SIGN(${c}) * SQRT(ABS(${c}))`),
979
+ sqlInvert: (c) => sql`SIGN(${c}) * (${c}) ** 2`
980
+ };
981
+ }
982
+ function scalePow({ exponent = 1 } = {}) {
983
+ const e = +exponent;
984
+ return {
985
+ apply: (x2) => Math.sign(x2) * Math.pow(Math.abs(x2), e),
986
+ invert: (x2) => Math.sign(x2) * Math.pow(Math.abs(x2), 1 / e),
987
+ sqlApply: (c) => (c = asColumn(c), sql`SIGN(${c}) * POW(ABS(${c}), ${e})`),
988
+ sqlInvert: (c) => sql`SIGN(${c}) * POW(ABS(${c}), 1/${e})`
989
+ };
990
+ }
991
+ function scaleTime() {
992
+ return {
993
+ apply: (x2) => +x2,
994
+ invert: (x2) => new Date(x2),
995
+ sqlApply: (c) => c instanceof Date ? +c : epoch_ms(asColumn(c)),
996
+ sqlInvert: identity
997
+ };
998
+ }
999
+ var scales = {
1000
+ linear: scaleLinear,
1001
+ log: scaleLog,
1002
+ symlog: scaleSymlog,
1003
+ sqrt: scaleSqrt,
1004
+ pow: scalePow,
1005
+ time: scaleTime,
1006
+ utc: scaleTime
1007
+ };
1008
+ function scaleTransform(options) {
1009
+ const scale = scales[options.type];
1010
+ return scale ? { ...options, ...scale(options) } : null;
1011
+ }
1012
+
923
1013
  // src/load/create.js
924
1014
  function create(name, query, {
925
1015
  replace = false,
@@ -929,6 +1019,11 @@ function create(name, query, {
929
1019
  return "CREATE" + (replace ? " OR REPLACE " : " ") + (temp ? "TEMP " : "") + (view ? "VIEW" : "TABLE") + (replace ? " " : " IF NOT EXISTS ") + name + " AS " + query;
930
1020
  }
931
1021
 
1022
+ // src/load/extension.js
1023
+ function loadExtension(name) {
1024
+ return `INSTALL ${name}; LOAD ${name}`;
1025
+ }
1026
+
932
1027
  // src/load/sql-from.js
933
1028
  function sqlFrom(data, {
934
1029
  columns = Object.keys(data?.[0] || {})
@@ -969,6 +1064,14 @@ function loadJSON(tableName, fileName, options) {
969
1064
  function loadParquet(tableName, fileName, options) {
970
1065
  return load("read_parquet", tableName, fileName, options);
971
1066
  }
1067
+ function loadSpatial(tableName, fileName, options = {}) {
1068
+ const { options: opt, ...rest } = options;
1069
+ if (opt) {
1070
+ const open = Array.isArray(opt) ? opt.join(", ") : typeof opt === "string" ? opt : Object.entries(opt).map(([key, value]) => `${key}=${value}`).join(", ");
1071
+ rest.open_options = open.toUpperCase();
1072
+ }
1073
+ return load("st_read", tableName, fileName, rest);
1074
+ }
972
1075
  function loadObjects(tableName, data, options = {}) {
973
1076
  const { select = ["*"], ...opt } = options;
974
1077
  const values = sqlFrom(data);
@@ -1012,6 +1115,9 @@ export {
1012
1115
  cast,
1013
1116
  castDouble,
1014
1117
  castInteger,
1118
+ centroid,
1119
+ centroidX,
1120
+ centroidY,
1015
1121
  column,
1016
1122
  contains,
1017
1123
  corr,
@@ -1029,6 +1135,7 @@ export {
1029
1135
  eq,
1030
1136
  first,
1031
1137
  first_value,
1138
+ geojson,
1032
1139
  gt,
1033
1140
  gte,
1034
1141
  isBetween,
@@ -1052,9 +1159,11 @@ export {
1052
1159
  literal,
1053
1160
  literalToSQL,
1054
1161
  loadCSV,
1162
+ loadExtension,
1055
1163
  loadJSON,
1056
1164
  loadObjects,
1057
1165
  loadParquet,
1166
+ loadSpatial,
1058
1167
  lower,
1059
1168
  lt,
1060
1169
  lte,
@@ -1086,6 +1195,7 @@ export {
1086
1195
  regrSlope,
1087
1196
  relation,
1088
1197
  row_number,
1198
+ scaleTransform,
1089
1199
  skewness,
1090
1200
  sql,
1091
1201
  stddev,
@@ -1096,5 +1206,7 @@ export {
1096
1206
  toSQL,
1097
1207
  upper,
1098
1208
  varPop,
1099
- variance
1209
+ variance,
1210
+ x,
1211
+ y
1100
1212
  };
@@ -1 +1 @@
1
- var N=class{constructor(t,e){t&&(this.table=String(t)),e&&(this.column=e)}get columns(){return this.column?[this.column]:[]}toString(){let{table:t,column:e}=this;if(e){let n=e.startsWith("*")?e:`"${e}"`;return`${t?`${Q(t)}.`:""}${n}`}else return t?Q(t):"NULL"}};function Q(r){return r.split(".").map(e=>`"${e}"`).join(".")}function V(r,t){return r instanceof N&&r.column===t}function l(r){return typeof r=="string"?k(r):r}function I(r){return typeof r=="string"?X(r):r}function X(r){return new N(r)}function k(r,t){return arguments.length===1&&(t=r,r=null),new N(r,t)}function nt(r){return new N(r,"*")}function ot(r){return typeof r=="string"?`"${r}"`:E(r)}function E(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 A=r=>typeof r?.addEventListener=="function";function _(r){return r instanceof w}var w=class{constructor(t,e,n){this._expr=Array.isArray(t)?t:[t],this._deps=e||[],this.annotate(n);let o=this._expr.filter(s=>A(s));o.length>0?(this._params=Array.from(new Set(o)),this._params.forEach(s=>{s.addEventListener("value",()=>st(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=>A(t)&&!_(t)?E(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 st(r,t){if(t?.size)return Promise.allSettled(Array.from(t,e=>e(r)))}function G(r,t){let e=[r[0]],n=new Set,o=t.length;for(let s=0,i=0;s<o;){let c=t[s];A(c)?e[++i]=c:(Array.isArray(c?.columns)&&c.columns.forEach(g=>n.add(g)),e[i]+=typeof c=="string"?c:E(c));let p=r[++s];A(e[i])?e[++i]=p:e[i]+=p}return{spans:e,cols:Array.from(n)}}function a(r,...t){let{spans:e,cols:n}=G(r,t);return new w(e,n)}function it(r){let t=l(r);return a`${t} DESC NULLS LAST`.annotate({label:t?.label,desc:!0})}var ct=r=>({value:r,toString:()=>E(r)});function D(r){r(this.op,this),this.children?.forEach(t=>t.visit(r))}function H(r,t){let e=t.filter(o=>o!=null).map(l),n=e.map((o,s)=>s?` ${r} `:"");return e.length===1?n.push(""):e.length>1&&(n[0]="(",n.push(")")),a(n,...e).annotate({op:r,children:e,visit:D})}var ut=(...r)=>H("AND",r.flat()),at=(...r)=>H("OR",r.flat()),lt=r=>t=>a`(${r} ${l(t)})`.annotate({op:r,a:t,visit:D}),pt=lt("NOT"),K=r=>t=>a`(${l(t)} ${r})`.annotate({op:r,a:t,visit:D}),ft=K("IS NULL"),ht=K("IS NOT NULL"),S=r=>(t,e)=>a`(${l(t)} ${r} ${l(e)})`.annotate({op:r,a:t,b:e,visit:D}),mt=S("="),gt=S("<>"),dt=S("<"),xt=S(">"),Et=S("<="),$t=S(">="),yt=S("IS DISTINCT FROM"),Nt=S("IS NOT DISTINCT FROM");function v(r,t,e,n){t=l(t);let o=r.startsWith("NOT ")?"NOT ":"";return(e?n?a`${o}(${e[0]} <= ${t} AND ${t} < ${e[1]})`:a`(${t} ${r} ${e[0]} AND ${e[1]})`:a``).annotate({op:r,visit:D,field:t,range:e})}var wt=(r,t,e)=>v("BETWEEN",r,t,e),St=(r,t,e)=>v("NOT BETWEEN",r,t,e);function T(r,t){return Array.from({length:r},()=>t)}function d(r,t){return(...e)=>{let n=e.map(l),o=t?`::${t}`:"";return(n.length?a([`${r}(`,...T(n.length-1,", "),`)${o}`],...n):a`${r}()${o}`).annotate({func:r,args:n})}}var Rt=d("REGEXP_MATCHES"),At=d("CONTAINS"),Tt=d("PREFIX"),bt=d("SUFFIX"),qt=d("LOWER"),Lt=d("UPPER"),Ot=d("LENGTH"),It=d("ISNAN"),Dt=d("ISFINITE"),Ct=d("ISINF");var C=class r extends w{constructor(t,e,n,o,s="",i="",c=""){let p;if(o&&!(s||i||c))p=o?a`${e} OVER "${o}"`:a`${e} OVER ()`;else{let q=s&&i?" ":"",L=(s||i)&&c?" ":"";p=a`${e} OVER (${o?`"${o}" `:""}${s}${q}${i}${L}${c})`}n&&(p=a`(${p})::${n}`);let{_expr:y,_deps:R}=p;super(y,R,{window:t,func:e,type:n,name:o,group:s,order:i,frame:c})}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:c}=this;return new r(e,n,o,t,s,i,c)}partitionby(...t){let e=t.flat().filter(y=>y).map(l),n=a(["PARTITION BY ",T(e.length-1,", "),""],...e),{window:o,func:s,type:i,name:c,order:p,frame:g}=this;return new r(o,s,i,c,n,p,g)}orderby(...t){let e=t.flat().filter(y=>y).map(l),n=a(["ORDER BY ",T(e.length-1,", "),""],...e),{window:o,func:s,type:i,name:c,group:p,frame:g}=this;return new r(o,s,i,c,p,n,g)}rows(t){let e=z("ROWS",t),{window:n,func:o,type:s,name:i,group:c,order:p}=this;return new r(n,o,s,i,c,p,e)}range(t){let e=z("RANGE",t),{window:n,func:o,type:s,name:i,group:c,order:p}=this;return new r(n,o,s,i,c,p,e)}};function z(r,t){if(A(t)){let e=a`${t}`;return e.toString=()=>`${r} ${J(t.value)}`,e}return`${r} ${J(t)}`}function J(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 $(r,t){return(...e)=>{let n=d(r)(...e);return new C(r,n,t)}}var _t=$("ROW_NUMBER","INTEGER"),Ft=$("RANK","INTEGER"),Pt=$("DENSE_RANK","INTEGER"),Ut=$("PERCENT_RANK"),Mt=$("CUME_DIST"),Gt=$("NTILE"),jt=$("LAG"),Wt=$("LEAD"),Yt=$("FIRST_VALUE"),Bt=$("LAST_VALUE"),Qt=$("NTH_VALUE");function Vt(r,...t){return a(r,...t).annotate({aggregate:!0})}var j=class r extends w{constructor(t,e,n,o,s){e=(e||[]).map(l);let{strings:i,exprs:c}=Xt(t,e,n,o,s),{spans:p,cols:g}=G(i,c);super(p,g,{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(kt).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 Xt(r,t,e,n,o){let s=`)${e?`::${e}`:""}`,i=[`${r}(${n?"DISTINCT ":""}`],c=[];return t.length?(i=i.concat([...T(t.length-1,", "),`${s}${o?" FILTER (WHERE ":""}`,...o?[")"]:[]]),c=[...t,...o?[o]:[]]):i[0]+="*"+s,{exprs:c,strings:i}}function kt(r){let t=E(r);return t&&t.startsWith('"')&&t.endsWith('"')?t.slice(1,-1):t}function u(r,t){return(...e)=>new j(r,e,t)}var Ht=u("COUNT","INTEGER"),Kt=u("AVG"),vt=u("AVG"),zt=u("MAD"),Jt=u("MAX"),Zt=u("MIN"),te=u("SUM","DOUBLE"),ee=u("PRODUCT"),re=u("MEDIAN"),ne=u("QUANTILE"),oe=u("MODE"),se=u("VARIANCE"),ie=u("STDDEV"),ce=u("SKEWNESS"),ue=u("KURTOSIS"),ae=u("ENTROPY"),le=u("VAR_POP"),pe=u("STDDEV_POP"),fe=u("CORR"),he=u("COVAR_POP"),me=u("REGR_INTERCEPT"),ge=u("REGR_SLOPE"),de=u("REGR_COUNT"),xe=u("REGR_R2"),Ee=u("REGR_SYY"),$e=u("REGR_SXX"),ye=u("REGR_SXY"),Ne=u("REGR_AVGX"),we=u("REGR_AVGY"),Se=u("FIRST"),Re=u("LAST"),Ae=u("ARG_MIN"),Te=u("ARG_MAX"),be=u("STRING_AGG"),qe=u("ARRAY_AGG");function W(r,t){let e=l(r),n=a`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 Le=r=>W(r,"DOUBLE"),Oe=r=>W(r,"INTEGER");var Ie=r=>{let t=l(r);return a`(1000 * (epoch(${t}) - second(${t})) + millisecond(${t}))::DOUBLE`},De=r=>{let t=l(r);return a`MAKE_DATE(2012, MONTH(${t}), 1)`.annotate({label:"month"})},Ce=r=>{let t=l(r);return a`MAKE_DATE(2012, MONTH(${t}), DAY(${t}))`.annotate({label:"date"})},_e=r=>{let t=l(r);return a`MAKE_DATE(2012, 1, DAY(${t}))`.annotate({label:"date"})};var U=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 b("UNION",t.flat())}static unionAll(...t){return new b("UNION ALL",t.flat())}static intersect(...t){return new b("INTERSECT",t.flat())}static except(...t){return new b("EXCEPT",t.flat())}constructor(){this.query={with:[],select:[],from:[],where:[],groupby:[],having:[],window:[],qualify:[],orderby:[]}}clone(){let t=new r;return t.query={...this.query},t}with(...t){let{query:e}=this;if(t.length===0)return e.with;{let n=[],o=(s,i)=>{let c=i.clone();c.cteFor=this,n.push({as:s,query:c})};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:l(o)});else if(o instanceof N)n.push({as:o.column,expr:o});else if(Array.isArray(o))n.push({as:o[0],expr:o[1]});else for(let s in o)n.push({as:F(s),expr:l(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:I(o)});else if(o instanceof N)n.push({as:o.table,from:o});else if(P(o)||_(o))n.push({from:o});else if(Array.isArray(o))n.push({as:F(o[0]),from:I(o[1])});else for(let s in o)n.push({as:F(s),from:I(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(l)),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:F(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(l)),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:c,query:p})=>(i[c]=p,i),{}),s=[];return t.from.forEach(({from:i})=>{if(P(i))s.push(i);else if(o[i.table]){let c=o[i.table];s.push(c)}}),s}toString(){let{select:t,distinct:e,from:n,sample:o,where:s,groupby:i,having:c,window:p,qualify:g,orderby:y,limit:R,offset:q,with:L}=this.query,m=[];if(L.length){let f=L.map(({as:h,query:x})=>`"${h}" AS (${x})`);m.push(`WITH ${f.join(", ")}`)}let tt=t.map(({as:f,expr:h})=>V(h,f)&&!h.table?`${h}`:`${h} AS "${f}"`);if(m.push(`SELECT${e?" DISTINCT":""} ${tt.join(", ")}`),n.length){let f=n.map(({as:h,from:x})=>{let O=P(x)?`(${x})`:`${x}`;return!h||h===x.table?O:`${O} AS "${h}"`});m.push(`FROM ${f.join(", ")}`)}if(s.length){let f=s.map(String).filter(h=>h).join(" AND ");f&&m.push(`WHERE ${f}`)}if(o){let{rows:f,perc:h,method:x,seed:O}=o,et=f?`${f} ROWS`:`${h} PERCENT`,rt=x?` (${x}${O!=null?`, ${O}`:""})`:"";m.push(`USING SAMPLE ${et}${rt}`)}if(i.length&&m.push(`GROUP BY ${i.join(", ")}`),c.length){let f=c.map(String).filter(h=>h).join(" AND ");f&&m.push(`HAVING ${f}`)}if(p.length){let f=p.map(({as:h,expr:x})=>`"${h}" AS (${x})`);m.push(`WINDOW ${f.join(", ")}`)}if(g.length){let f=g.map(String).filter(h=>h).join(" AND ");f&&m.push(`QUALIFY ${f}`)}return y.length&&m.push(`ORDER BY ${y.join(", ")}`),Number.isFinite(R)&&m.push(`LIMIT ${R}`),Number.isFinite(q)&&m.push(`OFFSET ${q}`),m.join(" ")}},b=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(l)),this)}limit(t){let{query:e}=this;return arguments.length===0?e.limit:(e.limit=Number.isFinite(t)?t:void 0,this)}offset(t){let{query:e}=this;return arguments.length===0?e.offset:(e.offset=Number.isFinite(t)?t:void 0,this)}get subqueries(){let{queries:t,cteFor:e}=this;return e&&t.forEach(n=>n.cteFor=e),t}toString(){let{op:t,queries:e,query:{orderby:n,limit:o,offset:s}}=this,i=[e.join(` ${t} `)];return n.length&&i.push(`ORDER BY ${n.join(", ")}`),Number.isFinite(o)&&i.push(`LIMIT ${o}`),Number.isFinite(s)&&i.push(`OFFSET ${s}`),i.join(" ")}};function P(r){return r instanceof U||r instanceof b}function F(r){return Fe(r)?r.slice(1,-1):r}function Fe(r){return r[0]==='"'&&r[r.length-1]==='"'}function M(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 Z(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=>`${E(o[i])} AS "${t[i]}"`);n.push(`(SELECT ${s.join(", ")})`)}return n.join(" UNION ALL ")}function B(r,t,e,n={},o={}){let{select:s=["*"],where:i,view:c,temp:p,replace:g,...y}=n,R=je({...o,...y}),q=`${r}('${e}'${R?", "+R:""})`,L=i?` WHERE ${i}`:"",m=`SELECT ${s.join(", ")} FROM ${q}${L}`;return M(t,m,{view:c,temp:p,replace:g})}function Pe(r,t,e){return B("read_csv",r,t,e,{auto_detect:!0,sample_size:-1})}function Ue(r,t,e){return B("read_json",r,t,e,{auto_detect:!0,json_format:"auto"})}function Me(r,t,e){return B("read_parquet",r,t,e)}function Ge(r,t,e={}){let{select:n=["*"],...o}=e,s=Z(t),i=n.length===1&&n[0]==="*"?s:`SELECT ${n} FROM ${s}`;return M(r,i,o)}function je(r){return Object.entries(r).map(([t,e])=>`${t}=${Y(e)}`).join(", ")}function Y(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=>Y(t)).join(", ")+"]":"{"+Object.entries(r).map(([t,e])=>`'${t}': ${Y(e)}`).join(", ")+"}";default:return r}}export{U as Query,N as Ref,Vt as agg,nt as all,ut as and,Te as argmax,Ae as argmin,qe as arrayAgg,l as asColumn,I as asRelation,Kt as avg,W as cast,Le as castDouble,Oe as castInteger,k as column,At as contains,fe as corr,Ht as count,he as covarPop,M as create,Mt as cume_dist,_e as dateDay,De as dateMonth,Ce as dateMonthDay,Pt as dense_rank,it as desc,ae as entropy,Ie as epoch_ms,mt as eq,Se as first,Yt as first_value,xt as gt,$t as gte,wt as isBetween,yt as isDistinct,Dt as isFinite,Ct as isInfinite,It as isNaN,St as isNotBetween,Nt as isNotDistinct,ht as isNotNull,ft as isNull,A as isParamLike,P as isQuery,_ as isSQLExpression,ue as kurtosis,jt as lag,Re as last,Bt as last_value,Wt as lead,Ot as length,ct as literal,E as literalToSQL,Pe as loadCSV,Ue as loadJSON,Ge as loadObjects,Me as loadParquet,qt as lower,dt as lt,Et as lte,zt as mad,Jt as max,vt as mean,re as median,Zt as min,oe as mode,gt as neq,pt as not,Qt as nth_value,Gt as ntile,at as or,Ut as percent_rank,Tt as prefix,ee as product,ne as quantile,Ft as rank,Rt as regexp_matches,Ne as regrAvgX,we as regrAvgY,de as regrCount,me as regrIntercept,xe as regrR2,$e as regrSXX,ye as regrSXY,Ee as regrSYY,ge as regrSlope,X as relation,_t as row_number,ce as skewness,a as sql,ie as stddev,pe as stddevPop,be as stringAgg,bt as suffix,te as sum,ot as toSQL,Lt as upper,le as varPop,se as variance};
1
+ var N=class{constructor(t,e){t&&(this.table=String(t)),e&&(this.column=e)}get columns(){return this.column?[this.column]:[]}toString(){let{table:t,column:e}=this;if(e){let n=e.startsWith("*")?e:`"${e}"`;return`${t?`${V(t)}.`:""}${n}`}else return t?V(t):"NULL"}};function V(r){return r.split(".").map(e=>`"${e}"`).join(".")}function k(r,t){return r instanceof N&&r.column===t}function u(r){return typeof r=="string"?K(r):r}function O(r){return typeof r=="string"?H(r):r}function H(r){return new N(r)}function K(r,t){return arguments.length===1&&(t=r,r=null),new N(r,t)}function ut(r){return new N(r,"*")}function lt(r){return typeof r=="string"?`"${r}"`:$(r)}function $(r){switch(typeof r){case"boolean":return r?"TRUE":"FALSE";case"string":return`'${r}'`;case"number":return Number.isFinite(r)?String(r):"NULL";default:if(r==null)return"NULL";if(r instanceof Date){let t=+r;if(Number.isNaN(t))return"NULL";let e=r.getUTCFullYear(),n=r.getUTCMonth(),o=r.getUTCDate();return t===Date.UTC(e,n,o)?`MAKE_DATE(${e}, ${n+1}, ${o})`:`EPOCH_MS(${t})`}else return r instanceof RegExp?`'${r.source}'`:String(r)}}var T=r=>typeof r?.addEventListener=="function";function M(r){return r instanceof S}var S=class{constructor(t,e,n){this._expr=Array.isArray(t)?t:[t],this._deps=e||[],this.annotate(n);let o=this._expr.filter(s=>T(s));o.length>0?(this._params=Array.from(new Set(o)),this._params.forEach(s=>{s.addEventListener("value",()=>pt(this,this.map?.get("value")))})):this.addEventListener=void 0}get value(){return this}get columns(){let{_params:t,_deps:e}=this;if(t){let n=new Set(t.flatMap(o=>{let s=o.value?.columns;return Array.isArray(s)?s:[]}));if(n.size){let o=new Set(e);return n.forEach(s=>o.add(s)),Array.from(o)}}return e}get column(){return this._deps.length?this._deps[0]:this.columns[0]}annotate(...t){return Object.assign(this,...t)}toString(){return this._expr.map(t=>T(t)&&!M(t)?$(t.value):t).join("")}addEventListener(t,e){let n=this.map||(this.map=new Map);(n.get(t)||(n.set(t,new Set),n.get(t))).add(e)}};function pt(r,t){if(t?.size)return Promise.allSettled(Array.from(t,e=>e(r)))}function W(r,t){let e=[r[0]],n=new Set,o=t.length;for(let s=0,i=0;s<o;){let a=t[s];T(a)?e[++i]=a:(Array.isArray(a?.columns)&&a.columns.forEach(d=>n.add(d)),e[i]+=typeof a=="string"?a:$(a));let p=r[++s];T(e[i])?e[++i]=p:e[i]+=p}return{spans:e,cols:Array.from(n)}}function c(r,...t){let{spans:e,cols:n}=W(r,t);return new S(e,n)}function ft(r){let t=u(r);return c`${t} DESC NULLS LAST`.annotate({label:t?.label,desc:!0})}var ht=r=>({value:r,toString:()=>$(r)});function D(r){r(this.op,this),this.children?.forEach(t=>t.visit(r))}function z(r,t){let e=t.filter(o=>o!=null).map(u),n=e.map((o,s)=>s?` ${r} `:"");return e.length===1?n.push(""):e.length>1&&(n[0]="(",n.push(")")),c(n,...e).annotate({op:r,children:e,visit:D})}var mt=(...r)=>z("AND",r.flat()),gt=(...r)=>z("OR",r.flat()),dt=r=>t=>c`(${r} ${u(t)})`.annotate({op:r,a:t,visit:D}),xt=dt("NOT"),J=r=>t=>c`(${u(t)} ${r})`.annotate({op:r,a:t,visit:D}),$t=J("IS NULL"),Et=J("IS NOT NULL"),w=r=>(t,e)=>c`(${u(t)} ${r} ${u(e)})`.annotate({op:r,a:t,b:e,visit:D}),yt=w("="),Nt=w("<>"),St=w("<"),wt=w(">"),At=w("<="),Tt=w(">="),Rt=w("IS DISTINCT FROM"),qt=w("IS NOT DISTINCT FROM");function Z(r,t,e,n){t=u(t);let o=r.startsWith("NOT ")?"NOT ":"";return(e?n?c`${o}(${e[0]} <= ${t} AND ${t} < ${e[1]})`:c`(${t} ${r} ${e[0]} AND ${e[1]})`:c``).annotate({op:r,visit:D,field:t,range:e})}var bt=(r,t,e)=>Z("BETWEEN",r,t,e),It=(r,t,e)=>Z("NOT BETWEEN",r,t,e);function R(r,t){return Array.from({length:r},()=>t)}function m(r,t){return(...e)=>{let n=e.map(u),o=t?`::${t}`:"";return(n.length?c([`${r}(`,...R(n.length-1,", "),`)${o}`],...n):c`${r}()${o}`).annotate({func:r,args:n})}}var Lt=m("REGEXP_MATCHES"),Ot=m("CONTAINS"),Dt=m("PREFIX"),_t=m("SUFFIX"),Mt=m("LOWER"),Ct=m("UPPER"),Pt=m("LENGTH"),Ft=m("ISNAN"),Gt=m("ISFINITE"),Ut=m("ISINF");var _=class r extends S{constructor(t,e,n,o,s="",i="",a=""){let p;if(o&&!(s||i||a))p=o?c`${e} OVER "${o}"`:c`${e} OVER ()`;else{let b=s&&i?" ":"",I=(s||i)&&a?" ":"";p=c`${e} OVER (${o?`"${o}" `:""}${s}${b}${i}${I}${a})`}n&&(p=c`(${p})::${n}`);let{_expr:y,_deps:A}=p;super(y,A,{window:t,func:e,type:n,name:o,group:s,order:i,frame:a})}get basis(){return this.column}get label(){let{func:t}=this;return t.label??t.toString()}over(t){let{window:e,func:n,type:o,group:s,order:i,frame:a}=this;return new r(e,n,o,t,s,i,a)}partitionby(...t){let e=t.flat().filter(y=>y).map(u),n=c(["PARTITION BY ",R(e.length-1,", "),""],...e),{window:o,func:s,type:i,name:a,order:p,frame:d}=this;return new r(o,s,i,a,n,p,d)}orderby(...t){let e=t.flat().filter(y=>y).map(u),n=c(["ORDER BY ",R(e.length-1,", "),""],...e),{window:o,func:s,type:i,name:a,group:p,frame:d}=this;return new r(o,s,i,a,p,n,d)}rows(t){let e=tt("ROWS",t),{window:n,func:o,type:s,name:i,group:a,order:p}=this;return new r(n,o,s,i,a,p,e)}range(t){let e=tt("RANGE",t),{window:n,func:o,type:s,name:i,group:a,order:p}=this;return new r(n,o,s,i,a,p,e)}};function tt(r,t){if(T(t)){let e=c`${t}`;return e.toString=()=>`${r} ${et(t.value)}`,e}return`${r} ${et(t)}`}function et(r){let[t,e]=r,n=t===0?"CURRENT ROW":Number.isFinite(t)?`${Math.abs(t)} PRECEDING`:"UNBOUNDED PRECEDING",o=e===0?"CURRENT ROW":Number.isFinite(e)?`${Math.abs(e)} FOLLOWING`:"UNBOUNDED FOLLOWING";return`BETWEEN ${n} AND ${o}`}function E(r,t){return(...e)=>{let n=m(r)(...e);return new _(r,n,t)}}var jt=E("ROW_NUMBER","INTEGER"),Wt=E("RANK","INTEGER"),Yt=E("DENSE_RANK","INTEGER"),vt=E("PERCENT_RANK"),Bt=E("CUME_DIST"),Xt=E("NTILE"),Qt=E("LAG"),Vt=E("LEAD"),kt=E("FIRST_VALUE"),Ht=E("LAST_VALUE"),Kt=E("NTH_VALUE");function zt(r,...t){return c(r,...t).annotate({aggregate:!0})}var Y=class r extends S{constructor(t,e,n,o,s){e=(e||[]).map(u);let{strings:i,exprs:a}=Jt(t,e,n,o,s),{spans:p,cols:d}=W(i,a);super(p,d,{aggregate:t,args:e,type:n,isDistinct:o,filter:s})}get basis(){return this.column}get label(){let{aggregate:t,args:e,isDistinct:n}=this,o=n?"DISTINCT"+(e.length?" ":""):"",s=e.length?`(${o}${e.map(Zt).join(", ")})`:"";return`${t.toLowerCase()}${s}`}distinct(){let{aggregate:t,args:e,type:n,filter:o}=this;return new r(t,e,n,!0,o)}where(t){let{aggregate:e,args:n,type:o,isDistinct:s}=this;return new r(e,n,o,s,t)}window(){let{aggregate:t,args:e,type:n,isDistinct:o}=this,s=new r(t,e,null,o);return new _(t,s,n)}partitionby(...t){return this.window().partitionby(...t)}orderby(...t){return this.window().orderby(...t)}rows(t,e){return this.window().rows(t,e)}range(t,e){return this.window().range(t,e)}};function Jt(r,t,e,n,o){let s=`)${e?`::${e}`:""}`,i=[`${r}(${n?"DISTINCT ":""}`],a=[];return t.length?(i=i.concat([...R(t.length-1,", "),`${s}${o?" FILTER (WHERE ":""}`,...o?[")"]:[]]),a=[...t,...o?[o]:[]]):i[0]+="*"+s,{exprs:a,strings:i}}function Zt(r){let t=$(r);return t&&t.startsWith('"')&&t.endsWith('"')?t.slice(1,-1):t}function l(r,t){return(...e)=>new Y(r,e,t)}var te=l("COUNT","INTEGER"),ee=l("AVG"),re=l("AVG"),ne=l("MAD"),oe=l("MAX"),se=l("MIN"),ie=l("SUM","DOUBLE"),ce=l("PRODUCT"),ae=l("MEDIAN"),ue=l("QUANTILE"),le=l("MODE"),pe=l("VARIANCE"),fe=l("STDDEV"),he=l("SKEWNESS"),me=l("KURTOSIS"),ge=l("ENTROPY"),de=l("VAR_POP"),xe=l("STDDEV_POP"),$e=l("CORR"),Ee=l("COVAR_POP"),ye=l("REGR_INTERCEPT"),Ne=l("REGR_SLOPE"),Se=l("REGR_COUNT"),we=l("REGR_R2"),Ae=l("REGR_SYY"),Te=l("REGR_SXX"),Re=l("REGR_SXY"),qe=l("REGR_AVGX"),be=l("REGR_AVGY"),Ie=l("FIRST"),Le=l("LAST"),Oe=l("ARG_MIN"),De=l("ARG_MAX"),_e=l("STRING_AGG"),Me=l("ARRAY_AGG");function v(r,t){let e=u(r),n=c`CAST(${e} AS ${t})`;return Object.defineProperty(n,"label",{enumerable:!0,get(){return r.label}}),Object.defineProperty(n,"aggregate",{enumerable:!0,get(){return r.aggregate||!1}}),n}var Ce=r=>v(r,"DOUBLE"),Pe=r=>v(r,"INTEGER");var B=r=>c`epoch_ms(${u(r)})`,Fe=r=>{let t=u(r);return c`MAKE_DATE(2012, MONTH(${t}), 1)`.annotate({label:"month"})},Ge=r=>{let t=u(r);return c`MAKE_DATE(2012, MONTH(${t}), DAY(${t}))`.annotate({label:"date"})},Ue=r=>{let t=u(r);return c`MAKE_DATE(2012, 1, DAY(${t}))`.annotate({label:"date"})};var je=m("ST_AsGeoJSON"),rt=m("ST_X"),nt=m("ST_Y"),X=m("ST_CENTROID"),We=r=>rt(X(r)),Ye=r=>nt(X(r));var F=class r{static select(...t){return new r().select(...t)}static from(...t){return new r().from(...t)}static with(...t){return new r().with(...t)}static union(...t){return new q("UNION",t.flat())}static unionAll(...t){return new q("UNION ALL",t.flat())}static intersect(...t){return new q("INTERSECT",t.flat())}static except(...t){return new q("EXCEPT",t.flat())}constructor(){this.query={with:[],select:[],from:[],where:[],groupby:[],having:[],window:[],qualify:[],orderby:[]}}clone(){let t=new r;return t.query={...this.query},t}with(...t){let{query:e}=this;if(t.length===0)return e.with;{let n=[],o=(s,i)=>{let a=i.clone();a.cteFor=this,n.push({as:s,query:a})};return t.flat().forEach(s=>{if(s!=null)if(s.as&&s.query)o(s.as,s.query);else for(let i in s)o(i,s[i])}),e.with=e.with.concat(n),this}}select(...t){let{query:e}=this;if(t.length===0)return e.select;{let n=[];for(let o of t.flat())if(o!=null)if(typeof o=="string")n.push({as:o,expr:u(o)});else if(o instanceof N)n.push({as:o.column,expr:o});else if(Array.isArray(o))n.push({as:o[0],expr:o[1]});else for(let s in o)n.push({as:C(s),expr:u(o[s])});return e.select=e.select.concat(n),this}}$select(...t){return this.query.select=[],this.select(...t)}distinct(t=!0){return this.query.distinct=!!t,this}from(...t){let{query:e}=this;if(t.length===0)return e.from;{let n=[];return t.flat().forEach(o=>{if(o!=null)if(typeof o=="string")n.push({as:o,from:O(o)});else if(o instanceof N)n.push({as:o.table,from:o});else if(P(o)||M(o))n.push({from:o});else if(Array.isArray(o))n.push({as:C(o[0]),from:O(o[1])});else for(let s in o)n.push({as:C(s),from:O(o[s])})}),e.from=e.from.concat(n),this}}$from(...t){return this.query.from=[],this.from(...t)}sample(t,e){let{query:n}=this;if(arguments.length===0)return n.sample;{let o=t;return typeof t=="number"&&(o=t>0&&t<1?{perc:100*t,method:e}:{rows:Math.round(t),method:e}),n.sample=o,this}}where(...t){let{query:e}=this;return t.length===0?e.where:(e.where=e.where.concat(t.flat().filter(n=>n)),this)}$where(...t){return this.query.where=[],this.where(...t)}groupby(...t){let{query:e}=this;return t.length===0?e.groupby:(e.groupby=e.groupby.concat(t.flat().filter(n=>n).map(u)),this)}$groupby(...t){return this.query.groupby=[],this.groupby(...t)}having(...t){let{query:e}=this;return t.length===0?e.having:(e.having=e.having.concat(t.flat().filter(n=>n)),this)}window(...t){let{query:e}=this;if(t.length===0)return e.window;{let n=[];return t.flat().forEach(o=>{if(o!=null)for(let s in o)n.push({as:C(s),expr:o[s]})}),e.window=e.window.concat(n),this}}qualify(...t){let{query:e}=this;return t.length===0?e.qualify:(e.qualify=e.qualify.concat(t.flat().filter(n=>n)),this)}orderby(...t){let{query:e}=this;return t.length===0?e.orderby:(e.orderby=e.orderby.concat(t.flat().filter(n=>n).map(u)),this)}limit(t){let{query:e}=this;return arguments.length===0?e.limit:(e.limit=Number.isFinite(t)?t:void 0,this)}offset(t){let{query:e}=this;return arguments.length===0?e.offset:(e.offset=Number.isFinite(t)?t:void 0,this)}get subqueries(){let{query:t,cteFor:e}=this,o=(e?.query||t).with?.reduce((i,{as:a,query:p})=>(i[a]=p,i),{}),s=[];return t.from.forEach(({from:i})=>{if(P(i))s.push(i);else if(o[i.table]){let a=o[i.table];s.push(a)}}),s}toString(){let{select:t,distinct:e,from:n,sample:o,where:s,groupby:i,having:a,window:p,qualify:d,orderby:y,limit:A,offset:b,with:I}=this.query,g=[];if(I.length){let f=I.map(({as:h,query:x})=>`"${h}" AS (${x})`);g.push(`WITH ${f.join(", ")}`)}let it=t.map(({as:f,expr:h})=>k(h,f)&&!h.table?`${h}`:`${h} AS "${f}"`);if(g.push(`SELECT${e?" DISTINCT":""} ${it.join(", ")}`),n.length){let f=n.map(({as:h,from:x})=>{let L=P(x)?`(${x})`:`${x}`;return!h||h===x.table?L:`${L} AS "${h}"`});g.push(`FROM ${f.join(", ")}`)}if(s.length){let f=s.map(String).filter(h=>h).join(" AND ");f&&g.push(`WHERE ${f}`)}if(o){let{rows:f,perc:h,method:x,seed:L}=o,ct=f?`${f} ROWS`:`${h} PERCENT`,at=x?` (${x}${L!=null?`, ${L}`:""})`:"";g.push(`USING SAMPLE ${ct}${at}`)}if(i.length&&g.push(`GROUP BY ${i.join(", ")}`),a.length){let f=a.map(String).filter(h=>h).join(" AND ");f&&g.push(`HAVING ${f}`)}if(p.length){let f=p.map(({as:h,expr:x})=>`"${h}" AS (${x})`);g.push(`WINDOW ${f.join(", ")}`)}if(d.length){let f=d.map(String).filter(h=>h).join(" AND ");f&&g.push(`QUALIFY ${f}`)}return y.length&&g.push(`ORDER BY ${y.join(", ")}`),Number.isFinite(A)&&g.push(`LIMIT ${A}`),Number.isFinite(b)&&g.push(`OFFSET ${b}`),g.join(" ")}},q=class r{constructor(t,e){this.op=t,this.queries=e.map(n=>n.clone()),this.query={orderby:[]}}clone(){let t=new r(this.op,this.queries);return t.query={...this.query},t}orderby(...t){let{query:e}=this;return t.length===0?e.orderby:(e.orderby=e.orderby.concat(t.flat().filter(n=>n).map(u)),this)}limit(t){let{query:e}=this;return arguments.length===0?e.limit:(e.limit=Number.isFinite(t)?t:void 0,this)}offset(t){let{query:e}=this;return arguments.length===0?e.offset:(e.offset=Number.isFinite(t)?t:void 0,this)}get subqueries(){let{queries:t,cteFor:e}=this;return e&&t.forEach(n=>n.cteFor=e),t}toString(){let{op:t,queries:e,query:{orderby:n,limit:o,offset:s}}=this,i=[e.join(` ${t} `)];return n.length&&i.push(`ORDER BY ${n.join(", ")}`),Number.isFinite(o)&&i.push(`LIMIT ${o}`),Number.isFinite(s)&&i.push(`OFFSET ${s}`),i.join(" ")}};function P(r){return r instanceof F||r instanceof q}function C(r){return ve(r)?r.slice(1,-1):r}function ve(r){return r[0]==='"'&&r[r.length-1]==='"'}var G=r=>r;function Be(){return{apply:G,invert:G,sqlApply:u,sqlInvert:G}}function Xe({base:r}={}){if(r==null||r===Math.E)return{apply:Math.log,invert:Math.exp,sqlApply:t=>c`LN(${u(t)})`,sqlInvert:t=>c`EXP(${t})`};if(r===10)return{apply:Math.log10,invert:t=>Math.pow(10,t),sqlApply:t=>c`LOG(${u(t)})`,sqlInvert:t=>c`POW(10, ${t})`};{let t=+r;return{apply:e=>Math.log(e)/Math.log(t),invert:e=>Math.pow(t,e),sqlApply:e=>c`LN(${u(e)}) / LN(${t})`,sqlInvert:e=>c`POW(${t}, ${e})`}}}function Qe({constant:r=1}={}){let t=+r;return{apply:e=>Math.sign(e)*Math.log1p(Math.abs(e)),invert:e=>Math.sign(e)*Math.exp(Math.abs(e)-t),sqlApply:e=>(e=u(e),c`SIGN(${e}) * LN(${t} + ABS(${e}))`),sqlInvert:e=>c`SIGN(${e}) * (EXP(ABS(${e})) - ${t})`}}function Ve(){return{apply:r=>Math.sign(r)*Math.sqrt(Math.abs(r)),invert:r=>Math.sign(r)*r*r,sqlApply:r=>(r=u(r),c`SIGN(${r}) * SQRT(ABS(${r}))`),sqlInvert:r=>c`SIGN(${r}) * (${r}) ** 2`}}function ke({exponent:r=1}={}){let t=+r;return{apply:e=>Math.sign(e)*Math.pow(Math.abs(e),t),invert:e=>Math.sign(e)*Math.pow(Math.abs(e),1/t),sqlApply:e=>(e=u(e),c`SIGN(${e}) * POW(ABS(${e}), ${t})`),sqlInvert:e=>c`SIGN(${e}) * POW(ABS(${e}), 1/${t})`}}function ot(){return{apply:r=>+r,invert:r=>new Date(r),sqlApply:r=>r instanceof Date?+r:B(u(r)),sqlInvert:G}}var He={linear:Be,log:Xe,symlog:Qe,sqrt:Ve,pow:ke,time:ot,utc:ot};function Ke(r){let t=He[r.type];return t?{...r,...t(r)}:null}function U(r,t,{replace:e=!1,temp:n=!0,view:o=!1}={}){return"CREATE"+(e?" OR REPLACE ":" ")+(n?"TEMP ":"")+(o?"VIEW":"TABLE")+(e?" ":" IF NOT EXISTS ")+r+" AS "+t}function ze(r){return`INSTALL ${r}; LOAD ${r}`}function st(r,{columns:t=Object.keys(r?.[0]||{})}={}){let e=[];if(Array.isArray(t)?(e=t,t=e.reduce((o,s)=>(o[s]=s,o),{})):t&&(e=Object.keys(t)),!e.length)throw new Error("Can not create table from empty column set.");let n=[];for(let o of r){let s=e.map(i=>`${$(o[i])} AS "${t[i]}"`);n.push(`(SELECT ${s.join(", ")})`)}return n.join(" UNION ALL ")}function j(r,t,e,n={},o={}){let{select:s=["*"],where:i,view:a,temp:p,replace:d,...y}=n,A=nr({...o,...y}),b=`${r}('${e}'${A?", "+A:""})`,I=i?` WHERE ${i}`:"",g=`SELECT ${s.join(", ")} FROM ${b}${I}`;return U(t,g,{view:a,temp:p,replace:d})}function Je(r,t,e){return j("read_csv",r,t,e,{auto_detect:!0,sample_size:-1})}function Ze(r,t,e){return j("read_json",r,t,e,{auto_detect:!0,json_format:"auto"})}function tr(r,t,e){return j("read_parquet",r,t,e)}function er(r,t,e={}){let{options:n,...o}=e;if(n){let s=Array.isArray(n)?n.join(", "):typeof n=="string"?n:Object.entries(n).map(([i,a])=>`${i}=${a}`).join(", ");o.open_options=s.toUpperCase()}return j("st_read",r,t,o)}function rr(r,t,e={}){let{select:n=["*"],...o}=e,s=st(t),i=n.length===1&&n[0]==="*"?s:`SELECT ${n} FROM ${s}`;return U(r,i,o)}function nr(r){return Object.entries(r).map(([t,e])=>`${t}=${Q(e)}`).join(", ")}function Q(r){switch(typeof r){case"boolean":return String(r);case"string":return`'${r}'`;case"undefined":case"object":return r==null?"NULL":Array.isArray(r)?"["+r.map(t=>Q(t)).join(", ")+"]":"{"+Object.entries(r).map(([t,e])=>`'${t}': ${Q(e)}`).join(", ")+"}";default:return r}}export{F as Query,N as Ref,zt as agg,ut as all,mt as and,De as argmax,Oe as argmin,Me as arrayAgg,u as asColumn,O as asRelation,ee as avg,v as cast,Ce as castDouble,Pe as castInteger,X as centroid,We as centroidX,Ye as centroidY,K as column,Ot as contains,$e as corr,te as count,Ee as covarPop,U as create,Bt as cume_dist,Ue as dateDay,Fe as dateMonth,Ge as dateMonthDay,Yt as dense_rank,ft as desc,ge as entropy,B as epoch_ms,yt as eq,Ie as first,kt as first_value,je as geojson,wt as gt,Tt as gte,bt as isBetween,Rt as isDistinct,Gt as isFinite,Ut as isInfinite,Ft as isNaN,It as isNotBetween,qt as isNotDistinct,Et as isNotNull,$t as isNull,T as isParamLike,P as isQuery,M as isSQLExpression,me as kurtosis,Qt as lag,Le as last,Ht as last_value,Vt as lead,Pt as length,ht as literal,$ as literalToSQL,Je as loadCSV,ze as loadExtension,Ze as loadJSON,rr as loadObjects,tr as loadParquet,er as loadSpatial,Mt as lower,St as lt,At as lte,ne as mad,oe as max,re as mean,ae as median,se as min,le as mode,Nt as neq,xt as not,Kt as nth_value,Xt as ntile,gt as or,vt as percent_rank,Dt as prefix,ce as product,ue as quantile,Wt as rank,Lt as regexp_matches,qe as regrAvgX,be as regrAvgY,Se as regrCount,ye as regrIntercept,we as regrR2,Te as regrSXX,Re as regrSXY,Ae as regrSYY,Ne as regrSlope,H as relation,jt as row_number,Ke as scaleTransform,he as skewness,c as sql,fe as stddev,xe as stddevPop,_e as stringAgg,_t as suffix,ie as sum,lt as toSQL,Ct as upper,de as varPop,pe as variance,rt as x,nt as y};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uwdata/mosaic-sql",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "SQL query construction and analysis.",
5
5
  "keywords": [
6
6
  "sql",
@@ -25,5 +25,5 @@
25
25
  "test": "mocha 'test/**/*-test.js'",
26
26
  "prepublishOnly": "npm run test && npm run lint && npm run build"
27
27
  },
28
- "gitHead": "4114465543a21b25d6d14647db7d95af875d2519"
28
+ "gitHead": "51517b28e916e355f4ce0dc6e98aef3a1db3f7b2"
29
29
  }
package/src/datetime.js CHANGED
@@ -2,8 +2,7 @@ import { sql } from './expression.js';
2
2
  import { asColumn } from './ref.js';
3
3
 
4
4
  export const epoch_ms = expr => {
5
- const d = asColumn(expr);
6
- return sql`(1000 * (epoch(${d}) - second(${d})) + millisecond(${d}))::DOUBLE`;
5
+ return sql`epoch_ms(${asColumn(expr)})`;
7
6
  };
8
7
 
9
8
  export const dateMonth = expr => {
package/src/index.js CHANGED
@@ -104,6 +104,15 @@ export {
104
104
  isInfinite
105
105
  } from './functions.js';
106
106
 
107
+ export {
108
+ centroid,
109
+ centroidX,
110
+ centroidY,
111
+ geojson,
112
+ x,
113
+ y
114
+ } from './spatial.js';
115
+
107
116
  export {
108
117
  row_number,
109
118
  rank,
@@ -128,10 +137,16 @@ export {
128
137
  literalToSQL
129
138
  } from './to-sql.js';
130
139
 
140
+ export {
141
+ scaleTransform
142
+ } from './scales.js';
143
+
131
144
  export { create } from './load/create.js';
145
+ export { loadExtension } from './load/extension.js';
132
146
  export {
133
147
  loadCSV,
134
148
  loadJSON,
135
149
  loadObjects,
136
- loadParquet
150
+ loadParquet,
151
+ loadSpatial
137
152
  } from './load/load.js';
@@ -0,0 +1,3 @@
1
+ export function loadExtension(name) {
2
+ return `INSTALL ${name}; LOAD ${name}`;
3
+ }
package/src/load/load.js CHANGED
@@ -22,6 +22,29 @@ export function loadParquet(tableName, fileName, options) {
22
22
  return load('read_parquet', tableName, fileName, options);
23
23
  }
24
24
 
25
+ /**
26
+ * Load geometry data within a spatial file format.
27
+ * This method requires that the DuckDB spatial extension is loaded.
28
+ * Supports GeoJSON, TopoJSON, and other comomn spatial formats.
29
+ * For TopoJSON, wet the layer option to indicate the feature to extract.
30
+ */
31
+ export function loadSpatial(tableName, fileName, options = {}) {
32
+ // nested options map to the open_options argument of st_read
33
+ const { options: opt, ...rest } = options;
34
+ if (opt) {
35
+ // TODO: check correct syntax for open_options
36
+ const open = Array.isArray(opt) ? opt.join(', ')
37
+ : typeof opt === 'string' ? opt
38
+ : Object.entries(opt)
39
+ .map(([key, value]) => `${key}=${value}`)
40
+ .join(', ');
41
+ rest.open_options = open.toUpperCase();
42
+ }
43
+ // TODO: handle box_2d for spatial_filter_box option
44
+ // TODO: handle wkb_blob for spatial_filter option
45
+ return load('st_read', tableName, fileName, rest);
46
+ }
47
+
25
48
  export function loadObjects(tableName, data, options = {}) {
26
49
  const { select = ['*'], ...opt } = options;
27
50
  const values = sqlFrom(data);
package/src/scales.js ADDED
@@ -0,0 +1,93 @@
1
+ import { epoch_ms } from './datetime.js';
2
+ import { sql } from './expression.js';
3
+ import { asColumn } from './ref.js';
4
+
5
+ const identity = x => x;
6
+
7
+ function scaleLinear() {
8
+ return {
9
+ apply: identity,
10
+ invert: identity,
11
+ sqlApply: asColumn,
12
+ sqlInvert: identity
13
+ };
14
+ }
15
+
16
+ function scaleLog({ base } = {}) {
17
+ if (base == null || base === Math.E) {
18
+ return {
19
+ apply: Math.log,
20
+ invert: Math.exp,
21
+ sqlApply: c => sql`LN(${asColumn(c)})`,
22
+ sqlInvert: c => sql`EXP(${c})`
23
+ };
24
+ } else if (base === 10) {
25
+ return {
26
+ apply: Math.log10,
27
+ invert: x => Math.pow(10, x),
28
+ sqlApply: c => sql`LOG(${asColumn(c)})`,
29
+ sqlInvert: c => sql`POW(10, ${c})`
30
+ };
31
+ } else {
32
+ const b = +base;
33
+ return {
34
+ apply: x => Math.log(x) / Math.log(b),
35
+ invert: x => Math.pow(b, x),
36
+ sqlApply: c => sql`LN(${asColumn(c)}) / LN(${b})`,
37
+ sqlInvert: c => sql`POW(${b}, ${c})`
38
+ };
39
+ }
40
+ }
41
+
42
+ function scaleSymlog({ constant = 1 } = {}) {
43
+ const _ = +constant;
44
+ return {
45
+ apply: x => Math.sign(x) * Math.log1p(Math.abs(x)),
46
+ invert: x => Math.sign(x) * Math.exp(Math.abs(x) - _),
47
+ sqlApply: c => (c = asColumn(c), sql`SIGN(${c}) * LN(${_} + ABS(${c}))`),
48
+ sqlInvert: c => sql`SIGN(${c}) * (EXP(ABS(${c})) - ${_})`
49
+ };
50
+ }
51
+
52
+ function scaleSqrt() {
53
+ return {
54
+ apply: x => Math.sign(x) * Math.sqrt(Math.abs(x)),
55
+ invert: x => Math.sign(x) * x * x,
56
+ sqlApply: c => (c = asColumn(c), sql`SIGN(${c}) * SQRT(ABS(${c}))`),
57
+ sqlInvert: c => sql`SIGN(${c}) * (${c}) ** 2`
58
+ };
59
+ }
60
+
61
+ function scalePow({ exponent = 1 } = {}) {
62
+ const e = +exponent;
63
+ return {
64
+ apply: x => Math.sign(x) * Math.pow(Math.abs(x), e),
65
+ invert: x => Math.sign(x) * Math.pow(Math.abs(x), 1/e),
66
+ sqlApply: c => (c = asColumn(c), sql`SIGN(${c}) * POW(ABS(${c}), ${e})`),
67
+ sqlInvert: c => sql`SIGN(${c}) * POW(ABS(${c}), 1/${e})`
68
+ };
69
+ }
70
+
71
+ function scaleTime() {
72
+ return {
73
+ apply: x => +x,
74
+ invert: x => new Date(x),
75
+ sqlApply: c => c instanceof Date ? +c : epoch_ms(asColumn(c)),
76
+ sqlInvert: identity
77
+ };
78
+ }
79
+
80
+ const scales = {
81
+ linear: scaleLinear,
82
+ log: scaleLog,
83
+ symlog: scaleSymlog,
84
+ sqrt: scaleSqrt,
85
+ pow: scalePow,
86
+ time: scaleTime,
87
+ utc: scaleTime
88
+ };
89
+
90
+ export function scaleTransform(options) {
91
+ const scale = scales[options.type];
92
+ return scale ? { ...options, ...scale(options) } : null;
93
+ }
package/src/spatial.js ADDED
@@ -0,0 +1,10 @@
1
+ import { functionCall } from './functions.js';
2
+
3
+ export const geojson = functionCall('ST_AsGeoJSON');
4
+
5
+ export const x = functionCall('ST_X');
6
+ export const y = functionCall('ST_Y');
7
+
8
+ export const centroid = functionCall('ST_CENTROID');
9
+ export const centroidX = geom => x(centroid(geom));
10
+ export const centroidY = geom => y(centroid(geom));