@malloydata/malloy 0.0.190 → 0.0.191-dev240925232958

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 (90) hide show
  1. package/dist/lang/ast/expressions/constant-expression.js +4 -1
  2. package/dist/lang/ast/expressions/expr-aggregate-function.js +25 -14
  3. package/dist/lang/ast/expressions/expr-alternation-tree.js +1 -3
  4. package/dist/lang/ast/expressions/expr-cast.js +1 -1
  5. package/dist/lang/ast/expressions/expr-coalesce.js +1 -1
  6. package/dist/lang/ast/expressions/expr-func.js +20 -31
  7. package/dist/lang/ast/expressions/expr-granular-time.js +1 -1
  8. package/dist/lang/ast/expressions/expr-id-reference.js +1 -3
  9. package/dist/lang/ast/expressions/expr-props.js +8 -8
  10. package/dist/lang/ast/expressions/expr-time-extract.js +7 -13
  11. package/dist/lang/ast/expressions/expr-ungroup.js +4 -8
  12. package/dist/lang/ast/expressions/for-range.js +2 -3
  13. package/dist/lang/ast/expressions/function-ordering.js +6 -6
  14. package/dist/lang/ast/expressions/partial-compare.js +1 -3
  15. package/dist/lang/ast/expressions/pick-when.js +30 -20
  16. package/dist/lang/ast/expressions/range.js +1 -1
  17. package/dist/lang/ast/expressions/top-by.js +1 -1
  18. package/dist/lang/ast/field-space/dynamic-space.js +1 -1
  19. package/dist/lang/ast/field-space/index-field-space.js +6 -6
  20. package/dist/lang/ast/field-space/parameter-space.js +14 -3
  21. package/dist/lang/ast/field-space/project-field-space.js +1 -1
  22. package/dist/lang/ast/field-space/query-spaces.d.ts +2 -1
  23. package/dist/lang/ast/field-space/query-spaces.js +7 -6
  24. package/dist/lang/ast/field-space/reference-field.js +1 -1
  25. package/dist/lang/ast/field-space/refined-space.js +3 -3
  26. package/dist/lang/ast/field-space/static-space.js +11 -2
  27. package/dist/lang/ast/parameters/has-parameter.js +4 -4
  28. package/dist/lang/ast/query-builders/index-builder.js +4 -4
  29. package/dist/lang/ast/query-builders/project-builder.js +2 -2
  30. package/dist/lang/ast/query-builders/reduce-builder.js +5 -5
  31. package/dist/lang/ast/query-elements/anonymous-query.js +1 -1
  32. package/dist/lang/ast/query-elements/query-reference.js +2 -2
  33. package/dist/lang/ast/query-items/field-declaration.js +7 -4
  34. package/dist/lang/ast/query-items/field-references.js +1 -1
  35. package/dist/lang/ast/query-items/typecheck_utils.js +31 -11
  36. package/dist/lang/ast/query-properties/filters.js +4 -4
  37. package/dist/lang/ast/query-properties/ordering.js +3 -3
  38. package/dist/lang/ast/query-properties/qop-desc.js +2 -2
  39. package/dist/lang/ast/query-properties/top.js +5 -5
  40. package/dist/lang/ast/query-utils.js +1 -1
  41. package/dist/lang/ast/source-elements/named-source.d.ts +2 -2
  42. package/dist/lang/ast/source-elements/named-source.js +12 -13
  43. package/dist/lang/ast/source-elements/refined-source.js +9 -7
  44. package/dist/lang/ast/source-elements/sql-source.js +5 -5
  45. package/dist/lang/ast/source-elements/table-source.js +2 -2
  46. package/dist/lang/ast/source-properties/joins.js +6 -6
  47. package/dist/lang/ast/source-properties/renames.js +3 -3
  48. package/dist/lang/ast/source-query-elements/source-query-element.d.ts +2 -1
  49. package/dist/lang/ast/source-query-elements/source-query-element.js +3 -2
  50. package/dist/lang/ast/source-query-elements/sq-arrow.js +2 -2
  51. package/dist/lang/ast/source-query-elements/sq-extend.js +1 -1
  52. package/dist/lang/ast/source-query-elements/sq-reference.js +5 -5
  53. package/dist/lang/ast/source-query-elements/sq-refine.js +2 -2
  54. package/dist/lang/ast/source-query-elements/sq-source.js +1 -1
  55. package/dist/lang/ast/sql-elements/sql-string.js +2 -2
  56. package/dist/lang/ast/statements/define-query.js +2 -2
  57. package/dist/lang/ast/statements/define-source.js +3 -3
  58. package/dist/lang/ast/statements/import-statement.js +7 -7
  59. package/dist/lang/ast/struct-utils.js +1 -1
  60. package/dist/lang/ast/types/expression-def.js +21 -22
  61. package/dist/lang/ast/types/lookup-result.d.ts +5 -1
  62. package/dist/lang/ast/types/malloy-element.d.ts +8 -5
  63. package/dist/lang/ast/types/malloy-element.js +33 -27
  64. package/dist/lang/ast/view-elements/qop-desc-view.js +3 -3
  65. package/dist/lang/ast/view-elements/reference-view.js +6 -6
  66. package/dist/lang/ast/view-elements/refine-utils.js +6 -6
  67. package/dist/lang/ast/view-elements/view-arrow.js +1 -1
  68. package/dist/lang/ast/view-elements/view-refine.js +1 -1
  69. package/dist/lang/malloy-to-ast.d.ts +7 -7
  70. package/dist/lang/malloy-to-ast.js +56 -55
  71. package/dist/lang/parse-log.d.ts +323 -6
  72. package/dist/lang/parse-log.js +62 -16
  73. package/dist/lang/parse-malloy.d.ts +5 -3
  74. package/dist/lang/parse-malloy.js +22 -31
  75. package/dist/lang/test/annotation.spec.js +4 -4
  76. package/dist/lang/test/expressions.spec.js +93 -74
  77. package/dist/lang/test/imports.spec.js +5 -5
  78. package/dist/lang/test/lenses.spec.js +18 -18
  79. package/dist/lang/test/literals.spec.js +1 -1
  80. package/dist/lang/test/locations.spec.js +5 -5
  81. package/dist/lang/test/parameters.spec.js +34 -34
  82. package/dist/lang/test/parse-expects.d.ts +10 -28
  83. package/dist/lang/test/parse-expects.js +38 -33
  84. package/dist/lang/test/parse.spec.js +49 -49
  85. package/dist/lang/test/query.spec.js +82 -82
  86. package/dist/lang/test/source.spec.js +6 -6
  87. package/dist/lang/test/test-translator.d.ts +19 -0
  88. package/dist/lang/test/test-translator.js +20 -1
  89. package/dist/tags.js +4 -2
  90. package/package.json +1 -1
@@ -67,11 +67,11 @@ describe('expressions', () => {
67
67
  });
68
68
  test('typecheck addition lhs', () => {
69
69
  const wrong = (0, test_translator_1.expr) `${'"string"'} + 1`;
70
- expect(wrong).translationToFailWith("The '+' operator requires a number, not a 'string'");
70
+ expect(wrong).toLog((0, test_translator_1.errorMessage)("The '+' operator requires a number, not a 'string'"));
71
71
  });
72
72
  test('typecheck addition rhs', () => {
73
73
  const wrong = (0, test_translator_1.expr) `1 + ${'"string"'}`;
74
- expect(wrong).translationToFailWith("The '+' operator requires a number, not a 'string'");
74
+ expect(wrong).toLog((0, test_translator_1.errorMessage)("The '+' operator requires a number, not a 'string'"));
75
75
  });
76
76
  test('subtraction', () => {
77
77
  expect('42 - 7').compilesTo('{42 - 7}');
@@ -134,16 +134,16 @@ describe('expressions', () => {
134
134
  expect('ai ?? 7').compilesTo('{ai coalesce 7}');
135
135
  });
136
136
  test('coalesce type mismatch', () => {
137
- expect(new test_translator_1.BetaExpression('ai ?? @2003')).translationToFailWith('Mismatched types for coalesce (number, date)');
137
+ expect(new test_translator_1.BetaExpression('ai ?? @2003')).toLog((0, test_translator_1.errorMessage)('Mismatched types for coalesce (number, date)'));
138
138
  });
139
139
  test('disallow date OP number', () => {
140
- expect(new test_translator_1.BetaExpression('@2001 = 7')).translationToFailWith('Cannot compare a date to a number');
140
+ expect(new test_translator_1.BetaExpression('@2001 = 7')).toLog((0, test_translator_1.errorMessage)('Cannot compare a date to a number'));
141
141
  });
142
142
  test('disallow date OP timestamp', () => {
143
- expect(new test_translator_1.BetaExpression('ad = ats')).translationToFailWith('Cannot compare a date to a timestamp');
143
+ expect(new test_translator_1.BetaExpression('ad = ats')).toLog((0, test_translator_1.errorMessage)('Cannot compare a date to a timestamp'));
144
144
  });
145
145
  test('disallow interval from date to timestamp', () => {
146
- expect(new test_translator_1.BetaExpression('days(ad to ats)')).translationToFailWith('Cannot measure from date to timestamp');
146
+ expect(new test_translator_1.BetaExpression('days(ad to ats)')).toLog((0, test_translator_1.errorMessage)('Cannot measure from date to timestamp'));
147
147
  });
148
148
  test('compare to truncation uses straight comparison', () => {
149
149
  expect('ad = ad.quarter').compilesTo('{ad = {timeTrunc-quarter ad}}');
@@ -165,7 +165,7 @@ describe('expressions', () => {
165
165
  });
166
166
  const noOffset = ['second', 'minute', 'hour'];
167
167
  test.each(noOffset.map(x => [x]))('disallow date delta %s', unit => {
168
- expect(new test_translator_1.BetaExpression(`ad + 10 ${unit}s`)).translationToFailWith(`Cannot offset date by ${unit}`);
168
+ expect(new test_translator_1.BetaExpression(`ad + 10 ${unit}s`)).toLog((0, test_translator_1.errorMessage)(`Cannot offset date by ${unit}`));
169
169
  });
170
170
  test('apply with parens', () => {
171
171
  expect((0, test_translator_1.expr) `ai ? (> 1 & < 100)`).toTranslate();
@@ -173,35 +173,35 @@ describe('expressions', () => {
173
173
  describe('sql friendly warnings', () => {
174
174
  test('is null with warning', () => {
175
175
  const warnSrc = (0, test_translator_1.expr) `ai is null`;
176
- expect(warnSrc).toTranslateWithWarnings("Use '= NULL' to check for NULL instead of 'IS NULL'");
176
+ expect(warnSrc).toLog((0, test_translator_1.warningMessage)("Use '= NULL' to check for NULL instead of 'IS NULL'"));
177
177
  expect(warnSrc).compilesTo('{is-null ai}');
178
178
  const warning = warnSrc.translator.problems()[0];
179
179
  expect(warning.replacement).toEqual('ai = null');
180
180
  });
181
181
  test('is not null with warning', () => {
182
182
  const warnSrc = (0, test_translator_1.expr) `ai is not null`;
183
- expect(warnSrc).toTranslateWithWarnings("Use '!= NULL' to check for NULL instead of 'IS NOT NULL'");
183
+ expect(warnSrc).toLog((0, test_translator_1.warningMessage)("Use '!= NULL' to check for NULL instead of 'IS NOT NULL'"));
184
184
  expect(warnSrc).compilesTo('{is-not-null ai}');
185
185
  const warning = warnSrc.translator.problems()[0];
186
186
  expect(warning.replacement).toEqual('ai != null');
187
187
  });
188
188
  test('like with warning', () => {
189
189
  const warnSrc = (0, test_translator_1.expr) `astr like 'a'`;
190
- expect(warnSrc).toTranslateWithWarnings("Use Malloy operator '~' instead of 'LIKE'");
190
+ expect(warnSrc).toLog((0, test_translator_1.warningMessage)("Use Malloy operator '~' instead of 'LIKE'"));
191
191
  expect(warnSrc).compilesTo('{astr like "a"}');
192
192
  const warning = warnSrc.translator.problems()[0];
193
193
  expect(warning.replacement).toEqual("astr ~ 'a'");
194
194
  });
195
195
  test('NOT LIKE with warning', () => {
196
196
  const warnSrc = (0, test_translator_1.expr) `astr not like 'a'`;
197
- expect(warnSrc).toTranslateWithWarnings("Use Malloy operator '!~' instead of 'NOT LIKE'");
197
+ expect(warnSrc).toLog((0, test_translator_1.warningMessage)("Use Malloy operator '!~' instead of 'NOT LIKE'"));
198
198
  expect(warnSrc).compilesTo('{astr !like "a"}');
199
199
  const warning = warnSrc.translator.problems()[0];
200
200
  expect(warning.replacement).toEqual("astr !~ 'a'");
201
201
  });
202
202
  test('is is-null in a model', () => {
203
203
  const isNullSrc = (0, test_translator_1.model) `source: xa is a extend { dimension: x1 is astr is null }`;
204
- expect(isNullSrc).toTranslateWithWarnings("Use '= NULL' to check for NULL instead of 'IS NULL'");
204
+ expect(isNullSrc).toLog((0, test_translator_1.warningMessage)("Use '= NULL' to check for NULL instead of 'IS NULL'"));
205
205
  });
206
206
  test('is not-null in a model', () => {
207
207
  const isNullSrc = (0, test_translator_1.model) `source: xa is a extend { dimension: x1 is not null }`;
@@ -209,7 +209,7 @@ describe('expressions', () => {
209
209
  });
210
210
  test('is not-null is in a model', () => {
211
211
  const isNullSrc = (0, test_translator_1.model) `source: xa is a extend { dimension: x1 is not null is null }`;
212
- expect(isNullSrc).toTranslateWithWarnings("Use '= NULL' to check for NULL instead of 'IS NULL'");
212
+ expect(isNullSrc).toLog((0, test_translator_1.warningMessage)("Use '= NULL' to check for NULL instead of 'IS NULL'"));
213
213
  const warning = isNullSrc.translator.problems()[0];
214
214
  expect(warning.replacement).toEqual('null = null');
215
215
  });
@@ -225,7 +225,7 @@ describe('expressions', () => {
225
225
  });
226
226
  test('not null::number', () => {
227
227
  const notNull = (0, test_translator_1.expr) `not null::number`;
228
- expect(notNull).translationToFailWith("'not' Can't use type number");
228
+ expect(notNull).toLog((0, test_translator_1.errorMessage)("'not' Can't use type number"));
229
229
  });
230
230
  test('(not null)::number', () => {
231
231
  const notNull = (0, test_translator_1.expr) `(not null)::number`;
@@ -246,7 +246,7 @@ describe('expressions', () => {
246
246
  });
247
247
  test('correctly flags filtered scalar', () => {
248
248
  const e = new test_translator_1.BetaExpression('ai { where: true }');
249
- expect(e).translationToFailWith('Filtered expression requires an aggregate computation');
249
+ expect(e).toLog((0, test_translator_1.errorMessage)('Filtered expression requires an aggregate computation'));
250
250
  });
251
251
  test('correctly flags filtered analytic', () => {
252
252
  expect((0, test_translator_1.markSource) `
@@ -254,7 +254,7 @@ describe('expressions', () => {
254
254
  group_by: ai
255
255
  calculate: l is lag(ai) { where: true }
256
256
  }
257
- `).translationToFailWith('Filtered expression requires an aggregate computation');
257
+ `).toLog((0, test_translator_1.errorMessage)('Filtered expression requires an aggregate computation'));
258
258
  });
259
259
  describe('expr props', () => {
260
260
  test('aggregate order by not allowed without experiments enabled', () => {
@@ -263,7 +263,7 @@ describe('expressions', () => {
263
263
  group_by: ai
264
264
  aggregate: x1 is string_agg(astr) { order_by: ai }
265
265
  }
266
- `).translationToFailWith('Enable experiment `aggregate_order_by` to use `order_by` with an aggregate function');
266
+ `).toLog((0, test_translator_1.errorMessage)('Enable experiment `aggregate_order_by` to use `order_by` with an aggregate function'));
267
267
  });
268
268
  test('aggregate limit not allowed without experiments enabled', () => {
269
269
  expect((0, test_translator_1.markSource) `
@@ -271,7 +271,7 @@ describe('expressions', () => {
271
271
  group_by: ai
272
272
  aggregate: x3 is string_agg(astr) { limit: 10 }
273
273
  }
274
- `).translationToFailWith("Experimental flag 'aggregate_limit' required to enable this feature");
274
+ `).toLog((0, test_translator_1.error)('experiment-not-enabled', { experimentId: 'aggregate_limit' }));
275
275
  });
276
276
  test('aggregate order_by not allowed with different experiment enabled', () => {
277
277
  expect((0, test_translator_1.markSource) `
@@ -280,7 +280,7 @@ describe('expressions', () => {
280
280
  group_by: ai
281
281
  aggregate: x1 is string_agg(astr) { order_by: ai }
282
282
  }
283
- `).translationToFailWith('Enable experiment `aggregate_order_by` to use `order_by` with an aggregate function');
283
+ `).toLog((0, test_translator_1.errorMessage)('Enable experiment `aggregate_order_by` to use `order_by` with an aggregate function'));
284
284
  });
285
285
  test('aggregate limit not allowed with different experiment enabled', () => {
286
286
  expect((0, test_translator_1.markSource) `
@@ -289,18 +289,18 @@ describe('expressions', () => {
289
289
  group_by: ai
290
290
  group_by: x3 is string_agg(astr) { limit: 10 }
291
291
  }
292
- `).translationToFailWith("Experimental flag 'aggregate_limit' required to enable this feature");
292
+ `).toLog((0, test_translator_1.error)('experiment-not-enabled', { experimentId: 'aggregate_limit' }));
293
293
  });
294
294
  test('props not allowed on most expressions', () => {
295
295
  expect((0, test_translator_1.markSource) `
296
- ##! experimental { aggregate_order_by aggregate_limit }
297
- run: a -> {
298
- group_by: x1 is 1 { order_by: ai }
299
- group_by: x2 is 1 { partition_by: ai }
300
- group_by: x3 is 1 { limit: 10 }
301
- group_by: x4 is 1 { where: ai }
302
- }
303
- `).translationToFailWith('`order_by` is not supported for this kind of expression', '`partition_by` is not supported for this kind of expression', '`limit` is not supported for this kind of expression', 'Filtered expression requires an aggregate computation');
296
+ ##! experimental { aggregate_order_by aggregate_limit }
297
+ run: a -> {
298
+ group_by: x1 is 1 { order_by: ai }
299
+ group_by: x2 is 1 { partition_by: ai }
300
+ group_by: x3 is 1 { limit: 10 }
301
+ group_by: x4 is 1 { where: ai }
302
+ }
303
+ `).toLog((0, test_translator_1.errorMessage)('`order_by` is not supported for this kind of expression'), (0, test_translator_1.errorMessage)('`partition_by` is not supported for this kind of expression'), (0, test_translator_1.errorMessage)('`limit` is not supported for this kind of expression'), (0, test_translator_1.errorMessage)('Filtered expression requires an aggregate computation'));
304
304
  });
305
305
  test('analytics can take parititon_by and order_by', () => {
306
306
  expect((0, test_translator_1.markSource) `
@@ -327,7 +327,7 @@ describe('expressions', () => {
327
327
  calculate: x is lag(ai) { partition_by: ac }
328
328
  calculate: y is lag(ai) { partition_by: x }
329
329
  }
330
- `).translationToFailWith('Partition expression must be scalar or aggregate', 'Partition expression must be scalar or aggregate');
330
+ `).toLog((0, test_translator_1.errorMessage)('Partition expression must be scalar or aggregate'), (0, test_translator_1.errorMessage)('Partition expression must be scalar or aggregate'));
331
331
  });
332
332
  test('analytics order_by requires expression', () => {
333
333
  expect((0, test_translator_1.markSource) `
@@ -336,7 +336,7 @@ describe('expressions', () => {
336
336
  group_by: ai
337
337
  calculate: x is lag(ai) { order_by: asc }
338
338
  }
339
- `).translationToFailWith('analytic `order_by` must specify an aggregate expression or output field reference');
339
+ `).toLog((0, test_translator_1.errorMessage)('analytic `order_by` must specify an aggregate expression or output field reference'));
340
340
  });
341
341
  test('string_agg_distinct order by cannot specify expression', () => {
342
342
  expect((0, test_translator_1.markSource) `
@@ -345,7 +345,7 @@ describe('expressions', () => {
345
345
  group_by: ai
346
346
  aggregate: x is string_agg_distinct(astr) { order_by: ai }
347
347
  }
348
- `).translationToFailWith('`order_by` must be only `asc` or `desc` with no expression');
348
+ `).toLog((0, test_translator_1.errorMessage)('`order_by` must be only `asc` or `desc` with no expression'));
349
349
  });
350
350
  test('string_agg_distinct order by can be just direction', () => {
351
351
  expect((0, test_translator_1.markSource) `
@@ -396,7 +396,7 @@ describe('expressions', () => {
396
396
  order_by: sum(ai)
397
397
  }
398
398
  }
399
- `).translationToFailWith('aggregate `order_by` must be scalar');
399
+ `).toLog((0, test_translator_1.errorMessage)('aggregate `order_by` must be scalar'));
400
400
  });
401
401
  test('aggregate order by cannot be analytic', () => {
402
402
  expect((0, test_translator_1.markSource) `
@@ -406,7 +406,7 @@ describe('expressions', () => {
406
406
  order_by: rank()
407
407
  }
408
408
  }
409
- `).translationToFailWith('aggregate `order_by` must be scalar');
409
+ `).toLog((0, test_translator_1.errorMessage)('aggregate `order_by` must be scalar'));
410
410
  });
411
411
  test('analytic order by can be an aggregate', () => {
412
412
  expect((0, test_translator_1.markSource) `
@@ -439,7 +439,7 @@ describe('expressions', () => {
439
439
  order_by: ai
440
440
  }
441
441
  }
442
- `).translationToFailWith('analytic `order_by` must be an aggregate or an output field reference');
442
+ `).toLog((0, test_translator_1.errorMessage)('analytic `order_by` must be an aggregate or an output field reference'));
443
443
  });
444
444
  test('can specify multiple wheres', () => {
445
445
  expect((0, test_translator_1.markSource) `
@@ -472,6 +472,7 @@ describe('expressions', () => {
472
472
  rename: nested is astruct
473
473
  rename: inline is aninline
474
474
  dimension: field is column * 2
475
+ dimension: field_and_one_field is column + one.column
475
476
  dimension: many_field is many.column * 2
476
477
  dimension: many_one_field is many.column + one.column
477
478
  join_one: one is a extend {
@@ -513,7 +514,7 @@ describe('expressions', () => {
513
514
  expect(modelX `one.column.min()`).toTranslate();
514
515
  });
515
516
  test('one.min(one.column)', () => {
516
- expect(modelX `one.min(one.column)`).translationToFailWith('Symmetric aggregate function `min` must be written as `min(expression)` or `path.to.field.min()`');
517
+ expect(modelX `one.min(one.column)`).toLog((0, test_translator_1.errorMessage)('Symmetric aggregate function `min` must be written as `min(expression)` or `path.to.field.min()`'));
517
518
  });
518
519
  test('min(one.column)', () => {
519
520
  expect(modelX `min(one.column)`).toTranslate();
@@ -522,7 +523,7 @@ describe('expressions', () => {
522
523
  expect(modelX `min(many.column)`).toTranslate();
523
524
  });
524
525
  test('min()', () => {
525
- expect(modelX `min()`).translationToFailWith('Symmetric aggregate function `min` must be written as `min(expression)` or `path.to.field.min()`');
526
+ expect(modelX `min()`).toLog((0, test_translator_1.errorMessage)('Symmetric aggregate function `min` must be written as `min(expression)` or `path.to.field.min()`'));
526
527
  });
527
528
  test('source.min(column)', () => {
528
529
  expect(modelX `source.min(column)`).toTranslate();
@@ -534,7 +535,7 @@ describe('expressions', () => {
534
535
  expect(modelX `max(many.column)`).toTranslate();
535
536
  });
536
537
  test('max()', () => {
537
- expect(modelX `max()`).translationToFailWith('Symmetric aggregate function `max` must be written as `max(expression)` or `path.to.field.max()`');
538
+ expect(modelX `max()`).toLog((0, test_translator_1.errorMessage)('Symmetric aggregate function `max` must be written as `max(expression)` or `path.to.field.max()`'));
538
539
  });
539
540
  test('source.max(many.column)', () => {
540
541
  expect(modelX `source.max(many.column)`).toTranslate();
@@ -555,7 +556,7 @@ describe('expressions', () => {
555
556
  expect(modelX `many.count()`).toTranslate();
556
557
  });
557
558
  test('sum()', () => {
558
- expect(modelX `sum()`).translationToFailWith('Asymmetric aggregate function `sum` must be written as `path.to.field.sum()`, `path.to.join.sum(expression)`, or `sum(expression)`');
559
+ expect(modelX `sum()`).toLog((0, test_translator_1.errorMessage)('Asymmetric aggregate function `sum` must be written as `path.to.field.sum()`, `path.to.join.sum(expression)`, or `sum(expression)`'));
559
560
  });
560
561
  test('sum(column)', () => {
561
562
  expect(modelX `sum(column)`).toTranslate();
@@ -570,10 +571,10 @@ describe('expressions', () => {
570
571
  expect(modelX `source.sum(column)`).toTranslate();
571
572
  });
572
573
  test('sum(many.column)', () => {
573
- expect(modelX `sum(many.column)`).translationToFailWith('Join path is required for this calculation; use `many.column.sum()`');
574
+ expect(modelX `sum(many.column)`).toLog((0, test_translator_1.errorMessage)('Join path is required for this calculation; use `many.column.sum()`'));
574
575
  });
575
576
  test('source.sum(many.column)', () => {
576
- expect(modelX `source.sum(many.column)`).translationToFailWith('Cannot compute `sum` across `join_many` relationship `many`; use `many.column.sum()`');
577
+ expect(modelX `source.sum(many.column)`).toLog((0, test_translator_1.errorMessage)('Cannot compute `sum` across `join_many` relationship `many`; use `many.column.sum()`'));
577
578
  });
578
579
  test('many.column.sum()', () => {
579
580
  expect(modelX `many.column.sum()`).toTranslate();
@@ -582,7 +583,7 @@ describe('expressions', () => {
582
583
  expect(modelX `many.sum(many.column)`).toTranslate();
583
584
  });
584
585
  test('sum(one.column)', () => {
585
- expect(modelX `sum(one.column)`).toTranslateWithWarnings('Join path is required for this calculation; use `one.column.sum()` or `source.sum(one.column)` to get a result weighted with respect to `source`');
586
+ expect(modelX `sum(one.column)`).toLog((0, test_translator_1.warningMessage)('Join path is required for this calculation; use `one.column.sum()` or `source.sum(one.column)` to get a result weighted with respect to `source`'));
586
587
  });
587
588
  test('sum(many.constant)', () => {
588
589
  expect(modelX `sum(many.constant)`).toTranslate();
@@ -591,13 +592,13 @@ describe('expressions', () => {
591
592
  expect(modelX `source.sum(many.constant)`).toTranslate();
592
593
  });
593
594
  test('sum(nested.column)', () => {
594
- expect(modelX `sum(nested.column)`).translationToFailWith('Join path is required for this calculation; use `nested.column.sum()`');
595
+ expect(modelX `sum(nested.column)`).toLog((0, test_translator_1.errorMessage)('Join path is required for this calculation; use `nested.column.sum()`'));
595
596
  });
596
597
  test('nested.column.sum()', () => {
597
598
  expect(modelX `nested.column.sum()`).toTranslate();
598
599
  });
599
600
  test('source.sum(nested.column)', () => {
600
- expect(modelX `source.sum(nested.column)`).translationToFailWith('Cannot compute `sum` across repeated relationship `nested`; use `nested.column.sum()`');
601
+ expect(modelX `source.sum(nested.column)`).toLog((0, test_translator_1.errorMessage)('Cannot compute `sum` across repeated relationship `nested`; use `nested.column.sum()`'));
601
602
  });
602
603
  test('can aggregate field defined with no join usage', () => {
603
604
  expect((0, test_translator_1.markSource) `
@@ -612,7 +613,7 @@ describe('expressions', () => {
612
613
  `).toTranslate();
613
614
  });
614
615
  test('sum(inline.column)', () => {
615
- expect(modelX `sum(inline.column)`).toTranslateWithWarnings('Join path is required for this calculation; use `inline.column.sum()` or `source.sum(inline.column)` to get a result weighted with respect to `source`');
616
+ expect(modelX `sum(inline.column)`).toLog((0, test_translator_1.warningMessage)('Join path is required for this calculation; use `inline.column.sum()` or `source.sum(inline.column)` to get a result weighted with respect to `source`'));
616
617
  });
617
618
  test('inline.column.sum()', () => {
618
619
  expect(modelX `inline.column.sum()`).toTranslate();
@@ -621,10 +622,10 @@ describe('expressions', () => {
621
622
  expect(modelX `source.sum(inline.column)`).toTranslate();
622
623
  });
623
624
  test('sum(many.field)', () => {
624
- expect(modelX `sum(many.field)`).translationToFailWith('Join path is required for this calculation; use `many.field.sum()`');
625
+ expect(modelX `sum(many.field)`).toLog((0, test_translator_1.errorMessage)('Join path is required for this calculation; use `many.field.sum()`'));
625
626
  });
626
627
  test('source.sum(many.field)', () => {
627
- expect(modelX `source.sum(many.field)`).translationToFailWith('Cannot compute `sum` across `join_many` relationship `many`; use `many.field.sum()`');
628
+ expect(modelX `source.sum(many.field)`).toLog((0, test_translator_1.errorMessage)('Cannot compute `sum` across `join_many` relationship `many`; use `many.field.sum()`'));
628
629
  });
629
630
  test('many.field.sum()', () => {
630
631
  expect(modelX `many.field.sum()`).toTranslate();
@@ -633,10 +634,10 @@ describe('expressions', () => {
633
634
  expect(modelX `many.sum(many.field)`).toTranslate();
634
635
  });
635
636
  test('sum(many.field + many.field)', () => {
636
- expect(modelX `sum(many.field + many.field)`).translationToFailWith('Join path is required for this calculation; use `many.sum(many.field + many.field)`');
637
+ expect(modelX `sum(many.field + many.field)`).toLog((0, test_translator_1.errorMessage)('Join path is required for this calculation; use `many.sum(many.field + many.field)`'));
637
638
  });
638
639
  test('source.sum(many.field + many.field)', () => {
639
- expect(modelX `source.sum(many.field + many.field)`).translationToFailWith('Cannot compute `sum` across `join_many` relationship `many`; use `many.sum(many.field + many.field)`');
640
+ expect(modelX `source.sum(many.field + many.field)`).toLog((0, test_translator_1.errorMessage)('Cannot compute `sum` across `join_many` relationship `many`; use `many.sum(many.field + many.field)`'));
640
641
  });
641
642
  test('many.field + many.field.sum()', () => {
642
643
  expect(modelX `many.field + many.field.sum()`).toTranslate();
@@ -645,10 +646,10 @@ describe('expressions', () => {
645
646
  expect(modelX `many.sum(many.field + many.field)`).toTranslate();
646
647
  });
647
648
  test('sum(many_field)', () => {
648
- expect(modelX `sum(many_field)`).translationToFailWith('Join path is required for this calculation; use `many_field.sum()`');
649
+ expect(modelX `sum(many_field)`).toLog((0, test_translator_1.errorMessage)('Join path is required for this calculation; use `many_field.sum()`'));
649
650
  });
650
651
  test('source.sum(many_field)', () => {
651
- expect(modelX `source.sum(many_field)`).translationToFailWith('Cannot compute `sum` across `join_many` relationship `many`; use `many_field.sum()`');
652
+ expect(modelX `source.sum(many_field)`).toLog((0, test_translator_1.errorMessage)('Cannot compute `sum` across `join_many` relationship `many`; use `many_field.sum()`'));
652
653
  });
653
654
  test('many_field.sum()', () => {
654
655
  expect(modelX `many_field.sum()`).toTranslate();
@@ -657,10 +658,10 @@ describe('expressions', () => {
657
658
  expect(modelX `many.sum(many_field)`).toTranslate();
658
659
  });
659
660
  test('sum(one.many_field)', () => {
660
- expect(modelX `sum(one.many_field)`).translationToFailWith('Join path is required for this calculation; use `one.many_field.sum()`');
661
+ expect(modelX `sum(one.many_field)`).toLog((0, test_translator_1.errorMessage)('Join path is required for this calculation; use `one.many_field.sum()`'));
661
662
  });
662
663
  test('source.sum(one.many_field)', () => {
663
- expect(modelX `source.sum(one.many_field)`).translationToFailWith('Cannot compute `sum` across `join_many` relationship `many`; use `one.many_field.sum()`');
664
+ expect(modelX `source.sum(one.many_field)`).toLog((0, test_translator_1.errorMessage)('Cannot compute `sum` across `join_many` relationship `many`; use `one.many_field.sum()`'));
664
665
  });
665
666
  test('one.many_field.sum()', () => {
666
667
  expect(modelX `one.many_field.sum()`).toTranslate();
@@ -669,28 +670,31 @@ describe('expressions', () => {
669
670
  expect(modelX `one.many.sum(one.many_field)`).toTranslate();
670
671
  });
671
672
  test('sum(many.field + one.field)', () => {
672
- expect(modelX `sum(many.field + one.field)`).translationToFailWith('Aggregated dimensional expression contains multiple join paths; rewrite, for example `sum(first_join.field + second_join.field)` as `first_join.field.sum() + second_join.field.sum()`');
673
+ expect(modelX `sum(many.field + one.field)`).toLog((0, test_translator_1.errorMessage)('Aggregated dimensional expression contains multiple join paths; rewrite, for example `sum(first_join.field + second_join.field)` as `first_join.field.sum() + second_join.field.sum()`'));
673
674
  });
674
675
  test('source.sum(many.field + one.field)', () => {
675
- expect(modelX `source.sum(many.field + one.field)`).translationToFailWith('Aggregated dimensional expression contains multiple join paths; rewrite, for example `sum(first_join.field + second_join.field)` as `first_join.field.sum() + second_join.field.sum()`');
676
+ expect(modelX `source.sum(many.field + one.field)`).toLog((0, test_translator_1.errorMessage)('Aggregated dimensional expression contains multiple join paths; rewrite, for example `sum(first_join.field + second_join.field)` as `first_join.field.sum() + second_join.field.sum()`'));
676
677
  });
677
678
  test('many.sum(many.field + one.field)', () => {
678
679
  expect(modelX `many.sum(many.field + one.field)`).toTranslate();
679
680
  });
681
+ test('many_one_field.sum()', () => {
682
+ expect(modelX `many_one_field.sum()`).toLog((0, test_translator_1.errorMessage)('Aggregated dimensional expression contains multiple join paths; rewrite, for example `sum(first_join.field + second_join.field)` as `first_join.field.sum() + second_join.field.sum()`'));
683
+ });
680
684
  test('sum(many_one_field)', () => {
681
- expect(modelX `sum(many_one_field)`).translationToFailWith('Aggregated dimensional expression contains multiple join paths; rewrite, for example `sum(first_join.field + second_join.field)` as `first_join.field.sum() + second_join.field.sum()`');
685
+ expect(modelX `sum(many_one_field)`).toLog((0, test_translator_1.errorMessage)('Aggregated dimensional expression contains multiple join paths; rewrite, for example `sum(first_join.field + second_join.field)` as `first_join.field.sum() + second_join.field.sum()`'));
682
686
  });
683
687
  test('source.sum(many_one_field)', () => {
684
- expect(modelX `source.sum(many_one_field)`).translationToFailWith('Aggregated dimensional expression contains multiple join paths; rewrite, for example `sum(first_join.field + second_join.field)` as `first_join.field.sum() + second_join.field.sum()`');
688
+ expect(modelX `source.sum(many_one_field)`).toLog((0, test_translator_1.errorMessage)('Aggregated dimensional expression contains multiple join paths; rewrite, for example `sum(first_join.field + second_join.field)` as `first_join.field.sum() + second_join.field.sum()`'));
685
689
  });
686
690
  test('many.sum(many_one_field)', () => {
687
691
  expect(modelX `many.sum(many_one_field)`).toTranslate();
688
692
  });
689
693
  test('sum(many.one.field)', () => {
690
- expect(modelX `sum(many.one.field)`).translationToFailWith('Join path is required for this calculation; use `many.one.field.sum()` or `many.sum(many.one.field)` to get a result weighted with respect to `many`');
694
+ expect(modelX `sum(many.one.field)`).toLog((0, test_translator_1.errorMessage)('Join path is required for this calculation; use `many.one.field.sum()` or `many.sum(many.one.field)` to get a result weighted with respect to `many`'));
691
695
  });
692
696
  test('sum(many.one.one.field)', () => {
693
- expect(modelX `sum(many.one.one.field)`).translationToFailWith('Join path is required for this calculation; use `many.one.one.field.sum()` or `many.sum(many.one.one.field)` to get a result weighted with respect to `many`');
697
+ expect(modelX `sum(many.one.one.field)`).toLog((0, test_translator_1.errorMessage)('Join path is required for this calculation; use `many.one.one.field.sum()` or `many.sum(many.one.one.field)` to get a result weighted with respect to `many`'));
694
698
  });
695
699
  test('many.avg(field)', () => {
696
700
  expect(modelX `many.avg(field)`).toTranslate();
@@ -699,7 +703,7 @@ describe('expressions', () => {
699
703
  expect(modelX `one.avg(field)`).toTranslate();
700
704
  });
701
705
  test('cross.avg(field)', () => {
702
- expect(modelX `cross.avg(field)`).translationToFailWith('Cannot compute `avg` across `join_cross` relationship `cross`; use `field.avg()`');
706
+ expect(modelX `cross.avg(field)`).toLog((0, test_translator_1.errorMessage)('Cannot compute `avg` across `join_cross` relationship `cross`; use `field.avg()`'));
703
707
  });
704
708
  test('cross.avg(cross.field)', () => {
705
709
  expect(modelX `cross.avg(cross.field)`).toTranslate();
@@ -714,7 +718,7 @@ describe('expressions', () => {
714
718
  expect(modelX `source.sum(one.column)`).toTranslate();
715
719
  });
716
720
  test('sum(one.column + one.column)', () => {
717
- expect(modelX `sum(one.column + one.column)`).toTranslateWithWarnings('Join path is required for this calculation; use `one.sum(one.column + one.column)` or `source.sum(one.column + one.column)` to get a result weighted with respect to `source`');
721
+ expect(modelX `sum(one.column + one.column)`).toLog((0, test_translator_1.warningMessage)('Join path is required for this calculation; use `one.sum(one.column + one.column)` or `source.sum(one.column + one.column)` to get a result weighted with respect to `source`'));
718
722
  });
719
723
  test('one.sum(one.column + one.column)', () => {
720
724
  expect(modelX `one.sum(one.column + one.column)`).toTranslate();
@@ -728,7 +732,7 @@ describe('expressions', () => {
728
732
  run: a -> {
729
733
  group_by: output is 1
730
734
  calculate: bar is lag(sum(output))
731
- }`).translationToFailWith("'output' is not defined");
735
+ }`).toLog((0, test_translator_1.errorMessage)("'output' is not defined"));
732
736
  });
733
737
  });
734
738
  describe('pick statements', () => {
@@ -784,11 +788,11 @@ describe('expressions', () => {
784
788
  `).toTranslate();
785
789
  });
786
790
  test('n-ary without else', () => {
787
- expect(`
791
+ return expect(`
788
792
  source: na is a extend { dimension: d is
789
793
  pick 7 when true and true
790
794
  }
791
- `).translationToFailWith("pick incomplete, missing 'else'");
795
+ `).toLog((0, test_translator_1.error)('pick-missing-else'));
792
796
  });
793
797
  test('n-ary with mismatch when clauses', () => {
794
798
  expect((0, test_translator_1.markSource) `
@@ -797,7 +801,10 @@ describe('expressions', () => {
797
801
  pick '7' when true or true
798
802
  else 7
799
803
  }
800
- `).translationToFailWith("pick type 'string', expected 'number'");
804
+ `).toLog((0, test_translator_1.error)('pick-type-does-not-match', {
805
+ pickType: 'string',
806
+ returnType: 'number',
807
+ }));
801
808
  });
802
809
  test('n-ary with mismatched else clause', () => {
803
810
  expect((0, test_translator_1.markSource) `
@@ -805,28 +812,40 @@ describe('expressions', () => {
805
812
  pick 7 when true and true
806
813
  else '7'
807
814
  }
808
- `).translationToFailWith("else type 'string', expected 'number'");
815
+ `).toLog((0, test_translator_1.error)('pick-else-type-does-not-match', {
816
+ elseType: 'string',
817
+ returnType: 'number',
818
+ }));
809
819
  });
810
820
  test('applied else mismatch', () => {
811
821
  expect((0, test_translator_1.markSource) `
812
822
  source: na is a extend { dimension: d is
813
823
  7 ? pick 7 when 7 else 'not seven'
814
824
  }
815
- `).translationToFailWith("else type 'string', expected 'number'");
825
+ `).toLog((0, test_translator_1.error)('pick-else-type-does-not-match', {
826
+ elseType: 'string',
827
+ returnType: 'number',
828
+ }));
816
829
  });
817
830
  test('applied default mismatch', () => {
818
831
  expect((0, test_translator_1.markSource) `
819
832
  source: na is a extend { dimension: d is
820
833
  7 ? pick 'seven' when 7
821
834
  }
822
- `).translationToFailWith("pick default type 'number', expected 'string'");
835
+ `).toLog((0, test_translator_1.error)('pick-default-type-does-not-match', {
836
+ defaultType: 'number',
837
+ returnType: 'string',
838
+ }));
823
839
  });
824
840
  test('applied when mismatch', () => {
825
841
  expect((0, test_translator_1.markSource) `
826
842
  source: na is a extend { dimension: d is
827
843
  7 ? pick 'seven' when 7 pick 6 when 6
828
844
  }
829
- `).translationToFailWith("pick type 'number', expected 'string'");
845
+ `).toLog((0, test_translator_1.error)('pick-type-does-not-match', {
846
+ pickType: 'number',
847
+ returnType: 'string',
848
+ }));
830
849
  });
831
850
  });
832
851
  test('paren and applied div', () => {
@@ -854,12 +873,12 @@ describe('sql native fields in schema', () => {
854
873
  test('flag unsupported equality', () => {
855
874
  // because we don't know if the two unsupported types are comparable
856
875
  const uModel = new test_translator_1.TestTranslator('run: ab->{ where: aun = b.aun select: * }');
857
- expect(uModel).translationToFailWith("Unsupported SQL native type 'undefined' not allowed in expression");
876
+ expect(uModel).toLog((0, test_translator_1.error)('sql-native-not-allowed-in-expression', { rawType: undefined }));
858
877
  });
859
878
  test('flag unsupported compare', () => {
860
879
  // because we don't know if the two unsupported types are comparable
861
880
  const uModel = new test_translator_1.TestTranslator('run: ab->{ where: aun > b.aun select: * }');
862
- expect(uModel).translationToFailWith("Unsupported SQL native type 'undefined' not allowed in expression");
881
+ expect(uModel).toLog((0, test_translator_1.error)('sql-native-not-allowed-in-expression', { rawType: undefined }));
863
882
  });
864
883
  test('allow unsupported equality when raw types match', () => {
865
884
  const uModel = new test_translator_1.TestTranslator('run: ab->{ where: aweird = b.aweird select: * }');
@@ -867,7 +886,7 @@ describe('sql native fields in schema', () => {
867
886
  });
868
887
  test('flag not applied to unsupported', () => {
869
888
  const uModel = new test_translator_1.TestTranslator('source: x is a extend { dimension: notUn is not aun }');
870
- expect(uModel).translationToFailWith("'not' Can't be used with unsupported SQL native type 'undefined'");
889
+ expect(uModel).toLog((0, test_translator_1.error)('sql-native-not-allowed-in-expression', { rawType: undefined }));
871
890
  });
872
891
  test('allow unsupported to be cast', () => {
873
892
  const uModel = new test_translator_1.TestTranslator('source: x is a extend { dimension: notUn is aun::string }');
@@ -891,14 +910,14 @@ describe('sql native fields in schema', () => {
891
910
  run: a -> {
892
911
  group_by: x is sql_number("\${asdfasdf} * 2")
893
912
  }
894
- `).translationToFailWith("Invalid interpolation: 'asdfasdf' is not defined");
913
+ `).toLog((0, test_translator_1.errorMessage)("Invalid interpolation: 'asdfasdf' is not defined"));
895
914
  });
896
915
  test('error when using sql_ function without experiment', () => {
897
916
  expect(`
898
917
  run: a -> {
899
918
  group_by: x is sql_number("\${asdfasdf} * 2")
900
919
  }
901
- `).translationToFailWith('Cannot use sql_function `sql_number`; use `sql_functions` experiment to enable this behavior');
920
+ `).toLog((0, test_translator_1.errorMessage)('Cannot use sql_function `sql_number`; use `sql_functions` experiment to enable this behavior'));
902
921
  });
903
922
  });
904
923
  describe('cast', () => {
@@ -920,7 +939,7 @@ describe('sql native fields in schema', () => {
920
939
  expect((0, test_translator_1.expr) `astr:::number + 1`).toTranslate();
921
940
  });
922
941
  test('sql cast illegal type name', () => {
923
- expect((0, test_translator_1.expr) `astr::"stuff 'n' things"`).translationToFailWith("Cast type `stuff 'n' things` is invalid for standardsql dialect");
942
+ expect((0, test_translator_1.expr) `astr::"stuff 'n' things"`).toLog((0, test_translator_1.errorMessage)("Cast type `stuff 'n' things` is invalid for standardsql dialect"));
924
943
  });
925
944
  });
926
945
  });
@@ -110,7 +110,7 @@ source: botProjQSrc is botProjQ
110
110
  },
111
111
  });
112
112
  docParse.translate();
113
- expect(docParse).translationToFailWith(new RegExp((0, escapeRegExp_1.default)(reportedError)));
113
+ expect(docParse).toLog((0, test_translator_1.errorMessage)(new RegExp((0, escapeRegExp_1.default)(reportedError))));
114
114
  });
115
115
  test('chained imports', () => {
116
116
  const docParse = new test_translator_1.TestTranslator('import "child"');
@@ -156,7 +156,7 @@ source: botProjQSrc is botProjQ
156
156
  }`,
157
157
  },
158
158
  });
159
- expect(docParse).translationToFailWith("Cannot redefine 'astr'");
159
+ expect(docParse).toLog((0, test_translator_1.errorMessage)("Cannot redefine 'astr'"));
160
160
  });
161
161
  test('source references expanded when not exported', () => {
162
162
  const srcFiles = {
@@ -221,7 +221,7 @@ source: botProjQSrc is botProjQ
221
221
  'internal://test/langtests/child': 'source: aa is a',
222
222
  },
223
223
  });
224
- expect(doc.translator).translationToFailWith("Cannot find 'bb', not imported");
224
+ expect(doc.translator).toLog((0, test_translator_1.errorMessage)("Cannot find 'bb', not imported"));
225
225
  });
226
226
  test('selective renamed import of source, not found', () => {
227
227
  const doc = (0, test_translator_1.model) `import { cc is ${'bb'} } from "child"`;
@@ -233,7 +233,7 @@ source: botProjQSrc is botProjQ
233
233
  'internal://test/langtests/child': 'source: aa is a',
234
234
  },
235
235
  });
236
- expect(doc.translator).translationToFailWith("Cannot find 'bb', not imported");
236
+ expect(doc.translator).toLog((0, test_translator_1.errorMessage)("Cannot find 'bb', not imported"));
237
237
  });
238
238
  test('selective import of source, no-redefinition', () => {
239
239
  const doc = (0, test_translator_1.model) `
@@ -247,7 +247,7 @@ source: botProjQSrc is botProjQ
247
247
  'internal://test/langtests/child': 'source: bb is a',
248
248
  },
249
249
  });
250
- expect(doc.translator).translationToFailWith("Cannot redefine 'cc'");
250
+ expect(doc.translator).toLog((0, test_translator_1.errorMessage)("Cannot redefine 'cc'"));
251
251
  });
252
252
  });
253
253
  //# sourceMappingURL=imports.spec.js.map