@malloydata/malloy 0.0.262 → 0.0.263-dev250414184158
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lang/ast/expressions/expr-filter-expr.d.ts +0 -3
- package/dist/lang/ast/expressions/expr-filter-expr.js +7 -59
- package/dist/lang/ast/expressions/expr-func.js +3 -0
- package/dist/lang/ast/expressions/pick-when.js +6 -0
- package/dist/lang/ast/field-space/dynamic-space.js +1 -1
- package/dist/lang/ast/field-space/join-space-field.js +1 -1
- package/dist/lang/ast/index.d.ts +1 -0
- package/dist/lang/ast/index.js +1 -0
- package/dist/lang/ast/parameters/has-parameter.d.ts +6 -3
- package/dist/lang/ast/parameters/has-parameter.js +28 -9
- package/dist/lang/ast/query-items/field-declaration.d.ts +1 -2
- package/dist/lang/ast/query-items/field-declaration.js +0 -4
- package/dist/lang/ast/source-elements/named-source.js +6 -0
- package/dist/lang/ast/source-properties/join.d.ts +3 -3
- package/dist/lang/ast/source-properties/join.js +2 -2
- package/dist/lang/ast/types/expression-def.d.ts +2 -1
- package/dist/lang/ast/types/expression-def.js +79 -17
- package/dist/lang/ast/types/space-param.d.ts +1 -3
- package/dist/lang/ast/types/space-param.js +8 -8
- package/dist/lang/lib/Malloy/MalloyLexer.d.ts +114 -113
- package/dist/lang/lib/Malloy/MalloyLexer.js +1272 -1266
- package/dist/lang/lib/Malloy/MalloyParser.d.ts +253 -239
- package/dist/lang/lib/Malloy/MalloyParser.js +2244 -2142
- package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +11 -0
- package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +7 -0
- package/dist/lang/malloy-to-ast.d.ts +1 -1
- package/dist/lang/malloy-to-ast.js +38 -12
- package/dist/lang/test/expr-to-str.js +3 -20
- package/dist/model/filter_compilers.d.ts +27 -0
- package/dist/model/filter_compilers.js +335 -3
- package/dist/model/malloy_query.d.ts +2 -1
- package/dist/model/malloy_query.js +45 -10
- package/dist/model/malloy_types.d.ts +18 -6
- package/dist/model/malloy_types.js +6 -2
- package/dist/to_stable.js +19 -5
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
- package/dist/model/filter_temporal_compiler.d.ts +0 -29
- package/dist/model/filter_temporal_compiler.js +0 -343
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import type { BinaryMalloyOperator } from '../types/binary_operators';
|
|
2
1
|
import type { ExprValue } from '../types/expr-value';
|
|
3
2
|
import { ExpressionDef } from '../types/expression-def';
|
|
4
|
-
import type { FieldSpace } from '../types/field-space';
|
|
5
3
|
export declare class ExprFilterExpression extends ExpressionDef {
|
|
6
4
|
readonly filterText: string;
|
|
7
5
|
elementType: string;
|
|
8
6
|
constructor(filterText: string);
|
|
9
7
|
getExpression(): ExprValue;
|
|
10
|
-
apply(fs: FieldSpace, op: BinaryMalloyOperator, left: ExpressionDef, _warnOnComplexTree?: boolean): ExprValue;
|
|
11
8
|
}
|
|
@@ -7,9 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.ExprFilterExpression = void 0;
|
|
10
|
-
const expr_value_1 = require("../types/expr-value");
|
|
11
10
|
const expression_def_1 = require("../types/expression-def");
|
|
12
|
-
const malloy_filter_1 = require("@malloydata/malloy-filter");
|
|
13
11
|
class ExprFilterExpression extends expression_def_1.ExpressionDef {
|
|
14
12
|
constructor(filterText) {
|
|
15
13
|
super();
|
|
@@ -17,63 +15,13 @@ class ExprFilterExpression extends expression_def_1.ExpressionDef {
|
|
|
17
15
|
this.elementType = 'filter expression literal';
|
|
18
16
|
}
|
|
19
17
|
getExpression() {
|
|
20
|
-
return
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return matchExpr;
|
|
28
|
-
}
|
|
29
|
-
let fParse;
|
|
30
|
-
switch (matchExpr.type) {
|
|
31
|
-
case 'string':
|
|
32
|
-
fParse = malloy_filter_1.StringFilterExpression.parse(this.filterText);
|
|
33
|
-
break;
|
|
34
|
-
case 'number':
|
|
35
|
-
fParse = malloy_filter_1.NumberFilterExpression.parse(this.filterText);
|
|
36
|
-
break;
|
|
37
|
-
case 'boolean':
|
|
38
|
-
if ((_a = fs.dialectObj()) === null || _a === void 0 ? void 0 : _a.booleanAsNumbers) {
|
|
39
|
-
return this.loggedErrorExpr('filter-expression-type', 'Boolean filters not supported on this connection type');
|
|
40
|
-
}
|
|
41
|
-
fParse = malloy_filter_1.BooleanFilterExpression.parse(this.filterText);
|
|
42
|
-
break;
|
|
43
|
-
case 'date':
|
|
44
|
-
case 'timestamp':
|
|
45
|
-
fParse = malloy_filter_1.TemporalFilterExpression.parse(this.filterText);
|
|
46
|
-
break;
|
|
47
|
-
default:
|
|
48
|
-
return left.loggedErrorExpr('filter-expression-type', `Cannot use filter expressions with type '${matchExpr.type}'`);
|
|
49
|
-
}
|
|
50
|
-
if (fParse.log.length > 0) {
|
|
51
|
-
for (const err of fParse.log) {
|
|
52
|
-
// Current parser only ever returns one error, it doesn't recover
|
|
53
|
-
// Theoretically possible to user the startIndex to point to the
|
|
54
|
-
// error inside the filter string, but I don't know if this is an
|
|
55
|
-
// f' string or an f''' string, and I think the startOffset is from
|
|
56
|
-
// the first non blank space in the filter (it was at one point)
|
|
57
|
-
// so for now, we just flag the entire filter source token.
|
|
58
|
-
return this.loggedErrorExpr('filter-expression-error', `Filter parse error: ${err.message}`);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
const filterMatch = {
|
|
62
|
-
node: 'filterMatch',
|
|
63
|
-
dataType: matchExpr.type,
|
|
64
|
-
filter: fParse.parsed,
|
|
65
|
-
e: matchExpr.value,
|
|
66
|
-
};
|
|
67
|
-
if (op === '!~') {
|
|
68
|
-
filterMatch.notMatch = true;
|
|
69
|
-
}
|
|
70
|
-
return (0, expr_value_1.computedExprValue)({
|
|
71
|
-
value: filterMatch,
|
|
72
|
-
dataType: { type: 'boolean' },
|
|
73
|
-
from: [matchExpr],
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
return this.loggedErrorExpr('filter-expression-type', `Cannot use the '${op}' operator with a filter expression`);
|
|
18
|
+
return {
|
|
19
|
+
type: 'filter expression',
|
|
20
|
+
value: { node: 'filterLiteral', filterSrc: this.filterText },
|
|
21
|
+
expressionType: 'scalar',
|
|
22
|
+
evalSpace: 'constant',
|
|
23
|
+
compositeFieldUsage: { fields: [], joinedUsage: {} },
|
|
24
|
+
};
|
|
77
25
|
}
|
|
78
26
|
}
|
|
79
27
|
exports.ExprFilterExpression = ExprFilterExpression;
|
|
@@ -309,6 +309,9 @@ class ExprFunc extends expression_def_1.ExpressionDef {
|
|
|
309
309
|
if (result.found === undefined) {
|
|
310
310
|
return this.loggedErrorExpr('sql-function-interpolation-not-found', `Invalid interpolation: ${result.error.message}`);
|
|
311
311
|
}
|
|
312
|
+
if (result.found.typeDesc().type === 'filter expression') {
|
|
313
|
+
return this.loggedErrorExpr('filter-expression-error', 'Filter expressions cannot be used in sql_ functions');
|
|
314
|
+
}
|
|
312
315
|
if (result.found.refType === 'parameter') {
|
|
313
316
|
expr.push({ node: 'parameter', path: [part.name] });
|
|
314
317
|
}
|
|
@@ -129,6 +129,9 @@ class Pick extends expression_def_1.ExpressionDef {
|
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
|
+
if (definedReturnType.type === 'filter expression') {
|
|
133
|
+
return this.loggedErrorExpr('filter-expression-error', 'Pick statments cannot have filter expression values');
|
|
134
|
+
}
|
|
132
135
|
caseValue.kids.caseElse = defaultVal.value;
|
|
133
136
|
return (0, expr_value_1.computedExprValue)({
|
|
134
137
|
dataType: definedReturnType,
|
|
@@ -188,6 +191,9 @@ class Pick extends expression_def_1.ExpressionDef {
|
|
|
188
191
|
returnType: definedReturnType.type,
|
|
189
192
|
});
|
|
190
193
|
}
|
|
194
|
+
if (definedReturnType.type === 'filter expression') {
|
|
195
|
+
return this.loggedErrorExpr('filter-expression-error', 'Pick statments cannot have filter expression values');
|
|
196
|
+
}
|
|
191
197
|
pick.kids.caseElse = defVal.value;
|
|
192
198
|
return (0, expr_value_1.computedExprValue)({
|
|
193
199
|
dataType: definedReturnType,
|
|
@@ -134,7 +134,7 @@ class DynamicSpace extends static_space_1.StaticSpace {
|
|
|
134
134
|
const parameterSpace = this.parameterSpace();
|
|
135
135
|
for (const [name, field] of reorderFields) {
|
|
136
136
|
if (field instanceof join_space_field_1.JoinSpaceField) {
|
|
137
|
-
const joinStruct = field.join.
|
|
137
|
+
const joinStruct = field.join.getStructDef(parameterSpace);
|
|
138
138
|
if (!error_factory_1.ErrorFactory.didCreate(joinStruct)) {
|
|
139
139
|
fieldIndices.set(name, this.sourceDef.fields.length);
|
|
140
140
|
this.sourceDef.fields.push(joinStruct);
|
|
@@ -26,7 +26,7 @@ exports.JoinSpaceField = void 0;
|
|
|
26
26
|
const static_space_1 = require("./static-space");
|
|
27
27
|
class JoinSpaceField extends static_space_1.StructSpaceField {
|
|
28
28
|
constructor(parameterSpace, join, forDialect) {
|
|
29
|
-
super(join.
|
|
29
|
+
super(join.getStructDef(parameterSpace), forDialect);
|
|
30
30
|
this.parameterSpace = parameterSpace;
|
|
31
31
|
this.join = join;
|
|
32
32
|
}
|
package/dist/lang/ast/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export * from './source-properties/timezone-statement';
|
|
|
19
19
|
export * from './expressions/apply';
|
|
20
20
|
export * from './expressions/binary-numeric';
|
|
21
21
|
export * from './expressions/boolean';
|
|
22
|
+
export * from './expressions/constant-expression';
|
|
22
23
|
export * from './expressions/function-ordering';
|
|
23
24
|
export * from './expressions/expr-add-sub';
|
|
24
25
|
export * from './expressions/expr-aggregate-function';
|
package/dist/lang/ast/index.js
CHANGED
|
@@ -57,6 +57,7 @@ __exportStar(require("./source-properties/timezone-statement"), exports);
|
|
|
57
57
|
__exportStar(require("./expressions/apply"), exports);
|
|
58
58
|
__exportStar(require("./expressions/binary-numeric"), exports);
|
|
59
59
|
__exportStar(require("./expressions/boolean"), exports);
|
|
60
|
+
__exportStar(require("./expressions/constant-expression"), exports);
|
|
60
61
|
__exportStar(require("./expressions/function-ordering"), exports);
|
|
61
62
|
__exportStar(require("./expressions/expr-add-sub"), exports);
|
|
62
63
|
__exportStar(require("./expressions/expr-aggregate-function"), exports);
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FilterableType } from '@malloydata/malloy-filter';
|
|
2
|
+
import type { Parameter, ParameterType } from '../../../model/malloy_types';
|
|
2
3
|
import type { ConstantExpression } from '../expressions/constant-expression';
|
|
3
4
|
import { MalloyElement } from '../types/malloy-element';
|
|
4
5
|
interface HasInit {
|
|
5
6
|
name: string;
|
|
6
|
-
type?:
|
|
7
|
+
type?: ParameterType;
|
|
8
|
+
filterType?: FilterableType;
|
|
7
9
|
default?: ConstantExpression;
|
|
8
10
|
}
|
|
9
11
|
export declare class HasParameter extends MalloyElement {
|
|
10
12
|
elementType: string;
|
|
11
13
|
readonly name: string;
|
|
12
|
-
readonly type?:
|
|
14
|
+
readonly type?: ParameterType;
|
|
13
15
|
readonly default?: ConstantExpression;
|
|
16
|
+
readonly filterType?: FilterableType;
|
|
14
17
|
constructor(init: HasInit);
|
|
15
18
|
parameter(): Parameter;
|
|
16
19
|
}
|
|
@@ -25,21 +25,25 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
25
25
|
exports.HasParameter = void 0;
|
|
26
26
|
const malloy_types_1 = require("../../../model/malloy_types");
|
|
27
27
|
const malloy_element_1 = require("../types/malloy-element");
|
|
28
|
+
const expression_def_1 = require("../types/expression-def");
|
|
28
29
|
class HasParameter extends malloy_element_1.MalloyElement {
|
|
29
30
|
constructor(init) {
|
|
30
31
|
super();
|
|
31
32
|
this.elementType = 'hasParameter';
|
|
32
33
|
this.name = init.name;
|
|
33
|
-
if (init.type && (0, malloy_types_1.
|
|
34
|
+
if (init.type && (0, malloy_types_1.isParameterType)(init.type)) {
|
|
34
35
|
this.type = init.type;
|
|
35
36
|
}
|
|
36
37
|
if (init.default) {
|
|
37
38
|
this.default = init.default;
|
|
38
39
|
this.has({ default: this.default });
|
|
39
40
|
}
|
|
41
|
+
if (init.filterType)
|
|
42
|
+
this.filterType = init.filterType;
|
|
40
43
|
}
|
|
41
44
|
parameter() {
|
|
42
45
|
var _a;
|
|
46
|
+
let paramReturn;
|
|
43
47
|
if (this.default !== undefined) {
|
|
44
48
|
const constant = this.default.constantValue();
|
|
45
49
|
if (this.type &&
|
|
@@ -65,6 +69,19 @@ class HasParameter extends malloy_element_1.MalloyElement {
|
|
|
65
69
|
};
|
|
66
70
|
}
|
|
67
71
|
}
|
|
72
|
+
if (constant.type === 'filter expression') {
|
|
73
|
+
if (this.type !== 'filter expression') {
|
|
74
|
+
this.logError('parameter-missing-default-or-type', `Filter expression parameters must have expicit filter type, for example '${this.name}::filter<string>'`);
|
|
75
|
+
}
|
|
76
|
+
if (this.filterType) {
|
|
77
|
+
(0, expression_def_1.checkFilterExpression)(this, this.filterType, constant.value);
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
value: constant.value,
|
|
81
|
+
name: this.name,
|
|
82
|
+
type: constant.type,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
68
85
|
if (!(0, malloy_types_1.isCastType)(constant.type) && constant.type !== 'error') {
|
|
69
86
|
this.default.logError('parameter-illegal-default-type', `Default value cannot have type \`${constant.type}\``);
|
|
70
87
|
return {
|
|
@@ -73,20 +90,22 @@ class HasParameter extends malloy_element_1.MalloyElement {
|
|
|
73
90
|
type: 'error',
|
|
74
91
|
};
|
|
75
92
|
}
|
|
76
|
-
|
|
93
|
+
paramReturn = {
|
|
77
94
|
value: constant.value,
|
|
78
95
|
name: this.name,
|
|
79
96
|
type: constant.type,
|
|
80
97
|
};
|
|
81
98
|
}
|
|
82
|
-
|
|
83
|
-
this.
|
|
99
|
+
else {
|
|
100
|
+
if (this.type === undefined) {
|
|
101
|
+
this.logError('parameter-missing-default-or-type', 'Parameter must have default value or declared type');
|
|
102
|
+
}
|
|
103
|
+
paramReturn = { value: null, name: this.name, type: (_a = this.type) !== null && _a !== void 0 ? _a : 'error' };
|
|
104
|
+
}
|
|
105
|
+
if (paramReturn.type === 'filter expression' && this.filterType) {
|
|
106
|
+
paramReturn.filterType = this.filterType;
|
|
84
107
|
}
|
|
85
|
-
return
|
|
86
|
-
value: null,
|
|
87
|
-
name: this.name,
|
|
88
|
-
type: (_a = this.type) !== null && _a !== void 0 ? _a : 'error',
|
|
89
|
-
};
|
|
108
|
+
return paramReturn;
|
|
90
109
|
}
|
|
91
110
|
}
|
|
92
111
|
exports.HasParameter = HasParameter;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Dialect } from '../../../dialect/dialect';
|
|
2
|
-
import type { Annotation, StructDef, TypeDesc, FieldDef, AtomicFieldDef
|
|
2
|
+
import type { Annotation, StructDef, TypeDesc, FieldDef, AtomicFieldDef } from '../../../model/malloy_types';
|
|
3
3
|
import type { ExprValue } from '../types/expr-value';
|
|
4
4
|
import type { ExpressionDef } from '../types/expression-def';
|
|
5
5
|
import type { FieldName, FieldSpace, QueryFieldSpace } from '../types/field-space';
|
|
@@ -87,5 +87,4 @@ export declare class FieldDefinitionValue extends SpaceField {
|
|
|
87
87
|
private defInQuery?;
|
|
88
88
|
getQueryFieldDef(fs: FieldSpace): AtomicFieldDef;
|
|
89
89
|
typeDesc(): TypeDesc;
|
|
90
|
-
entryType(): FieldDefType;
|
|
91
90
|
}
|
|
@@ -316,10 +316,6 @@ class FieldDefinitionValue extends space_field_1.SpaceField {
|
|
|
316
316
|
}
|
|
317
317
|
throw new Error(`Can't get typeDesc for ${typeFrom.type}`);
|
|
318
318
|
}
|
|
319
|
-
entryType() {
|
|
320
|
-
const typeFrom = this.defInQuery || this.fieldDef();
|
|
321
|
-
return typeFrom.type;
|
|
322
|
-
}
|
|
323
319
|
}
|
|
324
320
|
exports.FieldDefinitionValue = FieldDefinitionValue;
|
|
325
321
|
//# sourceMappingURL=field-declaration.js.map
|
|
@@ -31,6 +31,7 @@ const time_utils_1 = require("../time-utils");
|
|
|
31
31
|
const malloy_element_1 = require("../types/malloy-element");
|
|
32
32
|
const expr_id_reference_1 = require("../expressions/expr-id-reference");
|
|
33
33
|
const parameter_space_1 = require("../field-space/parameter-space");
|
|
34
|
+
const expression_def_1 = require("../types/expression-def");
|
|
34
35
|
class NamedSource extends source_1.Source {
|
|
35
36
|
constructor(ref, sourceArguments, args) {
|
|
36
37
|
super();
|
|
@@ -140,6 +141,11 @@ class NamedSource extends source_1.Source {
|
|
|
140
141
|
const paramSpace = parameterSpace !== null && parameterSpace !== void 0 ? parameterSpace : new parameter_space_1.ParameterSpace(parametersOut !== null && parametersOut !== void 0 ? parametersOut : []);
|
|
141
142
|
const pVal = argument.value.getExpression(paramSpace);
|
|
142
143
|
let value = pVal.value;
|
|
144
|
+
if (pVal.type === 'filter expression' &&
|
|
145
|
+
parameter.type === 'filter expression' &&
|
|
146
|
+
parameter.filterType) {
|
|
147
|
+
(0, expression_def_1.checkFilterExpression)(argument.value, parameter.filterType, value);
|
|
148
|
+
}
|
|
143
149
|
if (pVal.type !== parameter.type && (0, malloy_types_1.isCastType)(parameter.type)) {
|
|
144
150
|
value = (0, time_utils_1.castTo)(parameter.type, pVal.value, pVal.type, true);
|
|
145
151
|
}
|
|
@@ -15,7 +15,7 @@ import type { QueryPropertyInterface } from '../types/query-property-interface';
|
|
|
15
15
|
import { LegalRefinementStage } from '../types/query-property-interface';
|
|
16
16
|
export declare abstract class Join extends MalloyElement implements Noteable, MakeEntry {
|
|
17
17
|
abstract name: ModelEntryReference;
|
|
18
|
-
abstract
|
|
18
|
+
abstract getStructDef(parameterSpace: ParameterSpace): JoinFieldDef;
|
|
19
19
|
abstract fixupJoinOn(outer: FieldSpace, inStruct: JoinFieldDef): void;
|
|
20
20
|
readonly isNoteableObj = true;
|
|
21
21
|
extendNote: typeof extendNoteMethod;
|
|
@@ -31,7 +31,7 @@ export declare class KeyJoin extends Join {
|
|
|
31
31
|
readonly keyExpr: ExpressionDef;
|
|
32
32
|
elementType: string;
|
|
33
33
|
constructor(name: ModelEntryReference, sourceExpr: SourceQueryElement, keyExpr: ExpressionDef);
|
|
34
|
-
|
|
34
|
+
getStructDef(parameterSpace: ParameterSpace): JoinFieldDef;
|
|
35
35
|
fixupJoinOn(outer: FieldSpace, inStruct: JoinFieldDef): void;
|
|
36
36
|
}
|
|
37
37
|
export declare class ExpressionJoin extends Join {
|
|
@@ -45,7 +45,7 @@ export declare class ExpressionJoin extends Join {
|
|
|
45
45
|
set joinOn(joinExpr: ExpressionDef | undefined);
|
|
46
46
|
get joinOn(): ExpressionDef | undefined;
|
|
47
47
|
fixupJoinOn(outer: FieldSpace, inStruct: JoinFieldDef): void;
|
|
48
|
-
|
|
48
|
+
getStructDef(parameterSpace: ParameterSpace): JoinFieldDef;
|
|
49
49
|
}
|
|
50
50
|
export declare class JoinStatement extends DefinitionList<Join> implements QueryPropertyInterface {
|
|
51
51
|
readonly accessModifier: AccessModifierLabel | undefined;
|
|
@@ -60,7 +60,7 @@ class KeyJoin extends Join {
|
|
|
60
60
|
this.keyExpr = keyExpr;
|
|
61
61
|
this.elementType = 'joinOnKey';
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
getStructDef(parameterSpace) {
|
|
64
64
|
var _a;
|
|
65
65
|
const sourceDef = this.getStructDefFromExpr(parameterSpace);
|
|
66
66
|
if (!(0, malloy_types_1.isJoinable)(sourceDef)) {
|
|
@@ -143,7 +143,7 @@ class ExpressionJoin extends Join {
|
|
|
143
143
|
inStruct.onExpression = exprX.value;
|
|
144
144
|
inStruct.onCompositeFieldUsage = exprX.compositeFieldUsage;
|
|
145
145
|
}
|
|
146
|
-
|
|
146
|
+
getStructDef(parameterSpace) {
|
|
147
147
|
var _a;
|
|
148
148
|
const source = this.sourceExpr.getSource();
|
|
149
149
|
if (!source) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TimestampUnit } from '../../../model/malloy_types';
|
|
1
|
+
import type { Expr, TimestampUnit } from '../../../model/malloy_types';
|
|
2
2
|
import type { ExprValue } from './expr-value';
|
|
3
3
|
import type { FieldSpace } from './field-space';
|
|
4
4
|
import { MalloyElement } from './malloy-element';
|
|
@@ -83,3 +83,4 @@ export declare function getMorphicValue(mv: ExprValue, mt: MorphicType): ExprVal
|
|
|
83
83
|
* @return ExprValue of the expression
|
|
84
84
|
*/
|
|
85
85
|
export declare function applyBinary(fs: FieldSpace, left: ExpressionDef, op: BinaryMalloyOperator, right: ExpressionDef): ExprValue;
|
|
86
|
+
export declare function checkFilterExpression(logTo: MalloyElement, ft: string, fexpr: Expr): void;
|
|
@@ -45,7 +45,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
45
45
|
return result;
|
|
46
46
|
};
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
-
exports.applyBinary = exports.getMorphicValue = exports.ExprDuration = exports.ExpressionDef = exports.ATNodeType = void 0;
|
|
48
|
+
exports.checkFilterExpression = exports.applyBinary = exports.getMorphicValue = exports.ExprDuration = exports.ExpressionDef = exports.ATNodeType = void 0;
|
|
49
49
|
const malloy_types_1 = require("../../../model/malloy_types");
|
|
50
50
|
const TDU = __importStar(require("../typedesc-utils"));
|
|
51
51
|
const ast_utils_1 = require("../ast-utils");
|
|
@@ -54,6 +54,7 @@ const time_utils_1 = require("../time-utils");
|
|
|
54
54
|
const granular_result_1 = require("./granular-result");
|
|
55
55
|
const malloy_element_1 = require("./malloy-element");
|
|
56
56
|
const binary_operators_1 = require("./binary_operators");
|
|
57
|
+
const malloy_filter_1 = require("@malloydata/malloy-filter");
|
|
57
58
|
class TypeMismatch extends Error {
|
|
58
59
|
}
|
|
59
60
|
/** Node types in an alternation tree */
|
|
@@ -270,24 +271,54 @@ function equality(fs, left, op, right) {
|
|
|
270
271
|
}
|
|
271
272
|
}
|
|
272
273
|
}
|
|
273
|
-
let value
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
if (regexCmp) {
|
|
283
|
-
if (op[0] === '!') {
|
|
284
|
-
regexCmp = { node: 'not', e: { ...regexCmp } };
|
|
285
|
-
}
|
|
274
|
+
let value;
|
|
275
|
+
if (rhs.type === 'filter expression') {
|
|
276
|
+
if (op !== '~' && op !== '!~') {
|
|
277
|
+
return right.loggedErrorExpr('filter-expression-error', `Cannot use the '${op}' operator with a filter expression`);
|
|
278
|
+
}
|
|
279
|
+
if ((0, malloy_filter_1.isFilterable)(lhs.type)) {
|
|
280
|
+
let actualFilter = rhs.value;
|
|
281
|
+
while (actualFilter.node === '()') {
|
|
282
|
+
actualFilter = actualFilter.e;
|
|
286
283
|
}
|
|
287
|
-
|
|
288
|
-
|
|
284
|
+
if (actualFilter.node !== 'parameter') {
|
|
285
|
+
// Parameters are checked when parameter value is parsed
|
|
286
|
+
checkFilterExpression(right, lhs.type, actualFilter);
|
|
287
|
+
}
|
|
288
|
+
const filterMatch = {
|
|
289
|
+
node: 'filterMatch',
|
|
290
|
+
dataType: lhs.type,
|
|
291
|
+
kids: { filterExpr: rhs.value, expr: lhs.value },
|
|
292
|
+
};
|
|
293
|
+
if (op === '!~') {
|
|
294
|
+
filterMatch.notMatch = true;
|
|
295
|
+
}
|
|
296
|
+
value = filterMatch;
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
return left.loggedErrorExpr('filter-expression-type', `Cannot use filter expressions with type '${lhs.type}'`);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
value = timeCompare(left, lhs, op, rhs) || {
|
|
304
|
+
node,
|
|
305
|
+
kids: { left: lhs.value, right: rhs.value },
|
|
306
|
+
};
|
|
307
|
+
if (lhs.type !== 'error' &&
|
|
308
|
+
rhs.type !== 'error' &&
|
|
309
|
+
(op === '~' || op === '!~')) {
|
|
310
|
+
if (lhs.type !== 'string' || rhs.type !== 'string') {
|
|
311
|
+
let regexCmp = regexEqual(lhs, rhs);
|
|
312
|
+
if (regexCmp) {
|
|
313
|
+
if (op[0] === '!') {
|
|
314
|
+
regexCmp = { node: 'not', e: { ...regexCmp } };
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
throw new TypeMismatch("Incompatible types for match('~') operator");
|
|
319
|
+
}
|
|
320
|
+
value = regexCmp;
|
|
289
321
|
}
|
|
290
|
-
value = regexCmp;
|
|
291
322
|
}
|
|
292
323
|
}
|
|
293
324
|
return (0, expr_value_1.computedExprValue)({
|
|
@@ -452,4 +483,35 @@ function unsupportError(l, lhs, r, rhs) {
|
|
|
452
483
|
}
|
|
453
484
|
return undefined;
|
|
454
485
|
}
|
|
486
|
+
function checkFilterExpression(logTo, ft, fexpr) {
|
|
487
|
+
var _a, _b, _c, _d;
|
|
488
|
+
while (fexpr.node === '()') {
|
|
489
|
+
fexpr = fexpr.e;
|
|
490
|
+
}
|
|
491
|
+
if (fexpr.node !== 'filterLiteral') {
|
|
492
|
+
logTo.logError('filter-expression-error', 'Expected a filter expression literal here');
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
const fsrc = fexpr.filterSrc;
|
|
496
|
+
let err;
|
|
497
|
+
if (ft === 'date' || ft === 'timestamp') {
|
|
498
|
+
err = (_a = malloy_filter_1.TemporalFilterExpression.parse(fsrc).log[0]) === null || _a === void 0 ? void 0 : _a.message;
|
|
499
|
+
}
|
|
500
|
+
else if (ft === 'string') {
|
|
501
|
+
err = (_b = malloy_filter_1.StringFilterExpression.parse(fsrc).log[0]) === null || _b === void 0 ? void 0 : _b.message;
|
|
502
|
+
}
|
|
503
|
+
else if (ft === 'number') {
|
|
504
|
+
err = (_c = malloy_filter_1.NumberFilterExpression.parse(fsrc).log[0]) === null || _c === void 0 ? void 0 : _c.message;
|
|
505
|
+
}
|
|
506
|
+
else if (ft === 'boolean') {
|
|
507
|
+
err = (_d = malloy_filter_1.BooleanFilterExpression.parse(fsrc).log[0]) === null || _d === void 0 ? void 0 : _d.message;
|
|
508
|
+
}
|
|
509
|
+
else {
|
|
510
|
+
logTo.logError('filter-expression-type', `Cannot apply filter expression to type ${ft}`);
|
|
511
|
+
}
|
|
512
|
+
if (err !== undefined) {
|
|
513
|
+
logTo.logError('filter-expression-error', `Filter syntax error: ${err}`);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
exports.checkFilterExpression = checkFilterExpression;
|
|
455
517
|
//# sourceMappingURL=expression-def.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type Parameter, type TypeDesc } from '../../../model/malloy_types';
|
|
2
2
|
import { SpaceEntry } from './space-entry';
|
|
3
3
|
import type { HasParameter } from '../parameters/has-parameter';
|
|
4
4
|
export declare abstract class SpaceParam extends SpaceEntry {
|
|
@@ -11,12 +11,10 @@ export declare class AbstractParameter extends SpaceParam {
|
|
|
11
11
|
_parameter: Parameter | undefined;
|
|
12
12
|
parameter(): Parameter;
|
|
13
13
|
typeDesc(): TypeDesc;
|
|
14
|
-
entryType(): FieldDefType;
|
|
15
14
|
}
|
|
16
15
|
export declare class DefinedParameter extends SpaceParam {
|
|
17
16
|
readonly paramDef: Parameter;
|
|
18
17
|
constructor(paramDef: Parameter);
|
|
19
18
|
parameter(): Parameter;
|
|
20
19
|
typeDesc(): TypeDesc;
|
|
21
|
-
entryType(): FieldDefType;
|
|
22
20
|
}
|
|
@@ -69,16 +69,16 @@ class AbstractParameter extends SpaceParam {
|
|
|
69
69
|
return this._parameter;
|
|
70
70
|
}
|
|
71
71
|
typeDesc() {
|
|
72
|
+
const p = this.parameter();
|
|
73
|
+
const t = p.type;
|
|
74
|
+
const theType = t === 'filter expression' ? { type: t } : TDU.atomicDef(p);
|
|
72
75
|
return {
|
|
73
|
-
...
|
|
76
|
+
...theType,
|
|
74
77
|
expressionType: 'scalar',
|
|
75
78
|
evalSpace: 'constant',
|
|
76
79
|
compositeFieldUsage: (0, composite_source_utils_1.emptyCompositeFieldUsage)(),
|
|
77
80
|
};
|
|
78
81
|
}
|
|
79
|
-
entryType() {
|
|
80
|
-
return this.parameter().type;
|
|
81
|
-
}
|
|
82
82
|
}
|
|
83
83
|
exports.AbstractParameter = AbstractParameter;
|
|
84
84
|
class DefinedParameter extends SpaceParam {
|
|
@@ -90,8 +90,11 @@ class DefinedParameter extends SpaceParam {
|
|
|
90
90
|
return this.paramDef;
|
|
91
91
|
}
|
|
92
92
|
typeDesc() {
|
|
93
|
+
const p = this.parameter();
|
|
94
|
+
const t = p.type;
|
|
95
|
+
const theType = t === 'filter expression' ? { type: t } : TDU.atomicDef(p);
|
|
93
96
|
return {
|
|
94
|
-
...
|
|
97
|
+
...theType,
|
|
95
98
|
expressionType: 'scalar',
|
|
96
99
|
// TODO Not sure whether params are considered "input space". It seems like they
|
|
97
100
|
// could be input or constant, depending on usage (same as above).
|
|
@@ -99,9 +102,6 @@ class DefinedParameter extends SpaceParam {
|
|
|
99
102
|
compositeFieldUsage: (0, composite_source_utils_1.emptyCompositeFieldUsage)(),
|
|
100
103
|
};
|
|
101
104
|
}
|
|
102
|
-
entryType() {
|
|
103
|
-
return this.paramDef.type;
|
|
104
|
-
}
|
|
105
105
|
}
|
|
106
106
|
exports.DefinedParameter = DefinedParameter;
|
|
107
107
|
//# sourceMappingURL=space-param.js.map
|