@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
|
@@ -44,6 +44,7 @@ class ExprCast extends expression_def_1.ExpressionDef {
|
|
|
44
44
|
dataType: this.castType,
|
|
45
45
|
expressionType: expr.expressionType,
|
|
46
46
|
value: (0, utils_1.compressExpr)((0, time_utils_1.castTo)(this.castType, expr.value, expr.dataType, this.safe)),
|
|
47
|
+
evalSpace: expr.evalSpace,
|
|
47
48
|
};
|
|
48
49
|
}
|
|
49
50
|
}
|
|
@@ -5,7 +5,7 @@ export declare class ExprCoalesce extends ExpressionDef {
|
|
|
5
5
|
readonly expr: ExpressionDef;
|
|
6
6
|
readonly altExpr: ExpressionDef;
|
|
7
7
|
elementType: string;
|
|
8
|
-
legalChildTypes: import("
|
|
8
|
+
legalChildTypes: import("../../../model").TypeDesc[];
|
|
9
9
|
constructor(expr: ExpressionDef, altExpr: ExpressionDef);
|
|
10
10
|
getExpression(fs: FieldSpace): ExprValue;
|
|
11
11
|
}
|
|
@@ -52,6 +52,7 @@ class ExprCoalesce extends expression_def_1.ExpressionDef {
|
|
|
52
52
|
...whenNull,
|
|
53
53
|
expressionType: (0, model_1.maxExpressionType)(maybeNull.expressionType, whenNull.expressionType),
|
|
54
54
|
value: (0, model_1.mkExpr) `COALESCE(${maybeNull.value},${whenNull.value})`,
|
|
55
|
+
evalSpace: (0, model_1.mergeEvalSpaces)(maybeNull.evalSpace, whenNull.evalSpace),
|
|
55
56
|
};
|
|
56
57
|
}
|
|
57
58
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ExprAggregateFunction } from './expr-aggregate-function';
|
|
2
2
|
import { ExpressionDef } from '../types/expression-def';
|
|
3
3
|
export declare class ExprCountDistinct extends ExprAggregateFunction {
|
|
4
|
-
legalChildTypes: import("
|
|
4
|
+
legalChildTypes: import("../../..").TypeDesc[];
|
|
5
5
|
constructor(expr: ExpressionDef);
|
|
6
6
|
}
|
|
@@ -6,7 +6,7 @@ export declare class ExprFilter extends ExpressionDef {
|
|
|
6
6
|
readonly expr: ExpressionDef;
|
|
7
7
|
readonly filter: Filter;
|
|
8
8
|
elementType: string;
|
|
9
|
-
legalChildTypes: import("
|
|
9
|
+
legalChildTypes: import("../../../model/malloy_types").TypeDesc[];
|
|
10
10
|
constructor(expr: ExpressionDef, filter: Filter);
|
|
11
11
|
getExpression(fs: FieldSpace): ExprValue;
|
|
12
12
|
}
|
|
@@ -38,7 +38,7 @@ class ExprFilter extends expression_def_1.ExpressionDef {
|
|
|
38
38
|
getExpression(fs) {
|
|
39
39
|
const testList = this.filter.getFilterList(fs);
|
|
40
40
|
const resultExpr = this.expr.getExpression(fs);
|
|
41
|
-
if (resultExpr.expressionType
|
|
41
|
+
if (!(0, malloy_types_1.expressionIsAggregate)(resultExpr.expressionType)) {
|
|
42
42
|
this.expr.log('Filtered expression requires an aggregate computation');
|
|
43
43
|
return resultExpr;
|
|
44
44
|
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import { FieldValueType } from '../../../model/malloy_types';
|
|
2
|
+
import { FieldReference } from '../query-items/field-references';
|
|
1
3
|
import { ExprValue } from '../types/expr-value';
|
|
2
4
|
import { ExpressionDef } from '../types/expression-def';
|
|
3
5
|
import { FieldSpace } from '../types/field-space';
|
|
4
6
|
export declare class ExprFunc extends ExpressionDef {
|
|
5
7
|
readonly name: string;
|
|
6
8
|
readonly args: ExpressionDef[];
|
|
9
|
+
readonly isRaw: boolean;
|
|
10
|
+
readonly rawType: FieldValueType | undefined;
|
|
11
|
+
readonly source?: FieldReference | undefined;
|
|
7
12
|
elementType: string;
|
|
8
|
-
constructor(name: string, args: ExpressionDef[]);
|
|
13
|
+
constructor(name: string, args: ExpressionDef[], isRaw: boolean, rawType: FieldValueType | undefined, source?: FieldReference | undefined);
|
|
9
14
|
getExpression(fs: FieldSpace): ExprValue;
|
|
10
15
|
}
|
|
@@ -24,40 +24,290 @@
|
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
25
|
exports.ExprFunc = void 0;
|
|
26
26
|
const malloy_types_1 = require("../../../model/malloy_types");
|
|
27
|
+
const ast_utils_1 = require("../ast-utils");
|
|
28
|
+
const struct_space_field_base_1 = require("../field-space/struct-space-field-base");
|
|
27
29
|
const expression_def_1 = require("../types/expression-def");
|
|
28
30
|
const utils_1 = require("./utils");
|
|
29
31
|
class ExprFunc extends expression_def_1.ExpressionDef {
|
|
30
|
-
constructor(name, args) {
|
|
32
|
+
constructor(name, args, isRaw, rawType, source) {
|
|
31
33
|
super({ args: args });
|
|
32
34
|
this.name = name;
|
|
33
35
|
this.args = args;
|
|
36
|
+
this.isRaw = isRaw;
|
|
37
|
+
this.rawType = rawType;
|
|
38
|
+
this.source = source;
|
|
34
39
|
this.elementType = 'function call()';
|
|
40
|
+
this.has({ source: source });
|
|
35
41
|
}
|
|
36
42
|
getExpression(fs) {
|
|
37
|
-
var _a, _b, _c;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
var _a, _b, _c, _d;
|
|
44
|
+
const argExprsWithoutImplicit = this.args.map(arg => arg.getExpression(fs));
|
|
45
|
+
if (this.isRaw) {
|
|
46
|
+
let expressionType = 'scalar';
|
|
47
|
+
let collectType;
|
|
48
|
+
const funcCall = [`${this.name}(`];
|
|
49
|
+
for (const expr of argExprsWithoutImplicit) {
|
|
50
|
+
expressionType = (0, malloy_types_1.maxExpressionType)(expressionType, expr.expressionType);
|
|
51
|
+
if (collectType) {
|
|
52
|
+
funcCall.push(',');
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
collectType = expr.dataType;
|
|
56
|
+
}
|
|
57
|
+
funcCall.push(...expr.value);
|
|
58
|
+
}
|
|
59
|
+
funcCall.push(')');
|
|
60
|
+
const dataType = (_b = (_a = this.rawType) !== null && _a !== void 0 ? _a : collectType) !== null && _b !== void 0 ? _b : 'number';
|
|
61
|
+
return {
|
|
62
|
+
dataType,
|
|
63
|
+
expressionType,
|
|
64
|
+
value: (0, utils_1.compressExpr)(funcCall),
|
|
65
|
+
evalSpace: (0, malloy_types_1.mergeEvalSpaces)(...argExprsWithoutImplicit.map(e => e.evalSpace)),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
// TODO this makes functions case-insensitive. This is weird that this is the only place
|
|
69
|
+
// where case insensitivity is thing.
|
|
70
|
+
const func = (_c = this.modelEntry(this.name.toLowerCase())) === null || _c === void 0 ? void 0 : _c.entry;
|
|
71
|
+
if (func === undefined) {
|
|
72
|
+
this.log(`Unknown function '${this.name}'. Use '${this.name}!(...)' to call a SQL function directly.`);
|
|
73
|
+
return {
|
|
74
|
+
dataType: 'unknown',
|
|
75
|
+
expressionType: 'scalar',
|
|
76
|
+
value: [],
|
|
77
|
+
evalSpace: 'constant',
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
else if (func.type !== 'function') {
|
|
81
|
+
this.log(`Cannot call '${this.name}', which is of type ${func.type}`);
|
|
82
|
+
return {
|
|
83
|
+
dataType: 'unknown',
|
|
84
|
+
expressionType: 'scalar',
|
|
85
|
+
value: [],
|
|
86
|
+
evalSpace: 'constant',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// Find the 'implicit argument' for aggregate functions called like `some_join.some_field.agg(...args)`
|
|
90
|
+
// where the full arg list is `(some_field, ...args)`.
|
|
91
|
+
let implicitExpr = undefined;
|
|
92
|
+
let structPath = (_d = this.source) === null || _d === void 0 ? void 0 : _d.refString;
|
|
93
|
+
if (this.source) {
|
|
94
|
+
const sourceFoot = this.source.getField(fs).found;
|
|
95
|
+
if (sourceFoot) {
|
|
96
|
+
const footType = sourceFoot.typeDesc();
|
|
97
|
+
if ((0, malloy_types_1.isAtomicFieldType)(footType.dataType)) {
|
|
98
|
+
implicitExpr = {
|
|
99
|
+
dataType: footType.dataType,
|
|
100
|
+
expressionType: footType.expressionType,
|
|
101
|
+
value: [{ type: 'field', path: this.source.refString }],
|
|
102
|
+
evalSpace: footType.evalSpace,
|
|
103
|
+
};
|
|
104
|
+
structPath = this.source.sourceString;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
if (!(sourceFoot instanceof struct_space_field_base_1.StructSpaceFieldBase)) {
|
|
108
|
+
const message = `Aggregate source cannot be a ${footType.dataType}`;
|
|
109
|
+
this.log(message);
|
|
110
|
+
return (0, ast_utils_1.errorFor)(message);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
46
113
|
}
|
|
47
114
|
else {
|
|
48
|
-
|
|
115
|
+
const message = `Reference to undefined value ${this.source.refString}`;
|
|
116
|
+
this.log(message);
|
|
117
|
+
return (0, ast_utils_1.errorFor)(message);
|
|
49
118
|
}
|
|
50
|
-
funcCall.push(...expr.value);
|
|
51
119
|
}
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
120
|
+
// Construct the full args list including the implicit arg.
|
|
121
|
+
const argExprs = [
|
|
122
|
+
...(implicitExpr ? [implicitExpr] : []),
|
|
123
|
+
...argExprsWithoutImplicit,
|
|
124
|
+
];
|
|
125
|
+
const result = findOverload(func, argExprs);
|
|
126
|
+
if (result === undefined) {
|
|
127
|
+
this.log(`No matching overload for function ${this.name}(${argExprs
|
|
128
|
+
.map(e => e.dataType)
|
|
129
|
+
.join(', ')})`);
|
|
130
|
+
return {
|
|
131
|
+
dataType: 'unknown',
|
|
132
|
+
expressionType: 'scalar',
|
|
133
|
+
value: [],
|
|
134
|
+
evalSpace: 'constant',
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
const { overload, expressionTypeErrors, evalSpaceErrors, nullabilityErrors } = result;
|
|
138
|
+
// Report errors for expression type mismatch
|
|
139
|
+
for (const error of expressionTypeErrors) {
|
|
140
|
+
const adjustedIndex = error.argIndex - (implicitExpr ? 1 : 0);
|
|
141
|
+
const allowed = (0, malloy_types_1.expressionIsScalar)(error.maxExpressionType)
|
|
142
|
+
? 'scalar'
|
|
143
|
+
: 'scalar or aggregate';
|
|
144
|
+
const arg = this.args[adjustedIndex];
|
|
145
|
+
arg.log(`Parameter ${error.argIndex + 1} ('${error.param.name}') of ${this.name} must be ${allowed}, but received ${error.actualExpressionType}`);
|
|
146
|
+
}
|
|
147
|
+
// Report errors for eval space mismatch
|
|
148
|
+
for (const error of evalSpaceErrors) {
|
|
149
|
+
const adjustedIndex = error.argIndex - (implicitExpr ? 1 : 0);
|
|
150
|
+
const allowed = error.maxEvalSpace === 'literal'
|
|
151
|
+
? 'literal'
|
|
152
|
+
: error.maxEvalSpace === 'constant'
|
|
153
|
+
? 'literal or constant'
|
|
154
|
+
: 'literal, constant or output';
|
|
155
|
+
const arg = this.args[adjustedIndex];
|
|
156
|
+
arg.log(`Parameter ${error.argIndex + 1} ('${error.param.name}') of ${this.name} must be ${allowed}, but received ${error.actualEvalSpace}`);
|
|
157
|
+
}
|
|
158
|
+
// Report nullability errors
|
|
159
|
+
for (const error of nullabilityErrors) {
|
|
160
|
+
const adjustedIndex = error.argIndex - (implicitExpr ? 1 : 0);
|
|
161
|
+
const arg = this.args[adjustedIndex];
|
|
162
|
+
arg.log(`Parameter ${error.argIndex + 1} ('${error.param.name}') of ${this.name} must not be a literal null`);
|
|
163
|
+
}
|
|
164
|
+
const type = overload.returnType;
|
|
165
|
+
const expressionType = (0, malloy_types_1.maxOfExpressionTypes)([
|
|
166
|
+
type.expressionType,
|
|
167
|
+
...argExprs.map(e => e.expressionType),
|
|
168
|
+
]);
|
|
169
|
+
if (!(0, malloy_types_1.expressionIsAggregate)(overload.returnType.expressionType) &&
|
|
170
|
+
this.source !== undefined) {
|
|
171
|
+
this.log(`Cannot call function ${this.name}(${argExprs
|
|
172
|
+
.map(e => e.dataType)
|
|
173
|
+
.join(', ')}) with source`);
|
|
174
|
+
return {
|
|
175
|
+
dataType: 'unknown',
|
|
176
|
+
expressionType,
|
|
177
|
+
value: [],
|
|
178
|
+
evalSpace: 'constant',
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
const funcCall = [
|
|
182
|
+
{
|
|
183
|
+
type: 'function_call',
|
|
184
|
+
overload,
|
|
185
|
+
args: argExprs.map(x => x.value),
|
|
186
|
+
expressionType,
|
|
187
|
+
structPath,
|
|
188
|
+
},
|
|
189
|
+
];
|
|
190
|
+
if (type.dataType === 'any') {
|
|
191
|
+
this.log(`Invalid return type ${type.dataType} for function '${this.name}'`);
|
|
192
|
+
return {
|
|
193
|
+
dataType: 'unknown',
|
|
194
|
+
expressionType,
|
|
195
|
+
value: [],
|
|
196
|
+
evalSpace: 'constant',
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
const maxEvalSpace = (0, malloy_types_1.mergeEvalSpaces)(...argExprs.map(e => e.evalSpace));
|
|
200
|
+
// If the merged eval space of all args is constant, the result is constant.
|
|
201
|
+
// If the expression is scalar, then the eval space is that merged eval space.
|
|
202
|
+
// If the expression is aggregate, then then eval space is always 'output'.
|
|
203
|
+
// If the expression is analytic, the eval space doesn't really matter.. It's really
|
|
204
|
+
// 'super_output' but that's not useful to us, so it's just 'output'.
|
|
205
|
+
const evalSpace = maxEvalSpace === 'constant'
|
|
206
|
+
? 'constant'
|
|
207
|
+
: (0, malloy_types_1.expressionIsScalar)(expressionType)
|
|
208
|
+
? maxEvalSpace
|
|
209
|
+
: 'output';
|
|
55
210
|
return {
|
|
56
|
-
dataType: dataType,
|
|
211
|
+
dataType: type.dataType,
|
|
57
212
|
expressionType,
|
|
58
213
|
value: (0, utils_1.compressExpr)(funcCall),
|
|
214
|
+
evalSpace,
|
|
59
215
|
};
|
|
60
216
|
}
|
|
61
217
|
}
|
|
62
218
|
exports.ExprFunc = ExprFunc;
|
|
219
|
+
function findOverload(func, args) {
|
|
220
|
+
for (const overload of func.overloads) {
|
|
221
|
+
let paramIndex = 0;
|
|
222
|
+
let ok = true;
|
|
223
|
+
let matchedVariadic = false;
|
|
224
|
+
const expressionTypeErrors = [];
|
|
225
|
+
const evalSpaceErrors = [];
|
|
226
|
+
const nullabilityErrors = [];
|
|
227
|
+
for (let argIndex = 0; argIndex < args.length; argIndex++) {
|
|
228
|
+
const arg = args[argIndex];
|
|
229
|
+
const param = overload.params[paramIndex];
|
|
230
|
+
if (param === undefined) {
|
|
231
|
+
ok = false;
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
const argOk = param.allowedTypes.some(paramT => {
|
|
235
|
+
// Check whether types match (allowing for nullability errors, expression type errors,
|
|
236
|
+
// eval space errors, and unknown types due to prior errors in args)
|
|
237
|
+
const dataTypeMatch = paramT.dataType === arg.dataType ||
|
|
238
|
+
paramT.dataType === 'any' ||
|
|
239
|
+
// TODO We should consider whether `nulls` should always be allowed. It probably
|
|
240
|
+
// does not make sense to limit function calls to not allow nulls, since have
|
|
241
|
+
// so little control over nullability.
|
|
242
|
+
arg.dataType === 'null' ||
|
|
243
|
+
// TODO I've included this because it means that errors cascade a bit less...
|
|
244
|
+
// I think we may want to add an `error` type for nodes generated from errors,
|
|
245
|
+
// then make `error` propagate without generating more errors.
|
|
246
|
+
arg.dataType === 'unknown';
|
|
247
|
+
// Check expression type errors
|
|
248
|
+
if (paramT.expressionType) {
|
|
249
|
+
const expressionTypeMatch = (0, malloy_types_1.isExpressionTypeLEQ)(arg.expressionType, paramT.expressionType);
|
|
250
|
+
if (!expressionTypeMatch) {
|
|
251
|
+
expressionTypeErrors.push({
|
|
252
|
+
argIndex,
|
|
253
|
+
maxExpressionType: paramT.expressionType,
|
|
254
|
+
actualExpressionType: arg.expressionType,
|
|
255
|
+
param,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Check eval space errors
|
|
260
|
+
if (
|
|
261
|
+
// Error if literal is required but arg is not literal
|
|
262
|
+
(paramT.evalSpace === 'literal' && arg.evalSpace !== 'literal') ||
|
|
263
|
+
// Error if constant is required but arg is input/output
|
|
264
|
+
(paramT.evalSpace === 'constant' &&
|
|
265
|
+
(arg.evalSpace === 'input' || arg.evalSpace === 'output')) ||
|
|
266
|
+
// Error if output is required but arg is input
|
|
267
|
+
(paramT.evalSpace === 'output' && arg.evalSpace === 'input')) {
|
|
268
|
+
evalSpaceErrors.push({
|
|
269
|
+
argIndex,
|
|
270
|
+
param,
|
|
271
|
+
maxEvalSpace: paramT.evalSpace,
|
|
272
|
+
actualEvalSpace: arg.evalSpace,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
// Check nullability errors. For now we only require that literal arguments must be
|
|
276
|
+
// non-null, but in the future we may allow parameters to say whether they can accept literal
|
|
277
|
+
// nulls.
|
|
278
|
+
if (paramT.evalSpace === 'literal' && arg.dataType === 'null') {
|
|
279
|
+
nullabilityErrors.push({
|
|
280
|
+
argIndex,
|
|
281
|
+
param,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
return dataTypeMatch;
|
|
285
|
+
});
|
|
286
|
+
if (!argOk) {
|
|
287
|
+
ok = false;
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
if (param.isVariadic) {
|
|
291
|
+
if (argIndex === args.length - 1) {
|
|
292
|
+
matchedVariadic = true;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
paramIndex++;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (!matchedVariadic &&
|
|
300
|
+
(paramIndex !== args.length || paramIndex !== overload.params.length)) {
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
if (ok) {
|
|
304
|
+
return {
|
|
305
|
+
overload,
|
|
306
|
+
expressionTypeErrors,
|
|
307
|
+
evalSpaceErrors,
|
|
308
|
+
nullabilityErrors,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
63
313
|
//# sourceMappingURL=expr-func.js.map
|
|
@@ -15,7 +15,7 @@ export declare class ExprGranularTime extends ExpressionDef {
|
|
|
15
15
|
readonly units: TimestampUnit;
|
|
16
16
|
readonly truncate: boolean;
|
|
17
17
|
elementType: string;
|
|
18
|
-
legalChildTypes: import("
|
|
18
|
+
legalChildTypes: import("../../../model/malloy_types").TypeDesc[];
|
|
19
19
|
constructor(expr: ExpressionDef, units: TimestampUnit, truncate: boolean);
|
|
20
20
|
granular(): boolean;
|
|
21
21
|
getExpression(fs: FieldSpace): ExprValue;
|
|
@@ -40,8 +40,18 @@ class ExprIdReference extends expression_def_1.ExpressionDef {
|
|
|
40
40
|
getExpression(fs) {
|
|
41
41
|
const def = this.fieldReference.getField(fs);
|
|
42
42
|
if (def.found) {
|
|
43
|
+
if (def.found.typeDesc().evalSpace === 'output') {
|
|
44
|
+
return {
|
|
45
|
+
...def.found.typeDesc(),
|
|
46
|
+
value: [{ type: 'outputField', name: this.refString }],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
43
49
|
const value = [{ type: def.found.refType, path: this.refString }];
|
|
44
50
|
const td = def.found.typeDesc();
|
|
51
|
+
// We think that aggregates are more 'output' like, but maybe we will reconsider that...
|
|
52
|
+
if ((0, malloy_types_1.expressionIsAggregate)(td.expressionType)) {
|
|
53
|
+
td.evalSpace = 'output';
|
|
54
|
+
}
|
|
45
55
|
return { ...td, value };
|
|
46
56
|
}
|
|
47
57
|
this.log(def.error);
|
|
@@ -56,6 +66,8 @@ class ExprIdReference extends expression_def_1.ExpressionDef {
|
|
|
56
66
|
return {
|
|
57
67
|
dataType: 'boolean',
|
|
58
68
|
expressionType: lval.expressionType,
|
|
69
|
+
// TODO not sure about the input-ness of parameters
|
|
70
|
+
evalSpace: (0, malloy_types_1.mergeEvalSpaces)(lval.evalSpace, 'input'),
|
|
59
71
|
value: [
|
|
60
72
|
{
|
|
61
73
|
type: 'apply',
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ExprValue } from '../types/expr-value';
|
|
2
|
-
import { FieldValueType } from '
|
|
2
|
+
import { FieldValueType } from '../../../model';
|
|
3
3
|
import { ExprAggregateFunction } from './expr-aggregate-function';
|
|
4
4
|
import { ExpressionDef } from '../types/expression-def';
|
|
5
5
|
export declare class ExprMax extends ExprAggregateFunction {
|
|
6
|
-
legalChildTypes: import("
|
|
6
|
+
legalChildTypes: import("../../../model").TypeDesc[];
|
|
7
7
|
constructor(expr: ExpressionDef);
|
|
8
8
|
returns(forExpression: ExprValue): FieldValueType;
|
|
9
9
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ExprValue } from '../types/expr-value';
|
|
2
|
-
import { FieldValueType } from '
|
|
2
|
+
import { FieldValueType } from '../../../model';
|
|
3
3
|
import { ExprAggregateFunction } from './expr-aggregate-function';
|
|
4
4
|
import { ExpressionDef } from '../types/expression-def';
|
|
5
5
|
export declare class ExprMin extends ExprAggregateFunction {
|
|
6
|
-
legalChildTypes: import("
|
|
6
|
+
legalChildTypes: import("../../../model").TypeDesc[];
|
|
7
7
|
constructor(expr: ExpressionDef);
|
|
8
8
|
returns(forExpression: ExprValue): FieldValueType;
|
|
9
9
|
}
|
|
@@ -4,7 +4,7 @@ import { FieldSpace } from '../types/field-space';
|
|
|
4
4
|
import { Unary } from './unary';
|
|
5
5
|
export declare class ExprNot extends Unary {
|
|
6
6
|
elementType: string;
|
|
7
|
-
legalChildTypes: import("
|
|
7
|
+
legalChildTypes: import("../../..").TypeDesc[];
|
|
8
8
|
constructor(expr: ExpressionDef);
|
|
9
9
|
getExpression(fs: FieldSpace): ExprValue;
|
|
10
10
|
}
|
|
@@ -33,6 +33,8 @@ class ExprNow extends expression_def_1.ExpressionDef {
|
|
|
33
33
|
return {
|
|
34
34
|
dataType: 'timestamp',
|
|
35
35
|
expressionType: 'scalar',
|
|
36
|
+
// `now` is considered to be a constant, at least in the dialects we support today
|
|
37
|
+
evalSpace: 'constant',
|
|
36
38
|
value: [
|
|
37
39
|
{
|
|
38
40
|
type: 'dialect',
|
|
@@ -35,7 +35,11 @@ class ExprNumber extends expression_def_1.ExpressionDef {
|
|
|
35
35
|
return this.constantExpression();
|
|
36
36
|
}
|
|
37
37
|
constantExpression() {
|
|
38
|
-
return {
|
|
38
|
+
return {
|
|
39
|
+
...fragtype_utils_1.FT.numberT,
|
|
40
|
+
evalSpace: 'literal',
|
|
41
|
+
value: [{ type: 'dialect', function: 'numberLiteral', literal: this.n }],
|
|
42
|
+
};
|
|
39
43
|
}
|
|
40
44
|
}
|
|
41
45
|
exports.ExprNumber = ExprNumber;
|
|
@@ -34,7 +34,10 @@ class ExprRegEx extends expression_def_1.ExpressionDef {
|
|
|
34
34
|
return {
|
|
35
35
|
dataType: 'regular expression',
|
|
36
36
|
expressionType: 'scalar',
|
|
37
|
-
value: [
|
|
37
|
+
value: [
|
|
38
|
+
{ type: 'dialect', function: 'regexpLiteral', literal: this.regex },
|
|
39
|
+
],
|
|
40
|
+
evalSpace: 'literal',
|
|
38
41
|
};
|
|
39
42
|
}
|
|
40
43
|
}
|
|
@@ -96,6 +96,7 @@ class ExprTimeExtract extends expression_def_1.ExpressionDef {
|
|
|
96
96
|
return {
|
|
97
97
|
dataType: 'number',
|
|
98
98
|
expressionType: (0, malloy_types_1.maxExpressionType)(first.expressionType, last.expressionType),
|
|
99
|
+
evalSpace: (0, malloy_types_1.mergeEvalSpaces)(first.evalSpace, last.evalSpace),
|
|
99
100
|
value: [
|
|
100
101
|
{
|
|
101
102
|
type: 'dialect',
|
|
@@ -113,6 +114,7 @@ class ExprTimeExtract extends expression_def_1.ExpressionDef {
|
|
|
113
114
|
return {
|
|
114
115
|
dataType: 'number',
|
|
115
116
|
expressionType: argV.expressionType,
|
|
117
|
+
evalSpace: argV.evalSpace,
|
|
116
118
|
value: [
|
|
117
119
|
{
|
|
118
120
|
type: 'dialect',
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
import { FieldValueType } from '../../../model/malloy_types';
|
|
1
2
|
import { ExprValue } from '../types/expr-value';
|
|
2
3
|
import { ExpressionDef } from '../types/expression-def';
|
|
3
4
|
import { FieldName, FieldSpace } from '../types/field-space';
|
|
4
|
-
import { FieldValueType } from '../types/type-desc';
|
|
5
5
|
export declare class ExprUngroup extends ExpressionDef {
|
|
6
6
|
readonly control: 'all' | 'exclude';
|
|
7
7
|
readonly expr: ExpressionDef;
|
|
8
8
|
readonly fields: FieldName[];
|
|
9
|
-
legalChildTypes: import("
|
|
9
|
+
legalChildTypes: import("../../../model/malloy_types").TypeDesc[];
|
|
10
10
|
elementType: string;
|
|
11
11
|
constructor(control: 'all' | 'exclude', expr: ExpressionDef, fields: FieldName[]);
|
|
12
12
|
returns(_forExpression: ExprValue): FieldValueType;
|
|
@@ -27,7 +27,6 @@ const malloy_types_1 = require("../../../model/malloy_types");
|
|
|
27
27
|
const ast_utils_1 = require("../ast-utils");
|
|
28
28
|
const query_spaces_1 = require("../field-space/query-spaces");
|
|
29
29
|
const fragtype_utils_1 = require("../fragtype-utils");
|
|
30
|
-
const field_declaration_1 = require("../query-items/field-declaration");
|
|
31
30
|
const expression_def_1 = require("../types/expression-def");
|
|
32
31
|
class ExprUngroup extends expression_def_1.ExpressionDef {
|
|
33
32
|
constructor(control, expr, fields) {
|
|
@@ -47,21 +46,26 @@ class ExprUngroup extends expression_def_1.ExpressionDef {
|
|
|
47
46
|
this.expr.log(`${this.control}() expression must be an aggregate`);
|
|
48
47
|
return (0, ast_utils_1.errorFor)('ungrouped scalar');
|
|
49
48
|
}
|
|
49
|
+
if ((0, malloy_types_1.expressionIsUngroupedAggregate)(exprVal.expressionType)) {
|
|
50
|
+
this.expr.log(`${this.control}() expression must not already be ungrouped`);
|
|
51
|
+
return (0, ast_utils_1.errorFor)('doubly-ungrouped aggregate');
|
|
52
|
+
}
|
|
50
53
|
const ungroup = {
|
|
51
54
|
type: this.control,
|
|
52
55
|
e: exprVal.value,
|
|
53
56
|
};
|
|
54
57
|
if (this.typeCheck(this.expr, { ...exprVal, expressionType: 'scalar' })) {
|
|
55
58
|
if (this.fields.length > 0) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
if (!fs.isQueryFieldSpace()) {
|
|
60
|
+
this.log(`${this.control}() must be in a query -- weird internal error`);
|
|
61
|
+
return (0, ast_utils_1.errorFor)('ungroup query check');
|
|
59
62
|
}
|
|
60
|
-
|
|
63
|
+
const output = fs.outputSpace();
|
|
64
|
+
if (!(output instanceof query_spaces_1.QuerySpace)) {
|
|
65
|
+
// TODO maybe make OutputSpace return an interface which has checkUngroup
|
|
61
66
|
this.log(`${this.control}() must be in a query -- weird internal error`);
|
|
62
67
|
return (0, ast_utils_1.errorFor)('ungroup query check');
|
|
63
68
|
}
|
|
64
|
-
const output = qs.result;
|
|
65
69
|
const dstFields = [];
|
|
66
70
|
const isExclude = this.control === 'exclude';
|
|
67
71
|
for (const mustBeInOutput of this.fields) {
|
|
@@ -70,12 +74,16 @@ class ExprUngroup extends expression_def_1.ExpressionDef {
|
|
|
70
74
|
});
|
|
71
75
|
dstFields.push(mustBeInOutput.refString);
|
|
72
76
|
}
|
|
77
|
+
// TODO maybe now we can just look up the fields in the output space now and ensure
|
|
78
|
+
// they're all there, rather than waiting until the query is finished to do it?
|
|
79
|
+
// See `order_by` for an example of how this could work.
|
|
73
80
|
ungroup.fields = dstFields;
|
|
74
81
|
}
|
|
75
82
|
return {
|
|
76
83
|
dataType: this.returns(exprVal),
|
|
77
|
-
expressionType: '
|
|
84
|
+
expressionType: 'ungrouped_aggregate',
|
|
78
85
|
value: [ungroup],
|
|
86
|
+
evalSpace: 'output',
|
|
79
87
|
};
|
|
80
88
|
}
|
|
81
89
|
this.log(`${this.control}() incompatible type`);
|
|
@@ -7,7 +7,7 @@ export declare class ForRange extends ExpressionDef {
|
|
|
7
7
|
readonly duration: ExpressionDef;
|
|
8
8
|
readonly timeframe: Timeframe;
|
|
9
9
|
elementType: string;
|
|
10
|
-
legalChildTypes: import("
|
|
10
|
+
legalChildTypes: import("../../..").TypeDesc[];
|
|
11
11
|
constructor(from: ExpressionDef, duration: ExpressionDef, timeframe: Timeframe);
|
|
12
12
|
apply(fs: FieldSpace, op: string, expr: ExpressionDef): ExprValue;
|
|
13
13
|
requestExpression(_fs: FieldSpace): undefined;
|