@malloydata/malloy 0.0.177-dev240828173040 → 0.0.177-dev240829030921

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.
Files changed (121) hide show
  1. package/dist/dialect/dialect.d.ts +23 -13
  2. package/dist/dialect/dialect.js +33 -27
  3. package/dist/dialect/duckdb/duckdb.d.ts +7 -11
  4. package/dist/dialect/duckdb/duckdb.js +34 -100
  5. package/dist/dialect/duckdb/functions/greatest_and_least.js +5 -12
  6. package/dist/dialect/functions/concat.js +1 -1
  7. package/dist/dialect/functions/greatest_and_least.js +1 -1
  8. package/dist/dialect/functions/simple_numeric_functions.js +1 -1
  9. package/dist/dialect/functions/sql.js +5 -15
  10. package/dist/dialect/functions/string_agg.js +2 -2
  11. package/dist/dialect/functions/trim_functions.js +2 -2
  12. package/dist/dialect/functions/util.d.ts +6 -9
  13. package/dist/dialect/functions/util.js +29 -38
  14. package/dist/dialect/index.d.ts +1 -1
  15. package/dist/dialect/index.js +1 -2
  16. package/dist/dialect/pg_impl.d.ts +15 -0
  17. package/dist/dialect/pg_impl.js +91 -0
  18. package/dist/dialect/postgres/functions/greatest_and_least.js +1 -3
  19. package/dist/dialect/postgres/functions/string_agg.js +2 -2
  20. package/dist/dialect/postgres/postgres.d.ts +7 -11
  21. package/dist/dialect/postgres/postgres.js +29 -92
  22. package/dist/dialect/snowflake/functions/string_agg.js +2 -2
  23. package/dist/dialect/snowflake/snowflake.d.ts +9 -9
  24. package/dist/dialect/snowflake/snowflake.js +41 -48
  25. package/dist/dialect/standardsql/functions/string_agg.js +4 -4
  26. package/dist/dialect/standardsql/standardsql.d.ts +9 -9
  27. package/dist/dialect/standardsql/standardsql.js +56 -51
  28. package/dist/dialect/trino/functions/concat.js +1 -1
  29. package/dist/dialect/trino/functions/string_agg.js +2 -2
  30. package/dist/dialect/trino/trino.d.ts +11 -12
  31. package/dist/dialect/trino/trino.js +59 -83
  32. package/dist/index.d.ts +3 -3
  33. package/dist/index.js +3 -4
  34. package/dist/lang/ast/ast-utils.d.ts +1 -1
  35. package/dist/lang/ast/ast-utils.js +2 -2
  36. package/dist/lang/ast/expressions/apply.js +1 -2
  37. package/dist/lang/ast/expressions/binary-boolean.d.ts +2 -1
  38. package/dist/lang/ast/expressions/binary-boolean.js +6 -3
  39. package/dist/lang/ast/expressions/binary-numeric.d.ts +2 -1
  40. package/dist/lang/ast/expressions/boolean.js +1 -1
  41. package/dist/lang/ast/expressions/constant-expression.d.ts +3 -3
  42. package/dist/lang/ast/expressions/constant-expression.js +0 -23
  43. package/dist/lang/ast/expressions/expr-aggregate-function.js +24 -34
  44. package/dist/lang/ast/expressions/expr-alternation-tree.d.ts +6 -3
  45. package/dist/lang/ast/expressions/expr-alternation-tree.js +10 -5
  46. package/dist/lang/ast/expressions/expr-cast.js +1 -2
  47. package/dist/lang/ast/expressions/expr-coalesce.js +4 -1
  48. package/dist/lang/ast/expressions/expr-compare.d.ts +3 -3
  49. package/dist/lang/ast/expressions/expr-count-distinct.js +1 -1
  50. package/dist/lang/ast/expressions/expr-count.js +3 -3
  51. package/dist/lang/ast/expressions/expr-func.js +15 -18
  52. package/dist/lang/ast/expressions/expr-granular-time.js +8 -10
  53. package/dist/lang/ast/expressions/expr-id-reference.js +2 -2
  54. package/dist/lang/ast/expressions/expr-minus.js +5 -4
  55. package/dist/lang/ast/expressions/expr-not.js +1 -1
  56. package/dist/lang/ast/expressions/expr-now.js +1 -6
  57. package/dist/lang/ast/expressions/expr-null.js +1 -1
  58. package/dist/lang/ast/expressions/expr-number.js +1 -1
  59. package/dist/lang/ast/expressions/expr-parens.js +1 -1
  60. package/dist/lang/ast/expressions/expr-props.js +4 -7
  61. package/dist/lang/ast/expressions/expr-regex.js +1 -3
  62. package/dist/lang/ast/expressions/expr-string.js +1 -7
  63. package/dist/lang/ast/expressions/expr-time-extract.js +12 -16
  64. package/dist/lang/ast/expressions/expr-time.d.ts +2 -2
  65. package/dist/lang/ast/expressions/expr-time.js +4 -6
  66. package/dist/lang/ast/expressions/expr-ungroup.js +2 -2
  67. package/dist/lang/ast/expressions/for-range.d.ts +2 -1
  68. package/dist/lang/ast/expressions/function-ordering.js +5 -5
  69. package/dist/lang/ast/expressions/partial-compare.d.ts +3 -3
  70. package/dist/lang/ast/expressions/pick-when.js +24 -8
  71. package/dist/lang/ast/expressions/range.d.ts +2 -1
  72. package/dist/lang/ast/expressions/range.js +4 -2
  73. package/dist/lang/ast/expressions/time-literal.d.ts +4 -3
  74. package/dist/lang/ast/expressions/time-literal.js +5 -10
  75. package/dist/lang/ast/expressions/top-by.js +1 -2
  76. package/dist/lang/ast/expressions/utils.d.ts +3 -12
  77. package/dist/lang/ast/expressions/utils.js +8 -56
  78. package/dist/lang/ast/field-space/reference-field.js +1 -1
  79. package/dist/lang/ast/index.d.ts +1 -1
  80. package/dist/lang/ast/index.js +1 -1
  81. package/dist/lang/ast/query-builders/index-builder.d.ts +2 -2
  82. package/dist/lang/ast/query-builders/reduce-builder.d.ts +2 -2
  83. package/dist/lang/ast/query-items/field-declaration.js +1 -5
  84. package/dist/lang/ast/query-properties/filters.d.ts +3 -3
  85. package/dist/lang/ast/query-properties/filters.js +6 -5
  86. package/dist/lang/ast/query-properties/top.js +1 -2
  87. package/dist/lang/ast/source-elements/refined-source.js +1 -1
  88. package/dist/lang/ast/source-properties/joins.js +11 -10
  89. package/dist/lang/ast/time-utils.d.ts +5 -7
  90. package/dist/lang/ast/time-utils.js +17 -57
  91. package/dist/lang/ast/types/binary_operators.d.ts +9 -0
  92. package/dist/lang/ast/types/binary_operators.js +28 -0
  93. package/dist/lang/ast/types/expr-result.d.ts +3 -3
  94. package/dist/lang/ast/types/expression-def.d.ts +4 -3
  95. package/dist/lang/ast/types/expression-def.js +43 -50
  96. package/dist/lang/lib/Malloy/MalloyParser.d.ts +0 -11
  97. package/dist/lang/lib/Malloy/MalloyParser.js +803 -858
  98. package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +0 -13
  99. package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +0 -8
  100. package/dist/lang/malloy-to-ast.d.ts +0 -1
  101. package/dist/lang/malloy-to-ast.js +0 -4
  102. package/dist/lang/test/expressions.spec.js +42 -86
  103. package/dist/lang/test/field-symbols.spec.js +8 -6
  104. package/dist/lang/test/literals.spec.js +6 -6
  105. package/dist/lang/test/model_serialization.spec.js +5 -5
  106. package/dist/lang/test/test-translator.js +9 -7
  107. package/dist/malloy.d.ts +3 -3
  108. package/dist/malloy.js +1 -1
  109. package/dist/model/index.d.ts +1 -1
  110. package/dist/model/index.js +2 -1
  111. package/dist/model/malloy_query.d.ts +24 -19
  112. package/dist/model/malloy_query.js +272 -244
  113. package/dist/model/malloy_types.d.ts +224 -205
  114. package/dist/model/malloy_types.js +19 -98
  115. package/dist/model/utils.d.ts +10 -3
  116. package/dist/model/utils.js +84 -219
  117. package/package.json +1 -1
  118. package/dist/lang/ast/types/comparison.d.ts +0 -11
  119. package/dist/lang/ast/types/comparison.js +0 -41
  120. package/dist/lang/ast/types/equality.d.ts +0 -7
  121. package/dist/lang/ast/types/equality.js +0 -37
@@ -40,7 +40,6 @@ import { ExprNotContext } from "./MalloyParser";
40
40
  import { ExprLogicalAndContext } from "./MalloyParser";
41
41
  import { ExprLogicalOrContext } from "./MalloyParser";
42
42
  import { ExprCoalesceContext } from "./MalloyParser";
43
- import { ExprCountDisinctContext } from "./MalloyParser";
44
43
  import { ExprPathlessAggregateContext } from "./MalloyParser";
45
44
  import { ExprAggregateContext } from "./MalloyParser";
46
45
  import { ExprExprContext } from "./MalloyParser";
@@ -707,18 +706,6 @@ export interface MalloyParserListener extends ParseTreeListener {
707
706
  * @param ctx the parse tree
708
707
  */
709
708
  exitExprCoalesce?: (ctx: ExprCoalesceContext) => void;
710
- /**
711
- * Enter a parse tree produced by the `exprCountDisinct`
712
- * labeled alternative in `MalloyParser.fieldExpr`.
713
- * @param ctx the parse tree
714
- */
715
- enterExprCountDisinct?: (ctx: ExprCountDisinctContext) => void;
716
- /**
717
- * Exit a parse tree produced by the `exprCountDisinct`
718
- * labeled alternative in `MalloyParser.fieldExpr`.
719
- * @param ctx the parse tree
720
- */
721
- exitExprCountDisinct?: (ctx: ExprCountDisinctContext) => void;
722
709
  /**
723
710
  * Enter a parse tree produced by the `exprPathlessAggregate`
724
711
  * labeled alternative in `MalloyParser.fieldExpr`.
@@ -40,7 +40,6 @@ import { ExprNotContext } from "./MalloyParser";
40
40
  import { ExprLogicalAndContext } from "./MalloyParser";
41
41
  import { ExprLogicalOrContext } from "./MalloyParser";
42
42
  import { ExprCoalesceContext } from "./MalloyParser";
43
- import { ExprCountDisinctContext } from "./MalloyParser";
44
43
  import { ExprPathlessAggregateContext } from "./MalloyParser";
45
44
  import { ExprAggregateContext } from "./MalloyParser";
46
45
  import { ExprExprContext } from "./MalloyParser";
@@ -505,13 +504,6 @@ export interface MalloyParserVisitor<Result> extends ParseTreeVisitor<Result> {
505
504
  * @return the visitor result
506
505
  */
507
506
  visitExprCoalesce?: (ctx: ExprCoalesceContext) => Result;
508
- /**
509
- * Visit a parse tree produced by the `exprCountDisinct`
510
- * labeled alternative in `MalloyParser.fieldExpr`.
511
- * @param ctx the parse tree
512
- * @return the visitor result
513
- */
514
- visitExprCountDisinct?: (ctx: ExprCountDisinctContext) => Result;
515
507
  /**
516
508
  * Visit a parse tree produced by the `exprPathlessAggregate`
517
509
  * labeled alternative in `MalloyParser.fieldExpr`.
@@ -167,7 +167,6 @@ export declare class MalloyToAST extends AbstractParseTreeVisitor<ast.MalloyElem
167
167
  visitExprAddSub(pcx: parse.ExprAddSubContext): ast.ExprAddSub;
168
168
  visitExprMulDiv(pcx: parse.ExprMulDivContext): ast.ExprMulDiv;
169
169
  visitExprCompare(pcx: parse.ExprCompareContext): ast.ExprCompare;
170
- visitExprCountDisinct(pcx: parse.ExprCountDisinctContext): ast.ExprCountDistinct;
171
170
  visitExprUngroup(pcx: parse.ExprUngroupContext): ast.ExprUngroup;
172
171
  symmetricAggregateUsageError(aggFunc: string): string;
173
172
  asymmetricAggregateUsageError(aggFunc: string): string;
@@ -919,10 +919,6 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
919
919
  }
920
920
  throw this.internalError(pcx, `untranslatable comparison operator '${op}'`);
921
921
  }
922
- visitExprCountDisinct(pcx) {
923
- this.m4advisory(pcx, '`count(distinct expression)` deprecated, use `count(expression)` instead');
924
- return this.astAt(new ast.ExprCountDistinct(this.getFieldExpr(pcx.fieldExpr())), pcx);
925
- }
926
922
  visitExprUngroup(pcx) {
927
923
  const flist = pcx.fieldName().map(fcx => this.getFieldName(fcx));
928
924
  const kw = pcx.ungroup().text.toLowerCase();
@@ -22,31 +22,42 @@
22
22
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- const model_1 = require("../../model");
26
25
  const test_translator_1 = require("./test-translator");
27
26
  require("./parse-expects");
28
27
  /**
29
- * Convert an expression to a string, any fragment which is not a string turns into a variable,
30
- * useful for maybe checking simple code generation, but it sort of hints at an interesting matcher
31
- * @param expr Compiled expression
32
- * @returns A string with variables A,B,... substituded for non string elements
28
+ * Try and write a generic version of the expression, might some day be the basis for
29
+ * a much better expression matcher.
33
30
  */
34
- function exprToString(expr) {
35
- let varCode = 'A'.charCodeAt(0);
36
- const vars = {};
37
- return expr
38
- .map(f => {
39
- if (typeof f === 'string') {
40
- return f;
41
- }
42
- const key = JSON.stringify(f);
43
- if (!vars[key]) {
44
- vars[key] = String.fromCharCode(varCode);
45
- varCode += 1;
46
- }
47
- return vars[key];
48
- })
49
- .join('');
31
+ function exprToString(e, symbols = {}) {
32
+ switch (e.node) {
33
+ case '=':
34
+ case '>':
35
+ case '>=':
36
+ case '<':
37
+ case '<=':
38
+ case '+':
39
+ case '-':
40
+ case '*':
41
+ case '/':
42
+ case '%':
43
+ return `${exprToString(e.kids.left, symbols)}${e.node}${exprToString(e.kids.right, symbols)}`;
44
+ case 'and':
45
+ case 'or':
46
+ return `(${exprToString(e.kids.left, symbols)})${e.node}(${exprToString(e.kids.right, symbols)})`;
47
+ case 'field': {
48
+ const ref = e.path.join('.');
49
+ if (symbols[ref] === undefined) {
50
+ const nSyms = Object.keys(symbols).length;
51
+ symbols[ref] = String.fromCharCode('A'.charCodeAt(0) + nSyms);
52
+ }
53
+ return symbols[ref];
54
+ }
55
+ case '()':
56
+ return `(${exprToString(e.e, symbols)})`;
57
+ case 'not':
58
+ return `not(${exprToString(e.e, symbols)})`;
59
+ }
60
+ return `{${e.node}}`;
50
61
  }
51
62
  describe('expressions', () => {
52
63
  describe('timeframes', () => {
@@ -160,25 +171,25 @@ describe('expressions', () => {
160
171
  const compare = (0, test_translator_1.expr) `ad = ad.quarter`;
161
172
  expect(compare).toTranslate();
162
173
  const compare_expr = compare.translator.generated().value;
163
- expect(exprToString(compare_expr)).toEqual('A=B');
174
+ expect(exprToString(compare_expr)).toEqual('A={trunc}');
164
175
  });
165
176
  test('compare to granular result expression uses straight comparison', () => {
166
177
  const compare = (0, test_translator_1.expr) `ad = ad.quarter + 1`;
167
178
  expect(compare).toTranslate();
168
179
  const compare_expr = compare.translator.generated().value;
169
- expect(exprToString(compare_expr)).toEqual('A=B');
180
+ expect(exprToString(compare_expr)).toEqual('A={delta}');
170
181
  });
171
182
  test('apply granular-truncation uses range', () => {
172
183
  const compare = (0, test_translator_1.expr) `ad ? ad.quarter`;
173
184
  expect(compare).toTranslate();
174
185
  const compare_expr = compare.translator.generated().value;
175
- expect(exprToString(compare_expr)).toEqual('(A>=B)and(A<C)');
186
+ expect(exprToString(compare_expr)).toEqual('(A>={trunc})and(A<{delta})');
176
187
  });
177
- test('apply granular-literal alternation uses range', () => {
188
+ test('apply granular-literal alternation uses all literals for range', () => {
178
189
  const compare = (0, test_translator_1.expr) `ad ? @2020 | @2022`;
179
190
  expect(compare).toTranslate();
180
191
  const compare_expr = compare.translator.generated().value;
181
- expect(exprToString(compare_expr)).toEqual('((A>=B)and(A<C))or((A>=D)and(A<E))');
192
+ expect(exprToString(compare_expr)).toEqual('((A>={timeLiteral})and(A<{timeLiteral}))or((A>={timeLiteral})and(A<{timeLiteral}))');
182
193
  });
183
194
  // this should use range, but it uses = and alternations are
184
195
  // kind of needing help so this is a placeholder for
@@ -700,13 +711,6 @@ describe('expressions', () => {
700
711
  calculate: bar is lag(sum(output))
701
712
  }`).translationToFailWith("'output' is not defined");
702
713
  });
703
- test('count(distinct column)', () => {
704
- expect((0, test_translator_1.model) `
705
- ##! m4warnings=warn
706
- run: a -> {
707
- aggregate: x is count(distinct astr)
708
- }`).toTranslateWithWarnings('`count(distinct expression)` deprecated, use `count(expression)` instead');
709
- });
710
714
  });
711
715
  describe('pick statements', () => {
712
716
  test('full', () => {
@@ -807,59 +811,11 @@ describe('expressions', () => {
807
811
  });
808
812
  });
809
813
  test('paren and applied div', () => {
810
- var _a, _b;
811
- const modelSrc = 'query: z is a -> { group_by: x is 1+(3/4) }';
812
- const m = new test_translator_1.TestTranslator(modelSrc);
813
- expect(m).toTranslate();
814
- const queryDef = (_b = (_a = m.translate()) === null || _a === void 0 ? void 0 : _a.translated) === null || _b === void 0 ? void 0 : _b.modelDef.contents['z'];
815
- expect(queryDef).toBeDefined();
816
- expect(queryDef === null || queryDef === void 0 ? void 0 : queryDef.type).toBe('query');
817
- if (queryDef && queryDef.type === 'query') {
818
- const qSeg = queryDef.pipeline[0];
819
- expect(qSeg.type).toEqual('reduce');
820
- if (qSeg.type === 'reduce') {
821
- const x = qSeg.queryFields[0];
822
- if (x.type !== 'fieldref' &&
823
- (0, model_1.isFieldTypeDef)(x) &&
824
- x.type === 'number' &&
825
- x.e) {
826
- expect(x).toMatchObject({
827
- 'e': [
828
- {
829
- 'function': 'numberLiteral',
830
- 'literal': '1',
831
- 'type': 'dialect',
832
- },
833
- // TODO not sure why there are TWO sets of parentheses... A previous version of this test
834
- // just checked that there were ANY parens, so that went under the radar. Not fixing now.
835
- '+((',
836
- {
837
- 'denominator': [
838
- {
839
- 'function': 'numberLiteral',
840
- 'literal': '4',
841
- 'type': 'dialect',
842
- },
843
- ],
844
- 'function': 'div',
845
- 'numerator': [
846
- {
847
- 'function': 'numberLiteral',
848
- 'literal': '3',
849
- 'type': 'dialect',
850
- },
851
- ],
852
- 'type': 'dialect',
853
- },
854
- '))',
855
- ],
856
- });
857
- }
858
- else {
859
- fail('expression with parens compiled oddly');
860
- }
861
- }
862
- }
814
+ const one34 = (0, test_translator_1.expr) `1+(3/4)`;
815
+ expect(one34).toTranslate();
816
+ const exprVal = one34.translator.generated();
817
+ const exprE = exprVal.value;
818
+ expect(exprToString(exprE)).toEqual('{numberLiteral}+({numberLiteral}/{numberLiteral})');
863
819
  });
864
820
  test.each([
865
821
  ['ats', 'timestamp'],
@@ -144,11 +144,13 @@ describe('structdef comprehension', () => {
144
144
  structRelationship: {
145
145
  type: 'one',
146
146
  matrixOperation: 'left',
147
- onExpression: [
148
- { type: 'field', path: ['aKey'] },
149
- '=',
150
- { type: 'field', path: ['t', 'a'] },
151
- ],
147
+ onExpression: {
148
+ node: '=',
149
+ kids: {
150
+ left: { node: 'field', path: ['aKey'] },
151
+ right: { node: 'field', path: ['t', 'a'] },
152
+ },
153
+ },
152
154
  },
153
155
  structSource: { type: 'table', tablePath: 't' },
154
156
  fields: [{ type: 'string', name: 'a' }],
@@ -187,7 +189,7 @@ describe('structdef comprehension', () => {
187
189
  cOptStr: {
188
190
  name: 'cOptStr',
189
191
  type: 'string',
190
- value: ['value'],
192
+ value: { node: 'stringLiteral', literal: 'value' },
191
193
  },
192
194
  };
193
195
  const space = new static_space_1.StaticSpace(struct);
@@ -33,7 +33,7 @@ describe('literals', () => {
33
33
  test('string', () => {
34
34
  const m = new test_translator_1.BetaExpression("'forty two'");
35
35
  expect(m).toTranslate();
36
- const m42 = m.generated().value[0];
36
+ const m42 = m.generated().value;
37
37
  expect(m42).toMatchObject({ literal: 'forty two' });
38
38
  });
39
39
  test('string with quoted quote', () => {
@@ -99,7 +99,7 @@ describe('literals', () => {
99
99
  else {
100
100
  expect((0, granular_result_1.isGranularResult)(ir)).toBeFalsy();
101
101
  }
102
- expect(ir.value[0]).toEqual(expect.objectContaining(result));
102
+ expect(ir.value).toEqual(expect.objectContaining(result));
103
103
  });
104
104
  const morphicLiterals = [
105
105
  ['@1960', '1960-01-01 00:00:00'],
@@ -117,7 +117,7 @@ describe('literals', () => {
117
117
  if (morphic) {
118
118
  expect(morphTo).toBeDefined();
119
119
  if (morphTo) {
120
- expect(morphTo[0]).toEqual(expect.objectContaining({ literal: morphic }));
120
+ expect(morphTo).toEqual(expect.objectContaining({ literal: morphic }));
121
121
  }
122
122
  }
123
123
  else {
@@ -187,7 +187,7 @@ describe('literals', () => {
187
187
  right
188
188
  """`);
189
189
  expect(checking).toTranslate();
190
- const v = checking.generated().value[0];
190
+ const v = checking.generated().value;
191
191
  expect(v).toMatchObject({ literal: '\nleft\n mid\n right\n' });
192
192
  });
193
193
  test('multi-line indent decreasing', () => {
@@ -197,13 +197,13 @@ describe('literals', () => {
197
197
  left
198
198
  """`);
199
199
  expect(checking).toTranslate();
200
- const v = checking.generated().value[0];
200
+ const v = checking.generated().value;
201
201
  expect(v).toMatchObject({ literal: '\n right\n mid\nleft\n' });
202
202
  });
203
203
  test('multi-line indent keep', () => {
204
204
  const checking = new test_translator_1.BetaExpression('"""right\n mid\nleft"""');
205
205
  expect(checking).toTranslate();
206
- const v = checking.generated().value[0];
206
+ const v = checking.generated().value;
207
207
  expect(v).toMatchObject({ literal: 'right\n mid\nleft' });
208
208
  });
209
209
  test('timezone single quote', () => {
@@ -41,7 +41,7 @@ exports.CHILD_EXPLORE = {
41
41
  type: 'number',
42
42
  name: 'flight_count',
43
43
  expressionType: 'aggregate',
44
- e: [{ type: 'aggregate', function: 'count', e: [] }],
44
+ e: { node: 'aggregate', function: 'count', e: { node: '' } },
45
45
  },
46
46
  ],
47
47
  };
@@ -62,7 +62,7 @@ exports.PARENT_EXPLORE = {
62
62
  type: 'number',
63
63
  name: 'some_parent_count',
64
64
  expressionType: 'aggregate',
65
- e: [{ type: 'aggregate', function: 'count', e: [] }],
65
+ e: { node: 'aggregate', function: 'count', e: { node: '' } },
66
66
  },
67
67
  ],
68
68
  };
@@ -83,7 +83,7 @@ exports.GRADPARENT_EXPLORE = {
83
83
  type: 'number',
84
84
  name: 'some_gradparent_count',
85
85
  expressionType: 'aggregate',
86
- e: [{ type: 'aggregate', function: 'count', e: [] }],
86
+ e: { node: 'aggregate', function: 'count', e: { node: '' } },
87
87
  },
88
88
  ],
89
89
  };
@@ -104,14 +104,14 @@ exports.SOURCE_EXPLORE = {
104
104
  type: 'number',
105
105
  name: 'some_child_count',
106
106
  expressionType: 'aggregate',
107
- e: [{ type: 'aggregate', function: 'count', e: [] }],
107
+ e: { node: 'aggregate', function: 'count', e: { node: '' } },
108
108
  },
109
109
  ],
110
110
  };
111
111
  describe('serializeModel', () => {
112
112
  test('Stringify on an `explore` with no parent nor source explore', async () => {
113
113
  const parent_explore = new malloy_1.Explore(exports.PARENT_EXPLORE);
114
- expect(JSON.stringify(parent_explore)).toStrictEqual('{"_structDef":{"type":"struct","name":"some_ns.parent","as":"parent","dialect":"standardsql","structSource":{"type":"table","tablePath":"some_ns.parent"},"structRelationship":{"type":"basetable","connectionName":"bigquery"},"primaryKey":"id2","fields":[{"type":"string","name":"name"},{"type":"number","name":"some_parent_count","expressionType":"aggregate","e":[{"type":"aggregate","function":"count","e":[]}]}]}}');
114
+ expect(JSON.stringify(parent_explore)).toStrictEqual('{"_structDef":{"type":"struct","name":"some_ns.parent","as":"parent","dialect":"standardsql","structSource":{"type":"table","tablePath":"some_ns.parent"},"structRelationship":{"type":"basetable","connectionName":"bigquery"},"primaryKey":"id2","fields":[{"type":"string","name":"name"},{"type":"number","name":"some_parent_count","expressionType":"aggregate","e":{"node":"aggregate","function":"count","e":{"node":""}}}]}}');
115
115
  });
116
116
  test('No parent nor source explore', async () => {
117
117
  const parent_explore = new malloy_1.Explore(exports.PARENT_EXPLORE);
@@ -210,7 +210,7 @@ class TestTranslator extends parse_malloy_1.MalloyTranslator {
210
210
  this.allDialectsEnabled = true;
211
211
  /*
212
212
  * All test source files can assume that an import of this
213
- * model has already happened.
213
+
214
214
  *
215
215
  * Also the following tables will be available on _db_
216
216
  * aTable, malloytest.carriers, malloytest.flights, malloytest.airports
@@ -242,11 +242,13 @@ class TestTranslator extends parse_malloy_1.MalloyTranslator {
242
242
  structRelationship: {
243
243
  type: 'one',
244
244
  matrixOperation: 'left',
245
- onExpression: [
246
- { type: 'field', path: ['astr'] },
247
- '=',
248
- { type: 'field', path: ['b', 'astr'] },
249
- ],
245
+ onExpression: {
246
+ node: '=',
247
+ kids: {
248
+ left: { node: 'field', path: ['astr'] },
249
+ right: { node: 'field', path: ['b', 'astr'] },
250
+ },
251
+ },
250
252
  },
251
253
  },
252
254
  {
@@ -254,7 +256,7 @@ class TestTranslator extends parse_malloy_1.MalloyTranslator {
254
256
  name: 'acount',
255
257
  numberType: 'integer',
256
258
  expressionType: 'aggregate',
257
- e: ['COUNT()'],
259
+ e: { node: 'aggregate', function: 'count', e: { node: '' } },
258
260
  code: 'count()',
259
261
  },
260
262
  {
package/dist/malloy.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  import { RunSQLOptions } from './run_sql_options';
3
3
  import { DocumentCompletion as DocumentCompletionDefinition, DocumentSymbol as DocumentSymbolDefinition, LogMessage, MalloyTranslator } from './lang';
4
4
  import { DocumentHelpContext } from './lang/parse-tree-walkers/document-help-context-walker';
5
- import { CompiledQuery, DocumentLocation, DocumentReference, FieldBooleanDef, FieldDateDef, FieldJSONDef, FieldNumberDef, FieldStringDef, FieldTimestampDef, FieldTypeDef, FilterExpression, Query as InternalQuery, ModelDef, DocumentPosition as ModelDocumentPosition, NamedQuery, QueryData, QueryDataRow, QueryResult, SQLBlock, SQLBlockSource, SQLBlockStructDef, SearchIndexResult, SearchValueMapResult, StructDef, TurtleDef, FeldNativeUnsupportedDef, QueryRunStats, ImportLocation, Annotation } from './model';
5
+ import { CompiledQuery, DocumentLocation, DocumentReference, FieldBooleanDef, FieldDateDef, FieldJSONDef, FieldNumberDef, FieldStringDef, FieldTimestampDef, FieldTypeDef, FilterCondition, Query as InternalQuery, ModelDef, DocumentPosition as ModelDocumentPosition, NamedQuery, QueryData, QueryDataRow, QueryResult, SQLBlock, SQLBlockSource, SQLBlockStructDef, SearchIndexResult, SearchValueMapResult, StructDef, TurtleDef, FeldNativeUnsupportedDef, QueryRunStats, ImportLocation, Annotation } from './model';
6
6
  import { ModelString, ModelURL, QueryString, QueryURL, URLReader } from './runtime_types';
7
7
  import { Connection, InfoConnection, LookupConnection } from './connection/types';
8
8
  import { Tag, TagParse, TagParseSpec, Taggable } from './tags';
@@ -459,7 +459,7 @@ export declare class PreparedResult implements Taggable {
459
459
  get resultExplore(): Explore;
460
460
  get sourceExplore(): Explore;
461
461
  get _sourceExploreName(): string;
462
- get _sourceFilters(): FilterExpression[];
462
+ get _sourceFilters(): FilterCondition[];
463
463
  }
464
464
  /**
465
465
  * A URL reader which always throws an error when a URL's contents is requested.
@@ -578,7 +578,7 @@ export declare class Explore extends Entity implements Taggable {
578
578
  get parentExplore(): Explore | undefined;
579
579
  get sourceRelationship(): SourceRelationship;
580
580
  hasParentExplore(): this is ExploreField;
581
- get filters(): FilterExpression[];
581
+ get filters(): FilterCondition[];
582
582
  get limit(): number | undefined;
583
583
  get structDef(): StructDef;
584
584
  get queryTimezone(): string | undefined;
package/dist/malloy.js CHANGED
@@ -1146,7 +1146,7 @@ class Explore extends Entity {
1146
1146
  hasParentExplore() {
1147
1147
  return this instanceof ExploreField;
1148
1148
  }
1149
- // TODO wrapper type for FilterExpression
1149
+ // TODO wrapper type for FilterCondition
1150
1150
  get filters() {
1151
1151
  var _a;
1152
1152
  return ((_a = this.structDef.resultMetadata) === null || _a === void 0 ? void 0 : _a.filterList) || [];
@@ -1,3 +1,3 @@
1
1
  export * from './malloy_types';
2
2
  export { Segment, QueryModel } from './malloy_query';
3
- export { indent } from './utils';
3
+ export { indent, composeSQLExpr } from './utils';
@@ -36,11 +36,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
36
36
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.indent = exports.QueryModel = exports.Segment = void 0;
39
+ exports.composeSQLExpr = exports.indent = exports.QueryModel = exports.Segment = void 0;
40
40
  __exportStar(require("./malloy_types"), exports);
41
41
  var malloy_query_1 = require("./malloy_query");
42
42
  Object.defineProperty(exports, "Segment", { enumerable: true, get: function () { return malloy_query_1.Segment; } });
43
43
  Object.defineProperty(exports, "QueryModel", { enumerable: true, get: function () { return malloy_query_1.QueryModel; } });
44
44
  var utils_1 = require("./utils");
45
45
  Object.defineProperty(exports, "indent", { enumerable: true, get: function () { return utils_1.indent; } });
46
+ Object.defineProperty(exports, "composeSQLExpr", { enumerable: true, get: function () { return utils_1.composeSQLExpr; } });
46
47
  //# sourceMappingURL=index.js.map
@@ -1,5 +1,5 @@
1
1
  import { Dialect, DialectFieldList } from '../dialect';
2
- import { AggregateFragment, AggregateFunctionType, Annotation, CompiledQuery, DialectFragment, Expr, FieldDef, FieldFragment, Filtered, FilterExpression, FilterFragment, FunctionCallFragment, FunctionOverloadDef, FunctionParameterDef, JoinRelationship, ModelDef, OrderBy, OutputFieldFragment, Parameter, ParameterFragment, PipeSegment, Query, QueryFieldDef, QuerySegment, ResultMetadataDef, ResultStructMetadataDef, SearchIndexResult, SourceReferenceFragment, SegmentFieldDef, SpreadFragment, SQLExpressionFragment, SqlStringFragment, StructDef, StructRef, TurtleDef, UngroupFragment, FunctionOrderBy, Argument } from './malloy_types';
2
+ import { AggregateFunctionType, Annotation, CompiledQuery, Expr, FieldDef, Filtered, FunctionOverloadDef, FunctionParameterDef, JoinRelationship, ModelDef, OrderBy, OutputFieldNode, Parameter, ParameterNode, PipeSegment, Query, QueryFieldDef, QuerySegment, ResultMetadataDef, ResultStructMetadataDef, SearchIndexResult, SegmentFieldDef, StructDef, StructRef, TurtleDef, FunctionOrderBy, Argument, AggregateExpr, FilterCondition, GenericSQLExpr, FieldnameNode, FunctionCallNode, UngroupNode, SourceReferenceNode, PickExpr, SpreadExpr, FilteredExpr } from './malloy_types';
3
3
  import { Connection } from '../connection/types';
4
4
  import { AndChain } from './utils';
5
5
  import { QueryInfo } from '../dialect/dialect';
@@ -66,31 +66,30 @@ declare class QueryField extends QueryNode {
66
66
  getJoinableParent(): QueryStruct;
67
67
  caseGroup(groupSets: number[], s: string): string;
68
68
  getFullOutputName(): string;
69
- generateFieldFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: FieldFragment, state: GenerateState): string;
70
- generateOutputFieldFragment(resultSet: FieldInstanceResult, _context: QueryStruct, frag: OutputFieldFragment, _state: GenerateState): string;
71
- generateSQLExpression(resultSet: FieldInstanceResult, context: QueryStruct, frag: SQLExpressionFragment, state: GenerateState): string;
69
+ generateFieldFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: FieldnameNode, state: GenerateState): string;
70
+ generateOutputFieldFragment(resultSet: FieldInstanceResult, _context: QueryStruct, frag: OutputFieldNode, _state: GenerateState): string;
71
+ stringsFromSQLExpression(resultSet: FieldInstanceResult, context: QueryStruct, e: GenericSQLExpr, state: GenerateState): Generator<string, void, unknown>;
72
72
  private getParameterMap;
73
73
  private expandFunctionCall;
74
74
  getFunctionOrderBy(resultSet: FieldInstanceResult, context: QueryStruct, state: GenerateState, orderBy: FunctionOrderBy[], args: Expr[], overload: FunctionOverloadDef): string | undefined;
75
75
  generateAsymmetricStringAggExpression(resultSet: FieldInstanceResult, context: QueryStruct, value: Expr, separator: Expr | undefined, distinctKey: string, orderBy: FunctionOrderBy[] | undefined, dialectName: string, state: GenerateState): string;
76
76
  getParamForArgIndex(params: FunctionParameterDef[], argIndex: number): FunctionParameterDef;
77
- generateFunctionCallExpression(resultSet: FieldInstanceResult, context: QueryStruct, frag: FunctionCallFragment, state: GenerateState): string;
78
- generateSpread(_resultSet: FieldInstanceResult, _context: QueryStruct, _frag: SpreadFragment, _state: GenerateState): string;
79
- generateParameterFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: ParameterFragment, state: GenerateState): string;
80
- generateFilterFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: FilterFragment, state: GenerateState): string;
77
+ generateFunctionCallExpression(resultSet: FieldInstanceResult, context: QueryStruct, frag: FunctionCallNode, state: GenerateState): string;
78
+ generateSpread(_resultSet: FieldInstanceResult, _context: QueryStruct, _frag: SpreadExpr, _state: GenerateState): string;
79
+ generateParameterFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: ParameterNode, state: GenerateState): string;
80
+ generateFilterFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: FilteredExpr, state: GenerateState): string;
81
81
  generateDimFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: Expr, state: GenerateState): string;
82
- generateUngroupedFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: UngroupFragment, state: GenerateState): string;
82
+ generateUngroupedFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: UngroupNode, state: GenerateState): string;
83
83
  generateDistinctKeyIfNecessary(resultSet: FieldInstanceResult, context: QueryStruct, structPath: string[] | undefined): string | undefined;
84
- generateSumFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: AggregateFragment, state: GenerateState): string;
85
- generateSymmetricFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: AggregateFragment, state: GenerateState): string;
86
- generateAvgFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: AggregateFragment, state: GenerateState): string;
87
- generateCountFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: AggregateFragment, state: GenerateState): string;
88
- generateDialect(resultSet: FieldInstanceResult, context: QueryStruct, expr: DialectFragment, state: GenerateState): string;
89
- generateSqlString(resultSet: FieldInstanceResult, context: QueryStruct, expr: SqlStringFragment, state: GenerateState): string;
90
- generateSourceReference(resultSet: FieldInstanceResult, context: QueryStruct, expr: SourceReferenceFragment): string;
84
+ generateSumFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: AggregateExpr, state: GenerateState): string;
85
+ generateSymmetricFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: AggregateExpr, state: GenerateState): string;
86
+ generateAvgFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: AggregateExpr, state: GenerateState): string;
87
+ generateCountFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: AggregateExpr, state: GenerateState): string;
88
+ generateSourceReference(resultSet: FieldInstanceResult, context: QueryStruct, expr: SourceReferenceNode): string;
91
89
  getAnalyticPartitions(resultStruct: FieldInstanceResult, extraPartitionFields?: string[]): string[];
92
90
  generateAnalyticFragment(resultStruct: FieldInstanceResult, context: QueryStruct, expr: Expr, overload: FunctionOverloadDef, state: GenerateState, args: Expr[], partitionByFields?: string[], funcOrdering?: string): string;
93
- generateExpressionFromExpr(resultSet: FieldInstanceResult, context: QueryStruct, e: Expr, state?: GenerateState): string;
91
+ generatePickSQL(pf: PickExpr): string;
92
+ exprToSQL(resultSet: FieldInstanceResult, context: QueryStruct, exprToTranslate: Expr, state?: GenerateState): string;
94
93
  getExpr(): Expr;
95
94
  generateExpression(resultSet: FieldInstanceResult): string;
96
95
  }
@@ -98,7 +97,7 @@ declare class QueryAtomicField extends QueryField {
98
97
  includeInWildcard(): boolean;
99
98
  isCalculated(): boolean;
100
99
  isAggregate(): boolean;
101
- getFilterList(): FilterExpression[];
100
+ getFilterList(): FilterCondition[];
102
101
  hasExpression(): boolean;
103
102
  }
104
103
  declare class QueryFieldBoolean extends QueryAtomicField {
@@ -148,6 +147,12 @@ declare class FieldInstanceResult implements FieldInstance {
148
147
  ungroupedSets: Map<string, UngroupSet>;
149
148
  resultUsesUngrouped: boolean;
150
149
  constructor(turtleDef: TurtleDef, parent: FieldInstanceResult | undefined);
150
+ /**
151
+ * Information about the query containing this result set. Invented
152
+ * to pass on timezone information, but maybe more things will
153
+ * eventually go in here.
154
+ * @returns QueryInfo
155
+ */
151
156
  getQueryInfo(): QueryInfo;
152
157
  addField(as: string, field: QueryField, usage: FieldUsage): void;
153
158
  parentGroupSet(): number;
@@ -249,7 +254,7 @@ declare class QueryQuery extends QueryField {
249
254
  getSegmentFields(resultStruct: FieldInstanceResult): SegmentFieldDef[];
250
255
  expandFields(resultStruct: FieldInstanceResult): void;
251
256
  expandFilters(resultStruct: FieldInstanceResult): void;
252
- generateSQLFilters(resultStruct: FieldInstanceResult, which: 'where' | 'having', filterList?: FilterExpression[] | undefined): AndChain;
257
+ generateSQLFilters(resultStruct: FieldInstanceResult, which: 'where' | 'having'): AndChain;
253
258
  prepare(_stageWriter: StageWriter | undefined): void;
254
259
  getResultMetadata(fi: FieldInstance): ResultStructMetadataDef | ResultMetadataDef | undefined;
255
260
  /** returns a fields and primary key of a struct for this query */