@malloydata/malloy 0.0.32-dev230428002803 → 0.0.32-dev230506172904

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.
@@ -59,7 +59,7 @@ export declare abstract class Dialect {
59
59
  abstract sqlRegexpMatch(expr: Expr, regex: string): Expr;
60
60
  getFunctionInfo(functionName: string): FunctionInfo | undefined;
61
61
  dialectExpr(df: DialectFragment): Expr;
62
- sqlSumDistinct(_key: string, _value: string): string;
62
+ sqlSumDistinct(_key: string, _value: string, _funcName: string): string;
63
63
  sqlSampleTable(tableSQL: string, sample: Sampling | undefined): string;
64
64
  sqlOrderBy(orderTerms: string[]): string;
65
65
  }
@@ -68,7 +68,7 @@ class Dialect {
68
68
  return [this.sqlLiteralString(df.literal)];
69
69
  }
70
70
  }
71
- sqlSumDistinct(_key, _value) {
71
+ sqlSumDistinct(_key, _value, _funcName) {
72
72
  return 'sqlSumDistinct called bu not implemented';
73
73
  }
74
74
  sqlSampleTable(tableSQL, sample) {
@@ -25,7 +25,7 @@ export declare class DuckDBDialect extends Dialect {
25
25
  sqlAnyValueTurtle(groupSet: number, fieldList: DialectFieldList): string;
26
26
  sqlAnyValueLastTurtle(name: string, groupSet: number, sqlName: string): string;
27
27
  sqlCoaleseMeasuresInline(groupSet: number, fieldList: DialectFieldList): string;
28
- sqlUnnestAlias(source: string, alias: string, _fieldList: DialectFieldList, _needDistinctKey: boolean): string;
28
+ sqlUnnestAlias(source: string, alias: string, _fieldList: DialectFieldList, needDistinctKey: boolean): string;
29
29
  sqlSumDistinctHashedKey(_sqlDistinctKey: string): string;
30
30
  sqlGenerateUUID(): string;
31
31
  sqlDateToString(sqlDateExp: string): string;
@@ -45,7 +45,7 @@ export declare class DuckDBDialect extends Dialect {
45
45
  sqlCast(cast: TypecastFragment): Expr;
46
46
  sqlRegexpMatch(expr: Expr, regexp: string): Expr;
47
47
  sqlLiteralTime(timeString: string, type: TimeFieldType, _timezone: string): string;
48
- sqlSumDistinct(key: string, value: string): string;
48
+ sqlSumDistinct(key: string, value: string, funcName: string): string;
49
49
  sqlSampleTable(tableSQL: string, sample: Sampling | undefined): string;
50
50
  sqlOrderBy(orderTerms: string[]): string;
51
51
  sqlLiteralString(literal: string): string;
@@ -129,11 +129,11 @@ class DuckDBDialect extends dialect_1.Dialect {
129
129
  this.stringTypeName = 'VARCHAR';
130
130
  this.divisionIsInteger = true;
131
131
  this.supportsSumDistinctFunction = true;
132
- this.unnestWithNumbers = true;
132
+ this.unnestWithNumbers = false;
133
133
  this.defaultSampling = { rows: 50000 };
134
134
  this.supportUnnestArrayAgg = true;
135
135
  this.supportsCTEinCoorelatedSubQueries = true;
136
- this.dontUnionIndex = false;
136
+ this.dontUnionIndex = true;
137
137
  this.supportsQualify = true;
138
138
  this.functionInfo = {
139
139
  concat: { returnType: 'string' },
@@ -183,13 +183,27 @@ class DuckDBDialect extends dialect_1.Dialect {
183
183
  .join(', ');
184
184
  return `COALESCE(FIRST({${fields}}) FILTER(WHERE group_set=${groupSet}), {${nullValues}})`;
185
185
  }
186
- sqlUnnestAlias(source, alias, _fieldList, _needDistinctKey) {
187
- return `LEFT JOIN (select UNNEST(generate_series(1,
188
- 100000, --
189
- -- (SELECT genres_length FROM movies limit 1),
190
- 1)) as __row_id) as ${alias} ON ${alias}.__row_id <= array_length(${source})`;
191
- // When DuckDB supports lateral joins...
192
- //return `,(select UNNEST(generate_series(1, length(${source}),1))) as ${alias}(__row_id)`;
186
+ // sqlUnnestAlias(
187
+ // source: string,
188
+ // alias: string,
189
+ // _fieldList: DialectFieldList,
190
+ // _needDistinctKey: boolean
191
+ // ): string {
192
+ // return `LEFT JOIN (select UNNEST(generate_series(1,
193
+ // 100000, --
194
+ // -- (SELECT genres_length FROM movies limit 1),
195
+ // 1)) as __row_id) as ${alias} ON ${alias}.__row_id <= array_length(${source})`;
196
+ // // When DuckDB supports lateral joins...
197
+ // //return `,(select UNNEST(generate_series(1, length(${source}),1))) as ${alias}(__row_id)`;
198
+ // }
199
+ sqlUnnestAlias(source, alias, _fieldList, needDistinctKey) {
200
+ //Simulate left joins by guarenteeing there is at least one row.
201
+ if (!needDistinctKey) {
202
+ return `LEFT JOIN LATERAL (SELECT UNNEST(${source}), 1 as ignoreme) as ${alias}_outer(${alias},ignoreme) ON ${alias}_outer.ignoreme=1`;
203
+ }
204
+ else {
205
+ return `LEFT JOIN LATERAL (SELECT UNNEST(GENERATE_SERIES(1, length(${source}),1)) as __row_id, UNNEST(${source}), 1 as ignoreme) as ${alias}_outer(__row_id, ${alias},ignoreme) ON ${alias}_outer.ignoreme=1`;
206
+ }
193
207
  }
194
208
  sqlSumDistinctHashedKey(_sqlDistinctKey) {
195
209
  return 'uses sumDistinctFunction, should not be called';
@@ -201,7 +215,11 @@ class DuckDBDialect extends dialect_1.Dialect {
201
215
  return `(${sqlDateExp})::date::varchar`;
202
216
  }
203
217
  sqlFieldReference(alias, fieldName, _fieldType, _isNested, isArray) {
204
- if (isArray) {
218
+ // LTNOTE: hack, in duckdb we can't have structs as tables so we kind of simulate it.
219
+ if (fieldName === '__row_id') {
220
+ return `${alias}_outer.__row_id`;
221
+ }
222
+ else if (isArray) {
205
223
  return alias;
206
224
  }
207
225
  else {
@@ -321,10 +339,10 @@ class DuckDBDialect extends dialect_1.Dialect {
321
339
  throw new Error(`Unknown Literal time format ${type}`);
322
340
  }
323
341
  }
324
- sqlSumDistinct(key, value) {
342
+ sqlSumDistinct(key, value, funcName) {
325
343
  // return `sum_distinct(list({key:${key}, val: ${value}}))`;
326
344
  return `(
327
- SELECT sum(a.val) as value
345
+ SELECT ${funcName}(a.val) as value
328
346
  FROM (
329
347
  SELECT UNNEST(list(distinct {key:${key}, val: ${value}})) a
330
348
  )
@@ -45,7 +45,7 @@ export declare class PostgresDialect extends Dialect {
45
45
  sqlLiteralTime(timeString: string, type: TimeFieldType, _timezone: string): string;
46
46
  getFunctionInfo(functionName: string): FunctionInfo | undefined;
47
47
  sqlMeasureTime(from: TimeValue, to: TimeValue, units: string): Expr;
48
- sqlSumDistinct(key: string, value: string): string;
48
+ sqlSumDistinct(key: string, value: string, funcName: string): string;
49
49
  sqlSampleTable(tableSQL: string, sample: Sampling | undefined): string;
50
50
  sqlOrderBy(orderTerms: string[]): string;
51
51
  sqlLiteralString(literal: string): string;
@@ -296,10 +296,10 @@ class PostgresDialect extends dialect_1.Dialect {
296
296
  }
297
297
  throw new Error(`Unknown or unhandled postgres time unit: ${units}`);
298
298
  }
299
- sqlSumDistinct(key, value) {
299
+ sqlSumDistinct(key, value, funcName) {
300
300
  // return `sum_distinct(list({key:${key}, val: ${value}}))`;
301
301
  return `(
302
- SELECT sum((a::json->>'f2')::DOUBLE PRECISION) as value
302
+ SELECT ${funcName}((a::json->>'f2')::DOUBLE PRECISION) as value
303
303
  FROM (
304
304
  SELECT UNNEST(array_agg(distinct row_to_json(row(${key},${value}))::text)) a
305
305
  ) a
@@ -290,7 +290,7 @@ class QueryField extends QueryNode {
290
290
  let ret;
291
291
  if (distinctKeySQL) {
292
292
  if (this.parent.dialect.supportsSumDistinctFunction) {
293
- ret = this.parent.dialect.sqlSumDistinct(distinctKeySQL, dimSQL);
293
+ ret = this.parent.dialect.sqlSumDistinct(distinctKeySQL, dimSQL, 'SUM');
294
294
  }
295
295
  else {
296
296
  ret = sqlSumDistinct(this.parent.dialect, dimSQL, distinctKeySQL);
@@ -318,13 +318,15 @@ class QueryField extends QueryNode {
318
318
  countDistinctKeySQL = `CASE WHEN ${state.whereSQL} THEN ${distinctKeySQL} END`;
319
319
  }
320
320
  let sumDistinctSQL;
321
+ let avgDistinctSQL;
321
322
  if (this.parent.dialect.supportsSumDistinctFunction) {
322
- sumDistinctSQL = this.parent.dialect.sqlSumDistinct(distinctKeySQL, dimSQL);
323
+ avgDistinctSQL = this.parent.dialect.sqlSumDistinct(distinctKeySQL, dimSQL, 'AVG');
323
324
  }
324
325
  else {
325
326
  sumDistinctSQL = sqlSumDistinct(this.parent.dialect, dimSQL, distinctKeySQL);
327
+ avgDistinctSQL = `(${sumDistinctSQL})/NULLIF(COUNT(DISTINCT CASE WHEN ${dimSQL} IS NOT NULL THEN ${countDistinctKeySQL} END),0)`;
326
328
  }
327
- return `(${sumDistinctSQL})/NULLIF(COUNT(DISTINCT ${countDistinctKeySQL}),0)`;
329
+ return avgDistinctSQL;
328
330
  }
329
331
  else {
330
332
  return `AVG(${dimSQL})`;
@@ -1667,7 +1669,7 @@ class QueryQuery extends QueryField {
1667
1669
  let structSQL = qs.structSourceSQL(stageWriter);
1668
1670
  if ((0, malloy_types_1.isJoinOn)(structRelationship)) {
1669
1671
  if (ji.makeUniqueKey) {
1670
- structSQL = `(SELECT ${qs.dialect.sqlGenerateUUID()} as __distinct_key, * FROM ${structSQL})`;
1672
+ structSQL = `(SELECT ${qs.dialect.sqlGenerateUUID()} as __distinct_key, * FROM ${structSQL} as x)`;
1671
1673
  }
1672
1674
  let onCondition = '';
1673
1675
  if (qs.parent === undefined) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/malloy",
3
- "version": "0.0.32-dev230428002803",
3
+ "version": "0.0.32-dev230506172904",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",