@malloydata/malloy 0.0.262 → 0.0.263-dev250414184158
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.d.ts +0 -3
- package/dist/lang/ast/expressions/expr-filter-expr.js +7 -59
- package/dist/lang/ast/expressions/expr-func.js +3 -0
- package/dist/lang/ast/expressions/pick-when.js +6 -0
- package/dist/lang/ast/field-space/dynamic-space.js +1 -1
- package/dist/lang/ast/field-space/join-space-field.js +1 -1
- package/dist/lang/ast/index.d.ts +1 -0
- package/dist/lang/ast/index.js +1 -0
- package/dist/lang/ast/parameters/has-parameter.d.ts +6 -3
- package/dist/lang/ast/parameters/has-parameter.js +28 -9
- package/dist/lang/ast/query-items/field-declaration.d.ts +1 -2
- package/dist/lang/ast/query-items/field-declaration.js +0 -4
- package/dist/lang/ast/source-elements/named-source.js +6 -0
- package/dist/lang/ast/source-properties/join.d.ts +3 -3
- package/dist/lang/ast/source-properties/join.js +2 -2
- package/dist/lang/ast/types/expression-def.d.ts +2 -1
- package/dist/lang/ast/types/expression-def.js +79 -17
- package/dist/lang/ast/types/space-param.d.ts +1 -3
- package/dist/lang/ast/types/space-param.js +8 -8
- package/dist/lang/lib/Malloy/MalloyLexer.d.ts +114 -113
- package/dist/lang/lib/Malloy/MalloyLexer.js +1272 -1266
- package/dist/lang/lib/Malloy/MalloyParser.d.ts +253 -239
- package/dist/lang/lib/Malloy/MalloyParser.js +2244 -2142
- package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +11 -0
- package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +7 -0
- package/dist/lang/malloy-to-ast.d.ts +1 -1
- package/dist/lang/malloy-to-ast.js +38 -12
- package/dist/lang/test/expr-to-str.js +3 -20
- package/dist/model/filter_compilers.d.ts +27 -0
- package/dist/model/filter_compilers.js +335 -3
- package/dist/model/malloy_query.d.ts +2 -1
- package/dist/model/malloy_query.js +45 -10
- package/dist/model/malloy_types.d.ts +18 -6
- package/dist/model/malloy_types.js +6 -2
- package/dist/to_stable.js +19 -5
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
- package/dist/model/filter_temporal_compiler.d.ts +0 -29
- package/dist/model/filter_temporal_compiler.js +0 -343
|
@@ -25,7 +25,7 @@ export type AnyExpr = ExprE | ExprOptionalE | ExprWithKids | ExprLeaf;
|
|
|
25
25
|
export declare function exprHasKids(e: AnyExpr): e is ExprWithKids;
|
|
26
26
|
export declare function exprHasE(e: AnyExpr): e is ExprE;
|
|
27
27
|
export declare function exprIsLeaf(e: AnyExpr): boolean;
|
|
28
|
-
export type Expr = BinaryExpr | UnaryExpr | FunctionCallNode | OutputFieldNode | FilterCondition | FilteredExpr | AggregateExpr | EmptyExpr | UngroupNode | FunctionParameterNode | SpreadExpr | AggregateOrderByNode | AggregateLimitNode | FieldnameNode | SourceReferenceNode | ParameterNode | NowNode | MeasureTimeExpr | TimeExtractExpr | TimeDeltaExpr | TimeTruncExpr | TimeLiteralNode | TypecastExpr | RegexMatchExpr | RegexLiteralNode | FilterMatchExpr | StringLiteralNode | NumberLiteralNode | BooleanLiteralNode | RecordLiteralNode | ArrayLiteralNode | FunctionOrderBy | GenericSQLExpr | NullNode | CaseExpr | InCompareExpr | CompositeFieldExpr | ErrorNode;
|
|
28
|
+
export type Expr = BinaryExpr | UnaryExpr | FunctionCallNode | OutputFieldNode | FilterCondition | FilteredExpr | AggregateExpr | EmptyExpr | UngroupNode | FunctionParameterNode | SpreadExpr | AggregateOrderByNode | AggregateLimitNode | FieldnameNode | SourceReferenceNode | ParameterNode | NowNode | MeasureTimeExpr | TimeExtractExpr | TimeDeltaExpr | TimeTruncExpr | TimeLiteralNode | TypecastExpr | RegexMatchExpr | RegexLiteralNode | FilterMatchExpr | FilterLiteralExpr | StringLiteralNode | NumberLiteralNode | BooleanLiteralNode | RecordLiteralNode | ArrayLiteralNode | FunctionOrderBy | GenericSQLExpr | NullNode | CaseExpr | InCompareExpr | CompositeFieldExpr | ErrorNode;
|
|
29
29
|
export type BinaryOperator = '+' | '-' | '*' | '%' | '/' | 'and' | 'or' | '=' | '!=' | '>' | '<' | '>=' | '<=' | 'coalesce' | 'like' | '!like';
|
|
30
30
|
export interface BinaryExpr extends ExprWithKids {
|
|
31
31
|
node: BinaryOperator;
|
|
@@ -175,13 +175,18 @@ export interface RegexMatchExpr extends ExprWithKids {
|
|
|
175
175
|
}
|
|
176
176
|
export type FilterExprType = 'string' | 'number' | 'boolean' | 'date' | 'timestamp';
|
|
177
177
|
export declare function isFilterExprType(s: string): s is FilterExprType;
|
|
178
|
-
export interface FilterMatchExpr extends
|
|
178
|
+
export interface FilterMatchExpr extends ExprWithKids {
|
|
179
179
|
node: 'filterMatch';
|
|
180
180
|
dataType: FilterExprType;
|
|
181
181
|
notMatch?: true;
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
182
|
+
kids: {
|
|
183
|
+
filterExpr: Expr;
|
|
184
|
+
expr: Expr;
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
export interface FilterLiteralExpr extends ExprLeaf {
|
|
188
|
+
node: 'filterLiteral';
|
|
189
|
+
filterSrc: string;
|
|
185
190
|
}
|
|
186
191
|
export interface TimeLiteralNode extends ExprLeaf {
|
|
187
192
|
node: 'timeLiteral';
|
|
@@ -262,7 +267,14 @@ interface ParameterInfo {
|
|
|
262
267
|
name: string;
|
|
263
268
|
value: ConstantExpr | null;
|
|
264
269
|
}
|
|
265
|
-
export
|
|
270
|
+
export interface FilterExpressionDef {
|
|
271
|
+
type: 'filter expression';
|
|
272
|
+
filterType?: FilterExprType;
|
|
273
|
+
}
|
|
274
|
+
export type ParameterType = CastType | 'filter expression';
|
|
275
|
+
export declare function isParameterType(t: string): t is ParameterType;
|
|
276
|
+
export type ParameterTypeDef = AtomicTypeDef | FilterExpressionDef;
|
|
277
|
+
export type Parameter = ParameterTypeDef & ParameterInfo;
|
|
266
278
|
export type Argument = Parameter;
|
|
267
279
|
export declare function paramHasValue(p: Parameter): boolean;
|
|
268
280
|
export interface DocumentRange {
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
24
24
|
*/
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.
|
|
27
|
-
exports.TD = exports.isValueDate = exports.isValueTimestamp = exports.isValueBoolean = exports.isValueNumber = exports.isValueString = exports.isAtomic = exports.isTurtle = exports.getIdentifier = exports.isBasicAtomic = exports.mergeEvalSpaces = exports.isLiteral = exports.isBaseTable = exports.isSourceDef = void 0;
|
|
26
|
+
exports.isSegmentSQL = exports.isIndexSegment = exports.isRawSegment = exports.isSamplingEnable = exports.isSamplingPercent = exports.isSamplingRows = exports.isQuerySegment = exports.isProjectSegment = exports.isPartialSegment = exports.isReduceSegment = exports.structHasErrors = exports.segmentHasErrors = exports.refIsStructDef = exports.ValueType = exports.isExtractUnit = exports.isTimestampUnit = exports.isDateUnit = exports.isJoinedSource = exports.isJoined = exports.isJoinable = exports.isMatrixOperation = exports.isBasicArray = exports.isRepeatedRecord = exports.isRepeatedRecordFunctionParam = exports.mkArrayDef = exports.mkFieldDef = exports.fieldIsIntrinsic = exports.isCastType = exports.canOrderBy = exports.isAtomicFieldType = exports.isTemporalType = exports.hasExpression = exports.maxOfExpressionTypes = exports.maxExpressionType = exports.isExpressionTypeLEQ = exports.expressionIsAnalytic = exports.expressionIsCalculation = exports.expressionInvolvesAggregate = exports.expressionIsUngroupedAggregate = exports.expressionIsAggregate = exports.expressionIsScalar = exports.paramHasValue = exports.isParameterType = exports.isFilterExprType = exports.isRawCast = exports.mkTemporal = exports.isAsymmetricExpr = exports.exprIsLeaf = exports.exprHasE = exports.exprHasKids = void 0;
|
|
27
|
+
exports.TD = exports.isValueDate = exports.isValueTimestamp = exports.isValueBoolean = exports.isValueNumber = exports.isValueString = exports.isAtomic = exports.isTurtle = exports.getIdentifier = exports.isBasicAtomic = exports.mergeEvalSpaces = exports.isLiteral = exports.isBaseTable = exports.isSourceDef = exports.sourceBase = void 0;
|
|
28
28
|
function exprHasKids(e) {
|
|
29
29
|
return 'kids' in e;
|
|
30
30
|
}
|
|
@@ -75,6 +75,10 @@ function isFilterExprType(s) {
|
|
|
75
75
|
return ['string', 'number', 'boolean', 'date', 'timestamp'].includes(s);
|
|
76
76
|
}
|
|
77
77
|
exports.isFilterExprType = isFilterExprType;
|
|
78
|
+
function isParameterType(t) {
|
|
79
|
+
return isCastType(t) || t === 'filter expression';
|
|
80
|
+
}
|
|
81
|
+
exports.isParameterType = isParameterType;
|
|
78
82
|
function paramHasValue(p) {
|
|
79
83
|
return p.value !== null;
|
|
80
84
|
}
|
package/dist/to_stable.js
CHANGED
|
@@ -21,11 +21,20 @@ function modelDefToModelInfo(modelDef) {
|
|
|
21
21
|
continue;
|
|
22
22
|
if ((0, model_1.isSourceDef)(entry)) {
|
|
23
23
|
const parameters = entry.parameters && Object.entries(entry.parameters).length > 0
|
|
24
|
-
? Object.entries(entry.parameters).map(([name, parameter]) =>
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
? Object.entries(entry.parameters).map(([name, parameter]) => {
|
|
25
|
+
if ((0, model_1.isAtomic)(parameter)) {
|
|
26
|
+
return {
|
|
27
|
+
name,
|
|
28
|
+
type: typeDefToType(parameter),
|
|
29
|
+
default_value: convertParameterDefaultValue(parameter.value),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
name,
|
|
34
|
+
type: { kind: 'filter_expression_type' },
|
|
35
|
+
default_value: convertParameterDefaultValue(parameter.value),
|
|
36
|
+
};
|
|
37
|
+
})
|
|
29
38
|
: undefined;
|
|
30
39
|
const sourceInfo = {
|
|
31
40
|
kind: 'source',
|
|
@@ -89,6 +98,11 @@ function convertParameterDefaultValue(value) {
|
|
|
89
98
|
return { kind: 'number_literal', number_value: parseFloat(value.literal) };
|
|
90
99
|
case 'stringLiteral':
|
|
91
100
|
return { kind: 'string_literal', string_value: value.literal };
|
|
101
|
+
case 'filterLiteral':
|
|
102
|
+
return {
|
|
103
|
+
kind: 'filter_expression_literal',
|
|
104
|
+
filter_expression_value: value.filterSrc,
|
|
105
|
+
};
|
|
92
106
|
case 'timeLiteral':
|
|
93
107
|
return {
|
|
94
108
|
kind: 'timestamp_literal',
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const MALLOY_VERSION = "0.0.
|
|
1
|
+
export declare const MALLOY_VERSION = "0.0.263";
|
package/dist/version.js
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MALLOY_VERSION = void 0;
|
|
4
4
|
// generated with 'generate-version-file' script; do not edit manually
|
|
5
|
-
exports.MALLOY_VERSION = '0.0.
|
|
5
|
+
exports.MALLOY_VERSION = '0.0.263';
|
|
6
6
|
//# sourceMappingURL=version.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@malloydata/malloy",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.263-dev250414184158",
|
|
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.
|
|
45
|
-
"@malloydata/malloy-interfaces": "^0.0.
|
|
46
|
-
"@malloydata/malloy-tag": "^0.0.
|
|
44
|
+
"@malloydata/malloy-filter": "^0.0.263-dev250414184158",
|
|
45
|
+
"@malloydata/malloy-interfaces": "^0.0.263-dev250414184158",
|
|
46
|
+
"@malloydata/malloy-tag": "^0.0.263-dev250414184158",
|
|
47
47
|
"antlr4ts": "^0.5.0-alpha.4",
|
|
48
48
|
"assert": "^2.0.0",
|
|
49
49
|
"jaro-winkler": "^0.2.8",
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { TemporalFilter } from '@malloydata/malloy-filter';
|
|
2
|
-
import type { Dialect } from '../dialect';
|
|
3
|
-
/**
|
|
4
|
-
* I felt like there was enough "helpful functions needed to make everything
|
|
5
|
-
* work, all of which need to know the dialect", to justify making a class
|
|
6
|
-
* for this. Maybe this should just be a set of functions which take
|
|
7
|
-
* a dialect as an argument?
|
|
8
|
-
*/
|
|
9
|
-
export declare class TemporalFilterCompiler {
|
|
10
|
-
readonly expr: string;
|
|
11
|
-
readonly timetype: 'timestamp' | 'date';
|
|
12
|
-
readonly d: Dialect;
|
|
13
|
-
constructor(expr: string, dialect: Dialect, timetype?: 'timestamp' | 'date');
|
|
14
|
-
time(timeSQL: string): string;
|
|
15
|
-
compile(tc: TemporalFilter): string;
|
|
16
|
-
private expandLiteral;
|
|
17
|
-
private literalNode;
|
|
18
|
-
private nowExpr;
|
|
19
|
-
private n;
|
|
20
|
-
private delta;
|
|
21
|
-
private dayofWeek;
|
|
22
|
-
private nowDot;
|
|
23
|
-
private thisUnit;
|
|
24
|
-
private lastUnit;
|
|
25
|
-
private nextUnit;
|
|
26
|
-
mod7(n: string): string;
|
|
27
|
-
private moment;
|
|
28
|
-
private isIn;
|
|
29
|
-
}
|
|
@@ -1,343 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
-
*
|
|
5
|
-
* This source code is licensed under the MIT license found in the
|
|
6
|
-
* LICENSE file in the root directory of this source tree.
|
|
7
|
-
*/
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.TemporalFilterCompiler = void 0;
|
|
10
|
-
const malloy_types_1 = require("./malloy_types");
|
|
11
|
-
const luxon_1 = require("luxon");
|
|
12
|
-
const fYear = 'yyyy';
|
|
13
|
-
const fMonth = `${fYear}-LL`;
|
|
14
|
-
const fDay = `${fMonth}-dd`;
|
|
15
|
-
const fHour = `${fDay} HH`;
|
|
16
|
-
const fMinute = `${fHour}:mm`;
|
|
17
|
-
const fTimestamp = `${fMinute}:ss`;
|
|
18
|
-
/**
|
|
19
|
-
* I felt like there was enough "helpful functions needed to make everything
|
|
20
|
-
* work, all of which need to know the dialect", to justify making a class
|
|
21
|
-
* for this. Maybe this should just be a set of functions which take
|
|
22
|
-
* a dialect as an argument?
|
|
23
|
-
*/
|
|
24
|
-
class TemporalFilterCompiler {
|
|
25
|
-
constructor(expr, dialect, timetype = 'timestamp') {
|
|
26
|
-
this.expr = expr;
|
|
27
|
-
this.timetype = timetype;
|
|
28
|
-
this.d = dialect;
|
|
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
|
-
}
|
|
47
|
-
compile(tc) {
|
|
48
|
-
const x = this.expr;
|
|
49
|
-
switch (tc.operator) {
|
|
50
|
-
case 'after':
|
|
51
|
-
return `${x} ${tc.not ? '<' : '>='} ${this.time(this.moment(tc.after).end)}`;
|
|
52
|
-
case 'before':
|
|
53
|
-
return `${x} ${tc.not ? '>=' : '<'} ${this.time(this.moment(tc.before).begin.sql)}`;
|
|
54
|
-
case 'in': {
|
|
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
|
-
}
|
|
61
|
-
return this.isIn(tc.not, m.begin.sql, m.end);
|
|
62
|
-
}
|
|
63
|
-
case 'for': {
|
|
64
|
-
const start = this.moment(tc.begin);
|
|
65
|
-
const end = this.delta(start.begin, '+', tc.n, tc.units);
|
|
66
|
-
return this.isIn(tc.not, start.begin.sql, end.sql);
|
|
67
|
-
}
|
|
68
|
-
case 'in_last': {
|
|
69
|
-
// last N units means "N - 1 UNITS AGO FOR N UNITS"
|
|
70
|
-
const back = Number(tc.n) - 1;
|
|
71
|
-
const thisUnit = this.nowDot(tc.units);
|
|
72
|
-
const start = back > 0
|
|
73
|
-
? this.delta(thisUnit, '-', back.toString(), tc.units)
|
|
74
|
-
: thisUnit;
|
|
75
|
-
const end = this.delta(thisUnit, '+', '1', tc.units);
|
|
76
|
-
return this.isIn(tc.not, start.sql, end.sql);
|
|
77
|
-
}
|
|
78
|
-
case 'to': {
|
|
79
|
-
const firstMoment = this.moment(tc.fromMoment);
|
|
80
|
-
const lastMoment = this.moment(tc.toMoment);
|
|
81
|
-
return this.isIn(tc.not, firstMoment.begin.sql, lastMoment.begin.sql);
|
|
82
|
-
}
|
|
83
|
-
case 'last': {
|
|
84
|
-
const thisUnit = this.nowDot(tc.units);
|
|
85
|
-
const start = this.delta(thisUnit, '-', tc.n, tc.units);
|
|
86
|
-
return this.isIn(tc.not, start.sql, thisUnit.sql);
|
|
87
|
-
}
|
|
88
|
-
case 'next': {
|
|
89
|
-
const thisUnit = this.nowDot(tc.units);
|
|
90
|
-
const start = this.delta(thisUnit, '+', '1', tc.units);
|
|
91
|
-
const end = this.delta(thisUnit, '+', (Number(tc.n) + 1).toString(), tc.units);
|
|
92
|
-
return this.isIn(tc.not, start.sql, end.sql);
|
|
93
|
-
}
|
|
94
|
-
case 'null':
|
|
95
|
-
return tc.not ? `${x} IS NOT NULL` : `${x} IS NULL`;
|
|
96
|
-
case '()': {
|
|
97
|
-
const wrapped = '(' + this.compile(tc.expr) + ')';
|
|
98
|
-
return tc.not ? `NOT ${wrapped}` : wrapped;
|
|
99
|
-
}
|
|
100
|
-
case 'and':
|
|
101
|
-
case 'or':
|
|
102
|
-
return tc.members
|
|
103
|
-
.map(m => this.compile(m))
|
|
104
|
-
.join(` ${tc.operator.toUpperCase()} `);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
expandLiteral(tl) {
|
|
108
|
-
let literal = tl.literal;
|
|
109
|
-
switch (tl.units) {
|
|
110
|
-
case 'year': {
|
|
111
|
-
const y = luxon_1.DateTime.fromFormat(literal, fYear);
|
|
112
|
-
const begin = this.literalNode(y.toFormat(fTimestamp));
|
|
113
|
-
const next = y.plus({ year: 1 });
|
|
114
|
-
return { begin, end: this.literalNode(next.toFormat(fTimestamp)).sql };
|
|
115
|
-
}
|
|
116
|
-
case 'month': {
|
|
117
|
-
const yyyymm = luxon_1.DateTime.fromFormat(literal, fMonth);
|
|
118
|
-
const begin = this.literalNode(yyyymm.toFormat(fTimestamp));
|
|
119
|
-
const next = yyyymm.plus({ month: 1 });
|
|
120
|
-
return { begin, end: this.literalNode(next.toFormat(fTimestamp)).sql };
|
|
121
|
-
}
|
|
122
|
-
case 'day': {
|
|
123
|
-
const yyyymmdd = luxon_1.DateTime.fromFormat(literal, fDay);
|
|
124
|
-
const begin = this.literalNode(yyyymmdd.toFormat(fTimestamp));
|
|
125
|
-
const next = yyyymmdd.plus({ day: 1 });
|
|
126
|
-
return { begin, end: this.literalNode(next.toFormat(fTimestamp)).sql };
|
|
127
|
-
}
|
|
128
|
-
case 'hour': {
|
|
129
|
-
const ymdh = luxon_1.DateTime.fromFormat(literal, fHour);
|
|
130
|
-
const begin = this.literalNode(ymdh.toFormat(fTimestamp));
|
|
131
|
-
const next = ymdh.plus({ hour: 1 });
|
|
132
|
-
return { begin, end: this.literalNode(next.toFormat(fTimestamp)).sql };
|
|
133
|
-
}
|
|
134
|
-
case 'minute': {
|
|
135
|
-
const ymdhm = luxon_1.DateTime.fromFormat(literal, fMinute);
|
|
136
|
-
const begin = this.literalNode(ymdhm.toFormat(fTimestamp));
|
|
137
|
-
const next = ymdhm.plus({ minute: 1 });
|
|
138
|
-
return { begin, end: this.literalNode(next.toFormat(fTimestamp)).sql };
|
|
139
|
-
}
|
|
140
|
-
case 'week': {
|
|
141
|
-
const a = luxon_1.DateTime.fromFormat(literal.slice(0, 10), fDay);
|
|
142
|
-
// Luxon uses monday weeks, so look for the Monday week which contains
|
|
143
|
-
// the day after, which for all days except Sunday is the same as
|
|
144
|
-
// the sunday week, and on Sunday it is this monday week instead of
|
|
145
|
-
// last monday week.
|
|
146
|
-
const mondayWeek = a.plus({ day: 1 }).startOf('week');
|
|
147
|
-
// Now back that up by one day and we have the Sunday week
|
|
148
|
-
const ymd_wk = mondayWeek.minus({ day: 1 });
|
|
149
|
-
const begin = this.literalNode(ymd_wk.toFormat(fTimestamp));
|
|
150
|
-
const next = ymd_wk.plus({ days: 7 });
|
|
151
|
-
return { begin, end: this.literalNode(next.toFormat(fTimestamp)).sql };
|
|
152
|
-
}
|
|
153
|
-
case 'quarter': {
|
|
154
|
-
const yyyy = literal.slice(0, 4);
|
|
155
|
-
const q = literal.slice(6);
|
|
156
|
-
if (q === '1') {
|
|
157
|
-
literal = `${yyyy}-01-01 00:00:00`;
|
|
158
|
-
}
|
|
159
|
-
else if (q === '2') {
|
|
160
|
-
literal = `${yyyy}-03-01 00:00:00`;
|
|
161
|
-
}
|
|
162
|
-
else if (q === '3') {
|
|
163
|
-
literal = `${yyyy}-06-01 00:00:00`;
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
literal = `${yyyy}-09-01 00:00:00`;
|
|
167
|
-
}
|
|
168
|
-
const begin = this.literalNode(literal);
|
|
169
|
-
const ymd_q = luxon_1.DateTime.fromFormat(literal, fTimestamp);
|
|
170
|
-
const next = ymd_q.plus({ months: 3 });
|
|
171
|
-
return { begin, end: this.literalNode(next.toFormat(fTimestamp)).sql };
|
|
172
|
-
}
|
|
173
|
-
case undefined:
|
|
174
|
-
case 'second': {
|
|
175
|
-
const begin = this.literalNode(literal);
|
|
176
|
-
return { begin, end: begin.sql };
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
literalNode(literal) {
|
|
181
|
-
const literalNode = {
|
|
182
|
-
node: 'timeLiteral',
|
|
183
|
-
typeDef: { type: 'timestamp' },
|
|
184
|
-
literal,
|
|
185
|
-
};
|
|
186
|
-
return { ...literalNode, sql: this.d.sqlLiteralTime({}, literalNode) };
|
|
187
|
-
}
|
|
188
|
-
nowExpr() {
|
|
189
|
-
return {
|
|
190
|
-
node: 'now',
|
|
191
|
-
typeDef: { type: 'timestamp' },
|
|
192
|
-
sql: this.d.sqlNowExpr(),
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
n(literal) {
|
|
196
|
-
return { node: 'numberLiteral', literal, sql: literal };
|
|
197
|
-
}
|
|
198
|
-
delta(from, op, n, units) {
|
|
199
|
-
const ret = {
|
|
200
|
-
node: 'delta',
|
|
201
|
-
op,
|
|
202
|
-
units,
|
|
203
|
-
kids: {
|
|
204
|
-
base: (0, malloy_types_1.mkTemporal)(from, 'timestamp'),
|
|
205
|
-
delta: this.n(n),
|
|
206
|
-
},
|
|
207
|
-
};
|
|
208
|
-
return { ...ret, sql: this.d.sqlAlterTimeExpr(ret) };
|
|
209
|
-
}
|
|
210
|
-
dayofWeek(e) {
|
|
211
|
-
const t = {
|
|
212
|
-
node: 'extract',
|
|
213
|
-
e: (0, malloy_types_1.mkTemporal)(e, 'timestamp'),
|
|
214
|
-
units: 'day_of_week',
|
|
215
|
-
};
|
|
216
|
-
return { ...t, sql: this.d.sqlTimeExtractExpr({}, t) };
|
|
217
|
-
}
|
|
218
|
-
nowDot(units) {
|
|
219
|
-
const nowTruncExpr = {
|
|
220
|
-
node: 'trunc',
|
|
221
|
-
e: this.nowExpr(),
|
|
222
|
-
units,
|
|
223
|
-
};
|
|
224
|
-
return { ...nowTruncExpr, sql: this.d.sqlTruncExpr({}, nowTruncExpr) };
|
|
225
|
-
}
|
|
226
|
-
thisUnit(units) {
|
|
227
|
-
const thisUnit = this.nowDot(units);
|
|
228
|
-
const nextUnit = this.delta(thisUnit, '+', '1', units);
|
|
229
|
-
return { begin: thisUnit, end: nextUnit.sql };
|
|
230
|
-
}
|
|
231
|
-
lastUnit(units) {
|
|
232
|
-
const thisUnit = this.nowDot(units);
|
|
233
|
-
const lastUnit = this.delta(thisUnit, '-', '1', units);
|
|
234
|
-
return { begin: lastUnit, end: thisUnit.sql };
|
|
235
|
-
}
|
|
236
|
-
nextUnit(units) {
|
|
237
|
-
const thisUnit = this.nowDot(units);
|
|
238
|
-
const nextUnit = this.delta(thisUnit, '+', '1', units);
|
|
239
|
-
const next2Unit = this.delta(thisUnit, '+', '2', units);
|
|
240
|
-
return { begin: nextUnit, end: next2Unit.sql };
|
|
241
|
-
}
|
|
242
|
-
mod7(n) {
|
|
243
|
-
return this.d.hasModOperator ? `(${n})%7` : `MOD(${n},7)`;
|
|
244
|
-
}
|
|
245
|
-
moment(m) {
|
|
246
|
-
switch (m.moment) {
|
|
247
|
-
case 'now': {
|
|
248
|
-
const now = this.nowExpr();
|
|
249
|
-
return { begin: now, end: now.sql };
|
|
250
|
-
}
|
|
251
|
-
case 'literal':
|
|
252
|
-
return this.expandLiteral(m);
|
|
253
|
-
case 'ago':
|
|
254
|
-
case 'from_now': {
|
|
255
|
-
const nowTruncExpr = this.nowDot(m.units);
|
|
256
|
-
const nowTrunc = (0, malloy_types_1.mkTemporal)(nowTruncExpr, 'timestamp');
|
|
257
|
-
const beginExpr = this.delta(nowTrunc, m.moment === 'ago' ? '-' : '+', m.n, m.units);
|
|
258
|
-
// Now the end is one unit after that .. either n-1 units ago or n+1 units from now
|
|
259
|
-
if (m.moment === 'ago' && m.n === '1') {
|
|
260
|
-
return { begin: beginExpr, end: nowTruncExpr.sql };
|
|
261
|
-
}
|
|
262
|
-
const oneDifferent = Number(m.n) + (m.moment === 'ago' ? -1 : 1);
|
|
263
|
-
const endExpr = {
|
|
264
|
-
...beginExpr,
|
|
265
|
-
kids: { base: nowTrunc, delta: this.n(oneDifferent.toString()) },
|
|
266
|
-
};
|
|
267
|
-
return { begin: beginExpr, end: this.d.sqlAlterTimeExpr(endExpr) };
|
|
268
|
-
}
|
|
269
|
-
case 'today':
|
|
270
|
-
return this.thisUnit('day');
|
|
271
|
-
case 'yesterday':
|
|
272
|
-
return this.lastUnit('day');
|
|
273
|
-
case 'tomorrow':
|
|
274
|
-
return this.nextUnit('day');
|
|
275
|
-
case 'this':
|
|
276
|
-
return this.thisUnit(m.units);
|
|
277
|
-
case 'last':
|
|
278
|
-
return this.lastUnit(m.units);
|
|
279
|
-
case 'next':
|
|
280
|
-
return this.nextUnit(m.units);
|
|
281
|
-
case 'monday':
|
|
282
|
-
case 'tuesday':
|
|
283
|
-
case 'wednesday':
|
|
284
|
-
case 'thursday':
|
|
285
|
-
case 'friday':
|
|
286
|
-
case 'saturday':
|
|
287
|
-
case 'sunday': {
|
|
288
|
-
const destDay = [
|
|
289
|
-
'sunday',
|
|
290
|
-
'monday',
|
|
291
|
-
'tuesday',
|
|
292
|
-
'wednesday',
|
|
293
|
-
'thursday',
|
|
294
|
-
'friday',
|
|
295
|
-
'saturday',
|
|
296
|
-
].indexOf(m.moment);
|
|
297
|
-
const dow = this.dayofWeek(this.nowExpr()).sql;
|
|
298
|
-
if (m.which === 'next') {
|
|
299
|
-
const nForwards = `${this.mod7(`${destDay}-(${dow}-1)+6`)}+1`;
|
|
300
|
-
const begin = this.delta(this.thisUnit('day').begin, '+', nForwards, 'day');
|
|
301
|
-
const end = this.delta(this.thisUnit('day').begin, '+', `${nForwards}+1`, 'day');
|
|
302
|
-
// console.log(
|
|
303
|
-
// `SELECT ${
|
|
304
|
-
// this.nowExpr().sql
|
|
305
|
-
// } as now,\n ${destDay} as destDay,\n ${dow} as dow,\n ${nForwards} as nForwards,\n ${
|
|
306
|
-
// begin.sql
|
|
307
|
-
// } as begin,\n ${end.sql} as end`
|
|
308
|
-
// );
|
|
309
|
-
return { begin, end: end.sql };
|
|
310
|
-
}
|
|
311
|
-
// dacks back = mod((daw0 - dst) + 6, 7) + 1;
|
|
312
|
-
// dacks back = mod(((daw - 1) - dst) + 6, 7) + 1;
|
|
313
|
-
// dacks back = mod(((daw) - dst) + 7, 7) + 1;
|
|
314
|
-
const nBack = `${this.mod7(`(${dow}-1)-${destDay}+6`)}+1`;
|
|
315
|
-
const begin = this.delta(this.thisUnit('day').begin, '-', nBack, 'day');
|
|
316
|
-
const end = this.delta(this.thisUnit('day').begin, '-', `(${nBack})-1`, 'day');
|
|
317
|
-
// console.log(
|
|
318
|
-
// `SELECT ${
|
|
319
|
-
// this.nowExpr().sql
|
|
320
|
-
// } as now,\n ${destDay} as destDay,\n ${dow} as dow,\n ${nBack} as nBack,\n ${
|
|
321
|
-
// begin.sql
|
|
322
|
-
// } as begin,\n ${end.sql} as end`
|
|
323
|
-
// );
|
|
324
|
-
return { begin, end: end.sql };
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
isIn(notIn, begin, end) {
|
|
329
|
-
let begOp = '>=';
|
|
330
|
-
let endOp = '<';
|
|
331
|
-
let joinOp = 'AND';
|
|
332
|
-
if (notIn) {
|
|
333
|
-
joinOp = 'OR';
|
|
334
|
-
begOp = '<';
|
|
335
|
-
endOp = '>=';
|
|
336
|
-
}
|
|
337
|
-
begin = this.time(begin);
|
|
338
|
-
end = this.time(end);
|
|
339
|
-
return `${this.expr} ${begOp} ${begin} ${joinOp} ${this.expr} ${endOp} ${end}`;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
exports.TemporalFilterCompiler = TemporalFilterCompiler;
|
|
343
|
-
//# sourceMappingURL=filter_temporal_compiler.js.map
|