@malloydata/malloy 0.0.120-dev240131220408 → 0.0.120

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/dialect/dialect_map.js +12 -2
  2. package/dist/dialect/functions/all_functions.js +3 -0
  3. package/dist/dialect/functions/string_agg.d.ts +3 -0
  4. package/dist/dialect/functions/string_agg.js +47 -0
  5. package/dist/dialect/functions/util.d.ts +5 -0
  6. package/dist/dialect/functions/util.js +3 -0
  7. package/dist/dialect/postgres/functions/postgres_functions.js +3 -0
  8. package/dist/dialect/postgres/functions/string_agg.d.ts +3 -0
  9. package/dist/dialect/postgres/functions/string_agg.js +47 -0
  10. package/dist/dialect/standardsql/functions/standardsql_functions.js +3 -0
  11. package/dist/dialect/standardsql/functions/string_agg.d.ts +3 -0
  12. package/dist/dialect/standardsql/functions/string_agg.js +49 -0
  13. package/dist/index.d.ts +2 -2
  14. package/dist/lang/ast/expressions/expr-func.d.ts +11 -0
  15. package/dist/lang/ast/expressions/expr-func.js +69 -10
  16. package/dist/lang/ast/expressions/{expr-filter.d.ts → expr-props.d.ts} +5 -4
  17. package/dist/lang/ast/expressions/expr-props.js +122 -0
  18. package/dist/lang/ast/expressions/function-ordering.d.ts +18 -0
  19. package/dist/lang/ast/expressions/function-ordering.js +75 -0
  20. package/dist/lang/ast/expressions/partition_by.d.ts +7 -0
  21. package/dist/lang/ast/expressions/partition_by.js +35 -0
  22. package/dist/lang/ast/index.d.ts +4 -1
  23. package/dist/lang/ast/index.js +4 -1
  24. package/dist/lang/ast/query-items/field-references.d.ts +4 -0
  25. package/dist/lang/ast/query-items/field-references.js +12 -1
  26. package/dist/lang/ast/types/expression-def.d.ts +4 -0
  27. package/dist/lang/ast/types/expression-def.js +12 -0
  28. package/dist/lang/ast/types/field-prop-statement.d.ts +7 -0
  29. package/dist/lang/ast/types/field-prop-statement.js +37 -0
  30. package/dist/lang/lib/Malloy/MalloyLexer.d.ts +136 -135
  31. package/dist/lang/lib/Malloy/MalloyLexer.js +1186 -1174
  32. package/dist/lang/lib/Malloy/MalloyParser.d.ts +278 -213
  33. package/dist/lang/lib/Malloy/MalloyParser.js +2200 -1683
  34. package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +76 -36
  35. package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +48 -22
  36. package/dist/lang/malloy-to-ast.d.ts +6 -2
  37. package/dist/lang/malloy-to-ast.js +33 -9
  38. package/dist/lang/test/expressions.spec.js +132 -9
  39. package/dist/model/malloy_query.d.ts +2 -2
  40. package/dist/model/malloy_query.js +59 -25
  41. package/dist/model/malloy_types.d.ts +20 -2
  42. package/dist/model/malloy_types.js +5 -1
  43. package/dist/run_sql_options.d.ts +1 -0
  44. package/dist/runtime_types.d.ts +4 -1
  45. package/package.json +1 -1
  46. package/dist/lang/ast/expressions/expr-filter.js +0 -66
@@ -83,14 +83,24 @@ function getDialectFunction(name) {
83
83
  if (!returnEqual(overload, existingOverload)) {
84
84
  throw new Error('params match but return types differ!');
85
85
  }
86
- existingOverload.dialect[dialect.name] = overload.e;
86
+ existingOverload.dialect[dialect.name] = {
87
+ e: overload.e,
88
+ supportsOrderBy: overload.supportsOrderBy,
89
+ supportsLimit: overload.supportsLimit,
90
+ };
87
91
  handled = true;
88
92
  }
89
93
  if (!handled) {
90
94
  func.overloads.push({
91
95
  returnType: overload.returnType,
92
96
  params: overload.params,
93
- dialect: { [dialect.name]: overload.e },
97
+ dialect: {
98
+ [dialect.name]: {
99
+ e: overload.e,
100
+ supportsOrderBy: overload.supportsOrderBy,
101
+ supportsLimit: overload.supportsLimit,
102
+ },
103
+ },
94
104
  needsWindowOrderBy: overload.needsWindowOrderBy,
95
105
  between: overload.between,
96
106
  isSymmetric: overload.isSymmetric,
@@ -60,6 +60,7 @@ const simple_numeric_functions_1 = require("./simple_numeric_functions");
60
60
  const avg_moving_1 = require("./avg_moving");
61
61
  const function_map_1 = require("./function_map");
62
62
  const coalesce_1 = require("./coalesce");
63
+ const string_agg_1 = require("./string_agg");
63
64
  const sql_1 = require("./sql");
64
65
  /**
65
66
  * This is a function map containing default implementations of all Malloy
@@ -118,6 +119,8 @@ exports.FUNCTIONS.add('ln', simple_numeric_functions_1.fnLn);
118
119
  exports.FUNCTIONS.add('exp', simple_numeric_functions_1.fnExp);
119
120
  // Aggregate functions
120
121
  exports.FUNCTIONS.add('stddev', stddev_1.fnStddev);
122
+ exports.FUNCTIONS.add('string_agg', string_agg_1.fnStringAgg);
123
+ exports.FUNCTIONS.add('string_agg_distinct', string_agg_1.fnStringAggDistinct);
121
124
  // Analytic functions
122
125
  exports.FUNCTIONS.add('row_number', row_number_1.fnRowNumber);
123
126
  exports.FUNCTIONS.add('lag', lag_1.fnLag);
@@ -0,0 +1,3 @@
1
+ import { DialectFunctionOverloadDef } from './util';
2
+ export declare function fnStringAgg(): DialectFunctionOverloadDef[];
3
+ export declare function fnStringAggDistinct(): DialectFunctionOverloadDef[];
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright 2023 Google LLC
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files
7
+ * (the "Software"), to deal in the Software without restriction,
8
+ * including without limitation the rights to use, copy, modify, merge,
9
+ * publish, distribute, sublicense, and/or sell copies of the Software,
10
+ * and to permit persons to whom the Software is furnished to do so,
11
+ * subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.fnStringAggDistinct = exports.fnStringAgg = void 0;
26
+ const util_1 = require("./util");
27
+ function fnStringAgg() {
28
+ const value = (0, util_1.makeParam)('value', (0, util_1.maxScalar)('string'));
29
+ const separator = (0, util_1.makeParam)('separator', (0, util_1.literal)((0, util_1.maxScalar)('string')));
30
+ const orderBy = { type: 'aggregate_order_by' };
31
+ return [
32
+ (0, util_1.overload)((0, util_1.minAggregate)('string'), [value.param], (0, util_1.sql) `STRING_AGG(${value.arg}${orderBy})`, { supportsOrderBy: true }),
33
+ (0, util_1.overload)((0, util_1.minAggregate)('string'), [value.param, separator.param], (0, util_1.sql) `STRING_AGG(${value.arg}, ${separator.arg}${orderBy})`, { supportsOrderBy: true }),
34
+ ];
35
+ }
36
+ exports.fnStringAgg = fnStringAgg;
37
+ function fnStringAggDistinct() {
38
+ const value = (0, util_1.makeParam)('value', (0, util_1.maxScalar)('string'));
39
+ const separator = (0, util_1.makeParam)('separator', (0, util_1.literal)((0, util_1.maxScalar)('string')));
40
+ const orderBy = { type: 'aggregate_order_by' };
41
+ return [
42
+ (0, util_1.overload)((0, util_1.minAggregate)('string'), [value.param], (0, util_1.sql) `STRING_AGG(DISTINCT ${value.arg}${orderBy})`, { isSymmetric: true, supportsOrderBy: true }),
43
+ (0, util_1.overload)((0, util_1.minAggregate)('string'), [value.param, separator.param], (0, util_1.sql) `STRING_AGG(DISTINCT ${value.arg}, ${separator.arg}${orderBy})`, { isSymmetric: true, supportsOrderBy: true }),
44
+ ];
45
+ }
46
+ exports.fnStringAggDistinct = fnStringAggDistinct;
47
+ //# sourceMappingURL=string_agg.js.map
@@ -5,6 +5,8 @@ export interface DialectFunctionOverloadDef {
5
5
  e: Expr;
6
6
  needsWindowOrderBy?: boolean;
7
7
  isSymmetric?: boolean;
8
+ supportsOrderBy?: boolean;
9
+ supportsLimit?: boolean;
8
10
  between: {
9
11
  preceding: number | string;
10
12
  following: number | string;
@@ -43,4 +45,7 @@ export declare function overload(returnType: TypeDesc, params: FunctionParameter
43
45
  preceding: number | string;
44
46
  following: number | string;
45
47
  };
48
+ isSymmetric?: boolean;
49
+ supportsLimit?: boolean;
50
+ supportsOrderBy?: boolean;
46
51
  }): DialectFunctionOverloadDef;
@@ -181,6 +181,9 @@ function overload(returnType, params, e, options) {
181
181
  e,
182
182
  needsWindowOrderBy: options === null || options === void 0 ? void 0 : options.needsWindowOrderBy,
183
183
  between: options === null || options === void 0 ? void 0 : options.between,
184
+ isSymmetric: options === null || options === void 0 ? void 0 : options.isSymmetric,
185
+ supportsOrderBy: options === null || options === void 0 ? void 0 : options.supportsOrderBy,
186
+ supportsLimit: options === null || options === void 0 ? void 0 : options.supportsLimit,
184
187
  };
185
188
  }
186
189
  exports.overload = overload;
@@ -24,6 +24,7 @@
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.POSTGRES_FUNCTIONS = void 0;
26
26
  const functions_1 = require("../../functions");
27
+ const string_agg_1 = require("./string_agg");
27
28
  const byte_length_1 = require("./byte_length");
28
29
  const ends_with_1 = require("./ends_with");
29
30
  const greatest_and_least_1 = require("./greatest_and_least");
@@ -55,6 +56,8 @@ exports.POSTGRES_FUNCTIONS.add('trunc', trunc_1.fnTrunc);
55
56
  exports.POSTGRES_FUNCTIONS.add('substr', substr_1.fnSubstr);
56
57
  exports.POSTGRES_FUNCTIONS.add('replace', replace_1.fnReplace);
57
58
  exports.POSTGRES_FUNCTIONS.add('ends_with', ends_with_1.fnEndsWith);
59
+ exports.POSTGRES_FUNCTIONS.add('string_agg', string_agg_1.fnStringAgg);
60
+ exports.POSTGRES_FUNCTIONS.add('string_agg_distinct', string_agg_1.fnStringAggDistinct);
58
61
  exports.POSTGRES_FUNCTIONS.add('log', log_1.fnLog);
59
62
  exports.POSTGRES_FUNCTIONS.seal();
60
63
  //# sourceMappingURL=postgres_functions.js.map
@@ -0,0 +1,3 @@
1
+ import { DialectFunctionOverloadDef } from '../../functions/util';
2
+ export declare function fnStringAgg(): DialectFunctionOverloadDef[];
3
+ export declare function fnStringAggDistinct(): DialectFunctionOverloadDef[];
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright 2023 Google LLC
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files
7
+ * (the "Software"), to deal in the Software without restriction,
8
+ * including without limitation the rights to use, copy, modify, merge,
9
+ * publish, distribute, sublicense, and/or sell copies of the Software,
10
+ * and to permit persons to whom the Software is furnished to do so,
11
+ * subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.fnStringAggDistinct = exports.fnStringAgg = void 0;
26
+ const util_1 = require("../../functions/util");
27
+ function fnStringAgg() {
28
+ const value = (0, util_1.makeParam)('value', (0, util_1.maxScalar)('string'));
29
+ const separator = (0, util_1.makeParam)('separator', (0, util_1.literal)((0, util_1.maxScalar)('string')));
30
+ const orderBy = { type: 'aggregate_order_by' };
31
+ return [
32
+ (0, util_1.overload)((0, util_1.minAggregate)('string'), [value.param], (0, util_1.sql) `STRING_AGG(${value.arg}, ','${orderBy})`, { supportsOrderBy: true }),
33
+ (0, util_1.overload)((0, util_1.minAggregate)('string'), [value.param, separator.param], (0, util_1.sql) `STRING_AGG(${value.arg}, ${separator.arg}${orderBy})`, { supportsOrderBy: true }),
34
+ ];
35
+ }
36
+ exports.fnStringAgg = fnStringAgg;
37
+ function fnStringAggDistinct() {
38
+ const value = (0, util_1.makeParam)('value', (0, util_1.maxScalar)('string'));
39
+ const separator = (0, util_1.makeParam)('separator', (0, util_1.literal)((0, util_1.maxScalar)('string')));
40
+ const orderBy = { type: 'aggregate_order_by' };
41
+ return [
42
+ (0, util_1.overload)((0, util_1.minAggregate)('string'), [value.param], (0, util_1.sql) `STRING_AGG(DISTINCT ${value.arg}, ','${orderBy})`, { isSymmetric: true, supportsOrderBy: true }),
43
+ (0, util_1.overload)((0, util_1.minAggregate)('string'), [value.param, separator.param], (0, util_1.sql) `STRING_AGG(DISTINCT ${value.arg}, ${separator.arg}${orderBy})`, { isSymmetric: true, supportsOrderBy: true }),
44
+ ];
45
+ }
46
+ exports.fnStringAggDistinct = fnStringAggDistinct;
47
+ //# sourceMappingURL=string_agg.js.map
@@ -24,10 +24,13 @@
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.STANDARDSQL_FUNCTIONS = void 0;
26
26
  const functions_1 = require("../../functions");
27
+ const string_agg_1 = require("./string_agg");
27
28
  const chr_1 = require("./chr");
28
29
  const pi_1 = require("./pi");
29
30
  exports.STANDARDSQL_FUNCTIONS = functions_1.FUNCTIONS.clone();
30
31
  exports.STANDARDSQL_FUNCTIONS.add('pi', pi_1.fnPi);
31
32
  exports.STANDARDSQL_FUNCTIONS.add('chr', chr_1.fnChr);
33
+ exports.STANDARDSQL_FUNCTIONS.add('string_agg', string_agg_1.fnStringAgg);
34
+ exports.STANDARDSQL_FUNCTIONS.add('string_agg_distinct', string_agg_1.fnStringAggDistinct);
32
35
  exports.STANDARDSQL_FUNCTIONS.seal();
33
36
  //# sourceMappingURL=standardsql_functions.js.map
@@ -0,0 +1,3 @@
1
+ import { DialectFunctionOverloadDef } from '../../functions/util';
2
+ export declare function fnStringAgg(): DialectFunctionOverloadDef[];
3
+ export declare function fnStringAggDistinct(): DialectFunctionOverloadDef[];
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright 2023 Google LLC
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files
7
+ * (the "Software"), to deal in the Software without restriction,
8
+ * including without limitation the rights to use, copy, modify, merge,
9
+ * publish, distribute, sublicense, and/or sell copies of the Software,
10
+ * and to permit persons to whom the Software is furnished to do so,
11
+ * subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.fnStringAggDistinct = exports.fnStringAgg = void 0;
26
+ const util_1 = require("../../functions/util");
27
+ function fnStringAgg() {
28
+ const value = (0, util_1.makeParam)('value', (0, util_1.maxScalar)('string'));
29
+ const separator = (0, util_1.makeParam)('separator', (0, util_1.literal)((0, util_1.maxScalar)('string')));
30
+ const orderBy = { type: 'aggregate_order_by' };
31
+ const limit = { type: 'aggregate_limit' };
32
+ return [
33
+ (0, util_1.overload)((0, util_1.minAggregate)('string'), [value.param], (0, util_1.sql) `STRING_AGG(${value.arg}${orderBy}${limit})`, { supportsOrderBy: true, supportsLimit: true }),
34
+ (0, util_1.overload)((0, util_1.minAggregate)('string'), [value.param, separator.param], (0, util_1.sql) `STRING_AGG(${value.arg}, ${separator.arg}${orderBy}${limit})`, { supportsOrderBy: true, supportsLimit: true }),
35
+ ];
36
+ }
37
+ exports.fnStringAgg = fnStringAgg;
38
+ function fnStringAggDistinct() {
39
+ const value = (0, util_1.makeParam)('value', (0, util_1.maxScalar)('string'));
40
+ const separator = (0, util_1.makeParam)('separator', (0, util_1.literal)((0, util_1.maxScalar)('string')));
41
+ const orderBy = { type: 'aggregate_order_by' };
42
+ const limit = { type: 'aggregate_limit' };
43
+ return [
44
+ (0, util_1.overload)((0, util_1.minAggregate)('string'), [value.param], (0, util_1.sql) `STRING_AGG(DISTINCT ${value.arg}${orderBy}${limit})`, { isSymmetric: true, supportsOrderBy: true, supportsLimit: true }),
45
+ (0, util_1.overload)((0, util_1.minAggregate)('string'), [value.param, separator.param], (0, util_1.sql) `STRING_AGG(DISTINCT ${value.arg}, ${separator.arg}${orderBy}${limit})`, { isSymmetric: true, supportsOrderBy: true, supportsLimit: true }),
46
+ ];
47
+ }
48
+ exports.fnStringAggDistinct = fnStringAggDistinct;
49
+ //# sourceMappingURL=string_agg.js.map
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ export { HighlightType, MalloyTranslator, } from './lang';
6
6
  export type { LogMessage, TranslateResponse } from './lang';
7
7
  export { Malloy, Runtime, AtomicFieldType, ConnectionRuntime, SingleConnectionRuntime, EmptyURLReader, InMemoryURLReader, FixedConnectionMap, MalloyError, JoinRelationship, SourceRelationship, DateTimeframe, TimestampTimeframe, PreparedResult, Result, QueryMaterializer, CSVWriter, JSONWriter, Parse, DataWriter, Explore, } from './malloy';
8
8
  export type { Model, PreparedQuery, Field, AtomicField, ExploreField, QueryField, SortableField, DataArray, DataRecord, DataColumn, DataArrayOrRecord, Loggable, ModelMaterializer, DocumentSymbol, DocumentHighlight, ResultJSON, PreparedResultMaterializer, SQLBlockMaterializer, ExploreMaterializer, WriteStream, SerializedExplore, } from './malloy';
9
- export type { RunSQLOptions } from './run_sql_options';
10
- export type { Connection, ConnectionConfig, ConnectionFactory, ConnectionParameter, ConnectionParameterValue, ConnectionConfigSchema, InfoConnection, LookupConnection, ModelString, ModelURL, FetchSchemaOptions, PersistSQLResults, PooledConnection, QueryString, QueryURL, TestableConnection, StreamingConnection, URLReader, } from './runtime_types';
9
+ export type { QueryOptionsReader, RunSQLOptions } from './run_sql_options';
10
+ export type { Connection, ConnectionConfig, ConnectionFactory, ConnectionParameter, ConnectionParameterValue, ConnectionConfigSchema, FetchSchemaOptions, InfoConnection, LookupConnection, ModelString, ModelURL, PersistSQLResults, PooledConnection, QueryString, QueryURL, TestableConnection, StreamingConnection, URLReader, } from './runtime_types';
11
11
  export { toAsyncGenerator } from './connection_utils';
12
12
  export { type TagParse, Tag, type TagDict } from './tags';
@@ -1,5 +1,8 @@
1
1
  import { FieldValueType } from '../../../model/malloy_types';
2
2
  import { FieldReference } from '../query-items/field-references';
3
+ import { FunctionOrdering } from './function-ordering';
4
+ import { Limit } from '../query-properties/limit';
5
+ import { PartitionBy } from './partition_by';
3
6
  import { ExprValue } from '../types/expr-value';
4
7
  import { ExpressionDef } from '../types/expression-def';
5
8
  import { FieldSpace } from '../types/field-space';
@@ -11,5 +14,13 @@ export declare class ExprFunc extends ExpressionDef {
11
14
  readonly source?: FieldReference | undefined;
12
15
  elementType: string;
13
16
  constructor(name: string, args: ExpressionDef[], isRaw: boolean, rawType: FieldValueType | undefined, source?: FieldReference | undefined);
17
+ canSupportPartitionBy(): boolean;
18
+ canSupportOrderBy(): boolean;
19
+ canSupportLimit(): boolean;
14
20
  getExpression(fs: FieldSpace): ExprValue;
21
+ getPropsExpression(fs: FieldSpace, props?: {
22
+ partitionBys?: PartitionBy[];
23
+ orderBys?: FunctionOrdering[];
24
+ limit?: Limit;
25
+ }): ExprValue;
15
26
  }
@@ -39,8 +39,20 @@ class ExprFunc extends expression_def_1.ExpressionDef {
39
39
  this.elementType = 'function call()';
40
40
  this.has({ source: source });
41
41
  }
42
+ canSupportPartitionBy() {
43
+ return true;
44
+ }
45
+ canSupportOrderBy() {
46
+ return true;
47
+ }
48
+ canSupportLimit() {
49
+ return true;
50
+ }
42
51
  getExpression(fs) {
43
- var _a, _b, _c, _d;
52
+ return this.getPropsExpression(fs);
53
+ }
54
+ getPropsExpression(fs, props) {
55
+ var _a, _b, _c, _d, _e;
44
56
  const argExprsWithoutImplicit = this.args.map(arg => arg.getExpression(fs));
45
57
  if (this.isRaw) {
46
58
  let expressionType = 'scalar';
@@ -161,15 +173,62 @@ class ExprFunc extends expression_def_1.ExpressionDef {
161
173
  .join(', ')}) with source`);
162
174
  return (0, ast_utils_1.errorFor)('cannot call with source');
163
175
  }
164
- let funcCall = [
165
- {
166
- type: 'function_call',
167
- overload,
168
- args: argExprs.map(x => x.value),
169
- expressionType,
170
- structPath,
171
- },
172
- ];
176
+ const frag = {
177
+ type: 'function_call',
178
+ overload,
179
+ args: argExprs.map(x => x.value),
180
+ expressionType,
181
+ structPath,
182
+ };
183
+ let funcCall = [frag];
184
+ const dialect = (_e = fs.dialectObj()) === null || _e === void 0 ? void 0 : _e.name;
185
+ const dialectOverload = dialect ? overload.dialect[dialect] : undefined;
186
+ // TODO add in an error if you use an asymmetric function in BQ
187
+ // and the function uses joins
188
+ // TODO add in an error if you use an illegal join pattern
189
+ if (dialectOverload === undefined) {
190
+ this.log(`Function ${this.name} is not defined in dialect ${dialect}`);
191
+ }
192
+ else {
193
+ if ((props === null || props === void 0 ? void 0 : props.orderBys) && props.orderBys.length > 0) {
194
+ const isAnalytic = (0, malloy_types_1.expressionIsAnalytic)(overload.returnType.expressionType);
195
+ if (dialectOverload.supportsOrderBy || isAnalytic) {
196
+ const allObs = props.orderBys.flatMap(orderBy => isAnalytic
197
+ ? orderBy.getAnalyticOrderBy(fs)
198
+ : orderBy.getAggregateOrderBy(fs));
199
+ frag.orderBy = allObs;
200
+ }
201
+ else {
202
+ props.orderBys[0].log(`Function ${this.name} does not support order_by`);
203
+ }
204
+ }
205
+ if ((props === null || props === void 0 ? void 0 : props.limit) !== undefined) {
206
+ if (dialectOverload.supportsLimit) {
207
+ frag.limit = props.limit.limit;
208
+ }
209
+ else {
210
+ this.log(`Function ${this.name} does not support limit`);
211
+ }
212
+ }
213
+ }
214
+ if ((props === null || props === void 0 ? void 0 : props.partitionBys) && props.partitionBys.length > 0) {
215
+ const partitionByFields = [];
216
+ for (const partitionBy of props.partitionBys) {
217
+ for (const partitionField of partitionBy.partitionFields) {
218
+ const e = partitionField.getField(fs);
219
+ if (e.found === undefined) {
220
+ partitionField.log(`${partitionField.refString} is not defined`);
221
+ }
222
+ else if ((0, malloy_types_1.expressionIsScalar)(e.found.typeDesc().expressionType)) {
223
+ partitionByFields.push(partitionField.nameString);
224
+ }
225
+ else {
226
+ partitionField.log('Partition expression must be scalar');
227
+ }
228
+ }
229
+ }
230
+ frag.partitionBy = partitionByFields;
231
+ }
173
232
  if ([
174
233
  'sql_number',
175
234
  'sql_string',
@@ -1,12 +1,13 @@
1
- import { Filter } from '../query-properties/filters';
2
1
  import { ExprValue } from '../types/expr-value';
3
2
  import { ExpressionDef } from '../types/expression-def';
3
+ import { FieldPropStatement } from '../types/field-prop-statement';
4
4
  import { FieldSpace } from '../types/field-space';
5
- export declare class ExprFilter extends ExpressionDef {
5
+ export declare class ExprProps extends ExpressionDef {
6
6
  readonly expr: ExpressionDef;
7
- readonly filter: Filter;
7
+ readonly statements: FieldPropStatement[];
8
8
  elementType: string;
9
9
  legalChildTypes: import("../../../model/malloy_types").TypeDesc[];
10
- constructor(expr: ExpressionDef, filter: Filter);
10
+ constructor(expr: ExpressionDef, statements: FieldPropStatement[]);
11
+ private getFilteredExpression;
11
12
  getExpression(fs: FieldSpace): ExprValue;
12
13
  }
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright 2023 Google LLC
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files
7
+ * (the "Software"), to deal in the Software without restriction,
8
+ * including without limitation the rights to use, copy, modify, merge,
9
+ * publish, distribute, sublicense, and/or sell copies of the Software,
10
+ * and to permit persons to whom the Software is furnished to do so,
11
+ * subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.ExprProps = void 0;
26
+ const malloy_types_1 = require("../../../model/malloy_types");
27
+ const ast_utils_1 = require("../ast-utils");
28
+ const fragtype_utils_1 = require("../fragtype-utils");
29
+ const function_ordering_1 = require("./function-ordering");
30
+ const limit_1 = require("../query-properties/limit");
31
+ const partition_by_1 = require("./partition_by");
32
+ const expression_def_1 = require("../types/expression-def");
33
+ const expr_func_1 = require("./expr-func");
34
+ class ExprProps extends expression_def_1.ExpressionDef {
35
+ constructor(expr, statements) {
36
+ super({ expr, statements });
37
+ this.expr = expr;
38
+ this.statements = statements;
39
+ this.elementType = 'expression with props';
40
+ this.legalChildTypes = fragtype_utils_1.FT.anyAtomicT;
41
+ }
42
+ getFilteredExpression(fs, expr, wheres) {
43
+ if (wheres.length > 0) {
44
+ if (!this.expr.supportsWhere(expr)) {
45
+ this.expr.log('Filtered expression requires an aggregate computation');
46
+ return expr;
47
+ }
48
+ const filterList = [];
49
+ for (const where of wheres) {
50
+ const testList = where.getFilterList(fs);
51
+ if (testList.find(cond => (0, malloy_types_1.expressionIsCalculation)(cond.expressionType))) {
52
+ where.log('Cannot filter an expresion with an aggregate or analytical computation');
53
+ return expr;
54
+ }
55
+ filterList.push(...testList);
56
+ }
57
+ if (this.typeCheck(this.expr, { ...expr, expressionType: 'scalar' })) {
58
+ return {
59
+ ...expr,
60
+ value: [
61
+ {
62
+ type: 'filterExpression',
63
+ e: expr.value,
64
+ filterList,
65
+ },
66
+ ],
67
+ };
68
+ }
69
+ this.expr.log(`Cannot filter '${expr.dataType}' data`);
70
+ return (0, ast_utils_1.errorFor)('cannot filter type');
71
+ }
72
+ return expr;
73
+ }
74
+ getExpression(fs) {
75
+ const partitionBys = [];
76
+ let limit;
77
+ const orderBys = [];
78
+ const wheres = [];
79
+ for (const statement of this.statements) {
80
+ if (statement instanceof partition_by_1.PartitionBy) {
81
+ if (!this.expr.canSupportPartitionBy()) {
82
+ statement.log('`partition_by` is not supported for this kind of expression');
83
+ }
84
+ else {
85
+ partitionBys.push(statement);
86
+ }
87
+ }
88
+ else if (statement instanceof limit_1.Limit) {
89
+ if (limit) {
90
+ statement.log('limit already specified');
91
+ }
92
+ else if (!this.expr.canSupportLimit()) {
93
+ statement.log('`limit` is not supported for this kind of expression');
94
+ }
95
+ else {
96
+ limit = statement;
97
+ }
98
+ }
99
+ else if (statement instanceof function_ordering_1.FunctionOrdering) {
100
+ if (!this.expr.canSupportPartitionBy()) {
101
+ statement.log('`order_by` is not supported for this kind of expression');
102
+ }
103
+ else {
104
+ orderBys.push(statement);
105
+ }
106
+ }
107
+ else {
108
+ wheres.push(statement);
109
+ }
110
+ }
111
+ const resultExpr = this.expr instanceof expr_func_1.ExprFunc
112
+ ? this.expr.getPropsExpression(fs, {
113
+ partitionBys,
114
+ limit,
115
+ orderBys,
116
+ })
117
+ : this.expr.getExpression(fs);
118
+ return this.getFilteredExpression(fs, resultExpr, wheres);
119
+ }
120
+ }
121
+ exports.ExprProps = ExprProps;
122
+ //# sourceMappingURL=expr-props.js.map
@@ -0,0 +1,18 @@
1
+ import { FunctionOrderBy as ModelFunctionOrderBy } from '../../../model/malloy_types';
2
+ import { ExpressionDef } from '../types/expression-def';
3
+ import { FieldSpace } from '../types/field-space';
4
+ import { ListOf, MalloyElement } from '../types/malloy-element';
5
+ export declare class FunctionOrderBy extends MalloyElement {
6
+ readonly field: ExpressionDef;
7
+ readonly dir?: "asc" | "desc" | undefined;
8
+ elementType: string;
9
+ constructor(field: ExpressionDef, dir?: "asc" | "desc" | undefined);
10
+ getAnalyticOrderBy(fs: FieldSpace): ModelFunctionOrderBy;
11
+ getAggregateOrderBy(fs: FieldSpace): ModelFunctionOrderBy;
12
+ }
13
+ export declare class FunctionOrdering extends ListOf<FunctionOrderBy> {
14
+ elementType: string;
15
+ constructor(list: FunctionOrderBy[]);
16
+ getAnalyticOrderBy(fs: FieldSpace): ModelFunctionOrderBy[];
17
+ getAggregateOrderBy(fs: FieldSpace): ModelFunctionOrderBy[];
18
+ }
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright 2024 Google LLC
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files
7
+ * (the "Software"), to deal in the Software without restriction,
8
+ * including without limitation the rights to use, copy, modify, merge,
9
+ * publish, distribute, sublicense, and/or sell copies of the Software,
10
+ * and to permit persons to whom the Software is furnished to do so,
11
+ * subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.FunctionOrdering = exports.FunctionOrderBy = void 0;
26
+ const malloy_types_1 = require("../../../model/malloy_types");
27
+ const malloy_element_1 = require("../types/malloy-element");
28
+ const expr_id_reference_1 = require("./expr-id-reference");
29
+ class FunctionOrderBy extends malloy_element_1.MalloyElement {
30
+ constructor(field, dir) {
31
+ super();
32
+ this.field = field;
33
+ this.dir = dir;
34
+ this.elementType = 'orderBy';
35
+ this.has({ field });
36
+ }
37
+ getAnalyticOrderBy(fs) {
38
+ const expr = this.field.getExpression(fs);
39
+ if ((0, malloy_types_1.expressionIsAggregate)(expr.expressionType)) {
40
+ // Aggregates are okay
41
+ }
42
+ else if ((0, malloy_types_1.expressionIsScalar)(expr.expressionType)) {
43
+ if (!(this.field instanceof expr_id_reference_1.ExprIdReference) ||
44
+ expr.evalSpace === 'input') {
45
+ this.field.log('analytic `order_by` must be an aggregate or an output field reference');
46
+ }
47
+ }
48
+ else {
49
+ this.field.log('analytic `order_by` must be scalar or aggregate');
50
+ }
51
+ return { e: expr.value, dir: this.dir };
52
+ }
53
+ getAggregateOrderBy(fs) {
54
+ const expr = this.field.getExpression(fs);
55
+ if (!(0, malloy_types_1.expressionIsScalar)(expr.expressionType)) {
56
+ this.field.log('aggregate `order_by` must be scalar');
57
+ }
58
+ return { e: expr.value, dir: this.dir };
59
+ }
60
+ }
61
+ exports.FunctionOrderBy = FunctionOrderBy;
62
+ class FunctionOrdering extends malloy_element_1.ListOf {
63
+ constructor(list) {
64
+ super(list);
65
+ this.elementType = 'function-ordering';
66
+ }
67
+ getAnalyticOrderBy(fs) {
68
+ return this.list.map(el => el.getAnalyticOrderBy(fs));
69
+ }
70
+ getAggregateOrderBy(fs) {
71
+ return this.list.map(el => el.getAggregateOrderBy(fs));
72
+ }
73
+ }
74
+ exports.FunctionOrdering = FunctionOrdering;
75
+ //# sourceMappingURL=function-ordering.js.map
@@ -0,0 +1,7 @@
1
+ import { PartitionByFieldReference } from '../query-items/field-references';
2
+ import { ListOf } from '../types/malloy-element';
3
+ export declare class PartitionBy extends ListOf<PartitionByFieldReference> {
4
+ readonly partitionFields: PartitionByFieldReference[];
5
+ elementType: string;
6
+ constructor(partitionFields: PartitionByFieldReference[]);
7
+ }