@malloydata/malloy 0.0.2 → 0.0.4

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 (67) hide show
  1. package/README.md +12 -11
  2. package/dist/dialect/duckdb.d.ts +1 -1
  3. package/dist/dialect/postgres.d.ts +1 -1
  4. package/dist/index.d.ts +4 -4
  5. package/dist/lang/ast/ast-expr.d.ts +0 -1
  6. package/dist/lang/field-space.d.ts +9 -7
  7. package/dist/lang/lib/Malloy/MalloyLexer.d.ts +108 -106
  8. package/dist/lang/lib/Malloy/MalloyLexer.js +1019 -1006
  9. package/dist/lang/lib/Malloy/MalloyParser.d.ts +581 -590
  10. package/dist/lang/lib/Malloy/MalloyParser.js +1141 -1202
  11. package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +2015 -0
  12. package/dist/lang/lib/Malloy/MalloyParserListener.js +4 -0
  13. package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +1269 -0
  14. package/dist/lang/lib/Malloy/MalloyParserVisitor.js +4 -0
  15. package/dist/lang/parse-to-ast.d.ts +3 -4
  16. package/dist/lang/parse-to-ast.js +1 -1
  17. package/dist/lang/parse-tree-walkers/document-completion-walker.js +2 -0
  18. package/dist/lang/parse-tree-walkers/explore-query-walker.d.ts +2 -2
  19. package/dist/malloy.d.ts +1 -1
  20. package/dist/md5.d.ts +1 -0
  21. package/dist/md5.js +30 -0
  22. package/dist/model/malloy_types.d.ts +3 -1
  23. package/package.json +9 -14
  24. package/dist/connection_utils.js +0 -56
  25. package/dist/dialect/dialect-map.d.ts +0 -3
  26. package/dist/dialect/dialect-map.js +0 -33
  27. package/dist/dialect/dialect.js +0 -77
  28. package/dist/dialect/dialect_map.js +0 -35
  29. package/dist/dialect/duckdb.js +0 -349
  30. package/dist/dialect/index.js +0 -27
  31. package/dist/dialect/postgres.js +0 -308
  32. package/dist/dialect/standardsql.js +0 -361
  33. package/dist/index.js +0 -47
  34. package/dist/lang/ast/apply-expr.js +0 -231
  35. package/dist/lang/ast/ast-expr.js +0 -1051
  36. package/dist/lang/ast/ast-main.js +0 -2086
  37. package/dist/lang/ast/ast-time-expr.js +0 -549
  38. package/dist/lang/ast/ast-types.js +0 -215
  39. package/dist/lang/ast/index.js +0 -34
  40. package/dist/lang/ast/time-utils.js +0 -94
  41. package/dist/lang/field-space.js +0 -629
  42. package/dist/lang/field-utils.js +0 -33
  43. package/dist/lang/index.js +0 -22
  44. package/dist/lang/parse-log.js +0 -41
  45. package/dist/lang/reference-list.js +0 -80
  46. package/dist/lang/space-field.js +0 -346
  47. package/dist/lang/test/document-help-context-walker.spec.js +0 -45
  48. package/dist/lang/test/document-symbol-walker.spec.js +0 -100
  49. package/dist/lang/test/field-symbols.spec.js +0 -172
  50. package/dist/lang/test/parse.spec.js +0 -1936
  51. package/dist/lang/test/test-translator.js +0 -334
  52. package/dist/lang/zone.js +0 -97
  53. package/dist/malloy.js +0 -2354
  54. package/dist/model/index.js +0 -34
  55. package/dist/model/malloy-query.d.ts +0 -313
  56. package/dist/model/malloy-query.js +0 -2603
  57. package/dist/model/malloy-types.d.ts +0 -404
  58. package/dist/model/malloy-types.js +0 -242
  59. package/dist/model/malloy_query.js +0 -2996
  60. package/dist/model/malloy_types.js +0 -283
  61. package/dist/model/sql-block.d.ts +0 -11
  62. package/dist/model/sql-block.js +0 -38
  63. package/dist/model/sql_block.js +0 -41
  64. package/dist/model/utils.js +0 -84
  65. package/dist/runtime-types.d.ts +0 -116
  66. package/dist/runtime-types.js +0 -40
  67. package/dist/runtime_types.js +0 -15
@@ -1,361 +0,0 @@
1
- "use strict";
2
- /*
3
- * Copyright 2021 Google LLC
4
- *
5
- * This program is free software; you can redistribute it and/or
6
- * modify it under the terms of the GNU General Public License
7
- * version 2 as published by the Free Software Foundation.
8
- *
9
- * This program is distributed in the hope that it will be useful,
10
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- * GNU General Public License for more details.
13
- */
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.StandardSQLDialect = void 0;
16
- const utils_1 = require("../model/utils");
17
- const model_1 = require("../model");
18
- const dialect_1 = require("./dialect");
19
- const castMap = {
20
- number: "float64",
21
- };
22
- // These are the units that "TIMESTAMP_ADD" accepts
23
- const timestampAddUnits = [
24
- "microsecond",
25
- "millisecond",
26
- "second",
27
- "minute",
28
- "hour",
29
- "day",
30
- ];
31
- const extractMap = {
32
- day_of_week: "dayofweek",
33
- day_of_year: "dayofyear",
34
- };
35
- class StandardSQLDialect extends dialect_1.Dialect {
36
- constructor() {
37
- super(...arguments);
38
- this.name = "standardsql";
39
- this.defaultNumberType = "FLOAT64";
40
- this.udfPrefix = "__udf";
41
- this.hasFinalStage = false;
42
- this.stringTypeName = "STRING";
43
- this.divisionIsInteger = false;
44
- this.supportsSumDistinctFunction = false;
45
- this.unnestWithNumbers = false;
46
- this.defaultSampling = { enable: false };
47
- this.supportUnnestArrayAgg = false;
48
- this.supportsCTEinCoorelatedSubQueries = false;
49
- this.functionInfo = {
50
- timestamp_seconds: { returnType: "timestamp" },
51
- };
52
- this.keywords = `
53
- ALL
54
- AND
55
- ANY
56
- ARRAY
57
- AS
58
- ASC
59
- ASSERT_ROWS_MODIFIED
60
- AT
61
- BETWEEN
62
- BY
63
- CASE
64
- CAST
65
- COLLATE
66
- CONTAINS
67
- CREATE
68
- CROSS
69
- CUBE
70
- CURRENT
71
- DEFAULT
72
- DEFINE
73
- DESC
74
- DISTINCT
75
- ELSE
76
- END
77
- ENUM
78
- ESCAPE
79
- EXCEPT
80
- EXCLUDE
81
- EXISTS
82
- EXTRACT
83
- FALSE
84
- FETCH
85
- FOLLOWING
86
- FOR
87
- FROM
88
- FULL
89
- GROUP
90
- GROUPING
91
- GROUPS
92
- HASH
93
- HAVING
94
- IF
95
- IGNORE
96
- IN
97
- INNER
98
- INTERSECT
99
- INTERVAL
100
- INTO
101
- IS
102
- JOIN
103
- LATERAL
104
- LEFT
105
- LIKE
106
- LIMIT
107
- LOOKUP
108
- MERGE
109
- NATURAL
110
- NEW
111
- NO
112
- NOT
113
- NULL
114
- NULLS
115
- OF
116
- ON
117
- OR
118
- ORDER
119
- OUTER
120
- OVER
121
- PARTITION
122
- PRECEDING
123
- PROTO
124
- RANGE
125
- RECURSIVE
126
- RESPECT
127
- RIGHT
128
- ROLLUP
129
- ROWS
130
- SELECT
131
- SET
132
- SOME
133
- STRUCT
134
- TABLESAMPLE
135
- THEN
136
- TO
137
- TREAT
138
- TRUE
139
- UNBOUNDED
140
- UNION
141
- UNNEST
142
- USING
143
- WHEN
144
- WHERE
145
- WINDOW
146
- WITH
147
- WITHIN`.split(/\s/);
148
- }
149
- quoteTablePath(tablePath) {
150
- return `\`${tablePath}\``;
151
- }
152
- sqlGroupSetTable(groupSetCount) {
153
- return `CROSS JOIN (SELECT row_number() OVER() -1 group_set FROM UNNEST(GENERATE_ARRAY(0,${groupSetCount},1)))`;
154
- }
155
- sqlAnyValue(groupSet, fieldName) {
156
- return `ANY_VALUE(CASE WHEN group_set=${groupSet} THEN ${fieldName} END)`;
157
- }
158
- // can array agg or any_value a struct...
159
- sqlAggregateTurtle(groupSet, fieldList, orderBy, limit) {
160
- let tail = "";
161
- if (limit !== undefined) {
162
- tail += ` LIMIT ${limit}`;
163
- }
164
- const fields = fieldList
165
- .map((f) => `\n ${f.sqlExpression} as ${f.sqlOutputName}`)
166
- .join(", ");
167
- return `ARRAY_AGG(CASE WHEN group_set=${groupSet} THEN STRUCT(${fields}\n ) END IGNORE NULLS ${orderBy} ${tail})`;
168
- }
169
- sqlAnyValueTurtle(groupSet, fieldList) {
170
- const fields = fieldList
171
- .map((f) => `${f.sqlExpression} as ${f.sqlOutputName}`)
172
- .join(", ");
173
- return `ANY_VALUE(CASE WHEN group_set=${groupSet} THEN STRUCT(${fields}))`;
174
- }
175
- sqlAnyValueLastTurtle(name, groupSet, sqlName) {
176
- return `ANY_VALUE(CASE WHEN group_set=${groupSet} THEN ${name}__${groupSet} END) as ${sqlName}`;
177
- }
178
- sqlCoaleseMeasuresInline(groupSet, fieldList) {
179
- const fields = fieldList
180
- .map((f) => `${f.sqlExpression} as ${f.sqlOutputName}`)
181
- .join(", ");
182
- const nullValues = fieldList
183
- .map((f) => `NULL as ${f.sqlOutputName}`)
184
- .join(", ");
185
- return `COALESCE(ANY_VALUE(CASE WHEN group_set=${groupSet} THEN STRUCT(${fields}) END), STRUCT(${nullValues}))`;
186
- }
187
- //
188
- // this code used to be:
189
- //
190
- // from += `JOIN UNNEST(GENERATE_ARRAY(0,${this.maxGroupSet},1)) as group_set\n`;
191
- //
192
- // BigQuery will allocate more resources if we use a CROSS JOIN so we do that instead.
193
- //
194
- sqlUnnestAlias(source, alias, fieldList, needDistinctKey, isArray) {
195
- if (isArray) {
196
- if (needDistinctKey) {
197
- return `LEFT JOIN UNNEST(ARRAY(( SELECT AS STRUCT row_number() over() as __row_id, value FROM UNNEST(${source}) value))) as ${alias}`;
198
- }
199
- else {
200
- return `LEFT JOIN UNNEST(ARRAY((SELECT AS STRUCT value FROM unnest(${source}) value))) as ${alias}`;
201
- }
202
- }
203
- else if (needDistinctKey) {
204
- return `LEFT JOIN UNNEST(ARRAY(( SELECT AS STRUCT row_number() over() as __row_id, * FROM UNNEST(${source})))) as ${alias}`;
205
- }
206
- else {
207
- return `LEFT JOIN UNNEST(${source}) as ${alias}`;
208
- }
209
- }
210
- sqlSumDistinctHashedKey(sqlDistinctKey) {
211
- sqlDistinctKey = `CAST(${sqlDistinctKey} AS STRING)`;
212
- const upperPart = `cast(cast(concat('0x', substr(to_hex(md5(${sqlDistinctKey})), 1, 15)) as int64) as numeric) * 4294967296`;
213
- const lowerPart = `cast(cast(concat('0x', substr(to_hex(md5(${sqlDistinctKey})), 16, 8)) as int64) as numeric)`;
214
- // See the comment below on `sql_sum_distinct` for why we multiply by this decimal
215
- const precisionShiftMultiplier = "0.000000001";
216
- return `(${upperPart} + ${lowerPart}) * ${precisionShiftMultiplier}`;
217
- }
218
- sqlGenerateUUID() {
219
- return `GENERATE_UUID()`;
220
- }
221
- sqlFieldReference(alias, fieldName, _fieldType, _isNested, _isArray) {
222
- return `${alias}.${fieldName}`;
223
- }
224
- sqlUnnestPipelineHead(isSingleton, sourceSQLExpression) {
225
- let p = sourceSQLExpression;
226
- if (isSingleton) {
227
- p = `[${p}]`;
228
- }
229
- return `UNNEST(${p})`;
230
- }
231
- sqlCreateFunction(id, funcText) {
232
- return `CREATE TEMPORARY FUNCTION ${id}(__param ANY TYPE) AS ((\n${(0, utils_1.indent)(funcText)}));\n`;
233
- }
234
- sqlCreateTableAsSelect(tableName, sql) {
235
- return `
236
- CREATE TABLE IF NOT EXISTS \`${tableName}\`
237
- OPTIONS (
238
- expiration_timestamp=TIMESTAMP_ADD(current_timestamp(), INTERVAL 1 hour)
239
- )
240
- AS (
241
- ${(0, utils_1.indent)(sql)}
242
- );
243
- `;
244
- }
245
- sqlCreateFunctionCombineLastStage(lastStageName) {
246
- return `SELECT ARRAY((SELECT AS STRUCT * FROM ${lastStageName}))\n`;
247
- }
248
- sqlSelectAliasAsStruct(alias) {
249
- return `(SELECT AS STRUCT ${alias}.*)`;
250
- }
251
- sqlMaybeQuoteIdentifier(identifier) {
252
- return this.keywords.indexOf(identifier.toUpperCase()) > 0
253
- ? "`" + identifier + "`"
254
- : identifier;
255
- }
256
- sqlNow() {
257
- return (0, model_1.mkExpr) `CURRENT_TIMESTAMP()`;
258
- }
259
- sqlTrunc(sqlTime, units) {
260
- if (sqlTime.valueType == "date") {
261
- if ((0, model_1.isDateUnit)(units)) {
262
- return (0, model_1.mkExpr) `DATE_TRUNC(${sqlTime.value},${units})`;
263
- }
264
- return (0, model_1.mkExpr) `TIMESTAMP(${sqlTime.value})`;
265
- }
266
- return (0, model_1.mkExpr) `TIMESTAMP_TRUNC(${sqlTime.value},${units})`;
267
- }
268
- sqlExtract(expr, units) {
269
- const extractTo = extractMap[units] || units;
270
- return (0, model_1.mkExpr) `EXTRACT(${extractTo} FROM ${expr.value})`;
271
- }
272
- sqlAlterTime(op, expr, n, timeframe) {
273
- let theTime = expr.value;
274
- let computeType = expr.valueType;
275
- if (timeframe != "day" && timestampAddUnits.includes(timeframe)) {
276
- // The units must be done in timestamp, no matter the input type
277
- computeType = "timestamp";
278
- if (expr.valueType != "timestamp") {
279
- theTime = (0, model_1.mkExpr) `TIMESTAMP(${theTime})`;
280
- }
281
- }
282
- else if (expr.valueType == "timestamp") {
283
- theTime = (0, model_1.mkExpr) `DATETIME(${theTime})`;
284
- computeType = "datetime";
285
- }
286
- const funcName = computeType.toUpperCase() + (op == "+" ? "_ADD" : "_SUB");
287
- const newTime = (0, model_1.mkExpr) `${funcName}(${theTime}, INTERVAL ${n} ${timeframe})`;
288
- return computeType == "datetime" ? (0, model_1.mkExpr) `TIMESTAMP(${newTime})` : newTime;
289
- }
290
- ignoreInProject(fieldName) {
291
- return fieldName === "_PARTITIONTIME";
292
- }
293
- sqlCast(cast) {
294
- if (cast.srcType !== cast.dstType) {
295
- const dstType = castMap[cast.dstType] || cast.dstType;
296
- // This just makes the code look a little prettier ...
297
- if (!cast.safe && cast.srcType && (0, model_1.isTimeFieldType)(cast.srcType)) {
298
- if (dstType == "date") {
299
- return (0, model_1.mkExpr) `DATE(${cast.expr})`;
300
- }
301
- return (0, model_1.mkExpr) `TIMESTAMP(${cast.expr})`;
302
- }
303
- const castFunc = cast.safe ? "SAFE_CAST" : "CAST";
304
- return (0, model_1.mkExpr) `${castFunc}(${cast.expr} AS ${dstType})`;
305
- }
306
- return cast.expr;
307
- }
308
- sqlRegexpMatch(expr, regexp) {
309
- return (0, model_1.mkExpr) `REGEXP_CONTAINS(${expr}, r${regexp})`;
310
- }
311
- sqlLiteralTime(timeString, type, timezone) {
312
- if (type === "date") {
313
- return `DATE('${timeString}')`;
314
- }
315
- else if (type === "timestamp") {
316
- return `TIMESTAMP('${timeString}', '${timezone}')`;
317
- }
318
- else {
319
- throw new Error(`Unknown Liternal time format ${type}`);
320
- }
321
- }
322
- sqlMeasureTime(from, to, units) {
323
- let lVal = from.value;
324
- let rVal = to.value;
325
- let diffUsing = "TIMESTAMP_DIFF";
326
- if (units == "second" || units == "minute" || units == "hour") {
327
- if (from.valueType != "timestamp") {
328
- lVal = (0, model_1.mkExpr) `TIMESTAMP(${lVal})`;
329
- }
330
- if (to.valueType != "timestamp") {
331
- rVal = (0, model_1.mkExpr) `TIMESTAMP(${rVal})`;
332
- }
333
- }
334
- else {
335
- diffUsing = "DATE_DIFF";
336
- if (from.valueType != "date") {
337
- lVal = (0, model_1.mkExpr) `DATE(${lVal})`;
338
- }
339
- if (to.valueType != "date") {
340
- rVal = (0, model_1.mkExpr) `DATE(${rVal})`;
341
- }
342
- }
343
- return (0, model_1.mkExpr) `${diffUsing}(${rVal}, ${lVal}, ${units})`;
344
- }
345
- sqlSampleTable(tableSQL, sample) {
346
- if (sample !== undefined) {
347
- if ((0, model_1.isSamplingEnable)(sample) && sample.enable) {
348
- sample = this.defaultSampling;
349
- }
350
- if ((0, model_1.isSamplingRows)(sample)) {
351
- throw new Error(`StandardSQL doesn't support sampling by rows only percent`);
352
- }
353
- else if ((0, model_1.isSamplingPercent)(sample)) {
354
- return `(SELECT * FROM ${tableSQL} TABLESAMPLE SYSTEM (${sample.percent} PERCENT))`;
355
- }
356
- }
357
- return tableSQL;
358
- }
359
- }
360
- exports.StandardSQLDialect = StandardSQLDialect;
361
- //# sourceMappingURL=standardsql.js.map
package/dist/index.js DELETED
@@ -1,47 +0,0 @@
1
- "use strict";
2
- /*
3
- * Copyright 2022 Google LLC
4
- *
5
- * This program is free software; you can redistribute it and/or
6
- * modify it under the terms of the GNU General Public License
7
- * version 2 as published by the Free Software Foundation.
8
- *
9
- * This program is distributed in the hope that it will be useful,
10
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- * GNU General Public License for more details.
13
- */
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.toAsyncGenerator = exports.DataWriter = exports.JSONWriter = exports.CSVWriter = exports.QueryMaterializer = exports.parseTableURL = exports.Result = exports.TimestampTimeframe = exports.DateTimeframe = exports.SourceRelationship = exports.JoinRelationship = exports.MalloyError = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.AtomicFieldType = exports.Runtime = exports.Malloy = exports.MalloyTranslator = exports.HighlightType = exports.isFilteredAliasedName = exports.Segment = void 0;
16
- var model_1 = require("./model");
17
- // Used in Composer Demo
18
- Object.defineProperty(exports, "Segment", { enumerable: true, get: function () { return model_1.Segment; } });
19
- Object.defineProperty(exports, "isFilteredAliasedName", { enumerable: true, get: function () { return model_1.isFilteredAliasedName; } });
20
- var lang_1 = require("./lang");
21
- // Neede for VSCode extension
22
- Object.defineProperty(exports, "HighlightType", { enumerable: true, get: function () { return lang_1.HighlightType; } });
23
- // Needed for tests only
24
- Object.defineProperty(exports, "MalloyTranslator", { enumerable: true, get: function () { return lang_1.MalloyTranslator; } });
25
- var malloy_1 = require("./malloy");
26
- Object.defineProperty(exports, "Malloy", { enumerable: true, get: function () { return malloy_1.Malloy; } });
27
- Object.defineProperty(exports, "Runtime", { enumerable: true, get: function () { return malloy_1.Runtime; } });
28
- Object.defineProperty(exports, "AtomicFieldType", { enumerable: true, get: function () { return malloy_1.AtomicFieldType; } });
29
- Object.defineProperty(exports, "ConnectionRuntime", { enumerable: true, get: function () { return malloy_1.ConnectionRuntime; } });
30
- Object.defineProperty(exports, "SingleConnectionRuntime", { enumerable: true, get: function () { return malloy_1.SingleConnectionRuntime; } });
31
- Object.defineProperty(exports, "EmptyURLReader", { enumerable: true, get: function () { return malloy_1.EmptyURLReader; } });
32
- Object.defineProperty(exports, "InMemoryURLReader", { enumerable: true, get: function () { return malloy_1.InMemoryURLReader; } });
33
- Object.defineProperty(exports, "FixedConnectionMap", { enumerable: true, get: function () { return malloy_1.FixedConnectionMap; } });
34
- Object.defineProperty(exports, "MalloyError", { enumerable: true, get: function () { return malloy_1.MalloyError; } });
35
- Object.defineProperty(exports, "JoinRelationship", { enumerable: true, get: function () { return malloy_1.JoinRelationship; } });
36
- Object.defineProperty(exports, "SourceRelationship", { enumerable: true, get: function () { return malloy_1.SourceRelationship; } });
37
- Object.defineProperty(exports, "DateTimeframe", { enumerable: true, get: function () { return malloy_1.DateTimeframe; } });
38
- Object.defineProperty(exports, "TimestampTimeframe", { enumerable: true, get: function () { return malloy_1.TimestampTimeframe; } });
39
- Object.defineProperty(exports, "Result", { enumerable: true, get: function () { return malloy_1.Result; } });
40
- Object.defineProperty(exports, "parseTableURL", { enumerable: true, get: function () { return malloy_1.parseTableURL; } });
41
- Object.defineProperty(exports, "QueryMaterializer", { enumerable: true, get: function () { return malloy_1.QueryMaterializer; } });
42
- Object.defineProperty(exports, "CSVWriter", { enumerable: true, get: function () { return malloy_1.CSVWriter; } });
43
- Object.defineProperty(exports, "JSONWriter", { enumerable: true, get: function () { return malloy_1.JSONWriter; } });
44
- Object.defineProperty(exports, "DataWriter", { enumerable: true, get: function () { return malloy_1.DataWriter; } });
45
- var connection_utils_1 = require("./connection_utils");
46
- Object.defineProperty(exports, "toAsyncGenerator", { enumerable: true, get: function () { return connection_utils_1.toAsyncGenerator; } });
47
- //# sourceMappingURL=index.js.map
@@ -1,231 +0,0 @@
1
- "use strict";
2
- /*
3
- * Copyright 2021 Google LLC
4
- *
5
- * This program is free software; you can redistribute it and/or
6
- * modify it under the terms of the GNU General Public License
7
- * version 2 as published by the Free Software Foundation.
8
- *
9
- * This program is distributed in the hope that it will be useful,
10
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- * GNU General Public License for more details.
13
- */
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.nullsafeNot = exports.applyBinary = void 0;
16
- const malloy_types_1 = require("../../model/malloy_types");
17
- const index_1 = require("./index");
18
- /**
19
- * All of the magic of malloy expressions eventually flows to here,
20
- * where an operator is applied to two values. Depending on the
21
- * operator and value types this may involve transformations of
22
- * the values or even the operator.
23
- * @param fs FieldSpace for the symbols
24
- * @param left Left value
25
- * @param op The operator
26
- * @param right Right Value
27
- * @returns ExprValue of the expression
28
- */
29
- function applyBinary(fs, left, op, right) {
30
- if ((0, index_1.isEquality)(op)) {
31
- return equality(fs, left, op, right);
32
- }
33
- if ((0, index_1.isComparison)(op)) {
34
- return compare(fs, left, op, right);
35
- }
36
- if (oneOf(op, "+", "-")) {
37
- return delta(fs, left, op, right);
38
- }
39
- if (oneOf(op, "*")) {
40
- return numeric(fs, left, op, right);
41
- }
42
- if (oneOf(op, "/")) {
43
- const num = left.getExpression(fs);
44
- const denom = right.getExpression(fs);
45
- if (num.dataType != "number") {
46
- left.log("Numerator for division mus tbe a number");
47
- }
48
- else if (denom.dataType != "number") {
49
- right.log("Denominator for division mus tbe a number");
50
- }
51
- else {
52
- const div = {
53
- type: "dialect",
54
- function: "div",
55
- numerator: num.value,
56
- denominator: denom.value,
57
- };
58
- return {
59
- dataType: "number",
60
- aggregate: num.aggregate || denom.aggregate,
61
- value: [div],
62
- };
63
- }
64
- return (0, index_1.errorFor)("divide type mismatch");
65
- }
66
- left.log(`Canot use ${op} operator here`);
67
- return (0, index_1.errorFor)("applybinary bad operator");
68
- }
69
- exports.applyBinary = applyBinary;
70
- function oneOf(op, ...operators) {
71
- return operators.includes(op);
72
- }
73
- function allAre(oneType, ...values) {
74
- for (const v of values) {
75
- if (v.dataType !== oneType) {
76
- return false;
77
- }
78
- }
79
- return true;
80
- }
81
- function regexEqual(left, right) {
82
- if (left.dataType === "string") {
83
- if (right.dataType === "regular expression") {
84
- return [
85
- {
86
- type: "dialect",
87
- function: "regexpMatch",
88
- expr: left.value,
89
- regexp: right.value[0].replace(/^r'/, "'"),
90
- },
91
- ];
92
- }
93
- }
94
- else if (right.dataType === "string") {
95
- if (left.dataType === "regular expression") {
96
- return [
97
- {
98
- type: "dialect",
99
- function: "regexpMatch",
100
- expr: right.value,
101
- regexp: left.value[0].replace(/^r'/, "'"),
102
- },
103
- ];
104
- }
105
- }
106
- return undefined;
107
- }
108
- function nullCompare(left, op, right) {
109
- const not = op === "!=" || op === "!~";
110
- if (left.dataType === "null" || right.dataType === "null") {
111
- const maybeNot = not ? " NOT" : "";
112
- if (left.dataType !== "null") {
113
- return [...left.value, ` IS${maybeNot} NULL`];
114
- }
115
- if (right.dataType !== "null") {
116
- return [...right.value, `IS${maybeNot} NULL`];
117
- }
118
- return [not ? "false" : "true"];
119
- }
120
- return undefined;
121
- }
122
- function timeCompare(lhs, op, rhs) {
123
- if ((0, malloy_types_1.isTimeFieldType)(lhs.dataType) && (0, malloy_types_1.isTimeFieldType)(rhs.dataType)) {
124
- if (lhs.dataType !== rhs.dataType) {
125
- let lval = lhs.value;
126
- let rval = rhs.value;
127
- if (lhs.dataType === "timestamp") {
128
- lval = (0, index_1.castTimestampToDate)(lval);
129
- }
130
- else {
131
- rval = (0, index_1.castTimestampToDate)(rval);
132
- }
133
- return (0, index_1.compose)(lval, op, rval);
134
- }
135
- }
136
- return undefined;
137
- }
138
- function nullsafeNot(expr, op) {
139
- if (op === undefined || op === "!=" || op === "!~") {
140
- return (0, malloy_types_1.mkExpr) `COALESCE(NOT(${expr}),FALSE)`;
141
- }
142
- return expr;
143
- }
144
- exports.nullsafeNot = nullsafeNot;
145
- function equality(fs, left, op, right) {
146
- const lhs = left.getExpression(fs);
147
- const rhs = right.getExpression(fs);
148
- let value = timeCompare(lhs, op, rhs) || (0, index_1.compose)(lhs.value, op, rhs.value);
149
- if (lhs.dataType != "unknown" && rhs.dataType != "unknown") {
150
- switch (op) {
151
- case "~":
152
- case "!~": {
153
- if (lhs.dataType === "string" && rhs.dataType === "string") {
154
- value = (0, index_1.compose)(lhs.value, "LIKE", rhs.value);
155
- }
156
- else {
157
- const regexCmp = regexEqual(lhs, rhs);
158
- if (regexCmp === undefined) {
159
- throw new index_1.TypeMistmatch("Incompatible types for match('~') operator");
160
- }
161
- value = regexCmp;
162
- }
163
- value = nullsafeNot(value, op);
164
- break;
165
- }
166
- case "=":
167
- case "!=": {
168
- const nullCmp = nullCompare(lhs, op, rhs);
169
- if (nullCmp) {
170
- value = nullCmp;
171
- }
172
- else {
173
- value = nullsafeNot(regexEqual(lhs, rhs) || (0, index_1.compose)(lhs.value, "=", rhs.value), op);
174
- }
175
- break;
176
- }
177
- }
178
- }
179
- return {
180
- dataType: "boolean",
181
- aggregate: lhs.aggregate || rhs.aggregate,
182
- value,
183
- };
184
- }
185
- function compare(fs, left, op, right) {
186
- const lhs = left.getExpression(fs);
187
- const rhs = right.getExpression(fs);
188
- const anyAggregate = lhs.aggregate || rhs.aggregate;
189
- const value = timeCompare(lhs, op, rhs) || (0, index_1.compose)(lhs.value, op, rhs.value);
190
- return {
191
- dataType: "boolean",
192
- aggregate: anyAggregate,
193
- value: value,
194
- };
195
- }
196
- function numeric(fs, left, op, right) {
197
- const lhs = left.getExpression(fs);
198
- const rhs = right.getExpression(fs);
199
- const anyAggregate = lhs.aggregate || rhs.aggregate;
200
- if (allAre("number", lhs, rhs)) {
201
- return {
202
- dataType: "number",
203
- aggregate: anyAggregate,
204
- value: (0, index_1.compose)(lhs.value, op, rhs.value),
205
- };
206
- }
207
- left.log(`Non numeric('${lhs.dataType},${rhs.dataType}') value with '${op}'`);
208
- return (0, index_1.errorFor)("numbers required");
209
- }
210
- function delta(fs, left, op, right) {
211
- const lhs = left.getExpression(fs);
212
- const rhs = right.getExpression(fs);
213
- if ((0, malloy_types_1.isTimeFieldType)(lhs.dataType)) {
214
- let duration = right;
215
- if (rhs.dataType !== "duration") {
216
- if ((0, index_1.isGranularResult)(lhs)) {
217
- duration = new index_1.ExprDuration(right, lhs.timeframe);
218
- }
219
- else if (lhs.dataType === "date") {
220
- duration = new index_1.ExprDuration(right, "day");
221
- }
222
- else {
223
- left.log(`Can not offset time by '${rhs.dataType}'`);
224
- return (0, index_1.errorFor)(`time plus ${rhs.dataType}`);
225
- }
226
- }
227
- return duration.apply(fs, op, left);
228
- }
229
- return numeric(fs, left, op, right);
230
- }
231
- //# sourceMappingURL=apply-expr.js.map