@malloydata/malloy 0.0.198-dev241010005107 → 0.0.198-dev241010185717
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dialect/mysql/mysql.js +1 -1
- package/dist/lang/ast/expressions/case.d.ts +18 -0
- package/dist/lang/ast/expressions/case.js +114 -0
- package/dist/lang/ast/expressions/pick-when.js +15 -17
- package/dist/lang/ast/index.d.ts +1 -0
- package/dist/lang/ast/index.js +1 -0
- package/dist/lang/lib/Malloy/MalloyParser.d.ts +58 -18
- package/dist/lang/lib/Malloy/MalloyParser.js +1766 -1522
- package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +35 -0
- package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +22 -0
- package/dist/lang/malloy-to-ast.d.ts +2 -0
- package/dist/lang/malloy-to-ast.js +23 -4
- package/dist/lang/parse-log.d.ts +17 -1
- package/dist/lang/parse-log.js +4 -0
- package/dist/lang/test/expressions.spec.js +166 -0
- package/dist/lang/test/parse-expects.js +19 -6
- package/dist/model/malloy_query.d.ts +2 -2
- package/dist/model/malloy_query.js +14 -6
- package/dist/model/malloy_types.d.ts +7 -6
- package/dist/model/utils.js +2 -2
- package/package.json +1 -1
|
@@ -93,7 +93,7 @@ class MySQLDialect extends dialect_1.Dialect {
|
|
|
93
93
|
this.dontUnionIndex = false;
|
|
94
94
|
this.supportsQualify = false;
|
|
95
95
|
this.supportsNesting = true;
|
|
96
|
-
this.experimental =
|
|
96
|
+
this.experimental = false;
|
|
97
97
|
this.nativeBoolean = false;
|
|
98
98
|
this.supportsFullJoin = false;
|
|
99
99
|
this.supportsPipelinesInViews = false;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ExprValue } from '../types/expr-value';
|
|
2
|
+
import { ExpressionDef } from '../types/expression-def';
|
|
3
|
+
import { FieldSpace } from '../types/field-space';
|
|
4
|
+
import { MalloyElement } from '../types/malloy-element';
|
|
5
|
+
export declare class Case extends ExpressionDef {
|
|
6
|
+
readonly value: ExpressionDef | undefined;
|
|
7
|
+
readonly choices: CaseWhen[];
|
|
8
|
+
readonly elseValue?: ExpressionDef | undefined;
|
|
9
|
+
elementType: string;
|
|
10
|
+
constructor(value: ExpressionDef | undefined, choices: CaseWhen[], elseValue?: ExpressionDef | undefined);
|
|
11
|
+
getExpression(fs: FieldSpace): ExprValue;
|
|
12
|
+
}
|
|
13
|
+
export declare class CaseWhen extends MalloyElement {
|
|
14
|
+
readonly when: ExpressionDef;
|
|
15
|
+
readonly then: ExpressionDef;
|
|
16
|
+
elementType: string;
|
|
17
|
+
constructor(when: ExpressionDef, then: ExpressionDef);
|
|
18
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.CaseWhen = exports.Case = void 0;
|
|
10
|
+
const expression_def_1 = require("../types/expression-def");
|
|
11
|
+
const malloy_element_1 = require("../types/malloy-element");
|
|
12
|
+
const fragtype_utils_1 = require("../fragtype-utils");
|
|
13
|
+
const model_1 = require("../../../model");
|
|
14
|
+
function typeCoalesce(ev1, ev2) {
|
|
15
|
+
return ev1 === undefined ||
|
|
16
|
+
ev1.dataType === 'null' ||
|
|
17
|
+
ev1.dataType === 'error'
|
|
18
|
+
? ev2
|
|
19
|
+
: ev1;
|
|
20
|
+
}
|
|
21
|
+
class Case extends expression_def_1.ExpressionDef {
|
|
22
|
+
constructor(value, choices, elseValue) {
|
|
23
|
+
super({ choices });
|
|
24
|
+
this.value = value;
|
|
25
|
+
this.choices = choices;
|
|
26
|
+
this.elseValue = elseValue;
|
|
27
|
+
this.elementType = 'case';
|
|
28
|
+
this.has({ elseValue, value });
|
|
29
|
+
}
|
|
30
|
+
getExpression(fs) {
|
|
31
|
+
var _a;
|
|
32
|
+
const resultExpr = {
|
|
33
|
+
node: 'case',
|
|
34
|
+
kids: {
|
|
35
|
+
caseWhen: [],
|
|
36
|
+
caseThen: [],
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
let expressionType = 'scalar';
|
|
40
|
+
let evalSpace = 'constant';
|
|
41
|
+
let value = undefined;
|
|
42
|
+
if (this.value) {
|
|
43
|
+
value = this.value.getExpression(fs);
|
|
44
|
+
expressionType = (0, model_1.maxExpressionType)(expressionType, value.expressionType);
|
|
45
|
+
evalSpace = (0, model_1.mergeEvalSpaces)(evalSpace, value.evalSpace);
|
|
46
|
+
resultExpr.kids.caseValue = value.value;
|
|
47
|
+
}
|
|
48
|
+
const choiceValues = [];
|
|
49
|
+
for (const c of this.choices) {
|
|
50
|
+
const when = c.when.getExpression(fs);
|
|
51
|
+
const then = c.then.getExpression(fs);
|
|
52
|
+
choiceValues.push({ when, then });
|
|
53
|
+
}
|
|
54
|
+
let returnType;
|
|
55
|
+
for (const aChoice of choiceValues) {
|
|
56
|
+
if (value !== undefined) {
|
|
57
|
+
if (!fragtype_utils_1.FT.typeEq(aChoice.when, value)) {
|
|
58
|
+
return this.loggedErrorExpr('case-when-type-does-not-match', {
|
|
59
|
+
whenType: aChoice.when.dataType,
|
|
60
|
+
valueType: value.dataType,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
if (!fragtype_utils_1.FT.typeEq(aChoice.when, fragtype_utils_1.FT.boolT)) {
|
|
66
|
+
return this.loggedErrorExpr('case-when-must-be-boolean', {
|
|
67
|
+
whenType: aChoice.when.dataType,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (returnType && !fragtype_utils_1.FT.typeEq(returnType, aChoice.then, true)) {
|
|
72
|
+
return this.loggedErrorExpr('case-then-type-does-not-match', {
|
|
73
|
+
thenType: aChoice.then.dataType,
|
|
74
|
+
returnType: returnType.dataType,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
returnType = typeCoalesce(returnType, aChoice.then);
|
|
78
|
+
expressionType = (0, model_1.maxExpressionType)(expressionType, (0, model_1.maxExpressionType)(aChoice.then.expressionType, aChoice.when.expressionType));
|
|
79
|
+
evalSpace = (0, model_1.mergeEvalSpaces)(evalSpace, aChoice.then.evalSpace, aChoice.when.evalSpace);
|
|
80
|
+
resultExpr.kids.caseWhen.push(aChoice.when.value);
|
|
81
|
+
resultExpr.kids.caseThen.push(aChoice.then.value);
|
|
82
|
+
}
|
|
83
|
+
if (this.elseValue) {
|
|
84
|
+
const elseValue = this.elseValue.getExpression(fs);
|
|
85
|
+
if (returnType && !fragtype_utils_1.FT.typeEq(returnType, elseValue, true)) {
|
|
86
|
+
return this.loggedErrorExpr('case-else-type-does-not-match', {
|
|
87
|
+
elseType: elseValue.dataType,
|
|
88
|
+
returnType: returnType.dataType,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
returnType = typeCoalesce(returnType, elseValue);
|
|
92
|
+
expressionType = (0, model_1.maxExpressionType)(expressionType, elseValue.expressionType);
|
|
93
|
+
evalSpace = (0, model_1.mergeEvalSpaces)(evalSpace, elseValue.evalSpace);
|
|
94
|
+
resultExpr.kids.caseElse = elseValue.value;
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
value: resultExpr,
|
|
98
|
+
dataType: (_a = returnType === null || returnType === void 0 ? void 0 : returnType.dataType) !== null && _a !== void 0 ? _a : 'null',
|
|
99
|
+
expressionType,
|
|
100
|
+
evalSpace,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.Case = Case;
|
|
105
|
+
class CaseWhen extends malloy_element_1.MalloyElement {
|
|
106
|
+
constructor(when, then) {
|
|
107
|
+
super({ when, then });
|
|
108
|
+
this.when = when;
|
|
109
|
+
this.then = then;
|
|
110
|
+
this.elementType = 'caseWhen';
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.CaseWhen = CaseWhen;
|
|
114
|
+
//# sourceMappingURL=case.js.map
|
|
@@ -62,11 +62,10 @@ class Pick extends expression_def_1.ExpressionDef {
|
|
|
62
62
|
}
|
|
63
63
|
apply(fs, op, expr) {
|
|
64
64
|
const caseValue = {
|
|
65
|
-
node: '
|
|
65
|
+
node: 'case',
|
|
66
66
|
kids: {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
pickElse: { node: 'error', message: 'pick statement not complete' },
|
|
67
|
+
caseWhen: [],
|
|
68
|
+
caseThen: [],
|
|
70
69
|
},
|
|
71
70
|
};
|
|
72
71
|
let returnType;
|
|
@@ -86,8 +85,8 @@ class Pick extends expression_def_1.ExpressionDef {
|
|
|
86
85
|
});
|
|
87
86
|
}
|
|
88
87
|
returnType = typeCoalesce(returnType, thenExpr);
|
|
89
|
-
caseValue.kids.
|
|
90
|
-
caseValue.kids.
|
|
88
|
+
caseValue.kids.caseWhen.push(whenExpr.value);
|
|
89
|
+
caseValue.kids.caseThen.push(thenExpr.value);
|
|
91
90
|
}
|
|
92
91
|
const elsePart = this.elsePick || expr;
|
|
93
92
|
const elseVal = elsePart.getExpression(fs);
|
|
@@ -106,7 +105,7 @@ class Pick extends expression_def_1.ExpressionDef {
|
|
|
106
105
|
});
|
|
107
106
|
}
|
|
108
107
|
}
|
|
109
|
-
caseValue.kids.
|
|
108
|
+
caseValue.kids.caseElse = elseVal.value;
|
|
110
109
|
return {
|
|
111
110
|
dataType: returnType.dataType,
|
|
112
111
|
expressionType: (0, malloy_types_1.maxExpressionType)(anyExpressionType, elseVal.expressionType),
|
|
@@ -116,11 +115,10 @@ class Pick extends expression_def_1.ExpressionDef {
|
|
|
116
115
|
}
|
|
117
116
|
getExpression(fs) {
|
|
118
117
|
const pick = {
|
|
119
|
-
node: '
|
|
118
|
+
node: 'case',
|
|
120
119
|
kids: {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
pickElse: { node: 'error', message: 'pick statement not complete' },
|
|
120
|
+
caseWhen: [],
|
|
121
|
+
caseThen: [],
|
|
124
122
|
},
|
|
125
123
|
};
|
|
126
124
|
if (this.elsePick === undefined) {
|
|
@@ -131,8 +129,8 @@ class Pick extends expression_def_1.ExpressionDef {
|
|
|
131
129
|
if (c.pick === undefined) {
|
|
132
130
|
return this.loggedErrorExpr('pick-missing-value', 'pick with no value can only be used with apply');
|
|
133
131
|
}
|
|
134
|
-
const
|
|
135
|
-
if (
|
|
132
|
+
const caseWhen = c.when.requestExpression(fs);
|
|
133
|
+
if (caseWhen === undefined) {
|
|
136
134
|
this.loggedErrorExpr('pick-illegal-partial', 'pick with partial when can only be used with apply');
|
|
137
135
|
}
|
|
138
136
|
choiceValues.push({
|
|
@@ -158,8 +156,8 @@ class Pick extends expression_def_1.ExpressionDef {
|
|
|
158
156
|
returnType = typeCoalesce(returnType, aChoice.pick);
|
|
159
157
|
anyExpressionType = (0, malloy_types_1.maxExpressionType)(anyExpressionType, (0, malloy_types_1.maxExpressionType)(aChoice.pick.expressionType, aChoice.when.expressionType));
|
|
160
158
|
anyEvalSpace = (0, malloy_types_1.mergeEvalSpaces)(anyEvalSpace, aChoice.pick.evalSpace, aChoice.when.evalSpace);
|
|
161
|
-
pick.kids.
|
|
162
|
-
pick.kids.
|
|
159
|
+
pick.kids.caseWhen.push(aChoice.when.value);
|
|
160
|
+
pick.kids.caseThen.push(aChoice.pick.value);
|
|
163
161
|
}
|
|
164
162
|
const defVal = this.elsePick.getExpression(fs);
|
|
165
163
|
anyExpressionType = (0, malloy_types_1.maxExpressionType)(anyExpressionType, defVal.expressionType);
|
|
@@ -171,7 +169,7 @@ class Pick extends expression_def_1.ExpressionDef {
|
|
|
171
169
|
returnType: returnType.dataType,
|
|
172
170
|
});
|
|
173
171
|
}
|
|
174
|
-
pick.kids.
|
|
172
|
+
pick.kids.caseElse = defVal.value;
|
|
175
173
|
return {
|
|
176
174
|
dataType: returnType.dataType,
|
|
177
175
|
expressionType: anyExpressionType,
|
|
@@ -186,7 +184,7 @@ class PickWhen extends malloy_element_1.MalloyElement {
|
|
|
186
184
|
super({ when: when });
|
|
187
185
|
this.pick = pick;
|
|
188
186
|
this.when = when;
|
|
189
|
-
this.elementType = '
|
|
187
|
+
this.elementType = 'caseWhen';
|
|
190
188
|
this.has({ pick: pick });
|
|
191
189
|
}
|
|
192
190
|
}
|
package/dist/lang/ast/index.d.ts
CHANGED
|
@@ -52,6 +52,7 @@ export * from './expressions/time-literal';
|
|
|
52
52
|
export * from './expressions/partial-compare';
|
|
53
53
|
export * from './expressions/partition_by';
|
|
54
54
|
export * from './expressions/pick-when';
|
|
55
|
+
export * from './expressions/case';
|
|
55
56
|
export * from './expressions/expr-record-literal';
|
|
56
57
|
export * from './expressions/range';
|
|
57
58
|
export * from './expressions/time-frame';
|
package/dist/lang/ast/index.js
CHANGED
|
@@ -90,6 +90,7 @@ __exportStar(require("./expressions/time-literal"), exports);
|
|
|
90
90
|
__exportStar(require("./expressions/partial-compare"), exports);
|
|
91
91
|
__exportStar(require("./expressions/partition_by"), exports);
|
|
92
92
|
__exportStar(require("./expressions/pick-when"), exports);
|
|
93
|
+
__exportStar(require("./expressions/case"), exports);
|
|
93
94
|
__exportStar(require("./expressions/expr-record-literal"), exports);
|
|
94
95
|
__exportStar(require("./expressions/range"), exports);
|
|
95
96
|
__exportStar(require("./expressions/time-frame"), exports);
|
|
@@ -281,24 +281,26 @@ export declare class MalloyParser extends Parser {
|
|
|
281
281
|
static readonly RULE_partialAllowedFieldExpr = 115;
|
|
282
282
|
static readonly RULE_pickStatement = 116;
|
|
283
283
|
static readonly RULE_pick = 117;
|
|
284
|
-
static readonly
|
|
285
|
-
static readonly
|
|
286
|
-
static readonly
|
|
287
|
-
static readonly
|
|
288
|
-
static readonly
|
|
289
|
-
static readonly
|
|
290
|
-
static readonly
|
|
291
|
-
static readonly
|
|
292
|
-
static readonly
|
|
293
|
-
static readonly
|
|
294
|
-
static readonly
|
|
295
|
-
static readonly
|
|
296
|
-
static readonly
|
|
297
|
-
static readonly
|
|
298
|
-
static readonly
|
|
299
|
-
static readonly
|
|
300
|
-
static readonly
|
|
301
|
-
static readonly
|
|
284
|
+
static readonly RULE_caseStatement = 118;
|
|
285
|
+
static readonly RULE_caseWhen = 119;
|
|
286
|
+
static readonly RULE_recordKey = 120;
|
|
287
|
+
static readonly RULE_recordElement = 121;
|
|
288
|
+
static readonly RULE_argumentList = 122;
|
|
289
|
+
static readonly RULE_fieldNameList = 123;
|
|
290
|
+
static readonly RULE_fieldCollection = 124;
|
|
291
|
+
static readonly RULE_collectionWildCard = 125;
|
|
292
|
+
static readonly RULE_starQualified = 126;
|
|
293
|
+
static readonly RULE_taggedRef = 127;
|
|
294
|
+
static readonly RULE_refExpr = 128;
|
|
295
|
+
static readonly RULE_collectionMember = 129;
|
|
296
|
+
static readonly RULE_fieldPath = 130;
|
|
297
|
+
static readonly RULE_joinName = 131;
|
|
298
|
+
static readonly RULE_fieldName = 132;
|
|
299
|
+
static readonly RULE_justExpr = 133;
|
|
300
|
+
static readonly RULE_sqlExploreNameRef = 134;
|
|
301
|
+
static readonly RULE_nameSQLBlock = 135;
|
|
302
|
+
static readonly RULE_connectionName = 136;
|
|
303
|
+
static readonly RULE_experimentalStatementForTesting = 137;
|
|
302
304
|
static readonly ruleNames: string[];
|
|
303
305
|
private static readonly _LITERAL_NAMES;
|
|
304
306
|
private static readonly _SYMBOLIC_NAMES;
|
|
@@ -430,6 +432,8 @@ export declare class MalloyParser extends Parser {
|
|
|
430
432
|
partialAllowedFieldExpr(): PartialAllowedFieldExprContext;
|
|
431
433
|
pickStatement(): PickStatementContext;
|
|
432
434
|
pick(): PickContext;
|
|
435
|
+
caseStatement(): CaseStatementContext;
|
|
436
|
+
caseWhen(): CaseWhenContext;
|
|
433
437
|
recordKey(): RecordKeyContext;
|
|
434
438
|
recordElement(): RecordElementContext;
|
|
435
439
|
argumentList(): ArgumentListContext;
|
|
@@ -2261,6 +2265,13 @@ export declare class ExprPickContext extends FieldExprContext {
|
|
|
2261
2265
|
exitRule(listener: MalloyParserListener): void;
|
|
2262
2266
|
accept<Result>(visitor: MalloyParserVisitor<Result>): Result;
|
|
2263
2267
|
}
|
|
2268
|
+
export declare class ExprCaseContext extends FieldExprContext {
|
|
2269
|
+
caseStatement(): CaseStatementContext;
|
|
2270
|
+
constructor(ctx: FieldExprContext);
|
|
2271
|
+
enterRule(listener: MalloyParserListener): void;
|
|
2272
|
+
exitRule(listener: MalloyParserListener): void;
|
|
2273
|
+
accept<Result>(visitor: MalloyParserVisitor<Result>): Result;
|
|
2274
|
+
}
|
|
2264
2275
|
export declare class ExprUngroupContext extends FieldExprContext {
|
|
2265
2276
|
ungroup(): UngroupContext;
|
|
2266
2277
|
OPAREN(): TerminalNode;
|
|
@@ -2311,6 +2322,35 @@ export declare class PickContext extends ParserRuleContext {
|
|
|
2311
2322
|
exitRule(listener: MalloyParserListener): void;
|
|
2312
2323
|
accept<Result>(visitor: MalloyParserVisitor<Result>): Result;
|
|
2313
2324
|
}
|
|
2325
|
+
export declare class CaseStatementContext extends ParserRuleContext {
|
|
2326
|
+
_valueExpr: FieldExprContext;
|
|
2327
|
+
_caseElse: FieldExprContext;
|
|
2328
|
+
CASE(): TerminalNode;
|
|
2329
|
+
END(): TerminalNode;
|
|
2330
|
+
caseWhen(): CaseWhenContext[];
|
|
2331
|
+
caseWhen(i: number): CaseWhenContext;
|
|
2332
|
+
ELSE(): TerminalNode | undefined;
|
|
2333
|
+
fieldExpr(): FieldExprContext[];
|
|
2334
|
+
fieldExpr(i: number): FieldExprContext;
|
|
2335
|
+
constructor(parent: ParserRuleContext | undefined, invokingState: number);
|
|
2336
|
+
get ruleIndex(): number;
|
|
2337
|
+
enterRule(listener: MalloyParserListener): void;
|
|
2338
|
+
exitRule(listener: MalloyParserListener): void;
|
|
2339
|
+
accept<Result>(visitor: MalloyParserVisitor<Result>): Result;
|
|
2340
|
+
}
|
|
2341
|
+
export declare class CaseWhenContext extends ParserRuleContext {
|
|
2342
|
+
_condition: FieldExprContext;
|
|
2343
|
+
_result: FieldExprContext;
|
|
2344
|
+
WHEN(): TerminalNode;
|
|
2345
|
+
THEN(): TerminalNode;
|
|
2346
|
+
fieldExpr(): FieldExprContext[];
|
|
2347
|
+
fieldExpr(i: number): FieldExprContext;
|
|
2348
|
+
constructor(parent: ParserRuleContext | undefined, invokingState: number);
|
|
2349
|
+
get ruleIndex(): number;
|
|
2350
|
+
enterRule(listener: MalloyParserListener): void;
|
|
2351
|
+
exitRule(listener: MalloyParserListener): void;
|
|
2352
|
+
accept<Result>(visitor: MalloyParserVisitor<Result>): Result;
|
|
2353
|
+
}
|
|
2314
2354
|
export declare class RecordKeyContext extends ParserRuleContext {
|
|
2315
2355
|
id(): IdContext;
|
|
2316
2356
|
constructor(parent: ParserRuleContext | undefined, invokingState: number);
|