@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.
Files changed (40) hide show
  1. package/dist/lang/ast/expressions/expr-filter-expr.d.ts +0 -3
  2. package/dist/lang/ast/expressions/expr-filter-expr.js +7 -59
  3. package/dist/lang/ast/expressions/expr-func.js +3 -0
  4. package/dist/lang/ast/expressions/pick-when.js +6 -0
  5. package/dist/lang/ast/field-space/dynamic-space.js +1 -1
  6. package/dist/lang/ast/field-space/join-space-field.js +1 -1
  7. package/dist/lang/ast/index.d.ts +1 -0
  8. package/dist/lang/ast/index.js +1 -0
  9. package/dist/lang/ast/parameters/has-parameter.d.ts +6 -3
  10. package/dist/lang/ast/parameters/has-parameter.js +28 -9
  11. package/dist/lang/ast/query-items/field-declaration.d.ts +1 -2
  12. package/dist/lang/ast/query-items/field-declaration.js +0 -4
  13. package/dist/lang/ast/source-elements/named-source.js +6 -0
  14. package/dist/lang/ast/source-properties/join.d.ts +3 -3
  15. package/dist/lang/ast/source-properties/join.js +2 -2
  16. package/dist/lang/ast/types/expression-def.d.ts +2 -1
  17. package/dist/lang/ast/types/expression-def.js +79 -17
  18. package/dist/lang/ast/types/space-param.d.ts +1 -3
  19. package/dist/lang/ast/types/space-param.js +8 -8
  20. package/dist/lang/lib/Malloy/MalloyLexer.d.ts +114 -113
  21. package/dist/lang/lib/Malloy/MalloyLexer.js +1272 -1266
  22. package/dist/lang/lib/Malloy/MalloyParser.d.ts +253 -239
  23. package/dist/lang/lib/Malloy/MalloyParser.js +2244 -2142
  24. package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +11 -0
  25. package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +7 -0
  26. package/dist/lang/malloy-to-ast.d.ts +1 -1
  27. package/dist/lang/malloy-to-ast.js +38 -12
  28. package/dist/lang/test/expr-to-str.js +3 -20
  29. package/dist/model/filter_compilers.d.ts +27 -0
  30. package/dist/model/filter_compilers.js +335 -3
  31. package/dist/model/malloy_query.d.ts +2 -1
  32. package/dist/model/malloy_query.js +45 -10
  33. package/dist/model/malloy_types.d.ts +18 -6
  34. package/dist/model/malloy_types.js +6 -2
  35. package/dist/to_stable.js +19 -5
  36. package/dist/version.d.ts +1 -1
  37. package/dist/version.js +1 -1
  38. package/package.json +4 -4
  39. package/dist/model/filter_temporal_compiler.d.ts +0 -29
  40. 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 ExprE {
178
+ export interface FilterMatchExpr extends ExprWithKids {
179
179
  node: 'filterMatch';
180
180
  dataType: FilterExprType;
181
181
  notMatch?: true;
182
- filter: {
183
- operator: string;
184
- } | null;
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 type Parameter = AtomicTypeDef & ParameterInfo;
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.sourceBase = 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.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 = 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
- name,
26
- type: typeDefToType(parameter),
27
- default_value: convertParameterDefaultValue(parameter.value),
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.262";
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.262';
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.262",
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.262",
45
- "@malloydata/malloy-interfaces": "^0.0.262",
46
- "@malloydata/malloy-tag": "^0.0.262",
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