@malloydata/malloy 0.0.48 → 0.0.49-dev230626192330
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/index.js +1 -2
- package/dist/lang/ast/expressions/expr-func.js +0 -6
- package/dist/lang/ast/sources/named-source.js +4 -0
- package/dist/lang/ast/sources/sql-source.js +4 -0
- package/dist/lang/ast/sources/table-source.d.ts +21 -4
- package/dist/lang/ast/sources/table-source.js +49 -8
- package/dist/lang/lib/Malloy/MalloyParser.d.ts +132 -96
- package/dist/lang/lib/Malloy/MalloyParser.js +1700 -1504
- package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +53 -5
- package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +33 -3
- package/dist/lang/malloy-to-ast.d.ts +2 -1
- package/dist/lang/malloy-to-ast.js +19 -4
- package/dist/lang/parse-malloy.d.ts +1 -1
- package/dist/lang/parse-malloy.js +34 -31
- package/dist/lang/parse-tree-walkers/find-external-references.d.ts +24 -5
- package/dist/lang/parse-tree-walkers/find-external-references.js +59 -13
- package/dist/lang/test/parse-expects.js +3 -1
- package/dist/lang/test/parse.spec.js +30 -1
- package/dist/lang/test/test-translator.js +1 -0
- package/dist/lang/translate-response.d.ts +4 -1
- package/dist/malloy.d.ts +0 -4
- package/dist/malloy.js +12 -24
- package/dist/model/malloy_types.d.ts +4 -1
- package/dist/runtime_types.d.ts +4 -3
- package/package.json +1 -1
|
@@ -19,6 +19,8 @@ import { ExprNULLContext } from "./MalloyParser";
|
|
|
19
19
|
import { ExprBoolContext } from "./MalloyParser";
|
|
20
20
|
import { ExprRegexContext } from "./MalloyParser";
|
|
21
21
|
import { ExprNowContext } from "./MalloyParser";
|
|
22
|
+
import { TableFunctionContext } from "./MalloyParser";
|
|
23
|
+
import { TableMethodContext } from "./MalloyParser";
|
|
22
24
|
import { NestExistingContext } from "./MalloyParser";
|
|
23
25
|
import { NestDefContext } from "./MalloyParser";
|
|
24
26
|
import { ExprFieldPathContext } from "./MalloyParser";
|
|
@@ -97,6 +99,7 @@ import { PipelineFromNameContext } from "./MalloyParser";
|
|
|
97
99
|
import { FirstSegmentContext } from "./MalloyParser";
|
|
98
100
|
import { PipeElementContext } from "./MalloyParser";
|
|
99
101
|
import { ExploreTableContext } from "./MalloyParser";
|
|
102
|
+
import { ConnectionIdContext } from "./MalloyParser";
|
|
100
103
|
import { QueryPropertiesContext } from "./MalloyParser";
|
|
101
104
|
import { FilterShortcutContext } from "./MalloyParser";
|
|
102
105
|
import { ExploreQueryNameContext } from "./MalloyParser";
|
|
@@ -164,7 +167,8 @@ import { MalloyTypeContext } from "./MalloyParser";
|
|
|
164
167
|
import { CompareOpContext } from "./MalloyParser";
|
|
165
168
|
import { LiteralContext } from "./MalloyParser";
|
|
166
169
|
import { DateLiteralContext } from "./MalloyParser";
|
|
167
|
-
import {
|
|
170
|
+
import { TablePathContext } from "./MalloyParser";
|
|
171
|
+
import { TableURIContext } from "./MalloyParser";
|
|
168
172
|
import { IdContext } from "./MalloyParser";
|
|
169
173
|
import { TimeframeContext } from "./MalloyParser";
|
|
170
174
|
import { UngroupContext } from "./MalloyParser";
|
|
@@ -435,6 +439,30 @@ export interface MalloyParserListener extends ParseTreeListener {
|
|
|
435
439
|
* @param ctx the parse tree
|
|
436
440
|
*/
|
|
437
441
|
exitExprNow?: (ctx: ExprNowContext) => void;
|
|
442
|
+
/**
|
|
443
|
+
* Enter a parse tree produced by the `tableFunction`
|
|
444
|
+
* labeled alternative in `MalloyParser.exploreTable`.
|
|
445
|
+
* @param ctx the parse tree
|
|
446
|
+
*/
|
|
447
|
+
enterTableFunction?: (ctx: TableFunctionContext) => void;
|
|
448
|
+
/**
|
|
449
|
+
* Exit a parse tree produced by the `tableFunction`
|
|
450
|
+
* labeled alternative in `MalloyParser.exploreTable`.
|
|
451
|
+
* @param ctx the parse tree
|
|
452
|
+
*/
|
|
453
|
+
exitTableFunction?: (ctx: TableFunctionContext) => void;
|
|
454
|
+
/**
|
|
455
|
+
* Enter a parse tree produced by the `tableMethod`
|
|
456
|
+
* labeled alternative in `MalloyParser.exploreTable`.
|
|
457
|
+
* @param ctx the parse tree
|
|
458
|
+
*/
|
|
459
|
+
enterTableMethod?: (ctx: TableMethodContext) => void;
|
|
460
|
+
/**
|
|
461
|
+
* Exit a parse tree produced by the `tableMethod`
|
|
462
|
+
* labeled alternative in `MalloyParser.exploreTable`.
|
|
463
|
+
* @param ctx the parse tree
|
|
464
|
+
*/
|
|
465
|
+
exitTableMethod?: (ctx: TableMethodContext) => void;
|
|
438
466
|
/**
|
|
439
467
|
* Enter a parse tree produced by the `nestExisting`
|
|
440
468
|
* labeled alternative in `MalloyParser.nestEntry`.
|
|
@@ -1319,6 +1347,16 @@ export interface MalloyParserListener extends ParseTreeListener {
|
|
|
1319
1347
|
* @param ctx the parse tree
|
|
1320
1348
|
*/
|
|
1321
1349
|
exitExploreTable?: (ctx: ExploreTableContext) => void;
|
|
1350
|
+
/**
|
|
1351
|
+
* Enter a parse tree produced by `MalloyParser.connectionId`.
|
|
1352
|
+
* @param ctx the parse tree
|
|
1353
|
+
*/
|
|
1354
|
+
enterConnectionId?: (ctx: ConnectionIdContext) => void;
|
|
1355
|
+
/**
|
|
1356
|
+
* Exit a parse tree produced by `MalloyParser.connectionId`.
|
|
1357
|
+
* @param ctx the parse tree
|
|
1358
|
+
*/
|
|
1359
|
+
exitConnectionId?: (ctx: ConnectionIdContext) => void;
|
|
1322
1360
|
/**
|
|
1323
1361
|
* Enter a parse tree produced by `MalloyParser.queryProperties`.
|
|
1324
1362
|
* @param ctx the parse tree
|
|
@@ -1990,15 +2028,25 @@ export interface MalloyParserListener extends ParseTreeListener {
|
|
|
1990
2028
|
*/
|
|
1991
2029
|
exitDateLiteral?: (ctx: DateLiteralContext) => void;
|
|
1992
2030
|
/**
|
|
1993
|
-
* Enter a parse tree produced by `MalloyParser.
|
|
2031
|
+
* Enter a parse tree produced by `MalloyParser.tablePath`.
|
|
2032
|
+
* @param ctx the parse tree
|
|
2033
|
+
*/
|
|
2034
|
+
enterTablePath?: (ctx: TablePathContext) => void;
|
|
2035
|
+
/**
|
|
2036
|
+
* Exit a parse tree produced by `MalloyParser.tablePath`.
|
|
2037
|
+
* @param ctx the parse tree
|
|
2038
|
+
*/
|
|
2039
|
+
exitTablePath?: (ctx: TablePathContext) => void;
|
|
2040
|
+
/**
|
|
2041
|
+
* Enter a parse tree produced by `MalloyParser.tableURI`.
|
|
1994
2042
|
* @param ctx the parse tree
|
|
1995
2043
|
*/
|
|
1996
|
-
|
|
2044
|
+
enterTableURI?: (ctx: TableURIContext) => void;
|
|
1997
2045
|
/**
|
|
1998
|
-
* Exit a parse tree produced by `MalloyParser.
|
|
2046
|
+
* Exit a parse tree produced by `MalloyParser.tableURI`.
|
|
1999
2047
|
* @param ctx the parse tree
|
|
2000
2048
|
*/
|
|
2001
|
-
|
|
2049
|
+
exitTableURI?: (ctx: TableURIContext) => void;
|
|
2002
2050
|
/**
|
|
2003
2051
|
* Enter a parse tree produced by `MalloyParser.id`.
|
|
2004
2052
|
* @param ctx the parse tree
|
|
@@ -19,6 +19,8 @@ import { ExprNULLContext } from "./MalloyParser";
|
|
|
19
19
|
import { ExprBoolContext } from "./MalloyParser";
|
|
20
20
|
import { ExprRegexContext } from "./MalloyParser";
|
|
21
21
|
import { ExprNowContext } from "./MalloyParser";
|
|
22
|
+
import { TableFunctionContext } from "./MalloyParser";
|
|
23
|
+
import { TableMethodContext } from "./MalloyParser";
|
|
22
24
|
import { NestExistingContext } from "./MalloyParser";
|
|
23
25
|
import { NestDefContext } from "./MalloyParser";
|
|
24
26
|
import { ExprFieldPathContext } from "./MalloyParser";
|
|
@@ -97,6 +99,7 @@ import { PipelineFromNameContext } from "./MalloyParser";
|
|
|
97
99
|
import { FirstSegmentContext } from "./MalloyParser";
|
|
98
100
|
import { PipeElementContext } from "./MalloyParser";
|
|
99
101
|
import { ExploreTableContext } from "./MalloyParser";
|
|
102
|
+
import { ConnectionIdContext } from "./MalloyParser";
|
|
100
103
|
import { QueryPropertiesContext } from "./MalloyParser";
|
|
101
104
|
import { FilterShortcutContext } from "./MalloyParser";
|
|
102
105
|
import { ExploreQueryNameContext } from "./MalloyParser";
|
|
@@ -164,7 +167,8 @@ import { MalloyTypeContext } from "./MalloyParser";
|
|
|
164
167
|
import { CompareOpContext } from "./MalloyParser";
|
|
165
168
|
import { LiteralContext } from "./MalloyParser";
|
|
166
169
|
import { DateLiteralContext } from "./MalloyParser";
|
|
167
|
-
import {
|
|
170
|
+
import { TablePathContext } from "./MalloyParser";
|
|
171
|
+
import { TableURIContext } from "./MalloyParser";
|
|
168
172
|
import { IdContext } from "./MalloyParser";
|
|
169
173
|
import { TimeframeContext } from "./MalloyParser";
|
|
170
174
|
import { UngroupContext } from "./MalloyParser";
|
|
@@ -338,6 +342,20 @@ export interface MalloyParserVisitor<Result> extends ParseTreeVisitor<Result> {
|
|
|
338
342
|
* @return the visitor result
|
|
339
343
|
*/
|
|
340
344
|
visitExprNow?: (ctx: ExprNowContext) => Result;
|
|
345
|
+
/**
|
|
346
|
+
* Visit a parse tree produced by the `tableFunction`
|
|
347
|
+
* labeled alternative in `MalloyParser.exploreTable`.
|
|
348
|
+
* @param ctx the parse tree
|
|
349
|
+
* @return the visitor result
|
|
350
|
+
*/
|
|
351
|
+
visitTableFunction?: (ctx: TableFunctionContext) => Result;
|
|
352
|
+
/**
|
|
353
|
+
* Visit a parse tree produced by the `tableMethod`
|
|
354
|
+
* labeled alternative in `MalloyParser.exploreTable`.
|
|
355
|
+
* @param ctx the parse tree
|
|
356
|
+
* @return the visitor result
|
|
357
|
+
*/
|
|
358
|
+
visitTableMethod?: (ctx: TableMethodContext) => Result;
|
|
341
359
|
/**
|
|
342
360
|
* Visit a parse tree produced by the `nestExisting`
|
|
343
361
|
* labeled alternative in `MalloyParser.nestEntry`.
|
|
@@ -858,6 +876,12 @@ export interface MalloyParserVisitor<Result> extends ParseTreeVisitor<Result> {
|
|
|
858
876
|
* @return the visitor result
|
|
859
877
|
*/
|
|
860
878
|
visitExploreTable?: (ctx: ExploreTableContext) => Result;
|
|
879
|
+
/**
|
|
880
|
+
* Visit a parse tree produced by `MalloyParser.connectionId`.
|
|
881
|
+
* @param ctx the parse tree
|
|
882
|
+
* @return the visitor result
|
|
883
|
+
*/
|
|
884
|
+
visitConnectionId?: (ctx: ConnectionIdContext) => Result;
|
|
861
885
|
/**
|
|
862
886
|
* Visit a parse tree produced by `MalloyParser.queryProperties`.
|
|
863
887
|
* @param ctx the parse tree
|
|
@@ -1261,11 +1285,17 @@ export interface MalloyParserVisitor<Result> extends ParseTreeVisitor<Result> {
|
|
|
1261
1285
|
*/
|
|
1262
1286
|
visitDateLiteral?: (ctx: DateLiteralContext) => Result;
|
|
1263
1287
|
/**
|
|
1264
|
-
* Visit a parse tree produced by `MalloyParser.
|
|
1288
|
+
* Visit a parse tree produced by `MalloyParser.tablePath`.
|
|
1289
|
+
* @param ctx the parse tree
|
|
1290
|
+
* @return the visitor result
|
|
1291
|
+
*/
|
|
1292
|
+
visitTablePath?: (ctx: TablePathContext) => Result;
|
|
1293
|
+
/**
|
|
1294
|
+
* Visit a parse tree produced by `MalloyParser.tableURI`.
|
|
1265
1295
|
* @param ctx the parse tree
|
|
1266
1296
|
* @return the visitor result
|
|
1267
1297
|
*/
|
|
1268
|
-
|
|
1298
|
+
visitTableURI?: (ctx: TableURIContext) => Result;
|
|
1269
1299
|
/**
|
|
1270
1300
|
* Visit a parse tree produced by `MalloyParser.id`.
|
|
1271
1301
|
* @param ctx the parse tree
|
|
@@ -65,7 +65,8 @@ export declare class MalloyToAST extends AbstractParseTreeVisitor<ast.MalloyElem
|
|
|
65
65
|
visitSourceDefinition(pcx: parse.SourceDefinitionContext): ast.DefineSource;
|
|
66
66
|
visitExplore(pcx: parse.ExploreContext): ast.Source;
|
|
67
67
|
visitExploreProperties(pcx: parse.ExplorePropertiesContext): ast.SourceDesc;
|
|
68
|
-
|
|
68
|
+
visitTableFunction(pcx: parse.TableFunctionContext): ast.TableSource;
|
|
69
|
+
visitTableMethod(pcx: parse.TableMethodContext): ast.TableSource;
|
|
69
70
|
visitTableSource(pcx: parse.TableSourceContext): ast.TableSource;
|
|
70
71
|
visitSQLSourceName(pcx: parse.SQLSourceNameContext): ast.SQLSource;
|
|
71
72
|
visitQuerySource(pcx: parse.QuerySourceContext): ast.Source;
|
|
@@ -49,6 +49,7 @@ exports.MalloyToAST = void 0;
|
|
|
49
49
|
const AbstractParseTreeVisitor_1 = require("antlr4ts/tree/AbstractParseTreeVisitor");
|
|
50
50
|
const ast = __importStar(require("./ast"));
|
|
51
51
|
const Interval_1 = require("antlr4ts/misc/Interval");
|
|
52
|
+
const ast_1 = require("./ast");
|
|
52
53
|
const ENABLE_M4_WARNINGS = false;
|
|
53
54
|
class IgnoredElement extends ast.MalloyElement {
|
|
54
55
|
constructor(src) {
|
|
@@ -262,12 +263,26 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
262
263
|
}
|
|
263
264
|
return propList;
|
|
264
265
|
}
|
|
265
|
-
|
|
266
|
-
const
|
|
267
|
-
|
|
266
|
+
visitTableFunction(pcx) {
|
|
267
|
+
const tableURI = this.stripQuotes(pcx.tableURI().text);
|
|
268
|
+
const el = this.astAt(new ast.TableFunctionSource(tableURI), pcx);
|
|
269
|
+
if (ENABLE_M4_WARNINGS) {
|
|
270
|
+
this.astError(el, "`table('connection_name:table_path')` is deprecated; use `connection_name.table('table_path')`", 'warn');
|
|
271
|
+
}
|
|
272
|
+
return el;
|
|
273
|
+
}
|
|
274
|
+
visitTableMethod(pcx) {
|
|
275
|
+
const connId = pcx.connectionId();
|
|
276
|
+
const connectionName = this.astAt(this.getModelEntryName(connId), connId);
|
|
277
|
+
const tablePath = this.stripQuotes(pcx.tablePath().text);
|
|
278
|
+
return this.astAt(new ast.TableMethodSource(connectionName, tablePath), pcx);
|
|
268
279
|
}
|
|
269
280
|
visitTableSource(pcx) {
|
|
270
|
-
|
|
281
|
+
const result = this.visit(pcx.exploreTable());
|
|
282
|
+
if (result instanceof ast_1.TableSource) {
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
285
|
+
throw this.internalError(pcx, `Table source matched, but ${result.elementType} found`);
|
|
271
286
|
}
|
|
272
287
|
visitSQLSourceName(pcx) {
|
|
273
288
|
const name = this.getModelEntryName(pcx.sqlExploreNameRef());
|
|
@@ -56,7 +56,7 @@ declare class ParseStep implements TranslationStep {
|
|
|
56
56
|
}
|
|
57
57
|
declare class ImportsAndTablesStep implements TranslationStep {
|
|
58
58
|
readonly parseStep: ParseStep;
|
|
59
|
-
private
|
|
59
|
+
private parseReferences;
|
|
60
60
|
constructor(parseStep: ParseStep);
|
|
61
61
|
step(that: MalloyTranslation): DataRequestResponse | ParseResponse;
|
|
62
62
|
}
|
|
@@ -194,45 +194,40 @@ class ParseStep {
|
|
|
194
194
|
class ImportsAndTablesStep {
|
|
195
195
|
constructor(parseStep) {
|
|
196
196
|
this.parseStep = parseStep;
|
|
197
|
-
this.
|
|
197
|
+
this.parseReferences = undefined;
|
|
198
198
|
}
|
|
199
199
|
step(that) {
|
|
200
200
|
const parseReq = this.parseStep.step(that);
|
|
201
201
|
if (parseReq.parse === undefined) {
|
|
202
202
|
return parseReq;
|
|
203
203
|
}
|
|
204
|
-
if (!this.
|
|
205
|
-
this.
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
204
|
+
if (!this.parseReferences) {
|
|
205
|
+
this.parseReferences = (0, find_external_references_1.findReferences)(that, parseReq.parse.tokenStream, parseReq.parse.root);
|
|
206
|
+
for (const ref in this.parseReferences.tables) {
|
|
207
|
+
that.root.schemaZone.reference(ref, {
|
|
208
|
+
url: that.sourceURL,
|
|
209
|
+
range: this.parseReferences.tables[ref].firstReference,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
for (const relativeRef in this.parseReferences.urls) {
|
|
213
|
+
const firstRef = this.parseReferences.urls[relativeRef];
|
|
214
|
+
try {
|
|
215
|
+
const ref = decodeURI(new URL(relativeRef, that.sourceURL).toString());
|
|
216
|
+
that.addChild(ref);
|
|
217
|
+
that.root.importZone.reference(ref, {
|
|
210
218
|
url: that.sourceURL,
|
|
211
|
-
range:
|
|
219
|
+
range: firstRef,
|
|
212
220
|
});
|
|
213
221
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
that.
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
range: firstRef,
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
catch (err) {
|
|
227
|
-
// This import spec is so bad the URL library threw up, this
|
|
228
|
-
// may be impossible, because it will append any garbage
|
|
229
|
-
// to the known good rootURL assuming it is relative
|
|
230
|
-
that.root.logger.log({
|
|
231
|
-
message: `Malformed URL '${relativeRef}'"`,
|
|
232
|
-
at: { url: that.sourceURL, range: firstRef },
|
|
233
|
-
severity: 'error',
|
|
234
|
-
});
|
|
235
|
-
}
|
|
222
|
+
catch (err) {
|
|
223
|
+
// This import spec is so bad the URL library threw up, this
|
|
224
|
+
// may be impossible, because it will append any garbage
|
|
225
|
+
// to the known good rootURL assuming it is relative
|
|
226
|
+
that.root.logger.log({
|
|
227
|
+
message: `Malformed URL '${relativeRef}'"`,
|
|
228
|
+
at: { url: that.sourceURL, range: firstRef },
|
|
229
|
+
severity: 'error',
|
|
230
|
+
});
|
|
236
231
|
}
|
|
237
232
|
}
|
|
238
233
|
}
|
|
@@ -244,7 +239,15 @@ class ImportsAndTablesStep {
|
|
|
244
239
|
let allMissing = {};
|
|
245
240
|
const missingTables = that.root.schemaZone.getUndefined();
|
|
246
241
|
if (missingTables) {
|
|
247
|
-
|
|
242
|
+
const tables = {};
|
|
243
|
+
for (const key of missingTables) {
|
|
244
|
+
const info = this.parseReferences.tables[key];
|
|
245
|
+
tables[key] = {
|
|
246
|
+
connectionName: info.connectionName,
|
|
247
|
+
tablePath: info.tablePath,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
allMissing = { tables };
|
|
248
251
|
}
|
|
249
252
|
const missingImports = that.root.importZone.getUndefined();
|
|
250
253
|
if (missingImports) {
|
|
@@ -2,10 +2,29 @@ import { CommonTokenStream } from 'antlr4ts';
|
|
|
2
2
|
import { ParseTree } from 'antlr4ts/tree';
|
|
3
3
|
import { DocumentRange } from '../../model/malloy_types';
|
|
4
4
|
import { MalloyTranslation } from '../parse-malloy';
|
|
5
|
-
declare type
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
declare type NeedImports = Record<string, DocumentRange>;
|
|
6
|
+
declare type NeedTables = Record<string, {
|
|
7
|
+
connectionName: string | undefined;
|
|
8
|
+
tablePath: string;
|
|
9
|
+
firstReference: DocumentRange;
|
|
10
|
+
}>;
|
|
11
|
+
export declare function constructTableKey(connectionName: string | undefined, tablePath: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* This function parses an old-style `tableURI` into a connection name and
|
|
14
|
+
* table path. The name includes `deprecated` because it should only be used
|
|
15
|
+
* in the (deprecated) old-style `table('conn:tab')` syntax. Any use of this
|
|
16
|
+
* anywhere else is bad.
|
|
17
|
+
* @param tableURI The sting that is passed into the `table('conn:tab')` syntax.
|
|
18
|
+
* @returns A connection name and table path.
|
|
19
|
+
* @deprecated
|
|
20
|
+
*/
|
|
21
|
+
export declare function deprecatedParseTableURI(tableURI: string): {
|
|
22
|
+
connectionName?: string;
|
|
23
|
+
tablePath: string;
|
|
24
|
+
};
|
|
25
|
+
export interface FindReferencesData {
|
|
26
|
+
tables: NeedTables;
|
|
27
|
+
urls: NeedImports;
|
|
9
28
|
}
|
|
10
|
-
export declare function findReferences(trans: MalloyTranslation, tokens: CommonTokenStream, parseTree: ParseTree):
|
|
29
|
+
export declare function findReferences(trans: MalloyTranslation, tokens: CommonTokenStream, parseTree: ParseTree): FindReferencesData;
|
|
11
30
|
export {};
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.findReferences = void 0;
|
|
25
|
+
exports.findReferences = exports.deprecatedParseTableURI = exports.constructTableKey = void 0;
|
|
26
26
|
const ParseTreeWalker_1 = require("antlr4ts/tree/ParseTreeWalker");
|
|
27
27
|
class FindExternalReferences {
|
|
28
28
|
constructor(trans, tokens) {
|
|
@@ -31,31 +31,77 @@ class FindExternalReferences {
|
|
|
31
31
|
this.needTables = {};
|
|
32
32
|
this.needImports = {};
|
|
33
33
|
}
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
if (!this.needTables[
|
|
37
|
-
this.needTables[
|
|
34
|
+
registerTableReference(connectionName, tablePath, reference) {
|
|
35
|
+
const key = constructTableKey(connectionName, tablePath);
|
|
36
|
+
if (!this.needTables[key]) {
|
|
37
|
+
this.needTables[key] = {
|
|
38
|
+
connectionName,
|
|
39
|
+
tablePath,
|
|
40
|
+
firstReference: reference,
|
|
41
|
+
};
|
|
38
42
|
}
|
|
39
43
|
}
|
|
44
|
+
enterTableMethod(pcx) {
|
|
45
|
+
const connectionName = this.stripIdQuotes(pcx.connectionId().text);
|
|
46
|
+
const tablePath = this.tokens.getText(pcx.tablePath()).slice(1, -1);
|
|
47
|
+
const reference = this.trans.rangeFromContext(pcx);
|
|
48
|
+
this.registerTableReference(connectionName, tablePath, reference);
|
|
49
|
+
}
|
|
50
|
+
enterTableFunction(pcx) {
|
|
51
|
+
const tableURI = this.tokens.getText(pcx.tableURI()).slice(1, -1);
|
|
52
|
+
// This use of `deprecatedParseTableURI` is ok because it is for handling the
|
|
53
|
+
// old, soon-to-be-deprecated table syntax.
|
|
54
|
+
const { connectionName, tablePath } = deprecatedParseTableURI(tableURI);
|
|
55
|
+
const reference = this.trans.rangeFromContext(pcx);
|
|
56
|
+
this.registerTableReference(connectionName, tablePath, reference);
|
|
57
|
+
}
|
|
40
58
|
enterImportURL(pcx) {
|
|
41
59
|
const url = JSON.parse(pcx.JSON_STRING().text);
|
|
42
60
|
if (!this.needImports[url]) {
|
|
43
61
|
this.needImports[url] = this.trans.rangeFromContext(pcx);
|
|
44
62
|
}
|
|
45
63
|
}
|
|
64
|
+
stripIdQuotes(id) {
|
|
65
|
+
if (id[0] === '`' && id[id.length - 1] === '`') {
|
|
66
|
+
return id.slice(1, -1);
|
|
67
|
+
}
|
|
68
|
+
return id;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function constructTableKey(connectionName, tablePath) {
|
|
72
|
+
return connectionName === undefined
|
|
73
|
+
? tablePath
|
|
74
|
+
: `${connectionName}:${tablePath}`;
|
|
46
75
|
}
|
|
76
|
+
exports.constructTableKey = constructTableKey;
|
|
77
|
+
/**
|
|
78
|
+
* This function parses an old-style `tableURI` into a connection name and
|
|
79
|
+
* table path. The name includes `deprecated` because it should only be used
|
|
80
|
+
* in the (deprecated) old-style `table('conn:tab')` syntax. Any use of this
|
|
81
|
+
* anywhere else is bad.
|
|
82
|
+
* @param tableURI The sting that is passed into the `table('conn:tab')` syntax.
|
|
83
|
+
* @returns A connection name and table path.
|
|
84
|
+
* @deprecated
|
|
85
|
+
*/
|
|
86
|
+
function deprecatedParseTableURI(tableURI) {
|
|
87
|
+
const parts = tableURI.match(/^([^:]*):(.*)$/);
|
|
88
|
+
if (parts) {
|
|
89
|
+
const [, firstPart, secondPart] = parts;
|
|
90
|
+
return { connectionName: firstPart, tablePath: secondPart };
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
return { tablePath: tableURI };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.deprecatedParseTableURI = deprecatedParseTableURI;
|
|
47
97
|
function findReferences(trans, tokens, parseTree) {
|
|
48
98
|
const finder = new FindExternalReferences(trans, tokens);
|
|
49
99
|
const listener = finder;
|
|
50
100
|
ParseTreeWalker_1.ParseTreeWalker.DEFAULT.walk(listener, parseTree);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
if (Object.keys(finder.needImports).length > 0) {
|
|
56
|
-
refs = { ...refs, urls: finder.needImports };
|
|
57
|
-
}
|
|
58
|
-
return Object.keys(refs).length > 0 ? refs : null;
|
|
101
|
+
return {
|
|
102
|
+
tables: finder.needTables,
|
|
103
|
+
urls: finder.needImports,
|
|
104
|
+
};
|
|
59
105
|
}
|
|
60
106
|
exports.findReferences = findReferences;
|
|
61
107
|
//# sourceMappingURL=find-external-references.js.map
|
|
@@ -44,7 +44,9 @@ function prettyNeeds(response) {
|
|
|
44
44
|
let needString = '';
|
|
45
45
|
if (response.tables) {
|
|
46
46
|
needString += 'Tables:\n';
|
|
47
|
-
|
|
47
|
+
for (const table in response.tables) {
|
|
48
|
+
needString += ` - ${table}`;
|
|
49
|
+
}
|
|
48
50
|
}
|
|
49
51
|
if (response.compileSQL) {
|
|
50
52
|
needString += `Compile SQL: ${response.compileSQL.name}`;
|
|
@@ -28,6 +28,35 @@ const test_translator_1 = require("./test-translator");
|
|
|
28
28
|
const granular_result_1 = require("../ast/types/granular-result");
|
|
29
29
|
require("./parse-expects");
|
|
30
30
|
describe('model statements', () => {
|
|
31
|
+
describe('table method', () => {
|
|
32
|
+
test('table method works', () => {
|
|
33
|
+
expect("source: testA is conn.table('aTable')").toTranslate();
|
|
34
|
+
});
|
|
35
|
+
test('table method works with quoted connection name', () => {
|
|
36
|
+
expect("source: testA is `conn`.table('aTable')").toTranslate();
|
|
37
|
+
});
|
|
38
|
+
test('table method fails when connection name is wrong', () => {
|
|
39
|
+
expect("source: testA is bad_conn.table('aTable')").not.toTranslate();
|
|
40
|
+
});
|
|
41
|
+
test('table method fails when connection is not a connection', () => {
|
|
42
|
+
const m = (0, test_translator_1.model) `source: a1 is a; source: testA is a1.table('aTable')`;
|
|
43
|
+
// This is a somewhat weird behavior from the translator. During the
|
|
44
|
+
// first phase of translation, we fetch "external references" (tables and
|
|
45
|
+
// imports). At that point we don't know that there will be an error
|
|
46
|
+
// "a1 is not a connection," so we attempt to fetch `aTable` from connection
|
|
47
|
+
// `a1` even though a1 is not a connection. The response from the application
|
|
48
|
+
// is basically ignored in the end, as we still eventually get the error
|
|
49
|
+
// that a1 is not a connection (it's a source).
|
|
50
|
+
m.translator.update({
|
|
51
|
+
errors: { tables: { 'a1:aTable': 'invalid connection' } },
|
|
52
|
+
});
|
|
53
|
+
expect(m).translationToFailWith('a1 is not a connection');
|
|
54
|
+
});
|
|
55
|
+
// TODO unskip this when ENABLE_M4_WARNINGS becomes a document annotation
|
|
56
|
+
test.skip('table function is deprecated', () => {
|
|
57
|
+
expect("testA is table('conn:aTable')").toTranslateWithWarnings("`table('connection_name:table_path')` is deprecated; use `connection_name.table('table_path')`");
|
|
58
|
+
});
|
|
59
|
+
});
|
|
31
60
|
describe('source:', () => {
|
|
32
61
|
test('table', () => {
|
|
33
62
|
expect("source: testA is table('aTable')").toTranslate();
|
|
@@ -2409,7 +2438,7 @@ describe('translation need error locations', () => {
|
|
|
2409
2438
|
const result = m.translate();
|
|
2410
2439
|
m.update({
|
|
2411
2440
|
errors: {
|
|
2412
|
-
tables: { [(result.tables ||
|
|
2441
|
+
tables: { [Object.keys(result.tables || {})[0]]: 'Bad table!' },
|
|
2413
2442
|
},
|
|
2414
2443
|
});
|
|
2415
2444
|
expect(m).translationToFailWith(/Bad table!/);
|
|
@@ -254,6 +254,7 @@ class TestTranslator extends parse_malloy_1.MalloyTranslator {
|
|
|
254
254
|
this.importZone.define(testURI, testSrc);
|
|
255
255
|
for (const tableName in mockSchema) {
|
|
256
256
|
this.schemaZone.define(tableName, mockSchema[tableName]);
|
|
257
|
+
this.schemaZone.define('conn:' + tableName, mockSchema[tableName]);
|
|
257
258
|
}
|
|
258
259
|
}
|
|
259
260
|
translate() {
|
|
@@ -17,7 +17,10 @@ export interface ProblemResponse {
|
|
|
17
17
|
}
|
|
18
18
|
export declare type FatalResponse = FinalResponse & ProblemResponse;
|
|
19
19
|
export interface NeedSchemaData {
|
|
20
|
-
tables: string
|
|
20
|
+
tables: Record<string, {
|
|
21
|
+
connectionName: string | undefined;
|
|
22
|
+
tablePath: string;
|
|
23
|
+
}>;
|
|
21
24
|
}
|
|
22
25
|
export interface NeedURLData {
|
|
23
26
|
urls: string[];
|
package/dist/malloy.d.ts
CHANGED
|
@@ -231,10 +231,6 @@ export declare class PreparedQuery implements Taggable {
|
|
|
231
231
|
*/
|
|
232
232
|
getFlattenedQuery(defaultName: string): PreparedQuery;
|
|
233
233
|
}
|
|
234
|
-
export declare function parseTableURI(tableURI: string): {
|
|
235
|
-
connectionName?: string;
|
|
236
|
-
tablePath: string;
|
|
237
|
-
};
|
|
238
234
|
/**
|
|
239
235
|
* A parsed Malloy document.
|
|
240
236
|
*/
|
package/dist/malloy.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.CSVWriter = exports.JSONWriter = exports.DataWriter = exports.DataRecord = exports.DataArray = exports.Result = exports.ExploreMaterializer = exports.SQLBlockMaterializer = exports.PreparedResultMaterializer = exports.QueryMaterializer = exports.ModelMaterializer = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.Runtime = exports.ExploreField = exports.JoinRelationship = exports.QueryField = exports.Query = exports.StringField = exports.UnsupportedField = exports.JSONField = exports.BooleanField = exports.NumberField = exports.TimestampField = exports.DateField = exports.TimestampTimeframe = exports.DateTimeframe = exports.AtomicField = exports.AtomicFieldType = exports.Explore = exports.SourceRelationship = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = exports.PreparedResult = exports.DocumentCompletion = exports.DocumentSymbol = exports.DocumentPosition = exports.DocumentRange = exports.DocumentHighlight = exports.Parse = exports.
|
|
25
|
+
exports.CSVWriter = exports.JSONWriter = exports.DataWriter = exports.DataRecord = exports.DataArray = exports.Result = exports.ExploreMaterializer = exports.SQLBlockMaterializer = exports.PreparedResultMaterializer = exports.QueryMaterializer = exports.ModelMaterializer = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.Runtime = exports.ExploreField = exports.JoinRelationship = exports.QueryField = exports.Query = exports.StringField = exports.UnsupportedField = exports.JSONField = exports.BooleanField = exports.NumberField = exports.TimestampField = exports.DateField = exports.TimestampTimeframe = exports.DateTimeframe = exports.AtomicField = exports.AtomicFieldType = exports.Explore = exports.SourceRelationship = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = exports.PreparedResult = exports.DocumentCompletion = exports.DocumentSymbol = exports.DocumentPosition = exports.DocumentRange = exports.DocumentHighlight = exports.Parse = exports.PreparedQuery = exports.Model = exports.MalloyError = exports.Malloy = void 0;
|
|
26
26
|
const lang_1 = require("./lang");
|
|
27
27
|
const model_1 = require("./model");
|
|
28
28
|
const luxon_1 = require("luxon");
|
|
@@ -110,25 +110,24 @@ class Malloy {
|
|
|
110
110
|
if (result.tables) {
|
|
111
111
|
// collect tables by connection name since there may be multiple connections
|
|
112
112
|
const tablesByConnection = new Map();
|
|
113
|
-
for (const
|
|
114
|
-
const { connectionName } =
|
|
115
|
-
|
|
116
|
-
if (
|
|
117
|
-
|
|
113
|
+
for (const tableKey in result.tables) {
|
|
114
|
+
const { connectionName, tablePath } = result.tables[tableKey];
|
|
115
|
+
const connectionToTablesMap = tablesByConnection.get(connectionName);
|
|
116
|
+
if (connectionToTablesMap === undefined) {
|
|
117
|
+
tablesByConnection.set(connectionName, { [tableKey]: tablePath });
|
|
118
118
|
}
|
|
119
119
|
else {
|
|
120
|
-
connectionToTablesMap
|
|
120
|
+
connectionToTablesMap[tableKey] = tablePath;
|
|
121
121
|
}
|
|
122
|
-
tablesByConnection.set(connectionName, connectionToTablesMap);
|
|
123
122
|
}
|
|
124
123
|
// iterate over connections, fetching schema for all missing tables
|
|
125
|
-
for (const [connectionName,
|
|
124
|
+
for (const [connectionName, tablePathByKey] of tablesByConnection) {
|
|
126
125
|
try {
|
|
127
126
|
const connection = await connections.lookupConnection(connectionName);
|
|
128
127
|
// TODO detect if the union of `Object.keys(tables)` and `Object.keys(errors)` is not the same
|
|
129
|
-
// as `Object.keys(
|
|
128
|
+
// as `Object.keys(tablePathByKey)`, i.e. that all tables are accounted for. Otherwise
|
|
130
129
|
// the translator runs into an infinite loop fetching tables.
|
|
131
|
-
const { schemas: tables, errors } = await connection.fetchSchemaForTables(
|
|
130
|
+
const { schemas: tables, errors } = await connection.fetchSchemaForTables(tablePathByKey);
|
|
132
131
|
translator.update({ tables, errors: { tables: errors } });
|
|
133
132
|
}
|
|
134
133
|
catch (error) {
|
|
@@ -136,8 +135,8 @@ class Malloy {
|
|
|
136
135
|
// with all its tables
|
|
137
136
|
const tables = {};
|
|
138
137
|
const errors = {};
|
|
139
|
-
for (const
|
|
140
|
-
errors[
|
|
138
|
+
for (const tableKey in tablePathByKey) {
|
|
139
|
+
errors[tableKey] = error.toString();
|
|
141
140
|
}
|
|
142
141
|
translator.update({ tables, errors: { tables: errors } });
|
|
143
142
|
}
|
|
@@ -491,17 +490,6 @@ class PreparedQuery {
|
|
|
491
490
|
}
|
|
492
491
|
}
|
|
493
492
|
exports.PreparedQuery = PreparedQuery;
|
|
494
|
-
function parseTableURI(tableURI) {
|
|
495
|
-
const parts = tableURI.match(/^([^:]*):(.*)$/);
|
|
496
|
-
if (parts) {
|
|
497
|
-
const [, firstPart, secondPart] = parts;
|
|
498
|
-
return { connectionName: firstPart, tablePath: secondPart };
|
|
499
|
-
}
|
|
500
|
-
else {
|
|
501
|
-
return { tablePath: tableURI };
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
exports.parseTableURI = parseTableURI;
|
|
505
493
|
/**
|
|
506
494
|
* A parsed Malloy document.
|
|
507
495
|
*/
|
|
@@ -533,6 +533,9 @@ export interface FunctionDef extends NamedObject {
|
|
|
533
533
|
type: 'function';
|
|
534
534
|
overloads: FunctionOverloadDef[];
|
|
535
535
|
}
|
|
536
|
+
export interface ConnectionDef extends NamedObject {
|
|
537
|
+
type: 'connection';
|
|
538
|
+
}
|
|
536
539
|
export interface SQLBlockStructDef extends StructDef {
|
|
537
540
|
structSource: SubquerySource;
|
|
538
541
|
declaredSQLBlock?: boolean;
|
|
@@ -561,7 +564,7 @@ export interface FilterExpression {
|
|
|
561
564
|
}
|
|
562
565
|
/** Get the output name for a NamedObject */
|
|
563
566
|
export declare function getIdentifier(n: AliasedName): string;
|
|
564
|
-
export declare type NamedModelObject = StructDef | NamedQuery | FunctionDef;
|
|
567
|
+
export declare type NamedModelObject = StructDef | NamedQuery | FunctionDef | ConnectionDef;
|
|
565
568
|
/** Result of parsing a model file */
|
|
566
569
|
export interface ModelDef {
|
|
567
570
|
name: string;
|