@malloydata/malloy 0.0.3 → 0.0.4

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.
Files changed (37) hide show
  1. package/dist/lang/ast/ast-expr.d.ts +0 -1
  2. package/dist/lang/ast/ast-main.d.ts +2 -2
  3. package/package.json +1 -1
  4. package/dist/connection_utils.js +0 -56
  5. package/dist/dialect/dialect.js +0 -77
  6. package/dist/dialect/dialect_map.js +0 -35
  7. package/dist/dialect/duckdb.js +0 -347
  8. package/dist/dialect/index.js +0 -27
  9. package/dist/dialect/postgres.js +0 -315
  10. package/dist/dialect/standardsql.js +0 -362
  11. package/dist/index.js +0 -47
  12. package/dist/lang/ast/apply-expr.js +0 -231
  13. package/dist/lang/ast/ast-expr.js +0 -1041
  14. package/dist/lang/ast/ast-main.js +0 -2087
  15. package/dist/lang/ast/ast-time-expr.js +0 -549
  16. package/dist/lang/ast/ast-types.js +0 -215
  17. package/dist/lang/ast/index.js +0 -34
  18. package/dist/lang/ast/time-utils.js +0 -94
  19. package/dist/lang/field-space.js +0 -631
  20. package/dist/lang/field-utils.js +0 -33
  21. package/dist/lang/index.js +0 -22
  22. package/dist/lang/parse-log.js +0 -41
  23. package/dist/lang/reference-list.js +0 -80
  24. package/dist/lang/space-field.js +0 -346
  25. package/dist/lang/test/document-help-context-walker.spec.js +0 -45
  26. package/dist/lang/test/document-symbol-walker.spec.js +0 -100
  27. package/dist/lang/test/field-symbols.spec.js +0 -172
  28. package/dist/lang/test/parse.spec.js +0 -1951
  29. package/dist/lang/test/test-translator.js +0 -334
  30. package/dist/lang/zone.js +0 -97
  31. package/dist/malloy.js +0 -2360
  32. package/dist/model/index.js +0 -34
  33. package/dist/model/malloy_query.js +0 -2994
  34. package/dist/model/malloy_types.js +0 -283
  35. package/dist/model/sql_block.js +0 -41
  36. package/dist/model/utils.js +0 -84
  37. package/dist/runtime_types.js +0 -15
@@ -1,1041 +0,0 @@
1
- "use strict";
2
- /*
3
- * Copyright 2021 Google LLC
4
- *
5
- * This program is free software; you can redistribute it and/or
6
- * modify it under the terms of the GNU General Public License
7
- * version 2 as published by the Free Software Foundation.
8
- *
9
- * This program is distributed in the hope that it will be useful,
10
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- * GNU General Public License for more details.
13
- */
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.Pick = exports.PickWhen = exports.Range = 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.BinaryBoolean = exports.Boolean = exports.ExprNot = exports.ExprTime = exports.ExprRegEx = exports.ExprNumber = exports.ExprString = exports.TypeMistmatch = exports.FieldDeclaration = exports.ConstantSubExpression = exports.ExpressionDef = void 0;
16
- /*
17
- ** This file is the general framework for expression nodes and expression
18
- ** evaluation.
19
- */
20
- const malloy_types_1 = require("../../model/malloy_types");
21
- const field_space_1 = require("../field-space");
22
- const index_1 = require("./index");
23
- const apply_expr_1 = require("./apply-expr");
24
- const space_field_1 = require("../space-field");
25
- const time_utils_1 = require("./time-utils");
26
- /**
27
- * Root node for any element in an expression. These essentially
28
- * create a sub-tree in the larger AST. Expression nodes know
29
- * how to write themselves as SQL (or rather, generate the
30
- * template for SQL required by the query writer)
31
- */
32
- class ExpressionDef extends index_1.MalloyElement {
33
- constructor() {
34
- super(...arguments);
35
- this.legalChildTypes = index_1.FT.anyAtomicT;
36
- }
37
- granular() {
38
- return false;
39
- }
40
- /**
41
- * Some operators want to give the right hand value a chance to
42
- * rewrite itself. This requests a translation for a rewrite,
43
- * or returns undefined if that request should be denied.
44
- * @param fs FieldSpace
45
- * @returns Translated expression or undefined
46
- */
47
- requestExpression(fs) {
48
- return this.getExpression(fs);
49
- }
50
- defaultFieldName() {
51
- return undefined;
52
- }
53
- /**
54
- * Check an expression for type compatibility
55
- * @param _eNode currently unused, will be used to get error location
56
- * @param eVal ...list of expressions that must match legalChildTypes
57
- */
58
- typeCheck(eNode, eVal) {
59
- if (!index_1.FT.in(eVal, this.legalChildTypes)) {
60
- eNode.log(`'${this.elementType}' Can't use type ${index_1.FT.inspect(eVal)}`);
61
- return false;
62
- }
63
- return true;
64
- }
65
- /**
66
- * This is the operation which makes partial comparison and value trees work
67
- * The default implemention merely constructs LEFT OP RIGHT, but specialized
68
- * nodes like alternation trees or or partial comparison can control how
69
- * the appplication gets generated
70
- * @param fs The symbol table
71
- * @param op The operator being applied
72
- * @param expr The "other" (besdies 'this') value
73
- * @returns The translated expression
74
- */
75
- apply(fs, op, left) {
76
- return (0, apply_expr_1.applyBinary)(fs, left, op, this);
77
- }
78
- }
79
- exports.ExpressionDef = ExpressionDef;
80
- class DollarReference extends ExpressionDef {
81
- constructor(refType) {
82
- super();
83
- this.refType = refType;
84
- this.elementType = "$";
85
- }
86
- getExpression(_fs) {
87
- return {
88
- dataType: this.refType,
89
- value: [{ type: "applyVal" }],
90
- aggregate: false,
91
- };
92
- }
93
- }
94
- class ConstantFieldSpace {
95
- constructor() {
96
- this.type = "fieldSpace";
97
- }
98
- structDef() {
99
- throw new Error("ConstantFieldSpace cannot generate a structDef");
100
- }
101
- emptyStructDef() {
102
- throw new Error("ConstantFieldSpace cannot generate a structDef");
103
- }
104
- lookup(_name) {
105
- return {
106
- error: "Only constants allowed in parameter expressions",
107
- found: undefined,
108
- };
109
- }
110
- dialectObj() {
111
- return undefined;
112
- }
113
- whenComplete(step) {
114
- step();
115
- }
116
- }
117
- class ConstantSubExpression extends ExpressionDef {
118
- constructor(expr) {
119
- super({ expr });
120
- this.expr = expr;
121
- this.elementType = "constantExpression";
122
- }
123
- getExpression(_fs) {
124
- return this.constantValue();
125
- }
126
- get constantFs() {
127
- if (!this.cfs) {
128
- this.cfs = new ConstantFieldSpace();
129
- }
130
- return this.cfs;
131
- }
132
- constantValue() {
133
- return this.expr.getExpression(this.constantFs);
134
- }
135
- constantCondition(type) {
136
- const compareAndContrast = new index_1.ExprCompare(new DollarReference(type), "=", this.expr);
137
- const application = compareAndContrast.getExpression(this.constantFs);
138
- return { ...application, value: (0, index_1.compressExpr)(application.value) };
139
- }
140
- apply(fs, op, expr) {
141
- return this.expr.apply(fs, op, expr);
142
- }
143
- requestExpression(fs) {
144
- return this.expr.requestExpression(fs);
145
- }
146
- }
147
- exports.ConstantSubExpression = ConstantSubExpression;
148
- class FieldDeclaration extends index_1.MalloyElement {
149
- constructor(expr, defineName, exprSrc) {
150
- super({ expr });
151
- this.expr = expr;
152
- this.defineName = defineName;
153
- this.exprSrc = exprSrc;
154
- this.elementType = "fieldDeclaration";
155
- }
156
- fieldDef(fs, exprName) {
157
- /*
158
- * In an explore we cannot reference the thing we are defining, you need
159
- * to use rename. In a query, the output space is a new thing, and expressions
160
- * can reference the outer value in order to make a value with the new name,
161
- * and it feels wrong that this is HERE and not somehow in the QueryOperation.
162
- * For now, this stops the stack overflow, and passes all tests, but I think
163
- * a refactor of QueryFieldSpace might someday be the place where this should
164
- * happen.
165
- */
166
- return this.queryFieldDef(new field_space_1.DefSpace(fs, this), exprName);
167
- }
168
- queryFieldDef(exprFS, exprName) {
169
- let exprValue;
170
- try {
171
- exprValue = this.expr.getExpression(exprFS);
172
- }
173
- catch (error) {
174
- this.log(`Cannot define '${exprName}', ${error.message}`);
175
- return {
176
- name: `error_defining_${exprName}`,
177
- type: "string",
178
- };
179
- }
180
- const compressValue = (0, index_1.compressExpr)(exprValue.value);
181
- const retType = exprValue.dataType;
182
- if ((0, malloy_types_1.isAtomicFieldType)(retType)) {
183
- const template = {
184
- name: exprName,
185
- type: retType,
186
- location: this.location,
187
- };
188
- if (compressValue.length > 0) {
189
- template.e = compressValue;
190
- }
191
- if (exprValue.aggregate) {
192
- template.aggregate = true;
193
- }
194
- if (this.exprSrc) {
195
- template.code = this.exprSrc;
196
- }
197
- // TODO this should work for dates too
198
- if ((0, index_1.isGranularResult)(exprValue) && template.type === "timestamp") {
199
- template.timeframe = exprValue.timeframe;
200
- }
201
- return template;
202
- }
203
- const circularDef = exprFS instanceof field_space_1.DefSpace && exprFS.foundCircle;
204
- if (!circularDef) {
205
- if (exprValue.dataType == "unknown") {
206
- this.log(`Cannot define '${exprName}', value has unknown type`);
207
- }
208
- else {
209
- const badType = index_1.FT.inspect(exprValue);
210
- this.log(`Cannot define '${exprName}', unexpected type: ${badType}`);
211
- }
212
- }
213
- return {
214
- name: `error_defining_${exprName}`,
215
- type: "string",
216
- };
217
- }
218
- }
219
- exports.FieldDeclaration = FieldDeclaration;
220
- class TypeMistmatch extends Error {
221
- }
222
- exports.TypeMistmatch = TypeMistmatch;
223
- class ExprString extends ExpressionDef {
224
- constructor(value) {
225
- super();
226
- this.value = value;
227
- this.elementType = "string literal";
228
- }
229
- getExpression(_fs) {
230
- return { ...index_1.FT.stringT, value: [this.value] };
231
- }
232
- }
233
- exports.ExprString = ExprString;
234
- class ExprNumber extends ExpressionDef {
235
- constructor(n) {
236
- super();
237
- this.n = n;
238
- this.elementType = "numeric literal";
239
- }
240
- getExpression(_fs) {
241
- return this.constantExpression();
242
- }
243
- constantExpression() {
244
- return { ...index_1.FT.numberT, value: [this.n] };
245
- }
246
- }
247
- exports.ExprNumber = ExprNumber;
248
- class ExprRegEx extends ExpressionDef {
249
- constructor(regex) {
250
- super();
251
- this.regex = regex;
252
- this.elementType = "regular expression literal";
253
- }
254
- getExpression() {
255
- return {
256
- dataType: "regular expression",
257
- aggregate: false,
258
- value: [`r'${this.regex}'`],
259
- };
260
- }
261
- }
262
- exports.ExprRegEx = ExprRegEx;
263
- class ExprTime extends ExpressionDef {
264
- constructor(timeType, value, aggregate = false) {
265
- super();
266
- this.elementType = "timestampOrDate";
267
- this.elementType = timeType;
268
- this.translationValue = {
269
- dataType: timeType,
270
- aggregate: aggregate,
271
- value: typeof value === "string" ? [value] : value,
272
- };
273
- }
274
- getExpression(_fs) {
275
- return this.translationValue;
276
- }
277
- static fromValue(timeType, expr) {
278
- let value = expr.value;
279
- if (timeType != expr.dataType) {
280
- const toTs = {
281
- type: "dialect",
282
- function: "cast",
283
- safe: false,
284
- dstType: timeType,
285
- expr: expr.value,
286
- };
287
- if ((0, malloy_types_1.isTimeFieldType)(expr.dataType)) {
288
- toTs.srcType = expr.dataType;
289
- }
290
- value = (0, index_1.compressExpr)([toTs]);
291
- }
292
- return new ExprTime(timeType, value, expr.aggregate);
293
- }
294
- }
295
- exports.ExprTime = ExprTime;
296
- class Unary extends ExpressionDef {
297
- constructor(expr) {
298
- super({ expr });
299
- this.expr = expr;
300
- }
301
- }
302
- class ExprNot extends Unary {
303
- constructor(expr) {
304
- super(expr);
305
- this.elementType = "not";
306
- this.legalChildTypes = [index_1.FT.boolT, index_1.FT.nullT];
307
- }
308
- getExpression(fs) {
309
- const notThis = this.expr.getExpression(fs);
310
- if (this.typeCheck(this.expr, notThis)) {
311
- return {
312
- ...notThis,
313
- dataType: "boolean",
314
- value: (0, apply_expr_1.nullsafeNot)(notThis.value),
315
- };
316
- }
317
- return (0, index_1.errorFor)("not requires boolean");
318
- }
319
- }
320
- exports.ExprNot = ExprNot;
321
- class Boolean extends ExpressionDef {
322
- constructor(value) {
323
- super();
324
- this.value = value;
325
- this.elementType = "boolean literal";
326
- }
327
- getExpression() {
328
- return { ...index_1.FT.boolT, value: [this.value] };
329
- }
330
- }
331
- exports.Boolean = Boolean;
332
- class BinaryBoolean extends ExpressionDef {
333
- constructor(left, op, right) {
334
- super({ left, right });
335
- this.left = left;
336
- this.op = op;
337
- this.right = right;
338
- this.elementType = "abstract boolean binary";
339
- this.legalChildTypes = [index_1.FT.boolT];
340
- }
341
- getExpression(fs) {
342
- const left = this.left.getExpression(fs);
343
- const right = this.right.getExpression(fs);
344
- if (this.typeCheck(this.left, left) && this.typeCheck(this.right, right)) {
345
- return {
346
- dataType: "boolean",
347
- aggregate: left.aggregate || right.aggregate,
348
- value: (0, index_1.compose)(left.value, this.op, right.value),
349
- };
350
- }
351
- return (0, index_1.errorFor)("logial required boolean");
352
- }
353
- }
354
- exports.BinaryBoolean = BinaryBoolean;
355
- class ExprLogicalOp extends BinaryBoolean {
356
- constructor() {
357
- super(...arguments);
358
- this.elementType = "logical operator";
359
- this.legalChildTypes = [index_1.FT.boolT, { ...index_1.FT.boolT, aggregate: true }];
360
- }
361
- }
362
- exports.ExprLogicalOp = ExprLogicalOp;
363
- class ExprIdReference extends ExpressionDef {
364
- constructor(fieldReference) {
365
- super();
366
- this.fieldReference = fieldReference;
367
- this.elementType = "ExpressionIdReference";
368
- this.has({ fieldPath: fieldReference });
369
- }
370
- get refString() {
371
- return this.fieldReference.refString;
372
- }
373
- getExpression(fs) {
374
- const def = this.fieldReference.getField(fs);
375
- if (def.found) {
376
- // TODO if type is a query or a struct this should fail nicely
377
- const typeMixin = def.found.type();
378
- const dataType = typeMixin.type;
379
- const aggregate = !!typeMixin.aggregate;
380
- const value = [{ type: def.found.refType, path: this.refString }];
381
- return { dataType, aggregate, value };
382
- }
383
- this.log(def.error);
384
- return (0, index_1.errorFor)(def.error);
385
- }
386
- apply(fs, op, expr) {
387
- const entry = this.fieldReference.getField(fs).found;
388
- if (entry instanceof space_field_1.SpaceParam) {
389
- const cParam = entry.parameter();
390
- if ((0, malloy_types_1.isConditionParameter)(cParam)) {
391
- const lval = expr.getExpression(fs);
392
- return {
393
- dataType: "boolean",
394
- aggregate: lval.aggregate,
395
- value: [
396
- {
397
- type: "apply",
398
- value: lval.value,
399
- to: [{ type: "parameter", path: this.refString }],
400
- },
401
- ],
402
- };
403
- }
404
- }
405
- return super.apply(fs, op, expr);
406
- }
407
- }
408
- exports.ExprIdReference = ExprIdReference;
409
- class ExprNULL extends ExpressionDef {
410
- constructor() {
411
- super(...arguments);
412
- this.elementType = "NULL";
413
- }
414
- getExpression() {
415
- return {
416
- dataType: "null",
417
- value: ["NULL"],
418
- aggregate: false,
419
- };
420
- }
421
- }
422
- exports.ExprNULL = ExprNULL;
423
- class ExprParens extends ExpressionDef {
424
- constructor(expr) {
425
- super({ expr });
426
- this.expr = expr;
427
- this.elementType = "(expression)";
428
- }
429
- apply(fs, op, expr) {
430
- return this.expr.apply(fs, op, expr);
431
- }
432
- requestExpression(fs) {
433
- return this.expr.requestExpression(fs);
434
- }
435
- getExpression(fs) {
436
- const subExpr = this.expr.getExpression(fs);
437
- return { ...subExpr, value: ["(", ...subExpr.value, ")"] };
438
- }
439
- }
440
- exports.ExprParens = ExprParens;
441
- class ExprMinus extends ExpressionDef {
442
- constructor(expr) {
443
- super({ expr });
444
- this.expr = expr;
445
- this.elementType = "unary minus";
446
- this.legalChildTypes = [index_1.FT.numberT];
447
- }
448
- getExpression(fs) {
449
- const expr = this.expr.getExpression(fs);
450
- if (this.typeCheck(this.expr, expr)) {
451
- if (expr.value.length > 1) {
452
- return { ...expr, value: ["-(", ...expr.value, ")"] };
453
- }
454
- return { ...expr, value: ["-", ...expr.value] };
455
- }
456
- return (0, index_1.errorFor)("negate requires number");
457
- }
458
- }
459
- exports.ExprMinus = ExprMinus;
460
- class BinaryNumeric extends ExpressionDef {
461
- constructor(left, op, right) {
462
- super({ left, right });
463
- this.left = left;
464
- this.op = op;
465
- this.right = right;
466
- this.elementType = "numeric binary abstract";
467
- this.legalChildTypes = [index_1.FT.numberT];
468
- }
469
- getExpression(fs) {
470
- return this.right.apply(fs, this.op, this.left);
471
- }
472
- }
473
- exports.BinaryNumeric = BinaryNumeric;
474
- class ExprAddSub extends BinaryNumeric {
475
- constructor() {
476
- super(...arguments);
477
- this.elementType = "+-";
478
- }
479
- }
480
- exports.ExprAddSub = ExprAddSub;
481
- class ExprMulDiv extends BinaryNumeric {
482
- constructor() {
483
- super(...arguments);
484
- this.elementType = "*/";
485
- }
486
- }
487
- exports.ExprMulDiv = ExprMulDiv;
488
- class ExprAlternationTree extends BinaryBoolean {
489
- constructor(left, op, right) {
490
- super(left, op, right);
491
- this.elementType = "alternation";
492
- this.elementType = `${op}alternation${op}`;
493
- }
494
- apply(fs, applyOp, expr) {
495
- const choice1 = this.left.apply(fs, applyOp, expr);
496
- const choice2 = this.right.apply(fs, applyOp, expr);
497
- return {
498
- dataType: "boolean",
499
- aggregate: choice1.aggregate || choice2.aggregate,
500
- value: (0, index_1.compose)(choice1.value, this.op === "&" ? "and" : "or", choice2.value),
501
- };
502
- }
503
- requestExpression(_fs) {
504
- return undefined;
505
- }
506
- getExpression(_fs) {
507
- this.log(`Alternation tree has no value`);
508
- return (0, index_1.errorFor)("no value from alternation tree");
509
- }
510
- }
511
- exports.ExprAlternationTree = ExprAlternationTree;
512
- class ExprAggregateFunction extends ExpressionDef {
513
- constructor(func, expr) {
514
- super();
515
- this.func = func;
516
- this.legalChildTypes = [index_1.FT.numberT];
517
- this.elementType = func;
518
- if (expr) {
519
- this.expr = expr;
520
- this.has({ expr });
521
- }
522
- }
523
- returns(_forExpression) {
524
- return "number";
525
- }
526
- getExpression(fs) {
527
- var _a, _b;
528
- let exprVal = (_a = this.expr) === null || _a === void 0 ? void 0 : _a.getExpression(fs);
529
- let structPath = (_b = this.source) === null || _b === void 0 ? void 0 : _b.refString;
530
- if (this.source) {
531
- const sourceFoot = this.source.getField(fs).found;
532
- if (sourceFoot) {
533
- const footType = sourceFoot.type();
534
- if ((0, malloy_types_1.isAtomicFieldType)(footType.type)) {
535
- exprVal = {
536
- dataType: footType.type,
537
- aggregate: !!footType.aggregate,
538
- value: [{ type: "field", path: this.source.refString }],
539
- };
540
- structPath = this.source.sourceString;
541
- }
542
- else {
543
- if (!(sourceFoot instanceof space_field_1.StructSpaceField)) {
544
- this.log(`Aggregate source cannot be a ${footType.type}`);
545
- return (0, index_1.errorFor)(`Aggregate source cannot be a ${footType.type}`);
546
- }
547
- }
548
- }
549
- else {
550
- this.log(`Reference to undefined value ${this.source.refString}`);
551
- return (0, index_1.errorFor)(`Reference to undefined value ${this.source.refString}`);
552
- }
553
- }
554
- if (exprVal === undefined) {
555
- this.log("Missing expression for aggregate function");
556
- return (0, index_1.errorFor)("agggregate without expression");
557
- }
558
- if (this.typeCheck(this.expr || this, { ...exprVal, aggregate: false })) {
559
- const f = {
560
- type: "aggregate",
561
- function: this.func,
562
- e: exprVal.value,
563
- };
564
- if (structPath) {
565
- f.structPath = structPath;
566
- }
567
- return {
568
- dataType: this.returns(exprVal),
569
- aggregate: true,
570
- value: [f],
571
- };
572
- }
573
- return (0, index_1.errorFor)("aggregate type check");
574
- }
575
- }
576
- class ExprMin extends ExprAggregateFunction {
577
- constructor(expr) {
578
- super("min", expr);
579
- this.legalChildTypes = [index_1.FT.numberT, index_1.FT.stringT, index_1.FT.dateT, index_1.FT.timestampT];
580
- }
581
- returns(forExpression) {
582
- return forExpression.dataType;
583
- }
584
- }
585
- exports.ExprMin = ExprMin;
586
- class ExprMax extends ExprAggregateFunction {
587
- constructor(expr) {
588
- super("max", expr);
589
- this.legalChildTypes = [index_1.FT.numberT, index_1.FT.stringT, index_1.FT.dateT, index_1.FT.timestampT];
590
- }
591
- returns(forExpression) {
592
- return forExpression.dataType;
593
- }
594
- }
595
- exports.ExprMax = ExprMax;
596
- class ExprCountDistinct extends ExprAggregateFunction {
597
- constructor(expr) {
598
- super("count_distinct", expr);
599
- this.legalChildTypes = [index_1.FT.numberT, index_1.FT.stringT, index_1.FT.dateT, index_1.FT.timestampT];
600
- }
601
- }
602
- exports.ExprCountDistinct = ExprCountDistinct;
603
- class ExprAsymmetric extends ExprAggregateFunction {
604
- constructor(func, expr, source) {
605
- super(func, expr);
606
- this.func = func;
607
- this.expr = expr;
608
- this.source = source;
609
- this.has({ source });
610
- }
611
- defaultFieldName() {
612
- if (this.source && this.expr === undefined) {
613
- const tag = this.source.nameString;
614
- switch (this.func) {
615
- case "sum":
616
- return `total_${tag}`;
617
- case "avg":
618
- return `avg_${tag}`;
619
- }
620
- }
621
- return undefined;
622
- }
623
- }
624
- class ExprCount extends ExprAggregateFunction {
625
- constructor(source) {
626
- super("count");
627
- this.source = source;
628
- this.elementType = "count";
629
- this.has({ source });
630
- }
631
- defaultFieldName() {
632
- if (this.source) {
633
- return "count_" + this.source.nameString;
634
- }
635
- return undefined;
636
- }
637
- getExpression(_fs) {
638
- const ret = {
639
- type: "aggregate",
640
- function: "count",
641
- e: [],
642
- };
643
- if (this.source) {
644
- ret.structPath = this.source.refString;
645
- }
646
- return {
647
- dataType: "number",
648
- aggregate: true,
649
- value: [ret],
650
- };
651
- }
652
- }
653
- exports.ExprCount = ExprCount;
654
- class ExprAvg extends ExprAsymmetric {
655
- constructor(expr, source) {
656
- super("avg", expr, source);
657
- this.has({ source });
658
- }
659
- }
660
- exports.ExprAvg = ExprAvg;
661
- class ExprSum extends ExprAsymmetric {
662
- constructor(expr, source) {
663
- super("sum", expr, source);
664
- this.has({ source });
665
- }
666
- }
667
- exports.ExprSum = ExprSum;
668
- class ExprUngroup extends ExpressionDef {
669
- constructor(control, expr, fields) {
670
- super({ expr, fields });
671
- this.control = control;
672
- this.expr = expr;
673
- this.fields = fields;
674
- this.legalChildTypes = index_1.FT.anyAtomicT;
675
- this.elementType = "ungroup";
676
- }
677
- returns(_forExpression) {
678
- return "number";
679
- }
680
- getExpression(fs) {
681
- const exprVal = this.expr.getExpression(fs);
682
- if (!exprVal.aggregate) {
683
- this.expr.log(`${this.control}() expression must be an aggregate`);
684
- return (0, index_1.errorFor)("ungrouped scalar");
685
- }
686
- const ungroup = { type: this.control, e: exprVal.value };
687
- if (this.typeCheck(this.expr, { ...exprVal, aggregate: false })) {
688
- if (this.fields.length > 0) {
689
- let qs = fs;
690
- if (fs instanceof field_space_1.DefSpace) {
691
- qs = fs.realFS;
692
- }
693
- if (!(qs instanceof field_space_1.QuerySpace)) {
694
- this.log(`${this.control}() must be in a query -- weird internal error`);
695
- return (0, index_1.errorFor)("ungroup query check");
696
- }
697
- const output = qs.result;
698
- const dstFields = [];
699
- const isExclude = this.control == "exclude";
700
- for (const mustBeInOutput of this.fields) {
701
- output.whenComplete(() => {
702
- output.checkUngroup(mustBeInOutput, isExclude);
703
- });
704
- dstFields.push(mustBeInOutput.refString);
705
- }
706
- ungroup.fields = dstFields;
707
- }
708
- return {
709
- dataType: this.returns(exprVal),
710
- aggregate: true,
711
- value: [ungroup],
712
- };
713
- }
714
- this.log(`${this.control}() incompatible type`);
715
- return (0, index_1.errorFor)("ungrouped type check");
716
- }
717
- }
718
- exports.ExprUngroup = ExprUngroup;
719
- class WhenClause extends ExpressionDef {
720
- constructor(whenThis, thenThis) {
721
- super({ whenThis, thenThis });
722
- this.whenThis = whenThis;
723
- this.thenThis = thenThis;
724
- this.elementType = "when clause";
725
- }
726
- getExpression(_fs) {
727
- throw new Error("expression did something unxpected with 'WHEN'");
728
- }
729
- }
730
- exports.WhenClause = WhenClause;
731
- class ExprCase extends ExpressionDef {
732
- constructor(when, elseClause) {
733
- super({ when });
734
- this.when = when;
735
- this.elseClause = elseClause;
736
- this.elementType = "case statement";
737
- this.has({ elseClause });
738
- }
739
- getExpression(fs) {
740
- let retType;
741
- let aggregate = false;
742
- const caseExpr = ["CASE "];
743
- for (const clause of this.when) {
744
- const whenExpr = clause.whenThis.getExpression(fs);
745
- const thenExpr = clause.thenThis.getExpression(fs);
746
- aggregate || (aggregate = whenExpr.aggregate || thenExpr.aggregate);
747
- if (thenExpr.dataType !== "null") {
748
- if (retType && !index_1.FT.typeEq(retType, thenExpr)) {
749
- this.log(`Mismatched THEN clause types, ${index_1.FT.inspect(retType, thenExpr)}`);
750
- return (0, index_1.errorFor)("then typecheck");
751
- }
752
- else {
753
- retType = thenExpr;
754
- }
755
- }
756
- caseExpr.push("WHEN ", ...whenExpr.value, " THEN ", ...thenExpr.value);
757
- }
758
- if (this.elseClause) {
759
- const elseExpr = this.elseClause.getExpression(fs);
760
- aggregate || (aggregate = elseExpr.aggregate);
761
- caseExpr.push(" ELSE ", ...elseExpr.value);
762
- if (elseExpr.dataType !== "null") {
763
- if (retType && !index_1.FT.typeEq(retType, elseExpr)) {
764
- this.log(`Mismatched ELSE clause type, ${index_1.FT.inspect(retType, elseExpr)}`);
765
- return (0, index_1.errorFor)("else typecheck");
766
- }
767
- else {
768
- retType = elseExpr;
769
- }
770
- }
771
- }
772
- if (retType === undefined) {
773
- this.log("case statement type not computable");
774
- return (0, index_1.errorFor)("typeless case");
775
- }
776
- caseExpr.push(" END");
777
- return {
778
- dataType: retType.dataType,
779
- aggregate: aggregate,
780
- value: caseExpr,
781
- };
782
- }
783
- }
784
- exports.ExprCase = ExprCase;
785
- class ExprFilter extends ExpressionDef {
786
- constructor(expr, filter) {
787
- super({ expr, filter });
788
- this.expr = expr;
789
- this.filter = filter;
790
- this.elementType = "filtered expression";
791
- this.legalChildTypes = index_1.FT.anyAtomicT;
792
- }
793
- getExpression(fs) {
794
- const testList = this.filter.getFilterList(fs);
795
- const resultExpr = this.expr.getExpression(fs);
796
- for (const cond of testList) {
797
- if (cond.aggregate) {
798
- this.filter.log("Cannot filter a field with an aggregate computation");
799
- return (0, index_1.errorFor)("no filter on aggregate");
800
- }
801
- }
802
- if (!resultExpr.aggregate) {
803
- // TODO could log a warning, but I have a problem with the
804
- // idea of warnings, so for now ...
805
- return resultExpr;
806
- }
807
- if (this.typeCheck(this.expr, { ...resultExpr, aggregate: false })) {
808
- return {
809
- ...resultExpr,
810
- value: [
811
- {
812
- type: "filterExpression",
813
- e: resultExpr.value,
814
- filterList: testList,
815
- },
816
- ],
817
- };
818
- }
819
- this.expr.log(`Cannot filter '${resultExpr.dataType}' data`);
820
- return (0, index_1.errorFor)("cannot filter type");
821
- }
822
- }
823
- exports.ExprFilter = ExprFilter;
824
- function isCastType(t) {
825
- return ["string", "number", "boolean", "date", "timestamp"].includes(t);
826
- }
827
- exports.isCastType = isCastType;
828
- class ExprCast extends ExpressionDef {
829
- constructor(expr, castType, safe = false) {
830
- super({ expr });
831
- this.expr = expr;
832
- this.castType = castType;
833
- this.safe = safe;
834
- this.elementType = "cast";
835
- }
836
- getExpression(fs) {
837
- const expr = this.expr.getExpression(fs);
838
- return {
839
- dataType: this.castType,
840
- aggregate: expr.aggregate,
841
- value: (0, index_1.compressExpr)((0, time_utils_1.castTo)(this.castType, expr.value, this.safe)),
842
- };
843
- }
844
- }
845
- exports.ExprCast = ExprCast;
846
- class TopBy extends index_1.MalloyElement {
847
- constructor(by) {
848
- super();
849
- this.by = by;
850
- this.elementType = "topBy";
851
- if (by instanceof ExpressionDef) {
852
- this.has({ by });
853
- }
854
- }
855
- getBy(fs) {
856
- if (this.by instanceof ExpressionDef) {
857
- const byExpr = this.by.getExpression(fs);
858
- if (!byExpr.aggregate) {
859
- this.log("top by expression must be an aggregate");
860
- }
861
- return { by: "expression", e: (0, index_1.compressExpr)(byExpr.value) };
862
- }
863
- return { by: "name", name: this.by };
864
- }
865
- }
866
- exports.TopBy = TopBy;
867
- class Range extends ExpressionDef {
868
- constructor(first, last) {
869
- super({ first, last });
870
- this.first = first;
871
- this.last = last;
872
- this.elementType = "range";
873
- }
874
- apply(fs, op, expr) {
875
- switch (op) {
876
- case "=":
877
- case "!=": {
878
- const op1 = op === "=" ? ">=" : "<";
879
- const op2 = op === "=" ? "and" : "or";
880
- const op3 = op === "=" ? "<" : ">=";
881
- const fromValue = this.first.apply(fs, op1, expr);
882
- const toValue = this.last.apply(fs, op3, expr);
883
- return {
884
- dataType: "boolean",
885
- aggregate: fromValue.aggregate || toValue.aggregate,
886
- value: (0, index_1.compose)(fromValue.value, op2, toValue.value),
887
- };
888
- }
889
- /**
890
- * This is a little surprising, but is actually how you comapre a
891
- * value to a range ...
892
- *
893
- * val > begin to end val >= end
894
- * val >= begin to end val >= begin
895
- * val < begin to end val < begin
896
- * val <= begin to end val < end
897
- */
898
- case ">":
899
- return this.last.apply(fs, ">=", expr);
900
- case ">=":
901
- return this.first.apply(fs, ">=", expr);
902
- case "<":
903
- return this.first.apply(fs, "<", expr);
904
- case "<=":
905
- return this.last.apply(fs, "<", expr);
906
- }
907
- throw new Error("mysterious error in range computation");
908
- }
909
- requestExpression(_fs) {
910
- return undefined;
911
- }
912
- getExpression(_fs) {
913
- return (0, index_1.errorFor)("a range is not a value");
914
- }
915
- }
916
- exports.Range = Range;
917
- class PickWhen extends index_1.MalloyElement {
918
- constructor(pick, when) {
919
- super({ when });
920
- this.pick = pick;
921
- this.when = when;
922
- this.elementType = "pickWhen";
923
- this.has({ pick });
924
- }
925
- }
926
- exports.PickWhen = PickWhen;
927
- class Pick extends ExpressionDef {
928
- constructor(choices, elsePick) {
929
- super({ choices });
930
- this.choices = choices;
931
- this.elsePick = elsePick;
932
- this.elementType = "pick";
933
- this.has({ elsePick });
934
- }
935
- requestExpression(fs) {
936
- // pick statements are sometimes partials which must be applied
937
- // and sometimes have a value.
938
- if (this.elsePick === undefined) {
939
- return undefined;
940
- }
941
- for (const c of this.choices) {
942
- if (c.pick == undefined) {
943
- return undefined;
944
- }
945
- const whenResp = c.when.requestExpression(fs);
946
- if (whenResp == undefined || whenResp.dataType != "boolean") {
947
- // If when is not a boolean, we'll treat it like a partial compare
948
- return undefined;
949
- }
950
- }
951
- return this.getExpression(fs);
952
- }
953
- apply(fs, op, expr) {
954
- const caseValue = ["CASE"];
955
- let returnType;
956
- let anyAggregate = false;
957
- for (const choice of this.choices) {
958
- const whenExpr = choice.when.apply(fs, "=", expr);
959
- const thenExpr = choice.pick
960
- ? choice.pick.getExpression(fs)
961
- : expr.getExpression(fs);
962
- anyAggregate || (anyAggregate = whenExpr.aggregate || thenExpr.aggregate);
963
- if (returnType) {
964
- if (!index_1.FT.typeEq(returnType, thenExpr, true)) {
965
- const whenType = index_1.FT.inspect(thenExpr);
966
- this.log(`pick type '${whenType}', expected '${returnType.dataType}'`);
967
- return (0, index_1.errorFor)("pick when type");
968
- }
969
- }
970
- else {
971
- returnType = thenExpr;
972
- }
973
- caseValue.push(" WHEN ", ...whenExpr.value, " THEN ", ...thenExpr.value);
974
- }
975
- const elsePart = this.elsePick || expr;
976
- const elseVal = elsePart.getExpression(fs);
977
- returnType || (returnType = elseVal);
978
- if (!index_1.FT.typeEq(returnType, elseVal, true)) {
979
- const errSrc = this.elsePick ? "else" : "pick default";
980
- this.log(`${errSrc} type '${index_1.FT.inspect(elseVal)}', expected '${returnType.dataType}'`);
981
- return (0, index_1.errorFor)("pick else type");
982
- }
983
- return {
984
- dataType: returnType.dataType,
985
- aggregate: anyAggregate || elseVal.aggregate,
986
- value: (0, index_1.compressExpr)([...caseValue, " ELSE ", ...elseVal.value, " END"]),
987
- };
988
- }
989
- getExpression(fs) {
990
- if (this.elsePick === undefined) {
991
- this.log("pick incomplete, missing 'else'");
992
- return (0, index_1.errorFor)("no value for partial pick");
993
- }
994
- const choiceValues = [];
995
- for (const c of this.choices) {
996
- if (c.pick === undefined) {
997
- this.log("pick with no value can only be used with apply");
998
- return (0, index_1.errorFor)("no value for partial pick");
999
- }
1000
- const pickWhen = c.when.requestExpression(fs);
1001
- if (pickWhen === undefined) {
1002
- this.log("pick with partial when can only be used with apply");
1003
- return (0, index_1.errorFor)("partial when");
1004
- }
1005
- choiceValues.push({
1006
- pick: c.pick.getExpression(fs),
1007
- when: c.when.getExpression(fs),
1008
- });
1009
- }
1010
- const returnType = choiceValues[0].pick;
1011
- const caseValue = ["CASE"];
1012
- let anyAggregate = returnType.aggregate;
1013
- for (const aChoice of choiceValues) {
1014
- if (!index_1.FT.typeEq(aChoice.when, index_1.FT.boolT)) {
1015
- this.log(`when expression must be boolean, not '${index_1.FT.inspect(aChoice.when)}`);
1016
- return (0, index_1.errorFor)("pick when type");
1017
- }
1018
- if (!index_1.FT.typeEq(returnType, aChoice.pick, true)) {
1019
- const whenType = index_1.FT.inspect(aChoice.pick);
1020
- this.log(`pick type '${whenType}', expected '${returnType.dataType}'`);
1021
- return (0, index_1.errorFor)("pick value type");
1022
- }
1023
- anyAggregate || (anyAggregate = aChoice.pick.aggregate || aChoice.when.aggregate);
1024
- caseValue.push(" WHEN ", ...aChoice.when.value, " THEN ", ...aChoice.pick.value);
1025
- }
1026
- const defVal = this.elsePick.getExpression(fs);
1027
- anyAggregate || (anyAggregate = defVal.aggregate);
1028
- if (!index_1.FT.typeEq(returnType, defVal, true)) {
1029
- this.elsePick.log(`else type '${index_1.FT.inspect(defVal)}', expected '${returnType.dataType}'`);
1030
- return (0, index_1.errorFor)("pick value type mismatch");
1031
- }
1032
- caseValue.push(" ELSE ", ...defVal.value, " END");
1033
- return {
1034
- dataType: returnType.dataType,
1035
- aggregate: !!anyAggregate,
1036
- value: (0, index_1.compressExpr)(caseValue),
1037
- };
1038
- }
1039
- }
1040
- exports.Pick = Pick;
1041
- //# sourceMappingURL=ast-expr.js.map