@malloydata/malloy 0.0.39-dev230613161129 → 0.0.39
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/dialect/dialect.d.ts +9 -13
- package/dist/dialect/dialect.js +16 -3
- package/dist/dialect/dialect_map.d.ts +2 -0
- package/dist/dialect/dialect_map.js +61 -1
- package/dist/dialect/{duckdb.d.ts → duckdb/duckdb.d.ts} +8 -5
- package/dist/dialect/{duckdb.js → duckdb/duckdb.js} +21 -9
- package/dist/dialect/duckdb/functions/byte_length.d.ts +2 -0
- package/dist/dialect/duckdb/functions/byte_length.js +33 -0
- package/dist/dialect/duckdb/functions/div.d.ts +2 -0
- package/dist/dialect/duckdb/functions/div.js +38 -0
- package/dist/dialect/duckdb/functions/duckdb_functions.d.ts +1 -0
- package/dist/dialect/duckdb/functions/duckdb_functions.js +52 -0
- package/dist/dialect/duckdb/functions/ends_with.d.ts +2 -0
- package/dist/dialect/duckdb/functions/ends_with.js +35 -0
- package/dist/dialect/duckdb/functions/greatest_and_least.d.ts +3 -0
- package/dist/dialect/duckdb/functions/greatest_and_least.js +58 -0
- package/dist/dialect/duckdb/functions/index.d.ts +1 -0
- package/dist/dialect/duckdb/functions/index.js +28 -0
- package/dist/dialect/duckdb/functions/is_inf.d.ts +2 -0
- package/dist/dialect/duckdb/functions/is_inf.js +33 -0
- package/dist/dialect/duckdb/functions/is_nan.d.ts +2 -0
- package/dist/dialect/duckdb/functions/is_nan.js +33 -0
- package/dist/dialect/duckdb/functions/log.d.ts +2 -0
- package/dist/dialect/duckdb/functions/log.js +38 -0
- package/dist/dialect/duckdb/functions/rand.d.ts +2 -0
- package/dist/dialect/duckdb/functions/rand.js +31 -0
- package/dist/dialect/duckdb/functions/replace.d.ts +2 -0
- package/dist/dialect/duckdb/functions/replace.js +40 -0
- package/dist/dialect/duckdb/functions/trunc.d.ts +2 -0
- package/dist/dialect/duckdb/functions/trunc.js +39 -0
- package/dist/dialect/duckdb/functions/unicode.d.ts +2 -0
- package/dist/dialect/duckdb/functions/unicode.js +35 -0
- package/dist/dialect/duckdb/index.d.ts +1 -0
- package/dist/dialect/duckdb/index.js +40 -0
- package/dist/dialect/functions/all_functions.d.ts +8 -0
- package/dist/dialect/functions/all_functions.js +135 -0
- package/dist/dialect/functions/atan2.d.ts +2 -0
- package/dist/dialect/functions/atan2.js +33 -0
- package/dist/dialect/functions/avg_moving.d.ts +2 -0
- package/dist/dialect/functions/avg_moving.js +46 -0
- package/dist/dialect/functions/chr.d.ts +4 -0
- package/dist/dialect/functions/chr.js +45 -0
- package/dist/dialect/functions/coalesce.d.ts +2 -0
- package/dist/dialect/functions/coalesce.js +38 -0
- package/dist/dialect/functions/concat.d.ts +2 -0
- package/dist/dialect/functions/concat.js +38 -0
- package/dist/dialect/functions/div.d.ts +2 -0
- package/dist/dialect/functions/div.js +36 -0
- package/dist/dialect/functions/first_value_window.d.ts +3 -0
- package/dist/dialect/functions/first_value_window.js +49 -0
- package/dist/dialect/functions/function_map.d.ts +16 -0
- package/dist/dialect/functions/function_map.js +50 -0
- package/dist/dialect/functions/greatest_and_least.d.ts +3 -0
- package/dist/dialect/functions/greatest_and_least.js +44 -0
- package/dist/dialect/functions/ifnull.d.ts +2 -0
- package/dist/dialect/functions/ifnull.js +38 -0
- package/dist/dialect/functions/index.d.ts +2 -0
- package/dist/dialect/functions/index.js +28 -0
- package/dist/dialect/functions/is_inf.d.ts +2 -0
- package/dist/dialect/functions/is_inf.js +33 -0
- package/dist/dialect/functions/is_nan.d.ts +2 -0
- package/dist/dialect/functions/is_nan.js +33 -0
- package/dist/dialect/functions/lag.d.ts +2 -0
- package/dist/dialect/functions/lag.js +53 -0
- package/dist/dialect/functions/lead.d.ts +2 -0
- package/dist/dialect/functions/lead.js +50 -0
- package/dist/dialect/functions/length.d.ts +3 -0
- package/dist/dialect/functions/length.js +39 -0
- package/dist/dialect/functions/log.d.ts +2 -0
- package/dist/dialect/functions/log.js +35 -0
- package/dist/dialect/functions/lower.d.ts +2 -0
- package/dist/dialect/functions/lower.js +34 -0
- package/dist/dialect/functions/nullif.d.ts +2 -0
- package/dist/dialect/functions/nullif.js +42 -0
- package/dist/dialect/functions/pi.d.ts +2 -0
- package/dist/{lang/ast/types/type-desc.js → dialect/functions/pi.js} +7 -1
- package/dist/dialect/functions/pow.d.ts +2 -0
- package/dist/dialect/functions/pow.js +35 -0
- package/dist/dialect/functions/rand.d.ts +2 -0
- package/dist/dialect/functions/rand.js +31 -0
- package/dist/dialect/functions/rank.d.ts +2 -0
- package/dist/dialect/functions/rank.js +36 -0
- package/dist/dialect/functions/regexp_extract.d.ts +2 -0
- package/dist/dialect/functions/regexp_extract.js +41 -0
- package/dist/dialect/functions/repeat.d.ts +2 -0
- package/dist/dialect/functions/repeat.js +35 -0
- package/dist/dialect/functions/replace.d.ts +2 -0
- package/dist/dialect/functions/replace.js +42 -0
- package/dist/dialect/functions/reverse.d.ts +2 -0
- package/dist/dialect/functions/reverse.js +34 -0
- package/dist/dialect/functions/round.d.ts +2 -0
- package/dist/dialect/functions/round.js +40 -0
- package/dist/dialect/functions/row_number.d.ts +2 -0
- package/dist/dialect/functions/row_number.js +40 -0
- package/dist/dialect/functions/simple_numeric_functions.d.ts +15 -0
- package/dist/dialect/functions/simple_numeric_functions.js +60 -0
- package/dist/dialect/functions/starts_ends_with.d.ts +3 -0
- package/dist/dialect/functions/starts_ends_with.js +43 -0
- package/dist/dialect/functions/stddev.d.ts +2 -0
- package/dist/dialect/functions/stddev.js +34 -0
- package/dist/dialect/functions/strpos.d.ts +2 -0
- package/dist/dialect/functions/strpos.js +35 -0
- package/dist/dialect/functions/substr.d.ts +2 -0
- package/dist/dialect/functions/substr.js +37 -0
- package/dist/dialect/functions/sum_min_max_window.d.ts +7 -0
- package/dist/dialect/functions/sum_min_max_window.js +94 -0
- package/dist/dialect/functions/trim_functions.d.ts +4 -0
- package/dist/dialect/functions/trim_functions.js +42 -0
- package/dist/dialect/functions/trunc.d.ts +2 -0
- package/dist/dialect/functions/trunc.js +38 -0
- package/dist/dialect/functions/upper.d.ts +2 -0
- package/dist/dialect/functions/upper.js +34 -0
- package/dist/dialect/functions/util.d.ts +45 -0
- package/dist/dialect/functions/util.js +187 -0
- package/dist/dialect/index.d.ts +1 -1
- package/dist/dialect/index.js +2 -1
- package/dist/dialect/postgres/functions/byte_length.d.ts +2 -0
- package/dist/dialect/postgres/functions/byte_length.js +33 -0
- package/dist/dialect/postgres/functions/ends_with.d.ts +2 -0
- package/dist/dialect/postgres/functions/ends_with.js +38 -0
- package/dist/dialect/postgres/functions/greatest_and_least.d.ts +3 -0
- package/dist/dialect/postgres/functions/greatest_and_least.js +45 -0
- package/dist/dialect/postgres/functions/ifnull.d.ts +2 -0
- package/dist/dialect/postgres/functions/ifnull.js +40 -0
- package/dist/dialect/postgres/functions/index.d.ts +1 -0
- package/dist/dialect/postgres/functions/index.js +28 -0
- package/dist/dialect/postgres/functions/is_inf.d.ts +2 -0
- package/dist/dialect/postgres/functions/is_inf.js +34 -0
- package/dist/dialect/postgres/functions/is_nan.d.ts +2 -0
- package/dist/dialect/postgres/functions/is_nan.js +33 -0
- package/dist/dialect/postgres/functions/log.d.ts +2 -0
- package/dist/dialect/postgres/functions/log.js +37 -0
- package/dist/dialect/postgres/functions/postgres_functions.d.ts +1 -0
- package/dist/dialect/postgres/functions/postgres_functions.js +60 -0
- package/dist/dialect/postgres/functions/rand.d.ts +2 -0
- package/dist/dialect/postgres/functions/rand.js +31 -0
- package/dist/dialect/postgres/functions/regexp_extract.d.ts +2 -0
- package/dist/dialect/postgres/functions/regexp_extract.js +35 -0
- package/dist/dialect/postgres/functions/replace.d.ts +2 -0
- package/dist/dialect/postgres/functions/replace.js +40 -0
- package/dist/dialect/postgres/functions/round.d.ts +2 -0
- package/dist/dialect/postgres/functions/round.js +39 -0
- package/dist/dialect/postgres/functions/stddev.d.ts +2 -0
- package/dist/dialect/postgres/functions/stddev.js +37 -0
- package/dist/dialect/postgres/functions/substr.d.ts +2 -0
- package/dist/dialect/postgres/functions/substr.js +38 -0
- package/dist/dialect/postgres/functions/trunc.d.ts +2 -0
- package/dist/dialect/postgres/functions/trunc.js +40 -0
- package/dist/dialect/postgres/functions/unicode.d.ts +2 -0
- package/dist/dialect/postgres/functions/unicode.js +34 -0
- package/dist/dialect/postgres/index.d.ts +1 -0
- package/dist/dialect/postgres/index.js +40 -0
- package/dist/dialect/{postgres.d.ts → postgres/postgres.d.ts} +9 -5
- package/dist/dialect/{postgres.js → postgres/postgres.js} +24 -10
- package/dist/dialect/standardsql/functions/chr.d.ts +2 -0
- package/dist/dialect/standardsql/functions/chr.js +37 -0
- package/dist/dialect/standardsql/functions/index.d.ts +1 -0
- package/dist/dialect/standardsql/functions/index.js +28 -0
- package/dist/dialect/standardsql/functions/pi.d.ts +2 -0
- package/dist/dialect/standardsql/functions/pi.js +32 -0
- package/dist/dialect/standardsql/functions/standardsql_functions.d.ts +1 -0
- package/dist/dialect/standardsql/functions/standardsql_functions.js +33 -0
- package/dist/dialect/standardsql/index.d.ts +1 -0
- package/dist/dialect/standardsql/index.js +40 -0
- package/dist/dialect/{standardsql.d.ts → standardsql/standardsql.d.ts} +7 -4
- package/dist/dialect/{standardsql.js → standardsql/standardsql.js} +13 -11
- package/dist/index.d.ts +1 -1
- package/dist/lang/ast/ast-utils.js +1 -0
- package/dist/lang/ast/elements/define-query.js +1 -1
- package/dist/lang/ast/elements/import-statement.js +6 -1
- package/dist/lang/ast/executors/index-executor.d.ts +1 -1
- package/dist/lang/ast/executors/index-executor.js +2 -2
- package/dist/lang/ast/executors/project-executor.d.ts +1 -1
- package/dist/lang/ast/executors/project-executor.js +2 -2
- package/dist/lang/ast/executors/reduce-executor.d.ts +2 -4
- package/dist/lang/ast/executors/reduce-executor.js +8 -4
- package/dist/lang/ast/expressions/binary-boolean.d.ts +1 -1
- package/dist/lang/ast/expressions/binary-boolean.js +2 -0
- package/dist/lang/ast/expressions/constant-sub-expression.js +10 -0
- package/dist/lang/ast/expressions/expr-aggregate-function.d.ts +2 -2
- package/dist/lang/ast/expressions/expr-aggregate-function.js +28 -2
- package/dist/lang/ast/expressions/expr-alternation-tree.js +1 -0
- package/dist/lang/ast/expressions/expr-cast.js +1 -0
- package/dist/lang/ast/expressions/expr-coalesce.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-coalesce.js +1 -0
- package/dist/lang/ast/expressions/expr-count-distinct.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-count.js +1 -0
- package/dist/lang/ast/expressions/expr-filter.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-filter.js +1 -1
- package/dist/lang/ast/expressions/expr-func.d.ts +6 -1
- package/dist/lang/ast/expressions/expr-func.js +266 -16
- package/dist/lang/ast/expressions/expr-granular-time.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-id-reference.js +12 -0
- package/dist/lang/ast/expressions/expr-logical-op.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-max.d.ts +2 -2
- package/dist/lang/ast/expressions/expr-min.d.ts +2 -2
- package/dist/lang/ast/expressions/expr-not.d.ts +1 -1
- package/dist/lang/ast/expressions/expr-now.js +2 -0
- package/dist/lang/ast/expressions/expr-null.js +1 -0
- package/dist/lang/ast/expressions/expr-number.js +5 -1
- package/dist/lang/ast/expressions/expr-regex.js +4 -1
- package/dist/lang/ast/expressions/expr-string.js +1 -0
- package/dist/lang/ast/expressions/expr-time-extract.js +2 -0
- package/dist/lang/ast/expressions/expr-time.js +1 -0
- package/dist/lang/ast/expressions/expr-ungroup.d.ts +2 -2
- package/dist/lang/ast/expressions/expr-ungroup.js +15 -7
- package/dist/lang/ast/expressions/for-range.d.ts +1 -1
- package/dist/lang/ast/expressions/pick-when.js +7 -0
- package/dist/lang/ast/expressions/range.js +1 -0
- package/dist/lang/ast/expressions/time-literal.js +9 -3
- package/dist/lang/ast/field-space/column-space-field.d.ts +1 -2
- package/dist/lang/ast/field-space/dynamic-space.js +6 -4
- package/dist/lang/ast/field-space/field-definition-value.d.ts +1 -1
- package/dist/lang/ast/field-space/project-field-space.d.ts +2 -2
- package/dist/lang/ast/field-space/project-field-space.js +12 -13
- package/dist/lang/ast/field-space/query-space-field.d.ts +1 -2
- package/dist/lang/ast/field-space/query-space-field.js +1 -1
- package/dist/lang/ast/field-space/query-spaces.d.ts +16 -2
- package/dist/lang/ast/field-space/query-spaces.js +175 -10
- package/dist/lang/ast/field-space/reference-field.d.ts +3 -2
- package/dist/lang/ast/field-space/reference-field.js +8 -1
- package/dist/lang/ast/field-space/rename-space-field.d.ts +1 -2
- package/dist/lang/ast/field-space/static-space.d.ts +4 -3
- package/dist/lang/ast/field-space/static-space.js +4 -0
- package/dist/lang/ast/field-space/struct-space-field-base.d.ts +1 -2
- package/dist/lang/ast/field-space/struct-space-field-base.js +1 -1
- package/dist/lang/ast/field-space/wild-space-field.d.ts +1 -2
- package/dist/lang/ast/fragtype-utils.d.ts +1 -1
- package/dist/lang/ast/fragtype-utils.js +4 -3
- package/dist/lang/ast/index.d.ts +1 -0
- package/dist/lang/ast/index.js +1 -0
- package/dist/lang/ast/query-items/field-declaration.d.ts +40 -4
- package/dist/lang/ast/query-items/field-declaration.js +102 -3
- package/dist/lang/ast/query-items/field-references.d.ts +44 -2
- package/dist/lang/ast/query-items/field-references.js +110 -2
- package/dist/lang/ast/query-items/typecheck_utils.d.ts +10 -0
- package/dist/lang/ast/query-items/typecheck_utils.js +177 -0
- package/dist/lang/ast/query-properties/aggregate.js +0 -6
- package/dist/lang/ast/query-properties/calculate.d.ts +5 -0
- package/dist/lang/ast/query-properties/calculate.js +33 -0
- package/dist/lang/ast/query-properties/dimmensions.js +0 -3
- package/dist/lang/ast/query-properties/filters.js +6 -3
- package/dist/lang/ast/query-properties/group-by.js +0 -6
- package/dist/lang/ast/query-properties/measures.js +0 -3
- package/dist/lang/ast/query-properties/nest-reference.d.ts +2 -0
- package/dist/lang/ast/query-properties/nest-reference.js +23 -0
- package/dist/lang/ast/query-properties/ordering.d.ts +1 -1
- package/dist/lang/ast/query-properties/ordering.js +18 -8
- package/dist/lang/ast/query-properties/qop-desc.js +8 -4
- package/dist/lang/ast/query-properties/top.js +20 -6
- package/dist/lang/ast/sources/named-source.js +4 -0
- package/dist/lang/ast/sources/sql-source.js +5 -1
- package/dist/lang/ast/time-utils.d.ts +1 -2
- package/dist/lang/ast/types/expr-result.d.ts +1 -2
- package/dist/lang/ast/types/expression-def.d.ts +3 -4
- package/dist/lang/ast/types/expression-def.js +10 -2
- package/dist/lang/ast/types/field-space.d.ts +7 -0
- package/dist/lang/ast/types/global-name-space.d.ts +12 -0
- package/dist/lang/ast/types/global-name-space.js +51 -0
- package/dist/lang/ast/types/malloy-element.d.ts +1 -0
- package/dist/lang/ast/types/malloy-element.js +15 -2
- package/dist/lang/ast/types/query-property.d.ts +1 -2
- package/dist/lang/ast/types/query-property.js +2 -0
- package/dist/lang/ast/types/space-entry.d.ts +1 -1
- package/dist/lang/ast/types/space-field.d.ts +1 -2
- package/dist/lang/ast/types/space-field.js +5 -1
- package/dist/lang/ast/types/space-param.d.ts +1 -2
- package/dist/lang/ast/types/space-param.js +10 -2
- package/dist/lang/lib/Malloy/MalloyLexer.d.ts +138 -135
- package/dist/lang/lib/Malloy/MalloyLexer.js +1135 -1103
- package/dist/lang/lib/Malloy/MalloyParser.d.ts +252 -275
- package/dist/lang/lib/Malloy/MalloyParser.js +1753 -1905
- package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +40 -103
- package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +25 -64
- package/dist/lang/malloy-to-ast.d.ts +11 -7
- package/dist/lang/malloy-to-ast.js +90 -51
- package/dist/lang/parse-tree-walkers/document-symbol-walker.js +5 -2
- package/dist/lang/test/parse.spec.js +399 -18
- package/dist/lang/test/test-translator.d.ts +1 -0
- package/dist/lang/test/test-translator.js +5 -0
- package/dist/model/malloy_query.d.ts +13 -4
- package/dist/model/malloy_query.js +240 -76
- package/dist/model/malloy_types.d.ts +89 -18
- package/dist/model/malloy_types.js +88 -61
- package/dist/model/utils.d.ts +4 -0
- package/dist/model/utils.js +118 -1
- package/package.json +1 -1
- package/dist/lang/ast/types/type-desc.d.ts +0 -8
|
@@ -28,7 +28,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
28
28
|
exports.flattenQuery = exports.QueryModel = exports.Segment = void 0;
|
|
29
29
|
const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
|
|
30
30
|
const dialect_1 = require("../dialect");
|
|
31
|
-
const standardsql_1 = require("../dialect/standardsql");
|
|
31
|
+
const standardsql_1 = require("../dialect/standardsql/standardsql");
|
|
32
32
|
const malloy_types_1 = require("./malloy_types");
|
|
33
33
|
const utils_1 = require("./utils");
|
|
34
34
|
// quote a string for SQL use. Perhaps should be in dialect.
|
|
@@ -223,6 +223,101 @@ class QueryField extends QueryNode {
|
|
|
223
223
|
return field.generateExpression(resultSet);
|
|
224
224
|
}
|
|
225
225
|
}
|
|
226
|
+
generateOutputFieldFragment(resultSet, _context, frag, _state) {
|
|
227
|
+
return resultSet.getField(frag.name).getAnalyticalSQL(false);
|
|
228
|
+
}
|
|
229
|
+
generateSQLExpression(resultSet, context, frag, state) {
|
|
230
|
+
return this.generateExpressionFromExpr(resultSet, context, frag.e, state);
|
|
231
|
+
}
|
|
232
|
+
getParameterMap(overload, numArgs) {
|
|
233
|
+
return new Map(overload.params.map((param, paramIndex) => {
|
|
234
|
+
const argIndexes = param.isVariadic
|
|
235
|
+
? (0, utils_1.range)(paramIndex, numArgs)
|
|
236
|
+
: [paramIndex];
|
|
237
|
+
return [param.name, { param, argIndexes }];
|
|
238
|
+
}));
|
|
239
|
+
}
|
|
240
|
+
expandFunctionCall(dialect, overload, args) {
|
|
241
|
+
const paramMap = this.getParameterMap(overload, args.length);
|
|
242
|
+
if (overload.dialect[dialect] === undefined) {
|
|
243
|
+
throw new Error(`Function is not defined for dialect ${dialect}`);
|
|
244
|
+
}
|
|
245
|
+
return (0, utils_1.exprMap)(overload.dialect[dialect], fragment => {
|
|
246
|
+
if (typeof fragment === 'string') {
|
|
247
|
+
return [fragment];
|
|
248
|
+
}
|
|
249
|
+
else if (fragment.type === 'spread') {
|
|
250
|
+
const param = fragment.e[0];
|
|
251
|
+
if (fragment.e.length !== 1 ||
|
|
252
|
+
typeof param === 'string' ||
|
|
253
|
+
param.type !== 'function_parameter') {
|
|
254
|
+
throw new Error('Invalid function definition. Argument to spread must be a function parameter.');
|
|
255
|
+
return [];
|
|
256
|
+
}
|
|
257
|
+
const entry = paramMap.get(param.name);
|
|
258
|
+
if (entry === undefined) {
|
|
259
|
+
return [fragment];
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
return (0, utils_1.joinWith)(entry.argIndexes.map(argIndex => args[argIndex]), ',');
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
else if (fragment.type === 'function_parameter') {
|
|
266
|
+
const entry = paramMap.get(fragment.name);
|
|
267
|
+
if (entry === undefined) {
|
|
268
|
+
return [fragment];
|
|
269
|
+
}
|
|
270
|
+
else if (entry.param.isVariadic) {
|
|
271
|
+
const spread = (0, utils_1.joinWith)(entry.argIndexes.map(argIndex => args[argIndex]), ',');
|
|
272
|
+
return ['[', ...spread, ']'];
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
return args[entry.argIndexes[0]];
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return [fragment];
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
generateFunctionCallExpression(resultSet, context, frag, state) {
|
|
282
|
+
const overload = frag.overload;
|
|
283
|
+
const args = frag.args;
|
|
284
|
+
const distinctKey = (0, malloy_types_1.expressionIsAggregate)(overload.returnType.expressionType) &&
|
|
285
|
+
this.generateDistinctKeyIfNecessary(resultSet, context, frag.structPath);
|
|
286
|
+
if (distinctKey) {
|
|
287
|
+
if (!context.dialect.supportsAggDistinct) {
|
|
288
|
+
throw new Error(`Asymmetric aggregates are not supported for custom functions in ${context.dialect.name}.`);
|
|
289
|
+
}
|
|
290
|
+
const argsExpressions = args.map(arg => {
|
|
291
|
+
return this.generateDimFragment(resultSet, context, arg, state);
|
|
292
|
+
});
|
|
293
|
+
return context.dialect.sqlAggDistinct(distinctKey, argsExpressions, valNames => {
|
|
294
|
+
const funcCall = this.expandFunctionCall(context.dialect.name, overload, valNames.map(v => [v]));
|
|
295
|
+
return this.generateExpressionFromExpr(resultSet, context, funcCall, state);
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
const mappedArgs = (0, malloy_types_1.expressionIsAggregate)(overload.returnType.expressionType)
|
|
300
|
+
? args.map(arg => {
|
|
301
|
+
// TODO We assume that all arguments to this aggregate-returning function need to
|
|
302
|
+
// have filters applied to them. This is not necessarily true in the general case,
|
|
303
|
+
// e.g. in a function `avg_plus(a, b) = avg(a) + b` -- here, `b` should not be
|
|
304
|
+
// be filtered. But since there aren't any aggregate functions like this in the
|
|
305
|
+
// standard library we have planned, we ignore this for now.
|
|
306
|
+
return [this.generateDimFragment(resultSet, context, arg, state)];
|
|
307
|
+
})
|
|
308
|
+
: args;
|
|
309
|
+
const funcCall = this.expandFunctionCall(context.dialect.name, overload, mappedArgs);
|
|
310
|
+
if ((0, malloy_types_1.expressionIsAnalytic)(overload.returnType.expressionType)) {
|
|
311
|
+
// TODO probably need to pass in the function and arguments separately
|
|
312
|
+
// in order to generate parameter SQL correctly in BQ re: partition
|
|
313
|
+
return this.generateAnalyticFragment(resultSet, context, funcCall, overload, state, args);
|
|
314
|
+
}
|
|
315
|
+
return this.generateExpressionFromExpr(resultSet, context, funcCall, state);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
generateSpread(_resultSet, _context, _frag, _state) {
|
|
319
|
+
throw new Error('Unexpanded spread encountered during SQL generation');
|
|
320
|
+
}
|
|
226
321
|
generateParameterFragment(resultSet, context, expr, state) {
|
|
227
322
|
// find the structDef and return the path to the field...
|
|
228
323
|
const param = context.parameters()[expr.path];
|
|
@@ -244,7 +339,7 @@ class QueryField extends QueryNode {
|
|
|
244
339
|
return this.generateExpressionFromExpr(resultSet, context, expr.e, state.withWhere(allWhere.sql()));
|
|
245
340
|
}
|
|
246
341
|
generateDimFragment(resultSet, context, expr, state) {
|
|
247
|
-
let dim = this.generateExpressionFromExpr(resultSet, context, expr
|
|
342
|
+
let dim = this.generateExpressionFromExpr(resultSet, context, expr, state);
|
|
248
343
|
if (state.whereSQL) {
|
|
249
344
|
dim = `CASE WHEN ${state.whereSQL} THEN ${dim} END`;
|
|
250
345
|
}
|
|
@@ -270,7 +365,7 @@ class QueryField extends QueryNode {
|
|
|
270
365
|
const s = this.generateExpressionFromExpr(resultSet, context, expr.e, state.withTotal(totalGroupSet));
|
|
271
366
|
const fields = resultSet.getUngroupPartitions(ungroupSet);
|
|
272
367
|
let partitionBy = '';
|
|
273
|
-
const fieldsString = fields.map(f => f.
|
|
368
|
+
const fieldsString = fields.map(f => f.getAnalyticalSQL(true)).join(', ');
|
|
274
369
|
if (fieldsString.length > 0) {
|
|
275
370
|
partitionBy = `PARTITION BY ${fieldsString}`;
|
|
276
371
|
}
|
|
@@ -289,7 +384,7 @@ class QueryField extends QueryNode {
|
|
|
289
384
|
}
|
|
290
385
|
}
|
|
291
386
|
generateSumFragment(resultSet, context, expr, state) {
|
|
292
|
-
const dimSQL = this.generateDimFragment(resultSet, context, expr, state);
|
|
387
|
+
const dimSQL = this.generateDimFragment(resultSet, context, expr.e, state);
|
|
293
388
|
const distinctKeySQL = this.generateDistinctKeyIfNecessary(resultSet, context, expr.structPath);
|
|
294
389
|
let ret;
|
|
295
390
|
if (distinctKeySQL) {
|
|
@@ -306,7 +401,7 @@ class QueryField extends QueryNode {
|
|
|
306
401
|
return `COALESCE(${ret},0)`;
|
|
307
402
|
}
|
|
308
403
|
generateSymmetricFragment(resultSet, context, expr, state) {
|
|
309
|
-
const dimSQL = this.generateDimFragment(resultSet, context, expr, state);
|
|
404
|
+
const dimSQL = this.generateDimFragment(resultSet, context, expr.e, state);
|
|
310
405
|
const f = expr.function === 'count_distinct'
|
|
311
406
|
? 'count(distinct '
|
|
312
407
|
: expr.function + '(';
|
|
@@ -314,7 +409,7 @@ class QueryField extends QueryNode {
|
|
|
314
409
|
}
|
|
315
410
|
generateAvgFragment(resultSet, context, expr, state) {
|
|
316
411
|
// find the structDef and return the path to the field...
|
|
317
|
-
const dimSQL = this.generateDimFragment(resultSet, context, expr, state);
|
|
412
|
+
const dimSQL = this.generateDimFragment(resultSet, context, expr.e, state);
|
|
318
413
|
const distinctKeySQL = this.generateDistinctKeyIfNecessary(resultSet, context, expr.structPath);
|
|
319
414
|
if (distinctKeySQL) {
|
|
320
415
|
let countDistinctKeySQL = distinctKeySQL;
|
|
@@ -355,60 +450,93 @@ class QueryField extends QueryNode {
|
|
|
355
450
|
generateDialect(resultSet, context, expr, state) {
|
|
356
451
|
return this.generateExpressionFromExpr(resultSet, context, context.dialect.dialectExpr(resultSet.getQueryInfo(), expr), state);
|
|
357
452
|
}
|
|
358
|
-
|
|
359
|
-
const
|
|
360
|
-
let
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
453
|
+
getAnalyticPartitions(resultStruct) {
|
|
454
|
+
const ret = [];
|
|
455
|
+
let p = resultStruct.parent;
|
|
456
|
+
while (p !== undefined) {
|
|
457
|
+
const scalars = p.fields(fi => isScalarField(fi.f) && fi.fieldUsage.type === 'result');
|
|
458
|
+
const partitionSQLs = scalars.map(fi => fi.getAnalyticalSQL(true));
|
|
459
|
+
ret.push(...partitionSQLs);
|
|
460
|
+
p = p.parent;
|
|
364
461
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
let
|
|
369
|
-
const
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
fif: resultStruct.getField(ordering.field),
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
else {
|
|
379
|
-
orderingField = resultStruct.getFieldByNumber(ordering.field);
|
|
380
|
-
}
|
|
381
|
-
if (resultStruct.firstSegment.type === 'reduce') {
|
|
382
|
-
obSQL.push(` ${orderingField.fif.getSQL()}` +
|
|
383
|
-
// this.parent.dialect.sqlMaybeQuoteIdentifier(
|
|
384
|
-
// `${orderingField.name}__${resultStruct.groupSet}`
|
|
385
|
-
// ) +
|
|
386
|
-
` ${ordering.dir || 'ASC'}`);
|
|
462
|
+
return ret.join(', ');
|
|
463
|
+
}
|
|
464
|
+
generateAnalyticFragment(resultStruct, context, expr, overload, state, args) {
|
|
465
|
+
let partitionBy = '';
|
|
466
|
+
const isComplex = resultStruct.root().isComplexQuery;
|
|
467
|
+
const fieldsString = this.getAnalyticPartitions(resultStruct);
|
|
468
|
+
if (isComplex || fieldsString.length > 0) {
|
|
469
|
+
partitionBy = 'PARTITION BY ';
|
|
470
|
+
if (isComplex) {
|
|
471
|
+
partitionBy += 'group_set';
|
|
387
472
|
}
|
|
388
|
-
|
|
389
|
-
|
|
473
|
+
if (fieldsString.length > 0) {
|
|
474
|
+
partitionBy += `, ${fieldsString}`;
|
|
390
475
|
}
|
|
391
476
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
477
|
+
let orderBy = '';
|
|
478
|
+
if (overload.needsWindowOrderBy) {
|
|
479
|
+
// calculate the ordering.
|
|
480
|
+
const obSQL = [];
|
|
481
|
+
let orderingField;
|
|
482
|
+
const orderByDef = resultStruct.firstSegment.orderBy ||
|
|
483
|
+
resultStruct.calculateDefaultOrderBy();
|
|
484
|
+
for (const ordering of orderByDef) {
|
|
485
|
+
if (typeof ordering.field === 'string') {
|
|
486
|
+
orderingField = {
|
|
487
|
+
name: ordering.field,
|
|
488
|
+
fif: resultStruct.getField(ordering.field),
|
|
489
|
+
};
|
|
401
490
|
}
|
|
402
491
|
else {
|
|
403
|
-
|
|
492
|
+
orderingField = resultStruct.getFieldByNumber(ordering.field);
|
|
493
|
+
}
|
|
494
|
+
const exprType = orderingField.fif.f.fieldDef.expressionType;
|
|
495
|
+
// TODO today we do not support ordering by analytic functions at all, so this works
|
|
496
|
+
// but eventually we will, and this check will just want to ensure that the order field
|
|
497
|
+
// isn't the same as the field we're currently compiling (otherwise we will loop infintely)
|
|
498
|
+
if ((0, malloy_types_1.expressionIsAnalytic)(exprType)) {
|
|
499
|
+
continue;
|
|
500
|
+
}
|
|
501
|
+
if (resultStruct.firstSegment.type === 'reduce') {
|
|
502
|
+
const orderSQL = orderingField.fif.getAnalyticalSQL(false);
|
|
503
|
+
obSQL.push(` ${orderSQL} ${ordering.dir || 'ASC'}`);
|
|
404
504
|
}
|
|
505
|
+
else if (resultStruct.firstSegment.type === 'project') {
|
|
506
|
+
obSQL.push(` ${orderingField.fif.f.generateExpression(resultStruct)} ${ordering.dir || 'ASC'}`);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
if (obSQL.length > 0) {
|
|
510
|
+
orderBy = ' ' + this.parent.dialect.sqlOrderBy(obSQL);
|
|
405
511
|
}
|
|
406
512
|
}
|
|
407
|
-
|
|
408
|
-
|
|
513
|
+
let between = '';
|
|
514
|
+
if (overload.between) {
|
|
515
|
+
const [preceding, following] = [
|
|
516
|
+
overload.between.preceding,
|
|
517
|
+
overload.between.following,
|
|
518
|
+
].map(value => {
|
|
519
|
+
if (value === -1) {
|
|
520
|
+
return 'UNBOUNDED';
|
|
521
|
+
}
|
|
522
|
+
if (typeof value === 'number') {
|
|
523
|
+
return value;
|
|
524
|
+
}
|
|
525
|
+
const argIndex = overload.params.findIndex(param => param.name === value);
|
|
526
|
+
const arg = args[argIndex];
|
|
527
|
+
if (arg.length !== 1 ||
|
|
528
|
+
typeof arg[0] === 'string' ||
|
|
529
|
+
arg[0].type !== 'dialect' ||
|
|
530
|
+
arg[0].function !== 'numberLiteral') {
|
|
531
|
+
throw new Error('Invalid number of rows for window spec');
|
|
532
|
+
}
|
|
533
|
+
// TODO this does not handle float literals correctly
|
|
534
|
+
return arg[0].literal;
|
|
535
|
+
});
|
|
536
|
+
between = `ROWS BETWEEN ${preceding} PRECEDING AND ${following} FOLLOWING`;
|
|
409
537
|
}
|
|
410
|
-
const
|
|
411
|
-
return `${
|
|
538
|
+
const funcSQL = this.generateExpressionFromExpr(resultStruct, context, expr, state);
|
|
539
|
+
return `${funcSQL} OVER(${partitionBy} ${orderBy} ${between})`;
|
|
412
540
|
}
|
|
413
541
|
generateExpressionFromExpr(resultSet, context, e, state = new GenerateState()) {
|
|
414
542
|
let s = '';
|
|
@@ -428,9 +556,6 @@ class QueryField extends QueryNode {
|
|
|
428
556
|
else if ((0, malloy_types_1.isUngroupFragment)(expr)) {
|
|
429
557
|
s += this.generateUngroupedFragment(resultSet, context, expr, state);
|
|
430
558
|
}
|
|
431
|
-
else if ((0, malloy_types_1.isAnalyticFragment)(expr)) {
|
|
432
|
-
s += this.generateAnalyticFragment(resultSet, context, expr, state);
|
|
433
|
-
}
|
|
434
559
|
else if ((0, malloy_types_1.isAggregateFragment)(expr)) {
|
|
435
560
|
let agg;
|
|
436
561
|
if (expr.function === 'sum') {
|
|
@@ -471,6 +596,21 @@ class QueryField extends QueryNode {
|
|
|
471
596
|
throw new Error('Internal Error: Partial application value referenced but not provided');
|
|
472
597
|
}
|
|
473
598
|
}
|
|
599
|
+
else if ((0, malloy_types_1.isFunctionParameterFragment)(expr)) {
|
|
600
|
+
throw new Error('Internal Error: Function parameter fragment remaining during SQL generation');
|
|
601
|
+
}
|
|
602
|
+
else if ((0, malloy_types_1.isOutputFieldFragment)(expr)) {
|
|
603
|
+
s += this.generateOutputFieldFragment(resultSet, context, expr, state);
|
|
604
|
+
}
|
|
605
|
+
else if ((0, malloy_types_1.isSQLExpressionFragment)(expr)) {
|
|
606
|
+
s += this.generateSQLExpression(resultSet, context, expr, state);
|
|
607
|
+
}
|
|
608
|
+
else if ((0, malloy_types_1.isFunctionCallFragment)(expr)) {
|
|
609
|
+
s += this.generateFunctionCallExpression(resultSet, context, expr, state);
|
|
610
|
+
}
|
|
611
|
+
else if ((0, malloy_types_1.isSpreadFragment)(expr)) {
|
|
612
|
+
s += this.generateSpread(resultSet, context, expr, state);
|
|
613
|
+
}
|
|
474
614
|
else if (expr.type === 'dialect') {
|
|
475
615
|
s += this.generateDialect(resultSet, context, expr, state);
|
|
476
616
|
}
|
|
@@ -499,6 +639,9 @@ class QueryField extends QueryNode {
|
|
|
499
639
|
function isCalculatedField(f) {
|
|
500
640
|
return f instanceof QueryAtomicField && f.isCalculated();
|
|
501
641
|
}
|
|
642
|
+
function isAggregateField(f) {
|
|
643
|
+
return f instanceof QueryAtomicField && f.isAggregate();
|
|
644
|
+
}
|
|
502
645
|
function isScalarField(f) {
|
|
503
646
|
return f instanceof QueryAtomicField && !f.isCalculated();
|
|
504
647
|
}
|
|
@@ -509,6 +652,9 @@ class QueryAtomicField extends QueryField {
|
|
|
509
652
|
isCalculated() {
|
|
510
653
|
return (0, malloy_types_1.expressionIsCalculation)(this.fieldDef.expressionType);
|
|
511
654
|
}
|
|
655
|
+
isAggregate() {
|
|
656
|
+
return (0, malloy_types_1.expressionIsAggregate)(this.fieldDef.expressionType);
|
|
657
|
+
}
|
|
512
658
|
getFilterList() {
|
|
513
659
|
return [];
|
|
514
660
|
}
|
|
@@ -640,19 +786,22 @@ class FieldInstanceField {
|
|
|
640
786
|
getSQL() {
|
|
641
787
|
let exp = this.f.generateExpression(this.parent);
|
|
642
788
|
if (isScalarField(this.f)) {
|
|
643
|
-
exp = this.f.caseGroup(this.parent.
|
|
644
|
-
|
|
645
|
-
|
|
789
|
+
exp = this.f.caseGroup(this.parent.groupSet > 0
|
|
790
|
+
? this.parent.childGroups.concat(this.additionalGroupSets)
|
|
791
|
+
: [], exp);
|
|
646
792
|
}
|
|
647
793
|
return exp;
|
|
648
794
|
}
|
|
649
|
-
|
|
650
|
-
if (this.
|
|
795
|
+
getAnalyticalSQL(forPartition) {
|
|
796
|
+
if (this.analyticalSQL === undefined) {
|
|
651
797
|
return this.getSQL();
|
|
652
798
|
}
|
|
653
|
-
else {
|
|
799
|
+
else if (forPartition && this.partitionSQL) {
|
|
654
800
|
return this.partitionSQL;
|
|
655
801
|
}
|
|
802
|
+
else {
|
|
803
|
+
return this.analyticalSQL;
|
|
804
|
+
}
|
|
656
805
|
}
|
|
657
806
|
}
|
|
658
807
|
class FieldInstanceResult {
|
|
@@ -839,7 +988,7 @@ class FieldInstanceResult {
|
|
|
839
988
|
if (['date', 'timestamp'].indexOf(fi.f.fieldDef.type) > -1) {
|
|
840
989
|
return [{ dir: 'desc', field: fi.fieldUsage.resultIndex }];
|
|
841
990
|
}
|
|
842
|
-
else if (
|
|
991
|
+
else if (isAggregateField(fi.f)) {
|
|
843
992
|
return [{ dir: 'desc', field: fi.fieldUsage.resultIndex }];
|
|
844
993
|
}
|
|
845
994
|
}
|
|
@@ -1319,6 +1468,13 @@ class QueryQuery extends QueryField {
|
|
|
1319
1468
|
}
|
|
1320
1469
|
addDependantExpr(resultStruct, context, e, joinStack) {
|
|
1321
1470
|
for (const expr of e) {
|
|
1471
|
+
if ((0, malloy_types_1.isFunctionCallFragment)(expr) &&
|
|
1472
|
+
(0, malloy_types_1.expressionIsAnalytic)(expr.overload.returnType.expressionType) &&
|
|
1473
|
+
this.parent.dialect.name === 'standardsql') {
|
|
1474
|
+
// force the use of a lateral_join_bag
|
|
1475
|
+
resultStruct.root().isComplexQuery = true;
|
|
1476
|
+
resultStruct.root().queryUsesPartitioning = true;
|
|
1477
|
+
}
|
|
1322
1478
|
if ((0, malloy_types_1.isUngroupFragment)(expr)) {
|
|
1323
1479
|
resultStruct.resultUsesUngrouped = true;
|
|
1324
1480
|
resultStruct.root().isComplexQuery = true;
|
|
@@ -1352,6 +1508,7 @@ class QueryQuery extends QueryField {
|
|
|
1352
1508
|
this.addDependantExpr(resultStruct, context, filterCond.expression, joinStack);
|
|
1353
1509
|
this.addDependantExpr(resultStruct, context, expr.e, joinStack);
|
|
1354
1510
|
}
|
|
1511
|
+
this.addDependantExpr(resultStruct, context, expr.e, joinStack);
|
|
1355
1512
|
}
|
|
1356
1513
|
else if ((0, malloy_types_1.isDialectFragment)(expr)) {
|
|
1357
1514
|
const expressions = [];
|
|
@@ -1362,9 +1519,10 @@ class QueryQuery extends QueryField {
|
|
|
1362
1519
|
expressions.push(expr.denominator);
|
|
1363
1520
|
expressions.push(expr.numerator);
|
|
1364
1521
|
break;
|
|
1522
|
+
case 'numberLiteral':
|
|
1365
1523
|
case 'timeLiteral':
|
|
1366
|
-
break;
|
|
1367
1524
|
case 'stringLiteral':
|
|
1525
|
+
case 'regexpLiteral':
|
|
1368
1526
|
break;
|
|
1369
1527
|
case 'timeDiff':
|
|
1370
1528
|
expressions.push(expr.left.value, expr.right.value);
|
|
@@ -1399,8 +1557,18 @@ class QueryQuery extends QueryField {
|
|
|
1399
1557
|
}
|
|
1400
1558
|
this.addDependantExpr(resultStruct, context, expr.e, joinStack);
|
|
1401
1559
|
}
|
|
1402
|
-
else if ((0, malloy_types_1.
|
|
1403
|
-
|
|
1560
|
+
else if ((0, malloy_types_1.isFunctionCallFragment)(expr)) {
|
|
1561
|
+
if (expr.structPath) {
|
|
1562
|
+
this.addDependantPath(resultStruct, context, expr.structPath, true, joinStack);
|
|
1563
|
+
}
|
|
1564
|
+
// TODO Do we need to call `addStructToJoin` here in the case when there is no `structPath`
|
|
1565
|
+
// and the function is an aggregate function?
|
|
1566
|
+
for (const e of expr.args) {
|
|
1567
|
+
this.addDependantExpr(resultStruct, context, e, joinStack);
|
|
1568
|
+
}
|
|
1569
|
+
if ((0, malloy_types_1.expressionIsAnalytic)(expr.overload.returnType.expressionType)) {
|
|
1570
|
+
resultStruct.root().queryUsesPartitioning = true;
|
|
1571
|
+
}
|
|
1404
1572
|
}
|
|
1405
1573
|
}
|
|
1406
1574
|
}
|
|
@@ -1427,7 +1595,7 @@ class QueryQuery extends QueryField {
|
|
|
1427
1595
|
type: 'result',
|
|
1428
1596
|
});
|
|
1429
1597
|
this.addDependancies(resultStruct, field);
|
|
1430
|
-
if (
|
|
1598
|
+
if (isAggregateField(field)) {
|
|
1431
1599
|
if (this.firstSegment.type === 'project') {
|
|
1432
1600
|
throw new Error(`Aggregate Fields cannot be used in PROJECT - '${field.fieldDef.name}'`);
|
|
1433
1601
|
}
|
|
@@ -1486,7 +1654,7 @@ class QueryQuery extends QueryField {
|
|
|
1486
1654
|
for (const cond of list || []) {
|
|
1487
1655
|
const context = this.parent;
|
|
1488
1656
|
if ((which === 'having' && (0, malloy_types_1.expressionIsCalculation)(cond.expressionType)) ||
|
|
1489
|
-
(which === 'where' && cond.expressionType
|
|
1657
|
+
(which === 'where' && (0, malloy_types_1.expressionIsScalar)(cond.expressionType))) {
|
|
1490
1658
|
const sqlClause = this.generateExpressionFromExpr(resultStruct, context, cond.expression, undefined);
|
|
1491
1659
|
resultFilters.add(sqlClause);
|
|
1492
1660
|
}
|
|
@@ -1878,20 +2046,16 @@ class QueryQuery extends QueryField {
|
|
|
1878
2046
|
// BigQuery can't partition aggregate function except when the field has no
|
|
1879
2047
|
// expression. Additionally it can't partition by floats. We stuff expressions
|
|
1880
2048
|
// and numbers as strings into a lateral join when the query has ungrouped expressions
|
|
2049
|
+
const outputFieldName = `__lateral_join_bag.${outputName}`;
|
|
2050
|
+
fi.analyticalSQL = outputFieldName;
|
|
2051
|
+
output.lateralJoinSQLExpressions.push(`${exp} as ${outputName}`);
|
|
2052
|
+
output.sql.push(outputFieldName);
|
|
1881
2053
|
if (fi.f.fieldDef.type === 'number') {
|
|
1882
|
-
|
|
1883
|
-
output.sql.push(
|
|
1884
|
-
const outputFieldName = `__lateral_join_bag.${outputName}_string`;
|
|
1885
|
-
output.sql.push(outputFieldName);
|
|
2054
|
+
const outputFieldNameString = `${outputFieldName}_string`;
|
|
2055
|
+
output.sql.push(outputFieldNameString);
|
|
1886
2056
|
output.dimensionIndexes.push(output.fieldIndex++);
|
|
1887
2057
|
output.lateralJoinSQLExpressions.push(`CAST(${exp} as STRING) as ${outputName}_string`);
|
|
1888
|
-
fi.partitionSQL =
|
|
1889
|
-
}
|
|
1890
|
-
else {
|
|
1891
|
-
const outputFieldName = `__lateral_join_bag.${outputName}`;
|
|
1892
|
-
fi.partitionSQL = outputFieldName;
|
|
1893
|
-
output.lateralJoinSQLExpressions.push(`${exp} as ${outputName}`);
|
|
1894
|
-
output.sql.push(outputFieldName);
|
|
2058
|
+
fi.partitionSQL = outputFieldNameString;
|
|
1895
2059
|
}
|
|
1896
2060
|
}
|
|
1897
2061
|
else {
|
|
@@ -90,6 +90,11 @@ export interface ResultMetadata {
|
|
|
90
90
|
export interface ResultStructMetadata {
|
|
91
91
|
resultMetadata?: ResultStructMetadataDef;
|
|
92
92
|
}
|
|
93
|
+
export interface OutputFieldFragment {
|
|
94
|
+
type: 'outputField';
|
|
95
|
+
name: string;
|
|
96
|
+
}
|
|
97
|
+
export declare function isOutputFieldFragment(f: Fragment): f is OutputFieldFragment;
|
|
93
98
|
export interface FilterFragment {
|
|
94
99
|
type: 'filterExpression';
|
|
95
100
|
filterList: FilterExpression[];
|
|
@@ -111,20 +116,29 @@ export interface UngroupFragment {
|
|
|
111
116
|
fields?: string[];
|
|
112
117
|
}
|
|
113
118
|
export declare function isUngroupFragment(f: Fragment): f is UngroupFragment;
|
|
114
|
-
export
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
119
|
+
export interface FunctionParameterFragment {
|
|
120
|
+
type: 'function_parameter';
|
|
121
|
+
name: string;
|
|
122
|
+
}
|
|
123
|
+
export declare function isFunctionParameterFragment(f: Fragment): f is FunctionParameterFragment;
|
|
124
|
+
export interface FunctionCallFragment {
|
|
125
|
+
type: 'function_call';
|
|
126
|
+
overload: FunctionOverloadDef;
|
|
127
|
+
expressionType: ExpressionType;
|
|
128
|
+
args: Expr[];
|
|
129
|
+
structPath?: string;
|
|
130
|
+
}
|
|
131
|
+
export declare function isFunctionCallFragment(f: Fragment): f is FunctionCallFragment;
|
|
132
|
+
export interface SQLExpressionFragment {
|
|
133
|
+
type: 'sql_expression';
|
|
134
|
+
e: Expr;
|
|
126
135
|
}
|
|
127
|
-
export declare function
|
|
136
|
+
export declare function isSQLExpressionFragment(f: Fragment): f is SQLExpressionFragment;
|
|
137
|
+
export interface SpreadFragment {
|
|
138
|
+
type: 'spread';
|
|
139
|
+
e: Expr;
|
|
140
|
+
}
|
|
141
|
+
export declare function isSpreadFragment(f: Fragment): f is SpreadFragment;
|
|
128
142
|
export interface FieldFragment {
|
|
129
143
|
type: 'field';
|
|
130
144
|
path: string;
|
|
@@ -185,7 +199,7 @@ export interface TypecastFragment extends DialectFragmentBase {
|
|
|
185
199
|
export interface RegexpMatchFragment extends DialectFragmentBase {
|
|
186
200
|
function: 'regexpMatch';
|
|
187
201
|
expr: Expr;
|
|
188
|
-
regexp:
|
|
202
|
+
regexp: Expr;
|
|
189
203
|
}
|
|
190
204
|
export interface DivFragment extends DialectFragmentBase {
|
|
191
205
|
function: 'div';
|
|
@@ -202,8 +216,16 @@ export interface StringLiteralFragment extends DialectFragmentBase {
|
|
|
202
216
|
function: 'stringLiteral';
|
|
203
217
|
literal: string;
|
|
204
218
|
}
|
|
205
|
-
export
|
|
206
|
-
|
|
219
|
+
export interface RegexpLiteralFragment extends DialectFragmentBase {
|
|
220
|
+
function: 'regexpLiteral';
|
|
221
|
+
literal: string;
|
|
222
|
+
}
|
|
223
|
+
export interface NumberLiteralFragment extends DialectFragmentBase {
|
|
224
|
+
function: 'numberLiteral';
|
|
225
|
+
literal: string;
|
|
226
|
+
}
|
|
227
|
+
export declare type DialectFragment = DivFragment | TimeLiteralFragment | NowFragment | TimeDeltaFragment | TimeDiffFragment | TimeTruncFragment | TypecastFragment | TimeExtractFragment | StringLiteralFragment | RegexpLiteralFragment | NumberLiteralFragment | RegexpMatchFragment;
|
|
228
|
+
export declare type Fragment = string | ApplyFragment | ApplyValueFragment | FieldFragment | ParameterFragment | FilterFragment | OutputFieldFragment | AggregateFragment | UngroupFragment | DialectFragment | FunctionParameterFragment | FunctionCallFragment | SQLExpressionFragment | SpreadFragment;
|
|
207
229
|
export declare type Expr = Fragment[];
|
|
208
230
|
export interface TypedValue {
|
|
209
231
|
value: Expr;
|
|
@@ -224,15 +246,21 @@ declare type TagElement = Expr | string;
|
|
|
224
246
|
* ```
|
|
225
247
|
*/
|
|
226
248
|
export declare function mkExpr(src: TemplateStringsArray, ...exprs: TagElement[]): Expr;
|
|
227
|
-
export declare type ExpressionType = 'scalar' | 'aggregate' | '
|
|
249
|
+
export declare type ExpressionType = 'scalar' | 'aggregate' | 'scalar_analytic' | 'aggregate_analytic' | 'ungrouped_aggregate';
|
|
228
250
|
export interface Expression {
|
|
229
251
|
e?: Expr;
|
|
230
252
|
expressionType?: ExpressionType;
|
|
231
253
|
code?: string;
|
|
232
254
|
}
|
|
255
|
+
export declare function expressionIsScalar(e: ExpressionType | undefined): boolean;
|
|
233
256
|
export declare function expressionIsAggregate(e: ExpressionType | undefined): boolean;
|
|
257
|
+
export declare function expressionIsUngroupedAggregate(e: ExpressionType | undefined): boolean;
|
|
258
|
+
export declare function expressionInvolvesAggregate(e: ExpressionType | undefined): boolean;
|
|
234
259
|
export declare function expressionIsCalculation(e: ExpressionType | undefined): boolean;
|
|
260
|
+
export declare function expressionIsAnalytic(e: ExpressionType | undefined): boolean;
|
|
261
|
+
export declare function isExpressionTypeLEQ(e1: ExpressionType, e2: ExpressionType): boolean;
|
|
235
262
|
export declare function maxExpressionType(e1: ExpressionType, e2: ExpressionType): ExpressionType;
|
|
263
|
+
export declare function maxOfExpressionTypes(types: ExpressionType[]): ExpressionType;
|
|
236
264
|
interface JustExpression {
|
|
237
265
|
e: Expr;
|
|
238
266
|
}
|
|
@@ -452,6 +480,48 @@ export interface StructDef extends NamedObject, ResultStructMetadata, Filtered {
|
|
|
452
480
|
queryTimezone?: string;
|
|
453
481
|
dialect: string;
|
|
454
482
|
}
|
|
483
|
+
export declare type ExpressionValueType = AtomicFieldType | 'null' | 'unknown' | 'duration' | 'any' | 'regular expression';
|
|
484
|
+
export declare type FieldValueType = ExpressionValueType | 'turtle' | 'struct';
|
|
485
|
+
export interface ExpressionTypeDesc {
|
|
486
|
+
dataType: FieldValueType;
|
|
487
|
+
expressionType: ExpressionType;
|
|
488
|
+
rawType?: string;
|
|
489
|
+
evalSpace: EvalSpace;
|
|
490
|
+
}
|
|
491
|
+
export interface FunctionParamTypeDesc {
|
|
492
|
+
dataType: FieldValueType;
|
|
493
|
+
expressionType: ExpressionType | undefined;
|
|
494
|
+
evalSpace: EvalSpace;
|
|
495
|
+
}
|
|
496
|
+
export declare type EvalSpace = 'constant' | 'input' | 'output' | 'literal';
|
|
497
|
+
export declare function mergeEvalSpaces(...evalSpaces: EvalSpace[]): EvalSpace;
|
|
498
|
+
export interface TypeDesc {
|
|
499
|
+
dataType: FieldValueType;
|
|
500
|
+
expressionType: ExpressionType;
|
|
501
|
+
rawType?: string;
|
|
502
|
+
evalSpace: EvalSpace;
|
|
503
|
+
}
|
|
504
|
+
export interface FunctionParameterDef {
|
|
505
|
+
name: string;
|
|
506
|
+
allowedTypes: FunctionParamTypeDesc[];
|
|
507
|
+
isVariadic: boolean;
|
|
508
|
+
}
|
|
509
|
+
export interface FunctionOverloadDef {
|
|
510
|
+
returnType: TypeDesc;
|
|
511
|
+
needsWindowOrderBy?: boolean;
|
|
512
|
+
between?: {
|
|
513
|
+
preceding: number | string;
|
|
514
|
+
following: number | string;
|
|
515
|
+
};
|
|
516
|
+
params: FunctionParameterDef[];
|
|
517
|
+
dialect: {
|
|
518
|
+
[dialect: string]: Expr;
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
export interface FunctionDef extends NamedObject {
|
|
522
|
+
type: 'function';
|
|
523
|
+
overloads: FunctionOverloadDef[];
|
|
524
|
+
}
|
|
455
525
|
export interface SQLBlockStructDef extends StructDef {
|
|
456
526
|
structSource: SubquerySource;
|
|
457
527
|
declaredSQLBlock?: boolean;
|
|
@@ -480,7 +550,7 @@ export interface FilterExpression {
|
|
|
480
550
|
}
|
|
481
551
|
/** Get the output name for a NamedObject */
|
|
482
552
|
export declare function getIdentifier(n: AliasedName): string;
|
|
483
|
-
export declare type NamedModelObject = StructDef | NamedQuery;
|
|
553
|
+
export declare type NamedModelObject = StructDef | NamedQuery | FunctionDef;
|
|
484
554
|
/** Result of parsing a model file */
|
|
485
555
|
export interface ModelDef {
|
|
486
556
|
name: string;
|
|
@@ -489,6 +559,7 @@ export interface ModelDef {
|
|
|
489
559
|
}
|
|
490
560
|
/** Very common record type */
|
|
491
561
|
export declare type NamedStructDefs = Record<string, StructDef>;
|
|
562
|
+
export declare type NamedModelObjects = Record<string, NamedModelObject>;
|
|
492
563
|
export declare type QueryScalar = string | boolean | number | Date | Buffer | null;
|
|
493
564
|
/** One value in one column of returned data. */
|
|
494
565
|
export declare type QueryValue = QueryScalar | QueryData | QueryDataRow;
|