@malloydata/malloy 0.0.270 → 0.0.271-experiment-250430155127

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 (76) hide show
  1. package/dist/lang/ast/ast-utils.js +1 -2
  2. package/dist/lang/ast/expressions/expr-aggregate-function.js +18 -3
  3. package/dist/lang/ast/expressions/expr-count-distinct.js +1 -1
  4. package/dist/lang/ast/expressions/expr-count.js +3 -3
  5. package/dist/lang/ast/expressions/expr-filter-expr.js +1 -1
  6. package/dist/lang/ast/expressions/expr-func.js +12 -4
  7. package/dist/lang/ast/expressions/expr-id-reference.js +24 -11
  8. package/dist/lang/ast/expressions/expr-now.js +1 -2
  9. package/dist/lang/ast/expressions/expr-props.d.ts +169 -1
  10. package/dist/lang/ast/expressions/expr-props.js +35 -2
  11. package/dist/lang/ast/expressions/expr-ungroup.js +15 -2
  12. package/dist/lang/ast/expressions/grouped_by.d.ts +7 -0
  13. package/dist/lang/ast/expressions/grouped_by.js +19 -0
  14. package/dist/lang/ast/field-space/index-field-space.js +8 -12
  15. package/dist/lang/ast/field-space/query-spaces.d.ts +7 -10
  16. package/dist/lang/ast/field-space/query-spaces.js +30 -45
  17. package/dist/lang/ast/field-space/reference-field.js +16 -3
  18. package/dist/lang/ast/field-space/struct-space-field-base.js +2 -3
  19. package/dist/lang/ast/field-space/view-field.d.ts +48 -12
  20. package/dist/lang/ast/field-space/view-field.js +2 -2
  21. package/dist/lang/ast/index.d.ts +1 -0
  22. package/dist/lang/ast/index.js +1 -0
  23. package/dist/lang/ast/query-builders/index-builder.d.ts +3 -2
  24. package/dist/lang/ast/query-builders/index-builder.js +7 -6
  25. package/dist/lang/ast/query-builders/reduce-builder.d.ts +3 -2
  26. package/dist/lang/ast/query-builders/reduce-builder.js +5 -6
  27. package/dist/lang/ast/query-elements/query-arrow.js +11 -1
  28. package/dist/lang/ast/query-elements/query-base.d.ts +2 -2
  29. package/dist/lang/ast/query-elements/query-base.js +26 -9
  30. package/dist/lang/ast/query-elements/query-refine.js +1 -1
  31. package/dist/lang/ast/query-items/field-declaration.js +20 -2
  32. package/dist/lang/ast/query-items/field-references.d.ts +4 -0
  33. package/dist/lang/ast/query-items/field-references.js +12 -1
  34. package/dist/lang/ast/query-properties/filters.js +3 -3
  35. package/dist/lang/ast/query-properties/nest.js +3 -3
  36. package/dist/lang/ast/query-utils.d.ts +2 -0
  37. package/dist/lang/ast/query-utils.js +31 -1
  38. package/dist/lang/ast/source-elements/composite-source.js +4 -1
  39. package/dist/lang/ast/source-elements/sql-source.js +8 -1
  40. package/dist/lang/ast/source-elements/table-source.js +8 -4
  41. package/dist/lang/ast/source-properties/join.js +3 -2
  42. package/dist/lang/ast/typedesc-utils.js +1 -2
  43. package/dist/lang/ast/types/expr-value.d.ts +3 -1
  44. package/dist/lang/ast/types/expr-value.js +42 -4
  45. package/dist/lang/ast/types/field-prop-statement.d.ts +2 -1
  46. package/dist/lang/ast/types/field-prop-statement.js +3 -1
  47. package/dist/lang/ast/types/query-builder.d.ts +1 -0
  48. package/dist/lang/ast/types/space-field.js +6 -6
  49. package/dist/lang/ast/types/space-param.js +2 -3
  50. package/dist/lang/ast/view-elements/qop-desc-view.js +4 -2
  51. package/dist/lang/ast/view-elements/reference-view.d.ts +1 -1
  52. package/dist/lang/ast/view-elements/reference-view.js +17 -6
  53. package/dist/lang/ast/view-elements/refine-utils.js +1 -1
  54. package/dist/lang/ast/view-elements/view-arrow.d.ts +3 -3
  55. package/dist/lang/ast/view-elements/view-refine.d.ts +2 -2
  56. package/dist/lang/ast/view-elements/view-refine.js +3 -3
  57. package/dist/lang/ast/view-elements/view.d.ts +2 -2
  58. package/dist/lang/lib/Malloy/MalloyLexer.d.ts +161 -160
  59. package/dist/lang/lib/Malloy/MalloyLexer.js +1356 -1345
  60. package/dist/lang/lib/Malloy/MalloyParser.d.ts +235 -219
  61. package/dist/lang/lib/Malloy/MalloyParser.js +2165 -2041
  62. package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +11 -0
  63. package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +7 -0
  64. package/dist/lang/malloy-to-ast.d.ts +1 -0
  65. package/dist/lang/malloy-to-ast.js +8 -0
  66. package/dist/lang/parse-log.d.ts +7 -3
  67. package/dist/lang/parse-log.js +4 -4
  68. package/dist/lang/test/parse-expects.d.ts +2 -2
  69. package/dist/lang/test/parse-expects.js +5 -4
  70. package/dist/model/composite_source_utils.d.ts +29 -26
  71. package/dist/model/composite_source_utils.js +588 -197
  72. package/dist/model/malloy_query.js +4 -0
  73. package/dist/model/malloy_types.d.ts +27 -10
  74. package/dist/version.d.ts +1 -1
  75. package/dist/version.js +1 -1
  76. package/package.json +4 -4
@@ -23,7 +23,6 @@
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.errorFor = void 0;
26
- const composite_source_utils_1 = require("../../model/composite_source_utils");
27
26
  /**
28
27
  * When a translation hits an error, log and return one of these as a value.
29
28
  * This will allow the rest of the translation walk to complete. The
@@ -38,7 +37,7 @@ function errorFor(reason) {
38
37
  expressionType: 'scalar',
39
38
  value: { node: 'error', message: reason },
40
39
  evalSpace: 'constant',
41
- compositeFieldUsage: (0, composite_source_utils_1.emptyCompositeFieldUsage)(),
40
+ fieldUsage: [],
42
41
  };
43
42
  }
44
43
  exports.errorFor = errorFor;
@@ -55,6 +55,7 @@ const field_references_1 = require("../query-items/field-references");
55
55
  const expression_def_1 = require("../types/expression-def");
56
56
  const space_field_1 = require("../types/space-field");
57
57
  const expr_id_reference_1 = require("./expr-id-reference");
58
+ const composite_source_utils_1 = require("../../../model/composite_source_utils");
58
59
  class ExprAggregateFunction extends expression_def_1.ExpressionDef {
59
60
  constructor(func, expr, explicitSource) {
60
61
  super();
@@ -84,15 +85,24 @@ class ExprAggregateFunction extends expression_def_1.ExpressionDef {
84
85
  const footType = sourceFoot.typeDesc();
85
86
  if (!(sourceFoot instanceof static_space_1.StructSpaceField)) {
86
87
  if ((0, malloy_types_1.isAtomicFieldType)(footType.type)) {
88
+ const footPath = this.source.list.map(x => x.refString);
87
89
  expr = this.source;
88
90
  exprVal = {
89
91
  ...TDU.atomicDef(footType),
90
92
  expressionType: footType.expressionType,
91
93
  value: footType.evalSpace === 'output'
92
94
  ? { node: 'outputField', name: this.source.refString }
93
- : { node: 'field', path: this.source.path },
95
+ : {
96
+ node: 'field',
97
+ path: this.source.path,
98
+ at: this.source.location,
99
+ },
94
100
  evalSpace: footType.evalSpace,
95
- compositeFieldUsage: footType.compositeFieldUsage,
101
+ // TODO ensure that when there's an `expr` but no `source`, that `fieldUsage`
102
+ // still comes along correctly
103
+ fieldUsage: (0, composite_source_utils_1.mergeFieldUsage)(footType.fieldUsage, [
104
+ { path: footPath, at: this.source.location },
105
+ ]),
96
106
  };
97
107
  structPath = this.source.path.slice(0, -1);
98
108
  // Here we handle a special case where you write `foo.agg()` and `foo` is a
@@ -157,6 +167,7 @@ class ExprAggregateFunction extends expression_def_1.ExpressionDef {
157
167
  node: 'aggregate',
158
168
  function: this.func,
159
169
  e: exprVal.value,
170
+ at: this.location,
160
171
  };
161
172
  if (structPath && structPath.length > 0) {
162
173
  f.structPath = structPath;
@@ -178,7 +189,11 @@ class ExprAggregateFunction extends expression_def_1.ExpressionDef {
178
189
  if (this.source) {
179
190
  const lookup = this.source.getField(fs);
180
191
  if (lookup.found) {
181
- const sfd = { node: 'field', path: this.source.path };
192
+ const sfd = {
193
+ node: 'field',
194
+ path: this.source.path,
195
+ at: this.source.location,
196
+ };
182
197
  result.push(...getJoinUsage(fs, sfd));
183
198
  }
184
199
  }
@@ -60,7 +60,7 @@ class ExprCountDistinct extends expr_aggregate_function_1.ExprAggregateFunction
60
60
  evalSpace: ev.evalSpace,
61
61
  expressionType: 'aggregate',
62
62
  value: ev.value,
63
- compositeFieldUsage: ev.compositeFieldUsage,
63
+ fieldUsage: ev.fieldUsage,
64
64
  };
65
65
  }
66
66
  }
@@ -23,7 +23,6 @@
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.ExprCount = void 0;
26
- const composite_source_utils_1 = require("../../../model/composite_source_utils");
27
26
  const expr_aggregate_function_1 = require("./expr-aggregate-function");
28
27
  class ExprCount extends expr_aggregate_function_1.ExprAggregateFunction {
29
28
  constructor(source) {
@@ -45,7 +44,7 @@ class ExprCount extends expr_aggregate_function_1.ExprAggregateFunction {
45
44
  evalSpace: ev.evalSpace,
46
45
  expressionType: 'aggregate',
47
46
  value: ev.value,
48
- compositeFieldUsage: ev.compositeFieldUsage,
47
+ fieldUsage: ev.fieldUsage,
49
48
  };
50
49
  }
51
50
  getExpression(_fs) {
@@ -53,6 +52,7 @@ class ExprCount extends expr_aggregate_function_1.ExprAggregateFunction {
53
52
  node: 'aggregate',
54
53
  function: 'count',
55
54
  e: { node: '' },
55
+ at: this.location,
56
56
  };
57
57
  if (this.source) {
58
58
  ret.structPath = this.source.path;
@@ -63,7 +63,7 @@ class ExprCount extends expr_aggregate_function_1.ExprAggregateFunction {
63
63
  expressionType: 'aggregate',
64
64
  value: ret,
65
65
  evalSpace: 'output',
66
- compositeFieldUsage: (0, composite_source_utils_1.emptyCompositeFieldUsage)(),
66
+ fieldUsage: [],
67
67
  };
68
68
  }
69
69
  }
@@ -20,7 +20,7 @@ class ExprFilterExpression extends expression_def_1.ExpressionDef {
20
20
  value: { node: 'filterLiteral', filterSrc: this.filterText },
21
21
  expressionType: 'scalar',
22
22
  evalSpace: 'constant',
23
- compositeFieldUsage: { fields: [], joinedUsage: {} },
23
+ fieldUsage: [],
24
24
  };
25
25
  }
26
26
  }
@@ -140,9 +140,13 @@ class ExprFunc extends expression_def_1.ExpressionDef {
140
140
  implicitExpr = {
141
141
  ...TDU.atomicDef(footType),
142
142
  expressionType: footType.expressionType,
143
- value: { node: 'field', path: this.source.path },
143
+ value: {
144
+ node: 'field',
145
+ path: this.source.path,
146
+ at: this.source.location,
147
+ },
144
148
  evalSpace: footType.evalSpace,
145
- compositeFieldUsage: footType.compositeFieldUsage,
149
+ fieldUsage: footType.fieldUsage,
146
150
  };
147
151
  structPath = this.source.path.slice(0, -1);
148
152
  }
@@ -316,7 +320,11 @@ class ExprFunc extends expression_def_1.ExpressionDef {
316
320
  expr.push({ node: 'parameter', path: [part.name] });
317
321
  }
318
322
  else {
319
- expr.push({ node: 'field', path: [part.name] });
323
+ expr.push({
324
+ node: 'field',
325
+ path: [part.name],
326
+ at: this.args[0].location,
327
+ });
320
328
  }
321
329
  }
322
330
  }
@@ -342,7 +350,7 @@ class ExprFunc extends expression_def_1.ExpressionDef {
342
350
  expressionType,
343
351
  value: funcCall,
344
352
  evalSpace,
345
- compositeFieldUsage: (0, composite_source_utils_1.mergeCompositeFieldUsage)(...argExprs.map(e => e.compositeFieldUsage)),
353
+ fieldUsage: (0, composite_source_utils_1.mergeFieldUsage)(...argExprs.map(e => e.fieldUsage)),
346
354
  };
347
355
  }
348
356
  }
@@ -25,7 +25,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.ExprIdReference = void 0;
26
26
  const malloy_types_1 = require("../../../model/malloy_types");
27
27
  const expression_def_1 = require("../types/expression-def");
28
- const composite_source_utils_1 = require("../../../model/composite_source_utils");
29
28
  class ExprIdReference extends expression_def_1.ExpressionDef {
30
29
  constructor(fieldReference) {
31
30
  super();
@@ -38,30 +37,44 @@ class ExprIdReference extends expression_def_1.ExpressionDef {
38
37
  }
39
38
  getExpression(fs) {
40
39
  const def = this.fieldReference.getField(fs);
41
- // TODO Currently the join usage is always equivalent to the reference path here;
42
- // if/when we add namespaces, this will not be the case, and we will need to get the
43
- // join path from `getField` / `lookup`
44
- const compositeJoinUsage = this.fieldReference.list
45
- .map(n => n.name)
46
- .slice(0, -1);
47
40
  if (def.found) {
41
+ // TODO Currently the join usage is always equivalent to the reference path here;
42
+ // if/when we add namespaces, this will not be the case, and we will need to get the
43
+ // join path from `getField` / `lookup`
44
+ const fieldUsage = def.found.refType === 'field'
45
+ ? [
46
+ {
47
+ path: this.fieldReference.list.map(n => n.name),
48
+ at: this.fieldReference.location,
49
+ },
50
+ ]
51
+ : [];
48
52
  const td = def.found.typeDesc();
49
- const compositeFieldUsage = (0, composite_source_utils_1.joinedCompositeFieldUsage)(compositeJoinUsage, td.compositeFieldUsage);
50
53
  if (def.isOutputField) {
51
54
  return {
52
55
  ...td,
53
56
  // TODO what about literal??
54
57
  evalSpace: td.evalSpace === 'constant' ? 'constant' : 'output',
55
58
  value: { node: 'outputField', name: this.refString },
56
- compositeFieldUsage,
59
+ fieldUsage,
57
60
  };
58
61
  }
59
- const value = { node: def.found.refType, path: this.fieldReference.path };
62
+ const value = {
63
+ node: def.found.refType,
64
+ path: this.fieldReference.path,
65
+ at: this.fieldReference.location,
66
+ };
60
67
  // We think that aggregates are more 'output' like, but maybe we will reconsider that...
61
68
  const evalSpace = (0, malloy_types_1.expressionIsAggregate)(td.expressionType)
62
69
  ? 'output'
63
70
  : td.evalSpace;
64
- return { ...td, value, evalSpace, compositeFieldUsage };
71
+ return {
72
+ ...td,
73
+ value,
74
+ evalSpace,
75
+ fieldUsage,
76
+ requiresGroupBy: undefined,
77
+ };
65
78
  }
66
79
  return this.loggedErrorExpr(def.error.code, def.error.message);
67
80
  }
@@ -24,7 +24,6 @@
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.ExprNow = void 0;
26
26
  const expression_def_1 = require("../types/expression-def");
27
- const composite_source_utils_1 = require("../../../model/composite_source_utils");
28
27
  class ExprNow extends expression_def_1.ExpressionDef {
29
28
  constructor() {
30
29
  super(...arguments);
@@ -37,7 +36,7 @@ class ExprNow extends expression_def_1.ExpressionDef {
37
36
  // `now` is considered to be a constant, at least in the dialects we support today
38
37
  evalSpace: 'constant',
39
38
  value: { node: 'now', typeDef: { type: 'timestamp' } },
40
- compositeFieldUsage: (0, composite_source_utils_1.emptyCompositeFieldUsage)(),
39
+ fieldUsage: [],
41
40
  };
42
41
  }
43
42
  }
@@ -1,7 +1,8 @@
1
- import type { ExprValue } from '../types/expr-value';
1
+ import { type ExprValue } from '../types/expr-value';
2
2
  import { ExpressionDef } from '../types/expression-def';
3
3
  import type { FieldPropStatement } from '../types/field-prop-statement';
4
4
  import type { FieldSpace } from '../types/field-space';
5
+ import { GroupedBy } from './grouped_by';
5
6
  export declare class ExprProps extends ExpressionDef {
6
7
  readonly expr: ExpressionDef;
7
8
  readonly statements: FieldPropStatement[];
@@ -10,4 +11,171 @@ export declare class ExprProps extends ExpressionDef {
10
11
  constructor(expr: ExpressionDef, statements: FieldPropStatement[]);
11
12
  private getFilteredExpression;
12
13
  getExpression(fs: FieldSpace): ExprValue;
14
+ getGroupedBys(fs: FieldSpace, expr: ExprValue, groupedBys: GroupedBy[]): {
15
+ requiresGroupBy: import("../../../model/malloy_types").RequiredGroupBy[] | undefined;
16
+ type: "string";
17
+ bucketFilter?: string | undefined;
18
+ bucketOther?: string | undefined;
19
+ expressionType: import("../../../model/malloy_types").ExpressionType;
20
+ evalSpace: import("../../../model/malloy_types").EvalSpace;
21
+ fieldUsage: import("../../../model/malloy_types").FieldUsage[];
22
+ ungroupings?: import("../../../model/malloy_types").AggregateUngrouping[] | undefined;
23
+ value: import("../../../model/malloy_types").Expr;
24
+ morphic?: {
25
+ [x: string]: import("../../../model/malloy_types").Expr;
26
+ } | undefined;
27
+ } | {
28
+ requiresGroupBy: import("../../../model/malloy_types").RequiredGroupBy[] | undefined;
29
+ type: "date";
30
+ timeframe?: import("../../../model/malloy_types").DateUnit | undefined;
31
+ expressionType: import("../../../model/malloy_types").ExpressionType;
32
+ evalSpace: import("../../../model/malloy_types").EvalSpace;
33
+ fieldUsage: import("../../../model/malloy_types").FieldUsage[];
34
+ ungroupings?: import("../../../model/malloy_types").AggregateUngrouping[] | undefined;
35
+ value: import("../../../model/malloy_types").Expr;
36
+ morphic?: {
37
+ [x: string]: import("../../../model/malloy_types").Expr;
38
+ } | undefined;
39
+ } | {
40
+ requiresGroupBy: import("../../../model/malloy_types").RequiredGroupBy[] | undefined;
41
+ type: "timestamp";
42
+ timeframe?: import("../../../model/malloy_types").TimestampUnit | undefined;
43
+ expressionType: import("../../../model/malloy_types").ExpressionType;
44
+ evalSpace: import("../../../model/malloy_types").EvalSpace;
45
+ fieldUsage: import("../../../model/malloy_types").FieldUsage[];
46
+ ungroupings?: import("../../../model/malloy_types").AggregateUngrouping[] | undefined;
47
+ value: import("../../../model/malloy_types").Expr;
48
+ morphic?: {
49
+ [x: string]: import("../../../model/malloy_types").Expr;
50
+ } | undefined;
51
+ } | {
52
+ requiresGroupBy: import("../../../model/malloy_types").RequiredGroupBy[] | undefined;
53
+ type: "number";
54
+ numberType?: "integer" | "float" | undefined;
55
+ expressionType: import("../../../model/malloy_types").ExpressionType;
56
+ evalSpace: import("../../../model/malloy_types").EvalSpace;
57
+ fieldUsage: import("../../../model/malloy_types").FieldUsage[];
58
+ ungroupings?: import("../../../model/malloy_types").AggregateUngrouping[] | undefined;
59
+ value: import("../../../model/malloy_types").Expr;
60
+ morphic?: {
61
+ [x: string]: import("../../../model/malloy_types").Expr;
62
+ } | undefined;
63
+ } | {
64
+ requiresGroupBy: import("../../../model/malloy_types").RequiredGroupBy[] | undefined;
65
+ type: "boolean";
66
+ expressionType: import("../../../model/malloy_types").ExpressionType;
67
+ evalSpace: import("../../../model/malloy_types").EvalSpace;
68
+ fieldUsage: import("../../../model/malloy_types").FieldUsage[];
69
+ ungroupings?: import("../../../model/malloy_types").AggregateUngrouping[] | undefined;
70
+ value: import("../../../model/malloy_types").Expr;
71
+ morphic?: {
72
+ [x: string]: import("../../../model/malloy_types").Expr;
73
+ } | undefined;
74
+ } | {
75
+ requiresGroupBy: import("../../../model/malloy_types").RequiredGroupBy[] | undefined;
76
+ type: "json";
77
+ expressionType: import("../../../model/malloy_types").ExpressionType;
78
+ evalSpace: import("../../../model/malloy_types").EvalSpace;
79
+ fieldUsage: import("../../../model/malloy_types").FieldUsage[];
80
+ ungroupings?: import("../../../model/malloy_types").AggregateUngrouping[] | undefined;
81
+ value: import("../../../model/malloy_types").Expr;
82
+ morphic?: {
83
+ [x: string]: import("../../../model/malloy_types").Expr;
84
+ } | undefined;
85
+ } | {
86
+ requiresGroupBy: import("../../../model/malloy_types").RequiredGroupBy[] | undefined;
87
+ type: "sql native";
88
+ rawType?: string | undefined;
89
+ expressionType: import("../../../model/malloy_types").ExpressionType;
90
+ evalSpace: import("../../../model/malloy_types").EvalSpace;
91
+ fieldUsage: import("../../../model/malloy_types").FieldUsage[];
92
+ ungroupings?: import("../../../model/malloy_types").AggregateUngrouping[] | undefined;
93
+ value: import("../../../model/malloy_types").Expr;
94
+ morphic?: {
95
+ [x: string]: import("../../../model/malloy_types").Expr;
96
+ } | undefined;
97
+ } | {
98
+ requiresGroupBy: import("../../../model/malloy_types").RequiredGroupBy[] | undefined;
99
+ type: "error";
100
+ expressionType: import("../../../model/malloy_types").ExpressionType;
101
+ evalSpace: import("../../../model/malloy_types").EvalSpace;
102
+ fieldUsage: import("../../../model/malloy_types").FieldUsage[];
103
+ ungroupings?: import("../../../model/malloy_types").AggregateUngrouping[] | undefined;
104
+ value: import("../../../model/malloy_types").Expr;
105
+ morphic?: {
106
+ [x: string]: import("../../../model/malloy_types").Expr;
107
+ } | undefined;
108
+ } | {
109
+ requiresGroupBy: import("../../../model/malloy_types").RequiredGroupBy[] | undefined;
110
+ type: "array";
111
+ elementTypeDef: import("../../../model/malloy_types").BasicAtomicTypeDef | import("../../../model/malloy_types").BasicArrayTypeDef | import("../../../model/malloy_types").RepeatedRecordTypeDef;
112
+ expressionType: import("../../../model/malloy_types").ExpressionType;
113
+ evalSpace: import("../../../model/malloy_types").EvalSpace;
114
+ fieldUsage: import("../../../model/malloy_types").FieldUsage[];
115
+ ungroupings?: import("../../../model/malloy_types").AggregateUngrouping[] | undefined;
116
+ value: import("../../../model/malloy_types").Expr;
117
+ morphic?: {
118
+ [x: string]: import("../../../model/malloy_types").Expr;
119
+ } | undefined;
120
+ } | {
121
+ requiresGroupBy: import("../../../model/malloy_types").RequiredGroupBy[] | undefined;
122
+ type: "record";
123
+ fields: import("../../../model/malloy_types").FieldDef[];
124
+ expressionType: import("../../../model/malloy_types").ExpressionType;
125
+ evalSpace: import("../../../model/malloy_types").EvalSpace;
126
+ fieldUsage: import("../../../model/malloy_types").FieldUsage[];
127
+ ungroupings?: import("../../../model/malloy_types").AggregateUngrouping[] | undefined;
128
+ value: import("../../../model/malloy_types").Expr;
129
+ morphic?: {
130
+ [x: string]: import("../../../model/malloy_types").Expr;
131
+ } | undefined;
132
+ } | {
133
+ requiresGroupBy: import("../../../model/malloy_types").RequiredGroupBy[] | undefined;
134
+ type: "array";
135
+ elementTypeDef: import("../../../model/malloy_types").RecordElementTypeDef;
136
+ fields: import("../../../model/malloy_types").FieldDef[];
137
+ expressionType: import("../../../model/malloy_types").ExpressionType;
138
+ evalSpace: import("../../../model/malloy_types").EvalSpace;
139
+ fieldUsage: import("../../../model/malloy_types").FieldUsage[];
140
+ ungroupings?: import("../../../model/malloy_types").AggregateUngrouping[] | undefined;
141
+ value: import("../../../model/malloy_types").Expr;
142
+ morphic?: {
143
+ [x: string]: import("../../../model/malloy_types").Expr;
144
+ } | undefined;
145
+ } | {
146
+ requiresGroupBy: import("../../../model/malloy_types").RequiredGroupBy[] | undefined;
147
+ type: import("../../../model/malloy_types").NonAtomicType;
148
+ expressionType: import("../../../model/malloy_types").ExpressionType;
149
+ evalSpace: import("../../../model/malloy_types").EvalSpace;
150
+ fieldUsage: import("../../../model/malloy_types").FieldUsage[];
151
+ ungroupings?: import("../../../model/malloy_types").AggregateUngrouping[] | undefined;
152
+ value: import("../../../model/malloy_types").Expr;
153
+ morphic?: {
154
+ [x: string]: import("../../../model/malloy_types").Expr;
155
+ } | undefined;
156
+ } | {
157
+ requiresGroupBy: import("../../../model/malloy_types").RequiredGroupBy[] | undefined;
158
+ type: "date";
159
+ timeframe?: "day" | "week" | "month" | "quarter" | "year" | undefined;
160
+ expressionType: import("../../../model/malloy_types").ExpressionType;
161
+ evalSpace: import("../../../model/malloy_types").EvalSpace;
162
+ fieldUsage: import("../../../model/malloy_types").FieldUsage[];
163
+ ungroupings?: import("../../../model/malloy_types").AggregateUngrouping[] | undefined;
164
+ value: import("../../../model/malloy_types").Expr;
165
+ morphic?: {
166
+ [x: string]: import("../../../model/malloy_types").Expr;
167
+ } | undefined;
168
+ } | {
169
+ requiresGroupBy: import("../../../model/malloy_types").RequiredGroupBy[] | undefined;
170
+ type: "timestamp";
171
+ timeframe?: import("../../../model/malloy_types").TimestampUnit | undefined;
172
+ expressionType: import("../../../model/malloy_types").ExpressionType;
173
+ evalSpace: import("../../../model/malloy_types").EvalSpace;
174
+ fieldUsage: import("../../../model/malloy_types").FieldUsage[];
175
+ ungroupings?: import("../../../model/malloy_types").AggregateUngrouping[] | undefined;
176
+ value: import("../../../model/malloy_types").Expr;
177
+ morphic?: {
178
+ [x: string]: import("../../../model/malloy_types").Expr;
179
+ } | undefined;
180
+ };
13
181
  }
@@ -52,9 +52,11 @@ const TDU = __importStar(require("../typedesc-utils"));
52
52
  const function_ordering_1 = require("./function-ordering");
53
53
  const limit_1 = require("../query-properties/limit");
54
54
  const partition_by_1 = require("./partition_by");
55
+ const expr_value_1 = require("../types/expr-value");
55
56
  const expression_def_1 = require("../types/expression-def");
56
57
  const expr_func_1 = require("./expr-func");
57
58
  const composite_source_utils_1 = require("../../../model/composite_source_utils");
59
+ const grouped_by_1 = require("./grouped_by");
58
60
  class ExprProps extends expression_def_1.ExpressionDef {
59
61
  constructor(expr, statements) {
60
62
  super({ expr, statements });
@@ -81,7 +83,7 @@ class ExprProps extends expression_def_1.ExpressionDef {
81
83
  if (this.typeCheck(this.expr, { ...expr, expressionType: 'scalar' })) {
82
84
  return {
83
85
  ...expr,
84
- compositeFieldUsage: (0, composite_source_utils_1.mergeCompositeFieldUsage)(expr.compositeFieldUsage, ...filterList.map(f => f.compositeFieldUsage)),
86
+ fieldUsage: (0, composite_source_utils_1.mergeFieldUsage)(expr.fieldUsage, ...filterList.map(f => { var _a; return (_a = f.fieldUsage) !== null && _a !== void 0 ? _a : []; })),
85
87
  value: {
86
88
  node: 'filteredExpr',
87
89
  kids: { e: expr.value, filterList },
@@ -98,6 +100,7 @@ class ExprProps extends expression_def_1.ExpressionDef {
98
100
  let limit;
99
101
  const orderBys = [];
100
102
  const wheres = [];
103
+ const groupedBys = [];
101
104
  for (const statement of this.statements) {
102
105
  if (statement instanceof partition_by_1.PartitionBy) {
103
106
  if (!this.expr.canSupportPartitionBy()) {
@@ -126,6 +129,9 @@ class ExprProps extends expression_def_1.ExpressionDef {
126
129
  orderBys.push(statement);
127
130
  }
128
131
  }
132
+ else if (statement instanceof grouped_by_1.GroupedBy) {
133
+ groupedBys.push(statement);
134
+ }
129
135
  else {
130
136
  wheres.push(statement);
131
137
  }
@@ -137,7 +143,34 @@ class ExprProps extends expression_def_1.ExpressionDef {
137
143
  orderBys,
138
144
  })
139
145
  : this.expr.getExpression(fs);
140
- return this.getFilteredExpression(fs, resultExpr, wheres);
146
+ const filteredExpr = this.getFilteredExpression(fs, resultExpr, wheres);
147
+ return this.getGroupedBys(fs, filteredExpr, groupedBys);
148
+ }
149
+ getGroupedBys(fs, expr, groupedBys) {
150
+ const groupedByFields = [];
151
+ for (const requiredGroupBy of groupedBys) {
152
+ for (const field of requiredGroupBy.groupedByFields) {
153
+ const e = field.getField(fs);
154
+ if (e.found === undefined) {
155
+ field.logError('grouped-by-not-found', `${field.refString} is not defined`);
156
+ }
157
+ else if ((0, malloy_types_1.expressionIsAnalytic)(e.found.typeDesc().expressionType) ||
158
+ (0, malloy_types_1.expressionIsAggregate)(e.found.typeDesc().expressionType)) {
159
+ field.logError('non-scalar-grouped-by', '`grouped_by:` field must be a dimension');
160
+ }
161
+ else {
162
+ groupedByFields.push(field.nameString);
163
+ }
164
+ }
165
+ }
166
+ const allRequiredGroupBys = (0, expr_value_1.mergeGroupedBys)(expr.requiresGroupBy, groupedByFields.map(name => ({
167
+ path: [name],
168
+ at: this.location,
169
+ })));
170
+ return {
171
+ ...expr,
172
+ requiresGroupBy: allRequiredGroupBys,
173
+ };
141
174
  }
142
175
  }
143
176
  exports.ExprProps = ExprProps;
@@ -48,6 +48,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
48
48
  exports.ExprUngroup = void 0;
49
49
  const malloy_types_1 = require("../../../model/malloy_types");
50
50
  const query_spaces_1 = require("../field-space/query-spaces");
51
+ const reference_field_1 = require("../field-space/reference-field");
51
52
  const TDU = __importStar(require("../typedesc-utils"));
52
53
  const expression_def_1 = require("../types/expression-def");
53
54
  class ExprUngroup extends expression_def_1.ExpressionDef {
@@ -60,6 +61,7 @@ class ExprUngroup extends expression_def_1.ExpressionDef {
60
61
  this.elementType = 'ungroup';
61
62
  }
62
63
  getExpression(fs) {
64
+ var _a, _b;
63
65
  const exprVal = this.expr.getExpression(fs);
64
66
  if (!(0, malloy_types_1.expressionIsAggregate)(exprVal.expressionType)) {
65
67
  return this.expr.loggedErrorExpr('ungroup-of-non-aggregate', `${this.control}() expression must be an aggregate`);
@@ -71,13 +73,14 @@ class ExprUngroup extends expression_def_1.ExpressionDef {
71
73
  node: this.control,
72
74
  e: exprVal.value,
73
75
  };
76
+ const ungroupFields = [];
74
77
  if (this.typeCheck(this.expr, { ...exprVal, expressionType: 'scalar' })) {
78
+ const isExclude = this.control === 'exclude';
75
79
  // Now every mentioned field must be in the output space of one of the queries
76
80
  // of the nest tree leading to this query. If this is a source definition,
77
81
  // this is not checked until sql generation time.
78
82
  if (fs.isQueryFieldSpace() && this.fields.length > 0) {
79
83
  const dstFields = [];
80
- const isExclude = this.control === 'exclude';
81
84
  for (const mentionedField of this.fields) {
82
85
  let ofs = fs.outputSpace();
83
86
  let notFound = true;
@@ -85,6 +88,9 @@ class ExprUngroup extends expression_def_1.ExpressionDef {
85
88
  const entryInfo = ofs.lookup([mentionedField]);
86
89
  if (entryInfo.found && entryInfo.isOutputField) {
87
90
  dstFields.push(mentionedField.refString);
91
+ if (entryInfo.found instanceof reference_field_1.ReferenceField) {
92
+ ungroupFields.push(entryInfo.found.fieldRef.list.map(n => n.refString));
93
+ }
88
94
  notFound = false;
89
95
  }
90
96
  else if (ofs instanceof query_spaces_1.QuerySpace) {
@@ -106,7 +112,14 @@ class ExprUngroup extends expression_def_1.ExpressionDef {
106
112
  expressionType: 'ungrouped_aggregate',
107
113
  value: ungroup,
108
114
  evalSpace: 'output',
109
- compositeFieldUsage: exprVal.compositeFieldUsage,
115
+ fieldUsage: exprVal.fieldUsage,
116
+ ungroupings: [
117
+ {
118
+ requiresGroupBy: (_a = exprVal.requiresGroupBy) !== null && _a !== void 0 ? _a : [],
119
+ fieldUsage: (_b = exprVal.fieldUsage) !== null && _b !== void 0 ? _b : [],
120
+ ungroupedFields: isExclude ? ungroupFields !== null && ungroupFields !== void 0 ? ungroupFields : [] : '*',
121
+ },
122
+ ],
110
123
  };
111
124
  }
112
125
  return this.loggedErrorExpr('ungroup-with-non-scalar', `${this.control}() incompatible type`);
@@ -0,0 +1,7 @@
1
+ import type { GroupedByReference } from '../query-items/field-references';
2
+ import { ListOf } from '../types/malloy-element';
3
+ export declare class GroupedBy extends ListOf<GroupedByReference> {
4
+ readonly groupedByFields: GroupedByReference[];
5
+ elementType: string;
6
+ constructor(groupedByFields: GroupedByReference[]);
7
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.GroupedBy = void 0;
10
+ const malloy_element_1 = require("../types/malloy-element");
11
+ class GroupedBy extends malloy_element_1.ListOf {
12
+ constructor(groupedByFields) {
13
+ super(groupedByFields);
14
+ this.groupedByFields = groupedByFields;
15
+ this.elementType = 'require_group_by';
16
+ }
17
+ }
18
+ exports.GroupedBy = GroupedBy;
19
+ //# sourceMappingURL=grouped_by.js.map
@@ -53,18 +53,17 @@ class IndexFieldSpace extends query_spaces_1.QueryOperationSpace {
53
53
  this.logError('refinement-of-index-segment', 'index query operations cannot be refined');
54
54
  return { type: 'index', indexFields: [] };
55
55
  }
56
- let compositeFieldUsage = (0, composite_source_utils_1.emptyCompositeFieldUsage)();
57
- let narrowedCompositeFieldResolution = (0, composite_source_utils_1.emptyNarrowedCompositeFieldResolution)();
56
+ let fieldUsage = (0, composite_source_utils_1.emptyFieldUsage)();
58
57
  const indexFields = [];
59
58
  const source = this.inputSpace().structDef();
60
59
  for (const [name, field] of this.entries()) {
61
60
  if (field instanceof space_field_1.SpaceField) {
62
- let nextCompositeFieldUsage = undefined;
61
+ let nextFieldUsage = undefined;
63
62
  let logTo = undefined;
64
63
  const wild = this.expandedWild[name];
65
64
  if (wild) {
66
- indexFields.push({ type: 'fieldref', path: wild.path });
67
- nextCompositeFieldUsage = wild.entry.typeDesc().compositeFieldUsage;
65
+ indexFields.push({ type: 'fieldref', path: wild.path, at: wild.at });
66
+ nextFieldUsage = wild.entry.typeDesc().fieldUsage;
68
67
  }
69
68
  else if (field instanceof reference_field_1.ReferenceField) {
70
69
  // attempt to cause a type check
@@ -75,18 +74,14 @@ class IndexFieldSpace extends query_spaces_1.QueryOperationSpace {
75
74
  }
76
75
  else {
77
76
  indexFields.push(fieldRef.refToField);
78
- nextCompositeFieldUsage =
79
- check.found.typeDesc().compositeFieldUsage;
77
+ nextFieldUsage = check.found.typeDesc().fieldUsage;
80
78
  logTo = fieldRef;
81
79
  }
82
80
  }
83
- const next = this.applyNextCompositeFieldUsage(source, compositeFieldUsage, narrowedCompositeFieldResolution, nextCompositeFieldUsage, logTo);
84
- compositeFieldUsage = next.compositeFieldUsage;
85
- narrowedCompositeFieldResolution =
86
- next.narrowedCompositeFieldResolution;
81
+ fieldUsage = this.applyNextFieldUsage(source, fieldUsage, nextFieldUsage, logTo);
87
82
  }
88
83
  }
89
- this._compositeFieldUsage = compositeFieldUsage;
84
+ this._fieldUsage = fieldUsage;
90
85
  return { type: 'index', indexFields };
91
86
  }
92
87
  addRefineFromFields(_refineThis) { }
@@ -142,6 +137,7 @@ class IndexFieldSpace extends query_spaces_1.QueryOperationSpace {
142
137
  this.expandedWild[indexName] = {
143
138
  path: joinPath.concat(name),
144
139
  entry,
140
+ at: wild.location,
145
141
  };
146
142
  }
147
143
  }