@malloydata/malloy 0.0.3 → 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 (37) hide show
  1. package/dist/lang/ast/ast-expr.d.ts +0 -1
  2. package/dist/lang/ast/ast-main.d.ts +2 -2
  3. package/package.json +1 -1
  4. package/dist/connection_utils.js +0 -56
  5. package/dist/dialect/dialect.js +0 -77
  6. package/dist/dialect/dialect_map.js +0 -35
  7. package/dist/dialect/duckdb.js +0 -347
  8. package/dist/dialect/index.js +0 -27
  9. package/dist/dialect/postgres.js +0 -315
  10. package/dist/dialect/standardsql.js +0 -362
  11. package/dist/index.js +0 -47
  12. package/dist/lang/ast/apply-expr.js +0 -231
  13. package/dist/lang/ast/ast-expr.js +0 -1041
  14. package/dist/lang/ast/ast-main.js +0 -2087
  15. package/dist/lang/ast/ast-time-expr.js +0 -549
  16. package/dist/lang/ast/ast-types.js +0 -215
  17. package/dist/lang/ast/index.js +0 -34
  18. package/dist/lang/ast/time-utils.js +0 -94
  19. package/dist/lang/field-space.js +0 -631
  20. package/dist/lang/field-utils.js +0 -33
  21. package/dist/lang/index.js +0 -22
  22. package/dist/lang/parse-log.js +0 -41
  23. package/dist/lang/reference-list.js +0 -80
  24. package/dist/lang/space-field.js +0 -346
  25. package/dist/lang/test/document-help-context-walker.spec.js +0 -45
  26. package/dist/lang/test/document-symbol-walker.spec.js +0 -100
  27. package/dist/lang/test/field-symbols.spec.js +0 -172
  28. package/dist/lang/test/parse.spec.js +0 -1951
  29. package/dist/lang/test/test-translator.js +0 -334
  30. package/dist/lang/zone.js +0 -97
  31. package/dist/malloy.js +0 -2360
  32. package/dist/model/index.js +0 -34
  33. package/dist/model/malloy_query.js +0 -2994
  34. package/dist/model/malloy_types.js +0 -283
  35. package/dist/model/sql_block.js +0 -41
  36. package/dist/model/utils.js +0 -84
  37. package/dist/runtime_types.js +0 -15
@@ -1,315 +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.PostgresDialect = 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: "double precision",
21
- string: "varchar",
22
- };
23
- const pgExtractionMap = {
24
- day_of_week: "dow",
25
- day_of_year: "doy",
26
- };
27
- const pgMakeIntervalMap = {
28
- year: "years",
29
- month: "months",
30
- week: "weeks",
31
- day: "days",
32
- hour: "hours",
33
- minute: "mins",
34
- second: "secs",
35
- };
36
- const inSeconds = {
37
- second: 1,
38
- minute: 60,
39
- hour: 3600,
40
- };
41
- class PostgresDialect extends dialect_1.Dialect {
42
- constructor() {
43
- super(...arguments);
44
- this.name = "postgres";
45
- this.defaultNumberType = "DOUBLE PRECISION";
46
- this.udfPrefix = "pg_temp.__udf";
47
- this.hasFinalStage = true;
48
- this.stringTypeName = "VARCHAR";
49
- this.divisionIsInteger = true;
50
- this.supportsSumDistinctFunction = false;
51
- this.unnestWithNumbers = false;
52
- this.defaultSampling = { rows: 50000 };
53
- this.supportUnnestArrayAgg = true;
54
- this.supportsCTEinCoorelatedSubQueries = true;
55
- this.functionInfo = {
56
- concat: { returnType: "string" },
57
- };
58
- }
59
- quoteTablePath(tablePath) {
60
- return tablePath
61
- .split(".")
62
- .map((part) => `"${part}"`)
63
- .join(".");
64
- }
65
- sqlGroupSetTable(groupSetCount) {
66
- return `CROSS JOIN GENERATE_SERIES(0,${groupSetCount},1) as group_set`;
67
- }
68
- sqlAnyValue(groupSet, fieldName) {
69
- return `MAX(${fieldName})`;
70
- }
71
- mapFields(fieldList) {
72
- return fieldList
73
- .map((f) => `\n ${f.sqlExpression}${f.type == "number" ? `::${this.defaultNumberType}` : ""} as ${f.sqlOutputName}`
74
- //`${f.sqlExpression} ${f.type} as ${f.sqlOutputName}`
75
- )
76
- .join(", ");
77
- }
78
- sqlAggregateTurtle(groupSet, fieldList, orderBy, limit) {
79
- let tail = "";
80
- if (limit !== undefined) {
81
- tail += `[1:${limit}]`;
82
- }
83
- const fields = this.mapFields(fieldList);
84
- // return `(ARRAY_AGG((SELECT __x FROM (SELECT ${fields}) as __x) ${orderBy} ) FILTER (WHERE group_set=${groupSet}))${tail}`;
85
- return `COALESCE(TO_JSONB((ARRAY_AGG((SELECT TO_JSONB(__x) FROM (SELECT ${fields}\n ) as __x) ${orderBy} ) FILTER (WHERE group_set=${groupSet}))${tail}),'[]'::JSONB)`;
86
- }
87
- sqlAnyValueTurtle(groupSet, fieldList) {
88
- const fields = fieldList
89
- .map((f) => `${f.sqlExpression} as ${f.sqlOutputName}`)
90
- .join(", ");
91
- return `ANY_VALUE(CASE WHEN group_set=${groupSet} THEN STRUCT(${fields}))`;
92
- }
93
- sqlAnyValueLastTurtle(name, groupSet, sqlName) {
94
- return `(ARRAY_AGG(${name}__${groupSet}) FILTER (WHERE group_set=${groupSet} AND ${name}__${groupSet} IS NOT NULL))[1] as ${sqlName}`;
95
- }
96
- sqlCoaleseMeasuresInline(groupSet, fieldList) {
97
- const fields = this.mapFields(fieldList);
98
- return `TO_JSONB((ARRAY_AGG((SELECT __x FROM (SELECT ${fields}) as __x)) FILTER (WHERE group_set=${groupSet}))[1])`;
99
- }
100
- // UNNEST((select ARRAY((SELECT ROW(gen_random_uuid()::text, state, airport_count) FROM UNNEST(base.by_state) as by_state(state text, airport_count numeric, by_fac_type record[]))))) as by_state(__distinct_key text, state text, airport_count numeric)
101
- // sqlUnnestAlias(
102
- // source: string,
103
- // alias: string,
104
- // fieldList: DialectFieldList,
105
- // needDistinctKey: boolean
106
- // ): string {
107
- // const fields = [];
108
- // for (const f of fieldList) {
109
- // let t = undefined;
110
- // switch (f.type) {
111
- // case "string":
112
- // t = "text";
113
- // break;
114
- // case "number":
115
- // t = this.defaultNumberType;
116
- // break;
117
- // case "struct":
118
- // t = "record[]";
119
- // break;
120
- // }
121
- // fields.push(`${f.sqlOutputName} ${t || f.type}`);
122
- // }
123
- // if (needDistinctKey) {
124
- // return `UNNEST((select ARRAY((SELECT ROW(gen_random_uuid()::text, ${fieldList
125
- // .map((f) => f.sqlOutputName)
126
- // .join(", ")}) FROM UNNEST(${source}) as ${alias}(${fields.join(
127
- // ", "
128
- // )}))))) as ${alias}(__distinct_key text, ${fields.join(", ")})`;
129
- // } else {
130
- // return `UNNEST(${source}) as ${alias}(${fields.join(", ")})`;
131
- // }
132
- // }
133
- sqlUnnestAlias(source, alias, fieldList, needDistinctKey, isArray) {
134
- if (isArray) {
135
- if (needDistinctKey) {
136
- return `LEFT JOIN UNNEST(ARRAY((SELECT jsonb_build_object('__row_id', row_number() over (), 'value', v) FROM UNNEST(${source}) as v))) as ${alias} ON true`;
137
- }
138
- else {
139
- return `LEFT JOIN UNNEST(ARRAY((SELECT jsonb_build_object('value', v) FROM UNNEST(${source}) as v))) as ${alias} ON true`;
140
- }
141
- }
142
- else if (needDistinctKey) {
143
- // return `UNNEST(ARRAY(( SELECT AS STRUCT GENERATE_UUID() as __distinct_key, * FROM UNNEST(${source})))) as ${alias}`;
144
- return `LEFT JOIN UNNEST(ARRAY((SELECT jsonb_build_object('__row_number', row_number() over())|| __xx::jsonb as b FROM JSONB_ARRAY_ELEMENTS(${source}) __xx ))) as ${alias} ON true`;
145
- }
146
- else {
147
- // return `CROSS JOIN LATERAL JSONB_ARRAY_ELEMENTS(${source}) as ${alias}`;
148
- return `LEFT JOIN JSONB_ARRAY_ELEMENTS(${source}) as ${alias} ON true`;
149
- }
150
- }
151
- sqlSumDistinctHashedKey(sqlDistinctKey) {
152
- return `('x' || MD5(${sqlDistinctKey}::varchar))::bit(64)::bigint::DECIMAL(65,0) *18446744073709551616 + ('x' || SUBSTR(MD5(${sqlDistinctKey}::varchar),17))::bit(64)::bigint::DECIMAL(65,0)`;
153
- }
154
- sqlGenerateUUID() {
155
- return `GEN_RANDOM_UUID()`;
156
- }
157
- sqlFieldReference(alias, fieldName, fieldType, isNested, _isArray) {
158
- let ret = `${alias}->>'${fieldName}'`;
159
- if (isNested) {
160
- switch (fieldType) {
161
- case "string":
162
- break;
163
- case "number":
164
- ret = `(${ret})::double precision`;
165
- break;
166
- case "struct":
167
- ret = `(${ret})::jsonb`;
168
- break;
169
- }
170
- return ret;
171
- }
172
- else {
173
- return `${alias}."${fieldName}"`;
174
- }
175
- }
176
- sqlUnnestPipelineHead(isSingleton, sourceSQLExpression) {
177
- if (isSingleton) {
178
- return `UNNEST(ARRAY((SELECT ${sourceSQLExpression})))`;
179
- }
180
- else {
181
- return `JSONB_ARRAY_ELEMENTS(${sourceSQLExpression})`;
182
- }
183
- }
184
- sqlCreateFunction(id, funcText) {
185
- return `CREATE FUNCTION ${id}(JSONB) RETURNS JSONB AS $$\n${(0, utils_1.indent)(funcText)}\n$$ LANGUAGE SQL;\n`;
186
- }
187
- sqlCreateFunctionCombineLastStage(lastStageName) {
188
- return `SELECT JSONB_AGG(__stage0) FROM ${lastStageName}\n`;
189
- }
190
- sqlFinalStage(lastStageName, _fields) {
191
- return `SELECT row_to_json(finalStage) as row FROM ${lastStageName} AS finalStage`;
192
- }
193
- sqlSelectAliasAsStruct(alias) {
194
- return `ROW(${alias})`;
195
- }
196
- // TODO
197
- sqlMaybeQuoteIdentifier(identifier) {
198
- return `"${identifier}"`;
199
- }
200
- // The simple way to do this is to add a comment on the table
201
- // with the expiration time. https://www.postgresql.org/docs/current/sql-comment.html
202
- // and have a reaper that read comments.
203
- sqlCreateTableAsSelect(_tableName, _sql) {
204
- throw new Error("Not implemented Yet");
205
- }
206
- sqlNow() {
207
- return (0, model_1.mkExpr) `CURRENT_TIMESTAMP`;
208
- }
209
- sqlTrunc(sqlTime, units) {
210
- // adjusting for monday/sunday weeks
211
- const week = units == "week";
212
- const truncThis = week
213
- ? (0, model_1.mkExpr) `${sqlTime.value}+interval'1'day`
214
- : sqlTime.value;
215
- const trunced = (0, model_1.mkExpr) `DATE_TRUNC('${units}', ${truncThis})`;
216
- return week ? (0, model_1.mkExpr) `(${trunced}-interval'1'day)` : trunced;
217
- }
218
- sqlExtract(from, units) {
219
- const pgUnits = pgExtractionMap[units] || units;
220
- const extracted = (0, model_1.mkExpr) `EXTRACT(${pgUnits} FROM ${from.value})`;
221
- return units == "day_of_week" ? (0, model_1.mkExpr) `(${extracted}+1)` : extracted;
222
- }
223
- sqlAlterTime(op, expr, n, timeframe) {
224
- if (timeframe == "quarter") {
225
- timeframe = "month";
226
- n = (0, model_1.mkExpr) `${n}*3`;
227
- }
228
- const interval = (0, model_1.mkExpr) `make_interval(${pgMakeIntervalMap[timeframe]}=>${n})`;
229
- return (0, model_1.mkExpr) `((${expr.value})${op}${interval})`;
230
- }
231
- sqlCast(cast) {
232
- if (cast.dstType !== cast.srcType) {
233
- const castTo = castMap[cast.dstType] || cast.dstType;
234
- return (0, model_1.mkExpr) `cast(${cast.expr} as ${castTo})`;
235
- }
236
- return cast.expr;
237
- }
238
- sqlRegexpMatch(expr, regexp) {
239
- return (0, model_1.mkExpr) `(${expr} ~ ${regexp})`;
240
- }
241
- sqlLiteralTime(timeString, type, _timezone) {
242
- if (type == "date") {
243
- return `DATE('${timeString}')`;
244
- }
245
- else if (type == "timestamp") {
246
- return `TIMESTAMP '${timeString}'`;
247
- }
248
- else {
249
- throw new Error(`Unknown Literal time format ${type}`);
250
- }
251
- }
252
- getFunctionInfo(functionName) {
253
- return this.functionInfo[functionName];
254
- }
255
- sqlMeasureTime(from, to, units) {
256
- let lVal = from.value;
257
- let rVal = to.value;
258
- if (inSeconds[units]) {
259
- lVal = (0, model_1.mkExpr) `EXTRACT(EPOCH FROM ${lVal})`;
260
- rVal = (0, model_1.mkExpr) `EXTRACT(EPOCH FROM ${rVal})`;
261
- const duration = (0, model_1.mkExpr) `(${rVal} - ${lVal})`;
262
- return units == "second"
263
- ? duration
264
- : (0, model_1.mkExpr) `TRUNC(${duration}/${inSeconds[units].toString()})`;
265
- }
266
- if (units === "day") {
267
- return (0, model_1.mkExpr) `${rVal}::date - ${lVal}::date`;
268
- }
269
- const yearDiff = (0, model_1.mkExpr) `(DATE_PART('year', ${rVal}) - DATE_PART('year', ${lVal}))`;
270
- if (units == "year") {
271
- return yearDiff;
272
- }
273
- if (units == "week") {
274
- const dayDiffForWeekStart = (0, model_1.mkExpr) `(DATE_TRUNC('week', ${rVal} + '1 day'::interval)::date - DATE_TRUNC('week', ${lVal} + '1 day'::interval)::date)`;
275
- return (0, model_1.mkExpr) `${dayDiffForWeekStart} / 7`;
276
- }
277
- if (units == "month") {
278
- const monthDiff = (0, model_1.mkExpr) `DATE_PART('month', ${rVal}) - DATE_PART('month', ${lVal})`;
279
- return (0, model_1.mkExpr) `${yearDiff} * 12 + ${monthDiff}`;
280
- }
281
- if (units == "quarter") {
282
- const qDiff = (0, model_1.mkExpr) `DATE_PART('quarter', ${rVal}) - DATE_PART('quarter', ${lVal})`;
283
- return (0, model_1.mkExpr) `${yearDiff} * 4 + ${qDiff}`;
284
- }
285
- throw new Error(`Unknown or unhandled postgres time unit: ${units}`);
286
- }
287
- sqlSumDistinct(key, value) {
288
- // return `sum_distinct(list({key:${key}, val: ${value}}))`;
289
- return `(
290
- SELECT sum((a::json->>'f2')::DOUBLE PRECISION) as value
291
- FROM (
292
- SELECT UNNEST(array_agg(distinct row_to_json(row(${key},${value}))::text)) a
293
- ) a
294
- )`;
295
- }
296
- sqlSampleTable(tableSQL, sample) {
297
- if (sample !== undefined) {
298
- if ((0, model_1.isSamplingEnable)(sample) && sample.enable) {
299
- sample = this.defaultSampling;
300
- }
301
- if ((0, model_1.isSamplingRows)(sample)) {
302
- return `(SELECT * FROM ${tableSQL} TABLESAMPLE SYSTEM_ROWS(${sample.rows}))`;
303
- }
304
- else if ((0, model_1.isSamplingPercent)(sample)) {
305
- return `(SELECT * FROM ${tableSQL} TABLESAMPLE SYSTEM (${sample.percent}))`;
306
- }
307
- }
308
- return tableSQL;
309
- }
310
- sqlOrderBy(orderTerms) {
311
- return `ORDER BY ${orderTerms.map((t) => `${t} NULLS LAST`).join(",")}`;
312
- }
313
- }
314
- exports.PostgresDialect = PostgresDialect;
315
- //# sourceMappingURL=postgres.js.map
@@ -1,362 +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
- concat: { returnType: "string" },
52
- };
53
- this.keywords = `
54
- ALL
55
- AND
56
- ANY
57
- ARRAY
58
- AS
59
- ASC
60
- ASSERT_ROWS_MODIFIED
61
- AT
62
- BETWEEN
63
- BY
64
- CASE
65
- CAST
66
- COLLATE
67
- CONTAINS
68
- CREATE
69
- CROSS
70
- CUBE
71
- CURRENT
72
- DEFAULT
73
- DEFINE
74
- DESC
75
- DISTINCT
76
- ELSE
77
- END
78
- ENUM
79
- ESCAPE
80
- EXCEPT
81
- EXCLUDE
82
- EXISTS
83
- EXTRACT
84
- FALSE
85
- FETCH
86
- FOLLOWING
87
- FOR
88
- FROM
89
- FULL
90
- GROUP
91
- GROUPING
92
- GROUPS
93
- HASH
94
- HAVING
95
- IF
96
- IGNORE
97
- IN
98
- INNER
99
- INTERSECT
100
- INTERVAL
101
- INTO
102
- IS
103
- JOIN
104
- LATERAL
105
- LEFT
106
- LIKE
107
- LIMIT
108
- LOOKUP
109
- MERGE
110
- NATURAL
111
- NEW
112
- NO
113
- NOT
114
- NULL
115
- NULLS
116
- OF
117
- ON
118
- OR
119
- ORDER
120
- OUTER
121
- OVER
122
- PARTITION
123
- PRECEDING
124
- PROTO
125
- RANGE
126
- RECURSIVE
127
- RESPECT
128
- RIGHT
129
- ROLLUP
130
- ROWS
131
- SELECT
132
- SET
133
- SOME
134
- STRUCT
135
- TABLESAMPLE
136
- THEN
137
- TO
138
- TREAT
139
- TRUE
140
- UNBOUNDED
141
- UNION
142
- UNNEST
143
- USING
144
- WHEN
145
- WHERE
146
- WINDOW
147
- WITH
148
- WITHIN`.split(/\s/);
149
- }
150
- quoteTablePath(tablePath) {
151
- return `\`${tablePath}\``;
152
- }
153
- sqlGroupSetTable(groupSetCount) {
154
- return `CROSS JOIN (SELECT row_number() OVER() -1 group_set FROM UNNEST(GENERATE_ARRAY(0,${groupSetCount},1)))`;
155
- }
156
- sqlAnyValue(groupSet, fieldName) {
157
- return `ANY_VALUE(CASE WHEN group_set=${groupSet} THEN ${fieldName} END)`;
158
- }
159
- // can array agg or any_value a struct...
160
- sqlAggregateTurtle(groupSet, fieldList, orderBy, limit) {
161
- let tail = "";
162
- if (limit !== undefined) {
163
- tail += ` LIMIT ${limit}`;
164
- }
165
- const fields = fieldList
166
- .map((f) => `\n ${f.sqlExpression} as ${f.sqlOutputName}`)
167
- .join(", ");
168
- return `ARRAY_AGG(CASE WHEN group_set=${groupSet} THEN STRUCT(${fields}\n ) END IGNORE NULLS ${orderBy} ${tail})`;
169
- }
170
- sqlAnyValueTurtle(groupSet, fieldList) {
171
- const fields = fieldList
172
- .map((f) => `${f.sqlExpression} as ${f.sqlOutputName}`)
173
- .join(", ");
174
- return `ANY_VALUE(CASE WHEN group_set=${groupSet} THEN STRUCT(${fields}))`;
175
- }
176
- sqlAnyValueLastTurtle(name, groupSet, sqlName) {
177
- return `ANY_VALUE(CASE WHEN group_set=${groupSet} THEN ${name}__${groupSet} END) as ${sqlName}`;
178
- }
179
- sqlCoaleseMeasuresInline(groupSet, fieldList) {
180
- const fields = fieldList
181
- .map((f) => `${f.sqlExpression} as ${f.sqlOutputName}`)
182
- .join(", ");
183
- const nullValues = fieldList
184
- .map((f) => `NULL as ${f.sqlOutputName}`)
185
- .join(", ");
186
- return `COALESCE(ANY_VALUE(CASE WHEN group_set=${groupSet} THEN STRUCT(${fields}) END), STRUCT(${nullValues}))`;
187
- }
188
- //
189
- // this code used to be:
190
- //
191
- // from += `JOIN UNNEST(GENERATE_ARRAY(0,${this.maxGroupSet},1)) as group_set\n`;
192
- //
193
- // BigQuery will allocate more resources if we use a CROSS JOIN so we do that instead.
194
- //
195
- sqlUnnestAlias(source, alias, fieldList, needDistinctKey, isArray) {
196
- if (isArray) {
197
- if (needDistinctKey) {
198
- return `LEFT JOIN UNNEST(ARRAY(( SELECT AS STRUCT row_number() over() as __row_id, value FROM UNNEST(${source}) value))) as ${alias}`;
199
- }
200
- else {
201
- return `LEFT JOIN UNNEST(ARRAY((SELECT AS STRUCT value FROM unnest(${source}) value))) as ${alias}`;
202
- }
203
- }
204
- else if (needDistinctKey) {
205
- return `LEFT JOIN UNNEST(ARRAY(( SELECT AS STRUCT row_number() over() as __row_id, * FROM UNNEST(${source})))) as ${alias}`;
206
- }
207
- else {
208
- return `LEFT JOIN UNNEST(${source}) as ${alias}`;
209
- }
210
- }
211
- sqlSumDistinctHashedKey(sqlDistinctKey) {
212
- sqlDistinctKey = `CAST(${sqlDistinctKey} AS STRING)`;
213
- const upperPart = `cast(cast(concat('0x', substr(to_hex(md5(${sqlDistinctKey})), 1, 15)) as int64) as numeric) * 4294967296`;
214
- const lowerPart = `cast(cast(concat('0x', substr(to_hex(md5(${sqlDistinctKey})), 16, 8)) as int64) as numeric)`;
215
- // See the comment below on `sql_sum_distinct` for why we multiply by this decimal
216
- const precisionShiftMultiplier = "0.000000001";
217
- return `(${upperPart} + ${lowerPart}) * ${precisionShiftMultiplier}`;
218
- }
219
- sqlGenerateUUID() {
220
- return `GENERATE_UUID()`;
221
- }
222
- sqlFieldReference(alias, fieldName, _fieldType, _isNested, _isArray) {
223
- return `${alias}.${fieldName}`;
224
- }
225
- sqlUnnestPipelineHead(isSingleton, sourceSQLExpression) {
226
- let p = sourceSQLExpression;
227
- if (isSingleton) {
228
- p = `[${p}]`;
229
- }
230
- return `UNNEST(${p})`;
231
- }
232
- sqlCreateFunction(id, funcText) {
233
- return `CREATE TEMPORARY FUNCTION ${id}(__param ANY TYPE) AS ((\n${(0, utils_1.indent)(funcText)}));\n`;
234
- }
235
- sqlCreateTableAsSelect(tableName, sql) {
236
- return `
237
- CREATE TABLE IF NOT EXISTS \`${tableName}\`
238
- OPTIONS (
239
- expiration_timestamp=TIMESTAMP_ADD(current_timestamp(), INTERVAL 1 hour)
240
- )
241
- AS (
242
- ${(0, utils_1.indent)(sql)}
243
- );
244
- `;
245
- }
246
- sqlCreateFunctionCombineLastStage(lastStageName) {
247
- return `SELECT ARRAY((SELECT AS STRUCT * FROM ${lastStageName}))\n`;
248
- }
249
- sqlSelectAliasAsStruct(alias) {
250
- return `(SELECT AS STRUCT ${alias}.*)`;
251
- }
252
- sqlMaybeQuoteIdentifier(identifier) {
253
- return this.keywords.indexOf(identifier.toUpperCase()) > 0
254
- ? "`" + identifier + "`"
255
- : identifier;
256
- }
257
- sqlNow() {
258
- return (0, model_1.mkExpr) `CURRENT_TIMESTAMP()`;
259
- }
260
- sqlTrunc(sqlTime, units) {
261
- if (sqlTime.valueType == "date") {
262
- if ((0, model_1.isDateUnit)(units)) {
263
- return (0, model_1.mkExpr) `DATE_TRUNC(${sqlTime.value},${units})`;
264
- }
265
- return (0, model_1.mkExpr) `TIMESTAMP(${sqlTime.value})`;
266
- }
267
- return (0, model_1.mkExpr) `TIMESTAMP_TRUNC(${sqlTime.value},${units})`;
268
- }
269
- sqlExtract(expr, units) {
270
- const extractTo = extractMap[units] || units;
271
- return (0, model_1.mkExpr) `EXTRACT(${extractTo} FROM ${expr.value})`;
272
- }
273
- sqlAlterTime(op, expr, n, timeframe) {
274
- let theTime = expr.value;
275
- let computeType = expr.valueType;
276
- if (timeframe != "day" && timestampAddUnits.includes(timeframe)) {
277
- // The units must be done in timestamp, no matter the input type
278
- computeType = "timestamp";
279
- if (expr.valueType != "timestamp") {
280
- theTime = (0, model_1.mkExpr) `TIMESTAMP(${theTime})`;
281
- }
282
- }
283
- else if (expr.valueType == "timestamp") {
284
- theTime = (0, model_1.mkExpr) `DATETIME(${theTime})`;
285
- computeType = "datetime";
286
- }
287
- const funcName = computeType.toUpperCase() + (op == "+" ? "_ADD" : "_SUB");
288
- const newTime = (0, model_1.mkExpr) `${funcName}(${theTime}, INTERVAL ${n} ${timeframe})`;
289
- return computeType == "datetime" ? (0, model_1.mkExpr) `TIMESTAMP(${newTime})` : newTime;
290
- }
291
- ignoreInProject(fieldName) {
292
- return fieldName === "_PARTITIONTIME";
293
- }
294
- sqlCast(cast) {
295
- if (cast.srcType !== cast.dstType) {
296
- const dstType = castMap[cast.dstType] || cast.dstType;
297
- // This just makes the code look a little prettier ...
298
- if (!cast.safe && cast.srcType && (0, model_1.isTimeFieldType)(cast.srcType)) {
299
- if (dstType == "date") {
300
- return (0, model_1.mkExpr) `DATE(${cast.expr})`;
301
- }
302
- return (0, model_1.mkExpr) `TIMESTAMP(${cast.expr})`;
303
- }
304
- const castFunc = cast.safe ? "SAFE_CAST" : "CAST";
305
- return (0, model_1.mkExpr) `${castFunc}(${cast.expr} AS ${dstType})`;
306
- }
307
- return cast.expr;
308
- }
309
- sqlRegexpMatch(expr, regexp) {
310
- return (0, model_1.mkExpr) `REGEXP_CONTAINS(${expr}, r${regexp})`;
311
- }
312
- sqlLiteralTime(timeString, type, timezone) {
313
- if (type === "date") {
314
- return `DATE('${timeString}')`;
315
- }
316
- else if (type === "timestamp") {
317
- return `TIMESTAMP('${timeString}', '${timezone}')`;
318
- }
319
- else {
320
- throw new Error(`Unknown Liternal time format ${type}`);
321
- }
322
- }
323
- sqlMeasureTime(from, to, units) {
324
- let lVal = from.value;
325
- let rVal = to.value;
326
- let diffUsing = "TIMESTAMP_DIFF";
327
- if (units == "second" || units == "minute" || units == "hour") {
328
- if (from.valueType != "timestamp") {
329
- lVal = (0, model_1.mkExpr) `TIMESTAMP(${lVal})`;
330
- }
331
- if (to.valueType != "timestamp") {
332
- rVal = (0, model_1.mkExpr) `TIMESTAMP(${rVal})`;
333
- }
334
- }
335
- else {
336
- diffUsing = "DATE_DIFF";
337
- if (from.valueType != "date") {
338
- lVal = (0, model_1.mkExpr) `DATE(${lVal})`;
339
- }
340
- if (to.valueType != "date") {
341
- rVal = (0, model_1.mkExpr) `DATE(${rVal})`;
342
- }
343
- }
344
- return (0, model_1.mkExpr) `${diffUsing}(${rVal}, ${lVal}, ${units})`;
345
- }
346
- sqlSampleTable(tableSQL, sample) {
347
- if (sample !== undefined) {
348
- if ((0, model_1.isSamplingEnable)(sample) && sample.enable) {
349
- sample = this.defaultSampling;
350
- }
351
- if ((0, model_1.isSamplingRows)(sample)) {
352
- throw new Error(`StandardSQL doesn't support sampling by rows only percent`);
353
- }
354
- else if ((0, model_1.isSamplingPercent)(sample)) {
355
- return `(SELECT * FROM ${tableSQL} TABLESAMPLE SYSTEM (${sample.percent} PERCENT))`;
356
- }
357
- }
358
- return tableSQL;
359
- }
360
- }
361
- exports.StandardSQLDialect = StandardSQLDialect;
362
- //# sourceMappingURL=standardsql.js.map