@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
|
@@ -223,9 +223,346 @@ describe('model statements', () => {
|
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
225
|
`));
|
|
226
|
+
describe('query operation typechecking', () => {
|
|
227
|
+
describe('field declarations', () => {
|
|
228
|
+
test('cannot use aggregate in group_by', () => {
|
|
229
|
+
expect('query: a -> { group_by: s is count()}').compileToFailWith('Cannot use an aggregate field in a group_by operation, did you mean to use an aggregate operation instead?');
|
|
230
|
+
});
|
|
231
|
+
test('cannot use ungrouped_aggregate in group_by', () => {
|
|
232
|
+
expect('query: a -> { group_by: s is all(count())}').compileToFailWith('Cannot use an aggregate field in a group_by operation, did you mean to use an aggregate operation instead?');
|
|
233
|
+
});
|
|
234
|
+
test('cannot use analytic in group_by', () => {
|
|
235
|
+
expect('query: a -> { group_by: s is row_number()}').compileToFailWith('Cannot use an analytic field in a group_by operation, did you mean to use a calculate operation instead?');
|
|
236
|
+
});
|
|
237
|
+
test('cannot use aggregate in dimension', () => {
|
|
238
|
+
expect('source: a1 is a { dimension: s is count()}').compileToFailWith('Cannot use an aggregate field in a dimension declaration, did you mean to use a measure declaration instead?');
|
|
239
|
+
});
|
|
240
|
+
test('cannot use ungrouped_aggregate in dimension', () => {
|
|
241
|
+
expect('source: a1 is a { dimension: s is all(count())}').compileToFailWith('Cannot use an aggregate field in a dimension declaration, did you mean to use a measure declaration instead?');
|
|
242
|
+
});
|
|
243
|
+
test('cannot use analytic in dimension', () => {
|
|
244
|
+
expect('source: a1 is a { dimension: s is row_number()}').compileToFailWith('Cannot use an analytic field in a dimension declaration');
|
|
245
|
+
});
|
|
246
|
+
test('cannot use scalar in measure', () => {
|
|
247
|
+
expect('source: a1 is a { measure: s is 1}').compileToFailWith('Cannot use a scalar field in a measure declaration, did you mean to use a dimension declaration instead?');
|
|
248
|
+
});
|
|
249
|
+
test('cannot use analytic in measure', () => {
|
|
250
|
+
expect('source: a1 is a { measure: s is lag(count())}').compileToFailWith('Cannot use an analytic field in a measure declaration');
|
|
251
|
+
});
|
|
252
|
+
test('cannot use scalar in aggregate', () => {
|
|
253
|
+
expect('query: a -> { aggregate: s is 1}').compileToFailWith('Cannot use a scalar field in an aggregate operation, did you mean to use a group_by or project operation instead?');
|
|
254
|
+
});
|
|
255
|
+
test('cannot use analytic in aggregate', () => {
|
|
256
|
+
expect('query: a -> { aggregate: s is lag(count())}').compileToFailWith('Cannot use an analytic field in an aggregate operation, did you mean to use a calculate operation instead?');
|
|
257
|
+
});
|
|
258
|
+
test('cannot use scalar in calculate', () => {
|
|
259
|
+
expect('query: a -> { group_by: a is 1; calculate: s is 1 }').compileToFailWith('Cannot use a scalar field in a calculate operation, did you mean to use a group_by or project operation instead?');
|
|
260
|
+
});
|
|
261
|
+
test('cannot use aggregate in calculate', () => {
|
|
262
|
+
expect('query: a -> { group_by: a is 1; calculate: s is count() }').compileToFailWith('Cannot use an aggregate field in a calculate operation, did you mean to use an aggregate operation instead?');
|
|
263
|
+
});
|
|
264
|
+
test('cannot use aggregate in project', () => {
|
|
265
|
+
expect('query: a -> { project: s is count() }').compileToFailWith('Cannot use an aggregate field in a project operation, did you mean to use an aggregate operation instead?');
|
|
266
|
+
});
|
|
267
|
+
test('cannot use analytic in project', () => {
|
|
268
|
+
expect('query: a -> { project: s is row_number() }').compileToFailWith('Cannot use an analytic field in a project operation, did you mean to use a calculate operation instead?');
|
|
269
|
+
});
|
|
270
|
+
test('cannot use analytic in declare', () => {
|
|
271
|
+
expect('query: a -> { group_by: a is 1; declare: s is row_number() }').compileToFailWith('Analytic expressions can not be used in a declare block');
|
|
272
|
+
});
|
|
273
|
+
test('cannot use aggregate in index', () => {
|
|
274
|
+
expect('query: a { measure: acount is count() } -> { index: acount }').compileToFailWith('Cannot use an aggregate field in an index operation');
|
|
275
|
+
});
|
|
276
|
+
test('can use aggregate in except', modelOK(`
|
|
277
|
+
source: b1 is a { measure: acount is count() }
|
|
278
|
+
source: c1 is b1 { except: acount }
|
|
279
|
+
`));
|
|
280
|
+
});
|
|
281
|
+
describe('field references', () => {
|
|
282
|
+
test('cannot use aggregate in group_by', () => {
|
|
283
|
+
expect('query: a -> { declare: acount is count(); group_by: acount }').compileToFailWith('Cannot use an aggregate field in a group_by operation, did you mean to use an aggregate operation instead?');
|
|
284
|
+
});
|
|
285
|
+
test('cannot use query in group_by', () => {
|
|
286
|
+
expect('query: a { query: q is { group_by: x is 1 } } -> { group_by: q }').compileToFailWith('Cannot use a query field in a group_by operation, did you mean to use a nest operation instead?');
|
|
287
|
+
});
|
|
288
|
+
test('cannot use scalar in aggregate', () => {
|
|
289
|
+
expect('query: a -> { declare: aconst is 1; aggregate: aconst }').compileToFailWith('Cannot use a scalar field in an aggregate operation, did you mean to use a group_by or project operation instead?');
|
|
290
|
+
});
|
|
291
|
+
test('cannot use scalar in calculate', () => {
|
|
292
|
+
expect('query: a -> { declare: aconst is 1; group_by: x is 1; calculate: aconst }').compileToFailWith('Cannot use a scalar field in a calculate operation, did you mean to use a group_by or project operation instead?');
|
|
293
|
+
});
|
|
294
|
+
test('cannot use aggregate in calculate', () => {
|
|
295
|
+
expect('query: a -> { declare: acount is count(); group_by: x is 1; calculate: acount }').compileToFailWith('Cannot use an aggregate field in a calculate operation, did you mean to use an aggregate operation instead?');
|
|
296
|
+
});
|
|
297
|
+
test('cannot use query in project', () => {
|
|
298
|
+
expect('query: a { query: q is { group_by: x is 1 } } -> { project: q }').compileToFailWith('Cannot use a query field in a project operation, did you mean to use a nest operation instead?');
|
|
299
|
+
});
|
|
300
|
+
test('cannot use query in index', () => {
|
|
301
|
+
expect('query: a { query: q is { group_by: x is 1 } } -> { index: q }').compileToFailWith('Cannot use a query field in an index operation');
|
|
302
|
+
});
|
|
303
|
+
test('cannot use query in calculate', () => {
|
|
304
|
+
expect('query: a { query: q is { group_by: x is 1 } } -> { group_by: x is 1; calculate: q }').compileToFailWith('Cannot use a query field in a calculate operation, did you mean to use a nest operation instead?');
|
|
305
|
+
});
|
|
306
|
+
test('cannot use query in aggregate', () => {
|
|
307
|
+
expect('query: a { query: q is { group_by: x is 1 } } -> { aggregate: q }').compileToFailWith('Cannot use a query field in an aggregate operation, did you mean to use a nest operation instead?');
|
|
308
|
+
});
|
|
309
|
+
test('cannot use aggregate in calculate, preserved over refinement', () => {
|
|
310
|
+
expect(`query: a1 is a -> {
|
|
311
|
+
aggregate: c is count()
|
|
312
|
+
}
|
|
313
|
+
query: -> a1 {
|
|
314
|
+
calculate: b is c
|
|
315
|
+
}`).compileToFailWith('Cannot use an aggregate field in a calculate operation, did you mean to use an aggregate operation instead?');
|
|
316
|
+
});
|
|
317
|
+
test('cannot use scalar in calculate, preserved over refinement', () => {
|
|
318
|
+
expect(`query: a1 is a -> {
|
|
319
|
+
group_by: c is 1
|
|
320
|
+
}
|
|
321
|
+
query: -> a1 {
|
|
322
|
+
calculate: b is c
|
|
323
|
+
}`).compileToFailWith('Cannot use a scalar field in a calculate operation, did you mean to use a group_by or project operation instead?');
|
|
324
|
+
});
|
|
325
|
+
test('cannot use analytic in group_by, preserved over refinement', () => {
|
|
326
|
+
expect(`query: a1 is a -> {
|
|
327
|
+
group_by: c is 1
|
|
328
|
+
calculate: c2 is lag(c)
|
|
329
|
+
}
|
|
330
|
+
query: -> a1 {
|
|
331
|
+
group_by: b is c2
|
|
332
|
+
}`).compileToFailWith(
|
|
333
|
+
// c2 is not defined because group_by doesn't know to look in the output space
|
|
334
|
+
"'c2' is not defined", "Cannot define 'b', value has unknown type");
|
|
335
|
+
});
|
|
336
|
+
test('cannot use analytic in order_by, preserved over refinement', () => {
|
|
337
|
+
expect(`query: a1 is a -> {
|
|
338
|
+
group_by: c is 1
|
|
339
|
+
calculate: c2 is lag(c)
|
|
340
|
+
}
|
|
341
|
+
query: -> a1 {
|
|
342
|
+
order_by: c2
|
|
343
|
+
}`).compileToFailWith('Illegal order by of analytic field c2');
|
|
344
|
+
});
|
|
345
|
+
test('cannot ungroup an ungrouped', () => {
|
|
346
|
+
expect(`query: a1 is a -> {
|
|
347
|
+
group_by: c is 1
|
|
348
|
+
aggregate: c2 is all(all(sum(ai)))
|
|
349
|
+
}`).compileToFailWith('all() expression must not already be ungrouped', "Cannot define 'c2', value has unknown type");
|
|
350
|
+
});
|
|
351
|
+
test('cannot aggregate an ungrouped', () => {
|
|
352
|
+
expect(`query: a1 is a -> {
|
|
353
|
+
group_by: c is 1
|
|
354
|
+
aggregate: c2 is sum(all(sum(ai)))
|
|
355
|
+
}`).compileToFailWith('Aggregate expression cannot be aggregate', "Cannot define 'c2', value has unknown type");
|
|
356
|
+
});
|
|
357
|
+
test('cannot aggregate an aggregate', () => {
|
|
358
|
+
expect(`query: a1 is a -> {
|
|
359
|
+
group_by: c is 1
|
|
360
|
+
aggregate: c2 is sum(sum(ai))
|
|
361
|
+
}`).compileToFailWith('Aggregate expression cannot be aggregate', "Cannot define 'c2', value has unknown type");
|
|
362
|
+
});
|
|
363
|
+
test('can use field def in group_by, preserved over refinement', modelOK(`query: a1 is a -> {
|
|
364
|
+
group_by: c is 1
|
|
365
|
+
}
|
|
366
|
+
query: -> a1 {
|
|
367
|
+
order_by: c
|
|
368
|
+
}`));
|
|
369
|
+
test('can use field ref in group_by, preserved over refinement', modelOK(`query: a1 is a -> {
|
|
370
|
+
group_by: c is astr
|
|
371
|
+
}
|
|
372
|
+
query: -> a1 {
|
|
373
|
+
order_by: c
|
|
374
|
+
}`));
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
describe('function typechecking', () => {
|
|
378
|
+
test('use function correctly', modelOK(`query: a -> {
|
|
379
|
+
group_by: s is concat('a', 'b')
|
|
380
|
+
}`));
|
|
381
|
+
test('function no matching overload', () => {
|
|
382
|
+
expect(`query: a -> {
|
|
383
|
+
group_by: s is floor('a', 'b')
|
|
384
|
+
}`).compileToFailWith('No matching overload for function floor(string, string)', "Cannot define 's', value has unknown type");
|
|
385
|
+
});
|
|
386
|
+
test('unknown function', () => {
|
|
387
|
+
expect(`query: a -> {
|
|
388
|
+
group_by: s is asdfasdf()
|
|
389
|
+
}`).compileToFailWith("Unknown function 'asdfasdf'. Use 'asdfasdf!(...)' to call a SQL function directly.", "Cannot define 's', value has unknown type");
|
|
390
|
+
});
|
|
391
|
+
test('can select different overload', modelOK('query: a -> { group_by: s is concat() }'));
|
|
392
|
+
test('can pass different expression types', modelOK(`query: a -> {
|
|
393
|
+
group_by: f1 is sqrt(1)
|
|
394
|
+
aggregate: f2 is sqrt(count())
|
|
395
|
+
aggregate: f3 is sqrt(all(count()))
|
|
396
|
+
calculate: f4 is sqrt(lag(f1))
|
|
397
|
+
calculate: f5 is sqrt(lag(count()))
|
|
398
|
+
}`));
|
|
399
|
+
test('function return type correct', modelOK(`query: a -> {
|
|
400
|
+
group_by: s is floor(1.2) + 1
|
|
401
|
+
}`));
|
|
402
|
+
test('function return type incorrect', () => {
|
|
403
|
+
expect(`query: a -> {
|
|
404
|
+
group_by: s is floor(1.2) + 'a'
|
|
405
|
+
}`).compileToFailWith("Non numeric('number,string') value with '+'", "Cannot define 's', value has unknown type");
|
|
406
|
+
});
|
|
407
|
+
test('can use output value in calculate', modelOK(`query: a -> {
|
|
408
|
+
group_by: x is 1
|
|
409
|
+
calculate: s is lag(x)
|
|
410
|
+
}`));
|
|
411
|
+
test('cannot use output value in group_by', () => {
|
|
412
|
+
expect(`query: a -> {
|
|
413
|
+
group_by: x is 1
|
|
414
|
+
group_by: y is x
|
|
415
|
+
}`).compileToFailWith("'x' is not defined", "Cannot define 'y', value has unknown type");
|
|
416
|
+
});
|
|
417
|
+
test('lag can check that other args are constant', () => {
|
|
418
|
+
expect(`query: a -> {
|
|
419
|
+
group_by: x is 1
|
|
420
|
+
calculate: s is lag(x, 1, x)
|
|
421
|
+
}`).compileToFailWith(
|
|
422
|
+
// TODO improve this error message
|
|
423
|
+
"Parameter 3 ('default') of lag must be literal or constant, but received output");
|
|
424
|
+
});
|
|
425
|
+
test('lag can check that other args are literal', () => {
|
|
426
|
+
expect(`query: a -> {
|
|
427
|
+
group_by: x is 1
|
|
428
|
+
calculate: s is lag(x, 1 + 1)
|
|
429
|
+
}`).compileToFailWith(
|
|
430
|
+
// TODO improve this error message
|
|
431
|
+
"Parameter 2 ('offset') of lag must be literal, but received constant");
|
|
432
|
+
});
|
|
433
|
+
test('lag can check that other args are nonnull', () => {
|
|
434
|
+
expect(`query: a -> {
|
|
435
|
+
group_by: x is 1
|
|
436
|
+
calculate: s is lag(x, null)
|
|
437
|
+
}`).compileToFailWith("Parameter 2 ('offset') of lag must not be a literal null");
|
|
438
|
+
});
|
|
439
|
+
test('lag can use constant values for other args', modelOK(`query: a -> {
|
|
440
|
+
group_by: x is 1
|
|
441
|
+
calculate: s is lag(x, 2)
|
|
442
|
+
}`));
|
|
443
|
+
test('cannot name top level objects same as functions', () => {
|
|
444
|
+
expect((0, test_translator_1.markSource) `query: ${'concat is a -> { group_by: x is 1 }'}`).compileToFailWith(
|
|
445
|
+
// TODO improve this error message
|
|
446
|
+
"'concat' is already defined, cannot redefine");
|
|
447
|
+
});
|
|
448
|
+
test('`now` is considered constant`', modelOK(`query: a -> {
|
|
449
|
+
group_by: n is now
|
|
450
|
+
calculate: l is lag(n, 1, now)
|
|
451
|
+
}`));
|
|
452
|
+
// TODO it might be nice to reference a field which is a constant, and be able to
|
|
453
|
+
// use that as a constant param. Same with a literal.
|
|
454
|
+
test('cannot use a field which is a constant in a constant param', () => {
|
|
455
|
+
expect(`query: a -> {
|
|
456
|
+
group_by: ai, pi is pi()
|
|
457
|
+
calculate: l is lag(ai, 1, pi)
|
|
458
|
+
}`).compileToFailWith("Parameter 3 ('default') of lag must be literal or constant, but received output");
|
|
459
|
+
});
|
|
460
|
+
// TODO we don't handle referencing a join as a field correctly in all cases today.
|
|
461
|
+
// For now, it at least is considered type `struct` and therefore fails to parse
|
|
462
|
+
// as a function argument.
|
|
463
|
+
// We add <join_name>_id to the query, but it's not included in the output space
|
|
464
|
+
test('cannot use struct in function arg', () => {
|
|
465
|
+
expect(`query: a {join_one: b with astr } -> {
|
|
466
|
+
group_by: b
|
|
467
|
+
calculate: foo is lag(b)
|
|
468
|
+
}`).compileToFailWith('No matching overload for function lag(struct)', "Cannot define 'foo', value has unknown type");
|
|
469
|
+
});
|
|
470
|
+
// TODO this doesn't work today, we're not rigorous enough with integer
|
|
471
|
+
// subtypes. But we should probably make this typecheck properly.
|
|
472
|
+
test.skip('cannot use float in round precision', () => {
|
|
473
|
+
expect(`query: a -> {
|
|
474
|
+
group_by: x is round(1.5, 1.6)
|
|
475
|
+
}`).compileToFailWith(
|
|
476
|
+
// TODO improve this error message
|
|
477
|
+
"Parameter 2 ('precision') for round must be integer, received float");
|
|
478
|
+
});
|
|
479
|
+
test('cannot use stddev with no arguments', () => {
|
|
480
|
+
expect(`query: a -> {
|
|
481
|
+
aggregate: x is stddev()
|
|
482
|
+
}`).compileToFailWith('No matching overload for function stddev()', "Cannot define 'x', value has unknown type");
|
|
483
|
+
});
|
|
484
|
+
test('can use stddev with postfix syntax', modelOK(`query: a -> {
|
|
485
|
+
declare: y is 1
|
|
486
|
+
aggregate: x is y.stddev()
|
|
487
|
+
}`));
|
|
488
|
+
test('can use stddev with postfix syntax on join', modelOK(`query: a -> {
|
|
489
|
+
join_one: b with astr
|
|
490
|
+
aggregate: x is b.ai.stddev()
|
|
491
|
+
}`));
|
|
492
|
+
test('can use calculate with a measure', modelOK(`query: a { measure: c is count() } -> {
|
|
493
|
+
group_by: y is 1
|
|
494
|
+
calculate: x is lag(c)
|
|
495
|
+
}`));
|
|
496
|
+
test('cannot use calculate with input fields', () => {
|
|
497
|
+
expect(`query: a -> {
|
|
498
|
+
group_by: y is 1
|
|
499
|
+
calculate: x is lag(ai)
|
|
500
|
+
}`).compileToFailWith(
|
|
501
|
+
// TODO improve this error message:
|
|
502
|
+
// Parameter 1 ('value') of 'lag' must be a constant, an aggregate, or an expression using
|
|
503
|
+
// only fields that appear in the query output. Received an expression which uses a field
|
|
504
|
+
// that is not in the query output.
|
|
505
|
+
"Parameter 1 ('value') of lag must be literal, constant or output, but received input");
|
|
506
|
+
});
|
|
507
|
+
test('can use calculate with aggregate field which is not in query', modelOK(`query: a { measure: acount is count() } -> {
|
|
508
|
+
group_by: astr
|
|
509
|
+
calculate: pc is lag(acount)
|
|
510
|
+
}`));
|
|
511
|
+
test('cannot use agregate as argument to agg function', () => {
|
|
512
|
+
expect(`query: a -> {
|
|
513
|
+
aggregate: x is stddev(count())
|
|
514
|
+
}`).compileToFailWith("Parameter 1 ('value') of stddev must be scalar, but received aggregate");
|
|
515
|
+
});
|
|
516
|
+
test('cannot use calculate with no other fields', () => {
|
|
517
|
+
expect(`query: a -> {
|
|
518
|
+
calculate: x is row_number()
|
|
519
|
+
}`).compileToFailWith("Can't determine query type (group_by/aggregate/nest,project,index)");
|
|
520
|
+
});
|
|
521
|
+
// TODO someday make it so we can order by an analytic function
|
|
522
|
+
test('today: cannot order by analytic function', () => {
|
|
523
|
+
expect(`query: a -> {
|
|
524
|
+
group_by: astr
|
|
525
|
+
calculate: row_num is row_number()
|
|
526
|
+
order_by: row_num desc
|
|
527
|
+
}`).compileToFailWith('Illegal order by of analytic field row_num');
|
|
528
|
+
});
|
|
529
|
+
test('cannot use analytic in calculate -- and preserved over refinement', () => {
|
|
530
|
+
expect(`query: a1 is a -> {
|
|
531
|
+
group_by: astr
|
|
532
|
+
calculate: p is lag(astr)
|
|
533
|
+
}
|
|
534
|
+
query: -> a1 {
|
|
535
|
+
calculate: p1 is lag(p)
|
|
536
|
+
}`).compileToFailWith("Parameter 1 ('value') of lag must be scalar or aggregate, but received scalar_analytic");
|
|
537
|
+
});
|
|
538
|
+
test('cannot use aggregate analytic in project', () => {
|
|
539
|
+
expect(`query: a -> {
|
|
540
|
+
project: astr
|
|
541
|
+
calculate: p is lag(count())
|
|
542
|
+
}`).compileToFailWith('Cannot add aggregate analyics to project');
|
|
543
|
+
});
|
|
544
|
+
test('reference field in join', modelOK(`query: a -> {
|
|
545
|
+
join_one: b with astr
|
|
546
|
+
group_by: b.ai
|
|
547
|
+
}`));
|
|
548
|
+
// TODO decide whether this syntax should be legal, really...
|
|
549
|
+
test('reference join name in group_by', modelOK(`query: a -> {
|
|
550
|
+
join_one: b with astr
|
|
551
|
+
group_by: b
|
|
552
|
+
}`));
|
|
553
|
+
test('can reference project: inline join.* field in calculate', modelOK(`query: a -> {
|
|
554
|
+
join_one: b with astr
|
|
555
|
+
project: b.*
|
|
556
|
+
calculate: s is lag(ai)
|
|
557
|
+
}`));
|
|
558
|
+
test('can reference project: join.* field in calculate', modelOK(`query: a { join_one: b with astr } -> {
|
|
559
|
+
project: b.*
|
|
560
|
+
calculate: s is lag(ai)
|
|
561
|
+
}`));
|
|
562
|
+
});
|
|
226
563
|
});
|
|
227
564
|
test('errors on redefinition of query', () => {
|
|
228
|
-
expect('query: q1 is a -> { project: * }, q1 is a -> { project: * }').compileToFailWith("
|
|
565
|
+
expect('query: q1 is a -> { project: * }, q1 is a -> { project: * }').compileToFailWith("'q1' is already defined, cannot redefine");
|
|
229
566
|
});
|
|
230
567
|
});
|
|
231
568
|
describe('source properties', () => {
|
|
@@ -248,7 +585,7 @@ describe('source properties', () => {
|
|
|
248
585
|
test('single measure', modelOK('source: aa is a { measure: x is count() }'));
|
|
249
586
|
test('multiple measures', modelOK(`
|
|
250
587
|
source: aa is a {
|
|
251
|
-
|
|
588
|
+
measure:
|
|
252
589
|
x is count()
|
|
253
590
|
y is x * x
|
|
254
591
|
}
|
|
@@ -403,12 +740,18 @@ describe('qops', () => {
|
|
|
403
740
|
});
|
|
404
741
|
test('index sample-rows', modelOK('query:a->{index: *; sample: 100000}'));
|
|
405
742
|
test('top N', modelOK('query: a->{ top: 5; group_by: astr }'));
|
|
406
|
-
test('top N by field', modelOK('query: a->{top: 5 by
|
|
407
|
-
test('top N by expression', modelOK('query: ab->{top: 5 by
|
|
743
|
+
test('top N by field', modelOK('query: a->{top: 5 by astr; group_by: astr}'));
|
|
744
|
+
test('top N by expression', modelOK('query: ab->{top: 5 by ai + 1; group_by: ai}'));
|
|
745
|
+
test('top N by field must be in the output space', () => expect('query: a->{top: 5 by af; group_by: astr}').compileToFailWith('Unknown field af in output space'));
|
|
408
746
|
test('limit N', modelOK('query: a->{ limit: 5; group_by: astr }'));
|
|
409
|
-
test('order by', modelOK('query: a->{ order_by:
|
|
410
|
-
test('order by
|
|
411
|
-
|
|
747
|
+
test('order by', modelOK('query: a->{ order_by: astr; group_by: astr }'));
|
|
748
|
+
test('order by preserved over refinement', modelOK(`
|
|
749
|
+
query: a1 is a -> { group_by: astr }
|
|
750
|
+
query: -> a1 { order_by: astr }
|
|
751
|
+
`));
|
|
752
|
+
test('order by must be in the output space', () => expect('query: a -> { order_by: af; group_by: astr }').compileToFailWith('Unknown field af in output space'));
|
|
753
|
+
test('order by asc', modelOK('query: a->{ order_by: astr asc; group_by: astr }'));
|
|
754
|
+
test('order by desc', modelOK('query: a->{ order_by: astr desc; group_by: astr }'));
|
|
412
755
|
test('order by N', modelOK('query: a->{ order_by: 1 asc; group_by: astr }'));
|
|
413
756
|
test('order by multiple', modelOK(`
|
|
414
757
|
query: a->{
|
|
@@ -652,7 +995,7 @@ describe('expressions', () => {
|
|
|
652
995
|
});
|
|
653
996
|
});
|
|
654
997
|
test('field name', exprOK('astr'));
|
|
655
|
-
test('function call', exprOK(
|
|
998
|
+
test('function call', exprOK("concat('foo')"));
|
|
656
999
|
describe('operators', () => {
|
|
657
1000
|
test('addition', exprOK('42 + 7'));
|
|
658
1001
|
test('subtraction', exprOK('42 - 7'));
|
|
@@ -694,10 +1037,24 @@ describe('expressions', () => {
|
|
|
694
1037
|
});
|
|
695
1038
|
});
|
|
696
1039
|
test('filtered measure', exprOK("acount {? astr = 'why?' }"));
|
|
1040
|
+
test('filtered ungrouped aggregate', modelOK(`
|
|
1041
|
+
query: a -> {
|
|
1042
|
+
group_by: ai
|
|
1043
|
+
aggregate: x is all(avg(ai)) { where: true }
|
|
1044
|
+
}
|
|
1045
|
+
`));
|
|
697
1046
|
test('correctly flags filtered scalar', () => {
|
|
698
1047
|
const e = new test_translator_1.BetaExpression('ai { where: true }');
|
|
699
1048
|
expect(e).compileToFailWith('Filtered expression requires an aggregate computation');
|
|
700
1049
|
});
|
|
1050
|
+
test('correctly flags filtered analytic', () => {
|
|
1051
|
+
expect((0, test_translator_1.markSource) `
|
|
1052
|
+
query: a -> {
|
|
1053
|
+
group_by: ai
|
|
1054
|
+
calculate: l is lag(ai) { where: true }
|
|
1055
|
+
}
|
|
1056
|
+
`).compileToFailWith('Filtered expression requires an aggregate computation');
|
|
1057
|
+
});
|
|
701
1058
|
describe('aggregate forms', () => {
|
|
702
1059
|
test('count', exprOK('count()'));
|
|
703
1060
|
test('count distinct', exprOK('count(distinct astr)'));
|
|
@@ -810,13 +1167,37 @@ describe('expressions', () => {
|
|
|
810
1167
|
(0, model_1.isFieldTypeDef)(x) &&
|
|
811
1168
|
x.type === 'number' &&
|
|
812
1169
|
x.e) {
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
1170
|
+
expect(x).toMatchObject({
|
|
1171
|
+
'e': [
|
|
1172
|
+
{
|
|
1173
|
+
'function': 'numberLiteral',
|
|
1174
|
+
'literal': '1',
|
|
1175
|
+
'type': 'dialect',
|
|
1176
|
+
},
|
|
1177
|
+
// TODO not sure why there are TWO sets of parentheses... A previous version of this test
|
|
1178
|
+
// just checked that there were ANY parens, so that went under the radar. Not fixing now.
|
|
1179
|
+
'+((',
|
|
1180
|
+
{
|
|
1181
|
+
'denominator': [
|
|
1182
|
+
{
|
|
1183
|
+
'function': 'numberLiteral',
|
|
1184
|
+
'literal': '4',
|
|
1185
|
+
'type': 'dialect',
|
|
1186
|
+
},
|
|
1187
|
+
],
|
|
1188
|
+
'function': 'div',
|
|
1189
|
+
'numerator': [
|
|
1190
|
+
{
|
|
1191
|
+
'function': 'numberLiteral',
|
|
1192
|
+
'literal': '3',
|
|
1193
|
+
'type': 'dialect',
|
|
1194
|
+
},
|
|
1195
|
+
],
|
|
1196
|
+
'type': 'dialect',
|
|
1197
|
+
},
|
|
1198
|
+
'))',
|
|
1199
|
+
],
|
|
1200
|
+
});
|
|
820
1201
|
}
|
|
821
1202
|
else {
|
|
822
1203
|
fail('expression with parens compiled oddly');
|
|
@@ -1042,7 +1423,7 @@ describe('source locations', () => {
|
|
|
1042
1423
|
source: na is a {
|
|
1043
1424
|
measure: y is count()
|
|
1044
1425
|
query: x is {
|
|
1045
|
-
|
|
1426
|
+
aggregate: ${'z is y { where: true }'}
|
|
1046
1427
|
}
|
|
1047
1428
|
}`;
|
|
1048
1429
|
const m = new test_translator_1.TestTranslator(source.code);
|
|
@@ -1784,9 +2165,9 @@ describe('pipeline comprehension', () => {
|
|
|
1784
2165
|
expect(s2 === null || s2 === void 0 ? void 0 : s2.pipeline.length).toBe(2);
|
|
1785
2166
|
});
|
|
1786
2167
|
});
|
|
1787
|
-
describe('
|
|
2168
|
+
describe('raw function call with type specified', () => {
|
|
1788
2169
|
test('timestamp_seconds', () => {
|
|
1789
|
-
expect('timestamp_seconds(0)').toReturnType('timestamp');
|
|
2170
|
+
expect('timestamp_seconds!timestamp(0)').toReturnType('timestamp');
|
|
1790
2171
|
});
|
|
1791
2172
|
});
|
|
1792
2173
|
//# sourceMappingURL=parse.spec.js.map
|
|
@@ -14,6 +14,7 @@ export declare const aTableDef: StructDef;
|
|
|
14
14
|
declare class TestRoot extends MalloyElement implements NameSpace {
|
|
15
15
|
private modelDef;
|
|
16
16
|
elementType: string;
|
|
17
|
+
globalNameSpace: NameSpace;
|
|
17
18
|
constructor(child: MalloyElement, forTranslator: MalloyTranslator, modelDef: ModelDef);
|
|
18
19
|
namespace(): NameSpace;
|
|
19
20
|
getEntry(name: string): ModelEntry | undefined;
|
|
@@ -29,6 +29,7 @@ const malloy_types_1 = require("../../model/malloy_types");
|
|
|
29
29
|
const ast_1 = require("../ast");
|
|
30
30
|
const parse_malloy_1 = require("../parse-malloy");
|
|
31
31
|
const static_space_1 = require("../ast/field-space/static-space");
|
|
32
|
+
const global_name_space_1 = require("../ast/types/global-name-space");
|
|
32
33
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/explicit-module-boundary-types
|
|
33
34
|
function pretty(thing) {
|
|
34
35
|
return (0, util_1.inspect)(thing, { breakLength: 72, depth: Infinity });
|
|
@@ -148,12 +149,16 @@ class TestRoot extends ast_1.MalloyElement {
|
|
|
148
149
|
super({ child });
|
|
149
150
|
this.modelDef = modelDef;
|
|
150
151
|
this.elementType = 'test root';
|
|
152
|
+
this.globalNameSpace = new global_name_space_1.GlobalNameSpace();
|
|
151
153
|
this.setTranslator(forTranslator);
|
|
152
154
|
}
|
|
153
155
|
namespace() {
|
|
154
156
|
return this;
|
|
155
157
|
}
|
|
156
158
|
getEntry(name) {
|
|
159
|
+
const global = this.globalNameSpace.getEntry(name);
|
|
160
|
+
if (global)
|
|
161
|
+
return global;
|
|
157
162
|
const struct = this.modelDef.contents[name];
|
|
158
163
|
if (struct.type === 'struct') {
|
|
159
164
|
const exported = this.modelDef.exports.includes(name);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Dialect, DialectFieldList } from '../dialect';
|
|
2
|
-
import { AggregateFragment,
|
|
2
|
+
import { AggregateFragment, CompiledQuery, DialectFragment, Expr, FieldDef, FieldFragment, FieldRef, Filtered, FilterExpression, FilterFragment, FunctionCallFragment, FunctionOverloadDef, JoinRelationship, ModelDef, NamedQuery, OrderBy, OutputFieldFragment, Parameter, ParameterFragment, PipeSegment, Query, QueryFieldDef, QuerySegment, ResultMetadataDef, ResultStructMetadataDef, SearchIndexResult, SpreadFragment, SQLExpressionFragment, StructDef, StructRef, TurtleDef, UngroupFragment } from './malloy_types';
|
|
3
3
|
import { Connection } from '../runtime_types';
|
|
4
4
|
import { AndChain } from './utils';
|
|
5
5
|
import { QueryInfo } from '../dialect/dialect';
|
|
@@ -62,9 +62,15 @@ declare class QueryField extends QueryNode {
|
|
|
62
62
|
caseGroup(groupSets: number[], s: string): string;
|
|
63
63
|
getFullOutputName(): string;
|
|
64
64
|
generateFieldFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: FieldFragment, state: GenerateState): string;
|
|
65
|
+
generateOutputFieldFragment(resultSet: FieldInstanceResult, _context: QueryStruct, frag: OutputFieldFragment, _state: GenerateState): string;
|
|
66
|
+
generateSQLExpression(resultSet: FieldInstanceResult, context: QueryStruct, frag: SQLExpressionFragment, state: GenerateState): string;
|
|
67
|
+
private getParameterMap;
|
|
68
|
+
private expandFunctionCall;
|
|
69
|
+
generateFunctionCallExpression(resultSet: FieldInstanceResult, context: QueryStruct, frag: FunctionCallFragment, state: GenerateState): string;
|
|
70
|
+
generateSpread(_resultSet: FieldInstanceResult, _context: QueryStruct, _frag: SpreadFragment, _state: GenerateState): string;
|
|
65
71
|
generateParameterFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: ParameterFragment, state: GenerateState): string;
|
|
66
72
|
generateFilterFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: FilterFragment, state: GenerateState): string;
|
|
67
|
-
generateDimFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr:
|
|
73
|
+
generateDimFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: Expr, state: GenerateState): string;
|
|
68
74
|
generateUngroupedFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: UngroupFragment, state: GenerateState): string;
|
|
69
75
|
generateDistinctKeyIfNecessary(resultSet: FieldInstanceResult, context: QueryStruct, structPath: string | undefined): string | undefined;
|
|
70
76
|
generateSumFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: AggregateFragment, state: GenerateState): string;
|
|
@@ -72,7 +78,8 @@ declare class QueryField extends QueryNode {
|
|
|
72
78
|
generateAvgFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: AggregateFragment, state: GenerateState): string;
|
|
73
79
|
generateCountFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: AggregateFragment, state: GenerateState): string;
|
|
74
80
|
generateDialect(resultSet: FieldInstanceResult, context: QueryStruct, expr: DialectFragment, state: GenerateState): string;
|
|
75
|
-
|
|
81
|
+
getAnalyticPartitions(resultStruct: FieldInstanceResult): string;
|
|
82
|
+
generateAnalyticFragment(resultStruct: FieldInstanceResult, context: QueryStruct, expr: Expr, overload: FunctionOverloadDef, state: GenerateState, args: Expr[]): string;
|
|
76
83
|
generateExpressionFromExpr(resultSet: FieldInstanceResult, context: QueryStruct, e: Expr, state?: GenerateState): string;
|
|
77
84
|
getExpr(): Expr;
|
|
78
85
|
generateExpression(resultSet: FieldInstanceResult): string;
|
|
@@ -80,6 +87,7 @@ declare class QueryField extends QueryNode {
|
|
|
80
87
|
declare class QueryAtomicField extends QueryField {
|
|
81
88
|
includeInWildcard(): boolean;
|
|
82
89
|
isCalculated(): boolean;
|
|
90
|
+
isAggregate(): boolean;
|
|
83
91
|
getFilterList(): FilterExpression[];
|
|
84
92
|
hasExpression(): boolean;
|
|
85
93
|
}
|
|
@@ -110,11 +118,12 @@ declare class FieldInstanceField implements FieldInstance {
|
|
|
110
118
|
fieldUsage: FieldUsage;
|
|
111
119
|
additionalGroupSets: number[];
|
|
112
120
|
parent: FieldInstanceResult;
|
|
121
|
+
analyticalSQL: string | undefined;
|
|
113
122
|
partitionSQL: string | undefined;
|
|
114
123
|
constructor(f: QueryField, fieldUsage: FieldUsage, parent: FieldInstanceResult);
|
|
115
124
|
root(): FieldInstanceResultRoot;
|
|
116
125
|
getSQL(): string;
|
|
117
|
-
|
|
126
|
+
getAnalyticalSQL(forPartition: boolean): string;
|
|
118
127
|
}
|
|
119
128
|
declare type RepeatedResultType = 'nested' | 'inline_all_numbers' | 'inline';
|
|
120
129
|
declare type UngroupSet = {
|