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