@malloydata/malloy 0.0.247-dev250321153536 → 0.0.247-dev250321211927
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/expressions/expr-filter-expr.js +8 -4
- package/dist/lang/parse-log.d.ts +1 -0
- package/dist/model/filter_compilers.d.ts +1 -1
- package/dist/model/filter_compilers.js +6 -6
- package/dist/model/filter_temporal_compiler.d.ts +1 -0
- package/dist/model/filter_temporal_compiler.js +29 -13
- package/dist/model/malloy_query.js +1 -2
- package/package.json +4 -4
|
@@ -15,7 +15,6 @@ class ExprFilterExpression extends expression_def_1.ExpressionDef {
|
|
|
15
15
|
super();
|
|
16
16
|
this.filterText = filterText;
|
|
17
17
|
this.elementType = 'filter expression literal';
|
|
18
|
-
// mtoy todo parse the filter and reflect errors into the error stream
|
|
19
18
|
}
|
|
20
19
|
getExpression() {
|
|
21
20
|
return this.loggedErrorExpr('filter-expression-type', 'Filter expression illegal here');
|
|
@@ -49,9 +48,14 @@ class ExprFilterExpression extends expression_def_1.ExpressionDef {
|
|
|
49
48
|
return left.loggedErrorExpr('filter-expression-type', `Cannot use filter expressions with type '${matchExpr.type}'`);
|
|
50
49
|
}
|
|
51
50
|
if (fParse.log.length > 0) {
|
|
52
|
-
for (const
|
|
53
|
-
//
|
|
54
|
-
|
|
51
|
+
for (const err of fParse.log) {
|
|
52
|
+
// Current parser only ever returns one error, it doesn't recover
|
|
53
|
+
// Theoretically possible to user the startIndex to point to the
|
|
54
|
+
// error inside the filter string, but I don't know if this is an
|
|
55
|
+
// f' string or an f''' string, and I think the startOffset is from
|
|
56
|
+
// the first non blank space in the filter (it was at one point)
|
|
57
|
+
// so for now, we just flag the entire filter source token.
|
|
58
|
+
return this.loggedErrorExpr('filter-expression-error', `Filter parse error: ${err.message}`);
|
|
55
59
|
}
|
|
56
60
|
}
|
|
57
61
|
if (!fParse.parsed) {
|
package/dist/lang/parse-log.d.ts
CHANGED
|
@@ -364,6 +364,7 @@ type MessageParameterTypes = {
|
|
|
364
364
|
'wildcard-include-rename': string;
|
|
365
365
|
'literal-string-newline': string;
|
|
366
366
|
'filter-expression-type': string;
|
|
367
|
+
'filter-expression-error': string;
|
|
367
368
|
'invalid-malloy-query-document': string;
|
|
368
369
|
};
|
|
369
370
|
export declare const MESSAGE_FORMATTERS: PartialErrorCodeMessageMap;
|
|
@@ -5,5 +5,5 @@ export declare const FilterCompilers: {
|
|
|
5
5
|
numberCompile(nc: NumberFilter, x: string, d: Dialect): string;
|
|
6
6
|
booleanCompile(bc: BooleanFilter, x: string, _d: Dialect): string;
|
|
7
7
|
stringCompile(sc: StringFilter, x: string, d: Dialect): string;
|
|
8
|
-
temporalCompile(tc: TemporalFilter, x: string, d: Dialect): string;
|
|
8
|
+
temporalCompile(tc: TemporalFilter, x: string, d: Dialect, t: 'date' | 'timestamp'): string;
|
|
9
9
|
};
|
|
@@ -47,7 +47,7 @@ exports.FilterCompilers = {
|
|
|
47
47
|
return exports.FilterCompilers.booleanCompile(c, x, d);
|
|
48
48
|
}
|
|
49
49
|
else if ((t === 'date' || t === 'timestamp') && (0, malloy_filter_1.isTemporalFilter)(c)) {
|
|
50
|
-
return exports.FilterCompilers.temporalCompile(c, x, d);
|
|
50
|
+
return exports.FilterCompilers.temporalCompile(c, x, d, t);
|
|
51
51
|
}
|
|
52
52
|
throw new Error('INTERNAL ERROR: No filter compiler for ' + t);
|
|
53
53
|
},
|
|
@@ -167,9 +167,9 @@ exports.FilterCompilers = {
|
|
|
167
167
|
case ',': {
|
|
168
168
|
/*
|
|
169
169
|
* Basic formula over all members
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
170
|
+
* (ALL INCLUDED THINGS OR TOGETHER)
|
|
171
|
+
* AND
|
|
172
|
+
* (ALL EXCLUDED THINGS ANDED TOGETHER)
|
|
173
173
|
*/
|
|
174
174
|
const includes = [];
|
|
175
175
|
const excludes = [];
|
|
@@ -243,8 +243,8 @@ exports.FilterCompilers = {
|
|
|
243
243
|
}
|
|
244
244
|
},
|
|
245
245
|
// mtoy todo figure out what to do about dates
|
|
246
|
-
temporalCompile(tc, x, d) {
|
|
247
|
-
const c = new filter_temporal_compiler_1.TemporalFilterCompiler(x, d);
|
|
246
|
+
temporalCompile(tc, x, d, t) {
|
|
247
|
+
const c = new filter_temporal_compiler_1.TemporalFilterCompiler(x, d, t);
|
|
248
248
|
return c.compile(tc);
|
|
249
249
|
},
|
|
250
250
|
};
|
|
@@ -11,6 +11,7 @@ export declare class TemporalFilterCompiler {
|
|
|
11
11
|
readonly timetype: 'timestamp' | 'date';
|
|
12
12
|
readonly d: Dialect;
|
|
13
13
|
constructor(expr: string, dialect: Dialect, timetype?: 'timestamp' | 'date');
|
|
14
|
+
time(timeSQL: string): string;
|
|
14
15
|
compile(tc: TemporalFilter): string;
|
|
15
16
|
private expandLiteral;
|
|
16
17
|
private literalNode;
|
|
@@ -27,16 +27,37 @@ class TemporalFilterCompiler {
|
|
|
27
27
|
this.timetype = timetype;
|
|
28
28
|
this.d = dialect;
|
|
29
29
|
}
|
|
30
|
+
time(timeSQL) {
|
|
31
|
+
if (this.timetype === 'timestamp') {
|
|
32
|
+
return timeSQL;
|
|
33
|
+
}
|
|
34
|
+
return this.d.sqlCast({}, {
|
|
35
|
+
node: 'cast',
|
|
36
|
+
e: {
|
|
37
|
+
node: 'genericSQLExpr',
|
|
38
|
+
src: ['', timeSQL],
|
|
39
|
+
kids: { args: [] },
|
|
40
|
+
sql: timeSQL,
|
|
41
|
+
},
|
|
42
|
+
srcType: { type: 'timestamp' },
|
|
43
|
+
dstType: { type: 'date' },
|
|
44
|
+
safe: false,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
30
47
|
compile(tc) {
|
|
31
48
|
const x = this.expr;
|
|
32
49
|
switch (tc.operator) {
|
|
33
50
|
case 'after':
|
|
34
|
-
return `${x} ${tc.not ? '<' : '>='} ${this.moment(tc.after).end}`;
|
|
51
|
+
return `${x} ${tc.not ? '<' : '>='} ${this.time(this.moment(tc.after).end)}`;
|
|
35
52
|
case 'before':
|
|
36
|
-
return `${x} ${tc.not ? '>=' : '<'} ${this.moment(tc.before).begin}`;
|
|
53
|
+
return `${x} ${tc.not ? '>=' : '<'} ${this.time(this.moment(tc.before).begin.sql)}`;
|
|
37
54
|
case 'in': {
|
|
38
|
-
// mtoy todo in now
|
|
39
55
|
const m = this.moment(tc.in);
|
|
56
|
+
if (m.begin.sql === m.end) {
|
|
57
|
+
return tc.not
|
|
58
|
+
? `${x} != ${this.time(m.end)} OR ${x} IS NULL`
|
|
59
|
+
: `${x} = ${this.time(m.end)}`;
|
|
60
|
+
}
|
|
40
61
|
return this.isIn(tc.not, m.begin.sql, m.end);
|
|
41
62
|
}
|
|
42
63
|
case 'for': {
|
|
@@ -57,7 +78,7 @@ class TemporalFilterCompiler {
|
|
|
57
78
|
case 'to': {
|
|
58
79
|
const firstMoment = this.moment(tc.fromMoment);
|
|
59
80
|
const lastMoment = this.moment(tc.toMoment);
|
|
60
|
-
return this.isIn(tc.not, firstMoment.begin.sql, lastMoment.
|
|
81
|
+
return this.isIn(tc.not, firstMoment.begin.sql, lastMoment.begin.sql);
|
|
61
82
|
}
|
|
62
83
|
case 'last': {
|
|
63
84
|
const thisUnit = this.nowDot(tc.units);
|
|
@@ -221,7 +242,6 @@ class TemporalFilterCompiler {
|
|
|
221
242
|
}
|
|
222
243
|
moment(m) {
|
|
223
244
|
switch (m.moment) {
|
|
224
|
-
// mtoy todo moments which have no duration should have somethign in the interface?
|
|
225
245
|
case 'now': {
|
|
226
246
|
const now = this.nowExpr();
|
|
227
247
|
return { begin: now, end: now.sql };
|
|
@@ -230,20 +250,14 @@ class TemporalFilterCompiler {
|
|
|
230
250
|
return this.expandLiteral(m);
|
|
231
251
|
case 'ago':
|
|
232
252
|
case 'from_now': {
|
|
233
|
-
|
|
234
|
-
const nowTruncExpr = {
|
|
235
|
-
node: 'trunc',
|
|
236
|
-
e: this.nowExpr(),
|
|
237
|
-
units: m.units,
|
|
238
|
-
};
|
|
239
|
-
nowTruncExpr.sql = this.d.sqlTruncExpr({}, nowTruncExpr);
|
|
253
|
+
const nowTruncExpr = this.nowDot(m.units);
|
|
240
254
|
const nowTrunc = (0, malloy_types_1.mkTemporal)(nowTruncExpr, 'timestamp');
|
|
241
255
|
const beginExpr = this.delta(nowTrunc, m.moment === 'ago' ? '-' : '+', m.n, m.units);
|
|
242
256
|
// Now the end is one unit after that .. either n-1 units ago or n+1 units from now
|
|
243
257
|
if (m.moment === 'ago' && m.n === '1') {
|
|
244
258
|
return { begin: beginExpr, end: nowTruncExpr.sql };
|
|
245
259
|
}
|
|
246
|
-
const oneDifferent = Number(m.n) + m.moment === 'ago' ? -1 : 1;
|
|
260
|
+
const oneDifferent = Number(m.n) + (m.moment === 'ago' ? -1 : 1);
|
|
247
261
|
const endExpr = {
|
|
248
262
|
...beginExpr,
|
|
249
263
|
kids: { base: nowTrunc, delta: this.n(oneDifferent.toString()) },
|
|
@@ -318,6 +332,8 @@ class TemporalFilterCompiler {
|
|
|
318
332
|
begOp = '<';
|
|
319
333
|
endOp = '>=';
|
|
320
334
|
}
|
|
335
|
+
begin = this.time(begin);
|
|
336
|
+
end = this.time(end);
|
|
321
337
|
return `${this.expr} ${begOp} ${begin} ${joinOp} ${this.expr} ${endOp} ${end}`;
|
|
322
338
|
}
|
|
323
339
|
}
|
|
@@ -893,8 +893,7 @@ class QueryField extends QueryNode {
|
|
|
893
893
|
return filter_compilers_1.FilterCompilers.compile(expr.dataType, expr.filter, expr.e.sql || '', this.parent.dialect);
|
|
894
894
|
}
|
|
895
895
|
}
|
|
896
|
-
|
|
897
|
-
throw new Error(`Internal Error: Filter Compiler Undefined (FCU) ${expr.dataType}`);
|
|
896
|
+
throw new Error(`Internal Error: Filter Compiler Undefined Type '${expr.dataType}'`);
|
|
898
897
|
default:
|
|
899
898
|
throw new Error(`Internal Error: Unknown expression node '${expr.node}' ${JSON.stringify(expr, undefined, 2)}`);
|
|
900
899
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@malloydata/malloy",
|
|
3
|
-
"version": "0.0.247-
|
|
3
|
+
"version": "0.0.247-dev250321211927",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dist/index.js",
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"generate-version-file": "VERSION=$(npm pkg get version --workspaces=false | tr -d \\\")\necho \"// generated with 'generate-version-file' script; do not edit manually\\nexport const MALLOY_VERSION = '$VERSION';\" > src/version.ts"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@malloydata/malloy-filter": "^0.0.247-
|
|
45
|
-
"@malloydata/malloy-interfaces": "^0.0.247-
|
|
46
|
-
"@malloydata/malloy-tag": "^0.0.247-
|
|
44
|
+
"@malloydata/malloy-filter": "^0.0.247-dev250321211927",
|
|
45
|
+
"@malloydata/malloy-interfaces": "^0.0.247-dev250321211927",
|
|
46
|
+
"@malloydata/malloy-tag": "^0.0.247-dev250321211927",
|
|
47
47
|
"antlr4ts": "^0.5.0-alpha.4",
|
|
48
48
|
"assert": "^2.0.0",
|
|
49
49
|
"jest-diff": "^29.6.2",
|