@malloydata/malloy 0.0.28-dev230314211807 → 0.0.28-dev230320190215
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/define-query.js +1 -1
- package/dist/lang/ast/elements/import-statement.js +2 -6
- package/dist/lang/ast/query-elements/existing-query.d.ts +1 -1
- package/dist/lang/ast/query-elements/existing-query.js +3 -3
- package/dist/lang/ast/query-elements/full-query.d.ts +1 -1
- package/dist/lang/ast/query-elements/full-query.js +5 -3
- package/dist/lang/ast/sources/query-source.js +1 -1
- package/dist/lang/parse-malloy.d.ts +6 -2
- package/dist/lang/parse-malloy.js +3 -2
- package/dist/lang/test/imports.spec.d.ts +1 -0
- package/dist/lang/test/imports.spec.js +160 -0
- package/dist/lang/test/parse-expects.d.ts +14 -0
- package/dist/lang/test/parse-expects.js +232 -0
- package/dist/lang/test/parse.spec.d.ts +1 -14
- package/dist/lang/test/parse.spec.js +83 -459
- package/dist/lang/test/test-translator.d.ts +21 -3
- package/dist/lang/test/test-translator.js +105 -7
- package/package.json +1 -1
|
@@ -28,127 +28,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
29
|
const model_1 = require("../../model");
|
|
30
30
|
const sql_block_1 = require("../../model/sql_block");
|
|
31
|
-
const static_space_1 = require("../ast/field-space/static-space");
|
|
32
|
-
const expression_def_1 = require("../ast/types/expression-def");
|
|
33
31
|
const test_translator_1 = require("./test-translator");
|
|
34
32
|
const isEqual_1 = __importDefault(require("lodash/isEqual"));
|
|
35
|
-
const util_1 = require("util");
|
|
36
33
|
const granular_result_1 = require("../ast/types/granular-result");
|
|
37
|
-
|
|
38
|
-
/*
|
|
39
|
-
* Thinking of these tests as just "do things parse", there should maybe
|
|
40
|
-
* be additional tests for, "does the correct code get generated", but
|
|
41
|
-
* the first step should be to write all the phrases in the grammar
|
|
42
|
-
* and make sure they parse to ast and the ast generates something
|
|
43
|
-
*/
|
|
44
|
-
class Testable extends test_translator_1.TestTranslator {
|
|
45
|
-
}
|
|
46
|
-
class BetaModel extends Testable {
|
|
47
|
-
constructor(testSrc) {
|
|
48
|
-
super(testSrc);
|
|
49
|
-
this.testSrc = testSrc;
|
|
50
|
-
}
|
|
51
|
-
compile() {
|
|
52
|
-
const compileTo = this.translate();
|
|
53
|
-
if (compileTo.translated && inspectCompile) {
|
|
54
|
-
console.log('MODEL: ', (0, test_translator_1.pretty)(compileTo.translated.modelDef));
|
|
55
|
-
console.log('QUERIES: ', (0, test_translator_1.pretty)(compileTo.translated.queryList));
|
|
56
|
-
}
|
|
57
|
-
// All the stuff to ask the ast for a translation is already in TestTranslator
|
|
58
|
-
}
|
|
59
|
-
unresolved() {
|
|
60
|
-
return this.importsAndTablesStep.step(this);
|
|
61
|
-
}
|
|
62
|
-
getSourceDef(srcName) {
|
|
63
|
-
const t = this.translate().translated;
|
|
64
|
-
if (t) {
|
|
65
|
-
const s = t.modelDef.contents[srcName];
|
|
66
|
-
if (s.type === 'struct') {
|
|
67
|
-
return s;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return undefined;
|
|
71
|
-
}
|
|
72
|
-
getQuery(queryName) {
|
|
73
|
-
const t = this.translate().translated;
|
|
74
|
-
if (t) {
|
|
75
|
-
const s = typeof queryName === 'string'
|
|
76
|
-
? t.modelDef.contents[queryName]
|
|
77
|
-
: t.queryList[queryName];
|
|
78
|
-
if ((s === null || s === void 0 ? void 0 : s.type) === 'query') {
|
|
79
|
-
return s;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return undefined;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
function checkForErrors(trans) {
|
|
86
|
-
if (trans.logger === undefined) {
|
|
87
|
-
throw new Error('JESTERY BROKEN, CANT FIND ERORR LOG');
|
|
88
|
-
}
|
|
89
|
-
if (trans.logger.hasErrors()) {
|
|
90
|
-
return {
|
|
91
|
-
message: () => `Translation Errors:\n${trans.prettyErrors()}`,
|
|
92
|
-
pass: false,
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
return {
|
|
96
|
-
message: () => 'Unexpected error free translation',
|
|
97
|
-
pass: true,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
function prettyNeeds(response) {
|
|
101
|
-
let needString = '';
|
|
102
|
-
if (response.tables) {
|
|
103
|
-
needString += 'Tables:\n';
|
|
104
|
-
response.tables.forEach(table => (needString += ` - ${table}`));
|
|
105
|
-
}
|
|
106
|
-
if (response.compileSQL) {
|
|
107
|
-
needString += `Compile SQL: ${response.compileSQL.name}`;
|
|
108
|
-
}
|
|
109
|
-
if (response.urls) {
|
|
110
|
-
needString += 'URLs:\n';
|
|
111
|
-
response.urls.forEach(url => (needString += ` - ${url}`));
|
|
112
|
-
}
|
|
113
|
-
return needString;
|
|
114
|
-
}
|
|
115
|
-
function checkForNeededs(trans) {
|
|
116
|
-
const response = trans.translateStep.step(trans);
|
|
117
|
-
if (!response.final) {
|
|
118
|
-
return {
|
|
119
|
-
message: () => `Translation is not complete, needs:\n${prettyNeeds(response)}`,
|
|
120
|
-
pass: false,
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
return {
|
|
124
|
-
message: () => 'Unexpected complete translation',
|
|
125
|
-
pass: true,
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
function highlightError(dl, txt) {
|
|
129
|
-
if (dl === undefined) {
|
|
130
|
-
return '~Location Undefined~';
|
|
131
|
-
}
|
|
132
|
-
const { start, end } = dl.range;
|
|
133
|
-
const output = [
|
|
134
|
-
`${start.line}:${start.character}-${end.line}:${end.character}`,
|
|
135
|
-
];
|
|
136
|
-
let errStart = start.character;
|
|
137
|
-
const doc = txt.split('\n');
|
|
138
|
-
for (let line = start.line; line <= end.line; line += 1) {
|
|
139
|
-
const lineText = doc[line];
|
|
140
|
-
const lineStr = ` ${line}`.slice(-5);
|
|
141
|
-
output.push(`${lineStr}| ${lineText}`);
|
|
142
|
-
const upToError = ' | ' + ' '.repeat(errStart);
|
|
143
|
-
let errLen = end.character - errStart;
|
|
144
|
-
if (line < end.line) {
|
|
145
|
-
errLen = lineText.length - errStart;
|
|
146
|
-
errStart = 0;
|
|
147
|
-
}
|
|
148
|
-
output.push(upToError + '-'.repeat(errLen));
|
|
149
|
-
}
|
|
150
|
-
return output.join('\n');
|
|
151
|
-
}
|
|
34
|
+
require("./parse-expects");
|
|
152
35
|
function unlocatedStructDef(sd) {
|
|
153
36
|
const ret = { ...sd };
|
|
154
37
|
ret.fields = sd.fields.map(f => {
|
|
@@ -159,187 +42,15 @@ function unlocatedStructDef(sd) {
|
|
|
159
42
|
delete ret.location;
|
|
160
43
|
return ret;
|
|
161
44
|
}
|
|
162
|
-
expect.extend({
|
|
163
|
-
toCompile: function (s) {
|
|
164
|
-
const x = new BetaModel(s);
|
|
165
|
-
x.compile();
|
|
166
|
-
const errorCheck = checkForErrors(x);
|
|
167
|
-
if (!errorCheck.pass) {
|
|
168
|
-
return errorCheck;
|
|
169
|
-
}
|
|
170
|
-
x.translate();
|
|
171
|
-
return checkForNeededs(x);
|
|
172
|
-
},
|
|
173
|
-
modelParsed: function (x) {
|
|
174
|
-
x.compile();
|
|
175
|
-
return checkForErrors(x);
|
|
176
|
-
},
|
|
177
|
-
modelCompiled: function (x) {
|
|
178
|
-
x.compile();
|
|
179
|
-
const errorCheck = checkForErrors(x);
|
|
180
|
-
if (!errorCheck.pass) {
|
|
181
|
-
return errorCheck;
|
|
182
|
-
}
|
|
183
|
-
x.translate();
|
|
184
|
-
return checkForNeededs(x);
|
|
185
|
-
},
|
|
186
|
-
toBeErrorless: function (trans) {
|
|
187
|
-
return checkForErrors(trans);
|
|
188
|
-
},
|
|
189
|
-
toReturnType: function (functionCall, returnType) {
|
|
190
|
-
const exprModel = new BetaModel(`explore: x is a { dimension: d is ${functionCall} }`);
|
|
191
|
-
expect(exprModel).modelCompiled();
|
|
192
|
-
const x = exprModel.getSourceDef('x');
|
|
193
|
-
expect(x).toBeDefined();
|
|
194
|
-
if (x) {
|
|
195
|
-
const d = x.fields.find(f => f.name === 'd');
|
|
196
|
-
expect(d === null || d === void 0 ? void 0 : d.type).toBe(returnType);
|
|
197
|
-
}
|
|
198
|
-
return {
|
|
199
|
-
pass: true,
|
|
200
|
-
message: () => '',
|
|
201
|
-
};
|
|
202
|
-
},
|
|
203
|
-
compileToFailWith: function (s, ...msgs) {
|
|
204
|
-
var _a;
|
|
205
|
-
let emsg = 'Compile Error expectation not met\nExpected error';
|
|
206
|
-
let mSrc;
|
|
207
|
-
const qmsgs = msgs.map(s => `error '${s}'`);
|
|
208
|
-
if (msgs.length === 1) {
|
|
209
|
-
emsg += ` ${qmsgs[0]}`;
|
|
210
|
-
}
|
|
211
|
-
else {
|
|
212
|
-
emsg += `s [\n${qmsgs.join('\n')}\n]`;
|
|
213
|
-
}
|
|
214
|
-
let m;
|
|
215
|
-
let src;
|
|
216
|
-
if (s instanceof BetaModel) {
|
|
217
|
-
m = s;
|
|
218
|
-
src = m.testSrc;
|
|
219
|
-
}
|
|
220
|
-
else {
|
|
221
|
-
if (typeof s === 'string') {
|
|
222
|
-
src = s;
|
|
223
|
-
}
|
|
224
|
-
else {
|
|
225
|
-
src = s.code;
|
|
226
|
-
mSrc = s;
|
|
227
|
-
}
|
|
228
|
-
m = new BetaModel(src);
|
|
229
|
-
}
|
|
230
|
-
emsg += `\nSource:\n${src}`;
|
|
231
|
-
const t = m.translate();
|
|
232
|
-
if (t.translated) {
|
|
233
|
-
return { pass: false, message: () => emsg };
|
|
234
|
-
}
|
|
235
|
-
else if (t.errors === undefined) {
|
|
236
|
-
return {
|
|
237
|
-
pass: false,
|
|
238
|
-
message: () => 'TEST ERROR, not all objects resolved in source\n' +
|
|
239
|
-
(0, test_translator_1.pretty)(t) +
|
|
240
|
-
'\n' +
|
|
241
|
-
emsg,
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
const explain = [];
|
|
246
|
-
const errList = m.errors().errors;
|
|
247
|
-
let i;
|
|
248
|
-
for (i = 0; i < msgs.length && errList[i]; i += 1) {
|
|
249
|
-
const msg = msgs[i];
|
|
250
|
-
const err = errList[i];
|
|
251
|
-
if (msg !== err.message) {
|
|
252
|
-
explain.push(`Expected: ${msg}\nGot: ${err.message}`);
|
|
253
|
-
}
|
|
254
|
-
else {
|
|
255
|
-
if (mSrc === null || mSrc === void 0 ? void 0 : mSrc.locations[i]) {
|
|
256
|
-
const have = (_a = err.at) === null || _a === void 0 ? void 0 : _a.range;
|
|
257
|
-
const want = mSrc.locations[i].range;
|
|
258
|
-
if (!this.equals(have, want)) {
|
|
259
|
-
explain.push(`Expected '${msg}' at location: ${(0, util_1.inspect)(want)}\n` +
|
|
260
|
-
`Actual location: ${(0, util_1.inspect)(have)}`);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
if (i !== msgs.length) {
|
|
266
|
-
explain.push(...msgs.slice(i).map(m => `Missing: ${m}`));
|
|
267
|
-
}
|
|
268
|
-
if (i !== errList.length) {
|
|
269
|
-
explain.push(...errList.slice(i).map(m => `Unexpected Error: ${m.message}`));
|
|
270
|
-
}
|
|
271
|
-
if (explain.length === 0) {
|
|
272
|
-
return {
|
|
273
|
-
pass: true,
|
|
274
|
-
message: () => `All expected errors found: ${(0, test_translator_1.pretty)(msgs)}`,
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
return {
|
|
278
|
-
pass: false,
|
|
279
|
-
message: () => `Compiler did not generated expected errors\n${explain.join('\n')}`,
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
},
|
|
283
|
-
isLocationIn: function (checkAt, at, text) {
|
|
284
|
-
if (this.equals(at, checkAt)) {
|
|
285
|
-
return {
|
|
286
|
-
pass: true,
|
|
287
|
-
message: () => 'Locations match',
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
const errMsg = 'Locations do not match\n' +
|
|
291
|
-
`Expected: ${highlightError(at, text)}\n` +
|
|
292
|
-
`Received: ${highlightError(checkAt, text)}\n`;
|
|
293
|
-
return {
|
|
294
|
-
pass: false,
|
|
295
|
-
message: () => errMsg,
|
|
296
|
-
};
|
|
297
|
-
},
|
|
298
|
-
});
|
|
299
|
-
class BetaExpression extends Testable {
|
|
300
|
-
constructor(src) {
|
|
301
|
-
super(src, 'justExpr');
|
|
302
|
-
}
|
|
303
|
-
compile() {
|
|
304
|
-
const exprAst = this.ast();
|
|
305
|
-
if (exprAst instanceof expression_def_1.ExpressionDef) {
|
|
306
|
-
const aStruct = this.internalModel.contents['ab'];
|
|
307
|
-
if (aStruct.type === 'struct') {
|
|
308
|
-
const tstFS = new static_space_1.StaticSpace(aStruct);
|
|
309
|
-
const exprDef = exprAst.getExpression(tstFS);
|
|
310
|
-
this.compiled = exprDef;
|
|
311
|
-
if (inspectCompile) {
|
|
312
|
-
console.log('EXPRESSION: ', (0, test_translator_1.pretty)(exprDef));
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
else {
|
|
316
|
-
throw new Error("Can't get simple namespace for expression tests");
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
else if (this.logger.hasErrors()) {
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
const whatIsIt = (exprAst === null || exprAst === void 0 ? void 0 : exprAst.toString()) || 'NO AST GENERATED';
|
|
324
|
-
throw new Error(`Not an expression: ${whatIsIt}`);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
generated() {
|
|
328
|
-
if (!this.compiled) {
|
|
329
|
-
throw new Error('Must compile expression before fetching generated code');
|
|
330
|
-
}
|
|
331
|
-
return this.compiled;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
45
|
function exprOK(s) {
|
|
335
46
|
return () => {
|
|
336
|
-
expect(new BetaExpression(s)).modelParsed();
|
|
47
|
+
expect(new test_translator_1.BetaExpression(s)).modelParsed();
|
|
337
48
|
return undefined;
|
|
338
49
|
};
|
|
339
50
|
}
|
|
340
51
|
function modelOK(s) {
|
|
341
52
|
return () => {
|
|
342
|
-
const m = new
|
|
53
|
+
const m = new test_translator_1.TestTranslator(s);
|
|
343
54
|
expect(m).modelCompiled();
|
|
344
55
|
return undefined;
|
|
345
56
|
};
|
|
@@ -348,7 +59,7 @@ function badModel(s, msg) {
|
|
|
348
59
|
return () => {
|
|
349
60
|
const src = typeof s === 'string' ? s : s.code;
|
|
350
61
|
const emsg = `Error expectation not met\nExpected error: '${msg}'\nSource:\n${src}`;
|
|
351
|
-
const m = new
|
|
62
|
+
const m = new test_translator_1.TestTranslator(src);
|
|
352
63
|
const t = m.translate();
|
|
353
64
|
if (t.translated) {
|
|
354
65
|
fail(emsg);
|
|
@@ -382,7 +93,7 @@ describe('model statements', () => {
|
|
|
382
93
|
test('explore query', modelOK('explore: testA is from(a->{group_by: astr})'));
|
|
383
94
|
test('refine explore', modelOK('explore: aa is a { dimension: a is astr }'));
|
|
384
95
|
test('source refinement preserves original', () => {
|
|
385
|
-
const x = new
|
|
96
|
+
const x = new test_translator_1.TestTranslator('source: na is a + { dimension: one is 1 }');
|
|
386
97
|
expect(x).modelCompiled();
|
|
387
98
|
const a = x.getSourceDef('a');
|
|
388
99
|
if (a) {
|
|
@@ -427,7 +138,7 @@ describe('model statements', () => {
|
|
|
427
138
|
query: -> a_by_str { aggregate: str_count is count() }
|
|
428
139
|
`));
|
|
429
140
|
test('query refinement preserves original', () => {
|
|
430
|
-
const x = new
|
|
141
|
+
const x = new test_translator_1.TestTranslator(`
|
|
431
142
|
query: q is a -> { aggregate: acount is count() }
|
|
432
143
|
query: nq is -> q + { group_by: astr }
|
|
433
144
|
`);
|
|
@@ -440,7 +151,7 @@ describe('model statements', () => {
|
|
|
440
151
|
}
|
|
441
152
|
});
|
|
442
153
|
test('query composition preserves original', () => {
|
|
443
|
-
const x = new
|
|
154
|
+
const x = new test_translator_1.TestTranslator(`
|
|
444
155
|
query: q is ab -> { aggregate: acount }
|
|
445
156
|
query: nq is -> q -> { project: * }
|
|
446
157
|
`);
|
|
@@ -516,93 +227,6 @@ describe('model statements', () => {
|
|
|
516
227
|
}
|
|
517
228
|
`));
|
|
518
229
|
});
|
|
519
|
-
describe('import:', () => {
|
|
520
|
-
test('simple import', () => {
|
|
521
|
-
const docParse = new BetaModel('import "child"');
|
|
522
|
-
const xr = docParse.unresolved();
|
|
523
|
-
expect(docParse).toBeErrorless();
|
|
524
|
-
expect(xr).toEqual({ urls: ['internal://test/langtests/child'] });
|
|
525
|
-
docParse.update({
|
|
526
|
-
urls: { 'internal://test/langtests/child': 'explore: aa is a' },
|
|
527
|
-
});
|
|
528
|
-
const yr = docParse.unresolved();
|
|
529
|
-
expect(yr).toBeNull();
|
|
530
|
-
});
|
|
531
|
-
test('missing import', () => {
|
|
532
|
-
const docParse = new BetaModel('import "child"');
|
|
533
|
-
const xr = docParse.unresolved();
|
|
534
|
-
expect(docParse).toBeErrorless();
|
|
535
|
-
expect(xr).toEqual({ urls: ['internal://test/langtests/child'] });
|
|
536
|
-
const reportedError = 'ENOWAY: No way to find your child';
|
|
537
|
-
docParse.update({
|
|
538
|
-
errors: {
|
|
539
|
-
urls: { 'internal://test/langtests/child': reportedError },
|
|
540
|
-
},
|
|
541
|
-
});
|
|
542
|
-
docParse.translate();
|
|
543
|
-
expect(docParse).not.toBeErrorless();
|
|
544
|
-
expect(docParse.prettyErrors()).toContain(reportedError);
|
|
545
|
-
});
|
|
546
|
-
test('chained imports', () => {
|
|
547
|
-
const docParse = new BetaModel('import "child"');
|
|
548
|
-
docParse.update({
|
|
549
|
-
urls: { 'internal://test/langtests/child': 'import "grandChild"' },
|
|
550
|
-
});
|
|
551
|
-
const xr = docParse.unresolved();
|
|
552
|
-
expect(docParse).toBeErrorless();
|
|
553
|
-
expect(xr).toEqual({ urls: ['internal://test/langtests/grandChild'] });
|
|
554
|
-
});
|
|
555
|
-
test('relative imports', () => {
|
|
556
|
-
const docParse = new BetaModel('import "../parent.malloy"');
|
|
557
|
-
expect(docParse).modelParsed();
|
|
558
|
-
const xr = docParse.unresolved();
|
|
559
|
-
expect(xr).toEqual({ urls: ['internal://test/parent.malloy'] });
|
|
560
|
-
docParse.update({
|
|
561
|
-
urls: {
|
|
562
|
-
'internal://test/parent.malloy': "source: aa is table('aTable')",
|
|
563
|
-
},
|
|
564
|
-
});
|
|
565
|
-
expect(docParse).modelCompiled();
|
|
566
|
-
});
|
|
567
|
-
test('relative imports with errors', () => {
|
|
568
|
-
const docParse = new BetaModel('import "../parent.malloy"');
|
|
569
|
-
expect(docParse).modelParsed();
|
|
570
|
-
const xr = docParse.unresolved();
|
|
571
|
-
expect(xr).toEqual({ urls: ['internal://test/parent.malloy'] });
|
|
572
|
-
docParse.update({
|
|
573
|
-
urls: {
|
|
574
|
-
'internal://test/parent.malloy': `
|
|
575
|
-
source: aa is table('aTable') {
|
|
576
|
-
dimension: astr is 'not legal beause astr exists'
|
|
577
|
-
}`,
|
|
578
|
-
},
|
|
579
|
-
});
|
|
580
|
-
expect(docParse).compileToFailWith("Cannot redefine 'astr'");
|
|
581
|
-
});
|
|
582
|
-
test('source references expanded when not exported', () => {
|
|
583
|
-
const srcFiles = {
|
|
584
|
-
'internal://test/langtests/middle': `
|
|
585
|
-
import "bottom"
|
|
586
|
-
source: midSrc is from(bottomSrc -> { group_by: astr })
|
|
587
|
-
`,
|
|
588
|
-
'internal://test/langtests/bottom': "source: bottomSrc is table('aTable')",
|
|
589
|
-
};
|
|
590
|
-
const fullModel = new BetaModel(`
|
|
591
|
-
import "middle"
|
|
592
|
-
`);
|
|
593
|
-
fullModel.update({ urls: srcFiles });
|
|
594
|
-
expect(fullModel).modelCompiled();
|
|
595
|
-
const ms = fullModel.getSourceDef('midSrc');
|
|
596
|
-
expect(ms).toBeDefined();
|
|
597
|
-
if (ms) {
|
|
598
|
-
expect(ms.structSource.type).toBe('query');
|
|
599
|
-
if (ms.structSource.type === 'query') {
|
|
600
|
-
const qs = ms.structSource.query.structRef;
|
|
601
|
-
expect(typeof qs).not.toBe('string');
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
});
|
|
605
|
-
});
|
|
606
230
|
});
|
|
607
231
|
describe('explore properties', () => {
|
|
608
232
|
test('single dimension', modelOK('explore: aa is a { dimension: x is 1 }'));
|
|
@@ -675,7 +299,7 @@ describe('explore properties', () => {
|
|
|
675
299
|
test('primary_key', modelOK('explore: c is a { primary_key: ai }'));
|
|
676
300
|
test('rename', modelOK('explore: c is a { rename: nn is ai }'));
|
|
677
301
|
test('accept single', () => {
|
|
678
|
-
const onlyAstr = new
|
|
302
|
+
const onlyAstr = new test_translator_1.TestTranslator('explore: c is a { accept: astr }');
|
|
679
303
|
expect(onlyAstr).modelCompiled();
|
|
680
304
|
const c = onlyAstr.getSourceDef('c');
|
|
681
305
|
if (c) {
|
|
@@ -684,7 +308,7 @@ describe('explore properties', () => {
|
|
|
684
308
|
});
|
|
685
309
|
test('accept multi', modelOK('explore: c is a { accept: astr, af }'));
|
|
686
310
|
test('except single', () => {
|
|
687
|
-
const noAstr = new
|
|
311
|
+
const noAstr = new test_translator_1.TestTranslator('explore: c is a { except: astr }');
|
|
688
312
|
expect(noAstr).modelCompiled();
|
|
689
313
|
const c = noAstr.getSourceDef('c');
|
|
690
314
|
if (c) {
|
|
@@ -740,7 +364,7 @@ describe('qops', () => {
|
|
|
740
364
|
test('index unique on path', modelOK('query:ab->{index: b.astr, ab.astr}'));
|
|
741
365
|
test('index join.*', modelOK('query:ab->{index: ab.*}'));
|
|
742
366
|
test('index multiple', () => {
|
|
743
|
-
const model = new
|
|
367
|
+
const model = new test_translator_1.TestTranslator('query:a->{index: af, astr}');
|
|
744
368
|
expect(model).modelCompiled();
|
|
745
369
|
const q = model.getQuery(0);
|
|
746
370
|
expect(q).toBeDefined();
|
|
@@ -751,7 +375,7 @@ describe('qops', () => {
|
|
|
751
375
|
}
|
|
752
376
|
});
|
|
753
377
|
test('index star', () => {
|
|
754
|
-
const model = new
|
|
378
|
+
const model = new test_translator_1.TestTranslator('query:a->{index: *, astr}');
|
|
755
379
|
expect(model).modelCompiled();
|
|
756
380
|
const q = model.getQuery(0);
|
|
757
381
|
expect(q).toBeDefined();
|
|
@@ -765,7 +389,7 @@ describe('qops', () => {
|
|
|
765
389
|
test('index sampled', modelOK('query:a->{index: *; sample: true}'));
|
|
766
390
|
test('index unsampled', modelOK('query:a->{index: *; sample: false}'));
|
|
767
391
|
test('index sample-percent', () => {
|
|
768
|
-
const model = new
|
|
392
|
+
const model = new test_translator_1.TestTranslator('query:a->{index: *; sample: 42%}');
|
|
769
393
|
expect(model).modelCompiled();
|
|
770
394
|
const q = model.getQuery(0);
|
|
771
395
|
expect(q).toBeDefined();
|
|
@@ -798,7 +422,7 @@ describe('qops', () => {
|
|
|
798
422
|
test('compound aggregate still works', modelOK('query:ab->{ aggregate: thing is acount > 10 and acount < 100 }'));
|
|
799
423
|
test('where multiple', modelOK("query:a->{ group_by: astr; where: af > 10,astr~'a%' }"));
|
|
800
424
|
test('filters preserve source formatting in code:', () => {
|
|
801
|
-
const model = new
|
|
425
|
+
const model = new test_translator_1.TestTranslator("source: notb is a + { where: astr != 'b' }");
|
|
802
426
|
expect(model).modelCompiled();
|
|
803
427
|
const notb = model.getSourceDef('notb');
|
|
804
428
|
expect(notb).toBeDefined();
|
|
@@ -811,7 +435,7 @@ describe('qops', () => {
|
|
|
811
435
|
}
|
|
812
436
|
});
|
|
813
437
|
test('field expressions preserve source formatting in code:', () => {
|
|
814
|
-
const model = new
|
|
438
|
+
const model = new test_translator_1.TestTranslator('source: notb is a + { dimension: d is 1 + 2 }');
|
|
815
439
|
expect(model).modelCompiled();
|
|
816
440
|
const notb = model.getSourceDef('notb');
|
|
817
441
|
expect(notb).toBeDefined();
|
|
@@ -840,7 +464,7 @@ describe('qops', () => {
|
|
|
840
464
|
`));
|
|
841
465
|
test('nest ref', modelOK('query: ab->{group_by: ai; nest: aturtle}'));
|
|
842
466
|
test('refine query with extended source', () => {
|
|
843
|
-
const m = new
|
|
467
|
+
const m = new test_translator_1.TestTranslator(`
|
|
844
468
|
source: nab is ab {
|
|
845
469
|
query: xturtle is aturtle + {
|
|
846
470
|
declare: aratio is ai / acount
|
|
@@ -866,7 +490,7 @@ describe('qops', () => {
|
|
|
866
490
|
}
|
|
867
491
|
});
|
|
868
492
|
test('refine query source with field', () => {
|
|
869
|
-
const m = new
|
|
493
|
+
const m = new test_translator_1.TestTranslator(`
|
|
870
494
|
query: ab -> aturtle + {
|
|
871
495
|
declare: aratio is ai / acount
|
|
872
496
|
aggregate: aratio
|
|
@@ -890,7 +514,7 @@ describe('qops', () => {
|
|
|
890
514
|
}
|
|
891
515
|
});
|
|
892
516
|
test('refine query source with join', () => {
|
|
893
|
-
const m = new
|
|
517
|
+
const m = new test_translator_1.TestTranslator(`
|
|
894
518
|
query: ab -> aturtle + {
|
|
895
519
|
join_one: bb is b on bb.astr = astr
|
|
896
520
|
group_by: foo is bb.astr
|
|
@@ -977,7 +601,7 @@ describe('literals', () => {
|
|
|
977
601
|
],
|
|
978
602
|
];
|
|
979
603
|
test.each(literalTimes)('%s', (expr, timeType, timeframe, result) => {
|
|
980
|
-
const exprModel = new BetaExpression(expr);
|
|
604
|
+
const exprModel = new test_translator_1.BetaExpression(expr);
|
|
981
605
|
expect(exprModel).modelCompiled();
|
|
982
606
|
const ir = exprModel.generated();
|
|
983
607
|
expect(ir.dataType).toEqual(timeType);
|
|
@@ -1001,7 +625,7 @@ describe('literals', () => {
|
|
|
1001
625
|
['@1960-06-30 00:00', undefined],
|
|
1002
626
|
];
|
|
1003
627
|
test.each(morphicLiterals)('morphic value for %s is %s', (expr, morphic) => {
|
|
1004
|
-
const exprModel = new BetaExpression(expr);
|
|
628
|
+
const exprModel = new test_translator_1.BetaExpression(expr);
|
|
1005
629
|
expect(exprModel).modelCompiled();
|
|
1006
630
|
const ir = exprModel.generated();
|
|
1007
631
|
const morphTo = ir.morphic && ir.morphic['timestamp'];
|
|
@@ -1167,7 +791,7 @@ describe('expressions', () => {
|
|
|
1167
791
|
test('paren and applied div', () => {
|
|
1168
792
|
var _a, _b;
|
|
1169
793
|
const modelSrc = 'query: z is a -> { group_by: x is 1+(3/4) }';
|
|
1170
|
-
const m = new
|
|
794
|
+
const m = new test_translator_1.TestTranslator(modelSrc);
|
|
1171
795
|
expect(m).modelCompiled();
|
|
1172
796
|
const queryDef = (_b = (_a = m.translate()) === null || _a === void 0 ? void 0 : _a.translated) === null || _b === void 0 ? void 0 : _b.modelDef.contents['z'];
|
|
1173
797
|
expect(queryDef).toBeDefined();
|
|
@@ -1195,33 +819,33 @@ describe('expressions', () => {
|
|
|
1195
819
|
});
|
|
1196
820
|
describe('unspported fields in schema', () => {
|
|
1197
821
|
test('unsupported reference in result allowed', () => {
|
|
1198
|
-
const uModel = new
|
|
822
|
+
const uModel = new test_translator_1.TestTranslator('query: a->{ group_by: aun }');
|
|
1199
823
|
expect(uModel).modelCompiled();
|
|
1200
824
|
});
|
|
1201
825
|
test('unsupported reference can be compared to NULL', () => {
|
|
1202
|
-
const uModel = new
|
|
826
|
+
const uModel = new test_translator_1.TestTranslator('query: a->{ where: aun != NULL; project: * }');
|
|
1203
827
|
expect(uModel).modelCompiled();
|
|
1204
828
|
});
|
|
1205
829
|
test('flag unsupported equality', () => {
|
|
1206
830
|
// because we don't know if the two unsupported types are comparable
|
|
1207
|
-
const uModel = new
|
|
831
|
+
const uModel = new test_translator_1.TestTranslator('query: ab->{ where: aun = b.aun project: * }');
|
|
1208
832
|
expect(uModel).compileToFailWith('Unsupported type not allowed in expression');
|
|
1209
833
|
});
|
|
1210
834
|
test('flag unsupported compare', () => {
|
|
1211
835
|
// because we don't know if the two unsupported types are comparable
|
|
1212
|
-
const uModel = new
|
|
836
|
+
const uModel = new test_translator_1.TestTranslator('query: ab->{ where: aun > b.aun project: * }');
|
|
1213
837
|
expect(uModel).compileToFailWith('Unsupported type not allowed in expression');
|
|
1214
838
|
});
|
|
1215
839
|
test('allow unsupported equality when raw types match', () => {
|
|
1216
|
-
const uModel = new
|
|
840
|
+
const uModel = new test_translator_1.TestTranslator('query: ab->{ where: aweird = b.aweird project: * }');
|
|
1217
841
|
expect(uModel).modelCompiled();
|
|
1218
842
|
});
|
|
1219
843
|
test('flag not applied to unsupported', () => {
|
|
1220
|
-
const uModel = new
|
|
844
|
+
const uModel = new test_translator_1.TestTranslator('source: x is a { dimension: notUn is not aun }');
|
|
1221
845
|
expect(uModel).compileToFailWith("'not' Can't use type unsupported");
|
|
1222
846
|
});
|
|
1223
847
|
test('allow unsupported to be cast', () => {
|
|
1224
|
-
const uModel = new
|
|
848
|
+
const uModel = new test_translator_1.TestTranslator('source: x is a { dimension: notUn is aun::string }');
|
|
1225
849
|
expect(uModel).modelCompiled();
|
|
1226
850
|
});
|
|
1227
851
|
});
|
|
@@ -1247,7 +871,7 @@ describe('sql:', () => {
|
|
|
1247
871
|
}
|
|
1248
872
|
test('definition', () => {
|
|
1249
873
|
const selStmt = 'SELECT * FROM aTable';
|
|
1250
|
-
const model = new
|
|
874
|
+
const model = new test_translator_1.TestTranslator(`
|
|
1251
875
|
sql: users IS {
|
|
1252
876
|
select: """${selStmt}"""
|
|
1253
877
|
connection: "aConnection"
|
|
@@ -1272,7 +896,7 @@ describe('sql:', () => {
|
|
|
1272
896
|
});
|
|
1273
897
|
test('source from sql', () => {
|
|
1274
898
|
const selStmt = 'SELECT * FROM aTable';
|
|
1275
|
-
const model = new
|
|
899
|
+
const model = new test_translator_1.TestTranslator(`
|
|
1276
900
|
sql: users IS { select: """${selStmt}""" }
|
|
1277
901
|
source: malloyUsers is from_sql(users) { primary_key: ai }
|
|
1278
902
|
`);
|
|
@@ -1295,7 +919,7 @@ describe('sql:', () => {
|
|
|
1295
919
|
sql: users IS { select: """${selStmt}""" }
|
|
1296
920
|
source: malloyUsers is from_sql(users) { primary_key: ai }
|
|
1297
921
|
`;
|
|
1298
|
-
const model = new
|
|
922
|
+
const model = new test_translator_1.TestTranslator(`
|
|
1299
923
|
import "createModel.malloy"
|
|
1300
924
|
source: importUsers is malloyUsers
|
|
1301
925
|
`);
|
|
@@ -1309,7 +933,7 @@ describe('sql:', () => {
|
|
|
1309
933
|
expect(model).modelCompiled();
|
|
1310
934
|
});
|
|
1311
935
|
it('turducken', () => {
|
|
1312
|
-
const m = new
|
|
936
|
+
const m = new test_translator_1.TestTranslator(`
|
|
1313
937
|
sql: someSql is {
|
|
1314
938
|
select: """SELECT * FROM %{ a -> { group_by: astr } }% WHERE 1=1"""
|
|
1315
939
|
}
|
|
@@ -1333,7 +957,7 @@ describe('sql:', () => {
|
|
|
1333
957
|
sql: someSql is { select: """${selStmt}""" }
|
|
1334
958
|
source: newaa is newa
|
|
1335
959
|
`;
|
|
1336
|
-
const model = new
|
|
960
|
+
const model = new test_translator_1.TestTranslator(shouldBeOK);
|
|
1337
961
|
expect(model).modelParsed();
|
|
1338
962
|
const needReq = model.translate();
|
|
1339
963
|
const needs = needReq === null || needReq === void 0 ? void 0 : needReq.compileSQL;
|
|
@@ -1383,7 +1007,7 @@ describe('error handling', () => {
|
|
|
1383
1007
|
test("refine can't change query type", badModel('query: ab -> aturtle { project: astr }', 'project: not legal in grouping query'));
|
|
1384
1008
|
test('undefined field ref in query', badModel('query: ab -> { aggregate: xyzzy }', "'xyzzy' is not defined"));
|
|
1385
1009
|
// test("queries with anonymous expressions", () => {
|
|
1386
|
-
// const m = new
|
|
1010
|
+
// const m = new TestTranslator("query: a->{\n group_by: a+1\n}");
|
|
1387
1011
|
// expect(m).not.modelParsed();
|
|
1388
1012
|
// const errList = m.errors().errors;
|
|
1389
1013
|
// const firstError = errList[0];
|
|
@@ -1433,7 +1057,7 @@ describe('error handling', () => {
|
|
|
1433
1057
|
expect('}%').compileToFailWith("extraneous input '}%' expecting {<EOF>, EXPLORE, QUERY, SOURCE, SQL, IMPORT, ';'}");
|
|
1434
1058
|
});
|
|
1435
1059
|
test('bad sql in sql block', () => {
|
|
1436
|
-
const badModel = new
|
|
1060
|
+
const badModel = new test_translator_1.TestTranslator('sql: { select: """)""" }');
|
|
1437
1061
|
expect(badModel).modelParsed();
|
|
1438
1062
|
const needSchema = badModel.translate();
|
|
1439
1063
|
expect(needSchema.compileSQL).toBeDefined();
|
|
@@ -1474,19 +1098,19 @@ function getSelectOneStruct(sqlBlock) {
|
|
|
1474
1098
|
describe('source locations', () => {
|
|
1475
1099
|
test('renamed explore location', () => {
|
|
1476
1100
|
const source = (0, test_translator_1.markSource) `explore: ${'na is a'}`;
|
|
1477
|
-
const m = new
|
|
1101
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1478
1102
|
expect(m).modelParsed();
|
|
1479
1103
|
expect((0, test_translator_1.getExplore)(m.modelDef, 'na').location).toMatchObject(source.locations[0]);
|
|
1480
1104
|
});
|
|
1481
1105
|
test('refined explore location', () => {
|
|
1482
1106
|
const source = (0, test_translator_1.markSource) `explore: ${'na is a {}'}`;
|
|
1483
|
-
const m = new
|
|
1107
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1484
1108
|
expect(m).modelParsed();
|
|
1485
1109
|
expect((0, test_translator_1.getExplore)(m.modelDef, 'na').location).toMatchObject(source.locations[0]);
|
|
1486
1110
|
});
|
|
1487
1111
|
test('location of defined dimension', () => {
|
|
1488
1112
|
const source = (0, test_translator_1.markSource) `explore: na is a { dimension: ${'x is 1'} }`;
|
|
1489
|
-
const m = new
|
|
1113
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1490
1114
|
expect(m).modelCompiled();
|
|
1491
1115
|
const na = (0, test_translator_1.getExplore)(m.modelDef, 'na');
|
|
1492
1116
|
const x = (0, test_translator_1.getField)(na, 'x');
|
|
@@ -1494,7 +1118,7 @@ describe('source locations', () => {
|
|
|
1494
1118
|
});
|
|
1495
1119
|
test('location of defined measure', () => {
|
|
1496
1120
|
const source = (0, test_translator_1.markSource) `explore: na is a { measure: ${'x is count()'} }`;
|
|
1497
|
-
const m = new
|
|
1121
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1498
1122
|
expect(m).modelCompiled();
|
|
1499
1123
|
const na = (0, test_translator_1.getExplore)(m.modelDef, 'na');
|
|
1500
1124
|
const x = (0, test_translator_1.getField)(na, 'x');
|
|
@@ -1502,7 +1126,7 @@ describe('source locations', () => {
|
|
|
1502
1126
|
});
|
|
1503
1127
|
test('location of defined query', () => {
|
|
1504
1128
|
const source = (0, test_translator_1.markSource) `explore: na is a { query: ${'x is { group_by: y is 1 }'} }`;
|
|
1505
|
-
const m = new
|
|
1129
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1506
1130
|
expect(m).modelCompiled();
|
|
1507
1131
|
const na = (0, test_translator_1.getExplore)(m.modelDef, 'na');
|
|
1508
1132
|
const x = (0, test_translator_1.getField)(na, 'x');
|
|
@@ -1515,7 +1139,7 @@ describe('source locations', () => {
|
|
|
1515
1139
|
group_by: ${'y is 1'}
|
|
1516
1140
|
}
|
|
1517
1141
|
}`;
|
|
1518
|
-
const m = new
|
|
1142
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1519
1143
|
expect(m).modelCompiled();
|
|
1520
1144
|
const na = (0, test_translator_1.getExplore)(m.modelDef, 'na');
|
|
1521
1145
|
const x = (0, test_translator_1.getQueryField)(na, 'x');
|
|
@@ -1530,7 +1154,7 @@ describe('source locations', () => {
|
|
|
1530
1154
|
group_by: ${'z is y { where: true }'}
|
|
1531
1155
|
}
|
|
1532
1156
|
}`;
|
|
1533
|
-
const m = new
|
|
1157
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1534
1158
|
expect(m).modelCompiled();
|
|
1535
1159
|
const na = (0, test_translator_1.getExplore)(m.modelDef, 'na');
|
|
1536
1160
|
const x = (0, test_translator_1.getQueryField)(na, 'x');
|
|
@@ -1539,7 +1163,7 @@ describe('source locations', () => {
|
|
|
1539
1163
|
});
|
|
1540
1164
|
test('location of field inherited from table', () => {
|
|
1541
1165
|
const source = (0, test_translator_1.markSource) `explore: na is ${"table('aTable')"}`;
|
|
1542
|
-
const m = new
|
|
1166
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1543
1167
|
expect(m).modelCompiled();
|
|
1544
1168
|
const na = (0, test_translator_1.getExplore)(m.modelDef, 'na');
|
|
1545
1169
|
const abool = (0, test_translator_1.getField)(na, 'abool');
|
|
@@ -1550,7 +1174,7 @@ describe('source locations', () => {
|
|
|
1550
1174
|
sql: s is { select: ${'"""SELECT 1 as one """'} }
|
|
1551
1175
|
explore: na is from_sql(s)
|
|
1552
1176
|
`;
|
|
1553
|
-
const m = new
|
|
1177
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1554
1178
|
expect(m).modelParsed();
|
|
1555
1179
|
const compileSql = m.translate().compileSQL;
|
|
1556
1180
|
expect(compileSql).toBeDefined();
|
|
@@ -1574,7 +1198,7 @@ describe('source locations', () => {
|
|
|
1574
1198
|
}
|
|
1575
1199
|
)
|
|
1576
1200
|
`;
|
|
1577
|
-
const m = new
|
|
1201
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1578
1202
|
expect(m).modelCompiled();
|
|
1579
1203
|
const na = (0, test_translator_1.getExplore)(m.modelDef, 'na');
|
|
1580
1204
|
const abool = (0, test_translator_1.getField)(na, 'abool');
|
|
@@ -1584,14 +1208,14 @@ describe('source locations', () => {
|
|
|
1584
1208
|
});
|
|
1585
1209
|
test('location of named query', () => {
|
|
1586
1210
|
const source = (0, test_translator_1.markSource) `query: ${'q is a -> { project: * }'}`;
|
|
1587
|
-
const m = new
|
|
1211
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1588
1212
|
expect(m).modelCompiled();
|
|
1589
1213
|
const q = (0, test_translator_1.getExplore)(m.modelDef, 'q');
|
|
1590
1214
|
expect(q.location).toMatchObject(source.locations[0]);
|
|
1591
1215
|
});
|
|
1592
1216
|
test('location of field in named query', () => {
|
|
1593
1217
|
const source = (0, test_translator_1.markSource) `query: q is a -> { group_by: ${'b is 1'} }`;
|
|
1594
|
-
const m = new
|
|
1218
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1595
1219
|
expect(m).modelCompiled();
|
|
1596
1220
|
const q = (0, test_translator_1.getModelQuery)(m.modelDef, 'q');
|
|
1597
1221
|
const a = (0, test_translator_1.getField)(q.pipeline[0], 'b');
|
|
@@ -1599,7 +1223,7 @@ describe('source locations', () => {
|
|
|
1599
1223
|
});
|
|
1600
1224
|
test('location of named SQL block', () => {
|
|
1601
1225
|
const source = (0, test_translator_1.markSource) `${'sql: s is { select: """SELECT 1 as one""" }'}`;
|
|
1602
|
-
const m = new
|
|
1226
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1603
1227
|
expect(m).modelParsed();
|
|
1604
1228
|
const compileSql = m.translate().compileSQL;
|
|
1605
1229
|
expect(compileSql).toBeDefined();
|
|
@@ -1618,7 +1242,7 @@ describe('source locations', () => {
|
|
|
1618
1242
|
rename: ${'bbool is abool'}
|
|
1619
1243
|
}
|
|
1620
1244
|
`;
|
|
1621
|
-
const m = new
|
|
1245
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1622
1246
|
expect(m).modelCompiled();
|
|
1623
1247
|
const na = (0, test_translator_1.getExplore)(m.modelDef, 'na');
|
|
1624
1248
|
const bbool = (0, test_translator_1.getField)(na, 'bbool');
|
|
@@ -1630,7 +1254,7 @@ describe('source locations', () => {
|
|
|
1630
1254
|
join_one: ${'x is a { primary_key: abool } on abool'}
|
|
1631
1255
|
}
|
|
1632
1256
|
`;
|
|
1633
|
-
const m = new
|
|
1257
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1634
1258
|
expect(m).modelCompiled();
|
|
1635
1259
|
const na = (0, test_translator_1.getExplore)(m.modelDef, 'na');
|
|
1636
1260
|
const x = (0, test_translator_1.getField)(na, 'x');
|
|
@@ -1642,7 +1266,7 @@ describe('source locations', () => {
|
|
|
1642
1266
|
join_one: ${'x is a { primary_key: astr } with astr'}
|
|
1643
1267
|
}
|
|
1644
1268
|
`;
|
|
1645
|
-
const m = new
|
|
1269
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1646
1270
|
expect(m).modelCompiled();
|
|
1647
1271
|
const na = (0, test_translator_1.getExplore)(m.modelDef, 'na');
|
|
1648
1272
|
const x = (0, test_translator_1.getField)(na, 'x');
|
|
@@ -1657,7 +1281,7 @@ describe('source locations', () => {
|
|
|
1657
1281
|
} on abool
|
|
1658
1282
|
}
|
|
1659
1283
|
`;
|
|
1660
|
-
const m = new
|
|
1284
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1661
1285
|
expect(m).modelCompiled();
|
|
1662
1286
|
const na = (0, test_translator_1.getExplore)(m.modelDef, 'na');
|
|
1663
1287
|
const x = (0, test_translator_1.getJoinField)(na, 'x');
|
|
@@ -1667,7 +1291,7 @@ describe('source locations', () => {
|
|
|
1667
1291
|
// Since """ strings are not single tokens, I don't know how to do this.
|
|
1668
1292
|
// test("multi line sql block token span is correct", () => {
|
|
1669
1293
|
// const sqlSource = `sql: { select: """// line 0\n//line 1\n// line 2""" }`;
|
|
1670
|
-
// const m = new
|
|
1294
|
+
// const m = new TestTranslator(sqlSource);
|
|
1671
1295
|
// expect(m).not.modelParsed();
|
|
1672
1296
|
// const errList = m.errors().errors;
|
|
1673
1297
|
// expect(errList[0].at?.range.end).toEqual({ line: 2, character: 11 });
|
|
@@ -1684,7 +1308,7 @@ describe('source references', () => {
|
|
|
1684
1308
|
explore: ${'na is a'}
|
|
1685
1309
|
query: ${'na'} -> { project: * }
|
|
1686
1310
|
`;
|
|
1687
|
-
const m = new
|
|
1311
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1688
1312
|
expect(m).modelCompiled();
|
|
1689
1313
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1690
1314
|
location: source.locations[1],
|
|
@@ -1702,7 +1326,7 @@ describe('source references', () => {
|
|
|
1702
1326
|
}
|
|
1703
1327
|
query: t -> ${'q'}
|
|
1704
1328
|
`;
|
|
1705
|
-
const m = new
|
|
1329
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1706
1330
|
expect(m).modelCompiled();
|
|
1707
1331
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1708
1332
|
location: source.locations[1],
|
|
@@ -1718,7 +1342,7 @@ describe('source references', () => {
|
|
|
1718
1342
|
explore: na is a { query: ${'x is { group_by: y is 1 }'} }
|
|
1719
1343
|
query: na -> ${'x'}
|
|
1720
1344
|
`;
|
|
1721
|
-
const m = new
|
|
1345
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1722
1346
|
expect(m).modelCompiled();
|
|
1723
1347
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1724
1348
|
location: source.locations[1],
|
|
@@ -1734,7 +1358,7 @@ describe('source references', () => {
|
|
|
1734
1358
|
${'sql: s is {select:"""SELECT 1 as one"""}'}
|
|
1735
1359
|
explore: na is from_sql(${'s'})
|
|
1736
1360
|
`;
|
|
1737
|
-
const m = new
|
|
1361
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1738
1362
|
expect(m).modelParsed();
|
|
1739
1363
|
const compileSql = m.translate().compileSQL;
|
|
1740
1364
|
expect(compileSql).toBeDefined();
|
|
@@ -1760,7 +1384,7 @@ describe('source references', () => {
|
|
|
1760
1384
|
query: ${'q is a -> { project: * }'}
|
|
1761
1385
|
explore: na is from(-> ${'q'})
|
|
1762
1386
|
`;
|
|
1763
|
-
const m = new
|
|
1387
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1764
1388
|
expect(m).modelCompiled();
|
|
1765
1389
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1766
1390
|
location: source.locations[1],
|
|
@@ -1776,7 +1400,7 @@ describe('source references', () => {
|
|
|
1776
1400
|
query: ${'q is a -> { project: * }'}
|
|
1777
1401
|
query: q2 is -> ${'q'} -> { project: * }
|
|
1778
1402
|
`;
|
|
1779
|
-
const m = new
|
|
1403
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1780
1404
|
expect(m).modelCompiled();
|
|
1781
1405
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1782
1406
|
location: source.locations[1],
|
|
@@ -1792,7 +1416,7 @@ describe('source references', () => {
|
|
|
1792
1416
|
query: ${'q is a -> { project: * }'}
|
|
1793
1417
|
query: q2 is -> ${'q'} { limit: 10 }
|
|
1794
1418
|
`;
|
|
1795
|
-
const m = new
|
|
1419
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1796
1420
|
expect(m).modelCompiled();
|
|
1797
1421
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1798
1422
|
location: source.locations[1],
|
|
@@ -1808,7 +1432,7 @@ describe('source references', () => {
|
|
|
1808
1432
|
explore: na is ${"table('aTable')"}
|
|
1809
1433
|
query: na -> { project: bbool is not ${'abool'} }
|
|
1810
1434
|
`;
|
|
1811
|
-
const m = new
|
|
1435
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1812
1436
|
expect(m).modelCompiled();
|
|
1813
1437
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1814
1438
|
location: source.locations[1],
|
|
@@ -1826,7 +1450,7 @@ describe('source references', () => {
|
|
|
1826
1450
|
}
|
|
1827
1451
|
query: na -> { project: ${'`name`'} }
|
|
1828
1452
|
`;
|
|
1829
|
-
const m = new
|
|
1453
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1830
1454
|
expect(m).modelCompiled();
|
|
1831
1455
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1832
1456
|
location: source.locations[1],
|
|
@@ -1845,7 +1469,7 @@ describe('source references', () => {
|
|
|
1845
1469
|
}
|
|
1846
1470
|
query: na -> { project: bstr is self.${'astr'} }
|
|
1847
1471
|
`;
|
|
1848
|
-
const m = new
|
|
1472
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1849
1473
|
expect(m).modelCompiled();
|
|
1850
1474
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1851
1475
|
location: source.locations[1],
|
|
@@ -1863,7 +1487,7 @@ describe('source references', () => {
|
|
|
1863
1487
|
}
|
|
1864
1488
|
query: na -> { project: bstr is ${'self'}.astr }
|
|
1865
1489
|
`;
|
|
1866
|
-
const m = new
|
|
1490
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1867
1491
|
expect(m).modelCompiled();
|
|
1868
1492
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1869
1493
|
location: source.locations[1],
|
|
@@ -1878,7 +1502,7 @@ describe('source references', () => {
|
|
|
1878
1502
|
const source = (0, test_translator_1.markSource) `
|
|
1879
1503
|
query: ${"table('aTable')"} -> { group_by: ${'abool'} }
|
|
1880
1504
|
`;
|
|
1881
|
-
const m = new
|
|
1505
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1882
1506
|
expect(m).modelCompiled();
|
|
1883
1507
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1884
1508
|
location: source.locations[1],
|
|
@@ -1894,7 +1518,7 @@ describe('source references', () => {
|
|
|
1894
1518
|
explore: na is ${"table('aTable')"}
|
|
1895
1519
|
query: na -> { project: ${'abool'} }
|
|
1896
1520
|
`;
|
|
1897
|
-
const m = new
|
|
1521
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1898
1522
|
expect(m).modelCompiled();
|
|
1899
1523
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1900
1524
|
location: source.locations[1],
|
|
@@ -1912,7 +1536,7 @@ describe('source references', () => {
|
|
|
1912
1536
|
order_by: ${'abool'}
|
|
1913
1537
|
}
|
|
1914
1538
|
`;
|
|
1915
|
-
const m = new
|
|
1539
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1916
1540
|
expect(m).modelCompiled();
|
|
1917
1541
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1918
1542
|
location: source.locations[1],
|
|
@@ -1930,7 +1554,7 @@ describe('source references', () => {
|
|
|
1930
1554
|
order_by: ${'one'}
|
|
1931
1555
|
}
|
|
1932
1556
|
`;
|
|
1933
|
-
const m = new
|
|
1557
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1934
1558
|
expect(m).modelCompiled();
|
|
1935
1559
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1936
1560
|
location: source.locations[1],
|
|
@@ -1948,7 +1572,7 @@ describe('source references', () => {
|
|
|
1948
1572
|
aggregate: ${'c'}
|
|
1949
1573
|
}
|
|
1950
1574
|
`;
|
|
1951
|
-
const m = new
|
|
1575
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1952
1576
|
expect(m).modelCompiled();
|
|
1953
1577
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1954
1578
|
location: source.locations[1],
|
|
@@ -1966,7 +1590,7 @@ describe('source references', () => {
|
|
|
1966
1590
|
measure: c2 is ${'c'}
|
|
1967
1591
|
}
|
|
1968
1592
|
`;
|
|
1969
|
-
const m = new
|
|
1593
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1970
1594
|
expect(m).modelCompiled();
|
|
1971
1595
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1972
1596
|
location: source.locations[1],
|
|
@@ -1984,7 +1608,7 @@ describe('source references', () => {
|
|
|
1984
1608
|
top: 10 by ${'abool'}
|
|
1985
1609
|
}
|
|
1986
1610
|
`;
|
|
1987
|
-
const m = new
|
|
1611
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
1988
1612
|
expect(m).modelCompiled();
|
|
1989
1613
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1990
1614
|
location: source.locations[1],
|
|
@@ -2002,7 +1626,7 @@ describe('source references', () => {
|
|
|
2002
1626
|
top: 10 by ${'one'}
|
|
2003
1627
|
}
|
|
2004
1628
|
`;
|
|
2005
|
-
const m = new
|
|
1629
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
2006
1630
|
expect(m).modelCompiled();
|
|
2007
1631
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
2008
1632
|
location: source.locations[1],
|
|
@@ -2020,7 +1644,7 @@ describe('source references', () => {
|
|
|
2020
1644
|
where: ${'abool'}
|
|
2021
1645
|
}
|
|
2022
1646
|
`;
|
|
2023
|
-
const m = new
|
|
1647
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
2024
1648
|
expect(m).modelCompiled();
|
|
2025
1649
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
2026
1650
|
location: source.locations[1],
|
|
@@ -2036,7 +1660,7 @@ describe('source references', () => {
|
|
|
2036
1660
|
explore: na is ${"table('aTable')"}
|
|
2037
1661
|
query: na -> { aggregate: ai_sum is ${'ai'}.sum() }
|
|
2038
1662
|
`;
|
|
2039
|
-
const m = new
|
|
1663
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
2040
1664
|
expect(m).modelCompiled();
|
|
2041
1665
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
2042
1666
|
location: source.locations[1],
|
|
@@ -2057,7 +1681,7 @@ describe('source references', () => {
|
|
|
2057
1681
|
}
|
|
2058
1682
|
query: na -> { aggregate: ai_sum is ${'self'}.sum(self.ai) }
|
|
2059
1683
|
`;
|
|
2060
|
-
const m = new
|
|
1684
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
2061
1685
|
expect(m).modelCompiled();
|
|
2062
1686
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
2063
1687
|
location: source.locations[1],
|
|
@@ -2075,7 +1699,7 @@ describe('source references', () => {
|
|
|
2075
1699
|
}
|
|
2076
1700
|
query: na -> { aggregate: ai_sum is self.sum(${'self'}.ai) }
|
|
2077
1701
|
`;
|
|
2078
|
-
const m = new
|
|
1702
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
2079
1703
|
expect(m).modelCompiled();
|
|
2080
1704
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
2081
1705
|
location: source.locations[1],
|
|
@@ -2093,7 +1717,7 @@ describe('source references', () => {
|
|
|
2093
1717
|
join_one: ${'exp1'} on astr = exp1.astr
|
|
2094
1718
|
}
|
|
2095
1719
|
`;
|
|
2096
|
-
const m = new
|
|
1720
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
2097
1721
|
expect(m).modelCompiled();
|
|
2098
1722
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
2099
1723
|
location: source.locations[1],
|
|
@@ -2109,7 +1733,7 @@ describe('source references', () => {
|
|
|
2109
1733
|
explore: na is ${"table('aTable')"}
|
|
2110
1734
|
query: na -> { aggregate: ai_sum is sum(${'ai'}) }
|
|
2111
1735
|
`;
|
|
2112
|
-
const m = new
|
|
1736
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
2113
1737
|
expect(m).modelCompiled();
|
|
2114
1738
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
2115
1739
|
location: source.locations[1],
|
|
@@ -2126,7 +1750,7 @@ describe('source references', () => {
|
|
|
2126
1750
|
rename: bbool is ${'abool'}
|
|
2127
1751
|
}
|
|
2128
1752
|
`;
|
|
2129
|
-
const m = new
|
|
1753
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
2130
1754
|
expect(m).modelCompiled();
|
|
2131
1755
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
2132
1756
|
location: source.locations[1],
|
|
@@ -2144,7 +1768,7 @@ describe('source references', () => {
|
|
|
2144
1768
|
join_one: exp1 with ${'astr'}
|
|
2145
1769
|
}
|
|
2146
1770
|
`;
|
|
2147
|
-
const m = new
|
|
1771
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
2148
1772
|
expect(m).modelCompiled();
|
|
2149
1773
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
2150
1774
|
location: source.locations[1],
|
|
@@ -2159,7 +1783,7 @@ describe('source references', () => {
|
|
|
2159
1783
|
describe('translation need error locations', () => {
|
|
2160
1784
|
test('import error location', () => {
|
|
2161
1785
|
const source = (0, test_translator_1.markSource) `import ${'"badfile"'}`;
|
|
2162
|
-
const m = new
|
|
1786
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
2163
1787
|
const result = m.translate();
|
|
2164
1788
|
m.update({
|
|
2165
1789
|
errors: { urls: { [(result.urls || [])[0]]: 'Bad file!' } },
|
|
@@ -2174,7 +1798,7 @@ describe('translation need error locations', () => {
|
|
|
2174
1798
|
sql: bad_sql is {select: ${'"""BAD_SQL"""'}}
|
|
2175
1799
|
query: from_sql(bad_sql) -> { project: * }
|
|
2176
1800
|
`;
|
|
2177
|
-
const m = new
|
|
1801
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
2178
1802
|
expect(m).modelParsed();
|
|
2179
1803
|
const req = m.translate().compileSQL;
|
|
2180
1804
|
expect(req).toBeDefined();
|
|
@@ -2189,7 +1813,7 @@ describe('translation need error locations', () => {
|
|
|
2189
1813
|
const source = (0, test_translator_1.markSource) `
|
|
2190
1814
|
explore: bad_explore is ${"table('malloy-data.bad.table')"}
|
|
2191
1815
|
`;
|
|
2192
|
-
const m = new
|
|
1816
|
+
const m = new test_translator_1.TestTranslator(source.code);
|
|
2193
1817
|
const result = m.translate();
|
|
2194
1818
|
m.update({
|
|
2195
1819
|
errors: {
|
|
@@ -2263,7 +1887,7 @@ describe('pipeline comprehension', () => {
|
|
|
2263
1887
|
group_by: destination
|
|
2264
1888
|
}
|
|
2265
1889
|
`;
|
|
2266
|
-
const m = new
|
|
1890
|
+
const m = new test_translator_1.TestTranslator(src);
|
|
2267
1891
|
expect(m).modelCompiled();
|
|
2268
1892
|
const s2 = m.getQuery('s2');
|
|
2269
1893
|
expect(s2 === null || s2 === void 0 ? void 0 : s2.pipeline.length).toBe(2);
|