@malloydata/malloy 0.0.297 → 0.0.299
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/core.d.ts +1 -0
- package/dist/api/core.js +16 -10
- package/dist/lang/ast/field-space/index-field-space.js +2 -4
- package/dist/lang/ast/field-space/query-spaces.d.ts +1 -6
- package/dist/lang/ast/field-space/query-spaces.js +5 -34
- package/dist/lang/ast/field-space/struct-space-field-base.js +2 -2
- package/dist/lang/ast/query-properties/filters.js +1 -1
- package/dist/lang/ast/query-properties/qop-desc.js +2 -1
- package/dist/lang/ast/source-properties/join.js +2 -2
- package/dist/lang/syntax-errors/custom-error-messages.js +7 -2
- package/dist/lang/syntax-errors/malloy-parser-error-listener.js +45 -0
- package/dist/lang/utils.d.ts +7 -0
- package/dist/lang/utils.js +13 -0
- package/dist/model/composite_source_utils.js +51 -54
- package/dist/model/malloy_types.d.ts +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
package/dist/api/core.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export interface CompileModelState {
|
|
|
27
27
|
translator: MalloyTranslator;
|
|
28
28
|
done: boolean;
|
|
29
29
|
hasSource: boolean;
|
|
30
|
+
excludeReferences: boolean;
|
|
30
31
|
}
|
|
31
32
|
export declare function updateCompileModelState(state: CompileModelState, needs: Malloy.CompilerNeeds | undefined): void;
|
|
32
33
|
export declare function newCompileModelState(request: Malloy.CompileModelRequest): CompileModelState;
|
package/dist/api/core.js
CHANGED
|
@@ -258,17 +258,18 @@ function updateCompileModelState(state, needs) {
|
|
|
258
258
|
const update = compilerNeedsToUpdate(needs);
|
|
259
259
|
performUpdate(state, update);
|
|
260
260
|
}
|
|
261
|
-
function _newCompileModelState(modelURL, compilerNeeds, extendURL) {
|
|
261
|
+
function _newCompileModelState(modelURL, compilerNeeds, extendURL, excludeReferences = false) {
|
|
262
262
|
var _a, _b, _c, _d;
|
|
263
263
|
const translator = new lang_1.MalloyTranslator(modelURL, null, compilerNeedsToUpdate(compilerNeeds));
|
|
264
264
|
const hasSource = ((_b = (_a = compilerNeeds === null || compilerNeeds === void 0 ? void 0 : compilerNeeds.files) === null || _a === void 0 ? void 0 : _a.some(f => f.url === modelURL)) !== null && _b !== void 0 ? _b : false) ||
|
|
265
265
|
((_d = (_c = compilerNeeds === null || compilerNeeds === void 0 ? void 0 : compilerNeeds.translations) === null || _c === void 0 ? void 0 : _c.some(t => t.url === modelURL)) !== null && _d !== void 0 ? _d : false);
|
|
266
266
|
if (extendURL) {
|
|
267
267
|
return {
|
|
268
|
-
extending: _newCompileModelState(extendURL, compilerNeeds),
|
|
268
|
+
extending: _newCompileModelState(extendURL, compilerNeeds, undefined, excludeReferences),
|
|
269
269
|
translator,
|
|
270
270
|
done: false,
|
|
271
271
|
hasSource,
|
|
272
|
+
excludeReferences,
|
|
272
273
|
};
|
|
273
274
|
}
|
|
274
275
|
else {
|
|
@@ -276,14 +277,15 @@ function _newCompileModelState(modelURL, compilerNeeds, extendURL) {
|
|
|
276
277
|
translator,
|
|
277
278
|
done: false,
|
|
278
279
|
hasSource,
|
|
280
|
+
excludeReferences,
|
|
279
281
|
};
|
|
280
282
|
}
|
|
281
283
|
}
|
|
282
284
|
function newCompileModelState(request) {
|
|
283
|
-
return _newCompileModelState(request.model_url, request.compiler_needs, request.extend_model_url);
|
|
285
|
+
return _newCompileModelState(request.model_url, request.compiler_needs, request.extend_model_url, request.exclude_references);
|
|
284
286
|
}
|
|
285
287
|
function newCompileSourceState(request) {
|
|
286
|
-
return _newCompileModelState(request.model_url, request.compiler_needs, request.extend_model_url);
|
|
288
|
+
return _newCompileModelState(request.model_url, request.compiler_needs, request.extend_model_url, request.exclude_references);
|
|
287
289
|
}
|
|
288
290
|
// function hasNeeds(needs: Malloy.CompilerNeeds | undefined): boolean {
|
|
289
291
|
// if (needs === undefined) return false;
|
|
@@ -328,7 +330,7 @@ function _statedCompileModel(state) {
|
|
|
328
330
|
const model = (0, to_stable_1.modelDefToModelInfo)(result.modelDef);
|
|
329
331
|
return {
|
|
330
332
|
model,
|
|
331
|
-
modelDef: result.modelDef,
|
|
333
|
+
modelDef: maybeExcludeReferences(result.modelDef, state.excludeReferences),
|
|
332
334
|
timingInfo,
|
|
333
335
|
};
|
|
334
336
|
}
|
|
@@ -348,6 +350,14 @@ function _statedCompileModel(state) {
|
|
|
348
350
|
return { compilerNeeds, logs: result.problems, timingInfo };
|
|
349
351
|
}
|
|
350
352
|
}
|
|
353
|
+
function maybeExcludeReferences(modelDef, excludeReferences) {
|
|
354
|
+
if (!excludeReferences)
|
|
355
|
+
return modelDef;
|
|
356
|
+
return {
|
|
357
|
+
...modelDef,
|
|
358
|
+
references: undefined,
|
|
359
|
+
};
|
|
360
|
+
}
|
|
351
361
|
function wrapResponse(response, defaultURL) {
|
|
352
362
|
const logs = response.logs ? (0, util_1.mapLogs)(response.logs, defaultURL) : undefined;
|
|
353
363
|
if (response.compilerNeeds) {
|
|
@@ -375,10 +385,6 @@ function wrapResponse(response, defaultURL) {
|
|
|
375
385
|
};
|
|
376
386
|
}
|
|
377
387
|
}
|
|
378
|
-
function _compileModel(modelURL, compilerNeeds, extendURL, state) {
|
|
379
|
-
state !== null && state !== void 0 ? state : (state = _newCompileModelState(modelURL, compilerNeeds, extendURL));
|
|
380
|
-
return _statedCompileModel(state);
|
|
381
|
-
}
|
|
382
388
|
function compileModel(request, state) {
|
|
383
389
|
state !== null && state !== void 0 ? state : (state = newCompileModelState(request));
|
|
384
390
|
return statedCompileModel(state);
|
|
@@ -435,7 +441,7 @@ function newCompileQueryState(request) {
|
|
|
435
441
|
...((_b = needs.files) !== null && _b !== void 0 ? _b : []),
|
|
436
442
|
];
|
|
437
443
|
return {
|
|
438
|
-
..._newCompileModelState(queryURL, needs, request.model_url),
|
|
444
|
+
..._newCompileModelState(queryURL, needs, request.model_url, request.exclude_references),
|
|
439
445
|
defaultRowLimit: request.default_row_limit,
|
|
440
446
|
};
|
|
441
447
|
}
|
|
@@ -49,17 +49,16 @@ class IndexFieldSpace extends query_spaces_1.QueryOperationSpace {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
getPipeSegment(refineIndex) {
|
|
52
|
+
var _a;
|
|
52
53
|
if (refineIndex) {
|
|
53
54
|
this.logError('refinement-of-index-segment', 'index query operations cannot be refined');
|
|
54
55
|
return { type: 'index', indexFields: [] };
|
|
55
56
|
}
|
|
56
57
|
let fieldUsage = (0, composite_source_utils_1.emptyFieldUsage)();
|
|
57
58
|
const indexFields = [];
|
|
58
|
-
const source = this.inputSpace().structDef();
|
|
59
59
|
for (const [name, field] of this.entries()) {
|
|
60
60
|
if (field instanceof space_field_1.SpaceField) {
|
|
61
61
|
let nextFieldUsage = undefined;
|
|
62
|
-
let logTo = undefined;
|
|
63
62
|
const wild = this.expandedWild[name];
|
|
64
63
|
if (wild) {
|
|
65
64
|
indexFields.push({ type: 'fieldref', path: wild.path, at: wild.at });
|
|
@@ -75,10 +74,9 @@ class IndexFieldSpace extends query_spaces_1.QueryOperationSpace {
|
|
|
75
74
|
else {
|
|
76
75
|
indexFields.push(fieldRef.refToField);
|
|
77
76
|
nextFieldUsage = check.found.typeDesc().fieldUsage;
|
|
78
|
-
logTo = fieldRef;
|
|
79
77
|
}
|
|
80
78
|
}
|
|
81
|
-
fieldUsage =
|
|
79
|
+
fieldUsage = (_a = (0, composite_source_utils_1.mergeFieldUsage)(fieldUsage, nextFieldUsage)) !== null && _a !== void 0 ? _a : [];
|
|
82
80
|
}
|
|
83
81
|
}
|
|
84
82
|
this._fieldUsage = fieldUsage;
|
|
@@ -35,12 +35,10 @@ export declare abstract class QueryOperationSpace extends RefinedSpace implement
|
|
|
35
35
|
compositeFieldUsers: ({
|
|
36
36
|
type: 'filter';
|
|
37
37
|
filter: model.FilterCondition;
|
|
38
|
-
logTo: MalloyElement;
|
|
39
38
|
} | {
|
|
40
39
|
type: 'field';
|
|
41
40
|
name: string;
|
|
42
41
|
field: SpaceField;
|
|
43
|
-
logTo: MalloyElement | undefined;
|
|
44
42
|
})[];
|
|
45
43
|
_fieldUsage: model.FieldUsage[] | undefined;
|
|
46
44
|
get fieldUsage(): model.FieldUsage[];
|
|
@@ -52,11 +50,8 @@ export declare abstract class QueryOperationSpace extends RefinedSpace implement
|
|
|
52
50
|
outputSpace(): QueryOperationSpace;
|
|
53
51
|
protected addWild(wild: WildcardFieldReference): void;
|
|
54
52
|
protected addValidatedCompositeFieldUserFromEntry(name: string, entry: SpaceEntry): void;
|
|
55
|
-
|
|
56
|
-
protected getFieldUsageIncludingJoinOns(fieldUsage: model.FieldUsage[]): model.FieldUsage[];
|
|
57
|
-
addFieldUserFromFilter(filter: model.FilterCondition, logTo: MalloyElement): void;
|
|
53
|
+
addFieldUserFromFilter(filter: model.FilterCondition): void;
|
|
58
54
|
newEntry(name: string, logTo: MalloyElement, entry: SpaceEntry): void;
|
|
59
|
-
protected applyNextFieldUsage(source: model.SourceDef, fieldUsage: model.FieldUsage[], nextFieldUsage: model.FieldUsage[] | undefined, _logTo: MalloyElement | undefined): model.FieldUsage[];
|
|
60
55
|
}
|
|
61
56
|
export declare abstract class QuerySpace extends QueryOperationSpace {
|
|
62
57
|
addRefineFromFields(refineThis: model.PipeSegment): void;
|
|
@@ -66,7 +66,6 @@ const column_space_field_1 = require("./column-space-field");
|
|
|
66
66
|
const static_space_1 = require("./static-space");
|
|
67
67
|
const query_input_space_1 = require("./query-input-space");
|
|
68
68
|
const composite_source_utils_1 = require("../../../model/composite_source_utils");
|
|
69
|
-
const struct_space_field_base_1 = require("./struct-space-field-base");
|
|
70
69
|
/**
|
|
71
70
|
* The output space of a query operation. It is not named "QueryOutputSpace"
|
|
72
71
|
* because this is the namespace of the Query which is a layer of an output and
|
|
@@ -174,48 +173,20 @@ class QueryOperationSpace extends refined_space_1.RefinedSpace {
|
|
|
174
173
|
type: 'field',
|
|
175
174
|
name,
|
|
176
175
|
field: entry,
|
|
177
|
-
logTo: undefined,
|
|
178
176
|
});
|
|
179
177
|
}
|
|
180
178
|
}
|
|
181
|
-
|
|
182
|
-
var _a;
|
|
183
|
-
const reference = joinPath.map(n => new field_space_1.FieldName(n));
|
|
184
|
-
this.astEl.has({ reference });
|
|
185
|
-
const lookup = this.exprSpace.lookup(reference, 'private');
|
|
186
|
-
// Should always be found...
|
|
187
|
-
if (lookup.found && lookup.found instanceof struct_space_field_base_1.StructSpaceFieldBase) {
|
|
188
|
-
return (0, composite_source_utils_1.joinedFieldUsage)(joinPath.slice(0, -1), (_a = lookup.found.fieldDef().onFieldUsage) !== null && _a !== void 0 ? _a : (0, composite_source_utils_1.emptyFieldUsage)());
|
|
189
|
-
}
|
|
190
|
-
throw new Error('Unexpected join lookup was not found or not a struct');
|
|
191
|
-
}
|
|
192
|
-
getFieldUsageIncludingJoinOns(fieldUsage) {
|
|
193
|
-
let fieldUsageIncludingJoinOns = fieldUsage;
|
|
194
|
-
const joinPaths = (0, composite_source_utils_1.fieldUsageJoinPaths)(fieldUsage);
|
|
195
|
-
for (const joinPath of joinPaths) {
|
|
196
|
-
fieldUsageIncludingJoinOns = (0, composite_source_utils_1.mergeFieldUsage)(this.getJoinOnFieldUsage(joinPath), fieldUsageIncludingJoinOns);
|
|
197
|
-
}
|
|
198
|
-
return fieldUsageIncludingJoinOns;
|
|
199
|
-
}
|
|
200
|
-
addFieldUserFromFilter(filter, logTo) {
|
|
179
|
+
addFieldUserFromFilter(filter) {
|
|
201
180
|
if (filter.fieldUsage !== undefined) {
|
|
202
|
-
this.compositeFieldUsers.push({ type: 'filter', filter
|
|
181
|
+
this.compositeFieldUsers.push({ type: 'filter', filter });
|
|
203
182
|
}
|
|
204
183
|
}
|
|
205
184
|
newEntry(name, logTo, entry) {
|
|
206
185
|
if (entry instanceof space_field_1.SpaceField) {
|
|
207
|
-
this.compositeFieldUsers.push({ type: 'field', name, field: entry
|
|
186
|
+
this.compositeFieldUsers.push({ type: 'field', name, field: entry });
|
|
208
187
|
}
|
|
209
188
|
super.newEntry(name, logTo, entry);
|
|
210
189
|
}
|
|
211
|
-
applyNextFieldUsage(source, fieldUsage, nextFieldUsage, _logTo) {
|
|
212
|
-
var _a;
|
|
213
|
-
if (nextFieldUsage) {
|
|
214
|
-
const newFieldUsage = this.getFieldUsageIncludingJoinOns(nextFieldUsage);
|
|
215
|
-
fieldUsage = (_a = (0, composite_source_utils_1.mergeFieldUsage)(fieldUsage, newFieldUsage)) !== null && _a !== void 0 ? _a : [];
|
|
216
|
-
}
|
|
217
|
-
return fieldUsage;
|
|
218
|
-
}
|
|
219
190
|
}
|
|
220
191
|
exports.QueryOperationSpace = QueryOperationSpace;
|
|
221
192
|
// Project and Reduce or "QuerySegments" are built from a QuerySpace
|
|
@@ -264,9 +235,9 @@ class QuerySpace extends QueryOperationSpace {
|
|
|
264
235
|
return true;
|
|
265
236
|
}
|
|
266
237
|
queryFieldDefs() {
|
|
238
|
+
var _a;
|
|
267
239
|
const fields = [];
|
|
268
240
|
let fieldUsage = (0, composite_source_utils_1.emptyFieldUsage)();
|
|
269
|
-
const source = this.inputSpace().structDef();
|
|
270
241
|
for (const user of this.compositeFieldUsers) {
|
|
271
242
|
let nextFieldUsage = undefined;
|
|
272
243
|
if (user.type === 'filter') {
|
|
@@ -306,7 +277,7 @@ class QuerySpace extends QueryOperationSpace {
|
|
|
306
277
|
// fields, but the individual fields didn't have field defs.
|
|
307
278
|
}
|
|
308
279
|
}
|
|
309
|
-
fieldUsage =
|
|
280
|
+
fieldUsage = (_a = (0, composite_source_utils_1.mergeFieldUsage)(fieldUsage, nextFieldUsage)) !== null && _a !== void 0 ? _a : [];
|
|
310
281
|
}
|
|
311
282
|
this._fieldUsage = fieldUsage;
|
|
312
283
|
for (const drillDimension of this.drillDimensions) {
|
|
@@ -81,14 +81,14 @@ class StructSpaceFieldBase extends space_field_1.SpaceField {
|
|
|
81
81
|
type: this.structDef.type,
|
|
82
82
|
evalSpace: 'input',
|
|
83
83
|
expressionType: 'scalar',
|
|
84
|
-
fieldUsage: (_a = this.structDef.
|
|
84
|
+
fieldUsage: (_a = this.structDef.fieldUsage) !== null && _a !== void 0 ? _a : [],
|
|
85
85
|
};
|
|
86
86
|
}
|
|
87
87
|
return {
|
|
88
88
|
...TDU.atomicDef(this.structDef),
|
|
89
89
|
evalSpace: 'input',
|
|
90
90
|
expressionType: 'scalar',
|
|
91
|
-
fieldUsage: (_b = this.structDef.
|
|
91
|
+
fieldUsage: (_b = this.structDef.fieldUsage) !== null && _b !== void 0 ? _b : [],
|
|
92
92
|
};
|
|
93
93
|
}
|
|
94
94
|
}
|
|
@@ -168,7 +168,7 @@ class Filter extends malloy_element_1.ListOf {
|
|
|
168
168
|
const fExpr = this.checkedFilterCondition(filterFS, filter);
|
|
169
169
|
if (fExpr !== undefined) {
|
|
170
170
|
executeFor.filters.push(fExpr);
|
|
171
|
-
executeFor.resultFS.addFieldUserFromFilter(fExpr
|
|
171
|
+
executeFor.resultFS.addFieldUserFromFilter(fExpr);
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
}
|
|
@@ -31,6 +31,7 @@ const struct_utils_1 = require("../struct-utils");
|
|
|
31
31
|
const static_space_1 = require("../field-space/static-space");
|
|
32
32
|
const query_property_interface_1 = require("../types/query-property-interface");
|
|
33
33
|
const partial_builder_1 = require("../query-builders/partial-builder");
|
|
34
|
+
const utils_1 = require("../../utils");
|
|
34
35
|
class QOpDesc extends malloy_element_1.ListOf {
|
|
35
36
|
constructor() {
|
|
36
37
|
super(...arguments);
|
|
@@ -55,7 +56,7 @@ class QOpDesc extends malloy_element_1.ListOf {
|
|
|
55
56
|
if (el.forceQueryClass) {
|
|
56
57
|
if (guessType) {
|
|
57
58
|
if (guessType !== el.forceQueryClass) {
|
|
58
|
-
el.logError(`illegal-${guessType}-operation`, `
|
|
59
|
+
el.logError(`illegal-${guessType}-operation`, `Use of ${(0, utils_1.modernizeTermsForUserText)(el.forceQueryClass)} is not allowed in a ${(0, utils_1.modernizeTermsForUserText)(guessType)} query`);
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
62
|
else {
|
|
@@ -99,7 +99,7 @@ class KeyJoin extends Join {
|
|
|
99
99
|
right: exprX.value,
|
|
100
100
|
},
|
|
101
101
|
};
|
|
102
|
-
inStruct.
|
|
102
|
+
inStruct.fieldUsage = exprX.fieldUsage;
|
|
103
103
|
return;
|
|
104
104
|
}
|
|
105
105
|
else {
|
|
@@ -142,7 +142,7 @@ class ExpressionJoin extends Join {
|
|
|
142
142
|
return;
|
|
143
143
|
}
|
|
144
144
|
inStruct.onExpression = exprX.value;
|
|
145
|
-
inStruct.
|
|
145
|
+
inStruct.fieldUsage = exprX.fieldUsage;
|
|
146
146
|
}
|
|
147
147
|
getStructDef(parameterSpace) {
|
|
148
148
|
var _a;
|
|
@@ -63,12 +63,17 @@ const checkCustomErrorMessage = (parser, offendingSymbol, errorCases) => {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
const errReplace = (s) => {
|
|
66
|
-
|
|
66
|
+
let rs = s
|
|
67
67
|
.replace('${currentToken}', currentToken.text || '')
|
|
68
68
|
.replace('${offendingSymbol}', (offendingSymbol === null || offendingSymbol === void 0 ? void 0 : offendingSymbol.text) || '');
|
|
69
69
|
try {
|
|
70
70
|
const previousToken = parser.inputStream.LT(-1);
|
|
71
|
-
|
|
71
|
+
rs = rs.replace('${previousToken}', previousToken.text || '');
|
|
72
|
+
const offendingSymbolIndex = offendingSymbol === null || offendingSymbol === void 0 ? void 0 : offendingSymbol.tokenIndex;
|
|
73
|
+
if (offendingSymbolIndex && offendingSymbolIndex > 0) {
|
|
74
|
+
const previousSymbol = parser.inputStream.get(offendingSymbolIndex - 1);
|
|
75
|
+
rs = rs.replace('${previousSymbol}', previousSymbol.text || '');
|
|
76
|
+
}
|
|
72
77
|
}
|
|
73
78
|
catch (ex) {
|
|
74
79
|
// This shouldn't ever occur, but if it does, just leave the untokenized message.
|
|
@@ -170,6 +170,51 @@ exports.malloyCustomErrorCases = [
|
|
|
170
170
|
with: ['run:', 'query:', 'source:'],
|
|
171
171
|
},
|
|
172
172
|
},
|
|
173
|
+
{
|
|
174
|
+
errorMessage: '`count(distinct expression)` deprecated, use `count(expression)` instead.',
|
|
175
|
+
offendingSymbol: MalloyParser_1.MalloyParser.DISTINCT,
|
|
176
|
+
ruleContextOptions: ['fieldExpr'],
|
|
177
|
+
precedingTokenOptions: [[MalloyParser_1.MalloyParser.COUNT], [MalloyParser_1.MalloyParser.OPAREN]],
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
errorMessage: "Unexpected type '${offendingSymbol}' in dimension definition. Expected an expression or field reference.",
|
|
181
|
+
offendingSymbolTextOptions: [
|
|
182
|
+
'string',
|
|
183
|
+
'number',
|
|
184
|
+
'int',
|
|
185
|
+
'integer',
|
|
186
|
+
'bool',
|
|
187
|
+
'boolean',
|
|
188
|
+
'date',
|
|
189
|
+
'time',
|
|
190
|
+
'timestamp',
|
|
191
|
+
'array',
|
|
192
|
+
],
|
|
193
|
+
ruleContextOptions: ['fieldExpr'],
|
|
194
|
+
precedingTokenOptions: [[MalloyParser_1.MalloyParser.IDENTIFIER], [MalloyParser_1.MalloyParser.IS]],
|
|
195
|
+
},
|
|
196
|
+
// Identify a case where a user is using an open parenthesis following an
|
|
197
|
+
// identifier that does not represent a valid function.
|
|
198
|
+
{
|
|
199
|
+
errorMessage: "Unknown function '${previousSymbol}'. You can find available functions here: https://docs.malloydata.dev/documentation/language/functions",
|
|
200
|
+
offendingSymbol: MalloyParser_1.MalloyParser.OPAREN,
|
|
201
|
+
ruleContextOptions: ['vExpr'],
|
|
202
|
+
precedingTokenOptions: [[MalloyParser_1.MalloyParser.IDENTIFIER]],
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
errorMessage: "The 'project:' keyword is no longer supported. Use 'select:' instead.",
|
|
206
|
+
offendingSymbol: MalloyParser_1.MalloyParser.PROJECT,
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
errorMessage: "Unsupported keyword 'as'. Use 'is' to name something (ex: `dimension: name is expression`)",
|
|
210
|
+
offendingSymbolTextOptions: ['as'],
|
|
211
|
+
ruleContextOptions: ['isDefine'],
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
// Broader catch-all case for the 'as' keyword, including an alternative example.
|
|
215
|
+
errorMessage: "Unsupported keyword 'as'. Use 'is' to name something (ex: `select: new_name is column_name`)",
|
|
216
|
+
offendingSymbolTextOptions: ['as'],
|
|
217
|
+
},
|
|
173
218
|
];
|
|
174
219
|
class MalloyParserErrorListener {
|
|
175
220
|
constructor(
|
package/dist/lang/utils.d.ts
CHANGED
|
@@ -19,6 +19,13 @@ export declare function rangeFromContext(sourceInfo: SourceInfo | undefined, pcx
|
|
|
19
19
|
* to the line/char positions favored by LSP and VSCode.
|
|
20
20
|
*/
|
|
21
21
|
export declare function getSourceInfo(code: string): SourceInfo;
|
|
22
|
+
/**
|
|
23
|
+
* Rewrites text that is going to be presented to end users to avoid
|
|
24
|
+
* using terminology that is deprecated or changed.
|
|
25
|
+
*
|
|
26
|
+
* @param text raw text that is being used internally in Malloy
|
|
27
|
+
*/
|
|
28
|
+
export declare function modernizeTermsForUserText(text: string): string;
|
|
22
29
|
export interface ParseInfo {
|
|
23
30
|
root: ParseTree;
|
|
24
31
|
tokenStream: CommonTokenStream;
|
package/dist/lang/utils.js
CHANGED
|
@@ -28,6 +28,7 @@ exports.rangeFromTokens = rangeFromTokens;
|
|
|
28
28
|
exports.rangeFromToken = rangeFromToken;
|
|
29
29
|
exports.rangeFromContext = rangeFromContext;
|
|
30
30
|
exports.getSourceInfo = getSourceInfo;
|
|
31
|
+
exports.modernizeTermsForUserText = modernizeTermsForUserText;
|
|
31
32
|
function locationContainsPosition(location, position) {
|
|
32
33
|
return (location.range.start.line <= position.line &&
|
|
33
34
|
location.range.end.line >= position.line &&
|
|
@@ -112,4 +113,16 @@ function getSourceInfo(code) {
|
|
|
112
113
|
}
|
|
113
114
|
return info;
|
|
114
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Rewrites text that is going to be presented to end users to avoid
|
|
118
|
+
* using terminology that is deprecated or changed.
|
|
119
|
+
*
|
|
120
|
+
* @param text raw text that is being used internally in Malloy
|
|
121
|
+
*/
|
|
122
|
+
function modernizeTermsForUserText(text) {
|
|
123
|
+
if (text === 'project') {
|
|
124
|
+
return 'select';
|
|
125
|
+
}
|
|
126
|
+
return text;
|
|
127
|
+
}
|
|
115
128
|
//# sourceMappingURL=utils.js.map
|
|
@@ -26,12 +26,11 @@ exports.logCompositeError = logCompositeError;
|
|
|
26
26
|
exports.compileFilterExpression = compileFilterExpression;
|
|
27
27
|
const malloy_filter_1 = require("@malloydata/malloy-filter");
|
|
28
28
|
const malloy_types_1 = require("./malloy_types");
|
|
29
|
-
const utils_1 = require("
|
|
30
|
-
const utils_2 = require("../lang/utils");
|
|
29
|
+
const utils_1 = require("../lang/utils");
|
|
31
30
|
function _resolveCompositeSources(path, source, rootFields, nests, fieldUsage,
|
|
32
31
|
// for resolving nested composites; the list of sources to try
|
|
33
32
|
sources) {
|
|
34
|
-
var _a, _b, _c;
|
|
33
|
+
var _a, _b, _c, _d;
|
|
35
34
|
// TODO skip all this if the tree doesn't have any composite sources
|
|
36
35
|
let base = { ...source };
|
|
37
36
|
let anyComposites = false;
|
|
@@ -62,8 +61,9 @@ sources) {
|
|
|
62
61
|
fieldNames.add((_a = field.as) !== null && _a !== void 0 ? _a : field.name);
|
|
63
62
|
}
|
|
64
63
|
}
|
|
64
|
+
const fieldUsageWithWheres = (_b = mergeFieldUsage(fieldUsage, getFieldUsageFromFilterList(inputSource))) !== null && _b !== void 0 ? _b : [];
|
|
65
65
|
const fieldsForLookup = [...nonCompositeFields, ...inputSource.fields];
|
|
66
|
-
const expanded = expandFieldUsage(
|
|
66
|
+
const expanded = expandFieldUsage(fieldUsageWithWheres, fieldsForLookup);
|
|
67
67
|
if (expanded.missingFields.length > 0) {
|
|
68
68
|
// A lookup failed while expanding, which means this source certainly won't work
|
|
69
69
|
for (const missingField of expanded.missingFields) {
|
|
@@ -96,8 +96,13 @@ sources) {
|
|
|
96
96
|
if (inputSource.type === 'composite') {
|
|
97
97
|
const resolveInner = _resolveCompositeSources(path, inputSource, genRootFields(rootFields, path, fieldsForLookup, false), nests, compositeUsageInThisSource, inputSource.sources);
|
|
98
98
|
if ('error' in resolveInner) {
|
|
99
|
-
// Third point where we abort; if a nested composite failed
|
|
100
|
-
|
|
99
|
+
// Third point where we abort; if a nested composite failed; we don't call abort() because we want to unnest the failures from
|
|
100
|
+
if (resolveInner.error.code === 'no_suitable_composite_source_input') {
|
|
101
|
+
failures.push(...resolveInner.error.data.failures);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
abort();
|
|
105
|
+
}
|
|
101
106
|
continue overSources;
|
|
102
107
|
}
|
|
103
108
|
base = {
|
|
@@ -116,7 +121,7 @@ sources) {
|
|
|
116
121
|
...base,
|
|
117
122
|
fields,
|
|
118
123
|
arguments: source.arguments,
|
|
119
|
-
filterList: [...((
|
|
124
|
+
filterList: [...((_c = source.filterList) !== null && _c !== void 0 ? _c : []), ...((_d = base.filterList) !== null && _d !== void 0 ? _d : [])],
|
|
120
125
|
};
|
|
121
126
|
const joinError = processJoins(path, base, rootFields, nests, expandedCategorized);
|
|
122
127
|
// Fourth point where we abort: if a join failed
|
|
@@ -198,6 +203,7 @@ function onlyCompositeUsage(fieldUsage, fields) {
|
|
|
198
203
|
});
|
|
199
204
|
}
|
|
200
205
|
function expandFieldUsage(fieldUsage, fields) {
|
|
206
|
+
var _a;
|
|
201
207
|
const allFieldPathsReferenced = [...fieldUsage];
|
|
202
208
|
const joinPathsProcessed = [];
|
|
203
209
|
const missingFields = [];
|
|
@@ -217,17 +223,15 @@ function expandFieldUsage(fieldUsage, fields) {
|
|
|
217
223
|
continue;
|
|
218
224
|
}
|
|
219
225
|
if ((0, malloy_types_1.isAtomic)(def)) {
|
|
220
|
-
const fieldUsage =
|
|
226
|
+
const fieldUsage = (_a = def.fieldUsage) !== null && _a !== void 0 ? _a : [];
|
|
221
227
|
allFieldPathsReferenced.push(...fieldUsageAt(joinedFieldUsage(referenceJoinPath, fieldUsage), reference.at).filter(u1 => !allFieldPathsReferenced.some(u2 => pathEq(u1.path, u2.path))));
|
|
222
228
|
}
|
|
223
229
|
if (reference.path.length > 1) {
|
|
224
230
|
if (!joinPathsProcessed.some(p => pathEq(p, referenceJoinPath))) {
|
|
225
231
|
joinPathsProcessed.push(referenceJoinPath);
|
|
226
232
|
const join = lookup(referenceJoinPath, fields);
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
const fieldUsage = getFieldUsageForField(join);
|
|
230
|
-
allFieldPathsReferenced.push(...fieldUsageAt(joinedFieldUsage(joinJoinPath, fieldUsage), reference.at).filter(u1 => !allFieldPathsReferenced.some(u2 => pathEq(u1.path, u2.path))));
|
|
233
|
+
const joinFieldUsage = getJoinFieldUsage(join, referenceJoinPath);
|
|
234
|
+
allFieldPathsReferenced.push(...fieldUsageAt(joinFieldUsage, reference.at).filter(u1 => !allFieldPathsReferenced.some(u2 => pathEq(u1.path, u2.path))));
|
|
231
235
|
}
|
|
232
236
|
}
|
|
233
237
|
}
|
|
@@ -384,14 +388,19 @@ function processJoins(path, base, rootFields, nests, categorizedFieldUsage) {
|
|
|
384
388
|
}
|
|
385
389
|
return { anyComposites, errors };
|
|
386
390
|
}
|
|
387
|
-
function
|
|
391
|
+
function getFieldUsageFromFilterList(source) {
|
|
388
392
|
var _a;
|
|
393
|
+
return ((_a = source.filterList) !== null && _a !== void 0 ? _a : []).flatMap(filter => { var _a; return (_a = filter.fieldUsage) !== null && _a !== void 0 ? _a : []; });
|
|
394
|
+
}
|
|
395
|
+
function resolveCompositeSources(source, segment, fieldUsage) {
|
|
396
|
+
var _a, _b;
|
|
389
397
|
const sourceExtensions = (0, malloy_types_1.isQuerySegment)(segment)
|
|
390
398
|
? (_a = segment.extendSource) !== null && _a !== void 0 ? _a : []
|
|
391
399
|
: [];
|
|
392
400
|
const nestLevels = extractNestLevels(segment);
|
|
393
401
|
const fields = mergeFields(source.fields, sourceExtensions);
|
|
394
|
-
const
|
|
402
|
+
const fieldUsageWithWheres = (_b = mergeFieldUsage(fieldUsage, getFieldUsageFromFilterList(source))) !== null && _b !== void 0 ? _b : [];
|
|
403
|
+
const result = _resolveCompositeSources([], source, fields, nestLevels, fieldUsageWithWheres);
|
|
395
404
|
if ('success' in result) {
|
|
396
405
|
if (result.anyComposites) {
|
|
397
406
|
return { sourceDef: result.success, error: undefined };
|
|
@@ -498,27 +507,6 @@ function isCompositeField(fieldDef) {
|
|
|
498
507
|
function getNonCompositeFields(source) {
|
|
499
508
|
return source.fields.filter(f => !isCompositeField(f));
|
|
500
509
|
}
|
|
501
|
-
function getFieldUsageFromExpr(expr) {
|
|
502
|
-
const fieldUsage = [];
|
|
503
|
-
for (const node of (0, utils_1.exprWalk)(expr)) {
|
|
504
|
-
if (node.node === 'field') {
|
|
505
|
-
fieldUsage.push({
|
|
506
|
-
path: node.path,
|
|
507
|
-
at: node.at,
|
|
508
|
-
});
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
return fieldUsage;
|
|
512
|
-
}
|
|
513
|
-
function getFieldUsageForField(field) {
|
|
514
|
-
if ((0, malloy_types_1.isAtomic)(field) && field.e) {
|
|
515
|
-
return getFieldUsageFromExpr(field.e);
|
|
516
|
-
}
|
|
517
|
-
else if ((0, malloy_types_1.isJoined)(field) && field.onExpression) {
|
|
518
|
-
return getFieldUsageFromExpr(field.onExpression);
|
|
519
|
-
}
|
|
520
|
-
return [];
|
|
521
|
-
}
|
|
522
510
|
function nestLevelsAt(nests, at) {
|
|
523
511
|
var _a;
|
|
524
512
|
if (at === undefined)
|
|
@@ -570,7 +558,7 @@ function joinedUngroupings(joinPath, ungroupings) {
|
|
|
570
558
|
}));
|
|
571
559
|
}
|
|
572
560
|
function extractNestLevels(segment) {
|
|
573
|
-
var _a, _b, _c;
|
|
561
|
+
var _a, _b, _c, _d;
|
|
574
562
|
const fieldsReferencedDirectly = [];
|
|
575
563
|
const fieldsReferenced = [];
|
|
576
564
|
const nested = [];
|
|
@@ -594,12 +582,13 @@ function extractNestLevels(segment) {
|
|
|
594
582
|
nested.push(nestLevelsAt(extractNestLevels(head), head.referencedAt));
|
|
595
583
|
}
|
|
596
584
|
else {
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
585
|
+
const fieldUsage = (_a = field.fieldUsage) !== null && _a !== void 0 ? _a : [];
|
|
586
|
+
fieldsReferenced.push(...fieldUsage);
|
|
587
|
+
ungroupings.push(...((_b = field.ungroupings) !== null && _b !== void 0 ? _b : []));
|
|
588
|
+
requiredGroupBys.push(...((_c = field.requiresGroupBy) !== null && _c !== void 0 ? _c : []));
|
|
600
589
|
}
|
|
601
590
|
}
|
|
602
|
-
for (const filter of (
|
|
591
|
+
for (const filter of (_d = segment.filterList) !== null && _d !== void 0 ? _d : []) {
|
|
603
592
|
if (!(0, malloy_types_1.expressionIsScalar)(filter.expressionType))
|
|
604
593
|
continue;
|
|
605
594
|
const fields = getSingleValueFilterFields(filter.e);
|
|
@@ -677,7 +666,7 @@ function isSingleValueFilterNode(e) {
|
|
|
677
666
|
}
|
|
678
667
|
}
|
|
679
668
|
function expandRefs(nests, fields) {
|
|
680
|
-
var _a, _b, _c;
|
|
669
|
+
var _a, _b, _c, _d;
|
|
681
670
|
const newNests = [];
|
|
682
671
|
const requiredGroupBys = [...nests.requiredGroupBys];
|
|
683
672
|
const allUngroupings = [...nests.ungroupings];
|
|
@@ -718,7 +707,7 @@ function expandRefs(nests, fields) {
|
|
|
718
707
|
if (def.ungroupings) {
|
|
719
708
|
allUngroupings.push(...joinedUngroupings(joinPath, ungroupingsAt(def.ungroupings, field.at)));
|
|
720
709
|
}
|
|
721
|
-
const fieldUsage =
|
|
710
|
+
const fieldUsage = (_a = def.fieldUsage) !== null && _a !== void 0 ? _a : [];
|
|
722
711
|
const moreReferences = fieldUsageAt(joinedFieldUsage(joinPath, fieldUsage), field.at).filter(u1 => !references.some(u2 => pathEq(u1.path, u2.path)));
|
|
723
712
|
references.push(...moreReferences);
|
|
724
713
|
}
|
|
@@ -726,10 +715,8 @@ function expandRefs(nests, fields) {
|
|
|
726
715
|
if (!joinPathsProcessed.some(p => pathEq(p, joinPath))) {
|
|
727
716
|
joinPathsProcessed.push(joinPath);
|
|
728
717
|
const join = lookup(joinPath, fields);
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
const fieldUsage = getFieldUsageForField(join);
|
|
732
|
-
references.push(...fieldUsageAt(joinedFieldUsage(joinJoinPath, fieldUsage), field.at).filter(u1 => !references.some(u2 => pathEq(u1.path, u2.path))));
|
|
718
|
+
const joinFieldUsage = getJoinFieldUsage(join, joinPath);
|
|
719
|
+
references.push(...fieldUsageAt(joinFieldUsage, field.at).filter(u1 => !references.some(u2 => pathEq(u1.path, u2.path))));
|
|
733
720
|
}
|
|
734
721
|
}
|
|
735
722
|
}
|
|
@@ -740,10 +727,10 @@ function expandRefs(nests, fields) {
|
|
|
740
727
|
fieldsReferencedDirectly: [],
|
|
741
728
|
ungroupings: [],
|
|
742
729
|
nested: [],
|
|
743
|
-
requiredGroupBys: (
|
|
730
|
+
requiredGroupBys: (_b = ungrouping.requiresGroupBy) !== null && _b !== void 0 ? _b : [],
|
|
744
731
|
singleValueFilters: [],
|
|
745
732
|
}, fields);
|
|
746
|
-
missingFields.push(...((
|
|
733
|
+
missingFields.push(...((_c = expanded.missingFields) !== null && _c !== void 0 ? _c : []));
|
|
747
734
|
for (const field of expanded.result.requiredGroupBys) {
|
|
748
735
|
if (isUngroupedBy(ungrouping, field.path)) {
|
|
749
736
|
unsatisfiableGroupBys.push(field);
|
|
@@ -753,7 +740,7 @@ function expandRefs(nests, fields) {
|
|
|
753
740
|
const nested = [];
|
|
754
741
|
for (const level of [...nests.nested, ...newNests]) {
|
|
755
742
|
const expanded = expandRefs(level, fields);
|
|
756
|
-
missingFields.push(...((
|
|
743
|
+
missingFields.push(...((_d = expanded.missingFields) !== null && _d !== void 0 ? _d : []));
|
|
757
744
|
nested.push(expanded.result);
|
|
758
745
|
unsatisfiableGroupBys.push(...expanded.result.unsatisfiableGroupBys);
|
|
759
746
|
}
|
|
@@ -768,6 +755,15 @@ function expandRefs(nests, fields) {
|
|
|
768
755
|
missingFields: missingFields.length > 0 ? missingFields : undefined,
|
|
769
756
|
};
|
|
770
757
|
}
|
|
758
|
+
function getJoinFieldUsage(join, joinPath) {
|
|
759
|
+
var _a, _b;
|
|
760
|
+
return ((_b = mergeFieldUsage(
|
|
761
|
+
// For `fieldUsage` from join `on`, we need the path excluding the join name, since it's
|
|
762
|
+
// already rooted at the parent
|
|
763
|
+
joinedFieldUsage(joinPath.slice(0, -1), (_a = join.fieldUsage) !== null && _a !== void 0 ? _a : []),
|
|
764
|
+
// For `fieldUsage` from join `where`s, we need the path including the join name
|
|
765
|
+
joinedFieldUsage(joinPath, (0, malloy_types_1.isSourceDef)(join) ? getFieldUsageFromFilterList(join) : []))) !== null && _b !== void 0 ? _b : []);
|
|
766
|
+
}
|
|
771
767
|
function isUngroupedBy(ungrouping, groupedBy) {
|
|
772
768
|
if (ungrouping.ungroupedFields === '*')
|
|
773
769
|
return true;
|
|
@@ -882,13 +878,14 @@ function logCompositeError(error, logTo) {
|
|
|
882
878
|
if (error.code === 'no_suitable_composite_source_input') {
|
|
883
879
|
const firstFails = error.data.failures.map(failure => failure.issues[0]);
|
|
884
880
|
const sorted = sortIssuesByReferenceLocation(firstFails);
|
|
881
|
+
const joinPath = error.data.path;
|
|
885
882
|
const usages = sorted.map(issueFieldUsage);
|
|
886
883
|
const lastIssue = sorted[sorted.length - 1];
|
|
887
884
|
const lastUsage = usages[usages.length - 1];
|
|
888
885
|
const conflictingUsage = firstFails
|
|
889
886
|
.filter(i => i.type === 'missing-field')
|
|
890
887
|
.map(i => i.field);
|
|
891
|
-
const fConflictingUsage = formatFieldUsages(conflictingUsage);
|
|
888
|
+
const fConflictingUsage = formatFieldUsages(joinedFieldUsage(joinPath, conflictingUsage));
|
|
892
889
|
const dConflictingUsage = conflictingUsage.length > 0
|
|
893
890
|
? `there is no composite input source which defines all of ${fConflictingUsage}`
|
|
894
891
|
: undefined;
|
|
@@ -912,12 +909,12 @@ function logCompositeError(error, logTo) {
|
|
|
912
909
|
? `${joinPlural} ${formatPaths(uniqueFailedJoins)} could not be resolved`
|
|
913
910
|
: undefined;
|
|
914
911
|
const dLastIssue = lastUsage
|
|
915
|
-
? `uses field ${formatFieldUsages([lastUsage])}, resulting in`
|
|
912
|
+
? `uses field ${formatFieldUsages(joinedFieldUsage(joinPath, [lastUsage]))}, resulting in`
|
|
916
913
|
: 'results in';
|
|
917
914
|
const dIssues = dConflictingUsageAndMissingGroupBys
|
|
918
|
-
? commaAndList([dConflictingUsageAndMissingGroupBys, dFailedJoins].filter(
|
|
919
|
-
: commaAndList([dConflictingUsage, dMissingGroupBys, dFailedJoins].filter(
|
|
920
|
-
const message = `This operation ${dLastIssue} invalid usage of the composite source, as ${dIssues} (fields required in source: ${formatFieldUsages(error.data.usage)})`;
|
|
915
|
+
? commaAndList([dConflictingUsageAndMissingGroupBys, dFailedJoins].filter(utils_1.isNotUndefined))
|
|
916
|
+
: commaAndList([dConflictingUsage, dMissingGroupBys, dFailedJoins].filter(utils_1.isNotUndefined));
|
|
917
|
+
const message = `This operation ${dLastIssue} invalid usage of the composite source, as ${dIssues} (fields required in source: ${formatFieldUsages(joinedFieldUsage(joinPath, error.data.usage))})`;
|
|
921
918
|
logTo.logError('could-not-resolve-composite-source', message, {
|
|
922
919
|
at: issueLocation(lastIssue),
|
|
923
920
|
});
|
|
@@ -467,7 +467,7 @@ export interface JoinBase {
|
|
|
467
467
|
join: JoinType;
|
|
468
468
|
matrixOperation?: MatrixOperation;
|
|
469
469
|
onExpression?: Expr;
|
|
470
|
-
|
|
470
|
+
fieldUsage?: FieldUsage[];
|
|
471
471
|
accessModifier?: NonDefaultAccessModifierLabel | undefined;
|
|
472
472
|
}
|
|
473
473
|
export type Joinable = CompositeSourceDef | TableSourceDef | SQLSourceDef | QuerySourceDef | RepeatedRecordDef | RecordDef | ArrayDef;
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const MALLOY_VERSION = "0.0.
|
|
1
|
+
export declare const MALLOY_VERSION = "0.0.299";
|
package/dist/version.js
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MALLOY_VERSION = void 0;
|
|
4
4
|
// generated with 'generate-version-file' script; do not edit manually
|
|
5
|
-
exports.MALLOY_VERSION = '0.0.
|
|
5
|
+
exports.MALLOY_VERSION = '0.0.299';
|
|
6
6
|
//# sourceMappingURL=version.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@malloydata/malloy",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.299",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dist/index.js",
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"generate-version-file": "VERSION=$(npm pkg get version --workspaces=false | tr -d \\\")\necho \"// generated with 'generate-version-file' script; do not edit manually\\nexport const MALLOY_VERSION = '$VERSION';\" > src/version.ts"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@malloydata/malloy-filter": "0.0.
|
|
45
|
-
"@malloydata/malloy-interfaces": "0.0.
|
|
46
|
-
"@malloydata/malloy-tag": "0.0.
|
|
44
|
+
"@malloydata/malloy-filter": "0.0.299",
|
|
45
|
+
"@malloydata/malloy-interfaces": "0.0.299",
|
|
46
|
+
"@malloydata/malloy-tag": "0.0.299",
|
|
47
47
|
"antlr4ts": "^0.5.0-alpha.4",
|
|
48
48
|
"assert": "^2.0.0",
|
|
49
49
|
"jaro-winkler": "^0.2.8",
|