@malloydata/malloy 0.0.86-dev230923002041 → 0.0.86-dev230928155428
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.
|
@@ -84,7 +84,7 @@ class ReferenceField extends space_field_1.SpaceField {
|
|
|
84
84
|
// and annotate the expression.
|
|
85
85
|
if ((0, malloy_types_1.isAtomicFieldType)(origFd.type)) {
|
|
86
86
|
const newField = {
|
|
87
|
-
name: this.fieldRef.list[-1].refString,
|
|
87
|
+
name: this.fieldRef.list[this.fieldRef.list.length - 1].refString,
|
|
88
88
|
type: origFd.type,
|
|
89
89
|
e: [{ type: 'field', path }],
|
|
90
90
|
annotation,
|
|
@@ -820,6 +820,9 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
820
820
|
}
|
|
821
821
|
buildPipelineFromName(pipe, pipeCx) {
|
|
822
822
|
const firstCx = pipeCx.firstSegment();
|
|
823
|
+
if (this.m4WarningsEnabled() && firstCx.ARROW()) {
|
|
824
|
+
this.contextError(firstCx, "Leading '->' in a view or nest definition is no longer needed.", 'warn');
|
|
825
|
+
}
|
|
823
826
|
const nameCx = firstCx.exploreQueryName();
|
|
824
827
|
if (nameCx) {
|
|
825
828
|
pipe.turtleName = this.getFieldName(nameCx);
|
|
@@ -601,5 +601,31 @@ describe('query operation annotations', () => {
|
|
|
601
601
|
expect(note_b === null || note_b === void 0 ? void 0 : note_b.annotation).matchesAnnotation({ inherits: defaultTags });
|
|
602
602
|
}
|
|
603
603
|
});
|
|
604
|
+
test('annotations preserved from path references', () => {
|
|
605
|
+
const m = (0, test_translator_1.model) `
|
|
606
|
+
run: a -> {
|
|
607
|
+
extend: {
|
|
608
|
+
join_one: x is
|
|
609
|
+
a extend {
|
|
610
|
+
# blockNote
|
|
611
|
+
dimension:
|
|
612
|
+
# note
|
|
613
|
+
xdim
|
|
614
|
+
# b4-is
|
|
615
|
+
is
|
|
616
|
+
# after-is
|
|
617
|
+
1
|
|
618
|
+
} on x.ai = ai
|
|
619
|
+
}
|
|
620
|
+
group_by: x.xdim
|
|
621
|
+
}`;
|
|
622
|
+
expect(m).toTranslate();
|
|
623
|
+
const foundYou = m.translator.getQuery(0);
|
|
624
|
+
expect(foundYou).toBeDefined();
|
|
625
|
+
if (foundYou) {
|
|
626
|
+
const note_b = (0, test_translator_1.getFieldDef)(foundYou.pipeline[0], 'xdim');
|
|
627
|
+
expect(note_b === null || note_b === void 0 ? void 0 : note_b.annotation).matchesAnnotation({ inherits: defaultTags });
|
|
628
|
+
}
|
|
629
|
+
});
|
|
604
630
|
});
|
|
605
631
|
//# sourceMappingURL=annotation.spec.js.map
|
|
@@ -26,52 +26,53 @@ const test_translator_1 = require("./test-translator");
|
|
|
26
26
|
require("./parse-expects");
|
|
27
27
|
const model_1 = require("../../model");
|
|
28
28
|
describe('query:', () => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
describe('basic query syntax', () => {
|
|
30
|
+
test('anonymous query', () => {
|
|
31
|
+
expect((0, test_translator_1.markSource) `query: ${"table('aTable') -> { group_by: astr }"}`).toTranslate();
|
|
32
|
+
});
|
|
33
|
+
test('anonymous query', () => {
|
|
34
|
+
expect((0, test_translator_1.markSource) `##! m4warnings
|
|
34
35
|
query: ${"conn.table('aTable') -> { group_by: astr }"}`).toTranslateWithWarnings('Anonymous `query:` statements are deprecated, use `run:` instead');
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
});
|
|
37
|
+
test('run query', () => expect("run: table('aTable') -> { group_by: astr }").toTranslate());
|
|
38
|
+
test('run query ref', () => expect(`
|
|
38
39
|
query: foo is table('aTable') -> { group_by: astr }
|
|
39
40
|
run: foo
|
|
40
41
|
`).toTranslate());
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
test('query', () => expect("query: name is table('aTable') -> { group_by: astr }").toTranslate());
|
|
43
|
+
test('query', () => {
|
|
44
|
+
expect("query: name is table('aTable') -> { group_by: astr }").toTranslate();
|
|
45
|
+
});
|
|
46
|
+
test('query from query', () => {
|
|
47
|
+
expect(`
|
|
47
48
|
query: q1 is ab->{ group_by: astr limit: 10 }
|
|
48
49
|
query: q2 is ->q1
|
|
49
50
|
`).toTranslate();
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
});
|
|
52
|
+
test('query with refinements from query', () => {
|
|
53
|
+
expect(`
|
|
53
54
|
query: q1 is ab->{ group_by: astr limit: 10 }
|
|
54
55
|
query: q2 is ->q1 { aggregate: acount }
|
|
55
56
|
`).toTranslate();
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
});
|
|
58
|
+
test('chained query operations', () => {
|
|
59
|
+
expect(`
|
|
59
60
|
query: ab
|
|
60
61
|
-> { group_by: astr; aggregate: acount }
|
|
61
62
|
-> { top: 5; where: astr ~ 'a%' group_by: astr }
|
|
62
63
|
`).toTranslate();
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
});
|
|
65
|
+
test('from(query) refined into query', () => {
|
|
66
|
+
expect('query: from(ab -> {group_by: astr}) { dimension: bigstr is upper(astr) } -> { group_by: bigstr }').toTranslate();
|
|
67
|
+
});
|
|
68
|
+
test('query with shortcut filtered turtle', () => {
|
|
69
|
+
expect("query: allA is ab -> aturtle {? astr ~ 'a%' }").toTranslate();
|
|
70
|
+
});
|
|
71
|
+
test('query with filtered turtle', () => {
|
|
72
|
+
expect("query: allA is ab -> aturtle { where: astr ~ 'a%' }").toTranslate();
|
|
73
|
+
});
|
|
74
|
+
test('nest: in group_by:', () => {
|
|
75
|
+
expect(`
|
|
75
76
|
query: ab -> {
|
|
76
77
|
group_by: astr;
|
|
77
78
|
nest: nested_count is {
|
|
@@ -79,45 +80,45 @@ describe('query:', () => {
|
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
`).toTranslate();
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
});
|
|
84
|
+
test('reduce pipe project', () => {
|
|
85
|
+
expect(`
|
|
85
86
|
query: a -> { aggregate: f is count() } -> { project: f2 is f + 1 }
|
|
86
87
|
`).toTranslate();
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
});
|
|
89
|
+
test('refine and extend query', () => {
|
|
90
|
+
expect(`
|
|
90
91
|
query: a_by_str is a -> { group_by: astr }
|
|
91
92
|
query: -> a_by_str { aggregate: str_count is count() }
|
|
92
93
|
`).toTranslate();
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
});
|
|
95
|
+
test('query refinement preserves original', () => {
|
|
96
|
+
const x = new test_translator_1.TestTranslator(`
|
|
96
97
|
query: q is a -> { aggregate: acount is count() }
|
|
97
98
|
query: nq is -> q + { group_by: astr }
|
|
98
99
|
`);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
100
|
+
expect(x).toTranslate();
|
|
101
|
+
const q = x.getQuery('q');
|
|
102
|
+
expect(q).toBeDefined();
|
|
103
|
+
if (q) {
|
|
104
|
+
const qFields = q.pipeline[0].fields;
|
|
105
|
+
expect(qFields.length).toBe(1);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
test('query composition preserves original', () => {
|
|
109
|
+
const x = new test_translator_1.TestTranslator(`
|
|
109
110
|
query: q is ab -> { aggregate: acount }
|
|
110
111
|
query: nq is -> q -> { project: * }
|
|
111
112
|
`);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
113
|
+
expect(x).toTranslate();
|
|
114
|
+
const q = x.getQuery('q');
|
|
115
|
+
expect(q).toBeDefined();
|
|
116
|
+
if (q) {
|
|
117
|
+
expect(q.pipeline.length).toBe(1);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
test('all ungroup with args', () => {
|
|
121
|
+
expect(`
|
|
121
122
|
query: a -> {
|
|
122
123
|
group_by: astr
|
|
123
124
|
nest: by_int is {
|
|
@@ -126,9 +127,9 @@ describe('query:', () => {
|
|
|
126
127
|
}
|
|
127
128
|
}
|
|
128
129
|
`).toTranslate();
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
});
|
|
131
|
+
test('all ungroup checks args', () => {
|
|
132
|
+
expect(`
|
|
132
133
|
query: a -> {
|
|
133
134
|
group_by: astr
|
|
134
135
|
nest: by_int is {
|
|
@@ -137,9 +138,9 @@ describe('query:', () => {
|
|
|
137
138
|
}
|
|
138
139
|
}
|
|
139
140
|
`).translationToFailWith("all() 'afloat' is missing from query output");
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
});
|
|
142
|
+
test('exclude ungroup with args', () => {
|
|
143
|
+
expect(`
|
|
143
144
|
query: a -> {
|
|
144
145
|
group_by: aa is 'a'
|
|
145
146
|
nest: by_b is {
|
|
@@ -151,9 +152,9 @@ describe('query:', () => {
|
|
|
151
152
|
}
|
|
152
153
|
}
|
|
153
154
|
`).toTranslate();
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
155
|
+
});
|
|
156
|
+
test('exclude ungroup checks args', () => {
|
|
157
|
+
expect(`
|
|
157
158
|
query: a -> {
|
|
158
159
|
group_by: aa is 'a'
|
|
159
160
|
nest: by_b is {
|
|
@@ -165,9 +166,9 @@ describe('query:', () => {
|
|
|
165
166
|
}
|
|
166
167
|
}
|
|
167
168
|
`).translationToFailWith("exclude() 'aaa' is missing from query output");
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
});
|
|
170
|
+
test('exclude problem revealed by production models', () => {
|
|
171
|
+
expect(`
|
|
171
172
|
source: carriers is table('malloytest.carriers') {
|
|
172
173
|
primary_key: code
|
|
173
174
|
}
|
|
@@ -185,6 +186,7 @@ describe('query:', () => {
|
|
|
185
186
|
}
|
|
186
187
|
}
|
|
187
188
|
`).toTranslate();
|
|
189
|
+
});
|
|
188
190
|
});
|
|
189
191
|
describe('query operation typechecking', () => {
|
|
190
192
|
describe('field declarations', () => {
|
|
@@ -205,6 +205,11 @@ describe('source:', () => {
|
|
|
205
205
|
source: c is a extend {query: q is { group_by: astr } }
|
|
206
206
|
`).toTranslateWithWarnings('Use view: inside of a source instead of query:');
|
|
207
207
|
});
|
|
208
|
+
test('turtle in source m4 warning on arrow', () => {
|
|
209
|
+
expect(`##! m4warnings
|
|
210
|
+
source: c is a extend {view: q is -> { group_by: astr } }
|
|
211
|
+
`).toTranslateWithWarnings("Leading '->' in a view or nest definition is no longer needed.");
|
|
212
|
+
});
|
|
208
213
|
test('refined explore-query', () => {
|
|
209
214
|
expect(`
|
|
210
215
|
source: abNew is ab {
|