@malloydata/malloy 0.0.88-dev231002231014 → 0.0.88-dev231003001139
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/dialect/dialect_map.js +1 -0
- package/dist/dialect/functions/util.d.ts +1 -0
- package/dist/lang/ast/elements/define-query.d.ts +3 -3
- package/dist/lang/ast/elements/define-query.js +9 -4
- package/dist/lang/ast/elements/define-source.d.ts +3 -3
- package/dist/lang/ast/elements/define-source.js +12 -4
- package/dist/lang/ast/elements/pipeline-desc.d.ts +1 -0
- package/dist/lang/ast/elements/pipeline-desc.js +3 -0
- package/dist/lang/ast/elements/source-query-nodes.d.ts +72 -0
- package/dist/lang/ast/elements/source-query-nodes.js +368 -0
- package/dist/lang/ast/elements/source-query.d.ts +11 -0
- package/dist/lang/ast/{query-elements/run-query.js → elements/source-query.js} +32 -21
- package/dist/lang/ast/index.d.ts +2 -2
- package/dist/lang/ast/index.js +2 -2
- package/dist/lang/ast/query-elements/anonymous-query.d.ts +3 -3
- package/dist/lang/ast/query-elements/anonymous-query.js +15 -8
- package/dist/lang/ast/query-elements/existing-query.js +1 -1
- package/dist/lang/ast/query-items/field-references.d.ts +4 -0
- package/dist/lang/ast/query-items/field-references.js +11 -1
- package/dist/lang/ast/query-items/typecheck_utils.js +5 -5
- package/dist/lang/ast/query-properties/joins.d.ts +7 -5
- package/dist/lang/ast/query-properties/joins.js +22 -8
- package/dist/lang/ast/sources/sql-source.js +5 -0
- package/dist/lang/ast/sql-elements/sql-string.d.ts +2 -2
- package/dist/lang/ast/sql-elements/sql-string.js +19 -9
- package/dist/lang/ast/types/malloy-element.d.ts +3 -1
- package/dist/lang/ast/types/malloy-element.js +16 -5
- package/dist/lang/lib/Malloy/MalloyParser.d.ts +179 -184
- package/dist/lang/lib/Malloy/MalloyParser.js +3141 -2928
- package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +147 -199
- package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +88 -120
- package/dist/lang/malloy-to-ast.d.ts +16 -15
- package/dist/lang/malloy-to-ast.js +147 -141
- package/dist/lang/parse-tree-walkers/document-symbol-walker.js +1 -1
- package/dist/lang/parse-utils.js +2 -2
- package/dist/lang/test/annotation.spec.js +35 -46
- package/dist/lang/test/document-symbol-walker.spec.js +2 -2
- package/dist/lang/test/expressions.spec.js +16 -16
- package/dist/lang/test/imports.spec.js +10 -8
- package/dist/lang/test/literals.spec.js +4 -4
- package/dist/lang/test/locations.spec.js +82 -80
- package/dist/lang/test/parse-expects.js +5 -1
- package/dist/lang/test/parse.spec.js +173 -117
- package/dist/lang/test/query.spec.js +199 -203
- package/dist/lang/test/source.spec.js +54 -45
- package/dist/lang/test/sql-block.spec.js +19 -12
- package/dist/lang/test/test-translator.js +8 -5
- package/dist/malloy.js +2 -2
- package/dist/model/malloy_query.js +3 -0
- package/dist/model/malloy_types.d.ts +1 -0
- package/package.json +1 -2
- package/dist/lang/ast/query-elements/run-query.d.ts +0 -13
- package/dist/lang/ast/sources/named-source-or-query.d.ts +0 -10
- package/dist/lang/ast/sources/named-source-or-query.js +0 -71
|
@@ -54,6 +54,12 @@ const ast_1 = require("./ast");
|
|
|
54
54
|
const parse_utils_1 = require("./parse-utils");
|
|
55
55
|
const malloy_types_1 = require("../model/malloy_types");
|
|
56
56
|
const tags_1 = require("../tags");
|
|
57
|
+
class ErrorNode extends ast.SourceQueryNode {
|
|
58
|
+
constructor() {
|
|
59
|
+
super(...arguments);
|
|
60
|
+
this.elementType = 'parseErrorSourceQuery';
|
|
61
|
+
}
|
|
62
|
+
}
|
|
57
63
|
class IgnoredElement extends ast.MalloyElement {
|
|
58
64
|
constructor(src) {
|
|
59
65
|
super();
|
|
@@ -71,6 +77,11 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
71
77
|
this.parseInfo = parseInfo;
|
|
72
78
|
this.msgLog = msgLog;
|
|
73
79
|
this.compilerFlags = new tags_1.Tag();
|
|
80
|
+
// for (const flag of DEFAULT_COMPILER_FLAGS) {
|
|
81
|
+
// const withNewTag = Tag.fromTagline(flag, this.compilerFlags);
|
|
82
|
+
// this.compilerFlags = withNewTag.tag;
|
|
83
|
+
// }
|
|
84
|
+
this.compilerFlags = new tags_1.Tag();
|
|
74
85
|
}
|
|
75
86
|
/**
|
|
76
87
|
* Mostly used to flag a case where the grammar and the type system are
|
|
@@ -115,7 +126,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
115
126
|
acceptable.push(checked);
|
|
116
127
|
}
|
|
117
128
|
else if (!(el instanceof IgnoredElement)) {
|
|
118
|
-
this.astError(el, `
|
|
129
|
+
this.astError(el, `Parser enountered unexpected statement type '${el.elementType}' when it needed '${desc}'`);
|
|
119
130
|
}
|
|
120
131
|
}
|
|
121
132
|
return acceptable;
|
|
@@ -195,13 +206,6 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
195
206
|
// string: shortString | sqlString; So this will never happen
|
|
196
207
|
return '';
|
|
197
208
|
}
|
|
198
|
-
getSource(pcx) {
|
|
199
|
-
const source = this.visit(pcx);
|
|
200
|
-
if (source instanceof ast.Source) {
|
|
201
|
-
return source;
|
|
202
|
-
}
|
|
203
|
-
throw this.internalError(pcx, `Source expected, but ${source.elementType} found`);
|
|
204
|
-
}
|
|
205
209
|
makeSqlString(pcx, sqlStr) {
|
|
206
210
|
for (const part of pcx.sqlInterpolation()) {
|
|
207
211
|
if (part.CLOSE_CODE() && this.m4WarningsEnabled()) {
|
|
@@ -265,93 +269,34 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
265
269
|
return defList;
|
|
266
270
|
}
|
|
267
271
|
visitSourceDefinition(pcx) {
|
|
268
|
-
const
|
|
272
|
+
const exploreExpr = this.visit(pcx.sqExplore());
|
|
273
|
+
const exploreDef = new ast.DefineSource((0, parse_utils_1.getId)(pcx.sourceNameDef()), exploreExpr instanceof ast.SourceQueryNode ? exploreExpr : undefined, true, []);
|
|
269
274
|
const notes = this.getNotes(pcx.tags()).concat(this.getIsNotes(pcx.isDefine()));
|
|
270
275
|
exploreDef.extendNote({ notes });
|
|
271
276
|
return this.astAt(exploreDef, pcx);
|
|
272
277
|
}
|
|
273
|
-
visitQueryFromSQLSource(pcx) {
|
|
274
|
-
const query = new ast.FullQuery(this.visitSqlSource(pcx.sqlSource()));
|
|
275
|
-
return this.astAt(query, pcx);
|
|
276
|
-
}
|
|
277
|
-
visitQueryFromSource(pcx) {
|
|
278
|
-
const root = this.visitUnextendableSource(pcx.unextendableSource());
|
|
279
|
-
const query = new ast.FullQuery(root);
|
|
280
|
-
query.addSegments(...this.getSegments(pcx.pipeElement()));
|
|
281
|
-
return this.astAt(query, pcx);
|
|
282
|
-
}
|
|
283
278
|
getQueryRefinements(pcx) {
|
|
284
279
|
const properties = this.astAt(this.visitQueryProperties(pcx.queryProperties()), pcx);
|
|
285
|
-
if (
|
|
286
|
-
this.
|
|
280
|
+
if (pcx.REFINE()) {
|
|
281
|
+
this.contextError(pcx, 'The experimental "refine" operator is deprecated, use the "+" operator', 'warn');
|
|
287
282
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
visitRefinedQuery(pcx) {
|
|
291
|
-
const base = this.visit(pcx.refinableQuery());
|
|
292
|
-
if (ast.isQueryElement(base)) {
|
|
293
|
-
const rcx = pcx.queryRefinement();
|
|
294
|
-
if (rcx) {
|
|
295
|
-
const properties = this.getQueryRefinements(rcx);
|
|
296
|
-
base.refineWith(properties);
|
|
297
|
-
}
|
|
298
|
-
return base;
|
|
299
|
-
}
|
|
300
|
-
throw this.internalError(pcx, `Query expected, but ${base.elementType} found`);
|
|
301
|
-
}
|
|
302
|
-
visitQueryByTurtleName(pcx) {
|
|
303
|
-
const source = this.visitUnextendableSource(pcx.unextendableSource());
|
|
304
|
-
const query = new ast.FullQuery(source);
|
|
305
|
-
query.turtleName = this.getFieldName(pcx);
|
|
306
|
-
return this.astAt(query, pcx);
|
|
307
|
-
}
|
|
308
|
-
visitQueryByName(pcx) {
|
|
309
|
-
const query = new ast.ExistingQuery();
|
|
310
|
-
query.head = this.getModelEntryName(pcx);
|
|
311
|
-
const res = this.astAt(query, pcx);
|
|
312
|
-
if (this.m4WarningsEnabled() && pcx.ARROW()) {
|
|
313
|
-
this.astError(res, 'Leading arrow (`->`) when referencing a query is deprecated; remove the arrow', 'warn');
|
|
283
|
+
else if (!pcx.refineOperator()) {
|
|
284
|
+
this.contextError(pcx, 'Implicit query refinement is deprecated, use the `+` operator', 'warn');
|
|
314
285
|
}
|
|
315
|
-
return
|
|
286
|
+
return properties;
|
|
316
287
|
}
|
|
317
288
|
getSourceExtensions(pcx) {
|
|
318
289
|
const extensions = pcx === null || pcx === void 0 ? void 0 : pcx.exploreProperties();
|
|
319
290
|
const sourceDesc = this.astAt(this.visitExploreProperties(extensions), pcx);
|
|
320
|
-
if (this.m4WarningsEnabled()
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
return sourceDesc;
|
|
324
|
-
}
|
|
325
|
-
visitUnextendableSource(pcx) {
|
|
326
|
-
const unextendedSource = this.visit(pcx.extendableSource());
|
|
327
|
-
if (unextendedSource instanceof ast.Source) {
|
|
328
|
-
const ecx = pcx.sourceExtension();
|
|
329
|
-
if (ecx) {
|
|
330
|
-
const sourceDesc = this.getSourceExtensions(ecx);
|
|
331
|
-
return new ast.RefinedSource(unextendedSource, sourceDesc);
|
|
291
|
+
if (this.m4WarningsEnabled()) {
|
|
292
|
+
if (pcx.refineOperator()) {
|
|
293
|
+
this.contextError(pcx, 'Source extension with "+" is deprecated, use the "extend" operator', 'warn');
|
|
332
294
|
}
|
|
333
|
-
else {
|
|
334
|
-
|
|
295
|
+
else if (pcx.EXTEND() === undefined && this.m4WarningsEnabled()) {
|
|
296
|
+
this.contextError(pcx, 'Implicit source extension is deprecated, use the `extend` operator.', 'warn');
|
|
335
297
|
}
|
|
336
298
|
}
|
|
337
|
-
|
|
338
|
-
}
|
|
339
|
-
visitNormalQuery(pcx) {
|
|
340
|
-
const query = this.visit(pcx.unrefinableQuery());
|
|
341
|
-
if (ast.isQueryElement(query)) {
|
|
342
|
-
query.addSegments(...this.getSegments(pcx.pipeElement()));
|
|
343
|
-
return this.astAt(query, pcx);
|
|
344
|
-
}
|
|
345
|
-
throw this.internalError(pcx, `Expected query, but ${query.elementType} found`);
|
|
346
|
-
}
|
|
347
|
-
visitExtendedQuery(pcx) {
|
|
348
|
-
const query = this.visit(pcx.query());
|
|
349
|
-
if (!ast.isQueryElement(query)) {
|
|
350
|
-
throw this.internalError(pcx, `Query expected, but ${query.elementType} found`);
|
|
351
|
-
}
|
|
352
|
-
const source = new ast.QuerySource(query);
|
|
353
|
-
const sourceDesc = this.getSourceExtensions(pcx.sourceExtension());
|
|
354
|
-
return this.astAt(new ast.RefinedSource(source, sourceDesc), pcx);
|
|
299
|
+
return sourceDesc;
|
|
355
300
|
}
|
|
356
301
|
visitExploreProperties(pcx) {
|
|
357
302
|
const filterCx = pcx.filterShortcut();
|
|
@@ -376,15 +321,8 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
376
321
|
const tablePath = this.getPlainString(pcx.tablePath());
|
|
377
322
|
return this.astAt(new ast.TableMethodSource(connectionName, tablePath), pcx);
|
|
378
323
|
}
|
|
379
|
-
|
|
380
|
-
const
|
|
381
|
-
if (result instanceof ast_1.TableSource) {
|
|
382
|
-
return result;
|
|
383
|
-
}
|
|
384
|
-
throw this.internalError(pcx, `Table source matched, but ${result.elementType} found`);
|
|
385
|
-
}
|
|
386
|
-
visitSQLSourceName(pcx) {
|
|
387
|
-
const name = this.getModelEntryName(pcx.sqlExploreNameRef());
|
|
324
|
+
getLegacySQLSouce(pcx) {
|
|
325
|
+
const name = this.getModelEntryName(pcx);
|
|
388
326
|
const res = this.astAt(new ast.FromSQLSource(name), pcx);
|
|
389
327
|
if (this.m4WarningsEnabled()) {
|
|
390
328
|
this.astError(res, '`from_sql` is deprecated; use `connection_name.sql(...)` as a source directly', 'warn');
|
|
@@ -406,17 +344,6 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
406
344
|
const expr = new ast.SQLSource(connectionName, sqlStr);
|
|
407
345
|
return this.astAt(expr, pcx);
|
|
408
346
|
}
|
|
409
|
-
visitQuerySource(pcx) {
|
|
410
|
-
const query = this.visit(pcx.query());
|
|
411
|
-
if (ast.isQueryElement(query)) {
|
|
412
|
-
const el = this.astAt(new ast.QuerySource(query), pcx);
|
|
413
|
-
if (this.m4WarningsEnabled()) {
|
|
414
|
-
this.astError(el, '`from(some_query)` is deprecated; use `some_query` directly', 'warn');
|
|
415
|
-
}
|
|
416
|
-
return el;
|
|
417
|
-
}
|
|
418
|
-
throw this.internalError(pcx, `Expect query definition, got a '${query.elementType}'`);
|
|
419
|
-
}
|
|
420
347
|
visitDefJoinMany(pcx) {
|
|
421
348
|
const joinList = this.getJoinList(pcx.joinList());
|
|
422
349
|
const joins = [];
|
|
@@ -476,11 +403,11 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
476
403
|
}
|
|
477
404
|
getJoinSource(name, ecx) {
|
|
478
405
|
if (ecx) {
|
|
479
|
-
const joinSrc = this.
|
|
406
|
+
const joinSrc = this.getSqExpr(ecx.sqExpr());
|
|
480
407
|
const notes = this.getNotes(ecx._before_is).concat(this.getNotes(ecx._after_is));
|
|
481
408
|
return { joinFrom: joinSrc, notes };
|
|
482
409
|
}
|
|
483
|
-
return { joinFrom: new ast.
|
|
410
|
+
return { joinFrom: new ast.SQReference(name), notes: [] };
|
|
484
411
|
}
|
|
485
412
|
visitQueryJoinStatement(pcx) {
|
|
486
413
|
const result = this.astAt(this.visit(pcx.joinStatement()), pcx);
|
|
@@ -660,7 +587,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
660
587
|
.queryFieldEntry()
|
|
661
588
|
.map(e => this.getQueryFieldEntry(e, makeFieldDef, makeFieldRef)), x => x instanceof ast.FieldReference || x instanceof ast.FieldDeclaration
|
|
662
589
|
? x
|
|
663
|
-
: false, '
|
|
590
|
+
: false, 'view field');
|
|
664
591
|
}
|
|
665
592
|
visitAggregateStatement(pcx) {
|
|
666
593
|
const agStmt = new ast.Aggregate(this.getQueryItems(pcx.queryFieldList(), ast.AggregateFieldDeclaration, ast.AggregateFieldReference));
|
|
@@ -851,9 +778,9 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
851
778
|
}
|
|
852
779
|
visitTopLevelQueryDef(pcx) {
|
|
853
780
|
const queryName = (0, parse_utils_1.getId)(pcx.queryName());
|
|
854
|
-
const queryExpr = this.visit(pcx.
|
|
855
|
-
|
|
856
|
-
|
|
781
|
+
const queryExpr = this.visit(pcx.sqExpr());
|
|
782
|
+
const notes = this.getNotes(pcx.tags()).concat(this.getIsNotes(pcx.isDefine()));
|
|
783
|
+
if (queryExpr instanceof ast.SourceQueryNode) {
|
|
857
784
|
const queryDef = new ast.DefineQuery(queryName, queryExpr);
|
|
858
785
|
queryDef.extendNote({ notes });
|
|
859
786
|
return this.astAt(queryDef, pcx);
|
|
@@ -862,28 +789,24 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
862
789
|
}
|
|
863
790
|
visitAnonymousQuery(pcx) {
|
|
864
791
|
const defCx = pcx.topLevelAnonQueryDef();
|
|
865
|
-
const query = this.
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
this.astError(theQuery, 'Anonymous `query:` statements are deprecated, use `run:` instead', 'warn');
|
|
873
|
-
}
|
|
874
|
-
return this.astAt(theQuery, pcx);
|
|
792
|
+
const query = this.getSqExpr(defCx.sqExpr());
|
|
793
|
+
const theQuery = this.astAt(new ast.AnonymousQuery(query), defCx);
|
|
794
|
+
const notes = this.getNotes(pcx.topLevelAnonQueryDef().tags());
|
|
795
|
+
const blockNotes = this.getNotes(pcx.tags());
|
|
796
|
+
theQuery.extendNote({ notes, blockNotes });
|
|
797
|
+
if (this.m4WarningsEnabled()) {
|
|
798
|
+
this.contextError(defCx, 'Anonymous `query:` statements are deprecated, use `run:` instead', 'warn');
|
|
875
799
|
}
|
|
876
|
-
|
|
800
|
+
return this.astAt(theQuery, pcx);
|
|
877
801
|
}
|
|
878
802
|
visitRunStatement(pcx) {
|
|
879
|
-
const
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
throw this.internalError(pcx, `Run query matched, but ${query.elementType} found`);
|
|
803
|
+
const defCx = pcx.topLevelAnonQueryDef();
|
|
804
|
+
const query = this.getSqExpr(defCx.sqExpr());
|
|
805
|
+
const theQuery = this.astAt(new ast.AnonymousQuery(query), defCx);
|
|
806
|
+
const notes = this.getNotes(pcx.topLevelAnonQueryDef().tags());
|
|
807
|
+
const blockNotes = this.getNotes(pcx.tags());
|
|
808
|
+
theQuery.extendNote({ notes, blockNotes });
|
|
809
|
+
return this.astAt(theQuery, pcx);
|
|
887
810
|
}
|
|
888
811
|
visitNestStatement(pcx) {
|
|
889
812
|
const nests = this.visitNestedQueryList(pcx.nestedQueryList());
|
|
@@ -1221,22 +1144,6 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
1221
1144
|
}
|
|
1222
1145
|
return new ast.Pick(picks);
|
|
1223
1146
|
}
|
|
1224
|
-
visitSourceFromNamedModelEntry(pcx) {
|
|
1225
|
-
const name = this.getModelEntryName(pcx.sourceID());
|
|
1226
|
-
// Parameters ... coming ...
|
|
1227
|
-
// const paramListCx = pcx.isParam();
|
|
1228
|
-
// if (paramListCx) {
|
|
1229
|
-
// const paramInit: Record<string, ast.ConstantSubExpression> = {};
|
|
1230
|
-
// for (const cx of paramListCx) {
|
|
1231
|
-
// const pName = this.identifer(cx.id());
|
|
1232
|
-
// const pVal = this.getFieldExpr(cx.isExpr().partialAllowedFieldExpr());
|
|
1233
|
-
// paramInit[pName] = new ast.ConstantSubExpression(pVal);
|
|
1234
|
-
// }
|
|
1235
|
-
// return this.astAt(new ast.NamedSource(name, paramInit), pcx);
|
|
1236
|
-
// }
|
|
1237
|
-
const source = new ast.NamedSourceOrQuery(name);
|
|
1238
|
-
return this.astAt(source, pcx);
|
|
1239
|
-
}
|
|
1240
1147
|
visitExprFilter(pcx) {
|
|
1241
1148
|
const filters = this.visit(pcx.filteredBy());
|
|
1242
1149
|
return new ast.ExprFilter(this.getFieldExpr(pcx.fieldExpr()), filters);
|
|
@@ -1347,6 +1254,105 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
1347
1254
|
const allNotes = this.getNotes(pcx);
|
|
1348
1255
|
return new ast.ObjectAnnotation(allNotes);
|
|
1349
1256
|
}
|
|
1257
|
+
visitSQAmbiguous(pcx) {
|
|
1258
|
+
const addCx = pcx.ambiguousModification();
|
|
1259
|
+
const plus = [];
|
|
1260
|
+
const filterCx = addCx.filterShortcut();
|
|
1261
|
+
if (filterCx) {
|
|
1262
|
+
plus.push(this.getFilterShortcut(filterCx));
|
|
1263
|
+
}
|
|
1264
|
+
for (const modifier of addCx.modEither()) {
|
|
1265
|
+
plus.push(this.visit(modifier));
|
|
1266
|
+
}
|
|
1267
|
+
const sqExpr = this.getSqExpr(pcx.sqExpr());
|
|
1268
|
+
const hasPlus = !!pcx.PLUS();
|
|
1269
|
+
return this.astAt(new ast.SQLegacyModify(sqExpr, plus, hasPlus, this.m4WarningsEnabled()), pcx);
|
|
1270
|
+
}
|
|
1271
|
+
visitSQID(pcx) {
|
|
1272
|
+
if (this.m4WarningsEnabled() && pcx.ARROW()) {
|
|
1273
|
+
this.contextError(pcx, 'Leading arrow (`->`) when referencing a query is deprecated; remove the arrow', 'warn');
|
|
1274
|
+
}
|
|
1275
|
+
const ref = this.getModelEntryName(pcx);
|
|
1276
|
+
return this.astAt(new ast.SQReference(ref), pcx.id());
|
|
1277
|
+
}
|
|
1278
|
+
getSqExpr(cx) {
|
|
1279
|
+
const result = this.visit(cx);
|
|
1280
|
+
if (result instanceof ast.SourceQueryNode) {
|
|
1281
|
+
return result;
|
|
1282
|
+
}
|
|
1283
|
+
this.contextError(cx, `Expected a source/query expression, not '${result.elementType}'`);
|
|
1284
|
+
return new ErrorNode();
|
|
1285
|
+
}
|
|
1286
|
+
visitSQExtendedSource(pcx) {
|
|
1287
|
+
const extendSrc = this.getSqExpr(pcx.sqExpr());
|
|
1288
|
+
const src = new ast.SQExtendedSource(extendSrc, this.getSourceExtensions(pcx.sourceExtension()));
|
|
1289
|
+
return this.astAt(src, pcx);
|
|
1290
|
+
}
|
|
1291
|
+
visitSQArrow(pcx) {
|
|
1292
|
+
const applyTo = this.getSqExpr(pcx.sqExpr());
|
|
1293
|
+
const viewParts = [];
|
|
1294
|
+
const headCx = pcx.leadSeg();
|
|
1295
|
+
const headId = (0, parse_utils_1.getOptionalId)(headCx);
|
|
1296
|
+
const headIdCx = headCx.id();
|
|
1297
|
+
if (headIdCx && headId) {
|
|
1298
|
+
viewParts.push(new ast.ViewFieldReference([
|
|
1299
|
+
this.astAt(new ast.FieldName(headId), headIdCx),
|
|
1300
|
+
]));
|
|
1301
|
+
const andRefined = headCx.queryRefinement();
|
|
1302
|
+
if (andRefined) {
|
|
1303
|
+
viewParts.push(this.getQueryRefinements(andRefined));
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
const qopCx = headCx.queryProperties();
|
|
1307
|
+
if (qopCx) {
|
|
1308
|
+
viewParts.push(this.visitQueryProperties(qopCx));
|
|
1309
|
+
}
|
|
1310
|
+
for (const seg of pcx.qSeg()) {
|
|
1311
|
+
const asQop = seg.queryProperties();
|
|
1312
|
+
if (asQop) {
|
|
1313
|
+
viewParts.push(this.visitQueryProperties(asQop));
|
|
1314
|
+
}
|
|
1315
|
+
const viewName = (0, parse_utils_1.getOptionalId)(seg);
|
|
1316
|
+
if (viewName) {
|
|
1317
|
+
viewParts.push(new ast.ViewFieldReference([new ast.FieldName(viewName)]));
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
const sqExpr = new ast.SQAppendView(applyTo, viewParts);
|
|
1321
|
+
return this.astAt(sqExpr, pcx);
|
|
1322
|
+
}
|
|
1323
|
+
visitSQRefinedQuery(pcx) {
|
|
1324
|
+
const refineThis = this.getSqExpr(pcx.sqExpr());
|
|
1325
|
+
const refine = pcx.queryRefinement();
|
|
1326
|
+
if (this.m4WarningsEnabled() && refine.REFINE()) {
|
|
1327
|
+
this.contextError(refine, 'The `refine` keyword is deprecated, use the `+` operator', 'warn');
|
|
1328
|
+
}
|
|
1329
|
+
const refined = new ast.SQRefinedQuery(refineThis, this.getQueryRefinements(refine));
|
|
1330
|
+
return this.astAt(refined, pcx);
|
|
1331
|
+
}
|
|
1332
|
+
visitSQFrom(pcx) {
|
|
1333
|
+
const fromThis = this.getSqExpr(pcx.sqExpr());
|
|
1334
|
+
if (pcx.FROM() && this.m4WarningsEnabled()) {
|
|
1335
|
+
this.contextError(pcx, '`from(some_query)` is deprecated; use `some_query` directly', 'warn');
|
|
1336
|
+
}
|
|
1337
|
+
return this.astAt(new ast.SQFrom(fromThis), pcx);
|
|
1338
|
+
}
|
|
1339
|
+
visitSQTable(pcx) {
|
|
1340
|
+
const theTable = this.visit(pcx.exploreTable());
|
|
1341
|
+
if (theTable instanceof ast_1.TableSource) {
|
|
1342
|
+
const sqTable = new ast.SQSourceWrapper(theTable);
|
|
1343
|
+
return this.astAt(sqTable, pcx);
|
|
1344
|
+
}
|
|
1345
|
+
return new ErrorNode();
|
|
1346
|
+
}
|
|
1347
|
+
visitSQLegacySQLBlock(pcx) {
|
|
1348
|
+
const theBlock = this.getLegacySQLSouce(pcx.sqlExploreNameRef());
|
|
1349
|
+
const sqExpr = new ast.SQSourceWrapper(theBlock);
|
|
1350
|
+
return this.astAt(sqExpr, pcx);
|
|
1351
|
+
}
|
|
1352
|
+
visitSQSQL(pcx) {
|
|
1353
|
+
const sqExpr = new ast.SQSourceWrapper(this.visitSqlSource(pcx.sqlSource()));
|
|
1354
|
+
return this.astAt(sqExpr, pcx);
|
|
1355
|
+
}
|
|
1350
1356
|
}
|
|
1351
1357
|
exports.MalloyToAST = MalloyToAST;
|
|
1352
1358
|
//# sourceMappingURL=malloy-to-ast.js.map
|
|
@@ -65,7 +65,7 @@ class DocumentSymbolWalker {
|
|
|
65
65
|
}
|
|
66
66
|
enterAnonymousQuery(pcx) {
|
|
67
67
|
this.symbols.push({
|
|
68
|
-
range: this.translator.rangeFromContext(pcx.topLevelAnonQueryDef().
|
|
68
|
+
range: this.translator.rangeFromContext(pcx.topLevelAnonQueryDef().sqExpr()),
|
|
69
69
|
name: 'unnamed_query',
|
|
70
70
|
type: 'unnamed_query',
|
|
71
71
|
children: [],
|
package/dist/lang/parse-utils.js
CHANGED
|
@@ -55,8 +55,8 @@ function* getStringParts(cx) {
|
|
|
55
55
|
if (upToOpen.length > 2) {
|
|
56
56
|
yield upToOpen.slice(0, upToOpen.length - 2);
|
|
57
57
|
}
|
|
58
|
-
if (part.
|
|
59
|
-
yield part.
|
|
58
|
+
if (part.sqExpr()) {
|
|
59
|
+
yield part.sqExpr();
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
const lastChars = (_a = cx.SQL_END()) === null || _a === void 0 ? void 0 : _a.text.slice(0, -3);
|
|
@@ -58,15 +58,15 @@ const defaultTags = {
|
|
|
58
58
|
notes: ['# note\n', '# b4-is\n', '# after-is\n'],
|
|
59
59
|
};
|
|
60
60
|
const turtleDef = `
|
|
61
|
-
source: na is a {
|
|
61
|
+
source: na is a extend {
|
|
62
62
|
# blockNote
|
|
63
|
-
|
|
63
|
+
view:
|
|
64
64
|
# note
|
|
65
65
|
note_a
|
|
66
66
|
# b4-is
|
|
67
67
|
is
|
|
68
68
|
# after-is
|
|
69
|
-
{
|
|
69
|
+
{select: *}
|
|
70
70
|
}
|
|
71
71
|
`;
|
|
72
72
|
describe('document annotation', () => {
|
|
@@ -118,7 +118,7 @@ describe('document annotation', () => {
|
|
|
118
118
|
# note0
|
|
119
119
|
source: note_b is a
|
|
120
120
|
# note1
|
|
121
|
-
source: note_a is note_b { primary_key: ai }
|
|
121
|
+
source: note_a is note_b extend { primary_key: ai }
|
|
122
122
|
`);
|
|
123
123
|
expect(m).toTranslate();
|
|
124
124
|
const note_a = m.getSourceDef('note_a');
|
|
@@ -139,7 +139,7 @@ describe('document annotation', () => {
|
|
|
139
139
|
# b4-is
|
|
140
140
|
is
|
|
141
141
|
# after-is
|
|
142
|
-
a -> {
|
|
142
|
+
a -> {select: *}
|
|
143
143
|
`);
|
|
144
144
|
expect(m).toTranslate();
|
|
145
145
|
const note_a = m.getQuery('note_a');
|
|
@@ -148,29 +148,12 @@ describe('document annotation', () => {
|
|
|
148
148
|
expect(note_a.annotation).matchesAnnotation(defaultTags);
|
|
149
149
|
}
|
|
150
150
|
});
|
|
151
|
-
test('anonymous query annotation points', () => {
|
|
152
|
-
const m = new test_translator_1.TestTranslator(`
|
|
153
|
-
# note1
|
|
154
|
-
query:
|
|
155
|
-
# note2
|
|
156
|
-
a -> {project: *}
|
|
157
|
-
`);
|
|
158
|
-
expect(m).toTranslate();
|
|
159
|
-
const note_a = m.getQuery(0);
|
|
160
|
-
expect(note_a).toBeDefined();
|
|
161
|
-
if (note_a) {
|
|
162
|
-
expect(note_a.annotation).matchesAnnotation({
|
|
163
|
-
blockNotes: ['# note1\n'],
|
|
164
|
-
notes: ['# note2\n'],
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
151
|
test('run statement annotation points', () => {
|
|
169
152
|
const m = new test_translator_1.TestTranslator(`
|
|
170
153
|
# note1
|
|
171
154
|
run:
|
|
172
155
|
# note2
|
|
173
|
-
a -> {
|
|
156
|
+
a -> {select: *}
|
|
174
157
|
`);
|
|
175
158
|
expect(m).toTranslate();
|
|
176
159
|
const note_a = m.getQuery(0);
|
|
@@ -186,7 +169,7 @@ describe('document annotation', () => {
|
|
|
186
169
|
const m = new test_translator_1.TestTranslator(`
|
|
187
170
|
# note1
|
|
188
171
|
# note2
|
|
189
|
-
query: note_a is a -> {
|
|
172
|
+
query: note_a is a -> {select: *}
|
|
190
173
|
`);
|
|
191
174
|
expect(m).toTranslate();
|
|
192
175
|
const note_a = m.getQuery('note_a');
|
|
@@ -202,9 +185,9 @@ describe('document annotation', () => {
|
|
|
202
185
|
# noteb0
|
|
203
186
|
query:
|
|
204
187
|
# noteb1
|
|
205
|
-
note_b is a -> {
|
|
188
|
+
note_b is a -> { select: * }
|
|
206
189
|
# note1
|
|
207
|
-
query: note_a is
|
|
190
|
+
query: note_a is note_b + { where: astr = 'a' }
|
|
208
191
|
`);
|
|
209
192
|
expect(m).toTranslate();
|
|
210
193
|
const note_a = m.getQuery('note_a');
|
|
@@ -217,14 +200,20 @@ describe('document annotation', () => {
|
|
|
217
200
|
}
|
|
218
201
|
});
|
|
219
202
|
test('query from turtle inherits turtle annotation', () => {
|
|
220
|
-
const m =
|
|
203
|
+
const m = (0, test_translator_1.model) `
|
|
221
204
|
${turtleDef}
|
|
222
|
-
|
|
223
|
-
|
|
205
|
+
# run_block
|
|
206
|
+
run: # run_note
|
|
207
|
+
na -> note_a
|
|
208
|
+
`;
|
|
224
209
|
expect(m).toTranslate();
|
|
225
|
-
const note_a = m.getQuery(0);
|
|
210
|
+
const note_a = m.translator.getQuery(0);
|
|
226
211
|
expect(note_a === null || note_a === void 0 ? void 0 : note_a.annotation).toBeDefined();
|
|
227
|
-
expect(note_a === null || note_a === void 0 ? void 0 : note_a.annotation).matchesAnnotation({
|
|
212
|
+
expect(note_a === null || note_a === void 0 ? void 0 : note_a.annotation).matchesAnnotation({
|
|
213
|
+
blockNotes: ['# run_block\n'],
|
|
214
|
+
notes: ['# run_note\n'],
|
|
215
|
+
inherits: { inherits: defaultTags },
|
|
216
|
+
});
|
|
228
217
|
});
|
|
229
218
|
test('model annotations', () => {
|
|
230
219
|
var _a;
|
|
@@ -273,8 +262,8 @@ describe('source definition annotations', () => {
|
|
|
273
262
|
test('refined turtle inherits annotation', () => {
|
|
274
263
|
const m = new test_translator_1.TestTranslator(`
|
|
275
264
|
${turtleDef}
|
|
276
|
-
source: new_na is na
|
|
277
|
-
|
|
265
|
+
source: new_na is na extend {
|
|
266
|
+
view: new_note_a is note_a
|
|
278
267
|
}
|
|
279
268
|
`);
|
|
280
269
|
expect(m).toTranslate();
|
|
@@ -288,7 +277,7 @@ describe('source definition annotations', () => {
|
|
|
288
277
|
});
|
|
289
278
|
test('dimension block annotation', () => {
|
|
290
279
|
const m = new test_translator_1.TestTranslator(`
|
|
291
|
-
source: na is a {
|
|
280
|
+
source: na is a extend {
|
|
292
281
|
# blockNote
|
|
293
282
|
dimension:
|
|
294
283
|
# note
|
|
@@ -309,7 +298,7 @@ describe('source definition annotations', () => {
|
|
|
309
298
|
});
|
|
310
299
|
test('measure block annotation', () => {
|
|
311
300
|
const m = new test_translator_1.TestTranslator(`
|
|
312
|
-
source: na is a {
|
|
301
|
+
source: na is a extend {
|
|
313
302
|
# blockNote
|
|
314
303
|
measure:
|
|
315
304
|
# note
|
|
@@ -330,7 +319,7 @@ describe('source definition annotations', () => {
|
|
|
330
319
|
});
|
|
331
320
|
test('join_one-with block annotation', () => {
|
|
332
321
|
const m = new test_translator_1.TestTranslator(`
|
|
333
|
-
source: na is a {
|
|
322
|
+
source: na is a extend {
|
|
334
323
|
# blockNote
|
|
335
324
|
join_one:
|
|
336
325
|
# note
|
|
@@ -351,7 +340,7 @@ describe('source definition annotations', () => {
|
|
|
351
340
|
});
|
|
352
341
|
test('join_many-on block annotation', () => {
|
|
353
342
|
const m = new test_translator_1.TestTranslator(`
|
|
354
|
-
source: na is a {
|
|
343
|
+
source: na is a extend {
|
|
355
344
|
# blockNote
|
|
356
345
|
join_many:
|
|
357
346
|
# note
|
|
@@ -372,7 +361,7 @@ describe('source definition annotations', () => {
|
|
|
372
361
|
});
|
|
373
362
|
test('ignores model annotation', () => {
|
|
374
363
|
const m = new test_translator_1.TestTranslator(`
|
|
375
|
-
source: na is a {
|
|
364
|
+
source: na is a extend {
|
|
376
365
|
## model1
|
|
377
366
|
}
|
|
378
367
|
`);
|
|
@@ -382,9 +371,9 @@ describe('source definition annotations', () => {
|
|
|
382
371
|
describe('query operation annotations', () => {
|
|
383
372
|
test('ignores model annotation', () => {
|
|
384
373
|
expect(`
|
|
385
|
-
|
|
374
|
+
run: a -> {
|
|
386
375
|
## model1
|
|
387
|
-
|
|
376
|
+
select: *
|
|
388
377
|
}
|
|
389
378
|
`).translationToFailWith('Model annotations not allowed at this scope');
|
|
390
379
|
});
|
|
@@ -392,7 +381,7 @@ describe('query operation annotations', () => {
|
|
|
392
381
|
const m = new test_translator_1.TestTranslator(`
|
|
393
382
|
query: findme is a -> {
|
|
394
383
|
# blockNote
|
|
395
|
-
|
|
384
|
+
select:
|
|
396
385
|
# note
|
|
397
386
|
note_a
|
|
398
387
|
# b4-is
|
|
@@ -411,7 +400,7 @@ describe('query operation annotations', () => {
|
|
|
411
400
|
});
|
|
412
401
|
test('project ref inherits annotation', () => {
|
|
413
402
|
const m = new test_translator_1.TestTranslator(`
|
|
414
|
-
|
|
403
|
+
run: a extend {
|
|
415
404
|
# blockNote
|
|
416
405
|
dimension:
|
|
417
406
|
# note
|
|
@@ -422,7 +411,7 @@ describe('query operation annotations', () => {
|
|
|
422
411
|
astr
|
|
423
412
|
} -> {
|
|
424
413
|
# note1
|
|
425
|
-
|
|
414
|
+
select:
|
|
426
415
|
# note2
|
|
427
416
|
note_a
|
|
428
417
|
}
|
|
@@ -484,7 +473,7 @@ describe('query operation annotations', () => {
|
|
|
484
473
|
});
|
|
485
474
|
test('group_by ref inherits', () => {
|
|
486
475
|
const m = new test_translator_1.TestTranslator(`
|
|
487
|
-
source: aa is a
|
|
476
|
+
source: aa is a extend {
|
|
488
477
|
# blockNote
|
|
489
478
|
dimension:
|
|
490
479
|
# note
|
|
@@ -536,7 +525,7 @@ describe('query operation annotations', () => {
|
|
|
536
525
|
});
|
|
537
526
|
test('aggregate ref inherits', () => {
|
|
538
527
|
const m = new test_translator_1.TestTranslator(`
|
|
539
|
-
source: aa is a
|
|
528
|
+
source: aa is a extend {
|
|
540
529
|
# blockNote
|
|
541
530
|
measure:
|
|
542
531
|
# note
|
|
@@ -589,7 +578,7 @@ describe('query operation annotations', () => {
|
|
|
589
578
|
test('nest from existing inherits annotation', () => {
|
|
590
579
|
const m = new test_translator_1.TestTranslator(`
|
|
591
580
|
${turtleDef}
|
|
592
|
-
|
|
581
|
+
run: na -> {
|
|
593
582
|
nest: note_b is note_a
|
|
594
583
|
}
|
|
595
584
|
`);
|
|
@@ -176,8 +176,8 @@ test('run lenses go before block annotations', () => {
|
|
|
176
176
|
test('(regression) query does not use source block range', () => {
|
|
177
177
|
testLens((0, test_translator_1.markSource) `source: a is table('b') {
|
|
178
178
|
query:
|
|
179
|
-
${'x is {
|
|
180
|
-
y is {
|
|
179
|
+
${'x is {select: *}'}
|
|
180
|
+
y is {select: *}
|
|
181
181
|
}`, [0, 0]);
|
|
182
182
|
});
|
|
183
183
|
//# sourceMappingURL=document-symbol-walker.spec.js.map
|