@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.
- package/dist/lang/ast/elements/pipeline-desc.d.ts +13 -2
- package/dist/lang/ast/elements/pipeline-desc.js +15 -2
- package/dist/lang/ast/expressions/constant-sub-expression.js +0 -3
- package/dist/lang/ast/expressions/expr-ungroup.js +24 -19
- package/dist/lang/ast/field-space/dynamic-space.d.ts +0 -1
- package/dist/lang/ast/field-space/dynamic-space.js +0 -12
- package/dist/lang/ast/field-space/query-input-space.d.ts +0 -1
- package/dist/lang/ast/field-space/query-spaces.d.ts +1 -7
- package/dist/lang/ast/field-space/query-spaces.js +0 -27
- package/dist/lang/ast/field-space/static-space.d.ts +0 -1
- package/dist/lang/ast/field-space/static-space.js +0 -19
- package/dist/lang/ast/query-items/field-declaration.d.ts +0 -1
- package/dist/lang/ast/query-items/field-declaration.js +0 -3
- package/dist/lang/ast/query-properties/nest.d.ts +6 -4
- package/dist/lang/ast/query-properties/nest.js +16 -14
- package/dist/lang/ast/query-properties/qop-desc.d.ts +2 -2
- package/dist/lang/ast/query-properties/qop-desc.js +3 -3
- package/dist/lang/ast/query-properties/refinements.d.ts +10 -4
- package/dist/lang/ast/query-properties/refinements.js +7 -7
- package/dist/lang/ast/types/field-space.d.ts +0 -1
- package/dist/lang/test/query.spec.js +20 -0
- package/package.json +1 -1
|
@@ -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 {
|
|
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
|
-
|
|
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.
|
|
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
|
}
|
|
@@ -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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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;
|
|
@@ -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
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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 {
|
|
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,
|
|
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,
|
|
89
|
+
getOp(inputFS, isNestIn) {
|
|
90
90
|
const build = this.getBuilder(inputFS);
|
|
91
|
-
if (
|
|
92
|
-
build.
|
|
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
|
-
|
|
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,
|
|
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,
|
|
83
|
+
getOp(inputFS, refineTo) {
|
|
84
84
|
var _a, _b;
|
|
85
|
-
const 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,
|
|
158
|
+
getOp(inputFS, isNestIn, qOpDesc, refineThis) {
|
|
159
159
|
qOpDesc.refineFrom(refineThis);
|
|
160
|
-
return qOpDesc.getOp(inputFS,
|
|
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,
|
|
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', () => {
|