@malloydata/malloy 0.0.104-dev231116200719 → 0.0.104-dev231117205713

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.
@@ -2,7 +2,7 @@ import { Annotation, DocumentLocation, PipeSegment, Pipeline, StructDef } from '
2
2
  import { FieldSpace } from '../types/field-space';
3
3
  import { MalloyElement } from '../types/malloy-element';
4
4
  import { QOPDesc } from '../query-properties/qop-desc';
5
- import { QueryInputSpace } from '../field-space/query-input-space';
5
+ import { QuerySpace } from '../field-space/query-spaces';
6
6
  import { ViewFieldReference } from '../query-items/field-references';
7
7
  import { Refinement } from '../query-properties/refinements';
8
8
  interface AppendResult {
@@ -17,7 +17,18 @@ interface AppendResult {
17
17
  export declare abstract class PipelineDesc extends MalloyElement {
18
18
  protected refinements?: Refinement[];
19
19
  protected qops: QOPDesc[];
20
- nestedInQuerySpace?: QueryInputSpace;
20
+ private isNestIn?;
21
+ /**
22
+ * This pipeline is actually a nest statement, and the passed query space
23
+ * is the space for the query which contains the nest statement. This is
24
+ * used so that nest queries can walk up a nest chain to check
25
+ * "ungrouping" expressions.
26
+ *
27
+ * This is only here so that it can be used when a Builder is created
28
+ * so the query space created by the builder can also know that it is
29
+ * nested.
30
+ */
31
+ declareAsNestInside(qs: QuerySpace): void;
21
32
  alreadyRefined(): boolean;
22
33
  refineWith(refinements: (QOPDesc | ViewFieldReference)[]): void;
23
34
  addSegments(...segDesc: QOPDesc[]): void;
@@ -40,6 +40,19 @@ class PipelineDesc extends malloy_element_1.MalloyElement {
40
40
  super(...arguments);
41
41
  this.qops = [];
42
42
  }
43
+ /**
44
+ * This pipeline is actually a nest statement, and the passed query space
45
+ * is the space for the query which contains the nest statement. This is
46
+ * used so that nest queries can walk up a nest chain to check
47
+ * "ungrouping" expressions.
48
+ *
49
+ * This is only here so that it can be used when a Builder is created
50
+ * so the query space created by the builder can also know that it is
51
+ * nested.
52
+ */
53
+ declareAsNestInside(qs) {
54
+ this.isNestIn = qs;
55
+ }
43
56
  alreadyRefined() {
44
57
  return this.refinements !== undefined;
45
58
  }
@@ -54,7 +67,7 @@ class PipelineDesc extends malloy_element_1.MalloyElement {
54
67
  }
55
68
  appendOps(pipelineOutput, modelPipe) {
56
69
  const returnPipe = [...modelPipe];
57
- const nestedIn = modelPipe.length === 0 ? this.nestedInQuerySpace : undefined;
70
+ const nestedIn = modelPipe.length === 0 ? this.isNestIn : undefined;
58
71
  let nextFS = () => pipelineOutput;
59
72
  for (const qop of this.qops) {
60
73
  const next = qop.getOp(nextFS(), nestedIn);
@@ -81,7 +94,7 @@ class PipelineDesc extends malloy_element_1.MalloyElement {
81
94
  }
82
95
  pipeline.push(...modelPipe.pipeline);
83
96
  for (const refinement of this.refinements) {
84
- pipeline = refinement.refine(fs, pipeline);
97
+ pipeline = refinement.refine(fs, pipeline, this.isNestIn);
85
98
  }
86
99
  return { pipeline };
87
100
  }
@@ -52,9 +52,6 @@ class ConstantFieldSpace {
52
52
  dialectObj() {
53
53
  return undefined;
54
54
  }
55
- whenComplete(step) {
56
- step();
57
- }
58
55
  isQueryFieldSpace() {
59
56
  return false;
60
57
  }
@@ -55,28 +55,33 @@ class ExprUngroup extends expression_def_1.ExpressionDef {
55
55
  e: exprVal.value,
56
56
  };
57
57
  if (this.typeCheck(this.expr, { ...exprVal, expressionType: 'scalar' })) {
58
- if (this.fields.length > 0) {
59
- if (!fs.isQueryFieldSpace()) {
60
- this.log(`${this.control}() must be in a query -- weird internal error`);
61
- return (0, ast_utils_1.errorFor)('ungroup query check');
62
- }
63
- const output = fs.outputSpace();
64
- if (!(output instanceof query_spaces_1.QuerySpace)) {
65
- // TODO maybe make OutputSpace return an interface which has checkUngroup
66
- this.log(`${this.control}() must be in a query -- weird internal error`);
67
- return (0, ast_utils_1.errorFor)('ungroup query check');
68
- }
58
+ // Now every mentioned field must be in the output space of one of the queries
59
+ // of the nest tree leading to this query. If this is a source definition,
60
+ // this is not checked until sql generation time.
61
+ if (fs.isQueryFieldSpace() && this.fields.length > 0) {
69
62
  const dstFields = [];
70
63
  const isExclude = this.control === 'exclude';
71
- for (const mustBeInOutput of this.fields) {
72
- output.whenComplete(() => {
73
- output.checkUngroup(mustBeInOutput, isExclude);
74
- });
75
- dstFields.push(mustBeInOutput.refString);
64
+ for (const mentionedField of this.fields) {
65
+ let ofs = fs.outputSpace();
66
+ let notFound = true;
67
+ while (ofs) {
68
+ const entryInfo = ofs.lookup([mentionedField]);
69
+ if (entryInfo.found && entryInfo.isOutputField) {
70
+ dstFields.push(mentionedField.refString);
71
+ notFound = false;
72
+ }
73
+ else if (ofs instanceof query_spaces_1.QuerySpace) {
74
+ // should always be true, but don't have types right, thus the if
75
+ ofs = ofs.nestParent;
76
+ continue;
77
+ }
78
+ break;
79
+ }
80
+ if (notFound) {
81
+ const uName = isExclude ? 'exclude()' : 'all()';
82
+ mentionedField.log(`${uName} '${mentionedField.refString}' is missing from query output`);
83
+ }
76
84
  }
77
- // TODO maybe now we can just look up the fields in the output space now and ensure
78
- // they're all there, rather than waiting until the query is finished to do it?
79
- // See `order_by` for an example of how this could work.
80
85
  ungroup.fields = dstFields;
81
86
  }
82
87
  return {
@@ -11,7 +11,6 @@ export declare abstract class DynamicSpace extends StaticSpace {
11
11
  private complete;
12
12
  protected newTimezone?: string;
13
13
  constructor(extending: SourceSpec);
14
- whenComplete(finalizeStep: () => void): void;
15
14
  isComplete(): void;
16
15
  protected setEntry(name: string, value: SpaceEntry): void;
17
16
  addParameters(params: HasParameter[]): DynamicSpace;
@@ -45,20 +45,8 @@ class DynamicSpace extends static_space_1.StaticSpace {
45
45
  this.final = undefined;
46
46
  this.source = source;
47
47
  }
48
- whenComplete(finalizeStep) {
49
- if (this.complete) {
50
- finalizeStep();
51
- }
52
- else {
53
- this.completions.push(finalizeStep);
54
- }
55
- }
56
48
  isComplete() {
57
49
  this.complete = true;
58
- for (const step of this.completions) {
59
- step();
60
- }
61
- this.completions = [];
62
50
  }
63
51
  setEntry(name, value) {
64
52
  if (this.final) {
@@ -12,7 +12,6 @@ import { FieldSpace, QueryFieldSpace } from '../types/field-space';
12
12
  import { RefinedSpace } from './refined-space';
13
13
  export declare class QueryInputSpace extends RefinedSpace implements QueryFieldSpace {
14
14
  private queryOutput;
15
- nestParent?: QueryInputSpace;
16
15
  extendList: string[];
17
16
  /**
18
17
  * Because of circularity concerns this constructor is not typed
@@ -17,18 +17,12 @@ export declare abstract class QuerySpace extends RefinedSpace implements QueryFi
17
17
  astEl?: MalloyElement | undefined;
18
18
  abstract readonly segmentType: 'reduce' | 'project' | 'index';
19
19
  expandedWild: Record<string, string[]>;
20
+ nestParent?: QuerySpace;
20
21
  constructor(queryInputSpace: FieldSpace, refineThis: model.PipeSegment | undefined);
21
22
  private addRefineFromFields;
22
23
  log(s: string): void;
23
24
  pushFields(...defs: MalloyElement[]): void;
24
25
  protected addWild(wild: WildcardFieldReference): void;
25
- /**
26
- * Check for the definition of an ungrouping reference in the result space,
27
- * or in the case of an exclude reference, if this query is nested
28
- * in another query, in the result space of a query that this query
29
- * is nested inside of.
30
- */
31
- checkUngroup(fn: FieldName, isExclude: boolean): void;
32
26
  canContain(_typeDesc: model.TypeDesc): boolean;
33
27
  protected queryFieldDefs(): model.QueryFieldDef[];
34
28
  getQuerySegment(rf: model.QuerySegment | undefined): model.QuerySegment;
@@ -155,33 +155,6 @@ class QuerySpace extends refined_space_1.RefinedSpace {
155
155
  }
156
156
  }
157
157
  }
158
- /**
159
- * Check for the definition of an ungrouping reference in the result space,
160
- * or in the case of an exclude reference, if this query is nested
161
- * in another query, in the result space of a query that this query
162
- * is nested inside of.
163
- */
164
- checkUngroup(fn, isExclude) {
165
- if (!this.entry(fn.refString)) {
166
- const parent = this.exprSpace.nestParent;
167
- if (isExclude && parent) {
168
- parent.whenComplete(() => {
169
- const pOut = parent.outputSpace();
170
- // a little ugly, but it breaks a circularity problem
171
- if (pOut instanceof QuerySpace) {
172
- pOut.checkUngroup(fn, isExclude);
173
- }
174
- else {
175
- throw new Error('OUCH');
176
- }
177
- });
178
- }
179
- else {
180
- const uName = isExclude ? 'exclude()' : 'all()';
181
- fn.log(`${uName} '${fn.refString}' is missing from query output`);
182
- }
183
- }
184
- }
185
158
  canContain(_typeDesc) {
186
159
  return true;
187
160
  }
@@ -10,7 +10,6 @@ export declare class StaticSpace implements FieldSpace {
10
10
  private memoMap?;
11
11
  protected fromStruct: StructDef;
12
12
  constructor(sourceStructDef: StructDef);
13
- whenComplete(step: () => void): void;
14
13
  dialectObj(): Dialect | undefined;
15
14
  defToSpaceField(from: FieldDef): SpaceField;
16
15
  private get map();
@@ -35,9 +35,6 @@ class StaticSpace {
35
35
  this.type = 'fieldSpace';
36
36
  this.fromStruct = sourceStructDef;
37
37
  }
38
- whenComplete(step) {
39
- step();
40
- }
41
38
  dialectObj() {
42
39
  try {
43
40
  return (0, dialect_map_1.getDialect)(this.fromStruct.dialect);
@@ -104,22 +101,6 @@ class StaticSpace {
104
101
  return { error: `'${head}' is not defined`, found };
105
102
  }
106
103
  if (found instanceof space_field_1.SpaceField) {
107
- /*
108
- * TODO cache defs, post the addReference call to whenComplete
109
- *
110
- * In the cleanup phase of query space construction, it may check
111
- * the output space for ungrouping variables. However if an
112
- * ungrouping variable is a measure, the field expression value
113
- * needed to get the definition needs to be computed in the
114
- * input space of the query. There is a test which failed which
115
- * caused this code to be here, but this is really a bandaid.
116
- *
117
- * Some re-work of how to get the definition of a SpaceField
118
- * no matter what it is contained in needs to be thought out.
119
- *
120
- * ... or this check would look at the finalized output of
121
- * the namespace and not re-compile ...
122
- */
123
104
  const definition = found.fieldDef();
124
105
  if (definition) {
125
106
  head.addReference({
@@ -68,7 +68,6 @@ export declare class DefSpace implements FieldSpace {
68
68
  lookup(symbol: FieldName[]): LookupResult;
69
69
  entries(): [string, SpaceEntry][];
70
70
  dialectObj(): Dialect | undefined;
71
- whenComplete(step: () => void): void;
72
71
  isQueryFieldSpace(): this is QueryFieldSpace;
73
72
  outputSpace(): FieldSpace;
74
73
  inputSpace(): FieldSpace;
@@ -226,9 +226,6 @@ class DefSpace {
226
226
  dialectObj() {
227
227
  return this.realFS.dialectObj();
228
228
  }
229
- whenComplete(step) {
230
- this.realFS.whenComplete(step);
231
- }
232
229
  isQueryFieldSpace() {
233
230
  return this.realFS.isQueryFieldSpace();
234
231
  }
@@ -4,11 +4,11 @@ import { MalloyElement } from '../types/malloy-element';
4
4
  import { Noteable, extendNoteMethod } from '../types/noteable';
5
5
  import { QueryField } from '../field-space/query-space-field';
6
6
  import { TurtleHeadedPipe } from '../elements/pipeline-desc';
7
- import { QueryInputSpace } from '../field-space/query-input-space';
8
7
  import { LegalRefinementStage, QueryClass, QueryPropertyInterface } from '../types/query-property-interface';
9
8
  import { QueryBuilder } from '../types/query-builder';
10
9
  import { MakeEntry } from '../types/space-entry';
11
10
  import { DynamicSpace } from '../field-space/dynamic-space';
11
+ import { QuerySpace } from '../field-space/query-spaces';
12
12
  import { TypeDesc } from '../../../model';
13
13
  import { FieldReference, ViewFieldReference } from '../query-items/field-references';
14
14
  declare abstract class TurtleDeclRoot extends TurtleHeadedPipe implements Noteable, MakeEntry {
@@ -18,7 +18,7 @@ declare abstract class TurtleDeclRoot extends TurtleHeadedPipe implements Noteab
18
18
  note?: model.Annotation;
19
19
  constructor(name: string);
20
20
  getPipeline(fs: FieldSpace): model.Pipeline;
21
- getFieldDef(fs: FieldSpace, nestParent: QueryInputSpace | undefined): model.TurtleDef;
21
+ getFieldDef(fs: FieldSpace): model.TurtleDef;
22
22
  makeEntry(fs: DynamicSpace): void;
23
23
  }
24
24
  export declare class TurtleDecl extends TurtleDeclRoot {
@@ -41,15 +41,17 @@ export declare class NestDefinition extends TurtleDeclRoot implements QueryPrope
41
41
  makeEntry(fs: DynamicSpace): void;
42
42
  }
43
43
  export declare function isNestedQuery(me: MalloyElement): me is NestedQuery;
44
- export declare class QueryFieldAST extends QueryField {
44
+ export declare class ViewField extends QueryField {
45
45
  readonly turtle: TurtleDecl;
46
46
  protected name: string;
47
47
  renameAs?: string;
48
- nestParent?: QueryInputSpace;
49
48
  constructor(fs: FieldSpace, turtle: TurtleDecl, name: string);
50
49
  getQueryFieldDef(fs: FieldSpace): model.QueryFieldDef;
51
50
  fieldDef(): model.TurtleDef;
52
51
  }
52
+ export declare class NestField extends ViewField {
53
+ constructor(fs: FieldSpace, turtle: TurtleDecl, name: string, spaceContainingNest: QuerySpace);
54
+ }
53
55
  export declare class NestReference extends FieldReference implements QueryPropertyInterface, MakeEntry {
54
56
  readonly name: FieldReference;
55
57
  elementType: string;
@@ -45,7 +45,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
45
45
  return result;
46
46
  };
47
47
  Object.defineProperty(exports, "__esModule", { value: true });
48
- exports.NestReference = exports.QueryFieldAST = exports.isNestedQuery = exports.NestDefinition = exports.NestRefinement = exports.TurtleDecl = void 0;
48
+ exports.NestReference = exports.NestField = exports.ViewField = exports.isNestedQuery = exports.NestDefinition = exports.NestRefinement = exports.TurtleDecl = void 0;
49
49
  const model = __importStar(require("../../../model/malloy_types"));
50
50
  const noteable_1 = require("../types/noteable");
51
51
  const query_space_field_1 = require("../field-space/query-space-field");
@@ -126,10 +126,7 @@ class TurtleDeclRoot extends pipeline_desc_1.TurtleHeadedPipe {
126
126
  }
127
127
  return modelPipe;
128
128
  }
129
- getFieldDef(fs, nestParent) {
130
- if (nestParent) {
131
- this.nestedInQuerySpace = nestParent;
132
- }
129
+ getFieldDef(fs) {
133
130
  const pipe = this.getPipeline(fs);
134
131
  const turtle = {
135
132
  type: 'turtle',
@@ -148,7 +145,7 @@ class TurtleDeclRoot extends pipeline_desc_1.TurtleHeadedPipe {
148
145
  return turtle;
149
146
  }
150
147
  makeEntry(fs) {
151
- fs.newEntry(this.name, this, new QueryFieldAST(fs, this, this.name));
148
+ fs.newEntry(this.name, this, new ViewField(fs, this, this.name));
152
149
  }
153
150
  }
154
151
  class TurtleDecl extends TurtleDeclRoot {
@@ -171,8 +168,7 @@ class NestRefinement extends TurtleDeclRoot {
171
168
  }
172
169
  makeEntry(fs) {
173
170
  if (fs instanceof query_spaces_1.QuerySpace) {
174
- const qf = new QueryFieldAST(fs, this, this.name);
175
- qf.nestParent = fs.inputSpace();
171
+ const qf = new NestField(fs, this, this.name, fs);
176
172
  fs.newEntry(this.name, this, qf);
177
173
  return;
178
174
  }
@@ -192,8 +188,7 @@ class NestDefinition extends TurtleDeclRoot {
192
188
  }
193
189
  makeEntry(fs) {
194
190
  if (fs instanceof query_spaces_1.QuerySpace) {
195
- const qf = new QueryFieldAST(fs, this, this.name);
196
- qf.nestParent = fs.inputSpace();
191
+ const qf = new NestField(fs, this, this.name, fs);
197
192
  fs.newEntry(this.name, this, qf);
198
193
  return;
199
194
  }
@@ -207,28 +202,35 @@ function isNestedQuery(me) {
207
202
  me instanceof NestDefinition);
208
203
  }
209
204
  exports.isNestedQuery = isNestedQuery;
210
- class QueryFieldAST extends query_space_field_1.QueryField {
205
+ class ViewField extends query_space_field_1.QueryField {
211
206
  constructor(fs, turtle, name) {
212
207
  super(fs);
213
208
  this.turtle = turtle;
214
209
  this.name = name;
215
210
  }
216
211
  getQueryFieldDef(fs) {
217
- const def = this.turtle.getFieldDef(fs, this.nestParent);
212
+ const def = this.turtle.getFieldDef(fs);
218
213
  if (this.renameAs) {
219
214
  def.as = this.renameAs;
220
215
  }
221
216
  return def;
222
217
  }
223
218
  fieldDef() {
224
- const def = this.turtle.getFieldDef(this.inSpace, this.nestParent);
219
+ const def = this.turtle.getFieldDef(this.inSpace);
225
220
  if (this.renameAs) {
226
221
  def.as = this.renameAs;
227
222
  }
228
223
  return def;
229
224
  }
230
225
  }
231
- exports.QueryFieldAST = QueryFieldAST;
226
+ exports.ViewField = ViewField;
227
+ class NestField extends ViewField {
228
+ constructor(fs, turtle, name, spaceContainingNest) {
229
+ super(fs, turtle, name);
230
+ turtle.declareAsNestInside(spaceContainingNest);
231
+ }
232
+ }
233
+ exports.NestField = NestField;
232
234
  class NestReference extends field_references_1.FieldReference {
233
235
  constructor(name) {
234
236
  super([...name.list]);
@@ -4,7 +4,7 @@ import { ListOf } from '../types/malloy-element';
4
4
  import { OpDesc } from '../types/op-desc';
5
5
  import { QueryProperty } from '../types/query-property';
6
6
  import { QueryClass } from '../types/query-property-interface';
7
- import { QueryInputSpace } from '../field-space/query-input-space';
7
+ import { QuerySpace } from '../field-space/query-spaces';
8
8
  export declare class QOPDesc extends ListOf<QueryProperty> {
9
9
  elementType: string;
10
10
  opClass: QueryClass | undefined;
@@ -12,5 +12,5 @@ export declare class QOPDesc extends ListOf<QueryProperty> {
12
12
  protected computeType(): QueryClass | undefined;
13
13
  refineFrom(existing: PipeSegment): void;
14
14
  private getBuilder;
15
- getOp(inputFS: FieldSpace, headFieldSpace: QueryInputSpace | undefined): OpDesc;
15
+ getOp(inputFS: FieldSpace, isNestIn: QuerySpace | undefined): OpDesc;
16
16
  }
@@ -86,10 +86,10 @@ class QOPDesc extends malloy_element_1.ListOf {
86
86
  return new partial_builder_1.PartialBuilder(baseFS, this.refineThis);
87
87
  }
88
88
  }
89
- getOp(inputFS, headFieldSpace) {
89
+ getOp(inputFS, isNestIn) {
90
90
  const build = this.getBuilder(inputFS);
91
- if (headFieldSpace) {
92
- build.inputFS.nestParent = headFieldSpace;
91
+ if (isNestIn) {
92
+ build.resultFS.nestParent = isNestIn;
93
93
  }
94
94
  build.resultFS.astEl = this;
95
95
  for (const qp of this.list) {
@@ -4,8 +4,14 @@ import { MalloyElement } from '../types/malloy-element';
4
4
  import { OpDesc } from '../types/op-desc';
5
5
  import { ViewFieldReference } from '../query-items/field-references';
6
6
  import { QOPDesc } from './qop-desc';
7
+ import { QuerySpace } from '../field-space/query-spaces';
7
8
  export declare abstract class Refinement extends MalloyElement {
8
- abstract refine(inputFS: FieldSpace, pipeline: PipeSegment[]): PipeSegment[];
9
+ /**
10
+ * @param inputFS
11
+ * @param pipeline
12
+ * @param isNestIn The pipeline being refined is a nest, and this is the space which contains the nest statement
13
+ */
14
+ abstract refine(inputFS: FieldSpace, pipeline: PipeSegment[], isNestIn: QuerySpace | undefined): PipeSegment[];
9
15
  static from(base: QOPDesc | ViewFieldReference): QOPDescRefinement | NamedRefinement;
10
16
  }
11
17
  export declare class NamedRefinement extends Refinement {
@@ -13,13 +19,13 @@ export declare class NamedRefinement extends Refinement {
13
19
  elementType: string;
14
20
  constructor(name: ViewFieldReference);
15
21
  private getRefinementSegment;
16
- refine(inputFS: FieldSpace, pipeline: PipeSegment[]): PipeSegment[];
17
- getOp(inputFS: FieldSpace, _to: PipeSegment): OpDesc;
22
+ refine(inputFS: FieldSpace, pipeline: PipeSegment[], _isNestIn: QuerySpace | undefined): PipeSegment[];
23
+ getOp(inputFS: FieldSpace, refineTo: PipeSegment): OpDesc;
18
24
  }
19
25
  export declare class QOPDescRefinement extends Refinement {
20
26
  private readonly qOpDesc;
21
27
  elementType: string;
22
28
  constructor(qOpDesc: QOPDesc);
23
29
  private getOp;
24
- refine(inputFS: FieldSpace, _pipeline: PipeSegment[]): PipeSegment[];
30
+ refine(inputFS: FieldSpace, _pipeline: PipeSegment[], isNestIn: QuerySpace | undefined): PipeSegment[];
25
31
  }
@@ -70,7 +70,7 @@ class NamedRefinement extends Refinement {
70
70
  }
71
71
  this.name.log(`named refinement \`${this.name.refString}\` must be a view, found a ${res.found.typeDesc().dataType}`);
72
72
  }
73
- refine(inputFS, pipeline) {
73
+ refine(inputFS, pipeline, _isNestIn) {
74
74
  if (pipeline.length === 1) {
75
75
  return [this.getOp(inputFS, pipeline[0]).segment];
76
76
  }
@@ -80,9 +80,9 @@ class NamedRefinement extends Refinement {
80
80
  return pipeline;
81
81
  }
82
82
  }
83
- getOp(inputFS, _to) {
83
+ getOp(inputFS, refineTo) {
84
84
  var _a, _b;
85
- const to = { ..._to };
85
+ const to = { ...refineTo };
86
86
  const from = this.getRefinementSegment(inputFS);
87
87
  if (from) {
88
88
  // TODO need to disallow partial + index for now to make the types happy
@@ -155,15 +155,15 @@ class QOPDescRefinement extends Refinement {
155
155
  this.qOpDesc = qOpDesc;
156
156
  this.elementType = 'qopdescRefinement';
157
157
  }
158
- getOp(inputFS, headFS, qOpDesc, refineThis) {
158
+ getOp(inputFS, isNestIn, qOpDesc, refineThis) {
159
159
  qOpDesc.refineFrom(refineThis);
160
- return qOpDesc.getOp(inputFS, headFS).segment;
160
+ return qOpDesc.getOp(inputFS, isNestIn).segment;
161
161
  }
162
- refine(inputFS, _pipeline) {
162
+ refine(inputFS, _pipeline, isNestIn) {
163
163
  const pipeline = [..._pipeline];
164
164
  if (pipeline.length === 1) {
165
165
  this.qOpDesc.refineFrom(pipeline[0]);
166
- return [this.getOp(inputFS, undefined, this.qOpDesc, pipeline[0])];
166
+ return [this.getOp(inputFS, isNestIn, this.qOpDesc, pipeline[0])];
167
167
  }
168
168
  const headRefinements = new qop_desc_1.QOPDesc([]);
169
169
  const tailRefinements = new qop_desc_1.QOPDesc([]);
@@ -15,7 +15,6 @@ export interface FieldSpace {
15
15
  entry(symbol: string): SpaceEntry | undefined;
16
16
  entries(): [string, SpaceEntry][];
17
17
  dialectObj(): Dialect | undefined;
18
- whenComplete: (step: () => void) => void;
19
18
  isQueryFieldSpace(): this is QueryFieldSpace;
20
19
  }
21
20
  export interface QueryFieldSpace extends FieldSpace {
@@ -187,6 +187,26 @@ describe('query:', () => {
187
187
  }
188
188
  `).toTranslate();
189
189
  });
190
+ test('exclude output checking survives refinement', () => {
191
+ // This was https://github.com/malloydata/malloy/issues/1474
192
+ const nestExclude = (0, test_translator_1.model) `
193
+ source: flights is a extend {
194
+ dimension: carrier is astr, destination is astr
195
+ measure: flight_count is count()
196
+ view: by_dest is {
197
+ group_by: destination
198
+ aggregate: flight_count
199
+ }
200
+ }
201
+ run: flights -> {
202
+ group_by: carrier
203
+ nest: broken is by_dest + {
204
+ top: 5
205
+ aggregate: flights_to_dest_all_carriers is exclude(flight_count, carrier)
206
+ }
207
+ }`;
208
+ expect(nestExclude).toTranslate();
209
+ });
190
210
  });
191
211
  describe('query operation typechecking', () => {
192
212
  describe('field declarations', () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/malloy",
3
- "version": "0.0.104-dev231116200719",
3
+ "version": "0.0.104-dev231117205713",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",