@malloydata/malloy 0.0.22-dev230117232218 → 0.0.22-dev230119001546
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/apply-expr.d.ts +1 -14
- package/dist/lang/ast/apply-expr.js +1 -208
- package/dist/lang/ast/ast-expr.d.ts +9 -96
- package/dist/lang/ast/ast-expr.js +105 -384
- package/dist/lang/ast/ast-main.d.ts +141 -1
- package/dist/lang/ast/ast-main.js +681 -9
- package/dist/lang/ast/ast-time-expr.d.ts +2 -41
- package/dist/lang/ast/ast-time-expr.js +36 -204
- package/package.json +1 -1
|
@@ -22,215 +22,19 @@
|
|
|
22
22
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.
|
|
25
|
+
exports.Apply = exports.Pick = exports.PickWhen = exports.TopBy = exports.ExprCast = exports.isCastType = exports.ExprFilter = exports.ExprCase = exports.WhenClause = exports.ExprUngroup = exports.ExprSum = exports.ExprAvg = exports.ExprCount = exports.ExprCountDistinct = exports.ExprMax = exports.ExprMin = exports.ExprAlternationTree = exports.ExprMulDiv = exports.ExprAddSub = exports.BinaryNumeric = exports.ExprMinus = exports.ExprParens = exports.ExprNULL = exports.ExprIdReference = exports.ExprLogicalOp = exports.Boolean = exports.ExprNot = exports.ExprRegEx = exports.ExprNumber = exports.ExprString = void 0;
|
|
26
26
|
/*
|
|
27
27
|
** This file is the general framework for expression nodes and expression
|
|
28
28
|
** evaluation.
|
|
29
29
|
*/
|
|
30
30
|
const malloy_types_1 = require("../../model/malloy_types");
|
|
31
31
|
const field_space_1 = require("../field-space");
|
|
32
|
-
const
|
|
32
|
+
const ast_main_1 = require("./ast-main");
|
|
33
|
+
const ast_types_1 = require("./ast-types");
|
|
33
34
|
const apply_expr_1 = require("./apply-expr");
|
|
34
35
|
const space_field_1 = require("../space-field");
|
|
35
36
|
const time_utils_1 = require("./time-utils");
|
|
36
|
-
|
|
37
|
-
* Root node for any element in an expression. These essentially
|
|
38
|
-
* create a sub-tree in the larger AST. Expression nodes know
|
|
39
|
-
* how to write themselves as SQL (or rather, generate the
|
|
40
|
-
* template for SQL required by the query writer)
|
|
41
|
-
*/
|
|
42
|
-
class ExpressionDef extends index_1.MalloyElement {
|
|
43
|
-
constructor() {
|
|
44
|
-
super(...arguments);
|
|
45
|
-
this.legalChildTypes = index_1.FT.anyAtomicT;
|
|
46
|
-
}
|
|
47
|
-
granular() {
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Some operators want to give the right hand value a chance to
|
|
52
|
-
* rewrite itself. This requests a translation for a rewrite,
|
|
53
|
-
* or returns undefined if that request should be denied.
|
|
54
|
-
* @param fs FieldSpace
|
|
55
|
-
* @returns Translated expression or undefined
|
|
56
|
-
*/
|
|
57
|
-
requestExpression(fs) {
|
|
58
|
-
return this.getExpression(fs);
|
|
59
|
-
}
|
|
60
|
-
defaultFieldName() {
|
|
61
|
-
return undefined;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Check an expression for type compatibility
|
|
65
|
-
* @param _eNode currently unused, will be used to get error location
|
|
66
|
-
* @param eVal ...list of expressions that must match legalChildTypes
|
|
67
|
-
*/
|
|
68
|
-
typeCheck(eNode, eVal) {
|
|
69
|
-
if (!index_1.FT.in(eVal, this.legalChildTypes)) {
|
|
70
|
-
eNode.log(`'${this.elementType}' Can't use type ${index_1.FT.inspect(eVal)}`);
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* This is the operation which makes partial comparison and value trees work
|
|
77
|
-
* The default implemention merely constructs LEFT OP RIGHT, but specialized
|
|
78
|
-
* nodes like alternation trees or or partial comparison can control how
|
|
79
|
-
* the appplication gets generated
|
|
80
|
-
* @param fs The symbol table
|
|
81
|
-
* @param op The operator being applied
|
|
82
|
-
* @param expr The "other" (besdies 'this') value
|
|
83
|
-
* @returns The translated expression
|
|
84
|
-
*/
|
|
85
|
-
apply(fs, op, left) {
|
|
86
|
-
return (0, apply_expr_1.applyBinary)(fs, left, op, this);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
exports.ExpressionDef = ExpressionDef;
|
|
90
|
-
class DollarReference extends ExpressionDef {
|
|
91
|
-
constructor(refType) {
|
|
92
|
-
super();
|
|
93
|
-
this.refType = refType;
|
|
94
|
-
this.elementType = "$";
|
|
95
|
-
}
|
|
96
|
-
getExpression(_fs) {
|
|
97
|
-
return {
|
|
98
|
-
dataType: this.refType,
|
|
99
|
-
value: [{ type: "applyVal" }],
|
|
100
|
-
expressionType: "scalar",
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
class ConstantFieldSpace {
|
|
105
|
-
constructor() {
|
|
106
|
-
this.type = "fieldSpace";
|
|
107
|
-
}
|
|
108
|
-
structDef() {
|
|
109
|
-
throw new Error("ConstantFieldSpace cannot generate a structDef");
|
|
110
|
-
}
|
|
111
|
-
emptyStructDef() {
|
|
112
|
-
throw new Error("ConstantFieldSpace cannot generate a structDef");
|
|
113
|
-
}
|
|
114
|
-
lookup(_name) {
|
|
115
|
-
return {
|
|
116
|
-
error: "Only constants allowed in parameter expressions",
|
|
117
|
-
found: undefined,
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
dialectObj() {
|
|
121
|
-
return undefined;
|
|
122
|
-
}
|
|
123
|
-
whenComplete(step) {
|
|
124
|
-
step();
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
class ConstantSubExpression extends ExpressionDef {
|
|
128
|
-
constructor(expr) {
|
|
129
|
-
super({ expr });
|
|
130
|
-
this.expr = expr;
|
|
131
|
-
this.elementType = "constantExpression";
|
|
132
|
-
}
|
|
133
|
-
getExpression(_fs) {
|
|
134
|
-
return this.constantValue();
|
|
135
|
-
}
|
|
136
|
-
get constantFs() {
|
|
137
|
-
if (!this.cfs) {
|
|
138
|
-
this.cfs = new ConstantFieldSpace();
|
|
139
|
-
}
|
|
140
|
-
return this.cfs;
|
|
141
|
-
}
|
|
142
|
-
constantValue() {
|
|
143
|
-
return this.expr.getExpression(this.constantFs);
|
|
144
|
-
}
|
|
145
|
-
constantCondition(type) {
|
|
146
|
-
const compareAndContrast = new index_1.ExprCompare(new DollarReference(type), "=", this.expr);
|
|
147
|
-
const application = compareAndContrast.getExpression(this.constantFs);
|
|
148
|
-
return { ...application, value: (0, index_1.compressExpr)(application.value) };
|
|
149
|
-
}
|
|
150
|
-
apply(fs, op, expr) {
|
|
151
|
-
return this.expr.apply(fs, op, expr);
|
|
152
|
-
}
|
|
153
|
-
requestExpression(fs) {
|
|
154
|
-
return this.expr.requestExpression(fs);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
exports.ConstantSubExpression = ConstantSubExpression;
|
|
158
|
-
class FieldDeclaration extends index_1.MalloyElement {
|
|
159
|
-
constructor(expr, defineName, exprSrc) {
|
|
160
|
-
super({ expr });
|
|
161
|
-
this.expr = expr;
|
|
162
|
-
this.defineName = defineName;
|
|
163
|
-
this.exprSrc = exprSrc;
|
|
164
|
-
this.elementType = "fieldDeclaration";
|
|
165
|
-
}
|
|
166
|
-
fieldDef(fs, exprName) {
|
|
167
|
-
/*
|
|
168
|
-
* In an explore we cannot reference the thing we are defining, you need
|
|
169
|
-
* to use rename. In a query, the output space is a new thing, and expressions
|
|
170
|
-
* can reference the outer value in order to make a value with the new name,
|
|
171
|
-
* and it feels wrong that this is HERE and not somehow in the QueryOperation.
|
|
172
|
-
* For now, this stops the stack overflow, and passes all tests, but I think
|
|
173
|
-
* a refactor of QueryFieldSpace might someday be the place where this should
|
|
174
|
-
* happen.
|
|
175
|
-
*/
|
|
176
|
-
return this.queryFieldDef(new field_space_1.DefSpace(fs, this), exprName);
|
|
177
|
-
}
|
|
178
|
-
queryFieldDef(exprFS, exprName) {
|
|
179
|
-
let exprValue;
|
|
180
|
-
try {
|
|
181
|
-
exprValue = this.expr.getExpression(exprFS);
|
|
182
|
-
}
|
|
183
|
-
catch (error) {
|
|
184
|
-
this.log(`Cannot define '${exprName}', ${error.message}`);
|
|
185
|
-
return {
|
|
186
|
-
name: `error_defining_${exprName}`,
|
|
187
|
-
type: "string",
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
const compressValue = (0, index_1.compressExpr)(exprValue.value);
|
|
191
|
-
const retType = exprValue.dataType;
|
|
192
|
-
if ((0, malloy_types_1.isAtomicFieldType)(retType)) {
|
|
193
|
-
const template = {
|
|
194
|
-
name: exprName,
|
|
195
|
-
type: retType,
|
|
196
|
-
location: this.location,
|
|
197
|
-
};
|
|
198
|
-
if (compressValue.length > 0) {
|
|
199
|
-
template.e = compressValue;
|
|
200
|
-
}
|
|
201
|
-
if (exprValue.expressionType) {
|
|
202
|
-
template.expressionType = exprValue.expressionType;
|
|
203
|
-
}
|
|
204
|
-
if (this.exprSrc) {
|
|
205
|
-
template.code = this.exprSrc;
|
|
206
|
-
}
|
|
207
|
-
// TODO this should work for dates too
|
|
208
|
-
if ((0, index_1.isGranularResult)(exprValue) && template.type === "timestamp") {
|
|
209
|
-
template.timeframe = exprValue.timeframe;
|
|
210
|
-
}
|
|
211
|
-
return template;
|
|
212
|
-
}
|
|
213
|
-
const circularDef = exprFS instanceof field_space_1.DefSpace && exprFS.foundCircle;
|
|
214
|
-
if (!circularDef) {
|
|
215
|
-
if (exprValue.dataType == "unknown") {
|
|
216
|
-
this.log(`Cannot define '${exprName}', value has unknown type`);
|
|
217
|
-
}
|
|
218
|
-
else {
|
|
219
|
-
const badType = index_1.FT.inspect(exprValue);
|
|
220
|
-
this.log(`Cannot define '${exprName}', unexpected type: ${badType}`);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
return {
|
|
224
|
-
name: `error_defining_${exprName}`,
|
|
225
|
-
type: "string",
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
exports.FieldDeclaration = FieldDeclaration;
|
|
230
|
-
class TypeMistmatch extends Error {
|
|
231
|
-
}
|
|
232
|
-
exports.TypeMistmatch = TypeMistmatch;
|
|
233
|
-
class ExprString extends ExpressionDef {
|
|
37
|
+
class ExprString extends ast_main_1.ExpressionDef {
|
|
234
38
|
constructor(src) {
|
|
235
39
|
super();
|
|
236
40
|
this.elementType = "string literal";
|
|
@@ -240,7 +44,7 @@ class ExprString extends ExpressionDef {
|
|
|
240
44
|
}
|
|
241
45
|
getExpression(_fs) {
|
|
242
46
|
return {
|
|
243
|
-
...
|
|
47
|
+
...ast_types_1.FT.stringT,
|
|
244
48
|
value: [
|
|
245
49
|
{
|
|
246
50
|
type: "dialect",
|
|
@@ -252,7 +56,7 @@ class ExprString extends ExpressionDef {
|
|
|
252
56
|
}
|
|
253
57
|
}
|
|
254
58
|
exports.ExprString = ExprString;
|
|
255
|
-
class ExprNumber extends ExpressionDef {
|
|
59
|
+
class ExprNumber extends ast_main_1.ExpressionDef {
|
|
256
60
|
constructor(n) {
|
|
257
61
|
super();
|
|
258
62
|
this.n = n;
|
|
@@ -262,11 +66,11 @@ class ExprNumber extends ExpressionDef {
|
|
|
262
66
|
return this.constantExpression();
|
|
263
67
|
}
|
|
264
68
|
constantExpression() {
|
|
265
|
-
return { ...
|
|
69
|
+
return { ...ast_types_1.FT.numberT, value: [this.n] };
|
|
266
70
|
}
|
|
267
71
|
}
|
|
268
72
|
exports.ExprNumber = ExprNumber;
|
|
269
|
-
class ExprRegEx extends ExpressionDef {
|
|
73
|
+
class ExprRegEx extends ast_main_1.ExpressionDef {
|
|
270
74
|
constructor(regex) {
|
|
271
75
|
super();
|
|
272
76
|
this.regex = regex;
|
|
@@ -281,40 +85,7 @@ class ExprRegEx extends ExpressionDef {
|
|
|
281
85
|
}
|
|
282
86
|
}
|
|
283
87
|
exports.ExprRegEx = ExprRegEx;
|
|
284
|
-
class
|
|
285
|
-
constructor(timeType, value, expressionType = "scalar") {
|
|
286
|
-
super();
|
|
287
|
-
this.elementType = "timestampOrDate";
|
|
288
|
-
this.elementType = timeType;
|
|
289
|
-
this.translationValue = {
|
|
290
|
-
dataType: timeType,
|
|
291
|
-
expressionType,
|
|
292
|
-
value: typeof value === "string" ? [value] : value,
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
getExpression(_fs) {
|
|
296
|
-
return this.translationValue;
|
|
297
|
-
}
|
|
298
|
-
static fromValue(timeType, expr) {
|
|
299
|
-
let value = expr.value;
|
|
300
|
-
if (timeType != expr.dataType) {
|
|
301
|
-
const toTs = {
|
|
302
|
-
type: "dialect",
|
|
303
|
-
function: "cast",
|
|
304
|
-
safe: false,
|
|
305
|
-
dstType: timeType,
|
|
306
|
-
expr: expr.value,
|
|
307
|
-
};
|
|
308
|
-
if ((0, malloy_types_1.isTimeFieldType)(expr.dataType)) {
|
|
309
|
-
toTs.srcType = expr.dataType;
|
|
310
|
-
}
|
|
311
|
-
value = (0, index_1.compressExpr)([toTs]);
|
|
312
|
-
}
|
|
313
|
-
return new ExprTime(timeType, value, expr.expressionType);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
exports.ExprTime = ExprTime;
|
|
317
|
-
class Unary extends ExpressionDef {
|
|
88
|
+
class Unary extends ast_main_1.ExpressionDef {
|
|
318
89
|
constructor(expr) {
|
|
319
90
|
super({ expr });
|
|
320
91
|
this.expr = expr;
|
|
@@ -324,7 +95,7 @@ class ExprNot extends Unary {
|
|
|
324
95
|
constructor(expr) {
|
|
325
96
|
super(expr);
|
|
326
97
|
this.elementType = "not";
|
|
327
|
-
this.legalChildTypes = [
|
|
98
|
+
this.legalChildTypes = [ast_types_1.FT.boolT, ast_types_1.FT.nullT];
|
|
328
99
|
}
|
|
329
100
|
getExpression(fs) {
|
|
330
101
|
const notThis = this.expr.getExpression(fs);
|
|
@@ -335,53 +106,30 @@ class ExprNot extends Unary {
|
|
|
335
106
|
value: (0, apply_expr_1.nullsafeNot)(notThis.value),
|
|
336
107
|
};
|
|
337
108
|
}
|
|
338
|
-
return (0,
|
|
109
|
+
return (0, ast_types_1.errorFor)("not requires boolean");
|
|
339
110
|
}
|
|
340
111
|
}
|
|
341
112
|
exports.ExprNot = ExprNot;
|
|
342
|
-
class Boolean extends ExpressionDef {
|
|
113
|
+
class Boolean extends ast_main_1.ExpressionDef {
|
|
343
114
|
constructor(value) {
|
|
344
115
|
super();
|
|
345
116
|
this.value = value;
|
|
346
117
|
this.elementType = "boolean literal";
|
|
347
118
|
}
|
|
348
119
|
getExpression() {
|
|
349
|
-
return { ...
|
|
120
|
+
return { ...ast_types_1.FT.boolT, value: [this.value] };
|
|
350
121
|
}
|
|
351
122
|
}
|
|
352
123
|
exports.Boolean = Boolean;
|
|
353
|
-
class
|
|
354
|
-
constructor(left, op, right) {
|
|
355
|
-
super({ left, right });
|
|
356
|
-
this.left = left;
|
|
357
|
-
this.op = op;
|
|
358
|
-
this.right = right;
|
|
359
|
-
this.elementType = "abstract boolean binary";
|
|
360
|
-
this.legalChildTypes = [index_1.FT.boolT];
|
|
361
|
-
}
|
|
362
|
-
getExpression(fs) {
|
|
363
|
-
const left = this.left.getExpression(fs);
|
|
364
|
-
const right = this.right.getExpression(fs);
|
|
365
|
-
if (this.typeCheck(this.left, left) && this.typeCheck(this.right, right)) {
|
|
366
|
-
return {
|
|
367
|
-
dataType: "boolean",
|
|
368
|
-
expressionType: (0, malloy_types_1.maxExpressionType)(left.expressionType, right.expressionType),
|
|
369
|
-
value: (0, index_1.compose)(left.value, this.op, right.value),
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
return (0, index_1.errorFor)("logial required boolean");
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
exports.BinaryBoolean = BinaryBoolean;
|
|
376
|
-
class ExprLogicalOp extends BinaryBoolean {
|
|
124
|
+
class ExprLogicalOp extends ast_main_1.BinaryBoolean {
|
|
377
125
|
constructor() {
|
|
378
126
|
super(...arguments);
|
|
379
127
|
this.elementType = "logical operator";
|
|
380
|
-
this.legalChildTypes = [
|
|
128
|
+
this.legalChildTypes = [ast_types_1.FT.boolT, { ...ast_types_1.FT.boolT, aggregate: true }];
|
|
381
129
|
}
|
|
382
130
|
}
|
|
383
131
|
exports.ExprLogicalOp = ExprLogicalOp;
|
|
384
|
-
class ExprIdReference extends ExpressionDef {
|
|
132
|
+
class ExprIdReference extends ast_main_1.ExpressionDef {
|
|
385
133
|
constructor(fieldReference) {
|
|
386
134
|
super();
|
|
387
135
|
this.fieldReference = fieldReference;
|
|
@@ -402,7 +150,7 @@ class ExprIdReference extends ExpressionDef {
|
|
|
402
150
|
return { dataType, expressionType, value };
|
|
403
151
|
}
|
|
404
152
|
this.log(def.error);
|
|
405
|
-
return (0,
|
|
153
|
+
return (0, ast_types_1.errorFor)(def.error);
|
|
406
154
|
}
|
|
407
155
|
apply(fs, op, expr) {
|
|
408
156
|
const entry = this.fieldReference.getField(fs).found;
|
|
@@ -427,7 +175,7 @@ class ExprIdReference extends ExpressionDef {
|
|
|
427
175
|
}
|
|
428
176
|
}
|
|
429
177
|
exports.ExprIdReference = ExprIdReference;
|
|
430
|
-
class ExprNULL extends ExpressionDef {
|
|
178
|
+
class ExprNULL extends ast_main_1.ExpressionDef {
|
|
431
179
|
constructor() {
|
|
432
180
|
super(...arguments);
|
|
433
181
|
this.elementType = "NULL";
|
|
@@ -441,7 +189,7 @@ class ExprNULL extends ExpressionDef {
|
|
|
441
189
|
}
|
|
442
190
|
}
|
|
443
191
|
exports.ExprNULL = ExprNULL;
|
|
444
|
-
class ExprParens extends ExpressionDef {
|
|
192
|
+
class ExprParens extends ast_main_1.ExpressionDef {
|
|
445
193
|
constructor(expr) {
|
|
446
194
|
super({ expr });
|
|
447
195
|
this.expr = expr;
|
|
@@ -456,12 +204,12 @@ class ExprParens extends ExpressionDef {
|
|
|
456
204
|
}
|
|
457
205
|
}
|
|
458
206
|
exports.ExprParens = ExprParens;
|
|
459
|
-
class ExprMinus extends ExpressionDef {
|
|
207
|
+
class ExprMinus extends ast_main_1.ExpressionDef {
|
|
460
208
|
constructor(expr) {
|
|
461
209
|
super({ expr });
|
|
462
210
|
this.expr = expr;
|
|
463
211
|
this.elementType = "unary minus";
|
|
464
|
-
this.legalChildTypes = [
|
|
212
|
+
this.legalChildTypes = [ast_types_1.FT.numberT];
|
|
465
213
|
}
|
|
466
214
|
getExpression(fs) {
|
|
467
215
|
const expr = this.expr.getExpression(fs);
|
|
@@ -471,18 +219,18 @@ class ExprMinus extends ExpressionDef {
|
|
|
471
219
|
}
|
|
472
220
|
return { ...expr, value: ["-", ...expr.value] };
|
|
473
221
|
}
|
|
474
|
-
return (0,
|
|
222
|
+
return (0, ast_types_1.errorFor)("negate requires number");
|
|
475
223
|
}
|
|
476
224
|
}
|
|
477
225
|
exports.ExprMinus = ExprMinus;
|
|
478
|
-
class BinaryNumeric extends ExpressionDef {
|
|
226
|
+
class BinaryNumeric extends ast_main_1.ExpressionDef {
|
|
479
227
|
constructor(left, op, right) {
|
|
480
228
|
super({ left, right });
|
|
481
229
|
this.left = left;
|
|
482
230
|
this.op = op;
|
|
483
231
|
this.right = right;
|
|
484
232
|
this.elementType = "numeric binary abstract";
|
|
485
|
-
this.legalChildTypes = [
|
|
233
|
+
this.legalChildTypes = [ast_types_1.FT.numberT];
|
|
486
234
|
}
|
|
487
235
|
getExpression(fs) {
|
|
488
236
|
return this.right.apply(fs, this.op, this.left);
|
|
@@ -503,7 +251,7 @@ class ExprMulDiv extends BinaryNumeric {
|
|
|
503
251
|
}
|
|
504
252
|
}
|
|
505
253
|
exports.ExprMulDiv = ExprMulDiv;
|
|
506
|
-
class ExprAlternationTree extends BinaryBoolean {
|
|
254
|
+
class ExprAlternationTree extends ast_main_1.BinaryBoolean {
|
|
507
255
|
constructor(left, op, right) {
|
|
508
256
|
super(left, op, right);
|
|
509
257
|
this.elementType = "alternation";
|
|
@@ -515,7 +263,7 @@ class ExprAlternationTree extends BinaryBoolean {
|
|
|
515
263
|
return {
|
|
516
264
|
dataType: "boolean",
|
|
517
265
|
expressionType: (0, malloy_types_1.maxExpressionType)(choice1.expressionType, choice2.expressionType),
|
|
518
|
-
value: (0,
|
|
266
|
+
value: (0, ast_types_1.compose)(choice1.value, this.op === "&" ? "and" : "or", choice2.value),
|
|
519
267
|
};
|
|
520
268
|
}
|
|
521
269
|
requestExpression(_fs) {
|
|
@@ -523,15 +271,15 @@ class ExprAlternationTree extends BinaryBoolean {
|
|
|
523
271
|
}
|
|
524
272
|
getExpression(_fs) {
|
|
525
273
|
this.log(`Alternation tree has no value`);
|
|
526
|
-
return (0,
|
|
274
|
+
return (0, ast_types_1.errorFor)("no value from alternation tree");
|
|
527
275
|
}
|
|
528
276
|
}
|
|
529
277
|
exports.ExprAlternationTree = ExprAlternationTree;
|
|
530
|
-
class ExprAggregateFunction extends ExpressionDef {
|
|
278
|
+
class ExprAggregateFunction extends ast_main_1.ExpressionDef {
|
|
531
279
|
constructor(func, expr) {
|
|
532
280
|
super();
|
|
533
281
|
this.func = func;
|
|
534
|
-
this.legalChildTypes = [
|
|
282
|
+
this.legalChildTypes = [ast_types_1.FT.numberT];
|
|
535
283
|
this.elementType = func;
|
|
536
284
|
if (expr) {
|
|
537
285
|
this.expr = expr;
|
|
@@ -560,18 +308,18 @@ class ExprAggregateFunction extends ExpressionDef {
|
|
|
560
308
|
else {
|
|
561
309
|
if (!(sourceFoot instanceof space_field_1.StructSpaceField)) {
|
|
562
310
|
this.log(`Aggregate source cannot be a ${footType.type}`);
|
|
563
|
-
return (0,
|
|
311
|
+
return (0, ast_types_1.errorFor)(`Aggregate source cannot be a ${footType.type}`);
|
|
564
312
|
}
|
|
565
313
|
}
|
|
566
314
|
}
|
|
567
315
|
else {
|
|
568
316
|
this.log(`Reference to undefined value ${this.source.refString}`);
|
|
569
|
-
return (0,
|
|
317
|
+
return (0, ast_types_1.errorFor)(`Reference to undefined value ${this.source.refString}`);
|
|
570
318
|
}
|
|
571
319
|
}
|
|
572
320
|
if (exprVal === undefined) {
|
|
573
321
|
this.log("Missing expression for aggregate function");
|
|
574
|
-
return (0,
|
|
322
|
+
return (0, ast_types_1.errorFor)("agggregate without expression");
|
|
575
323
|
}
|
|
576
324
|
if (this.typeCheck(this.expr || this, {
|
|
577
325
|
...exprVal,
|
|
@@ -591,13 +339,13 @@ class ExprAggregateFunction extends ExpressionDef {
|
|
|
591
339
|
value: [f],
|
|
592
340
|
};
|
|
593
341
|
}
|
|
594
|
-
return (0,
|
|
342
|
+
return (0, ast_types_1.errorFor)("aggregate type check");
|
|
595
343
|
}
|
|
596
344
|
}
|
|
597
345
|
class ExprMin extends ExprAggregateFunction {
|
|
598
346
|
constructor(expr) {
|
|
599
347
|
super("min", expr);
|
|
600
|
-
this.legalChildTypes = [
|
|
348
|
+
this.legalChildTypes = [ast_types_1.FT.numberT, ast_types_1.FT.stringT, ast_types_1.FT.dateT, ast_types_1.FT.timestampT];
|
|
601
349
|
}
|
|
602
350
|
returns(forExpression) {
|
|
603
351
|
return forExpression.dataType;
|
|
@@ -607,7 +355,7 @@ exports.ExprMin = ExprMin;
|
|
|
607
355
|
class ExprMax extends ExprAggregateFunction {
|
|
608
356
|
constructor(expr) {
|
|
609
357
|
super("max", expr);
|
|
610
|
-
this.legalChildTypes = [
|
|
358
|
+
this.legalChildTypes = [ast_types_1.FT.numberT, ast_types_1.FT.stringT, ast_types_1.FT.dateT, ast_types_1.FT.timestampT];
|
|
611
359
|
}
|
|
612
360
|
returns(forExpression) {
|
|
613
361
|
return forExpression.dataType;
|
|
@@ -617,7 +365,7 @@ exports.ExprMax = ExprMax;
|
|
|
617
365
|
class ExprCountDistinct extends ExprAggregateFunction {
|
|
618
366
|
constructor(expr) {
|
|
619
367
|
super("count_distinct", expr);
|
|
620
|
-
this.legalChildTypes = [
|
|
368
|
+
this.legalChildTypes = [ast_types_1.FT.numberT, ast_types_1.FT.stringT, ast_types_1.FT.dateT, ast_types_1.FT.timestampT];
|
|
621
369
|
}
|
|
622
370
|
}
|
|
623
371
|
exports.ExprCountDistinct = ExprCountDistinct;
|
|
@@ -686,13 +434,13 @@ class ExprSum extends ExprAsymmetric {
|
|
|
686
434
|
}
|
|
687
435
|
}
|
|
688
436
|
exports.ExprSum = ExprSum;
|
|
689
|
-
class ExprUngroup extends ExpressionDef {
|
|
437
|
+
class ExprUngroup extends ast_main_1.ExpressionDef {
|
|
690
438
|
constructor(control, expr, fields) {
|
|
691
439
|
super({ expr, fields });
|
|
692
440
|
this.control = control;
|
|
693
441
|
this.expr = expr;
|
|
694
442
|
this.fields = fields;
|
|
695
|
-
this.legalChildTypes =
|
|
443
|
+
this.legalChildTypes = ast_types_1.FT.anyAtomicT;
|
|
696
444
|
this.elementType = "ungroup";
|
|
697
445
|
}
|
|
698
446
|
returns(_forExpression) {
|
|
@@ -702,7 +450,7 @@ class ExprUngroup extends ExpressionDef {
|
|
|
702
450
|
const exprVal = this.expr.getExpression(fs);
|
|
703
451
|
if (!(0, malloy_types_1.expressionIsAggregate)(exprVal.expressionType)) {
|
|
704
452
|
this.expr.log(`${this.control}() expression must be an aggregate`);
|
|
705
|
-
return (0,
|
|
453
|
+
return (0, ast_types_1.errorFor)("ungrouped scalar");
|
|
706
454
|
}
|
|
707
455
|
const ungroup = { type: this.control, e: exprVal.value };
|
|
708
456
|
if (this.typeCheck(this.expr, { ...exprVal, expressionType: "scalar" })) {
|
|
@@ -713,7 +461,7 @@ class ExprUngroup extends ExpressionDef {
|
|
|
713
461
|
}
|
|
714
462
|
if (!(qs instanceof field_space_1.QuerySpace)) {
|
|
715
463
|
this.log(`${this.control}() must be in a query -- weird internal error`);
|
|
716
|
-
return (0,
|
|
464
|
+
return (0, ast_types_1.errorFor)("ungroup query check");
|
|
717
465
|
}
|
|
718
466
|
const output = qs.result;
|
|
719
467
|
const dstFields = [];
|
|
@@ -733,11 +481,11 @@ class ExprUngroup extends ExpressionDef {
|
|
|
733
481
|
};
|
|
734
482
|
}
|
|
735
483
|
this.log(`${this.control}() incompatible type`);
|
|
736
|
-
return (0,
|
|
484
|
+
return (0, ast_types_1.errorFor)("ungrouped type check");
|
|
737
485
|
}
|
|
738
486
|
}
|
|
739
487
|
exports.ExprUngroup = ExprUngroup;
|
|
740
|
-
class WhenClause extends ExpressionDef {
|
|
488
|
+
class WhenClause extends ast_main_1.ExpressionDef {
|
|
741
489
|
constructor(whenThis, thenThis) {
|
|
742
490
|
super({ whenThis, thenThis });
|
|
743
491
|
this.whenThis = whenThis;
|
|
@@ -749,7 +497,7 @@ class WhenClause extends ExpressionDef {
|
|
|
749
497
|
}
|
|
750
498
|
}
|
|
751
499
|
exports.WhenClause = WhenClause;
|
|
752
|
-
class ExprCase extends ExpressionDef {
|
|
500
|
+
class ExprCase extends ast_main_1.ExpressionDef {
|
|
753
501
|
constructor(when, elseClause) {
|
|
754
502
|
super({ when });
|
|
755
503
|
this.when = when;
|
|
@@ -766,9 +514,9 @@ class ExprCase extends ExpressionDef {
|
|
|
766
514
|
const thenExpr = clause.thenThis.getExpression(fs);
|
|
767
515
|
expressionType = (0, malloy_types_1.maxExpressionType)(expressionType, (0, malloy_types_1.maxExpressionType)(whenExpr.expressionType, thenExpr.expressionType));
|
|
768
516
|
if (thenExpr.dataType !== "null") {
|
|
769
|
-
if (retType && !
|
|
770
|
-
this.log(`Mismatched THEN clause types, ${
|
|
771
|
-
return (0,
|
|
517
|
+
if (retType && !ast_types_1.FT.typeEq(retType, thenExpr)) {
|
|
518
|
+
this.log(`Mismatched THEN clause types, ${ast_types_1.FT.inspect(retType, thenExpr)}`);
|
|
519
|
+
return (0, ast_types_1.errorFor)("then typecheck");
|
|
772
520
|
}
|
|
773
521
|
else {
|
|
774
522
|
retType = thenExpr;
|
|
@@ -781,9 +529,9 @@ class ExprCase extends ExpressionDef {
|
|
|
781
529
|
expressionType = (0, malloy_types_1.maxExpressionType)(expressionType, elseExpr.expressionType);
|
|
782
530
|
caseExpr.push(" ELSE ", ...elseExpr.value);
|
|
783
531
|
if (elseExpr.dataType !== "null") {
|
|
784
|
-
if (retType && !
|
|
785
|
-
this.log(`Mismatched ELSE clause type, ${
|
|
786
|
-
return (0,
|
|
532
|
+
if (retType && !ast_types_1.FT.typeEq(retType, elseExpr)) {
|
|
533
|
+
this.log(`Mismatched ELSE clause type, ${ast_types_1.FT.inspect(retType, elseExpr)}`);
|
|
534
|
+
return (0, ast_types_1.errorFor)("else typecheck");
|
|
787
535
|
}
|
|
788
536
|
else {
|
|
789
537
|
retType = elseExpr;
|
|
@@ -792,7 +540,7 @@ class ExprCase extends ExpressionDef {
|
|
|
792
540
|
}
|
|
793
541
|
if (retType === undefined) {
|
|
794
542
|
this.log("case statement type not computable");
|
|
795
|
-
return (0,
|
|
543
|
+
return (0, ast_types_1.errorFor)("typeless case");
|
|
796
544
|
}
|
|
797
545
|
caseExpr.push(" END");
|
|
798
546
|
return {
|
|
@@ -803,13 +551,13 @@ class ExprCase extends ExpressionDef {
|
|
|
803
551
|
}
|
|
804
552
|
}
|
|
805
553
|
exports.ExprCase = ExprCase;
|
|
806
|
-
class ExprFilter extends ExpressionDef {
|
|
554
|
+
class ExprFilter extends ast_main_1.ExpressionDef {
|
|
807
555
|
constructor(expr, filter) {
|
|
808
556
|
super({ expr, filter });
|
|
809
557
|
this.expr = expr;
|
|
810
558
|
this.filter = filter;
|
|
811
559
|
this.elementType = "filtered expression";
|
|
812
|
-
this.legalChildTypes =
|
|
560
|
+
this.legalChildTypes = ast_types_1.FT.anyAtomicT;
|
|
813
561
|
}
|
|
814
562
|
getExpression(fs) {
|
|
815
563
|
const testList = this.filter.getFilterList(fs);
|
|
@@ -817,7 +565,7 @@ class ExprFilter extends ExpressionDef {
|
|
|
817
565
|
for (const cond of testList) {
|
|
818
566
|
if ((0, malloy_types_1.expressionIsCalculation)(cond.expressionType)) {
|
|
819
567
|
this.filter.log("Cannot filter a field with an aggregate or analytical computation");
|
|
820
|
-
return (0,
|
|
568
|
+
return (0, ast_types_1.errorFor)("no filter on aggregate");
|
|
821
569
|
}
|
|
822
570
|
}
|
|
823
571
|
if (resultExpr.expressionType === "scalar") {
|
|
@@ -838,7 +586,7 @@ class ExprFilter extends ExpressionDef {
|
|
|
838
586
|
};
|
|
839
587
|
}
|
|
840
588
|
this.expr.log(`Cannot filter '${resultExpr.dataType}' data`);
|
|
841
|
-
return (0,
|
|
589
|
+
return (0, ast_types_1.errorFor)("cannot filter type");
|
|
842
590
|
}
|
|
843
591
|
}
|
|
844
592
|
exports.ExprFilter = ExprFilter;
|
|
@@ -846,7 +594,7 @@ function isCastType(t) {
|
|
|
846
594
|
return ["string", "number", "boolean", "date", "timestamp"].includes(t);
|
|
847
595
|
}
|
|
848
596
|
exports.isCastType = isCastType;
|
|
849
|
-
class ExprCast extends ExpressionDef {
|
|
597
|
+
class ExprCast extends ast_main_1.ExpressionDef {
|
|
850
598
|
constructor(expr, castType, safe = false) {
|
|
851
599
|
super({ expr });
|
|
852
600
|
this.expr = expr;
|
|
@@ -859,83 +607,33 @@ class ExprCast extends ExpressionDef {
|
|
|
859
607
|
return {
|
|
860
608
|
dataType: this.castType,
|
|
861
609
|
expressionType: expr.expressionType,
|
|
862
|
-
value: (0,
|
|
610
|
+
value: (0, ast_types_1.compressExpr)((0, time_utils_1.castTo)(this.castType, expr.value, this.safe)),
|
|
863
611
|
};
|
|
864
612
|
}
|
|
865
613
|
}
|
|
866
614
|
exports.ExprCast = ExprCast;
|
|
867
|
-
class TopBy extends
|
|
615
|
+
class TopBy extends ast_main_1.MalloyElement {
|
|
868
616
|
constructor(by) {
|
|
869
617
|
super();
|
|
870
618
|
this.by = by;
|
|
871
619
|
this.elementType = "topBy";
|
|
872
|
-
if (by instanceof ExpressionDef) {
|
|
620
|
+
if (by instanceof ast_main_1.ExpressionDef) {
|
|
873
621
|
this.has({ by });
|
|
874
622
|
}
|
|
875
623
|
}
|
|
876
624
|
getBy(fs) {
|
|
877
|
-
if (this.by instanceof ExpressionDef) {
|
|
625
|
+
if (this.by instanceof ast_main_1.ExpressionDef) {
|
|
878
626
|
const byExpr = this.by.getExpression(fs);
|
|
879
627
|
if (!(0, malloy_types_1.expressionIsAggregate)(byExpr.expressionType)) {
|
|
880
628
|
this.log("top by expression must be an aggregate");
|
|
881
629
|
}
|
|
882
|
-
return { by: "expression", e: (0,
|
|
630
|
+
return { by: "expression", e: (0, ast_types_1.compressExpr)(byExpr.value) };
|
|
883
631
|
}
|
|
884
632
|
return { by: "name", name: this.by };
|
|
885
633
|
}
|
|
886
634
|
}
|
|
887
635
|
exports.TopBy = TopBy;
|
|
888
|
-
class
|
|
889
|
-
constructor(first, last) {
|
|
890
|
-
super({ first, last });
|
|
891
|
-
this.first = first;
|
|
892
|
-
this.last = last;
|
|
893
|
-
this.elementType = "range";
|
|
894
|
-
}
|
|
895
|
-
apply(fs, op, expr) {
|
|
896
|
-
switch (op) {
|
|
897
|
-
case "=":
|
|
898
|
-
case "!=": {
|
|
899
|
-
const op1 = op === "=" ? ">=" : "<";
|
|
900
|
-
const op2 = op === "=" ? "and" : "or";
|
|
901
|
-
const op3 = op === "=" ? "<" : ">=";
|
|
902
|
-
const fromValue = this.first.apply(fs, op1, expr);
|
|
903
|
-
const toValue = this.last.apply(fs, op3, expr);
|
|
904
|
-
return {
|
|
905
|
-
dataType: "boolean",
|
|
906
|
-
expressionType: (0, malloy_types_1.maxExpressionType)(fromValue.expressionType, toValue.expressionType),
|
|
907
|
-
value: (0, index_1.compose)(fromValue.value, op2, toValue.value),
|
|
908
|
-
};
|
|
909
|
-
}
|
|
910
|
-
/**
|
|
911
|
-
* This is a little surprising, but is actually how you comapre a
|
|
912
|
-
* value to a range ...
|
|
913
|
-
*
|
|
914
|
-
* val > begin to end val >= end
|
|
915
|
-
* val >= begin to end val >= begin
|
|
916
|
-
* val < begin to end val < begin
|
|
917
|
-
* val <= begin to end val < end
|
|
918
|
-
*/
|
|
919
|
-
case ">":
|
|
920
|
-
return this.last.apply(fs, ">=", expr);
|
|
921
|
-
case ">=":
|
|
922
|
-
return this.first.apply(fs, ">=", expr);
|
|
923
|
-
case "<":
|
|
924
|
-
return this.first.apply(fs, "<", expr);
|
|
925
|
-
case "<=":
|
|
926
|
-
return this.last.apply(fs, "<", expr);
|
|
927
|
-
}
|
|
928
|
-
throw new Error("mysterious error in range computation");
|
|
929
|
-
}
|
|
930
|
-
requestExpression(_fs) {
|
|
931
|
-
return undefined;
|
|
932
|
-
}
|
|
933
|
-
getExpression(_fs) {
|
|
934
|
-
return (0, index_1.errorFor)("a range is not a value");
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
exports.Range = Range;
|
|
938
|
-
class PickWhen extends index_1.MalloyElement {
|
|
636
|
+
class PickWhen extends ast_main_1.MalloyElement {
|
|
939
637
|
constructor(pick, when) {
|
|
940
638
|
super({ when });
|
|
941
639
|
this.pick = pick;
|
|
@@ -945,7 +643,7 @@ class PickWhen extends index_1.MalloyElement {
|
|
|
945
643
|
}
|
|
946
644
|
}
|
|
947
645
|
exports.PickWhen = PickWhen;
|
|
948
|
-
class Pick extends ExpressionDef {
|
|
646
|
+
class Pick extends ast_main_1.ExpressionDef {
|
|
949
647
|
constructor(choices, elsePick) {
|
|
950
648
|
super({ choices });
|
|
951
649
|
this.choices = choices;
|
|
@@ -982,10 +680,10 @@ class Pick extends ExpressionDef {
|
|
|
982
680
|
: expr.getExpression(fs);
|
|
983
681
|
anyExpressionType = (0, malloy_types_1.maxExpressionType)(anyExpressionType, (0, malloy_types_1.maxExpressionType)(whenExpr.expressionType, thenExpr.expressionType));
|
|
984
682
|
if (returnType) {
|
|
985
|
-
if (!
|
|
986
|
-
const whenType =
|
|
683
|
+
if (!ast_types_1.FT.typeEq(returnType, thenExpr, true)) {
|
|
684
|
+
const whenType = ast_types_1.FT.inspect(thenExpr);
|
|
987
685
|
this.log(`pick type '${whenType}', expected '${returnType.dataType}'`);
|
|
988
|
-
return (0,
|
|
686
|
+
return (0, ast_types_1.errorFor)("pick when type");
|
|
989
687
|
}
|
|
990
688
|
}
|
|
991
689
|
else {
|
|
@@ -996,32 +694,32 @@ class Pick extends ExpressionDef {
|
|
|
996
694
|
const elsePart = this.elsePick || expr;
|
|
997
695
|
const elseVal = elsePart.getExpression(fs);
|
|
998
696
|
returnType || (returnType = elseVal);
|
|
999
|
-
if (!
|
|
697
|
+
if (!ast_types_1.FT.typeEq(returnType, elseVal, true)) {
|
|
1000
698
|
const errSrc = this.elsePick ? "else" : "pick default";
|
|
1001
|
-
this.log(`${errSrc} type '${
|
|
1002
|
-
return (0,
|
|
699
|
+
this.log(`${errSrc} type '${ast_types_1.FT.inspect(elseVal)}', expected '${returnType.dataType}'`);
|
|
700
|
+
return (0, ast_types_1.errorFor)("pick else type");
|
|
1003
701
|
}
|
|
1004
702
|
return {
|
|
1005
703
|
dataType: returnType.dataType,
|
|
1006
704
|
expressionType: (0, malloy_types_1.maxExpressionType)(anyExpressionType, elseVal.expressionType),
|
|
1007
|
-
value: (0,
|
|
705
|
+
value: (0, ast_types_1.compressExpr)([...caseValue, " ELSE ", ...elseVal.value, " END"]),
|
|
1008
706
|
};
|
|
1009
707
|
}
|
|
1010
708
|
getExpression(fs) {
|
|
1011
709
|
if (this.elsePick === undefined) {
|
|
1012
710
|
this.log("pick incomplete, missing 'else'");
|
|
1013
|
-
return (0,
|
|
711
|
+
return (0, ast_types_1.errorFor)("no value for partial pick");
|
|
1014
712
|
}
|
|
1015
713
|
const choiceValues = [];
|
|
1016
714
|
for (const c of this.choices) {
|
|
1017
715
|
if (c.pick === undefined) {
|
|
1018
716
|
this.log("pick with no value can only be used with apply");
|
|
1019
|
-
return (0,
|
|
717
|
+
return (0, ast_types_1.errorFor)("no value for partial pick");
|
|
1020
718
|
}
|
|
1021
719
|
const pickWhen = c.when.requestExpression(fs);
|
|
1022
720
|
if (pickWhen === undefined) {
|
|
1023
721
|
this.log("pick with partial when can only be used with apply");
|
|
1024
|
-
return (0,
|
|
722
|
+
return (0, ast_types_1.errorFor)("partial when");
|
|
1025
723
|
}
|
|
1026
724
|
choiceValues.push({
|
|
1027
725
|
pick: c.pick.getExpression(fs),
|
|
@@ -1032,31 +730,54 @@ class Pick extends ExpressionDef {
|
|
|
1032
730
|
const caseValue = ["CASE"];
|
|
1033
731
|
let anyExpressionType = returnType.expressionType;
|
|
1034
732
|
for (const aChoice of choiceValues) {
|
|
1035
|
-
if (!
|
|
1036
|
-
this.log(`when expression must be boolean, not '${
|
|
1037
|
-
return (0,
|
|
733
|
+
if (!ast_types_1.FT.typeEq(aChoice.when, ast_types_1.FT.boolT)) {
|
|
734
|
+
this.log(`when expression must be boolean, not '${ast_types_1.FT.inspect(aChoice.when)}`);
|
|
735
|
+
return (0, ast_types_1.errorFor)("pick when type");
|
|
1038
736
|
}
|
|
1039
|
-
if (!
|
|
1040
|
-
const whenType =
|
|
737
|
+
if (!ast_types_1.FT.typeEq(returnType, aChoice.pick, true)) {
|
|
738
|
+
const whenType = ast_types_1.FT.inspect(aChoice.pick);
|
|
1041
739
|
this.log(`pick type '${whenType}', expected '${returnType.dataType}'`);
|
|
1042
|
-
return (0,
|
|
740
|
+
return (0, ast_types_1.errorFor)("pick value type");
|
|
1043
741
|
}
|
|
1044
742
|
anyExpressionType = (0, malloy_types_1.maxExpressionType)(anyExpressionType, (0, malloy_types_1.maxExpressionType)(aChoice.pick.expressionType, aChoice.when.expressionType));
|
|
1045
743
|
caseValue.push(" WHEN ", ...aChoice.when.value, " THEN ", ...aChoice.pick.value);
|
|
1046
744
|
}
|
|
1047
745
|
const defVal = this.elsePick.getExpression(fs);
|
|
1048
746
|
anyExpressionType = (0, malloy_types_1.maxExpressionType)(anyExpressionType, defVal.expressionType);
|
|
1049
|
-
if (!
|
|
1050
|
-
this.elsePick.log(`else type '${
|
|
1051
|
-
return (0,
|
|
747
|
+
if (!ast_types_1.FT.typeEq(returnType, defVal, true)) {
|
|
748
|
+
this.elsePick.log(`else type '${ast_types_1.FT.inspect(defVal)}', expected '${returnType.dataType}'`);
|
|
749
|
+
return (0, ast_types_1.errorFor)("pick value type mismatch");
|
|
1052
750
|
}
|
|
1053
751
|
caseValue.push(" ELSE ", ...defVal.value, " END");
|
|
1054
752
|
return {
|
|
1055
753
|
dataType: returnType.dataType,
|
|
1056
754
|
expressionType: anyExpressionType,
|
|
1057
|
-
value: (0,
|
|
755
|
+
value: (0, ast_types_1.compressExpr)(caseValue),
|
|
1058
756
|
};
|
|
1059
757
|
}
|
|
1060
758
|
}
|
|
1061
759
|
exports.Pick = Pick;
|
|
760
|
+
function nullCompare(left, op, right) {
|
|
761
|
+
const not = op === "!=" || op === "!~";
|
|
762
|
+
if (left.dataType === "null" || right.dataType === "null") {
|
|
763
|
+
const maybeNot = not ? " NOT" : "";
|
|
764
|
+
if (left.dataType !== "null") {
|
|
765
|
+
return [...left.value, ` IS${maybeNot} NULL`];
|
|
766
|
+
}
|
|
767
|
+
if (right.dataType !== "null") {
|
|
768
|
+
return [...right.value, `IS${maybeNot} NULL`];
|
|
769
|
+
}
|
|
770
|
+
return [not ? "false" : "true"];
|
|
771
|
+
}
|
|
772
|
+
return undefined;
|
|
773
|
+
}
|
|
774
|
+
class Apply extends ast_main_1.ExprCompare {
|
|
775
|
+
constructor(left, right) {
|
|
776
|
+
super(left, "=", right);
|
|
777
|
+
this.left = left;
|
|
778
|
+
this.right = right;
|
|
779
|
+
this.elementType = "apply";
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
exports.Apply = Apply;
|
|
1062
783
|
//# sourceMappingURL=ast-expr.js.map
|