@malloydata/malloy 0.0.157 → 0.0.158-dev240805161224

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 (67) hide show
  1. package/dist/lang/ast/expressions/constant-expression.d.ts +28 -0
  2. package/dist/lang/ast/expressions/{constant-sub-expression.js → constant-expression.js} +6 -5
  3. package/dist/lang/ast/expressions/expr-func.js +29 -11
  4. package/dist/lang/ast/expressions/expr-id-reference.d.ts +0 -1
  5. package/dist/lang/ast/expressions/expr-id-reference.js +0 -24
  6. package/dist/lang/ast/field-space/dynamic-space.d.ts +4 -1
  7. package/dist/lang/ast/field-space/dynamic-space.js +22 -11
  8. package/dist/lang/ast/field-space/index-field-space.js +3 -0
  9. package/dist/lang/ast/field-space/join-space-field.d.ts +3 -1
  10. package/dist/lang/ast/field-space/join-space-field.js +3 -2
  11. package/dist/lang/ast/field-space/parameter-space.d.ts +18 -0
  12. package/dist/lang/ast/field-space/parameter-space.js +67 -0
  13. package/dist/lang/ast/field-space/query-spaces.js +3 -0
  14. package/dist/lang/ast/field-space/reference-field.js +13 -4
  15. package/dist/lang/ast/field-space/refined-space.d.ts +2 -1
  16. package/dist/lang/ast/field-space/refined-space.js +12 -1
  17. package/dist/lang/ast/field-space/static-space.js +3 -5
  18. package/dist/lang/ast/index.d.ts +1 -0
  19. package/dist/lang/ast/index.js +1 -0
  20. package/dist/lang/ast/parameters/argument.d.ts +14 -0
  21. package/dist/lang/ast/parameters/argument.js +20 -0
  22. package/dist/lang/ast/parameters/has-parameter.d.ts +3 -5
  23. package/dist/lang/ast/parameters/has-parameter.js +24 -13
  24. package/dist/lang/ast/query-elements/query-arrow.js +7 -7
  25. package/dist/lang/ast/query-elements/query-head-struct.d.ts +6 -4
  26. package/dist/lang/ast/query-elements/query-head-struct.js +6 -5
  27. package/dist/lang/ast/query-elements/query-raw.js +7 -7
  28. package/dist/lang/ast/query-elements/query-reference.js +2 -2
  29. package/dist/lang/ast/query-items/field-references.d.ts +4 -0
  30. package/dist/lang/ast/query-items/field-references.js +12 -1
  31. package/dist/lang/ast/source-elements/named-source.d.ts +15 -12
  32. package/dist/lang/ast/source-elements/named-source.js +91 -60
  33. package/dist/lang/ast/source-elements/query-source.d.ts +4 -1
  34. package/dist/lang/ast/source-elements/query-source.js +9 -3
  35. package/dist/lang/ast/source-elements/refined-source.d.ts +3 -2
  36. package/dist/lang/ast/source-elements/refined-source.js +12 -7
  37. package/dist/lang/ast/source-elements/source.d.ts +6 -4
  38. package/dist/lang/ast/source-elements/source.js +19 -16
  39. package/dist/lang/ast/source-elements/sql-source.d.ts +2 -2
  40. package/dist/lang/ast/source-elements/sql-source.js +4 -3
  41. package/dist/lang/ast/source-properties/joins.d.ts +5 -4
  42. package/dist/lang/ast/source-properties/joins.js +7 -7
  43. package/dist/lang/ast/source-query-elements/sq-reference.d.ts +3 -1
  44. package/dist/lang/ast/source-query-elements/sq-reference.js +9 -2
  45. package/dist/lang/ast/statements/define-source.d.ts +4 -2
  46. package/dist/lang/ast/statements/define-source.js +28 -14
  47. package/dist/lang/ast/struct-utils.js +3 -2
  48. package/dist/lang/ast/types/expression-def.js +2 -0
  49. package/dist/lang/lib/Malloy/MalloyParser.d.ts +169 -101
  50. package/dist/lang/lib/Malloy/MalloyParser.js +2105 -1600
  51. package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +64 -9
  52. package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +40 -5
  53. package/dist/lang/malloy-to-ast.d.ts +5 -1
  54. package/dist/lang/malloy-to-ast.js +51 -10
  55. package/dist/lang/test/expressions.spec.js +21 -1
  56. package/dist/lang/test/field-symbols.spec.js +0 -2
  57. package/dist/lang/test/locations.spec.js +3 -0
  58. package/dist/lang/test/parameters.spec.d.ts +1 -0
  59. package/dist/lang/test/parameters.spec.js +578 -0
  60. package/dist/model/malloy_query.d.ts +8 -5
  61. package/dist/model/malloy_query.js +68 -37
  62. package/dist/model/malloy_types.d.ts +12 -14
  63. package/dist/model/malloy_types.js +22 -10
  64. package/package.json +1 -1
  65. package/dist/lang/ast/expressions/constant-sub-expression.d.ts +0 -16
  66. package/dist/lang/ast/parameters/constant-parameter.d.ts +0 -8
  67. package/dist/lang/ast/parameters/constant-parameter.js +0 -54
@@ -0,0 +1,578 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ const test_translator_1 = require("./test-translator");
10
+ require("./parse-expects");
11
+ describe('parameters', () => {
12
+ test('can declare parameter with no default value', () => {
13
+ expect(`
14
+ ##! experimental.parameters
15
+ source: ab_new(param::number) is ab
16
+ `).toTranslate();
17
+ });
18
+ test('can declare parameter with default value literal', () => {
19
+ expect(`
20
+ ##! experimental.parameters
21
+ source: ab_new(param::number is 7) is ab
22
+ `).toTranslate();
23
+ });
24
+ test('can declare parameter with default value constant', () => {
25
+ expect(`
26
+ ##! experimental.parameters
27
+ source: ab_new(param::number is 7 + 7) is ab
28
+ `).toTranslate();
29
+ });
30
+ test('cannot specify default value with incompatible type', () => {
31
+ expect((0, test_translator_1.markSource) `
32
+ ##! experimental.parameters
33
+ source: ab_new(param::number is ${'"hello"'}) is ab
34
+ `).translationToFailWith('Default value for parameter does not match declared type `number`');
35
+ });
36
+ test('error if paramter has no type or value', () => {
37
+ expect((0, test_translator_1.markSource) `
38
+ ##! experimental.parameters
39
+ source: ab_new(param) is ab
40
+ `).translationToFailWith('Parameter must have default value or declared type');
41
+ });
42
+ test('error if paramter type is null', () => {
43
+ expect((0, test_translator_1.markSource) `
44
+ ##! experimental.parameters
45
+ source: ab_new(param is null) is ab
46
+ `).translationToFailWith('Default value cannot have type `null`');
47
+ });
48
+ test('error if paramter type is range', () => {
49
+ expect((0, test_translator_1.markSource) `
50
+ ##! experimental.parameters
51
+ source: ab_new(param is 10 to 20) is ab
52
+ `).translationToFailWith('A Range is not a value');
53
+ });
54
+ test('no additional error if default value type is error', () => {
55
+ expect((0, test_translator_1.markSource) `
56
+ ##! experimental.parameters
57
+ source: ab_new(param::number is 1 + "foo") is ab
58
+ `).translationToFailWith("Non numeric('number,string') value with '+'");
59
+ });
60
+ test('can declare parameter with inferred type', () => {
61
+ expect(`
62
+ ##! experimental.parameters
63
+ source: ab_new(param is 7) is ab
64
+ `).toTranslate();
65
+ });
66
+ test('can pass parameter into extended base source', () => {
67
+ expect(`
68
+ ##! experimental.parameters
69
+ source: ab_new(param::number) is ab
70
+ source: ab_new_new(param::number) is ab_new(param) extend {}
71
+ `).toTranslate();
72
+ });
73
+ test.skip('can pass parameter into source of query', () => {
74
+ expect(`
75
+ ##! experimental.parameters
76
+ source: ab_new(param::number) is ab
77
+ source: ab_new_new(param::number) is ab_new(param) -> { select: * }
78
+ `).toTranslate();
79
+ });
80
+ test('can pass parameter to override default value with constant', () => {
81
+ expect(`
82
+ ##! experimental.parameters
83
+ source: ab_new(param::number is 10) is ab
84
+ source: ab_new_new is ab_new(param is 7) extend {}
85
+ `).toTranslate();
86
+ });
87
+ test('can pass parameter to override default value with param value', () => {
88
+ expect(`
89
+ ##! experimental.parameters
90
+ source: ab_new(param::number is 10) is ab
91
+ source: ab_new_new(param::number is 11) is ab_new(param) extend {}
92
+ `).toTranslate();
93
+ });
94
+ test('can pass parameter into named base source', () => {
95
+ expect(`
96
+ ##! experimental.parameters
97
+ source: ab_new(param::number) is ab
98
+ source: ab_new_new(param::number) is ab_new(param)
99
+ `).toTranslate();
100
+ });
101
+ test('can pass differently-named parameter into extended base source', () => {
102
+ expect(`
103
+ ##! experimental.parameters
104
+ source: ab_new(new_param::number) is ab
105
+ source: ab_new_new(new_new_param::number) is ab_new(new_param is new_new_param) extend {}
106
+ `).toTranslate();
107
+ });
108
+ test('can pass differently-named parameter into named base source', () => {
109
+ expect(`
110
+ ##! experimental.parameters
111
+ source: ab_new(new_param::number) is ab
112
+ source: ab_new_new(new_new_param::number) is ab_new(new_param is new_new_param)
113
+ `).toTranslate();
114
+ });
115
+ test('can pass parameter into base source longhand', () => {
116
+ expect(`
117
+ ##! experimental.parameters
118
+ source: ab_new(param::number) is ab
119
+ source: ab_new_new(param::number) is ab_new(param is param)
120
+ `).toTranslate();
121
+ });
122
+ test('can pass parameter into base source shorthand', () => {
123
+ expect(`
124
+ ##! experimental.parameters
125
+ source: ab_new(param::number) is ab
126
+ source: ab_new_new(param::number) is ab_new(param)
127
+ `).toTranslate();
128
+ });
129
+ test('can use declared parameter in dimension', () => {
130
+ expect(`
131
+ ##! experimental.parameters
132
+ source: ab_new(param::number) is ab extend {
133
+ dimension: param_plus_one is param + 1
134
+ }
135
+ `).toTranslate();
136
+ });
137
+ test('can use declared parameter in sql function', () => {
138
+ expect(`
139
+ ##! experimental { parameters sql_functions }
140
+ source: ab_new(param::number) is ab extend {
141
+ dimension: param_plus_one is sql_number("\${param} + 1")
142
+ }
143
+ run: ab_new(param is 1) -> param_plus_one
144
+ `).toTranslate();
145
+ });
146
+ test('can use declared parameter in nest extending other', () => {
147
+ expect(`
148
+ ##! experimental.parameters
149
+ source: ab_new(param::number is 10) is ab extend {
150
+ dimension: p1 is param
151
+ view: my_view is {
152
+ group_by: p2 is param
153
+ nest: nested is {
154
+ group_by: p3 is param
155
+ }
156
+ }
157
+ }
158
+ run: ab_new -> my_view
159
+ `).toTranslate();
160
+ });
161
+ test('can use declared parameter in source extension in view', () => {
162
+ expect(`
163
+ ##! experimental.parameters
164
+ source: ab_new(param::number is 10) is ab extend {
165
+ view: my_view is {
166
+ extend: {
167
+ dimension: p1 is param
168
+ }
169
+ group_by: p1
170
+ }
171
+ }
172
+ `).toTranslate();
173
+ });
174
+ test('can use declared parameter in nest with table', () => {
175
+ expect(`
176
+ ##! experimental.parameters
177
+ source: ab_new(param::number is 10) is _db_.table('aTable') extend {
178
+ dimension: p1 is param
179
+ view: my_view is {
180
+ group_by: p2 is param
181
+ nest: nested is {
182
+ group_by: p3 is param
183
+ }
184
+ }
185
+ }
186
+ run: ab_new -> my_view
187
+ `).toTranslate();
188
+ });
189
+ test('can pass argument for param', () => {
190
+ expect(`
191
+ ##! experimental.parameters
192
+ source: ab_new(param::number) is ab
193
+ run: ab_new(param is 1) -> { select: * }
194
+ `).toTranslate();
195
+ });
196
+ test('can not pass argument for default-valued param', () => {
197
+ expect(`
198
+ ##! experimental.parameters
199
+ source: ab_new(param is 1) is ab
200
+ run: ab_new -> { select: * }
201
+ `).toTranslate();
202
+ });
203
+ test('can pass zero args for source with default-valued param', () => {
204
+ expect(`
205
+ ##! experimental.parameters
206
+ source: ab_new(param is 1) is ab
207
+ run: ab_new() -> { select: * }
208
+ `).toTranslate();
209
+ });
210
+ test('can pass non-literal argument for param', () => {
211
+ expect(`
212
+ ##! experimental.parameters
213
+ source: ab_new(param::number) is ab
214
+ run: ab_new(param is 1 + 1) -> { select: * }
215
+ `).toTranslate();
216
+ });
217
+ test('parameter not included in wildcard', () => {
218
+ expect((0, test_translator_1.markSource) `
219
+ ##! experimental.parameters
220
+ source: ab_new(param::number) is ab extend {
221
+ view: all_fields is { select: * }
222
+ }
223
+ run: ab_new(param is 1) -> all_fields -> { select: ${'param'} }
224
+ `).translationToFailWith("'param' is not defined");
225
+ });
226
+ test('cannot reference renamed param in query against source', () => {
227
+ expect((0, test_translator_1.markSource) `
228
+ ##! experimental.parameters
229
+ source: ab_new(param::number) is ab
230
+ run: ab_new(param is 1) -> { select: p is ${'param'} }
231
+ `).translationToFailWith("'param' is not defined");
232
+ });
233
+ test('cannot reference param in query against source', () => {
234
+ expect((0, test_translator_1.markSource) `
235
+ ##! experimental.parameters
236
+ source: ab_new(param::number) is ab
237
+ run: ab_new(param is 1) -> { select: ${'param'} }
238
+ `).translationToFailWith("'param' is not defined");
239
+ });
240
+ test('cannot reference param in source extension', () => {
241
+ expect((0, test_translator_1.markSource) `
242
+ ##! experimental.parameters
243
+ source: ab_new(param::number) is ab
244
+ source: x is ab_new(param is 1) extend {
245
+ dimension: param_copy is ${'param'}
246
+ }
247
+ `).translationToFailWith("'param' is not defined");
248
+ });
249
+ test('cannot reference param in in-query source extension', () => {
250
+ expect((0, test_translator_1.markSource) `
251
+ ##! experimental.parameters
252
+ source: ab_new(param::number) is ab
253
+ run: ab_new(param is 1) -> {
254
+ extend: {
255
+ dimension: param_copy is ${'param'}
256
+ }
257
+ group_by: param_copy
258
+ }
259
+ `).translationToFailWith("'param' is not defined");
260
+ });
261
+ test('can reference field in source in argument', () => {
262
+ expect((0, test_translator_1.markSource) `
263
+ ##! experimental.parameters
264
+ source: ab_new(param::number) is ab
265
+ run: ab_new(param is ${'ai'}) -> { select: * }
266
+ `).translationToFailWith('`ai` is not defined');
267
+ });
268
+ test('can pass through parameter to joined source', () => {
269
+ expect(`
270
+ ##! experimental.parameters
271
+ source: ab_ext_1(a_1::string) is ab extend {
272
+ where: ai = a_1
273
+ }
274
+
275
+ source: ab_ext_2(a_2::string) is ab extend {
276
+ where: ai = a_2
277
+ join_many: ab_ext_1 is ab_ext_1(a_1 is a_2) on 1 = 1
278
+ }
279
+
280
+ run: ab_ext_2(a_2 is "CA") -> {
281
+ group_by:
282
+ a1 is ai,
283
+ a2 is ab_ext_1.ai
284
+ aggregate: c is count()
285
+ }
286
+ `).toTranslate();
287
+ });
288
+ test.skip('can pass through parameter to source in joined query', () => {
289
+ expect(`
290
+ ##! experimental.parameters
291
+ source: ab_ext_1(a_1::string) is ab extend {
292
+ where: ai = a_1
293
+ }
294
+
295
+ source: ab_ext_2(a_2::string) is ab extend {
296
+ where: ai = a_2
297
+ join_many: ab_ext_1 is ab_ext_1(a_1 is a_2) -> { select: * } on 1 = 1
298
+ }
299
+ `).toTranslate();
300
+ });
301
+ test.skip('can pass through parameter to view in joined query', () => {
302
+ expect(`
303
+ ##! experimental.parameters
304
+ source: ab_ext(param::string) is ab extend {
305
+ join_many: abq is ab -> { select: p is param } on 1 = 1
306
+ }
307
+ `).toTranslate();
308
+ });
309
+ test.skip('can pass through parameter to source in query in SQL source', () => {
310
+ expect(`
311
+ ##! experimental.parameters
312
+ source: ab_ext(param::string) is ab
313
+ source: sql_query(a_1::string) is duckdb.sql("""
314
+ SELECT * FROM (%{ ab_ext(param is a_1) -> { select: * } })
315
+ """)
316
+ `).toTranslate();
317
+ });
318
+ test.skip('can pass through parameter to view in query in SQL source', () => {
319
+ expect(`
320
+ ##! experimental.parameters
321
+ source: sql_query(a_1::string) is duckdb.sql("""
322
+ SELECT * FROM (%{ ab -> { select: p is param } })
323
+ """)
324
+ `).toTranslate();
325
+ });
326
+ test.skip('can pass through parameter to source in query in joined SQL source', () => {
327
+ expect(`
328
+ ##! experimental.parameters
329
+ source: ab_ext_1(a_1::string) is ab extend {
330
+ where: ai = a_1
331
+ }
332
+
333
+ source: ab_ext_2(a_2::string) is ab extend {
334
+ where: ai = a_2
335
+ join_many: ab_ext_1 is duckdb.sql("""
336
+ SELECT * FROM (%{ ab_ext_1(a_1 is a_2) -> { select: * } })
337
+ """) on 1 = 1
338
+ }
339
+ `).toTranslate();
340
+ });
341
+ test('can reference param in query against source', () => {
342
+ expect((0, test_translator_1.markSource) `
343
+ ##! experimental.parameters
344
+ source: ab_new(param::number) is ab
345
+ run: ab_new(param is 1) -> { select: ${'param'} }
346
+ `).translationToFailWith("'param' is not defined");
347
+ });
348
+ test('can reference param in view in source', () => {
349
+ expect(`
350
+ ##! experimental.parameters
351
+ source: ab_new(param::number) is ab extend {
352
+ view: x is { select: param }
353
+ }
354
+ `).toTranslate();
355
+ });
356
+ test('can declare dimension which is just the parameter', () => {
357
+ expect(`
358
+ ##! experimental.parameters
359
+ source: ab_new(param::number) is ab extend {
360
+ dimension: p is param
361
+ }
362
+ `).toTranslate();
363
+ });
364
+ test('cannot reference param in expression in query against source', () => {
365
+ expect(`
366
+ ##! experimental.parameters
367
+ source: ab_new(param::number) is ab
368
+ run: ab_new(param is 1) -> { select: p is ${'param'} }
369
+ `).translationToFailWith("'param' is not defined");
370
+ });
371
+ test('error when declaring parameter twice', () => {
372
+ expect((0, test_translator_1.markSource) `
373
+ ##! experimental.parameters
374
+ source: ab_new(param::number, ${'param::number'}) is ab
375
+ `).translationToFailWith('Cannot redefine parameter `param`');
376
+ });
377
+ // This behavior will likely change in the future; but in the meantime, this
378
+ // safeguards against some confusion about parameter scoping
379
+ test('error when declaring parameter with same name as field (extended)', () => {
380
+ expect(`
381
+ ##! experimental.parameters
382
+ source: ab_new(ai::string) is ab extend {
383
+ dimension: foo is upper(ai)
384
+ }
385
+ `).translationToFailWith('No matching overload for function upper(number)', 'Illegal shadowing of field `ai` by parameter with the same name');
386
+ });
387
+ test('can shadow field that is excepted', () => {
388
+ expect(`
389
+ ##! experimental.parameters
390
+ source: ab_new(ai::string) is ab extend {
391
+ except: ai
392
+ dimension: foo is upper(ai)
393
+ }
394
+ `).toTranslate();
395
+ });
396
+ test('error when declaring parameter with same name as field (not extended)', () => {
397
+ expect((0, test_translator_1.markSource) `
398
+ ##! experimental.parameters
399
+ source: ab_new(${'ai::string'}) is ab
400
+ `).translationToFailWith('Illegal shadowing of field `ai` by parameter with the same name');
401
+ });
402
+ test('do not inherit parameters from base source', () => {
403
+ expect((0, test_translator_1.markSource) `
404
+ ##! experimental.parameters
405
+ source: ab_new(param::number) is ab
406
+ source: ab_new_new is ab_new(param is 1)
407
+ run: ab_new_new(${'param'} is 2) -> { select: * }
408
+ `).translationToFailWith('`ab_new_new` has no declared parameter named `param`');
409
+ });
410
+ test('error when declaring field with same name as parameter', () => {
411
+ expect((0, test_translator_1.markSource) `
412
+ ##! experimental.parameters
413
+ source: ab_new(param::number) is ab extend {
414
+ dimension: param is 1
415
+ }
416
+ `).translationToFailWith("Cannot redefine 'param'");
417
+ });
418
+ test('error when declaring parameter without experiment enabled', () => {
419
+ expect((0, test_translator_1.markSource) `
420
+ source: ab_new(param::number) is ab
421
+ `).translationToFailWith("Experimental flag 'parameters' required to enable this feature");
422
+ });
423
+ test('cannot except parameter from extended source', () => {
424
+ expect((0, test_translator_1.markSource) `
425
+ ##! experimental.parameters
426
+ source: ab_new(param_a::number) is ab
427
+ source: ab_new_new(param_b::number) is ab_new(param_a is 1) extend {
428
+ except: param_a
429
+ }
430
+ `).translationToFailWith('`param_a` is not defined');
431
+ });
432
+ test('cannot except parameter in direct extend', () => {
433
+ expect((0, test_translator_1.markSource) `
434
+ ##! experimental.parameters
435
+ source: ab_new(param::number) is ab extend {
436
+ except: param
437
+ }
438
+ `).translationToFailWith('Illegal `except:` of parameter');
439
+ });
440
+ test('cannot accept parameter', () => {
441
+ expect((0, test_translator_1.markSource) `
442
+ ##! experimental.parameters
443
+ source: ab_new(param::number) is ab extend {
444
+ accept: param
445
+ }
446
+ `).translationToFailWith('Illegal `accept:` of parameter');
447
+ });
448
+ test('error when using parameter without experiment enabled', () => {
449
+ expect((0, test_translator_1.markSource) `
450
+ run: ab_new${'(param is param)'} -> { select: * }
451
+ `).translationToFailWith("Experimental flag 'parameters' required to enable this feature");
452
+ });
453
+ test('parameters cannot reference themselves', () => {
454
+ expect((0, test_translator_1.markSource) `
455
+ ##! experimental.parameters
456
+ source: ab_new(param::number) is ab
457
+ run: ab_new(param is ${'param'}) -> { select: * }
458
+ `).translationToFailWith('`param` is not defined');
459
+ });
460
+ // This just looks like circular referencing--in reality, you cannot reference other
461
+ // parameters in parameter arguments, hence just "xxx is not defined"
462
+ test('error when circularly referencing mutually recursive parameters in argument', () => {
463
+ expect((0, test_translator_1.markSource) `
464
+ ##! experimental.parameters
465
+ source: ab_new(p_a::number, p_b::number) is ab
466
+ run: ab_new(p_a is ${'p_b'}, p_b is ${'p_a'}) -> { select: * }
467
+ `).translationToFailWith('`p_b` is not defined', '`p_a` is not defined');
468
+ });
469
+ test('error when passing param with no name', () => {
470
+ expect((0, test_translator_1.markSource) `
471
+ ##! experimental.parameters
472
+ source: ab_new(param::number) is ab
473
+ run: ab_new(${'1'}) -> { select: * }
474
+ `).translationToFailWith('Parameterized source arguments must be named with `parameter_name is`', 'Argument not provided for required parameter `param`');
475
+ });
476
+ test('error when passing param with incorrect name', () => {
477
+ expect((0, test_translator_1.markSource) `
478
+ ##! experimental.parameters
479
+ source: ab_new(param::number) is ab
480
+ run: ab_new(${'wrong_name'} is 1, param is 2) -> { select: * }
481
+ `).translationToFailWith('`ab_new` has no declared parameter named `wrong_name`');
482
+ });
483
+ test('error when passing param multiple times', () => {
484
+ expect((0, test_translator_1.markSource) `
485
+ ##! experimental.parameters
486
+ source: ab_new(param::number) is ab
487
+ run: ab_new(param is 1, ${'param is 2'}) -> { select: * }
488
+ `).translationToFailWith('Cannot pass argument for `param` more than once');
489
+ });
490
+ test('error when not specifying argument for param with parentheses', () => {
491
+ expect((0, test_translator_1.markSource) `
492
+ ##! experimental.parameters
493
+ source: ab_new(param::number) is ab
494
+ run: ${'ab_new'}() -> { select: * }
495
+ `).translationToFailWith('Argument not provided for required parameter `param`');
496
+ });
497
+ test('error when not specifying argument for param without parentheses', () => {
498
+ expect((0, test_translator_1.markSource) `
499
+ ##! experimental.parameters
500
+ source: ab_new(param::number) is ab
501
+ run: ${'ab_new'} -> { select: * }
502
+ `).translationToFailWith('Argument not provided for required parameter `param`');
503
+ });
504
+ test('error when not specifying argument for param second time', () => {
505
+ expect((0, test_translator_1.markSource) `
506
+ ##! experimental.parameters
507
+ source: ab_new(param::number) is ab
508
+ run: ab_new(param is 1) -> { select: * }
509
+ run: ${'ab_new'} -> { select: * }
510
+ `).translationToFailWith('Argument not provided for required parameter `param`');
511
+ });
512
+ test('error when referencing parameter that does not exist in join definition', () => {
513
+ expect((0, test_translator_1.markSource) `
514
+ ##! experimental.parameters
515
+ source: ab_new_1(param_1::number) is ab
516
+ source: ab_new_2(param_2::number) is ab extend {
517
+ join_one: ab_join is ab_new_1(param_1 is ${'param_3'})
518
+ }
519
+ `).translationToFailWith('`param_3` is not defined');
520
+ });
521
+ test('error when referencing identifier in default param value', () => {
522
+ expect((0, test_translator_1.markSource) `
523
+ ##! experimental.parameters
524
+ source: ab_new_1(param_1 is ${'ident'}) is ab
525
+ `).translationToFailWith('Only constants allowed in parameter default values');
526
+ });
527
+ test.skip('can use param in multi-stage query', () => {
528
+ expect(`
529
+ ##! experimental.parameters
530
+ source: ab_new(param::number) is ab extend {
531
+ view: q is {
532
+ select: *
533
+ } -> {
534
+ group_by: x is param
535
+ }
536
+ }
537
+ `).toTranslate();
538
+ });
539
+ test('can not pass parameter into source of query yet', () => {
540
+ expect((0, test_translator_1.markSource) `
541
+ ##! experimental.parameters
542
+ source: ab_new(param::number) is ab
543
+ source: ab_new_new(param::number) is ab_new(${'param'}) -> { select: * }
544
+ `).translationToFailWith('`param` is not defined');
545
+ });
546
+ test.skip('can add an annotation to a param', () => {
547
+ expect(`
548
+ ##! experimental.parameters
549
+ source: ab_new(
550
+ # mytag=1
551
+ param::number
552
+ ) is ab
553
+ `).toTranslate();
554
+ });
555
+ test('source arguments from query propagate as arguments not parameters', () => {
556
+ expect(`
557
+ ##! experimental.parameters
558
+ source: ab_new(param::number) is ab extend {
559
+ dimension: param_value is param
560
+ }
561
+ query: foo is ab_new(param is 1) -> { select: param_value }
562
+ source: foo_ext is foo
563
+ run: foo_ext -> { select: param_value }
564
+ `).toTranslate();
565
+ });
566
+ test('source arguments carry over from previous invocation', () => {
567
+ expect(`
568
+ ##! experimental.parameters
569
+ source: ab_new(param::number) is ab extend {
570
+ dimension: param_value is param
571
+ }
572
+ source: foo is ab_new(param is 1)
573
+ source: foo_ext is foo
574
+ run: foo_ext -> { select: param_value }
575
+ `).toTranslate();
576
+ });
577
+ });
578
+ //# sourceMappingURL=parameters.spec.js.map
@@ -1,5 +1,5 @@
1
1
  import { Dialect, DialectFieldList } from '../dialect';
2
- import { AggregateFragment, AggregateFunctionType, Annotation, CompiledQuery, DialectFragment, Expr, FieldDef, FieldFragment, Filtered, FilterExpression, FilterFragment, FunctionCallFragment, FunctionOverloadDef, FunctionParameterDef, JoinRelationship, ModelDef, OrderBy, OutputFieldFragment, Parameter, ParameterFragment, PipeSegment, Query, QueryFieldDef, QuerySegment, ResultMetadataDef, ResultStructMetadataDef, SearchIndexResult, SourceReferenceFragment, SegmentFieldDef, SpreadFragment, SQLExpressionFragment, SqlStringFragment, StructDef, StructRef, TurtleDef, UngroupFragment, FunctionOrderBy } from './malloy_types';
2
+ import { AggregateFragment, AggregateFunctionType, Annotation, CompiledQuery, DialectFragment, Expr, FieldDef, FieldFragment, Filtered, FilterExpression, FilterFragment, FunctionCallFragment, FunctionOverloadDef, FunctionParameterDef, JoinRelationship, ModelDef, OrderBy, OutputFieldFragment, Parameter, ParameterFragment, PipeSegment, Query, QueryFieldDef, QuerySegment, ResultMetadataDef, ResultStructMetadataDef, SearchIndexResult, SourceReferenceFragment, SegmentFieldDef, SpreadFragment, SQLExpressionFragment, SqlStringFragment, StructDef, StructRef, TurtleDef, UngroupFragment, FunctionOrderBy, Argument } from './malloy_types';
3
3
  import { Connection } from '../runtime_types';
4
4
  import { AndChain } from './utils';
5
5
  import { QueryInfo } from '../dialect/dialect';
@@ -76,7 +76,7 @@ declare class QueryField extends QueryNode {
76
76
  getParamForArgIndex(params: FunctionParameterDef[], argIndex: number): FunctionParameterDef;
77
77
  generateFunctionCallExpression(resultSet: FieldInstanceResult, context: QueryStruct, frag: FunctionCallFragment, state: GenerateState): string;
78
78
  generateSpread(_resultSet: FieldInstanceResult, _context: QueryStruct, _frag: SpreadFragment, _state: GenerateState): string;
79
- generateParameterFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: ParameterFragment, _state: GenerateState): string;
79
+ generateParameterFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: ParameterFragment, state: GenerateState): string;
80
80
  generateFilterFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: FilterFragment, state: GenerateState): string;
81
81
  generateDimFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: Expr, state: GenerateState): string;
82
82
  generateUngroupedFragment(resultSet: FieldInstanceResult, context: QueryStruct, expr: UngroupFragment, state: GenerateState): string;
@@ -284,6 +284,7 @@ declare class QueryQuery extends QueryField {
284
284
  }
285
285
  /** Structure object as it is used to build a query */
286
286
  declare class QueryStruct extends QueryNode {
287
+ readonly sourceArguments: Record<string, Argument> | undefined;
287
288
  fieldDef: StructDef;
288
289
  parent: QueryStruct | undefined;
289
290
  model: QueryModel;
@@ -291,8 +292,10 @@ declare class QueryStruct extends QueryNode {
291
292
  pathAliasMap: Map<string, string>;
292
293
  dialect: Dialect;
293
294
  connectionName: string;
294
- constructor(fieldDef: StructDef, parent: ParentQueryStruct | ParentQueryModel);
295
- parameters(): Record<string, Parameter>;
295
+ constructor(fieldDef: StructDef, sourceArguments: Record<string, Argument> | undefined, parent: ParentQueryStruct | ParentQueryModel);
296
+ resolveParentParameterReferences(param: Parameter): Parameter;
297
+ private _arguments;
298
+ arguments(): Record<string, Argument>;
296
299
  addFieldsFromFieldList(fields: FieldDef[]): void;
297
300
  getAliasIdentifier(): string;
298
301
  getSQLIdentifier(): string;
@@ -346,7 +349,7 @@ export declare class QueryModel {
346
349
  constructor(modelDef: ModelDef | undefined);
347
350
  loadModelFromDef(modelDef: ModelDef): void;
348
351
  getStructByName(name: string): QueryStruct;
349
- getStructFromRef(structRef: StructRef): QueryStruct;
352
+ getStructFromRef(structRef: StructRef, sourceArguments: Record<string, Argument> | undefined): QueryStruct;
350
353
  loadQuery(query: Query, stageWriter: StageWriter | undefined, emitFinalStage?: boolean, isJoinedSubquery?: boolean): QueryResults;
351
354
  compileQuery(query: Query, finalize?: boolean): CompiledQuery;
352
355
  exploreSearchSQLMap: Map<any, any>;