@malloydata/malloy 0.0.240-dev250311202829 → 0.0.240-dev250311214430
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/api/core.d.ts +1 -0
- package/dist/api/core.js +2 -1
- package/dist/lang/malloy-parse-info.d.ts +2 -10
- package/dist/lang/malloy-to-ast.d.ts +1 -0
- package/dist/lang/malloy-to-ast.js +9 -6
- package/dist/lang/malloy-to-stable-query.d.ts +76 -0
- package/dist/lang/malloy-to-stable-query.js +660 -0
- package/dist/lang/parse-log.d.ts +1 -0
- package/dist/lang/parse-malloy.d.ts +2 -9
- package/dist/lang/parse-malloy.js +7 -112
- package/dist/lang/parse-tree-walkers/model-annotation-walker.js +1 -1
- package/dist/lang/run-malloy-parser.d.ts +3 -0
- package/dist/lang/run-malloy-parser.js +53 -0
- package/dist/lang/syntax-errors/malloy-parser-error-listener.d.ts +4 -3
- package/dist/lang/syntax-errors/malloy-parser-error-listener.js +8 -4
- package/dist/lang/utils.d.ts +27 -1
- package/dist/lang/utils.js +78 -1
- package/package.json +3 -3
- package/dist/api/asynchronous.spec.d.ts +0 -1
- package/dist/api/asynchronous.spec.js +0 -240
- package/dist/api/sessioned.spec.d.ts +0 -1
- package/dist/api/sessioned.spec.js +0 -476
- package/dist/api/stateless.spec.d.ts +0 -1
- package/dist/api/stateless.spec.js +0 -400
- package/dist/lang/test/annotation.spec.d.ts +0 -14
- package/dist/lang/test/annotation.spec.js +0 -809
- package/dist/lang/test/composite-field-usage.spec.d.ts +0 -1
- package/dist/lang/test/composite-field-usage.spec.js +0 -261
- package/dist/lang/test/document-help-context-walker.spec.d.ts +0 -1
- package/dist/lang/test/document-help-context-walker.spec.js +0 -55
- package/dist/lang/test/document-symbol-walker.spec.d.ts +0 -1
- package/dist/lang/test/document-symbol-walker.spec.js +0 -209
- package/dist/lang/test/expressions.spec.d.ts +0 -1
- package/dist/lang/test/expressions.spec.js +0 -1181
- package/dist/lang/test/field-symbols.spec.d.ts +0 -1
- package/dist/lang/test/field-symbols.spec.js +0 -194
- package/dist/lang/test/find-table-path-walker.spec.d.ts +0 -1
- package/dist/lang/test/find-table-path-walker.spec.js +0 -50
- package/dist/lang/test/imports.spec.d.ts +0 -1
- package/dist/lang/test/imports.spec.js +0 -283
- package/dist/lang/test/lenses.spec.d.ts +0 -1
- package/dist/lang/test/lenses.spec.js +0 -384
- package/dist/lang/test/literals.spec.d.ts +0 -1
- package/dist/lang/test/literals.spec.js +0 -267
- package/dist/lang/test/locations.spec.d.ts +0 -1
- package/dist/lang/test/locations.spec.js +0 -679
- package/dist/lang/test/model-annotation-walker.spec.d.ts +0 -1
- package/dist/lang/test/model-annotation-walker.spec.js +0 -46
- package/dist/lang/test/model_serialization.spec.d.ts +0 -5
- package/dist/lang/test/model_serialization.spec.js +0 -116
- package/dist/lang/test/parameters.spec.d.ts +0 -1
- package/dist/lang/test/parameters.spec.js +0 -619
- package/dist/lang/test/parse.spec.d.ts +0 -1
- package/dist/lang/test/parse.spec.js +0 -893
- package/dist/lang/test/pretranslate.spec.d.ts +0 -1
- package/dist/lang/test/pretranslate.spec.js +0 -80
- package/dist/lang/test/query.spec.d.ts +0 -1
- package/dist/lang/test/query.spec.js +0 -1149
- package/dist/lang/test/source.spec.d.ts +0 -1
- package/dist/lang/test/source.spec.js +0 -570
- package/dist/lang/test/sql-block.spec.d.ts +0 -1
- package/dist/lang/test/sql-block.spec.js +0 -145
- package/dist/lang/test/syntax-errors.spec.d.ts +0 -1
- package/dist/lang/test/syntax-errors.spec.js +0 -142
- package/dist/model/utils.spec.d.ts +0 -1
- package/dist/model/utils.spec.js +0 -38
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Copyright 2023 Google LLC
|
|
4
|
-
*
|
|
5
|
-
* Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
-
* a copy of this software and associated documentation files
|
|
7
|
-
* (the "Software"), to deal in the Software without restriction,
|
|
8
|
-
* including without limitation the rights to use, copy, modify, merge,
|
|
9
|
-
* publish, distribute, sublicense, and/or sell copies of the Software,
|
|
10
|
-
* and to permit persons to whom the Software is furnished to do so,
|
|
11
|
-
* subject to the following conditions:
|
|
12
|
-
*
|
|
13
|
-
* The above copyright notice and this permission notice shall be
|
|
14
|
-
* included in all copies or substantial portions of the Software.
|
|
15
|
-
*
|
|
16
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
-
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
-
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
-
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
20
|
-
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
21
|
-
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
22
|
-
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
-
*/
|
|
24
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
const test_translator_1 = require("./test-translator");
|
|
26
|
-
require("./parse-expects");
|
|
27
|
-
describe('lenses', () => {
|
|
28
|
-
test('long lens patterns', () => {
|
|
29
|
-
expect((0, test_translator_1.markSource) `
|
|
30
|
-
source: s1 is a extend {
|
|
31
|
-
view: v1 is { group_by: d1 is 1 }
|
|
32
|
-
view: v2 is { group_by: d2 is 2 }
|
|
33
|
-
view: v3 is { group_by: d3 is 3 }
|
|
34
|
-
view: v4 is v1 + v2 + v3
|
|
35
|
-
view: v5 is {
|
|
36
|
-
nest: n1 is v1 + v2 + v3
|
|
37
|
-
nest: n2 is { group_by: d1 is 1 } + v2 + v3
|
|
38
|
-
nest: n3 is v1 + v2 + { group_by: d3 is 3 }
|
|
39
|
-
}
|
|
40
|
-
view: v6 is { group_by: d1 is 1 } + v2 + v3
|
|
41
|
-
}
|
|
42
|
-
run: s1 -> v4
|
|
43
|
-
source: s2 is s1 -> v1 + v2 + v3
|
|
44
|
-
source: s3 is s1 -> { group_by: d1 is 1 } + v2 + v3
|
|
45
|
-
`).toTranslate();
|
|
46
|
-
});
|
|
47
|
-
test('lens parens patterns', () => {
|
|
48
|
-
expect((0, test_translator_1.markSource) `
|
|
49
|
-
source: s1 is a extend {
|
|
50
|
-
view: v1 is { group_by: d1 is 1 }
|
|
51
|
-
view: v2 is { group_by: d2 is 2 }
|
|
52
|
-
view: v3 is { group_by: d3 is 3 }
|
|
53
|
-
view: v4 is (v1 + v2) + v3
|
|
54
|
-
view: v5 is {
|
|
55
|
-
nest: n1 is v1 + (v2 + v3)
|
|
56
|
-
nest: n2 is (({ group_by: d1 is 1 } + v2) + v3)
|
|
57
|
-
nest: n3 is v1 + v2 + { group_by: d3 is 3 }
|
|
58
|
-
}
|
|
59
|
-
view: v6 is { group_by: d1 is 1 } + (v2 + v3)
|
|
60
|
-
}
|
|
61
|
-
run: (s1 -> v4)
|
|
62
|
-
run: (s1 -> (((v4))))
|
|
63
|
-
source: s2 is ((s1 -> v1) + v2) + v3
|
|
64
|
-
source: s3 is s1 -> (v1 + (v2 + v3))
|
|
65
|
-
source: s4 is (s1 -> v1) + (v2 + v3)
|
|
66
|
-
source: s5 is s1 -> { group_by: d1 is 1 } + v2 + v3
|
|
67
|
-
`).toTranslate();
|
|
68
|
-
});
|
|
69
|
-
test('cannot have overlapping names', () => {
|
|
70
|
-
expect((0, test_translator_1.markSource) `
|
|
71
|
-
source: x is a extend {
|
|
72
|
-
dimension: n is 1
|
|
73
|
-
view: d is { group_by: n }
|
|
74
|
-
}
|
|
75
|
-
run: x -> d + d
|
|
76
|
-
`).toLog((0, test_translator_1.errorMessage)('overlapping fields in refinement: n'));
|
|
77
|
-
});
|
|
78
|
-
test('cannot override limit', () => {
|
|
79
|
-
expect((0, test_translator_1.markSource) `
|
|
80
|
-
source: x is a extend {
|
|
81
|
-
view: d1 is { group_by: n1 is 1; limit: 10 }
|
|
82
|
-
view: d2 is { group_by: n2 is 2; limit: 20 }
|
|
83
|
-
}
|
|
84
|
-
run: x -> d1 + d2
|
|
85
|
-
`).toLog((0, test_translator_1.errorMessage)('refinement cannot override existing limit'));
|
|
86
|
-
});
|
|
87
|
-
test('cannot override ordering', () => {
|
|
88
|
-
expect((0, test_translator_1.markSource) `
|
|
89
|
-
source: x is a extend {
|
|
90
|
-
view: d1 is { group_by: n1 is ai; order_by: n1 }
|
|
91
|
-
view: d2 is { group_by: n2 is 1; order_by: n2 }
|
|
92
|
-
}
|
|
93
|
-
run: x -> d1 + d2
|
|
94
|
-
`).toLog((0, test_translator_1.errorMessage)('refinement cannot override existing ordering'));
|
|
95
|
-
});
|
|
96
|
-
test('weird issue with order by constant group by', () => {
|
|
97
|
-
expect((0, test_translator_1.markSource) `
|
|
98
|
-
source: x is a extend {
|
|
99
|
-
view: d1 is { group_by: n1 is 1; order_by: n1 }
|
|
100
|
-
}
|
|
101
|
-
`).toTranslate();
|
|
102
|
-
});
|
|
103
|
-
test('can add a limit late', () => {
|
|
104
|
-
expect((0, test_translator_1.markSource) `
|
|
105
|
-
source: x is a extend {
|
|
106
|
-
view: d1 is { group_by: n1 is 1 }
|
|
107
|
-
view: d2 is { group_by: n2 is 2 }
|
|
108
|
-
}
|
|
109
|
-
run: x -> d1 + d2 + { limit: 10 }
|
|
110
|
-
`).toTranslate();
|
|
111
|
-
});
|
|
112
|
-
test('cannot refine with incompatible view types', () => {
|
|
113
|
-
expect((0, test_translator_1.markSource) `
|
|
114
|
-
source: x is a extend {
|
|
115
|
-
view: grp is { group_by: n1 is 1 }
|
|
116
|
-
view: proj is { select: n2 is 2 }
|
|
117
|
-
view: idx is { index: * }
|
|
118
|
-
}
|
|
119
|
-
run: x -> grp + proj
|
|
120
|
-
run: x -> grp + idx
|
|
121
|
-
run: x -> proj + idx
|
|
122
|
-
run: x -> proj + grp
|
|
123
|
-
run: x -> idx + grp
|
|
124
|
-
run: x -> idx + proj
|
|
125
|
-
`).toLog((0, test_translator_1.errorMessage)('cannot refine reduce view with project view'), (0, test_translator_1.errorMessage)('cannot refine reduce view with index view'), (0, test_translator_1.errorMessage)('cannot refine project view with index view'), (0, test_translator_1.errorMessage)('cannot refine project view with reduce view'), (0, test_translator_1.errorMessage)('cannot refine index view with reduce view'), (0, test_translator_1.errorMessage)('cannot refine index view with project view'));
|
|
126
|
-
});
|
|
127
|
-
test('can reference dimension at head of query when experiment is enabled', () => {
|
|
128
|
-
expect((0, test_translator_1.markSource) `
|
|
129
|
-
source: x is a extend {
|
|
130
|
-
dimension: n is 1
|
|
131
|
-
}
|
|
132
|
-
run: x -> n
|
|
133
|
-
`).toTranslate();
|
|
134
|
-
});
|
|
135
|
-
test('can change refine precedence', () => {
|
|
136
|
-
expect((0, test_translator_1.markSource) `
|
|
137
|
-
source: x is a extend {
|
|
138
|
-
dimension:
|
|
139
|
-
a is 1
|
|
140
|
-
b is 2
|
|
141
|
-
c is 3
|
|
142
|
-
}
|
|
143
|
-
run: x -> a + (b + c)
|
|
144
|
-
`).toTranslate();
|
|
145
|
-
});
|
|
146
|
-
test.skip('can split multi-stage refinement with plus', () => {
|
|
147
|
-
expect((0, test_translator_1.markSource) `
|
|
148
|
-
source: x is a extend {
|
|
149
|
-
view: two_stage is { group_by: a is 1 } -> { group_by: a }
|
|
150
|
-
}
|
|
151
|
-
run: x -> two_stage + ({ where: true } + { limit: 3 })
|
|
152
|
-
`).toTranslate();
|
|
153
|
-
});
|
|
154
|
-
test('cannot refine with multi-stage', () => {
|
|
155
|
-
expect((0, test_translator_1.markSource) `
|
|
156
|
-
source: x is a extend {
|
|
157
|
-
view: one_stage is { group_by: a is 1 }
|
|
158
|
-
view: two_stage is { group_by: a is 1 } -> { group_by: a }
|
|
159
|
-
}
|
|
160
|
-
run: x -> one_stage + two_stage
|
|
161
|
-
`).toLog((0, test_translator_1.errorMessage)('named refinement `two_stage` must have exactly one stage'));
|
|
162
|
-
});
|
|
163
|
-
test('cannot refine with literal multi-stage', () => {
|
|
164
|
-
expect((0, test_translator_1.markSource) `
|
|
165
|
-
source: x is a extend {
|
|
166
|
-
view: one_stage is { group_by: a is 1 }
|
|
167
|
-
view: two_stage is { group_by: a is 1 } -> { group_by: a }
|
|
168
|
-
}
|
|
169
|
-
run: x -> one_stage + ({ group_by: a is 1 } -> { group_by: a })
|
|
170
|
-
`).toLog((0, test_translator_1.errorMessage)('A multi-segment view cannot be used as a refinement'));
|
|
171
|
-
});
|
|
172
|
-
test('can reference dimension in refinement when experiment is enabled', () => {
|
|
173
|
-
expect((0, test_translator_1.markSource) `
|
|
174
|
-
source: x is a extend {
|
|
175
|
-
dimension: n is 1
|
|
176
|
-
view: d is { group_by: n1 is 1 }
|
|
177
|
-
}
|
|
178
|
-
run: x -> d + n
|
|
179
|
-
`).toTranslate();
|
|
180
|
-
});
|
|
181
|
-
test('can reference join field when experiment is enabled', () => {
|
|
182
|
-
expect((0, test_translator_1.markSource) `
|
|
183
|
-
source: x is a extend {
|
|
184
|
-
join_cross: y is a extend { dimension: n is 1 } on true
|
|
185
|
-
}
|
|
186
|
-
run: x -> y.n
|
|
187
|
-
`).toTranslate();
|
|
188
|
-
});
|
|
189
|
-
test('can reference join field in refinement when experiment is enabled', () => {
|
|
190
|
-
expect((0, test_translator_1.markSource) `
|
|
191
|
-
source: x is a extend {
|
|
192
|
-
join_cross: y is a extend { dimension: n is 1 } on true
|
|
193
|
-
}
|
|
194
|
-
run: x -> ai + y.n
|
|
195
|
-
`).toTranslate();
|
|
196
|
-
});
|
|
197
|
-
test('can reference join field in nest refinement when experiment is enabled', () => {
|
|
198
|
-
expect((0, test_translator_1.markSource) `
|
|
199
|
-
source: x is a extend {
|
|
200
|
-
join_cross: y is a extend { dimension: n is 1 } on true
|
|
201
|
-
}
|
|
202
|
-
run: x -> { nest: ai + y.n }
|
|
203
|
-
`).toTranslate();
|
|
204
|
-
});
|
|
205
|
-
test('can nest dimension when experiment is enabled', () => {
|
|
206
|
-
expect((0, test_translator_1.markSource) `
|
|
207
|
-
source: x is a extend {
|
|
208
|
-
dimension: n is 1
|
|
209
|
-
view: d is { nest: n }
|
|
210
|
-
}
|
|
211
|
-
run: x -> d
|
|
212
|
-
`).toTranslate();
|
|
213
|
-
});
|
|
214
|
-
test('cannot use join_name in refinement shortcut', () => {
|
|
215
|
-
expect((0, test_translator_1.markSource) `
|
|
216
|
-
source: x is a extend {
|
|
217
|
-
join_one: y is a on true
|
|
218
|
-
view: m is { aggregate: c is count() }
|
|
219
|
-
}
|
|
220
|
-
run: x -> m + y + { limit: 1 }`).toLog((0, test_translator_1.errorMessage)('named refinement `y` must be a view, found a table'));
|
|
221
|
-
});
|
|
222
|
-
test('cannot use view from join as whole pipeline', () => {
|
|
223
|
-
expect((0, test_translator_1.markSource) `
|
|
224
|
-
source: x is a extend {
|
|
225
|
-
join_one: y is a extend {
|
|
226
|
-
view: z is { group_by: d is 1 }
|
|
227
|
-
} on true
|
|
228
|
-
}
|
|
229
|
-
run: x -> y.z
|
|
230
|
-
`).toLog((0, test_translator_1.errorMessage)('Cannot use view from join'));
|
|
231
|
-
});
|
|
232
|
-
test('cannot use view from join in nest', () => {
|
|
233
|
-
expect((0, test_translator_1.markSource) `
|
|
234
|
-
source: x is a extend {
|
|
235
|
-
join_one: y is a extend {
|
|
236
|
-
view: z is { group_by: d is 1 }
|
|
237
|
-
} on true
|
|
238
|
-
}
|
|
239
|
-
run: x -> { nest: y.z }
|
|
240
|
-
`).toLog((0, test_translator_1.errorMessage)('Cannot use view from join'));
|
|
241
|
-
});
|
|
242
|
-
test('cannot use view from join as nest view head', () => {
|
|
243
|
-
expect((0, test_translator_1.markSource) `
|
|
244
|
-
source: x is a extend {
|
|
245
|
-
join_one: y is a extend {
|
|
246
|
-
view: z is { group_by: d is 1 }
|
|
247
|
-
} on true
|
|
248
|
-
}
|
|
249
|
-
run: x -> { nest: y.z + { limit: 1 } }
|
|
250
|
-
`).toLog((0, test_translator_1.errorMessage)('Cannot use view from join'));
|
|
251
|
-
});
|
|
252
|
-
test('cannot use view from join as lens in query', () => {
|
|
253
|
-
expect((0, test_translator_1.markSource) `
|
|
254
|
-
source: x is a extend {
|
|
255
|
-
join_one: y is a extend {
|
|
256
|
-
view: z is { group_by: d is 1 }
|
|
257
|
-
} on true
|
|
258
|
-
}
|
|
259
|
-
run: x -> ai + y.z
|
|
260
|
-
`).toLog((0, test_translator_1.errorMessage)('Cannot use view from join as refinement'));
|
|
261
|
-
});
|
|
262
|
-
test('cannot use view from join as lens in nest', () => {
|
|
263
|
-
expect((0, test_translator_1.markSource) `
|
|
264
|
-
source: x is a extend {
|
|
265
|
-
join_one: y is a extend {
|
|
266
|
-
view: z is { group_by: d is 1 }
|
|
267
|
-
} on true
|
|
268
|
-
}
|
|
269
|
-
run: x -> { nest: ai + y.z }
|
|
270
|
-
`).toLog((0, test_translator_1.errorMessage)('Cannot use view from join as refinement'));
|
|
271
|
-
});
|
|
272
|
-
test('can nest dimension with refinement when experiment is enabled', () => {
|
|
273
|
-
expect((0, test_translator_1.markSource) `
|
|
274
|
-
source: x is a extend {
|
|
275
|
-
dimension: n is 1
|
|
276
|
-
view: d is { nest: n + { where: n > 0 } }
|
|
277
|
-
}
|
|
278
|
-
run: x -> d
|
|
279
|
-
`).toTranslate();
|
|
280
|
-
});
|
|
281
|
-
test('cannot reference join', () => {
|
|
282
|
-
expect((0, test_translator_1.markSource) `
|
|
283
|
-
source: x is a extend {
|
|
284
|
-
join_one: b is a on true
|
|
285
|
-
dimension: n is 1
|
|
286
|
-
view: d is { group_by: n }
|
|
287
|
-
}
|
|
288
|
-
run: x -> d + b
|
|
289
|
-
`).toLog((0, test_translator_1.errorMessage)('named refinement `b` must be a view, found a table'));
|
|
290
|
-
});
|
|
291
|
-
test('cannot reference field in LHS of refinement in group_by', () => {
|
|
292
|
-
expect((0, test_translator_1.markSource) `
|
|
293
|
-
source: x is a extend {
|
|
294
|
-
view: v is { group_by: i is 1 }
|
|
295
|
-
}
|
|
296
|
-
run: x -> v + { group_by: j is ${'i'} }
|
|
297
|
-
`).toLog((0, test_translator_1.errorMessage)("'i' is not defined"));
|
|
298
|
-
});
|
|
299
|
-
test('cannot named-refine multi-stage query', () => {
|
|
300
|
-
expect((0, test_translator_1.markSource) `
|
|
301
|
-
source: x is a extend {
|
|
302
|
-
join_one: b is a on true
|
|
303
|
-
dimension: n is 1
|
|
304
|
-
view: multi is { group_by: n } -> { group_by: n }
|
|
305
|
-
view: d is { group_by: n }
|
|
306
|
-
}
|
|
307
|
-
run: x -> multi + d
|
|
308
|
-
run: x -> d + multi
|
|
309
|
-
`).toLog((0, test_translator_1.errorMessage)('Named refinements of multi-stage views are not supported'), (0, test_translator_1.errorMessage)('named refinement `multi` must have exactly one stage'));
|
|
310
|
-
});
|
|
311
|
-
});
|
|
312
|
-
describe('partial views', () => {
|
|
313
|
-
test('allow where-headed refinement chains', () => {
|
|
314
|
-
expect((0, test_translator_1.markSource) `
|
|
315
|
-
source: x is a extend {
|
|
316
|
-
view: metrics is { aggregate: c is count() }
|
|
317
|
-
view: cool_metrics is { where: true } + metrics
|
|
318
|
-
}
|
|
319
|
-
`).toTranslate();
|
|
320
|
-
});
|
|
321
|
-
test('order by tacked on the end should work', () => {
|
|
322
|
-
expect((0, test_translator_1.markSource) `
|
|
323
|
-
run: a -> {
|
|
324
|
-
nest: astr + ai + { order_by: astr }
|
|
325
|
-
}
|
|
326
|
-
run: a -> {
|
|
327
|
-
nest: astr + { order_by: astr }
|
|
328
|
-
}
|
|
329
|
-
run: a -> astr + { order_by: astr }
|
|
330
|
-
run: a -> astr + ai + { order_by: astr }
|
|
331
|
-
`).toTranslate();
|
|
332
|
-
});
|
|
333
|
-
test('name can be inferred with arrow', () => {
|
|
334
|
-
expect((0, test_translator_1.markSource) `
|
|
335
|
-
run: a extend { view: foo is { group_by: astr } } -> {
|
|
336
|
-
nest: foo -> astr + { order_by: astr }
|
|
337
|
-
}
|
|
338
|
-
`).toTranslate();
|
|
339
|
-
});
|
|
340
|
-
test('nice error when nest has no name', () => {
|
|
341
|
-
expect((0, test_translator_1.markSource) `
|
|
342
|
-
run: a -> {
|
|
343
|
-
nest: { group_by: astr }
|
|
344
|
-
}
|
|
345
|
-
`).toLog((0, test_translator_1.errorMessage)('`nest:` view requires a name (add `nest_name is ...`)'));
|
|
346
|
-
});
|
|
347
|
-
test.skip('partial with index', () => {
|
|
348
|
-
expect((0, test_translator_1.markSource) `
|
|
349
|
-
source: x is a extend {
|
|
350
|
-
view: idx is { index: * }
|
|
351
|
-
}
|
|
352
|
-
run: x -> { where: true } + idx
|
|
353
|
-
`).toTranslate();
|
|
354
|
-
});
|
|
355
|
-
test('disallow chains that have no fields in view', () => {
|
|
356
|
-
expect((0, test_translator_1.markSource) `
|
|
357
|
-
source: x is a extend {
|
|
358
|
-
view: bad1 is { where: true }
|
|
359
|
-
view: bad2 is { where: true } + { where: false }
|
|
360
|
-
}
|
|
361
|
-
`).toLog((0, test_translator_1.error)('ambiguous-view-type'), (0, test_translator_1.error)('ambiguous-view-type'));
|
|
362
|
-
});
|
|
363
|
-
test('disallow chains that have no fields in multi-stage', () => {
|
|
364
|
-
expect((0, test_translator_1.markSource) `
|
|
365
|
-
source: x is a extend {
|
|
366
|
-
view: v is { group_by: ai }
|
|
367
|
-
view: v2 is v -> { where: true }
|
|
368
|
-
view: v3 is { where: true } -> { group_by: undef }
|
|
369
|
-
}
|
|
370
|
-
run: x -> v -> { where: true }
|
|
371
|
-
run: x -> { where: true } -> { group_by: undef }
|
|
372
|
-
`).toLog((0, test_translator_1.error)('ambiguous-view-type'), (0, test_translator_1.errorMessage)("'undef' is not defined"), (0, test_translator_1.error)('ambiguous-view-type'), (0, test_translator_1.error)('ambiguous-view-type'), (0, test_translator_1.errorMessage)("'undef' is not defined"), (0, test_translator_1.error)('ambiguous-view-type'));
|
|
373
|
-
});
|
|
374
|
-
test('copy of view with refinement should work', () => {
|
|
375
|
-
expect((0, test_translator_1.markSource) `
|
|
376
|
-
source: x is a extend {
|
|
377
|
-
view: metrics is { aggregate: c is count() }
|
|
378
|
-
view: v is { group_by: ai } + metrics
|
|
379
|
-
view: v2 is v + { order_by: c }
|
|
380
|
-
}
|
|
381
|
-
`).toTranslate();
|
|
382
|
-
});
|
|
383
|
-
});
|
|
384
|
-
//# sourceMappingURL=lenses.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import './parse-expects';
|
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Copyright 2023 Google LLC
|
|
4
|
-
*
|
|
5
|
-
* Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
-
* a copy of this software and associated documentation files
|
|
7
|
-
* (the "Software"), to deal in the Software without restriction,
|
|
8
|
-
* including without limitation the rights to use, copy, modify, merge,
|
|
9
|
-
* publish, distribute, sublicense, and/or sell copies of the Software,
|
|
10
|
-
* and to permit persons to whom the Software is furnished to do so,
|
|
11
|
-
* subject to the following conditions:
|
|
12
|
-
*
|
|
13
|
-
* The above copyright notice and this permission notice shall be
|
|
14
|
-
* included in all copies or substantial portions of the Software.
|
|
15
|
-
*
|
|
16
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
-
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
-
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
-
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
20
|
-
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
21
|
-
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
22
|
-
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
-
*/
|
|
24
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
const test_translator_1 = require("./test-translator");
|
|
26
|
-
require("./parse-expects");
|
|
27
|
-
const granular_result_1 = require("../ast/types/granular-result");
|
|
28
|
-
describe('literals', () => {
|
|
29
|
-
test('integer', () => {
|
|
30
|
-
expect((0, test_translator_1.expr) `42`).toTranslate();
|
|
31
|
-
});
|
|
32
|
-
test('string', () => {
|
|
33
|
-
const m = new test_translator_1.BetaExpression("'forty two'");
|
|
34
|
-
expect(m).toTranslate();
|
|
35
|
-
const m42 = m.generated().value;
|
|
36
|
-
expect(m42).toMatchObject({ literal: 'forty two' });
|
|
37
|
-
});
|
|
38
|
-
test('string with quoted quote', () => {
|
|
39
|
-
const str = "'Isn" + '\\' + "'t this nice'";
|
|
40
|
-
expect(new test_translator_1.BetaExpression(str)).toTranslate();
|
|
41
|
-
});
|
|
42
|
-
test('string with quoted backslash', () => {
|
|
43
|
-
const str = "'Is " + '\\' + '\\' + " nice'";
|
|
44
|
-
expect(new test_translator_1.BetaExpression(str)).toTranslate();
|
|
45
|
-
});
|
|
46
|
-
test("raw s'string", () => {
|
|
47
|
-
expect("s'a'").compilesTo('{"a"}');
|
|
48
|
-
});
|
|
49
|
-
test('raw s"string', () => {
|
|
50
|
-
expect('s "a"').compilesTo('{"a"}');
|
|
51
|
-
});
|
|
52
|
-
test('raw string with quoted end char', () => {
|
|
53
|
-
expect("s'a\\'b'").compilesTo('{"a\\\'b"}');
|
|
54
|
-
});
|
|
55
|
-
const literalTimes = [
|
|
56
|
-
['@1960', 'date', 'year', { literal: '1960-01-01' }],
|
|
57
|
-
['@1960-Q2', 'date', 'quarter', { literal: '1960-04-01' }],
|
|
58
|
-
['@1960-06', 'date', 'month', { literal: '1960-06-01' }],
|
|
59
|
-
['@1960-06-26-WK', 'date', 'week', { literal: '1960-06-26' }],
|
|
60
|
-
['@1960-06-30', 'date', 'day', { literal: '1960-06-30' }],
|
|
61
|
-
['@1960-06-30 10', 'timestamp', 'hour', { literal: '1960-06-30 10:00:00' }],
|
|
62
|
-
[
|
|
63
|
-
'@1960-06-30 10:30',
|
|
64
|
-
'timestamp',
|
|
65
|
-
'minute',
|
|
66
|
-
{ literal: '1960-06-30 10:30:00' },
|
|
67
|
-
],
|
|
68
|
-
[
|
|
69
|
-
'@1960-06-30 10:30:00',
|
|
70
|
-
'timestamp',
|
|
71
|
-
undefined,
|
|
72
|
-
{ literal: '1960-06-30 10:30:00' },
|
|
73
|
-
],
|
|
74
|
-
[
|
|
75
|
-
'@1960-06-30 10:30:00.123',
|
|
76
|
-
'timestamp',
|
|
77
|
-
undefined,
|
|
78
|
-
{ literal: '1960-06-30 10:30:00.123' },
|
|
79
|
-
],
|
|
80
|
-
[
|
|
81
|
-
'@1960-06-30T10:30:00',
|
|
82
|
-
'timestamp',
|
|
83
|
-
undefined,
|
|
84
|
-
{ literal: '1960-06-30 10:30:00' },
|
|
85
|
-
],
|
|
86
|
-
[
|
|
87
|
-
'@1960-06-30 10:30:00[America/Los_Angeles]',
|
|
88
|
-
'timestamp',
|
|
89
|
-
undefined,
|
|
90
|
-
{
|
|
91
|
-
literal: '1960-06-30 10:30:00',
|
|
92
|
-
timezone: 'America/Los_Angeles',
|
|
93
|
-
},
|
|
94
|
-
],
|
|
95
|
-
];
|
|
96
|
-
test.each(literalTimes)('%s', (expr, timeType, timeframe, result) => {
|
|
97
|
-
const exprModel = new test_translator_1.BetaExpression(expr);
|
|
98
|
-
expect(exprModel).toTranslate();
|
|
99
|
-
const ir = exprModel.generated();
|
|
100
|
-
expect(ir.type).toEqual(timeType);
|
|
101
|
-
if (timeframe) {
|
|
102
|
-
expect((0, granular_result_1.isGranularResult)(ir)).toBeTruthy();
|
|
103
|
-
if ((0, granular_result_1.isGranularResult)(ir)) {
|
|
104
|
-
expect(ir.timeframe).toEqual(timeframe);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
expect((0, granular_result_1.isGranularResult)(ir)).toBeFalsy();
|
|
109
|
-
}
|
|
110
|
-
expect(ir.value).toEqual(expect.objectContaining(result));
|
|
111
|
-
});
|
|
112
|
-
const morphicLiterals = [
|
|
113
|
-
['@1960', '1960-01-01 00:00:00'],
|
|
114
|
-
['@1960-Q2', '1960-04-01 00:00:00'],
|
|
115
|
-
['@1960-06', '1960-06-01 00:00:00'],
|
|
116
|
-
['@1960-06-26-Wk', '1960-06-26 00:00:00'],
|
|
117
|
-
['@1960-06-30', '1960-06-30 00:00:00'],
|
|
118
|
-
['@1960-06-30 00:00', undefined],
|
|
119
|
-
];
|
|
120
|
-
test.each(morphicLiterals)('morphic value for %s is %s', (expr, morphic) => {
|
|
121
|
-
const exprModel = new test_translator_1.BetaExpression(expr);
|
|
122
|
-
expect(exprModel).toTranslate();
|
|
123
|
-
const ir = exprModel.generated();
|
|
124
|
-
const morphTo = ir.morphic && ir.morphic['timestamp'];
|
|
125
|
-
if (morphic) {
|
|
126
|
-
expect(morphTo).toBeDefined();
|
|
127
|
-
if (morphTo) {
|
|
128
|
-
expect(morphTo).toEqual(expect.objectContaining({ literal: morphic }));
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
expect(morphTo).toBeUndefined();
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
test('minute+locale', () => {
|
|
136
|
-
expect((0, test_translator_1.expr) `@1960-06-30 10:30[America/Los_Angeles]`).toTranslate();
|
|
137
|
-
});
|
|
138
|
-
test('second 8601', () => {
|
|
139
|
-
expect((0, test_translator_1.expr) `@1960-06-30T10:30:31`).toTranslate();
|
|
140
|
-
});
|
|
141
|
-
test('null', () => {
|
|
142
|
-
expect((0, test_translator_1.expr) `null`).toTranslate();
|
|
143
|
-
});
|
|
144
|
-
test('now', () => {
|
|
145
|
-
expect((0, test_translator_1.expr) `now`).toTranslate();
|
|
146
|
-
});
|
|
147
|
-
test('true', () => {
|
|
148
|
-
expect((0, test_translator_1.expr) `true`).toTranslate();
|
|
149
|
-
});
|
|
150
|
-
test('false', () => {
|
|
151
|
-
expect((0, test_translator_1.expr) `false`).toTranslate();
|
|
152
|
-
});
|
|
153
|
-
test('regex', () => {
|
|
154
|
-
expect((0, test_translator_1.expr) `r'RegularExpression'`).toTranslate();
|
|
155
|
-
});
|
|
156
|
-
describe('string parsing in language', () => {
|
|
157
|
-
const tz = 'America/Mexico_City';
|
|
158
|
-
test('multi-line indent increasing', () => {
|
|
159
|
-
const checking = new test_translator_1.BetaExpression(`"""
|
|
160
|
-
left
|
|
161
|
-
mid
|
|
162
|
-
right
|
|
163
|
-
"""`);
|
|
164
|
-
expect(checking).toTranslate();
|
|
165
|
-
const v = checking.generated().value;
|
|
166
|
-
expect(v).toMatchObject({ literal: '\nleft\n mid\n right\n' });
|
|
167
|
-
});
|
|
168
|
-
test('multi-line indent decreasing', () => {
|
|
169
|
-
const checking = new test_translator_1.BetaExpression(`"""
|
|
170
|
-
right
|
|
171
|
-
mid
|
|
172
|
-
left
|
|
173
|
-
"""`);
|
|
174
|
-
expect(checking).toTranslate();
|
|
175
|
-
const v = checking.generated().value;
|
|
176
|
-
expect(v).toMatchObject({ literal: '\n right\n mid\nleft\n' });
|
|
177
|
-
});
|
|
178
|
-
test('multi-line indent keep', () => {
|
|
179
|
-
const checking = new test_translator_1.BetaExpression('"""right\n mid\nleft"""');
|
|
180
|
-
expect(checking).toTranslate();
|
|
181
|
-
const v = checking.generated().value;
|
|
182
|
-
expect(v).toMatchObject({ literal: 'right\n mid\nleft' });
|
|
183
|
-
});
|
|
184
|
-
test('timezone single quote', () => {
|
|
185
|
-
const m = new test_translator_1.TestTranslator(`run: a-> {timezone: '${tz}'; select: *}`);
|
|
186
|
-
expect(m).toParse();
|
|
187
|
-
});
|
|
188
|
-
test('timezone double quote', () => {
|
|
189
|
-
const m = new test_translator_1.TestTranslator(`run: a-> {timezone: "${tz}"; select: *}`);
|
|
190
|
-
expect(m).toParse();
|
|
191
|
-
});
|
|
192
|
-
test('timezone triple quote', () => {
|
|
193
|
-
const m = new test_translator_1.TestTranslator(`run: a->{timezone: """${tz}"""; select: *}`);
|
|
194
|
-
expect(m).toParse();
|
|
195
|
-
});
|
|
196
|
-
test('timezone with illegal query', () => {
|
|
197
|
-
expect(`run: a->{timezone: """${tz}%{ab->aturtle}"""; select: *}`).toLog((0, test_translator_1.errorMessage)('%{ query } illegal in this string'));
|
|
198
|
-
});
|
|
199
|
-
test('table single quote', () => {
|
|
200
|
-
const m = new test_translator_1.TestTranslator("source: n is bigquery.table('n')");
|
|
201
|
-
expect(m).toParse();
|
|
202
|
-
});
|
|
203
|
-
test('table double quote', () => {
|
|
204
|
-
const m = new test_translator_1.TestTranslator('source: n is bigquery.table("n")');
|
|
205
|
-
expect(m).toParse();
|
|
206
|
-
});
|
|
207
|
-
test('table triple quote', () => {
|
|
208
|
-
const m = new test_translator_1.TestTranslator('source: n is bigquery.table("""n""")');
|
|
209
|
-
expect(m).toParse();
|
|
210
|
-
});
|
|
211
|
-
test('sql single quote', () => {
|
|
212
|
-
const m = new test_translator_1.TestTranslator("source: n is bigquery.sql('n')");
|
|
213
|
-
expect(m).toParse();
|
|
214
|
-
});
|
|
215
|
-
test('sql double quote', () => {
|
|
216
|
-
const m = new test_translator_1.TestTranslator('source: n is bigquery.sql("n")');
|
|
217
|
-
expect(m).toParse();
|
|
218
|
-
});
|
|
219
|
-
test('sql triple quote', () => {
|
|
220
|
-
const m = new test_translator_1.TestTranslator('source: n is bigquery.sql("""n""")');
|
|
221
|
-
expect(m).toParse();
|
|
222
|
-
});
|
|
223
|
-
test('import single quote', () => {
|
|
224
|
-
const m = new test_translator_1.TestTranslator("import 'a'");
|
|
225
|
-
expect(m).toParse();
|
|
226
|
-
});
|
|
227
|
-
test('import double quote', () => {
|
|
228
|
-
const m = new test_translator_1.TestTranslator('import "a"');
|
|
229
|
-
expect(m).toParse();
|
|
230
|
-
});
|
|
231
|
-
test('import triple quote', () => {
|
|
232
|
-
const m = new test_translator_1.TestTranslator('import """a"""');
|
|
233
|
-
expect(m).toParse();
|
|
234
|
-
});
|
|
235
|
-
test('literal single quote', () => {
|
|
236
|
-
const x = new test_translator_1.BetaExpression("'x'");
|
|
237
|
-
expect(x).toParse();
|
|
238
|
-
});
|
|
239
|
-
test('literal double quote', () => {
|
|
240
|
-
const x = new test_translator_1.BetaExpression('"x"');
|
|
241
|
-
expect(x).toParse();
|
|
242
|
-
});
|
|
243
|
-
test('literal triple quote', () => {
|
|
244
|
-
const x = new test_translator_1.BetaExpression('"""x"""');
|
|
245
|
-
expect(x).toParse();
|
|
246
|
-
});
|
|
247
|
-
test('Error for missing close in raw string', () => {
|
|
248
|
-
expect((0, test_translator_1.expr) `s'hello\n`).toLog((0, test_translator_1.errorMessage)('String cannot contain a new-line character'));
|
|
249
|
-
});
|
|
250
|
-
test('a string containing a tab', () => expect((0, test_translator_1.expr) `'\t'`).toParse());
|
|
251
|
-
});
|
|
252
|
-
describe('compound literals', () => {
|
|
253
|
-
test('simple record literal', () => {
|
|
254
|
-
expect('{answer is 42}').compilesTo('{answer:42}');
|
|
255
|
-
});
|
|
256
|
-
test('record literal with path', () => {
|
|
257
|
-
expect('{aninline.column}').compilesTo('{column:aninline.column}');
|
|
258
|
-
});
|
|
259
|
-
test('array of records with same schema', () => {
|
|
260
|
-
expect('[{name is "one", val is 1},{name is "two", val is 2}]').compilesTo('[{name:{"one"}, val:1}, {name:{"two"}, val:2}]');
|
|
261
|
-
});
|
|
262
|
-
test('array of records with head schema', () => {
|
|
263
|
-
expect('[{name is "one", val is 1},{"two", 2}]').compilesTo('[{name:{"one"}, val:1}, {name:{"two"}, val:2}]');
|
|
264
|
-
});
|
|
265
|
-
});
|
|
266
|
-
});
|
|
267
|
-
//# sourceMappingURL=literals.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import './parse-expects';
|