@malloydata/malloy 0.0.22-dev230117223957 → 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.
@@ -1,16 +1,3 @@
1
1
  import { Expr } from "../../model/malloy_types";
2
- import { FieldSpace } from "../field-space";
3
- import { ExprValue, ExpressionDef, Equality } from "./index";
4
- /**
5
- * All of the magic of malloy expressions eventually flows to here,
6
- * where an operator is applied to two values. Depending on the
7
- * operator and value types this may involve transformations of
8
- * the values or even the operator.
9
- * @param fs FieldSpace for the symbols
10
- * @param left Left value
11
- * @param op The operator
12
- * @param right Right Value
13
- * @returns ExprValue of the expression
14
- */
15
- export declare function applyBinary(fs: FieldSpace, left: ExpressionDef, op: string, right: ExpressionDef): ExprValue;
2
+ import { Equality } from "./ast-types";
16
3
  export declare function nullsafeNot(expr: Expr, op?: Equality): Expr;
@@ -22,129 +22,8 @@
22
22
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.nullsafeNot = exports.applyBinary = void 0;
25
+ exports.nullsafeNot = void 0;
26
26
  const malloy_types_1 = require("../../model/malloy_types");
27
- const index_1 = require("./index");
28
- /**
29
- * All of the magic of malloy expressions eventually flows to here,
30
- * where an operator is applied to two values. Depending on the
31
- * operator and value types this may involve transformations of
32
- * the values or even the operator.
33
- * @param fs FieldSpace for the symbols
34
- * @param left Left value
35
- * @param op The operator
36
- * @param right Right Value
37
- * @returns ExprValue of the expression
38
- */
39
- function applyBinary(fs, left, op, right) {
40
- if ((0, index_1.isEquality)(op)) {
41
- return equality(fs, left, op, right);
42
- }
43
- if ((0, index_1.isComparison)(op)) {
44
- return compare(fs, left, op, right);
45
- }
46
- if (oneOf(op, "+", "-")) {
47
- return delta(fs, left, op, right);
48
- }
49
- if (oneOf(op, "*", "%")) {
50
- return numeric(fs, left, op, right);
51
- }
52
- if (oneOf(op, "/")) {
53
- const num = left.getExpression(fs);
54
- const denom = right.getExpression(fs);
55
- if (num.dataType != "number") {
56
- left.log("Numerator for division must be a number");
57
- }
58
- else if (denom.dataType != "number") {
59
- right.log("Denominator for division must be a number");
60
- }
61
- else {
62
- const div = {
63
- type: "dialect",
64
- function: "div",
65
- numerator: num.value,
66
- denominator: denom.value,
67
- };
68
- return {
69
- dataType: "number",
70
- expressionType: (0, malloy_types_1.maxExpressionType)(num.expressionType, denom.expressionType),
71
- value: [div],
72
- };
73
- }
74
- return (0, index_1.errorFor)("divide type mismatch");
75
- }
76
- left.log(`Canot use ${op} operator here`);
77
- return (0, index_1.errorFor)("applybinary bad operator");
78
- }
79
- exports.applyBinary = applyBinary;
80
- function oneOf(op, ...operators) {
81
- return operators.includes(op);
82
- }
83
- function allAre(oneType, ...values) {
84
- for (const v of values) {
85
- if (v.dataType !== oneType) {
86
- return false;
87
- }
88
- }
89
- return true;
90
- }
91
- function regexEqual(left, right) {
92
- if (left.dataType === "string") {
93
- if (right.dataType === "regular expression") {
94
- return [
95
- {
96
- type: "dialect",
97
- function: "regexpMatch",
98
- expr: left.value,
99
- regexp: right.value[0].replace(/^r'/, "'"),
100
- },
101
- ];
102
- }
103
- }
104
- else if (right.dataType === "string") {
105
- if (left.dataType === "regular expression") {
106
- return [
107
- {
108
- type: "dialect",
109
- function: "regexpMatch",
110
- expr: right.value,
111
- regexp: left.value[0].replace(/^r'/, "'"),
112
- },
113
- ];
114
- }
115
- }
116
- return undefined;
117
- }
118
- function nullCompare(left, op, right) {
119
- const not = op === "!=" || op === "!~";
120
- if (left.dataType === "null" || right.dataType === "null") {
121
- const maybeNot = not ? " NOT" : "";
122
- if (left.dataType !== "null") {
123
- return [...left.value, ` IS${maybeNot} NULL`];
124
- }
125
- if (right.dataType !== "null") {
126
- return [...right.value, `IS${maybeNot} NULL`];
127
- }
128
- return [not ? "false" : "true"];
129
- }
130
- return undefined;
131
- }
132
- function timeCompare(lhs, op, rhs) {
133
- if ((0, malloy_types_1.isTimeFieldType)(lhs.dataType) && (0, malloy_types_1.isTimeFieldType)(rhs.dataType)) {
134
- if (lhs.dataType !== rhs.dataType) {
135
- let lval = lhs.value;
136
- let rval = rhs.value;
137
- if (lhs.dataType === "timestamp") {
138
- lval = (0, index_1.castTimestampToDate)(lval);
139
- }
140
- else {
141
- rval = (0, index_1.castTimestampToDate)(rval);
142
- }
143
- return (0, index_1.compose)(lval, op, rval);
144
- }
145
- }
146
- return undefined;
147
- }
148
27
  function nullsafeNot(expr, op) {
149
28
  if (op === undefined || op === "!=" || op === "!~") {
150
29
  return (0, malloy_types_1.mkExpr) `COALESCE(NOT(${expr}),FALSE)`;
@@ -152,90 +31,4 @@ function nullsafeNot(expr, op) {
152
31
  return expr;
153
32
  }
154
33
  exports.nullsafeNot = nullsafeNot;
155
- function equality(fs, left, op, right) {
156
- const lhs = left.getExpression(fs);
157
- const rhs = right.getExpression(fs);
158
- let value = timeCompare(lhs, op, rhs) || (0, index_1.compose)(lhs.value, op, rhs.value);
159
- if (lhs.dataType != "unknown" && rhs.dataType != "unknown") {
160
- switch (op) {
161
- case "~":
162
- case "!~": {
163
- if (lhs.dataType === "string" && rhs.dataType === "string") {
164
- value = (0, index_1.compose)(lhs.value, "LIKE", rhs.value);
165
- }
166
- else {
167
- const regexCmp = regexEqual(lhs, rhs);
168
- if (regexCmp === undefined) {
169
- throw new index_1.TypeMistmatch("Incompatible types for match('~') operator");
170
- }
171
- value = regexCmp;
172
- }
173
- value = nullsafeNot(value, op);
174
- break;
175
- }
176
- case "=":
177
- case "!=": {
178
- const nullCmp = nullCompare(lhs, op, rhs);
179
- if (nullCmp) {
180
- value = nullCmp;
181
- }
182
- else {
183
- value = nullsafeNot(regexEqual(lhs, rhs) || (0, index_1.compose)(lhs.value, "=", rhs.value), op);
184
- }
185
- break;
186
- }
187
- }
188
- }
189
- return {
190
- dataType: "boolean",
191
- expressionType: (0, malloy_types_1.maxExpressionType)(lhs.expressionType, rhs.expressionType),
192
- value,
193
- };
194
- }
195
- function compare(fs, left, op, right) {
196
- const lhs = left.getExpression(fs);
197
- const rhs = right.getExpression(fs);
198
- const expressionType = (0, malloy_types_1.maxExpressionType)(lhs.expressionType, rhs.expressionType);
199
- const value = timeCompare(lhs, op, rhs) || (0, index_1.compose)(lhs.value, op, rhs.value);
200
- return {
201
- dataType: "boolean",
202
- expressionType,
203
- value: value,
204
- };
205
- }
206
- function numeric(fs, left, op, right) {
207
- const lhs = left.getExpression(fs);
208
- const rhs = right.getExpression(fs);
209
- const expressionType = (0, malloy_types_1.maxExpressionType)(lhs.expressionType, rhs.expressionType);
210
- if (allAre("number", lhs, rhs)) {
211
- return {
212
- dataType: "number",
213
- expressionType,
214
- value: (0, index_1.compose)(lhs.value, op, rhs.value),
215
- };
216
- }
217
- left.log(`Non numeric('${lhs.dataType},${rhs.dataType}') value with '${op}'`);
218
- return (0, index_1.errorFor)("numbers required");
219
- }
220
- function delta(fs, left, op, right) {
221
- const lhs = left.getExpression(fs);
222
- const rhs = right.getExpression(fs);
223
- if ((0, malloy_types_1.isTimeFieldType)(lhs.dataType)) {
224
- let duration = right;
225
- if (rhs.dataType !== "duration") {
226
- if ((0, index_1.isGranularResult)(lhs)) {
227
- duration = new index_1.ExprDuration(right, lhs.timeframe);
228
- }
229
- else if (lhs.dataType === "date") {
230
- duration = new index_1.ExprDuration(right, "day");
231
- }
232
- else {
233
- left.log(`Can not offset time by '${rhs.dataType}'`);
234
- return (0, index_1.errorFor)(`time plus ${rhs.dataType}`);
235
- }
236
- }
237
- return duration.apply(fs, op, left);
238
- }
239
- return numeric(fs, left, op, right);
240
- }
241
34
  //# sourceMappingURL=apply-expr.js.map
@@ -1,75 +1,7 @@
1
- import { By, AtomicFieldType, FieldTypeDef, Fragment, TimeFieldType, ExpressionType } from "../../model/malloy_types";
1
+ import { By, ExpressionType } from "../../model/malloy_types";
2
2
  import { FieldSpace } from "../field-space";
3
- import { Filter, MalloyElement, ExprValue, FieldValueType, FragType } from "./index";
4
- import { FieldName, FieldReference } from "./ast-main";
5
- /**
6
- * Root node for any element in an expression. These essentially
7
- * create a sub-tree in the larger AST. Expression nodes know
8
- * how to write themselves as SQL (or rather, generate the
9
- * template for SQL required by the query writer)
10
- */
11
- export declare abstract class ExpressionDef extends MalloyElement {
12
- abstract elementType: string;
13
- granular(): boolean;
14
- /**
15
- * Returns the "translation" or template for SQL generation. When asking
16
- * for a tranlsation you may pass the types you can accept, allowing
17
- * the translation code a chance to convert to match your expectations
18
- * @param space Namespace for looking up field references
19
- */
20
- abstract getExpression(fs: FieldSpace): ExprValue;
21
- legalChildTypes: FragType[];
22
- /**
23
- * Some operators want to give the right hand value a chance to
24
- * rewrite itself. This requests a translation for a rewrite,
25
- * or returns undefined if that request should be denied.
26
- * @param fs FieldSpace
27
- * @returns Translated expression or undefined
28
- */
29
- requestExpression(fs: FieldSpace): ExprValue | undefined;
30
- defaultFieldName(): string | undefined;
31
- /**
32
- * Check an expression for type compatibility
33
- * @param _eNode currently unused, will be used to get error location
34
- * @param eVal ...list of expressions that must match legalChildTypes
35
- */
36
- typeCheck(eNode: ExpressionDef, eVal: ExprValue): boolean;
37
- /**
38
- * This is the operation which makes partial comparison and value trees work
39
- * The default implemention merely constructs LEFT OP RIGHT, but specialized
40
- * nodes like alternation trees or or partial comparison can control how
41
- * the appplication gets generated
42
- * @param fs The symbol table
43
- * @param op The operator being applied
44
- * @param expr The "other" (besdies 'this') value
45
- * @returns The translated expression
46
- */
47
- apply(fs: FieldSpace, op: string, left: ExpressionDef): ExprValue;
48
- }
49
- export declare class ConstantSubExpression extends ExpressionDef {
50
- readonly expr: ExpressionDef;
51
- elementType: string;
52
- private cfs?;
53
- constructor(expr: ExpressionDef);
54
- getExpression(_fs: FieldSpace): ExprValue;
55
- private get constantFs();
56
- constantValue(): ExprValue;
57
- constantCondition(type: AtomicFieldType): ExprValue;
58
- apply(fs: FieldSpace, op: string, expr: ExpressionDef): ExprValue;
59
- requestExpression(fs: FieldSpace): ExprValue | undefined;
60
- }
61
- export declare class FieldDeclaration extends MalloyElement {
62
- readonly expr: ExpressionDef;
63
- readonly defineName: string;
64
- readonly exprSrc?: string | undefined;
65
- elementType: string;
66
- isMeasure?: boolean;
67
- constructor(expr: ExpressionDef, defineName: string, exprSrc?: string | undefined);
68
- fieldDef(fs: FieldSpace, exprName: string): FieldTypeDef;
69
- queryFieldDef(exprFS: FieldSpace, exprName: string): FieldTypeDef;
70
- }
71
- export declare class TypeMistmatch extends Error {
72
- }
3
+ import { BinaryBoolean, ExpressionDef, ExprCompare, FieldName, FieldReference, Filter, MalloyElement } from "./ast-main";
4
+ import { ExprValue, FieldValueType, FragType } from "./ast-types";
73
5
  export declare class ExprString extends ExpressionDef {
74
6
  elementType: string;
75
7
  value: string;
@@ -89,13 +21,6 @@ export declare class ExprRegEx extends ExpressionDef {
89
21
  constructor(regex: string);
90
22
  getExpression(): ExprValue;
91
23
  }
92
- export declare class ExprTime extends ExpressionDef {
93
- elementType: string;
94
- readonly translationValue: ExprValue;
95
- constructor(timeType: TimeFieldType, value: Fragment[] | string, expressionType?: ExpressionType);
96
- getExpression(_fs: FieldSpace): ExprValue;
97
- static fromValue(timeType: TimeFieldType, expr: ExprValue): ExprTime;
98
- }
99
24
  declare abstract class Unary extends ExpressionDef {
100
25
  readonly expr: ExpressionDef;
101
26
  constructor(expr: ExpressionDef);
@@ -112,15 +37,6 @@ export declare class Boolean extends ExpressionDef {
112
37
  constructor(value: "true" | "false");
113
38
  getExpression(): ExprValue;
114
39
  }
115
- export declare abstract class BinaryBoolean<opType extends string> extends ExpressionDef {
116
- readonly left: ExpressionDef;
117
- readonly op: opType;
118
- readonly right: ExpressionDef;
119
- elementType: string;
120
- legalChildTypes: FragType[];
121
- constructor(left: ExpressionDef, op: opType, right: ExpressionDef);
122
- getExpression(fs: FieldSpace): ExprValue;
123
- }
124
40
  export declare class ExprLogicalOp extends BinaryBoolean<"and" | "or"> {
125
41
  elementType: string;
126
42
  legalChildTypes: (FragType | {
@@ -267,15 +183,6 @@ export declare class TopBy extends MalloyElement {
267
183
  constructor(by: string | ExpressionDef);
268
184
  getBy(fs: FieldSpace): By;
269
185
  }
270
- export declare class Range extends ExpressionDef {
271
- readonly first: ExpressionDef;
272
- readonly last: ExpressionDef;
273
- elementType: string;
274
- constructor(first: ExpressionDef, last: ExpressionDef);
275
- apply(fs: FieldSpace, op: string, expr: ExpressionDef): ExprValue;
276
- requestExpression(_fs: FieldSpace): ExprValue | undefined;
277
- getExpression(_fs: FieldSpace): ExprValue;
278
- }
279
186
  export declare class PickWhen extends MalloyElement {
280
187
  readonly pick: ExpressionDef | undefined;
281
188
  readonly when: ExpressionDef;
@@ -291,4 +198,10 @@ export declare class Pick extends ExpressionDef {
291
198
  apply(fs: FieldSpace, op: string, expr: ExpressionDef): ExprValue;
292
199
  getExpression(fs: FieldSpace): ExprValue;
293
200
  }
201
+ export declare class Apply extends ExprCompare {
202
+ readonly left: ExpressionDef;
203
+ readonly right: ExpressionDef;
204
+ elementType: string;
205
+ constructor(left: ExpressionDef, right: ExpressionDef);
206
+ }
294
207
  export {};