@malloydata/malloy 0.0.11-dev221202152346 → 0.0.11
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/index.d.ts +1 -1
- package/dist/lang/ast/ast-main.d.ts +61 -21
- package/dist/lang/ast/ast-main.js +170 -92
- package/dist/lang/index.d.ts +1 -1
- package/dist/lang/lib/Malloy/MalloyLexer.d.ts +135 -128
- package/dist/lang/lib/Malloy/MalloyLexer.js +1124 -1069
- package/dist/lang/lib/Malloy/MalloyListener.d.ts +2026 -0
- package/dist/lang/lib/Malloy/MalloyListener.js +4 -0
- package/dist/lang/lib/Malloy/MalloyParser.d.ts +276 -232
- package/dist/lang/lib/Malloy/MalloyParser.js +1719 -1456
- package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +48 -15
- package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +30 -9
- package/dist/lang/lib/Malloy/MalloyVisitor.d.ts +1276 -0
- package/dist/lang/lib/Malloy/MalloyVisitor.js +4 -0
- package/dist/lang/parse-malloy.d.ts +14 -23
- package/dist/lang/parse-malloy.js +37 -51
- package/dist/lang/parse-to-ast.d.ts +3 -2
- package/dist/lang/parse-to-ast.js +45 -13
- package/dist/lang/parse-tree-walkers/document-symbol-walker.js +2 -2
- package/dist/lang/test/parse.spec.d.ts +5 -3
- package/dist/lang/test/parse.spec.js +267 -181
- package/dist/malloy.d.ts +20 -20
- package/dist/malloy.js +73 -75
- package/dist/md5.d.ts +1 -0
- package/dist/md5.js +30 -0
- package/dist/model/malloy_query.js +1 -1
- package/dist/model/malloy_types.d.ts +19 -9
- package/dist/model/malloy_types.js +10 -1
- package/dist/model/sql_block.d.ts +5 -9
- package/dist/model/sql_block.js +21 -13
- package/dist/runtime_types.d.ts +8 -23
- package/package.json +1 -1
|
@@ -89,9 +89,8 @@ function prettyNeeds(response) {
|
|
|
89
89
|
needString += "Tables:\n";
|
|
90
90
|
response.tables.forEach((table) => (needString += ` - ${table}`));
|
|
91
91
|
}
|
|
92
|
-
if (response.
|
|
93
|
-
needString +=
|
|
94
|
-
response.sqlStructs.forEach((sql) => (needString += ` - ${sql.as || "(unnamed sql struct)"}`));
|
|
92
|
+
if (response.compileSQL) {
|
|
93
|
+
needString += `Compile SQL: ${response.compileSQL.name}`;
|
|
95
94
|
}
|
|
96
95
|
if (response.urls) {
|
|
97
96
|
needString += "URLs:\n";
|
|
@@ -112,12 +111,56 @@ function checkForNeededs(trans) {
|
|
|
112
111
|
pass: true,
|
|
113
112
|
};
|
|
114
113
|
}
|
|
114
|
+
function highlightError(dl, txt) {
|
|
115
|
+
if (dl == undefined) {
|
|
116
|
+
return "~Location Undefined~";
|
|
117
|
+
}
|
|
118
|
+
const { start, end } = dl.range;
|
|
119
|
+
const output = [
|
|
120
|
+
`${start.line}:${start.character}-${end.line}:${end.character}`,
|
|
121
|
+
];
|
|
122
|
+
let errStart = start.character;
|
|
123
|
+
const doc = txt.split("\n");
|
|
124
|
+
for (let line = start.line; line <= end.line; line += 1) {
|
|
125
|
+
const lineText = doc[line];
|
|
126
|
+
const lineStr = ` ${line}`.slice(-5);
|
|
127
|
+
output.push(`${lineStr}| ${lineText}`);
|
|
128
|
+
const upToError = ` | ` + " ".repeat(errStart);
|
|
129
|
+
let errLen = end.character - errStart;
|
|
130
|
+
if (line < end.line) {
|
|
131
|
+
errLen = lineText.length - errStart;
|
|
132
|
+
errStart = 0;
|
|
133
|
+
}
|
|
134
|
+
output.push(upToError + "-".repeat(errLen));
|
|
135
|
+
}
|
|
136
|
+
return output.join("\n");
|
|
137
|
+
}
|
|
138
|
+
function unlocatedStructDef(sd) {
|
|
139
|
+
const ret = { ...sd };
|
|
140
|
+
ret.fields = sd.fields.map((f) => {
|
|
141
|
+
const nf = { ...f };
|
|
142
|
+
delete nf.location;
|
|
143
|
+
return nf;
|
|
144
|
+
});
|
|
145
|
+
delete ret.location;
|
|
146
|
+
return ret;
|
|
147
|
+
}
|
|
115
148
|
expect.extend({
|
|
116
|
-
toCompile: function (
|
|
149
|
+
toCompile: function (s) {
|
|
150
|
+
const x = new BetaModel(s);
|
|
151
|
+
x.compile();
|
|
152
|
+
const errorCheck = checkForErrors(x);
|
|
153
|
+
if (!errorCheck.pass) {
|
|
154
|
+
return errorCheck;
|
|
155
|
+
}
|
|
156
|
+
x.translate();
|
|
157
|
+
return checkForNeededs(x);
|
|
158
|
+
},
|
|
159
|
+
modelParsed: function (x) {
|
|
117
160
|
x.compile();
|
|
118
161
|
return checkForErrors(x);
|
|
119
162
|
},
|
|
120
|
-
|
|
163
|
+
modelCompiled: function (x) {
|
|
121
164
|
x.compile();
|
|
122
165
|
const errorCheck = checkForErrors(x);
|
|
123
166
|
if (!errorCheck.pass) {
|
|
@@ -131,7 +174,7 @@ expect.extend({
|
|
|
131
174
|
},
|
|
132
175
|
toReturnType: function (functionCall, returnType) {
|
|
133
176
|
const exprModel = new BetaModel(`explore: x is a { dimension: d is ${functionCall} }`);
|
|
134
|
-
expect(exprModel).
|
|
177
|
+
expect(exprModel).modelCompiled();
|
|
135
178
|
const x = exprModel.getSourceDef("x");
|
|
136
179
|
expect(x).toBeDefined();
|
|
137
180
|
if (x) {
|
|
@@ -223,6 +266,21 @@ expect.extend({
|
|
|
223
266
|
};
|
|
224
267
|
}
|
|
225
268
|
},
|
|
269
|
+
isLocationIn: function (checkAt, at, text) {
|
|
270
|
+
if (this.equals(at, checkAt)) {
|
|
271
|
+
return {
|
|
272
|
+
pass: true,
|
|
273
|
+
message: () => `Locations match`,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
const errMsg = `Locations do not match\n` +
|
|
277
|
+
`Expected: ${highlightError(at, text)}\n` +
|
|
278
|
+
`Received: ${highlightError(checkAt, text)}\n`;
|
|
279
|
+
return {
|
|
280
|
+
pass: false,
|
|
281
|
+
message: () => errMsg,
|
|
282
|
+
};
|
|
283
|
+
},
|
|
226
284
|
});
|
|
227
285
|
class BetaExpression extends Testable {
|
|
228
286
|
constructor(src) {
|
|
@@ -254,14 +312,14 @@ class BetaExpression extends Testable {
|
|
|
254
312
|
}
|
|
255
313
|
function exprOK(s) {
|
|
256
314
|
return () => {
|
|
257
|
-
expect(new BetaExpression(s)).
|
|
315
|
+
expect(new BetaExpression(s)).modelParsed();
|
|
258
316
|
return undefined;
|
|
259
317
|
};
|
|
260
318
|
}
|
|
261
319
|
function modelOK(s) {
|
|
262
320
|
return () => {
|
|
263
321
|
const m = new BetaModel(s);
|
|
264
|
-
expect(m).
|
|
322
|
+
expect(m).modelCompiled();
|
|
265
323
|
return undefined;
|
|
266
324
|
};
|
|
267
325
|
}
|
|
@@ -293,9 +351,9 @@ function badModel(s, msg) {
|
|
|
293
351
|
describe("model statements", () => {
|
|
294
352
|
describe("explore:", () => {
|
|
295
353
|
test("explore table", modelOK(`explore: testA is table('aTable')`));
|
|
296
|
-
test("explore shorcut fitlered table",
|
|
297
|
-
|
|
298
|
-
|
|
354
|
+
test("explore shorcut fitlered table", () => {
|
|
355
|
+
expect(`explore: testA is table('aTable') {? astr ~ 'a%' } `).toCompile();
|
|
356
|
+
});
|
|
299
357
|
test("explore fitlered table", modelOK(`
|
|
300
358
|
explore: testA is table('aTable') { where: astr ~ 'a%' }
|
|
301
359
|
`));
|
|
@@ -304,7 +362,7 @@ describe("model statements", () => {
|
|
|
304
362
|
test("refine explore", modelOK(`explore: aa is a { dimension: a is astr }`));
|
|
305
363
|
test("source refinement preserves original", () => {
|
|
306
364
|
const x = new BetaModel("source: na is a + { dimension: one is 1 }");
|
|
307
|
-
expect(x).
|
|
365
|
+
expect(x).modelCompiled();
|
|
308
366
|
const a = x.getSourceDef("a");
|
|
309
367
|
if (a) {
|
|
310
368
|
const aFields = a.fields.map((f) => f.as || f.name);
|
|
@@ -352,7 +410,7 @@ describe("model statements", () => {
|
|
|
352
410
|
query: q is a -> { aggregate: acount is count() }
|
|
353
411
|
query: nq is -> q + { group_by: astr }
|
|
354
412
|
`);
|
|
355
|
-
expect(x).
|
|
413
|
+
expect(x).modelCompiled();
|
|
356
414
|
const q = x.getQuery("q");
|
|
357
415
|
expect(q).toBeDefined();
|
|
358
416
|
if (q) {
|
|
@@ -365,7 +423,7 @@ describe("model statements", () => {
|
|
|
365
423
|
query: q is ab -> { aggregate: acount }
|
|
366
424
|
query: nq is -> q -> { project: * }
|
|
367
425
|
`);
|
|
368
|
-
expect(x).
|
|
426
|
+
expect(x).modelCompiled();
|
|
369
427
|
const q = x.getQuery("q");
|
|
370
428
|
expect(q).toBeDefined();
|
|
371
429
|
if (q) {
|
|
@@ -473,7 +531,7 @@ describe("model statements", () => {
|
|
|
473
531
|
});
|
|
474
532
|
test("relative imports", () => {
|
|
475
533
|
const docParse = new BetaModel(`import "../parent.malloy"`);
|
|
476
|
-
expect(docParse).
|
|
534
|
+
expect(docParse).modelParsed();
|
|
477
535
|
const xr = docParse.unresolved();
|
|
478
536
|
expect(xr).toEqual({ urls: ["internal://test/parent.malloy"] });
|
|
479
537
|
docParse.update({
|
|
@@ -481,11 +539,11 @@ describe("model statements", () => {
|
|
|
481
539
|
"internal://test/parent.malloy": `source: aa is table('aTable')`,
|
|
482
540
|
},
|
|
483
541
|
});
|
|
484
|
-
expect(docParse).
|
|
542
|
+
expect(docParse).modelCompiled();
|
|
485
543
|
});
|
|
486
544
|
test("relative imports with errors", () => {
|
|
487
545
|
const docParse = new BetaModel(`import "../parent.malloy"`);
|
|
488
|
-
expect(docParse).
|
|
546
|
+
expect(docParse).modelParsed();
|
|
489
547
|
const xr = docParse.unresolved();
|
|
490
548
|
expect(xr).toEqual({ urls: ["internal://test/parent.malloy"] });
|
|
491
549
|
docParse.update({
|
|
@@ -510,7 +568,7 @@ describe("model statements", () => {
|
|
|
510
568
|
import "middle"
|
|
511
569
|
`);
|
|
512
570
|
fullModel.update({ urls: srcFiles });
|
|
513
|
-
expect(fullModel).
|
|
571
|
+
expect(fullModel).modelCompiled();
|
|
514
572
|
const ms = fullModel.getSourceDef("midSrc");
|
|
515
573
|
expect(ms).toBeDefined();
|
|
516
574
|
if (ms) {
|
|
@@ -595,7 +653,7 @@ describe("explore properties", () => {
|
|
|
595
653
|
test("rename", modelOK("explore: c is a { rename: nn is ai }"));
|
|
596
654
|
test("accept single", () => {
|
|
597
655
|
const onlyAstr = new BetaModel("explore: c is a { accept: astr }");
|
|
598
|
-
expect(onlyAstr).
|
|
656
|
+
expect(onlyAstr).modelCompiled();
|
|
599
657
|
const c = onlyAstr.getSourceDef("c");
|
|
600
658
|
if (c) {
|
|
601
659
|
expect(c.fields.length).toBe(1);
|
|
@@ -604,7 +662,7 @@ describe("explore properties", () => {
|
|
|
604
662
|
test("accept multi", modelOK("explore: c is a { accept: astr, af }"));
|
|
605
663
|
test("except single", () => {
|
|
606
664
|
const noAstr = new BetaModel("explore: c is a { except: astr }");
|
|
607
|
-
expect(noAstr).
|
|
665
|
+
expect(noAstr).modelCompiled();
|
|
608
666
|
const c = noAstr.getSourceDef("c");
|
|
609
667
|
if (c) {
|
|
610
668
|
const foundAstr = c.fields.find((f) => f.name == "astr");
|
|
@@ -612,7 +670,7 @@ describe("explore properties", () => {
|
|
|
612
670
|
}
|
|
613
671
|
});
|
|
614
672
|
test("except multi", modelOK("explore: c is a { except: astr, af }"));
|
|
615
|
-
test("explore-query", modelOK("explore: c is a {query: q is { group_by: astr }}"));
|
|
673
|
+
test("explore-query", modelOK("explore: c is a {query: q is { group_by: astr } }"));
|
|
616
674
|
test("refined explore-query", modelOK(`
|
|
617
675
|
explore: abNew is ab {
|
|
618
676
|
query: for1 is aturtle {? ai = 1 }
|
|
@@ -660,7 +718,7 @@ describe("qops", () => {
|
|
|
660
718
|
test("index join.*", modelOK("query:ab->{index: ab.*}"));
|
|
661
719
|
test("index multiple", () => {
|
|
662
720
|
const model = new BetaModel("query:a->{index: af, astr}");
|
|
663
|
-
expect(model).
|
|
721
|
+
expect(model).modelCompiled();
|
|
664
722
|
const q = model.getQuery(0);
|
|
665
723
|
expect(q).toBeDefined();
|
|
666
724
|
if (q) {
|
|
@@ -671,7 +729,7 @@ describe("qops", () => {
|
|
|
671
729
|
});
|
|
672
730
|
test("index star", () => {
|
|
673
731
|
const model = new BetaModel("query:a->{index: *, astr}");
|
|
674
|
-
expect(model).
|
|
732
|
+
expect(model).modelCompiled();
|
|
675
733
|
const q = model.getQuery(0);
|
|
676
734
|
expect(q).toBeDefined();
|
|
677
735
|
if (q) {
|
|
@@ -685,7 +743,7 @@ describe("qops", () => {
|
|
|
685
743
|
test("index unsampled", modelOK("query:a->{index: *; sample: false}"));
|
|
686
744
|
test("index sample-percent", () => {
|
|
687
745
|
const model = new BetaModel("query:a->{index: *; sample: 42%}");
|
|
688
|
-
expect(model).
|
|
746
|
+
expect(model).modelCompiled();
|
|
689
747
|
const q = model.getQuery(0);
|
|
690
748
|
expect(q).toBeDefined();
|
|
691
749
|
if (q) {
|
|
@@ -716,7 +774,7 @@ describe("qops", () => {
|
|
|
716
774
|
test("where multiple", modelOK("query:a->{ group_by: astr; where: af > 10,astr~'a%' }"));
|
|
717
775
|
test(`filters preserve source formatting in code:`, () => {
|
|
718
776
|
const model = new BetaModel(`source: notb is a + { where: astr != 'b' }`);
|
|
719
|
-
expect(model).
|
|
777
|
+
expect(model).modelCompiled();
|
|
720
778
|
const notb = model.getSourceDef("notb");
|
|
721
779
|
expect(notb).toBeDefined();
|
|
722
780
|
if (notb) {
|
|
@@ -729,7 +787,7 @@ describe("qops", () => {
|
|
|
729
787
|
});
|
|
730
788
|
test(`field expressions preserve source formatting in code:`, () => {
|
|
731
789
|
const model = new BetaModel(`source: notb is a + { dimension: d is 1 + 2 }`);
|
|
732
|
-
expect(model).
|
|
790
|
+
expect(model).modelCompiled();
|
|
733
791
|
const notb = model.getSourceDef("notb");
|
|
734
792
|
expect(notb).toBeDefined();
|
|
735
793
|
if (notb) {
|
|
@@ -765,7 +823,7 @@ describe("qops", () => {
|
|
|
765
823
|
}
|
|
766
824
|
query: nab -> xturtle + { aggregate: aratio }
|
|
767
825
|
`);
|
|
768
|
-
expect(m).
|
|
826
|
+
expect(m).modelCompiled();
|
|
769
827
|
const t = m.translate();
|
|
770
828
|
if (t.translated) {
|
|
771
829
|
const q = t.translated.queryList[0].pipeline[0];
|
|
@@ -789,7 +847,7 @@ describe("qops", () => {
|
|
|
789
847
|
aggregate: aratio
|
|
790
848
|
}
|
|
791
849
|
`);
|
|
792
|
-
expect(m).
|
|
850
|
+
expect(m).modelCompiled();
|
|
793
851
|
const t = m.translate();
|
|
794
852
|
if (t.translated) {
|
|
795
853
|
const q = t.translated.queryList[0].pipeline[0];
|
|
@@ -813,7 +871,7 @@ describe("qops", () => {
|
|
|
813
871
|
group_by: foo is bb.astr
|
|
814
872
|
}
|
|
815
873
|
`);
|
|
816
|
-
expect(m).
|
|
874
|
+
expect(m).modelCompiled();
|
|
817
875
|
const t = m.translate();
|
|
818
876
|
if (t.translated) {
|
|
819
877
|
const q = t.translated.queryList[0].pipeline[0];
|
|
@@ -989,7 +1047,7 @@ describe("expressions", () => {
|
|
|
989
1047
|
var _a, _b;
|
|
990
1048
|
const modelSrc = `query: z is a -> { group_by: x is 1+(3/4) }`;
|
|
991
1049
|
const m = new BetaModel(modelSrc);
|
|
992
|
-
expect(m).
|
|
1050
|
+
expect(m).modelCompiled();
|
|
993
1051
|
const queryDef = (_b = (_a = m.translate()) === null || _a === void 0 ? void 0 : _a.translated) === null || _b === void 0 ? void 0 : _b.modelDef.contents.z;
|
|
994
1052
|
expect(queryDef).toBeDefined();
|
|
995
1053
|
expect(queryDef === null || queryDef === void 0 ? void 0 : queryDef.type).toBe("query");
|
|
@@ -1014,8 +1072,9 @@ describe("expressions", () => {
|
|
|
1014
1072
|
}
|
|
1015
1073
|
});
|
|
1016
1074
|
});
|
|
1017
|
-
describe("sql
|
|
1075
|
+
describe("sql:", () => {
|
|
1018
1076
|
function makeSchemaResponse(sql) {
|
|
1077
|
+
const cname = sql.connection || "bigquery";
|
|
1019
1078
|
return {
|
|
1020
1079
|
type: "struct",
|
|
1021
1080
|
name: sql.name,
|
|
@@ -1023,85 +1082,95 @@ describe("sql backdoor", () => {
|
|
|
1023
1082
|
structSource: {
|
|
1024
1083
|
type: "sql",
|
|
1025
1084
|
method: "subquery",
|
|
1026
|
-
sqlBlock: {
|
|
1085
|
+
sqlBlock: {
|
|
1086
|
+
type: "sqlBlock",
|
|
1087
|
+
...sql,
|
|
1088
|
+
selectStr: sql.select.filter((s) => typeof s == "string").join(""),
|
|
1089
|
+
},
|
|
1027
1090
|
},
|
|
1028
|
-
structRelationship: { type: "basetable", connectionName:
|
|
1091
|
+
structRelationship: { type: "basetable", connectionName: cname },
|
|
1029
1092
|
fields: test_translator_1.aTableDef.fields,
|
|
1030
1093
|
};
|
|
1031
1094
|
}
|
|
1032
|
-
test("
|
|
1033
|
-
|
|
1095
|
+
test("definition", () => {
|
|
1096
|
+
const selStmt = "SELECT * FROM aTable";
|
|
1034
1097
|
const model = new BetaModel(`
|
|
1035
|
-
sql: users IS
|
|
1036
|
-
|
|
1098
|
+
sql: users IS {
|
|
1099
|
+
select: """${selStmt}"""
|
|
1100
|
+
connection: "aConnection"
|
|
1101
|
+
}
|
|
1037
1102
|
`);
|
|
1038
1103
|
const needReq = model.translate();
|
|
1039
|
-
expect(model).
|
|
1040
|
-
const needs = needReq === null || needReq === void 0 ? void 0 : needReq.
|
|
1104
|
+
expect(model).modelParsed();
|
|
1105
|
+
const needs = needReq === null || needReq === void 0 ? void 0 : needReq.compileSQL;
|
|
1041
1106
|
expect(needs).toBeDefined();
|
|
1042
1107
|
if (needs) {
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
connection: "someConnection",
|
|
1047
|
-
});
|
|
1048
|
-
expect(needs[0]).toMatchObject(sql);
|
|
1049
|
-
const refKey = needs[0].name;
|
|
1108
|
+
const sql = (0, sql_block_1.makeSQLBlock)([{ sql: selStmt }], "aConnection");
|
|
1109
|
+
expect(needs).toMatchObject(sql);
|
|
1110
|
+
const refKey = needs.name;
|
|
1050
1111
|
expect(refKey).toBeDefined();
|
|
1051
1112
|
if (refKey) {
|
|
1052
|
-
|
|
1053
|
-
|
|
1113
|
+
const sr = makeSchemaResponse(sql);
|
|
1114
|
+
model.update({ compileSQL: { [refKey]: sr } });
|
|
1115
|
+
expect(model).modelCompiled();
|
|
1116
|
+
expect(unlocatedStructDef(model.sqlBlocks[0])).toEqual(unlocatedStructDef({ ...sr, as: "users" }));
|
|
1054
1117
|
}
|
|
1055
|
-
const users = model.getSourceDef("malloyUsers");
|
|
1056
|
-
expect(users).toBeDefined();
|
|
1057
|
-
expect(users).toHaveProperty("structSource.sqlBlock.connection", "someConnection");
|
|
1058
1118
|
}
|
|
1059
1119
|
});
|
|
1060
|
-
test("
|
|
1120
|
+
test("source from sql", () => {
|
|
1121
|
+
const selStmt = "SELECT * FROM aTable";
|
|
1061
1122
|
const model = new BetaModel(`
|
|
1062
|
-
sql: users IS
|
|
1123
|
+
sql: users IS { select: """${selStmt}""" }
|
|
1063
1124
|
source: malloyUsers is from_sql(users) { primary_key: ai }
|
|
1064
1125
|
`);
|
|
1126
|
+
expect(model).modelParsed();
|
|
1065
1127
|
const needReq = model.translate();
|
|
1066
|
-
|
|
1067
|
-
const needs = needReq === null || needReq === void 0 ? void 0 : needReq.sqlStructs;
|
|
1128
|
+
const needs = needReq === null || needReq === void 0 ? void 0 : needReq.compileSQL;
|
|
1068
1129
|
expect(needs).toBeDefined();
|
|
1069
1130
|
if (needs) {
|
|
1070
|
-
|
|
1071
|
-
const
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
model.update({ sqlStructs: { [refKey]: makeSchemaResponse(sql) } });
|
|
1077
|
-
expect(model).toTranslate();
|
|
1078
|
-
}
|
|
1131
|
+
const sql = (0, sql_block_1.makeSQLBlock)([{ sql: selStmt }], "aConnection");
|
|
1132
|
+
const refKey = needs.name;
|
|
1133
|
+
model.update({ compileSQL: { [refKey]: makeSchemaResponse(sql) } });
|
|
1134
|
+
expect(model).modelCompiled();
|
|
1135
|
+
const users = model.getSourceDef("malloyUsers");
|
|
1136
|
+
expect(users).toBeDefined();
|
|
1079
1137
|
}
|
|
1080
1138
|
});
|
|
1081
1139
|
test("explore from imported sql-based-source", () => {
|
|
1140
|
+
const selStmt = "SELECT * FROM aTable";
|
|
1082
1141
|
const createModel = `
|
|
1083
|
-
sql: users IS
|
|
1142
|
+
sql: users IS { select: """${selStmt}""" }
|
|
1084
1143
|
source: malloyUsers is from_sql(users) { primary_key: ai }
|
|
1085
1144
|
`;
|
|
1086
1145
|
const model = new BetaModel(`
|
|
1087
1146
|
import "createModel.malloy"
|
|
1088
|
-
source:
|
|
1147
|
+
source: importUsers is malloyUsers
|
|
1089
1148
|
`);
|
|
1090
1149
|
model.importZone.define("internal://test/langtests/createModel.malloy", createModel);
|
|
1150
|
+
expect(model).modelParsed();
|
|
1091
1151
|
const needReq = model.translate();
|
|
1092
|
-
|
|
1093
|
-
const needs = needReq === null || needReq === void 0 ? void 0 : needReq.sqlStructs;
|
|
1152
|
+
const needs = needReq === null || needReq === void 0 ? void 0 : needReq.compileSQL;
|
|
1094
1153
|
expect(needs).toBeDefined();
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1154
|
+
const sql = (0, sql_block_1.makeSQLBlock)([{ sql: selStmt }]);
|
|
1155
|
+
model.update({ compileSQL: { [sql.name]: makeSchemaResponse(sql) } });
|
|
1156
|
+
expect(model).modelCompiled();
|
|
1157
|
+
});
|
|
1158
|
+
it("turducken", () => {
|
|
1159
|
+
const m = new BetaModel(`
|
|
1160
|
+
sql: someSql is {
|
|
1161
|
+
select: """SELECT * FROM %{ a -> { group_by: astr } }% WHERE 1=1"""
|
|
1162
|
+
}
|
|
1163
|
+
`);
|
|
1164
|
+
expect(m).modelParsed();
|
|
1165
|
+
const compileSql = m.translate().compileSQL;
|
|
1166
|
+
expect(compileSql).toBeDefined();
|
|
1167
|
+
if (compileSql) {
|
|
1168
|
+
const select = compileSql.select[0];
|
|
1169
|
+
const star = compileSql.select[1];
|
|
1170
|
+
const where = compileSql.select[2];
|
|
1171
|
+
expect(select).toEqual({ sql: "SELECT * FROM " });
|
|
1172
|
+
expect((0, model_1.isSQLFragment)(star)).toBeFalsy();
|
|
1173
|
+
expect(where).toEqual({ sql: " WHERE 1=1" });
|
|
1105
1174
|
}
|
|
1106
1175
|
});
|
|
1107
1176
|
});
|
|
@@ -1146,7 +1215,7 @@ describe("error handling", () => {
|
|
|
1146
1215
|
test("undefined field ref in query", badModel(`query: ab -> { aggregate: xyzzy }`, "'xyzzy' is not defined"));
|
|
1147
1216
|
// test("queries with anonymous expressions", () => {
|
|
1148
1217
|
// const m = new BetaModel("query: a->{\n group_by: a+1\n}");
|
|
1149
|
-
// expect(m).not.
|
|
1218
|
+
// expect(m).not.modelParsed();
|
|
1150
1219
|
// const errList = m.errors().errors;
|
|
1151
1220
|
// const firstError = errList[0];
|
|
1152
1221
|
// expect(firstError.message).toBe("Expressions in queries must have names");
|
|
@@ -1193,6 +1262,10 @@ describe("error handling", () => {
|
|
|
1193
1262
|
`));
|
|
1194
1263
|
});
|
|
1195
1264
|
function getSelectOneStruct(sqlBlock) {
|
|
1265
|
+
const selectThis = sqlBlock.select[0];
|
|
1266
|
+
if (!(0, model_1.isSQLFragment)(selectThis)) {
|
|
1267
|
+
throw new Error("weird test support error sorry");
|
|
1268
|
+
}
|
|
1196
1269
|
return {
|
|
1197
1270
|
type: "struct",
|
|
1198
1271
|
name: sqlBlock.name,
|
|
@@ -1200,7 +1273,11 @@ function getSelectOneStruct(sqlBlock) {
|
|
|
1200
1273
|
structSource: {
|
|
1201
1274
|
type: "sql",
|
|
1202
1275
|
method: "subquery",
|
|
1203
|
-
sqlBlock
|
|
1276
|
+
sqlBlock: {
|
|
1277
|
+
type: "sqlBlock",
|
|
1278
|
+
name: sqlBlock.name,
|
|
1279
|
+
selectStr: selectThis.sql,
|
|
1280
|
+
},
|
|
1204
1281
|
},
|
|
1205
1282
|
structRelationship: { type: "basetable", connectionName: "bigquery" },
|
|
1206
1283
|
fields: [{ type: "number", name: "one" }],
|
|
@@ -1210,19 +1287,19 @@ describe("source locations", () => {
|
|
|
1210
1287
|
test("renamed explore location", () => {
|
|
1211
1288
|
const source = (0, test_translator_1.markSource) `explore: ${"na is a"}`;
|
|
1212
1289
|
const m = new BetaModel(source.code);
|
|
1213
|
-
expect(m).
|
|
1290
|
+
expect(m).modelParsed();
|
|
1214
1291
|
expect((0, test_translator_1.getExplore)(m.modelDef, "na").location).toMatchObject(source.locations[0]);
|
|
1215
1292
|
});
|
|
1216
1293
|
test("refined explore location", () => {
|
|
1217
1294
|
const source = (0, test_translator_1.markSource) `explore: ${"na is a {}"}`;
|
|
1218
1295
|
const m = new BetaModel(source.code);
|
|
1219
|
-
expect(m).
|
|
1296
|
+
expect(m).modelParsed();
|
|
1220
1297
|
expect((0, test_translator_1.getExplore)(m.modelDef, "na").location).toMatchObject(source.locations[0]);
|
|
1221
1298
|
});
|
|
1222
1299
|
test("location of defined dimension", () => {
|
|
1223
1300
|
const source = (0, test_translator_1.markSource) `explore: na is a { dimension: ${"x is 1"} }`;
|
|
1224
1301
|
const m = new BetaModel(source.code);
|
|
1225
|
-
expect(m).
|
|
1302
|
+
expect(m).modelCompiled();
|
|
1226
1303
|
const na = (0, test_translator_1.getExplore)(m.modelDef, "na");
|
|
1227
1304
|
const x = (0, test_translator_1.getField)(na, "x");
|
|
1228
1305
|
expect(x.location).toMatchObject(source.locations[0]);
|
|
@@ -1230,7 +1307,7 @@ describe("source locations", () => {
|
|
|
1230
1307
|
test("location of defined measure", () => {
|
|
1231
1308
|
const source = (0, test_translator_1.markSource) `explore: na is a { measure: ${"x is count()"} }`;
|
|
1232
1309
|
const m = new BetaModel(source.code);
|
|
1233
|
-
expect(m).
|
|
1310
|
+
expect(m).modelCompiled();
|
|
1234
1311
|
const na = (0, test_translator_1.getExplore)(m.modelDef, "na");
|
|
1235
1312
|
const x = (0, test_translator_1.getField)(na, "x");
|
|
1236
1313
|
expect(x.location).toMatchObject(source.locations[0]);
|
|
@@ -1238,7 +1315,7 @@ describe("source locations", () => {
|
|
|
1238
1315
|
test("location of defined query", () => {
|
|
1239
1316
|
const source = (0, test_translator_1.markSource) `explore: na is a { query: ${"x is { group_by: y is 1 }"} }`;
|
|
1240
1317
|
const m = new BetaModel(source.code);
|
|
1241
|
-
expect(m).
|
|
1318
|
+
expect(m).modelCompiled();
|
|
1242
1319
|
const na = (0, test_translator_1.getExplore)(m.modelDef, "na");
|
|
1243
1320
|
const x = (0, test_translator_1.getField)(na, "x");
|
|
1244
1321
|
expect(x.location).toMatchObject(source.locations[0]);
|
|
@@ -1251,7 +1328,7 @@ describe("source locations", () => {
|
|
|
1251
1328
|
}
|
|
1252
1329
|
}`;
|
|
1253
1330
|
const m = new BetaModel(source.code);
|
|
1254
|
-
expect(m).
|
|
1331
|
+
expect(m).modelCompiled();
|
|
1255
1332
|
const na = (0, test_translator_1.getExplore)(m.modelDef, "na");
|
|
1256
1333
|
const x = (0, test_translator_1.getQueryField)(na, "x");
|
|
1257
1334
|
const y = (0, test_translator_1.getField)(x.pipeline[0], "y");
|
|
@@ -1266,7 +1343,7 @@ describe("source locations", () => {
|
|
|
1266
1343
|
}
|
|
1267
1344
|
}`;
|
|
1268
1345
|
const m = new BetaModel(source.code);
|
|
1269
|
-
expect(m).
|
|
1346
|
+
expect(m).modelCompiled();
|
|
1270
1347
|
const na = (0, test_translator_1.getExplore)(m.modelDef, "na");
|
|
1271
1348
|
const x = (0, test_translator_1.getQueryField)(na, "x");
|
|
1272
1349
|
const z = (0, test_translator_1.getField)(x.pipeline[0], "z");
|
|
@@ -1275,29 +1352,29 @@ describe("source locations", () => {
|
|
|
1275
1352
|
test("location of field inherited from table", () => {
|
|
1276
1353
|
const source = (0, test_translator_1.markSource) `explore: na is ${"table('aTable')"}`;
|
|
1277
1354
|
const m = new BetaModel(source.code);
|
|
1278
|
-
expect(m).
|
|
1355
|
+
expect(m).modelCompiled();
|
|
1279
1356
|
const na = (0, test_translator_1.getExplore)(m.modelDef, "na");
|
|
1280
1357
|
const abool = (0, test_translator_1.getField)(na, "abool");
|
|
1281
1358
|
expect(abool.location).toMatchObject(source.locations[0]);
|
|
1282
1359
|
});
|
|
1283
1360
|
test("location of field inherited from sql block", () => {
|
|
1284
|
-
const source = (0, test_translator_1.markSource)
|
|
1285
|
-
sql:
|
|
1286
|
-
|
|
1361
|
+
const source = (0, test_translator_1.markSource) `--- comment
|
|
1362
|
+
sql: s is { select: ${'"""SELECT 1 as one """'} }
|
|
1287
1363
|
explore: na is from_sql(s)
|
|
1288
1364
|
`;
|
|
1289
1365
|
const m = new BetaModel(source.code);
|
|
1290
|
-
|
|
1291
|
-
const
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1366
|
+
expect(m).modelParsed();
|
|
1367
|
+
const compileSql = m.translate().compileSQL;
|
|
1368
|
+
expect(compileSql).toBeDefined();
|
|
1369
|
+
if (compileSql) {
|
|
1370
|
+
m.update({
|
|
1371
|
+
compileSQL: { [compileSql.name]: getSelectOneStruct(compileSql) },
|
|
1372
|
+
});
|
|
1373
|
+
expect(m).modelCompiled();
|
|
1374
|
+
const na = (0, test_translator_1.getExplore)(m.modelDef, "na");
|
|
1375
|
+
const one = (0, test_translator_1.getField)(na, "one");
|
|
1376
|
+
expect(one.location).isLocationIn(source.locations[0], source.code);
|
|
1377
|
+
}
|
|
1301
1378
|
});
|
|
1302
1379
|
test("location of fields inherited from a query", () => {
|
|
1303
1380
|
const source = (0, test_translator_1.markSource) `
|
|
@@ -1310,7 +1387,7 @@ describe("source locations", () => {
|
|
|
1310
1387
|
)
|
|
1311
1388
|
`;
|
|
1312
1389
|
const m = new BetaModel(source.code);
|
|
1313
|
-
expect(m).
|
|
1390
|
+
expect(m).modelCompiled();
|
|
1314
1391
|
const na = (0, test_translator_1.getExplore)(m.modelDef, "na");
|
|
1315
1392
|
const abool = (0, test_translator_1.getField)(na, "abool");
|
|
1316
1393
|
expect(abool.location).toMatchObject(source.locations[0]);
|
|
@@ -1320,24 +1397,32 @@ describe("source locations", () => {
|
|
|
1320
1397
|
test("location of named query", () => {
|
|
1321
1398
|
const source = (0, test_translator_1.markSource) `query: ${"q is a -> { project: * }"}`;
|
|
1322
1399
|
const m = new BetaModel(source.code);
|
|
1323
|
-
expect(m).
|
|
1400
|
+
expect(m).modelCompiled();
|
|
1324
1401
|
const q = (0, test_translator_1.getExplore)(m.modelDef, "q");
|
|
1325
1402
|
expect(q.location).toMatchObject(source.locations[0]);
|
|
1326
1403
|
});
|
|
1327
1404
|
test("location of field in named query", () => {
|
|
1328
1405
|
const source = (0, test_translator_1.markSource) `query: q is a -> { group_by: ${"b is 1"} }`;
|
|
1329
1406
|
const m = new BetaModel(source.code);
|
|
1330
|
-
expect(m).
|
|
1407
|
+
expect(m).modelCompiled();
|
|
1331
1408
|
const q = (0, test_translator_1.getModelQuery)(m.modelDef, "q");
|
|
1332
1409
|
const a = (0, test_translator_1.getField)(q.pipeline[0], "b");
|
|
1333
1410
|
expect(a.location).toMatchObject(source.locations[0]);
|
|
1334
1411
|
});
|
|
1335
1412
|
test("location of named SQL block", () => {
|
|
1336
|
-
const source = (0, test_translator_1.markSource) `sql:
|
|
1413
|
+
const source = (0, test_translator_1.markSource) `${`sql: s is { select: """SELECT 1 as one""" }`}`;
|
|
1337
1414
|
const m = new BetaModel(source.code);
|
|
1338
|
-
expect(m).
|
|
1339
|
-
const
|
|
1340
|
-
expect(
|
|
1415
|
+
expect(m).modelParsed();
|
|
1416
|
+
const compileSql = m.translate().compileSQL;
|
|
1417
|
+
expect(compileSql).toBeDefined();
|
|
1418
|
+
if (compileSql) {
|
|
1419
|
+
m.update({
|
|
1420
|
+
compileSQL: { [compileSql.name]: getSelectOneStruct(compileSql) },
|
|
1421
|
+
});
|
|
1422
|
+
expect(m).modelCompiled();
|
|
1423
|
+
const s = m.sqlBlocks[0];
|
|
1424
|
+
expect(s.location).isLocationIn(source.locations[0], source.code);
|
|
1425
|
+
}
|
|
1341
1426
|
});
|
|
1342
1427
|
test("location of renamed field", () => {
|
|
1343
1428
|
const source = (0, test_translator_1.markSource) `
|
|
@@ -1346,7 +1431,7 @@ describe("source locations", () => {
|
|
|
1346
1431
|
}
|
|
1347
1432
|
`;
|
|
1348
1433
|
const m = new BetaModel(source.code);
|
|
1349
|
-
expect(m).
|
|
1434
|
+
expect(m).modelCompiled();
|
|
1350
1435
|
const na = (0, test_translator_1.getExplore)(m.modelDef, "na");
|
|
1351
1436
|
const bbool = (0, test_translator_1.getField)(na, "bbool");
|
|
1352
1437
|
expect(bbool.location).toMatchObject(source.locations[0]);
|
|
@@ -1358,7 +1443,7 @@ describe("source locations", () => {
|
|
|
1358
1443
|
}
|
|
1359
1444
|
`;
|
|
1360
1445
|
const m = new BetaModel(source.code);
|
|
1361
|
-
expect(m).
|
|
1446
|
+
expect(m).modelCompiled();
|
|
1362
1447
|
const na = (0, test_translator_1.getExplore)(m.modelDef, "na");
|
|
1363
1448
|
const x = (0, test_translator_1.getField)(na, "x");
|
|
1364
1449
|
expect(x.location).toMatchObject(source.locations[0]);
|
|
@@ -1370,7 +1455,7 @@ describe("source locations", () => {
|
|
|
1370
1455
|
}
|
|
1371
1456
|
`;
|
|
1372
1457
|
const m = new BetaModel(source.code);
|
|
1373
|
-
expect(m).
|
|
1458
|
+
expect(m).modelCompiled();
|
|
1374
1459
|
const na = (0, test_translator_1.getExplore)(m.modelDef, "na");
|
|
1375
1460
|
const x = (0, test_translator_1.getField)(na, "x");
|
|
1376
1461
|
expect(x.location).toMatchObject(source.locations[0]);
|
|
@@ -1385,21 +1470,20 @@ describe("source locations", () => {
|
|
|
1385
1470
|
}
|
|
1386
1471
|
`;
|
|
1387
1472
|
const m = new BetaModel(source.code);
|
|
1388
|
-
expect(m).
|
|
1473
|
+
expect(m).modelCompiled();
|
|
1389
1474
|
const na = (0, test_translator_1.getExplore)(m.modelDef, "na");
|
|
1390
1475
|
const x = (0, test_translator_1.getJoinField)(na, "x");
|
|
1391
1476
|
const y = (0, test_translator_1.getField)(x, "y");
|
|
1392
1477
|
expect(y.location).toMatchObject(source.locations[0]);
|
|
1393
1478
|
});
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
});
|
|
1479
|
+
// Since """ strings are not single tokens, I don't know how to do this.
|
|
1480
|
+
// test("multi line sql block token span is correct", () => {
|
|
1481
|
+
// const sqlSource = `sql: { select: """// line 0\n//line 1\n// line 2""" }`;
|
|
1482
|
+
// const m = new BetaModel(sqlSource);
|
|
1483
|
+
// expect(m).not.modelParsed();
|
|
1484
|
+
// const errList = m.errors().errors;
|
|
1485
|
+
// expect(errList[0].at?.range.end).toEqual({ line: 2, character: 11 });
|
|
1486
|
+
// });
|
|
1403
1487
|
test("undefined query location", badModel((0, test_translator_1.markSource) `query: ${"-> xyz"}`, "Reference to undefined query 'xyz'"));
|
|
1404
1488
|
test("undefined field reference", badModel((0, test_translator_1.markSource) `query: a -> { group_by: ${"xyz"} }`, "'xyz' is not defined"));
|
|
1405
1489
|
test("bad query", badModel((0, test_translator_1.markSource) `query: a -> { group_by: astr; ${"project: *"} }`, "project: not legal in grouping query"));
|
|
@@ -1413,7 +1497,7 @@ describe("source references", () => {
|
|
|
1413
1497
|
query: ${"na"} -> { project: * }
|
|
1414
1498
|
`;
|
|
1415
1499
|
const m = new BetaModel(source.code);
|
|
1416
|
-
expect(m).
|
|
1500
|
+
expect(m).modelCompiled();
|
|
1417
1501
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1418
1502
|
location: source.locations[1],
|
|
1419
1503
|
type: "exploreReference",
|
|
@@ -1431,7 +1515,7 @@ describe("source references", () => {
|
|
|
1431
1515
|
query: t -> ${"q"}
|
|
1432
1516
|
`;
|
|
1433
1517
|
const m = new BetaModel(source.code);
|
|
1434
|
-
expect(m).
|
|
1518
|
+
expect(m).modelCompiled();
|
|
1435
1519
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1436
1520
|
location: source.locations[1],
|
|
1437
1521
|
type: "fieldReference",
|
|
@@ -1447,7 +1531,7 @@ describe("source references", () => {
|
|
|
1447
1531
|
query: na -> ${"x"}
|
|
1448
1532
|
`;
|
|
1449
1533
|
const m = new BetaModel(source.code);
|
|
1450
|
-
expect(m).
|
|
1534
|
+
expect(m).modelCompiled();
|
|
1451
1535
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1452
1536
|
location: source.locations[1],
|
|
1453
1537
|
type: "fieldReference",
|
|
@@ -1459,26 +1543,29 @@ describe("source references", () => {
|
|
|
1459
1543
|
});
|
|
1460
1544
|
test("reference to sql block", () => {
|
|
1461
1545
|
const source = (0, test_translator_1.markSource) `
|
|
1462
|
-
sql:
|
|
1546
|
+
${`sql: s is {select:"""SELECT 1 as one"""}`}
|
|
1463
1547
|
explore: na is from_sql(${"s"})
|
|
1464
1548
|
`;
|
|
1465
1549
|
const m = new BetaModel(source.code);
|
|
1466
|
-
|
|
1467
|
-
const
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1550
|
+
expect(m).modelParsed();
|
|
1551
|
+
const compileSql = m.translate().compileSQL;
|
|
1552
|
+
expect(compileSql).toBeDefined();
|
|
1553
|
+
if (compileSql) {
|
|
1554
|
+
m.update({
|
|
1555
|
+
compileSQL: { [compileSql.name]: getSelectOneStruct(compileSql) },
|
|
1556
|
+
});
|
|
1557
|
+
expect(m).modelCompiled();
|
|
1558
|
+
const ref = m.referenceAt(pos(source.locations[1]));
|
|
1559
|
+
expect(ref).toMatchObject({
|
|
1560
|
+
location: source.locations[1],
|
|
1561
|
+
type: "sqlBlockReference",
|
|
1562
|
+
text: "s",
|
|
1563
|
+
definition: {
|
|
1564
|
+
...getSelectOneStruct(compileSql),
|
|
1565
|
+
location: source.locations[0],
|
|
1566
|
+
},
|
|
1567
|
+
});
|
|
1568
|
+
}
|
|
1482
1569
|
});
|
|
1483
1570
|
test("reference to query in from", () => {
|
|
1484
1571
|
const source = (0, test_translator_1.markSource) `
|
|
@@ -1486,7 +1573,7 @@ describe("source references", () => {
|
|
|
1486
1573
|
explore: na is from(-> ${"q"})
|
|
1487
1574
|
`;
|
|
1488
1575
|
const m = new BetaModel(source.code);
|
|
1489
|
-
expect(m).
|
|
1576
|
+
expect(m).modelCompiled();
|
|
1490
1577
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1491
1578
|
location: source.locations[1],
|
|
1492
1579
|
type: "queryReference",
|
|
@@ -1502,7 +1589,7 @@ describe("source references", () => {
|
|
|
1502
1589
|
query: q2 is -> ${"q"} -> { project: * }
|
|
1503
1590
|
`;
|
|
1504
1591
|
const m = new BetaModel(source.code);
|
|
1505
|
-
expect(m).
|
|
1592
|
+
expect(m).modelCompiled();
|
|
1506
1593
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1507
1594
|
location: source.locations[1],
|
|
1508
1595
|
type: "queryReference",
|
|
@@ -1518,7 +1605,7 @@ describe("source references", () => {
|
|
|
1518
1605
|
query: q2 is -> ${"q"} { limit: 10 }
|
|
1519
1606
|
`;
|
|
1520
1607
|
const m = new BetaModel(source.code);
|
|
1521
|
-
expect(m).
|
|
1608
|
+
expect(m).modelCompiled();
|
|
1522
1609
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1523
1610
|
location: source.locations[1],
|
|
1524
1611
|
type: "queryReference",
|
|
@@ -1534,7 +1621,7 @@ describe("source references", () => {
|
|
|
1534
1621
|
query: na -> { project: bbool is not ${"abool"} }
|
|
1535
1622
|
`;
|
|
1536
1623
|
const m = new BetaModel(source.code);
|
|
1537
|
-
expect(m).
|
|
1624
|
+
expect(m).modelCompiled();
|
|
1538
1625
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1539
1626
|
location: source.locations[1],
|
|
1540
1627
|
type: "fieldReference",
|
|
@@ -1552,7 +1639,7 @@ describe("source references", () => {
|
|
|
1552
1639
|
query: na -> { project: ${"`name`"} }
|
|
1553
1640
|
`;
|
|
1554
1641
|
const m = new BetaModel(source.code);
|
|
1555
|
-
expect(m).
|
|
1642
|
+
expect(m).modelCompiled();
|
|
1556
1643
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1557
1644
|
location: source.locations[1],
|
|
1558
1645
|
type: "fieldReference",
|
|
@@ -1571,7 +1658,7 @@ describe("source references", () => {
|
|
|
1571
1658
|
query: na -> { project: bstr is self.${"astr"} }
|
|
1572
1659
|
`;
|
|
1573
1660
|
const m = new BetaModel(source.code);
|
|
1574
|
-
expect(m).
|
|
1661
|
+
expect(m).modelCompiled();
|
|
1575
1662
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1576
1663
|
location: source.locations[1],
|
|
1577
1664
|
type: "fieldReference",
|
|
@@ -1589,7 +1676,7 @@ describe("source references", () => {
|
|
|
1589
1676
|
query: na -> { project: bstr is ${"self"}.astr }
|
|
1590
1677
|
`;
|
|
1591
1678
|
const m = new BetaModel(source.code);
|
|
1592
|
-
expect(m).
|
|
1679
|
+
expect(m).modelCompiled();
|
|
1593
1680
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1594
1681
|
location: source.locations[1],
|
|
1595
1682
|
type: "joinReference",
|
|
@@ -1604,7 +1691,7 @@ describe("source references", () => {
|
|
|
1604
1691
|
query: ${"table('aTable')"} -> { group_by: ${"abool"} }
|
|
1605
1692
|
`;
|
|
1606
1693
|
const m = new BetaModel(source.code);
|
|
1607
|
-
expect(m).
|
|
1694
|
+
expect(m).modelCompiled();
|
|
1608
1695
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1609
1696
|
location: source.locations[1],
|
|
1610
1697
|
type: "fieldReference",
|
|
@@ -1620,7 +1707,7 @@ describe("source references", () => {
|
|
|
1620
1707
|
query: na -> { project: ${"abool"} }
|
|
1621
1708
|
`;
|
|
1622
1709
|
const m = new BetaModel(source.code);
|
|
1623
|
-
expect(m).
|
|
1710
|
+
expect(m).modelCompiled();
|
|
1624
1711
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1625
1712
|
location: source.locations[1],
|
|
1626
1713
|
type: "fieldReference",
|
|
@@ -1638,7 +1725,7 @@ describe("source references", () => {
|
|
|
1638
1725
|
}
|
|
1639
1726
|
`;
|
|
1640
1727
|
const m = new BetaModel(source.code);
|
|
1641
|
-
expect(m).
|
|
1728
|
+
expect(m).modelCompiled();
|
|
1642
1729
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1643
1730
|
location: source.locations[1],
|
|
1644
1731
|
type: "fieldReference",
|
|
@@ -1656,7 +1743,7 @@ describe("source references", () => {
|
|
|
1656
1743
|
}
|
|
1657
1744
|
`;
|
|
1658
1745
|
const m = new BetaModel(source.code);
|
|
1659
|
-
expect(m).
|
|
1746
|
+
expect(m).modelCompiled();
|
|
1660
1747
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1661
1748
|
location: source.locations[1],
|
|
1662
1749
|
type: "fieldReference",
|
|
@@ -1674,7 +1761,7 @@ describe("source references", () => {
|
|
|
1674
1761
|
}
|
|
1675
1762
|
`;
|
|
1676
1763
|
const m = new BetaModel(source.code);
|
|
1677
|
-
expect(m).
|
|
1764
|
+
expect(m).modelCompiled();
|
|
1678
1765
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1679
1766
|
location: source.locations[1],
|
|
1680
1767
|
type: "fieldReference",
|
|
@@ -1692,7 +1779,7 @@ describe("source references", () => {
|
|
|
1692
1779
|
}
|
|
1693
1780
|
`;
|
|
1694
1781
|
const m = new BetaModel(source.code);
|
|
1695
|
-
expect(m).
|
|
1782
|
+
expect(m).modelCompiled();
|
|
1696
1783
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1697
1784
|
location: source.locations[1],
|
|
1698
1785
|
type: "fieldReference",
|
|
@@ -1710,7 +1797,7 @@ describe("source references", () => {
|
|
|
1710
1797
|
}
|
|
1711
1798
|
`;
|
|
1712
1799
|
const m = new BetaModel(source.code);
|
|
1713
|
-
expect(m).
|
|
1800
|
+
expect(m).modelCompiled();
|
|
1714
1801
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1715
1802
|
location: source.locations[1],
|
|
1716
1803
|
type: "fieldReference",
|
|
@@ -1728,7 +1815,7 @@ describe("source references", () => {
|
|
|
1728
1815
|
}
|
|
1729
1816
|
`;
|
|
1730
1817
|
const m = new BetaModel(source.code);
|
|
1731
|
-
expect(m).
|
|
1818
|
+
expect(m).modelCompiled();
|
|
1732
1819
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1733
1820
|
location: source.locations[1],
|
|
1734
1821
|
type: "fieldReference",
|
|
@@ -1746,7 +1833,7 @@ describe("source references", () => {
|
|
|
1746
1833
|
}
|
|
1747
1834
|
`;
|
|
1748
1835
|
const m = new BetaModel(source.code);
|
|
1749
|
-
expect(m).
|
|
1836
|
+
expect(m).modelCompiled();
|
|
1750
1837
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1751
1838
|
location: source.locations[1],
|
|
1752
1839
|
type: "fieldReference",
|
|
@@ -1762,7 +1849,7 @@ describe("source references", () => {
|
|
|
1762
1849
|
query: na -> { aggregate: ai_sum is ${"ai"}.sum() }
|
|
1763
1850
|
`;
|
|
1764
1851
|
const m = new BetaModel(source.code);
|
|
1765
|
-
expect(m).
|
|
1852
|
+
expect(m).modelCompiled();
|
|
1766
1853
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1767
1854
|
location: source.locations[1],
|
|
1768
1855
|
type: "fieldReference",
|
|
@@ -1783,7 +1870,7 @@ describe("source references", () => {
|
|
|
1783
1870
|
query: na -> { aggregate: ai_sum is ${"self"}.sum(self.ai) }
|
|
1784
1871
|
`;
|
|
1785
1872
|
const m = new BetaModel(source.code);
|
|
1786
|
-
expect(m).
|
|
1873
|
+
expect(m).modelCompiled();
|
|
1787
1874
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1788
1875
|
location: source.locations[1],
|
|
1789
1876
|
type: "joinReference",
|
|
@@ -1801,7 +1888,7 @@ describe("source references", () => {
|
|
|
1801
1888
|
query: na -> { aggregate: ai_sum is self.sum(${"self"}.ai) }
|
|
1802
1889
|
`;
|
|
1803
1890
|
const m = new BetaModel(source.code);
|
|
1804
|
-
expect(m).
|
|
1891
|
+
expect(m).modelCompiled();
|
|
1805
1892
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1806
1893
|
location: source.locations[1],
|
|
1807
1894
|
type: "joinReference",
|
|
@@ -1819,7 +1906,7 @@ describe("source references", () => {
|
|
|
1819
1906
|
}
|
|
1820
1907
|
`;
|
|
1821
1908
|
const m = new BetaModel(source.code);
|
|
1822
|
-
expect(m).
|
|
1909
|
+
expect(m).modelCompiled();
|
|
1823
1910
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1824
1911
|
location: source.locations[1],
|
|
1825
1912
|
type: "exploreReference",
|
|
@@ -1835,7 +1922,7 @@ describe("source references", () => {
|
|
|
1835
1922
|
query: na -> { aggregate: ai_sum is sum(${"ai"}) }
|
|
1836
1923
|
`;
|
|
1837
1924
|
const m = new BetaModel(source.code);
|
|
1838
|
-
expect(m).
|
|
1925
|
+
expect(m).modelCompiled();
|
|
1839
1926
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1840
1927
|
location: source.locations[1],
|
|
1841
1928
|
type: "fieldReference",
|
|
@@ -1852,7 +1939,7 @@ describe("source references", () => {
|
|
|
1852
1939
|
}
|
|
1853
1940
|
`;
|
|
1854
1941
|
const m = new BetaModel(source.code);
|
|
1855
|
-
expect(m).
|
|
1942
|
+
expect(m).modelCompiled();
|
|
1856
1943
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1857
1944
|
location: source.locations[1],
|
|
1858
1945
|
type: "fieldReference",
|
|
@@ -1870,7 +1957,7 @@ describe("source references", () => {
|
|
|
1870
1957
|
}
|
|
1871
1958
|
`;
|
|
1872
1959
|
const m = new BetaModel(source.code);
|
|
1873
|
-
expect(m).
|
|
1960
|
+
expect(m).modelCompiled();
|
|
1874
1961
|
expect(m.referenceAt(pos(source.locations[1]))).toMatchObject({
|
|
1875
1962
|
location: source.locations[1],
|
|
1876
1963
|
type: "fieldReference",
|
|
@@ -1889,27 +1976,26 @@ describe("translation need error locations", () => {
|
|
|
1889
1976
|
m.update({
|
|
1890
1977
|
errors: { urls: { [(result.urls || [])[0]]: "Bad file!" } },
|
|
1891
1978
|
});
|
|
1892
|
-
expect(m).not.
|
|
1979
|
+
expect(m).not.modelParsed();
|
|
1893
1980
|
const errList = m.errors().errors;
|
|
1894
|
-
expect(errList[0].at).
|
|
1981
|
+
expect(errList[0].at).isLocationIn(source.locations[0], source.code);
|
|
1895
1982
|
return undefined;
|
|
1896
1983
|
});
|
|
1897
1984
|
test("sql struct error location", () => {
|
|
1898
1985
|
const source = (0, test_translator_1.markSource) `
|
|
1899
|
-
sql: bad_sql is
|
|
1900
|
-
query:
|
|
1986
|
+
sql: bad_sql is {select: ${'"""BAD_SQL"""'}}
|
|
1987
|
+
query: from_sql(bad_sql) -> { project: * }
|
|
1901
1988
|
`;
|
|
1902
1989
|
const m = new BetaModel(source.code);
|
|
1903
|
-
|
|
1904
|
-
m.
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
}
|
|
1908
|
-
}
|
|
1909
|
-
expect(m).not.
|
|
1990
|
+
expect(m).modelParsed();
|
|
1991
|
+
const req = m.translate().compileSQL;
|
|
1992
|
+
expect(req).toBeDefined();
|
|
1993
|
+
if (req) {
|
|
1994
|
+
m.update({ errors: { compileSQL: { [req.name]: "Bad SQL!" } } });
|
|
1995
|
+
}
|
|
1996
|
+
expect(m).not.modelCompiled();
|
|
1910
1997
|
const errList = m.errors().errors;
|
|
1911
|
-
expect(errList[0].at).
|
|
1912
|
-
return undefined;
|
|
1998
|
+
expect(errList[0].at).isLocationIn(source.locations[0], source.code);
|
|
1913
1999
|
});
|
|
1914
2000
|
test("table struct error location", () => {
|
|
1915
2001
|
const source = (0, test_translator_1.markSource) `
|
|
@@ -1922,9 +2008,9 @@ describe("translation need error locations", () => {
|
|
|
1922
2008
|
tables: { [(result.tables || [])[0]]: "Bad table!" },
|
|
1923
2009
|
},
|
|
1924
2010
|
});
|
|
1925
|
-
expect(m).not.
|
|
2011
|
+
expect(m).not.modelParsed();
|
|
1926
2012
|
const errList = m.errors().errors;
|
|
1927
|
-
expect(errList[0].at).
|
|
2013
|
+
expect(errList[0].at).isLocationIn(source.locations[0], source.code);
|
|
1928
2014
|
return undefined;
|
|
1929
2015
|
});
|
|
1930
2016
|
});
|
|
@@ -1990,7 +2076,7 @@ describe("pipeline comprehension", () => {
|
|
|
1990
2076
|
}
|
|
1991
2077
|
`;
|
|
1992
2078
|
const m = new BetaModel(src);
|
|
1993
|
-
expect(m).
|
|
2079
|
+
expect(m).modelCompiled();
|
|
1994
2080
|
const s2 = m.getQuery("s2");
|
|
1995
2081
|
expect(s2 === null || s2 === void 0 ? void 0 : s2.pipeline.length).toBe(2);
|
|
1996
2082
|
});
|