@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.
- 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/dist/run_sql_options.js +18 -8
- package/package.json +1 -1
|
@@ -1,16 +1,3 @@
|
|
|
1
1
|
import { Expr } from "../../model/malloy_types";
|
|
2
|
-
import {
|
|
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 =
|
|
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,
|
|
1
|
+
import { By, ExpressionType } from "../../model/malloy_types";
|
|
2
2
|
import { FieldSpace } from "../field-space";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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 {};
|