@uwdata/mosaic-sql 0.3.5 → 0.5.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
@@ -522,6 +522,14 @@ var dateDay = (expr) => {
522
522
  return sql`MAKE_DATE(2012, 1, DAY(${d}))`.annotate({ label: "date" });
523
523
  };
524
524
 
525
+ // src/spatial.js
526
+ var geojson = functionCall("ST_AsGeoJSON");
527
+ var x = functionCall("ST_X");
528
+ var y = functionCall("ST_Y");
529
+ var centroid = functionCall("ST_CENTROID");
530
+ var centroidX = (geom) => x(centroid(geom));
531
+ var centroidY = (geom) => y(centroid(geom));
532
+
525
533
  // src/Query.js
526
534
  var Query = class _Query {
527
535
  static select(...expr) {
@@ -669,7 +677,7 @@ var Query = class _Query {
669
677
  return query.where;
670
678
  } else {
671
679
  query.where = query.where.concat(
672
- expr.flat().filter((x) => x)
680
+ expr.flat().filter((x2) => x2)
673
681
  );
674
682
  return this;
675
683
  }
@@ -684,7 +692,7 @@ var Query = class _Query {
684
692
  return query.groupby;
685
693
  } else {
686
694
  query.groupby = query.groupby.concat(
687
- expr.flat().filter((x) => x).map(asColumn)
695
+ expr.flat().filter((x2) => x2).map(asColumn)
688
696
  );
689
697
  return this;
690
698
  }
@@ -699,7 +707,7 @@ var Query = class _Query {
699
707
  return query.having;
700
708
  } else {
701
709
  query.having = query.having.concat(
702
- expr.flat().filter((x) => x)
710
+ expr.flat().filter((x2) => x2)
703
711
  );
704
712
  return this;
705
713
  }
@@ -728,7 +736,7 @@ var Query = class _Query {
728
736
  return query.qualify;
729
737
  } else {
730
738
  query.qualify = query.qualify.concat(
731
- expr.flat().filter((x) => x)
739
+ expr.flat().filter((x2) => x2)
732
740
  );
733
741
  return this;
734
742
  }
@@ -739,7 +747,7 @@ var Query = class _Query {
739
747
  return query.orderby;
740
748
  } else {
741
749
  query.orderby = query.orderby.concat(
742
- expr.flat().filter((x) => x).map(asColumn)
750
+ expr.flat().filter((x2) => x2).map(asColumn)
743
751
  );
744
752
  return this;
745
753
  }
@@ -810,7 +818,7 @@ var Query = class _Query {
810
818
  sql2.push(`FROM ${rels.join(", ")}`);
811
819
  }
812
820
  if (where.length) {
813
- const clauses = where.map(String).filter((x) => x).join(" AND ");
821
+ const clauses = where.map(String).filter((x2) => x2).join(" AND ");
814
822
  if (clauses)
815
823
  sql2.push(`WHERE ${clauses}`);
816
824
  }
@@ -824,7 +832,7 @@ var Query = class _Query {
824
832
  sql2.push(`GROUP BY ${groupby.join(", ")}`);
825
833
  }
826
834
  if (having.length) {
827
- const clauses = having.map(String).filter((x) => x).join(" AND ");
835
+ const clauses = having.map(String).filter((x2) => x2).join(" AND ");
828
836
  if (clauses)
829
837
  sql2.push(`HAVING ${clauses}`);
830
838
  }
@@ -833,7 +841,7 @@ var Query = class _Query {
833
841
  sql2.push(`WINDOW ${windows.join(", ")}`);
834
842
  }
835
843
  if (qualify.length) {
836
- const clauses = qualify.map(String).filter((x) => x).join(" AND ");
844
+ const clauses = qualify.map(String).filter((x2) => x2).join(" AND ");
837
845
  if (clauses)
838
846
  sql2.push(`QUALIFY ${clauses}`);
839
847
  }
@@ -866,7 +874,7 @@ var SetOperation = class _SetOperation {
866
874
  return query.orderby;
867
875
  } else {
868
876
  query.orderby = query.orderby.concat(
869
- expr.flat().filter((x) => x).map(asColumn)
877
+ expr.flat().filter((x2) => x2).map(asColumn)
870
878
  );
871
879
  return this;
872
880
  }
@@ -929,6 +937,11 @@ function create(name, query, {
929
937
  return "CREATE" + (replace ? " OR REPLACE " : " ") + (temp ? "TEMP " : "") + (view ? "VIEW" : "TABLE") + (replace ? " " : " IF NOT EXISTS ") + name + " AS " + query;
930
938
  }
931
939
 
940
+ // src/load/extension.js
941
+ function loadExtension(name) {
942
+ return `INSTALL ${name}; LOAD ${name}`;
943
+ }
944
+
932
945
  // src/load/sql-from.js
933
946
  function sqlFrom(data, {
934
947
  columns = Object.keys(data?.[0] || {})
@@ -969,6 +982,14 @@ function loadJSON(tableName, fileName, options) {
969
982
  function loadParquet(tableName, fileName, options) {
970
983
  return load("read_parquet", tableName, fileName, options);
971
984
  }
985
+ function loadSpatial(tableName, fileName, options = {}) {
986
+ const { options: opt, ...rest } = options;
987
+ if (opt) {
988
+ const open = Array.isArray(opt) ? opt.join(", ") : typeof opt === "string" ? opt : Object.entries(opt).map(([key, value]) => `${key}=${value}`).join(", ");
989
+ rest.open_options = open.toUpperCase();
990
+ }
991
+ return load("st_read", tableName, fileName, rest);
992
+ }
972
993
  function loadObjects(tableName, data, options = {}) {
973
994
  const { select = ["*"], ...opt } = options;
974
995
  const values = sqlFrom(data);
@@ -1012,6 +1033,9 @@ export {
1012
1033
  cast,
1013
1034
  castDouble,
1014
1035
  castInteger,
1036
+ centroid,
1037
+ centroidX,
1038
+ centroidY,
1015
1039
  column,
1016
1040
  contains,
1017
1041
  corr,
@@ -1029,6 +1053,7 @@ export {
1029
1053
  eq,
1030
1054
  first,
1031
1055
  first_value,
1056
+ geojson,
1032
1057
  gt,
1033
1058
  gte,
1034
1059
  isBetween,
@@ -1052,9 +1077,11 @@ export {
1052
1077
  literal,
1053
1078
  literalToSQL,
1054
1079
  loadCSV,
1080
+ loadExtension,
1055
1081
  loadJSON,
1056
1082
  loadObjects,
1057
1083
  loadParquet,
1084
+ loadSpatial,
1058
1085
  lower,
1059
1086
  lt,
1060
1087
  lte,
@@ -1096,5 +1123,7 @@ export {
1096
1123
  toSQL,
1097
1124
  upper,
1098
1125
  varPop,
1099
- variance
1126
+ variance,
1127
+ x,
1128
+ y
1100
1129
  };
@@ -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?`${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"?H(r):r}function I(r){return typeof r=="string"?k(r):r}function k(r){return new N(r)}function H(r,t){return arguments.length===1&&(t=r,r=null),new N(r,t)}function it(r){return new N(r,"*")}function ct(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 R=r=>typeof r?.addEventListener=="function";function _(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=>R(s));o.length>0?(this._params=Array.from(new Set(o)),this._params.forEach(s=>{s.addEventListener("value",()=>at(this,this.map?.get("value")))})):this.addEventListener=void 0}get value(){return this}get columns(){let{_params:t,_deps:e}=this;if(t){let n=new Set(t.flatMap(o=>{let s=o.value?.columns;return Array.isArray(s)?s:[]}));if(n.size){let o=new Set(e);return n.forEach(s=>o.add(s)),Array.from(o)}}return e}get column(){return this._deps.length?this._deps[0]:this.columns[0]}annotate(...t){return Object.assign(this,...t)}toString(){return this._expr.map(t=>R(t)&&!_(t)?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 at(r,t){if(t?.size)return Promise.allSettled(Array.from(t,e=>e(r)))}function M(r,t){let e=[r[0]],n=new Set,o=t.length;for(let s=0,i=0;s<o;){let c=t[s];R(c)?e[++i]=c:(Array.isArray(c?.columns)&&c.columns.forEach(x=>n.add(x)),e[i]+=typeof c=="string"?c:E(c));let p=r[++s];R(e[i])?e[++i]=p:e[i]+=p}return{spans:e,cols:Array.from(n)}}function u(r,...t){let{spans:e,cols:n}=M(r,t);return new S(e,n)}function ut(r){let t=l(r);return u`${t} DESC NULLS LAST`.annotate({label:t?.label,desc:!0})}var lt=r=>({value:r,toString:()=>E(r)});function D(r){r(this.op,this),this.children?.forEach(t=>t.visit(r))}function K(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(")")),u(n,...e).annotate({op:r,children:e,visit:D})}var pt=(...r)=>K("AND",r.flat()),ft=(...r)=>K("OR",r.flat()),ht=r=>t=>u`(${r} ${l(t)})`.annotate({op:r,a:t,visit:D}),mt=ht("NOT"),v=r=>t=>u`(${l(t)} ${r})`.annotate({op:r,a:t,visit:D}),gt=v("IS NULL"),xt=v("IS NOT NULL"),w=r=>(t,e)=>u`(${l(t)} ${r} ${l(e)})`.annotate({op:r,a:t,b:e,visit:D}),dt=w("="),Et=w("<>"),$t=w("<"),yt=w(">"),Nt=w("<="),St=w(">="),wt=w("IS DISTINCT FROM"),At=w("IS NOT DISTINCT FROM");function z(r,t,e,n){t=l(t);let o=r.startsWith("NOT ")?"NOT ":"";return(e?n?u`${o}(${e[0]} <= ${t} AND ${t} < ${e[1]})`:u`(${t} ${r} ${e[0]} AND ${e[1]})`:u``).annotate({op:r,visit:D,field:t,range:e})}var Rt=(r,t,e)=>z("BETWEEN",r,t,e),Tt=(r,t,e)=>z("NOT BETWEEN",r,t,e);function T(r,t){return Array.from({length:r},()=>t)}function m(r,t){return(...e)=>{let n=e.map(l),o=t?`::${t}`:"";return(n.length?u([`${r}(`,...T(n.length-1,", "),`)${o}`],...n):u`${r}()${o}`).annotate({func:r,args:n})}}var bt=m("REGEXP_MATCHES"),Lt=m("CONTAINS"),Ot=m("PREFIX"),qt=m("SUFFIX"),It=m("LOWER"),Dt=m("UPPER"),Ct=m("LENGTH"),_t=m("ISNAN"),Ft=m("ISFINITE"),Pt=m("ISINF");var C=class r extends S{constructor(t,e,n,o,s="",i="",c=""){let p;if(o&&!(s||i||c))p=o?u`${e} OVER "${o}"`:u`${e} OVER ()`;else{let L=s&&i?" ":"",O=(s||i)&&c?" ":"";p=u`${e} OVER (${o?`"${o}" `:""}${s}${L}${i}${O}${c})`}n&&(p=u`(${p})::${n}`);let{_expr:y,_deps:A}=p;super(y,A,{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=u(["PARTITION BY ",T(e.length-1,", "),""],...e),{window:o,func:s,type:i,name:c,order:p,frame:x}=this;return new r(o,s,i,c,n,p,x)}orderby(...t){let e=t.flat().filter(y=>y).map(l),n=u(["ORDER BY ",T(e.length-1,", "),""],...e),{window:o,func:s,type:i,name:c,group:p,frame:x}=this;return new r(o,s,i,c,p,n,x)}rows(t){let e=J("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=J("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 J(r,t){if(R(t)){let e=u`${t}`;return e.toString=()=>`${r} ${Z(t.value)}`,e}return`${r} ${Z(t)}`}function Z(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=m(r)(...e);return new C(r,n,t)}}var Ut=$("ROW_NUMBER","INTEGER"),jt=$("RANK","INTEGER"),Gt=$("DENSE_RANK","INTEGER"),Mt=$("PERCENT_RANK"),Yt=$("CUME_DIST"),Wt=$("NTILE"),Xt=$("LAG"),Bt=$("LEAD"),Qt=$("FIRST_VALUE"),Vt=$("LAST_VALUE"),kt=$("NTH_VALUE");function Ht(r,...t){return u(r,...t).annotate({aggregate:!0})}var Y=class r extends S{constructor(t,e,n,o,s){e=(e||[]).map(l);let{strings:i,exprs:c}=Kt(t,e,n,o,s),{spans:p,cols:x}=M(i,c);super(p,x,{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(vt).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 Kt(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 vt(r){let t=E(r);return t&&t.startsWith('"')&&t.endsWith('"')?t.slice(1,-1):t}function a(r,t){return(...e)=>new Y(r,e,t)}var zt=a("COUNT","INTEGER"),Jt=a("AVG"),Zt=a("AVG"),te=a("MAD"),ee=a("MAX"),re=a("MIN"),ne=a("SUM","DOUBLE"),oe=a("PRODUCT"),se=a("MEDIAN"),ie=a("QUANTILE"),ce=a("MODE"),ae=a("VARIANCE"),ue=a("STDDEV"),le=a("SKEWNESS"),pe=a("KURTOSIS"),fe=a("ENTROPY"),he=a("VAR_POP"),me=a("STDDEV_POP"),ge=a("CORR"),xe=a("COVAR_POP"),de=a("REGR_INTERCEPT"),Ee=a("REGR_SLOPE"),$e=a("REGR_COUNT"),ye=a("REGR_R2"),Ne=a("REGR_SYY"),Se=a("REGR_SXX"),we=a("REGR_SXY"),Ae=a("REGR_AVGX"),Re=a("REGR_AVGY"),Te=a("FIRST"),be=a("LAST"),Le=a("ARG_MIN"),Oe=a("ARG_MAX"),qe=a("STRING_AGG"),Ie=a("ARRAY_AGG");function W(r,t){let e=l(r),n=u`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 De=r=>W(r,"DOUBLE"),Ce=r=>W(r,"INTEGER");var _e=r=>{let t=l(r);return u`(1000 * (epoch(${t}) - second(${t})) + millisecond(${t}))::DOUBLE`},Fe=r=>{let t=l(r);return u`MAKE_DATE(2012, MONTH(${t}), 1)`.annotate({label:"month"})},Pe=r=>{let t=l(r);return u`MAKE_DATE(2012, MONTH(${t}), DAY(${t}))`.annotate({label:"date"})},Ue=r=>{let t=l(r);return u`MAKE_DATE(2012, 1, DAY(${t}))`.annotate({label:"date"})};var je=m("ST_AsGeoJSON"),tt=m("ST_X"),et=m("ST_Y"),X=m("ST_CENTROID"),Ge=r=>tt(X(r)),Me=r=>et(X(r));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:x,orderby:y,limit:A,offset:L,with:O}=this.query,g=[];if(O.length){let f=O.map(({as:h,query:d})=>`"${h}" AS (${d})`);g.push(`WITH ${f.join(", ")}`)}let nt=t.map(({as:f,expr:h})=>V(h,f)&&!h.table?`${h}`:`${h} AS "${f}"`);if(g.push(`SELECT${e?" DISTINCT":""} ${nt.join(", ")}`),n.length){let f=n.map(({as:h,from:d})=>{let q=P(d)?`(${d})`:`${d}`;return!h||h===d.table?q:`${q} 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:d,seed:q}=o,ot=f?`${f} ROWS`:`${h} PERCENT`,st=d?` (${d}${q!=null?`, ${q}`:""})`:"";g.push(`USING SAMPLE ${ot}${st}`)}if(i.length&&g.push(`GROUP BY ${i.join(", ")}`),c.length){let f=c.map(String).filter(h=>h).join(" AND ");f&&g.push(`HAVING ${f}`)}if(p.length){let f=p.map(({as:h,expr:d})=>`"${h}" AS (${d})`);g.push(`WINDOW ${f.join(", ")}`)}if(x.length){let f=x.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(L)&&g.push(`OFFSET ${L}`),g.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 Ye(r)?r.slice(1,-1):r}function Ye(r){return r[0]==='"'&&r[r.length-1]==='"'}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 We(r){return`INSTALL ${r}; LOAD ${r}`}function rt(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 G(r,t,e,n={},o={}){let{select:s=["*"],where:i,view:c,temp:p,replace:x,...y}=n,A=He({...o,...y}),L=`${r}('${e}'${A?", "+A:""})`,O=i?` WHERE ${i}`:"",g=`SELECT ${s.join(", ")} FROM ${L}${O}`;return j(t,g,{view:c,temp:p,replace:x})}function Xe(r,t,e){return G("read_csv",r,t,e,{auto_detect:!0,sample_size:-1})}function Be(r,t,e){return G("read_json",r,t,e,{auto_detect:!0,json_format:"auto"})}function Qe(r,t,e){return G("read_parquet",r,t,e)}function Ve(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,c])=>`${i}=${c}`).join(", ");o.open_options=s.toUpperCase()}return G("st_read",r,t,o)}function ke(r,t,e={}){let{select:n=["*"],...o}=e,s=rt(t),i=n.length===1&&n[0]==="*"?s:`SELECT ${n} FROM ${s}`;return j(r,i,o)}function He(r){return Object.entries(r).map(([t,e])=>`${t}=${B(e)}`).join(", ")}function B(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=>B(t)).join(", ")+"]":"{"+Object.entries(r).map(([t,e])=>`'${t}': ${B(e)}`).join(", ")+"}";default:return r}}export{U as Query,N as Ref,Ht as agg,it as all,pt as and,Oe as argmax,Le as argmin,Ie as arrayAgg,l as asColumn,I as asRelation,Jt as avg,W as cast,De as castDouble,Ce as castInteger,X as centroid,Ge as centroidX,Me as centroidY,H as column,Lt as contains,ge as corr,zt as count,xe as covarPop,j as create,Yt as cume_dist,Ue as dateDay,Fe as dateMonth,Pe as dateMonthDay,Gt as dense_rank,ut as desc,fe as entropy,_e as epoch_ms,dt as eq,Te as first,Qt as first_value,je as geojson,yt as gt,St as gte,Rt as isBetween,wt as isDistinct,Ft as isFinite,Pt as isInfinite,_t as isNaN,Tt as isNotBetween,At as isNotDistinct,xt as isNotNull,gt as isNull,R as isParamLike,P as isQuery,_ as isSQLExpression,pe as kurtosis,Xt as lag,be as last,Vt as last_value,Bt as lead,Ct as length,lt as literal,E as literalToSQL,Xe as loadCSV,We as loadExtension,Be as loadJSON,ke as loadObjects,Qe as loadParquet,Ve as loadSpatial,It as lower,$t as lt,Nt as lte,te as mad,ee as max,Zt as mean,se as median,re as min,ce as mode,Et as neq,mt as not,kt as nth_value,Wt as ntile,ft as or,Mt as percent_rank,Ot as prefix,oe as product,ie as quantile,jt as rank,bt as regexp_matches,Ae as regrAvgX,Re as regrAvgY,$e as regrCount,de as regrIntercept,ye as regrR2,Se as regrSXX,we as regrSXY,Ne as regrSYY,Ee as regrSlope,k as relation,Ut as row_number,le as skewness,u as sql,ue as stddev,me as stddevPop,qe as stringAgg,qt as suffix,ne as sum,ct as toSQL,Dt as upper,he as varPop,ae as variance,tt as x,et as y};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uwdata/mosaic-sql",
3
- "version": "0.3.5",
3
+ "version": "0.5.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": "7cc66d26c687a28036b3c7102045f2196572847b"
28
+ "gitHead": "92886dddfb126c1439924c5a0189e4639c3519a7"
29
29
  }
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,
@@ -129,9 +138,11 @@ export {
129
138
  } from './to-sql.js';
130
139
 
131
140
  export { create } from './load/create.js';
141
+ export { loadExtension } from './load/extension.js';
132
142
  export {
133
143
  loadCSV,
134
144
  loadJSON,
135
145
  loadObjects,
136
- loadParquet
146
+ loadParquet,
147
+ loadSpatial
137
148
  } 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/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));