@malloydata/malloy-tests 0.0.68-dev230808000650 → 0.0.68

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 (81) hide show
  1. package/dist/databases/all/db_index.spec.d.ts +1 -0
  2. package/dist/databases/all/db_index.spec.js +36 -0
  3. package/dist/databases/all/db_index.spec.js.map +1 -0
  4. package/dist/databases/all/expr.spec.d.ts +0 -2
  5. package/dist/databases/all/expr.spec.js +2 -547
  6. package/dist/databases/all/expr.spec.js.map +1 -1
  7. package/dist/databases/all/functions.spec.d.ts +1 -2
  8. package/dist/databases/all/functions.spec.js +2 -751
  9. package/dist/databases/all/functions.spec.js.map +1 -1
  10. package/dist/databases/all/join.spec.d.ts +1 -2
  11. package/dist/databases/all/join.spec.js +2 -276
  12. package/dist/databases/all/join.spec.js.map +1 -1
  13. package/dist/databases/all/nomodel.spec.d.ts +1 -2
  14. package/dist/databases/all/nomodel.spec.js +2 -923
  15. package/dist/databases/all/nomodel.spec.js.map +1 -1
  16. package/dist/databases/all/orderby.spec.d.ts +1 -2
  17. package/dist/databases/all/orderby.spec.js +2 -191
  18. package/dist/databases/all/orderby.spec.js.map +1 -1
  19. package/dist/databases/all/problems.spec.d.ts +1 -2
  20. package/dist/databases/all/problems.spec.js +2 -80
  21. package/dist/databases/all/problems.spec.js.map +1 -1
  22. package/dist/databases/all/sql_expressions.spec.d.ts +1 -2
  23. package/dist/databases/all/sql_expressions.spec.js +2 -62
  24. package/dist/databases/all/sql_expressions.spec.js.map +1 -1
  25. package/dist/databases/all/time.spec.d.ts +1 -3
  26. package/dist/databases/all/time.spec.js +2 -615
  27. package/dist/databases/all/time.spec.js.map +1 -1
  28. package/dist/databases/{all/index.spec.d.ts → shared/db_index.d.ts} +1 -0
  29. package/dist/databases/{all/index.spec.js → shared/db_index.js} +2 -33
  30. package/dist/databases/shared/db_index.js.map +1 -0
  31. package/dist/databases/shared/expr.d.ts +3 -0
  32. package/dist/databases/shared/expr.js +551 -0
  33. package/dist/databases/shared/expr.js.map +1 -0
  34. package/dist/databases/shared/functions.d.ts +3 -0
  35. package/dist/databases/shared/functions.js +754 -0
  36. package/dist/databases/shared/functions.js.map +1 -0
  37. package/dist/databases/shared/join.d.ts +3 -0
  38. package/dist/databases/shared/join.js +302 -0
  39. package/dist/databases/shared/join.js.map +1 -0
  40. package/dist/databases/shared/nomodel.d.ts +3 -0
  41. package/dist/databases/shared/nomodel.js +950 -0
  42. package/dist/databases/shared/nomodel.js.map +1 -0
  43. package/dist/databases/shared/orderby.d.ts +3 -0
  44. package/dist/databases/shared/orderby.js +217 -0
  45. package/dist/databases/shared/orderby.js.map +1 -0
  46. package/dist/databases/shared/problems.d.ts +3 -0
  47. package/dist/databases/shared/problems.js +106 -0
  48. package/dist/databases/shared/problems.js.map +1 -0
  49. package/dist/databases/shared/sql_expressions.d.ts +3 -0
  50. package/dist/databases/shared/sql_expressions.js +88 -0
  51. package/dist/databases/shared/sql_expressions.js.map +1 -0
  52. package/dist/databases/shared/test_list.js +18 -18
  53. package/dist/databases/shared/test_list.js.map +1 -1
  54. package/dist/databases/shared/time.d.ts +3 -0
  55. package/dist/databases/shared/time.js +640 -0
  56. package/dist/databases/shared/time.js.map +1 -0
  57. package/dist/index.d.ts +9 -10
  58. package/dist/index.js +19 -21
  59. package/dist/index.js.map +1 -1
  60. package/package.json +6 -6
  61. package/src/databases/all/db_index.spec.ts +37 -0
  62. package/src/databases/all/expr.spec.ts +2 -670
  63. package/src/databases/all/functions.spec.ts +1 -1101
  64. package/src/databases/all/join.spec.ts +1 -315
  65. package/src/databases/all/nomodel.spec.ts +2 -1124
  66. package/src/databases/all/orderby.spec.ts +1 -234
  67. package/src/databases/all/problems.spec.ts +1 -87
  68. package/src/databases/all/sql_expressions.spec.ts +1 -71
  69. package/src/databases/all/time.spec.ts +1 -761
  70. package/src/databases/{all/index.spec.ts → shared/db_index.ts} +2 -13
  71. package/src/databases/shared/expr.ts +695 -0
  72. package/src/databases/shared/functions.ts +1126 -0
  73. package/src/databases/shared/join.ts +340 -0
  74. package/src/databases/shared/nomodel.ts +1150 -0
  75. package/src/databases/shared/orderby.ts +260 -0
  76. package/src/databases/shared/problems.ts +113 -0
  77. package/src/databases/shared/sql_expressions.ts +96 -0
  78. package/src/databases/shared/test_list.ts +9 -9
  79. package/src/databases/shared/time.ts +786 -0
  80. package/src/index.ts +10 -11
  81. package/dist/databases/all/index.spec.js.map +0 -1
@@ -23,762 +23,13 @@
23
23
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
24
  */
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.functionsSharedTests = void 0;
27
26
  const runtimes_1 = require("../../runtimes");
28
27
  const util_1 = require("../../util");
29
- const functionsSharedTests = (runtimes, _splitFunction) => {
30
- const expressionModelText = `
31
- source: aircraft_models is table('malloytest.aircraft_models'){
32
- primary_key: aircraft_model_code
33
- }
34
-
35
- source: aircraft is table('malloytest.aircraft'){
36
- primary_key: tail_num
37
- join_one: aircraft_models with aircraft_model_code
38
- measure: aircraft_count is count()
39
- }
40
-
41
- source: airports is table('malloytest.airports') {}
42
-
43
- source: state_facts is table('malloytest.state_facts') {}
44
- `;
45
- const expressionModels = new Map();
46
- runtimes.runtimeMap.forEach((runtime, databaseName) => expressionModels.set(databaseName, runtime.loadModel(expressionModelText)));
47
- expressionModels.forEach((expressionModel, databaseName) => {
48
- const funcTestGeneral = async (expr, type, expected) => {
49
- const run = async () => {
50
- return await expressionModel
51
- .loadQuery(`
52
- query: aircraft -> { ${type}: f is ${expr} }`)
53
- .run();
54
- };
55
- if (expected.success !== undefined) {
56
- const result = await run();
57
- expect(result.data.path(0, 'f').value).toBe(expected.success);
58
- }
59
- else {
60
- expect(run).rejects.toThrowError(expected.error);
61
- }
62
- };
63
- const funcTest = (expr, expexted) => funcTestGeneral(expr, 'group_by', { success: expexted });
64
- const funcTestAgg = (expr, expexted) => funcTestGeneral(expr, 'aggregate', { success: expexted });
65
- const funcTestMultiple = async (...testCases) => {
66
- const run = async () => {
67
- return await expressionModel
68
- .loadQuery(`
69
- query: aircraft -> { ${testCases.map((testCase, i) => `group_by: f${i} is ${testCase[0]}`)} }`)
70
- .run();
71
- };
72
- const result = await run();
73
- testCases.forEach((testCase, i) => {
74
- expect(result.data.path(0, `f${i}`).value).toBe(testCase[1]);
75
- });
76
- };
77
- describe('concat', () => {
78
- it(`works - ${databaseName}`, async () => {
79
- await funcTestMultiple(["concat('foo', 'bar')", 'foobar'], ["concat(1, 'bar')", '1bar'], [
80
- "concat('cons', true)",
81
- databaseName === 'postgres' ? 'const' : 'construe',
82
- ], ["concat('foo', @2003)", 'foo2003-01-01'], [
83
- "concat('foo', @2003-01-01 12:00:00)",
84
- databaseName === 'bigquery'
85
- ? 'foo2003-01-01 12:00:00+00'
86
- : 'foo2003-01-01 12:00:00',
87
- ],
88
- // TODO Maybe implement consistent null behavior
89
- // ["concat('foo', null)", null],
90
- ['concat()', '']);
91
- });
92
- });
93
- describe('round', () => {
94
- it(`works - ${databaseName}`, async () => {
95
- await funcTestMultiple(['round(1.2)', 1],
96
- // TODO Remove when we upgrade to DuckDB 0.8.X -- DuckDB has some bugs with rounding
97
- // that are fixed in 0.8.
98
- ...(databaseName === 'duckdb_wasm'
99
- ? []
100
- : [['round(12.222, 1)', 12.2]]), ['round(12.2, -1)', 10], ['round(null)', null], ['round(1, null)', null]);
101
- });
102
- });
103
- describe('floor', () => {
104
- it(`works - ${databaseName}`, async () => {
105
- await funcTestMultiple(['floor(1.9)', 1],
106
- // TODO Remove when we upgrade to DuckDB 0.8.X -- DuckDB has some bugs with rounding
107
- // that are fixed in 0.8.
108
- ...(databaseName === 'duckdb_wasm'
109
- ? []
110
- : [['floor(-1.9)', -2]]), ['floor(null)', null]);
111
- await funcTest('floor(1.9)', 1);
112
- });
113
- });
114
- describe('ceil', () => {
115
- it(`works - ${databaseName}`, async () => {
116
- await funcTestMultiple(['ceil(1.9)', 2],
117
- // TODO Remove when we upgrade to DuckDB 0.8.X -- DuckDB has some bugs with rounding
118
- // that are fixed in 0.8.
119
- ...(databaseName === 'duckdb_wasm'
120
- ? []
121
- : [['ceil(-1.9)', -1]]), ['ceil(null)', null]);
122
- });
123
- });
124
- describe('length', () => {
125
- it(`works - ${databaseName}`, async () => {
126
- await funcTestMultiple(["length('foo')", 3], ['length(null)', null]);
127
- });
128
- });
129
- describe('lower', () => {
130
- it(`works - ${databaseName}`, async () => {
131
- await funcTestMultiple(["lower('FoO')", 'foo'], ['lower(null)', null]);
132
- });
133
- });
134
- describe('upper', () => {
135
- it(`works - ${databaseName}`, async () => {
136
- await funcTestMultiple(["upper('fOo')", 'FOO'], ['upper(null)', null]);
137
- });
138
- });
139
- describe('regexp_extract', () => {
140
- it(`works - ${databaseName}`, async () => {
141
- await funcTestMultiple(["regexp_extract('I have a dog', r'd[aeiou]g')", 'dog'], ["regexp_extract(null, r'd[aeiou]g')", null], ["regexp_extract('foo', null)", null], ["regexp_extract('I have a d0g', r'd\\dg')", 'd0g']);
142
- });
143
- });
144
- describe('replace', () => {
145
- it(`works - ${databaseName}`, async () => {
146
- await funcTestMultiple(["replace('aaaa', 'a', 'c')", 'cccc'], ["replace('aaaa', r'.', 'c')", 'cccc'], [
147
- "replace('axbxc', r'(a).(b).(c)', '\\\\0 - \\\\1 - \\\\2 - \\\\3')",
148
- databaseName === 'postgres'
149
- ? '\\0 - a - b - c'
150
- : 'axbxc - a - b - c',
151
- ], ["replace('aaaa', '', 'c')", 'aaaa'], ["replace(null, 'a', 'c')", null], ["replace('aaaa', null, 'c')", null], ["replace('aaaa', 'a', null)", null]);
152
- });
153
- });
154
- describe('substr', () => {
155
- it(`works - ${databaseName}`, async () => {
156
- await funcTestMultiple(["substr('foo', 2)", 'oo'], ["substr('foo', 2, 1)", 'o'], ["substr('foo bar baz', -3)", 'baz'], ['substr(null, 1, 2)', null], ["substr('aaaa', null, 1)", null], ["substr('aaaa', 1, null)", null]);
157
- });
158
- });
159
- describe('raw function call', () => {
160
- it(`works - ${databaseName}`, async () => {
161
- await funcTestMultiple(['floor(cbrt!(27)::number)', 3], ['floor(cbrt!number(27))', 3], ["substr('foo bar baz', -3)", 'baz'], ['substr(null, 1, 2)', null], ["substr('aaaa', null, 1)", null], ["substr('aaaa', 1, null)", null]);
162
- });
163
- });
164
- describe('stddev', () => {
165
- // TODO symmetric aggregates don't work with custom aggregate functions in BQ currently
166
- if (databaseName === 'bigquery')
167
- return;
168
- it(`works - ${databaseName}`, async () => {
169
- await funcTestAgg('round(stddev(aircraft_models.seats))', 29);
170
- });
171
- it(`works with struct - ${databaseName}`, async () => {
172
- await funcTestAgg('round(aircraft_models.stddev(aircraft_models.seats))', 41);
173
- });
174
- it(`works with implicit parameter - ${databaseName}`, async () => {
175
- await funcTestAgg('round(aircraft_models.seats.stddev())', 41);
176
- });
177
- it(`works with filter - ${databaseName}`, async () => {
178
- await funcTestAgg('round(aircraft_models.seats.stddev() { where: 1 = 1 })', 41);
179
- await funcTestAgg('round(aircraft_models.seats.stddev() { where: aircraft_models.seats > 4 })', 69);
180
- });
181
- });
182
- describe('row_number', () => {
183
- it(`works when the order by is a dimension - ${databaseName}`, async () => {
184
- const result = await expressionModel
185
- .loadQuery(`query: state_facts -> {
186
- group_by: state
187
- calculate: row_num is row_number()
188
- }`)
189
- .run();
190
- expect(result.data.path(0, 'row_num').value).toBe(1);
191
- expect(result.data.path(1, 'row_num').value).toBe(2);
192
- });
193
- it(`works when the order by is a dimension in the other order - ${databaseName}`, async () => {
194
- const result = await expressionModel
195
- .loadQuery(`query: state_facts -> {
196
- calculate: row_num is row_number()
197
- group_by: state
198
- }`)
199
- .run();
200
- expect(result.data.path(0, 'row_num').value).toBe(1);
201
- expect(result.data.path(1, 'row_num').value).toBe(2);
202
- });
203
- it(`works when the order by is a measure - ${databaseName}`, async () => {
204
- const result = await expressionModel
205
- .loadQuery(`query: state_facts -> {
206
- group_by: popular_name
207
- aggregate: c is count()
208
- calculate: row_num is row_number()
209
- }`)
210
- .run();
211
- expect(result.data.path(0, 'row_num').value).toBe(1);
212
- expect(result.data.path(1, 'row_num').value).toBe(2);
213
- });
214
- it(`works when the order by is a measure but there is no group by - ${databaseName}`, async () => {
215
- const result = await expressionModel
216
- .loadQuery(`query: state_facts -> {
217
- aggregate: c is count()
218
- calculate: row_num is row_number()
219
- }`)
220
- .run();
221
- expect(result.data.path(0, 'row_num').value).toBe(1);
222
- });
223
- it(`works inside nest - ${databaseName}`, async () => {
224
- const result = await expressionModel
225
- .loadQuery(`query: state_facts { join_one: airports on airports.state = state } -> {
226
- group_by: state
227
- nest: q is {
228
- group_by: airports.county
229
- calculate: row_num is row_number()
230
- }
231
- }`)
232
- .run();
233
- expect(result.data.path(0, 'q', 0, 'row_num').value).toBe(1);
234
- expect(result.data.path(0, 'q', 1, 'row_num').value).toBe(2);
235
- expect(result.data.path(1, 'q', 0, 'row_num').value).toBe(1);
236
- expect(result.data.path(1, 'q', 1, 'row_num').value).toBe(2);
237
- });
238
- test(`works outside nest, but with a nest nearby - ${databaseName}`, async () => {
239
- const result = await expressionModel
240
- .loadQuery(`query: state_facts -> {
241
- group_by: state
242
- calculate: row_num is row_number()
243
- nest: nested is {
244
- group_by: state
245
- }
246
- }`)
247
- .run();
248
- expect(result.data.path(0, 'row_num').value).toBe(1);
249
- expect(result.data.path(1, 'row_num').value).toBe(2);
250
- });
251
- });
252
- describe('rank', () => {
253
- it(`works ordered by dimension - ${databaseName}`, async () => {
254
- const result = await expressionModel
255
- .loadQuery(`query: state_facts -> {
256
- group_by:
257
- state,
258
- births_ballpark is ceil(births / 1000000) * 1000000
259
- order_by: births_ballpark desc
260
- calculate: births_ballpark_rank is rank()
261
- limit: 20
262
- }`)
263
- .run({ rowLimit: 20 });
264
- expect(result.data.path(0, 'births_ballpark_rank').value).toBe(1);
265
- expect(result.data.path(1, 'births_ballpark_rank').value).toBe(2);
266
- expect(result.data.path(8, 'births_ballpark_rank').value).toBe(9);
267
- expect(result.data.path(9, 'births_ballpark_rank').value).toBe(9);
268
- expect(result.data.path(10, 'births_ballpark_rank').value).toBe(9);
269
- expect(result.data.path(11, 'births_ballpark_rank').value).toBe(12);
270
- });
271
- it(`works ordered by aggregate - ${databaseName}`, async () => {
272
- const result = await expressionModel
273
- .loadQuery(`query: state_facts -> {
274
- group_by: first_letter is substr(state, 1, 1)
275
- aggregate: states_with_first_letter_ish is round(count() / 2) * 2
276
- calculate: r is rank()
277
- }`)
278
- .run();
279
- expect(result.data.path(0, 'r').value).toBe(1);
280
- expect(result.data.path(1, 'r').value).toBe(1);
281
- expect(result.data.path(2, 'r').value).toBe(3);
282
- expect(result.data.path(3, 'r').value).toBe(3);
283
- });
284
- });
285
- describe('lag', () => {
286
- it(`works with one param - ${databaseName}`, async () => {
287
- const result = await expressionModel
288
- .loadQuery(`query: state_facts -> {
289
- group_by: state
290
- calculate: prev_state is lag(state)
291
- }`)
292
- .run();
293
- expect(result.data.path(0, 'state').value).toBe('AK');
294
- expect(result.data.path(0, 'prev_state').value).toBe(null);
295
- expect(result.data.path(1, 'prev_state').value).toBe('AK');
296
- expect(result.data.path(1, 'state').value).toBe('AL');
297
- expect(result.data.path(2, 'prev_state').value).toBe('AL');
298
- });
299
- it(`works with expression field - ${databaseName}`, async () => {
300
- const result = await expressionModel
301
- .loadQuery(`query: state_facts -> {
302
- group_by: lower_state is lower(state)
303
- calculate: prev_state is lag(lower_state)
304
- }`)
305
- .run();
306
- expect(result.data.path(0, 'lower_state').value).toBe('ak');
307
- expect(result.data.path(0, 'prev_state').value).toBe(null);
308
- expect(result.data.path(1, 'prev_state').value).toBe('ak');
309
- expect(result.data.path(1, 'lower_state').value).toBe('al');
310
- expect(result.data.path(2, 'prev_state').value).toBe('al');
311
- });
312
- it(`works with expression - ${databaseName}`, async () => {
313
- const result = await expressionModel
314
- .loadQuery(`query: state_facts -> {
315
- group_by: state
316
- calculate: prev_state is lag(lower(state))
317
- }`)
318
- .run();
319
- expect(result.data.path(0, 'state').value).toBe('AK');
320
- expect(result.data.path(0, 'prev_state').value).toBe(null);
321
- expect(result.data.path(1, 'prev_state').value).toBe('ak');
322
- expect(result.data.path(1, 'state').value).toBe('AL');
323
- expect(result.data.path(2, 'prev_state').value).toBe('al');
324
- });
325
- it(`works with field, ordering by expression field - ${databaseName}`, async () => {
326
- const result = await expressionModel
327
- .loadQuery(`query: state_facts -> {
328
- group_by: lower_state is lower(state)
329
- aggregate: c is count()
330
- order_by: lower_state
331
- calculate: prev_count is lag(c)
332
- }`)
333
- .run();
334
- expect(result.data.path(0, 'lower_state').value).toBe('ak');
335
- expect(result.data.path(0, 'prev_count').value).toBe(null);
336
- expect(result.data.path(1, 'prev_count').value).toBe(1);
337
- expect(result.data.path(1, 'lower_state').value).toBe('al');
338
- expect(result.data.path(2, 'prev_count').value).toBe(1);
339
- });
340
- it(`works with offset - ${databaseName}`, async () => {
341
- const result = await expressionModel
342
- .loadQuery(`query: state_facts -> {
343
- group_by: state
344
- calculate: prev_prev_state is lag(state, 2)
345
- }`)
346
- .run();
347
- expect(result.data.path(0, 'state').value).toBe('AK');
348
- expect(result.data.path(0, 'prev_prev_state').value).toBe(null);
349
- expect(result.data.path(1, 'prev_prev_state').value).toBe(null);
350
- expect(result.data.path(2, 'prev_prev_state').value).toBe('AK');
351
- expect(result.data.path(1, 'state').value).toBe('AL');
352
- expect(result.data.path(3, 'prev_prev_state').value).toBe('AL');
353
- });
354
- it(`works with default value - ${databaseName}`, async () => {
355
- const result = await expressionModel
356
- .loadQuery(`query: state_facts -> {
357
- group_by: state
358
- calculate: prev_state is lag(state, 1, 'NONE')
359
- }`)
360
- .run();
361
- expect(result.data.path(0, 'prev_state').value).toBe('NONE');
362
- });
363
- it(`works with now as the default value - ${databaseName}`, async () => {
364
- const result = await expressionModel
365
- .loadQuery(`
366
- query: state_facts -> {
367
- group_by: state
368
- calculate: lag_val is lag(@2011-11-11 11:11:11, 1, now).year = now.year
369
- }`)
370
- .run();
371
- expect(result.data.path(0, 'lag_val').value).toBe(true);
372
- expect(result.data.path(1, 'lag_val').value).toBe(false);
373
- });
374
- });
375
- describe('output field in calculate', () => {
376
- it(`dotted aggregates work with an output field - ${databaseName}`, async () => {
377
- const result = await expressionModel
378
- .loadQuery(`query: aircraft -> {
379
- group_by: aircraft_models.seats
380
- aggregate: s is aircraft_models.seats.sum()
381
- calculate: a is lag(seats.sum())
382
- }`)
383
- .run();
384
- expect(result.data.path(1, 'a').value).toBe(result.data.path(0, 's').value);
385
- });
386
- });
387
- describe('first_value', () => {
388
- test(`works in nest - ${databaseName}`, async () => {
389
- const result = await expressionModel
390
- .loadQuery(`
391
- query: aircraft -> {
392
- group_by: state
393
- where: state != null
394
- nest: by_county is {
395
- limit: 2
396
- group_by: county
397
- aggregate: aircraft_count
398
- calculate: first_count is first_value(count())
399
- }
400
- }`)
401
- .run();
402
- expect(result.data.path(0, 'by_county', 1, 'first_count').value).toBe(result.data.path(0, 'by_county', 0, 'aircraft_count').value);
403
- expect(result.data.path(1, 'by_county', 1, 'first_count').value).toBe(result.data.path(1, 'by_county', 0, 'aircraft_count').value);
404
- });
405
- it(`works outside nest - ${databaseName}`, async () => {
406
- const result = await expressionModel
407
- .loadQuery(`
408
- query: state_facts -> {
409
- group_by: state, births
410
- order_by: births desc
411
- calculate: most_births is first_value(births)
412
- }`)
413
- .run();
414
- const firstBirths = result.data.path(0, 'births').value;
415
- expect(result.data.path(0, 'most_births').value).toBe(firstBirths);
416
- expect(result.data.path(1, 'most_births').value).toBe(firstBirths);
417
- });
418
- it(`works with an aggregate which is not in the query - ${databaseName}`, async () => {
419
- const result = await expressionModel
420
- .loadQuery(`
421
- query: airports { measure: airport_count is count() } -> {
422
- group_by: state
423
- where: state != null
424
- calculate: prev_airport_count is lag(airport_count)
425
- }`)
426
- .run();
427
- expect(result.data.path(0, 'prev_airport_count').value).toBe(null);
428
- expect(result.data.path(1, 'prev_airport_count').value).toBe(608);
429
- expect(result.data.path(2, 'prev_airport_count').value).toBe(260);
430
- });
431
- it(`works with a localized aggregate - ${databaseName}`, async () => {
432
- const result = await expressionModel
433
- .loadQuery(`
434
- query: aircraft -> {
435
- group_by: aircraft_models.seats,
436
- calculate: prev_sum_of_seats is lag(aircraft_models.seats.sum())
437
- }`)
438
- .run();
439
- expect(result.data.path(0, 'prev_sum_of_seats').value).toBe(null);
440
- expect(result.data.path(1, 'prev_sum_of_seats').value).toBe(0);
441
- expect(result.data.path(2, 'prev_sum_of_seats').value).toBe(230);
442
- });
443
- });
444
- describe('trunc', () => {
445
- it(`works - ${databaseName}`, async () => {
446
- await funcTestMultiple(['trunc(1.9)', 1],
447
- // TODO Remove when we upgrade to DuckDB 0.8.X -- DuckDB has some bugs with rounding
448
- // that are fixed in 0.8.
449
- ...(databaseName === 'duckdb_wasm'
450
- ? []
451
- : [['trunc(-1.9)', -1]]), ['trunc(12.29, 1)', 12.2], ['trunc(19.2, -1)', 10], ['trunc(null)', null], ['trunc(1, null)', null]);
452
- });
453
- });
454
- describe('log', () => {
455
- it(`works - ${databaseName}`, async () => {
456
- await funcTestMultiple(['log(10, 10)', 1], ['log(100, 10)', 2], ['log(32, 2)', 5], ['log(null, 2)', null], ['log(10, null)', null]);
457
- });
458
- });
459
- describe('ln', () => {
460
- it(`works - ${databaseName}`, async () => {
461
- await funcTestMultiple(['ln(exp(1))', 1], ['ln(exp(2))', 2], ['ln(null)', null]);
462
- });
463
- });
464
- describe('exp', () => {
465
- it(`works - ${databaseName}`, async () => {
466
- await funcTestMultiple(['exp(0)', 1], ['ln(exp(1))', 1], ['exp(null)', null]);
467
- });
468
- });
469
- // TODO trig functions could have more exhaustive tests -- these are mostly just here to
470
- // ensure they exist
471
- describe('cos', () => {
472
- it(`works - ${databaseName}`, async () => {
473
- await funcTestMultiple(['cos(0)', 1], ['cos(null)', null]);
474
- });
475
- });
476
- describe('acos', () => {
477
- it(`works - ${databaseName}`, async () => {
478
- await funcTestMultiple(['acos(1)', 0], ['acos(null)', null]);
479
- });
480
- });
481
- describe('sin', () => {
482
- it(`works - ${databaseName}`, async () => {
483
- await funcTestMultiple(['sin(0)', 0], ['sin(null)', null]);
484
- });
485
- });
486
- describe('asin', () => {
487
- it(`works - ${databaseName}`, async () => {
488
- await funcTestMultiple(['asin(0)', 0], ['asin(null)', null]);
489
- });
490
- });
491
- describe('tan', () => {
492
- it(`works - ${databaseName}`, async () => {
493
- await funcTestMultiple(['tan(0)', 0], ['tan(null)', null]);
494
- });
495
- });
496
- describe('atan', () => {
497
- it(`works - ${databaseName}`, async () => {
498
- await funcTestMultiple(['atan(0)', 0], ['atan(null)', null]);
499
- });
500
- });
501
- describe('atan2', () => {
502
- it(`works - ${databaseName}`, async () => {
503
- await funcTestMultiple(['atan2(0, 1)', 0], ['atan2(null, 1)', null], ['atan2(1, null)', null]);
504
- });
505
- });
506
- describe('sqrt', () => {
507
- it(`works - ${databaseName}`, async () => {
508
- await funcTestMultiple(['sqrt(9)', 3], ['sqrt(6.25)', 2.5], ['sqrt(null)', null]);
509
- });
510
- });
511
- describe('pow', () => {
512
- it(`works - ${databaseName}`, async () => {
513
- await funcTestMultiple(['pow(2, 3)', 8], ['pow(null, 3)', null], ['pow(2, null)', null]);
514
- });
515
- });
516
- describe('abs', () => {
517
- it(`works - ${databaseName}`, async () => {
518
- await funcTestMultiple(['abs(-3)', 3], ['abs(3)', 3], ['abs(null)', null]);
519
- });
520
- });
521
- describe('sign', () => {
522
- it(`works - ${databaseName}`, async () => {
523
- await funcTestMultiple(['sign(100)', 1], ['sign(-2)', -1], ['sign(0)', 0], ['sign(null)', null]);
524
- });
525
- });
526
- describe('is_inf', () => {
527
- it(`works - ${databaseName}`, async () => {
528
- await funcTestMultiple(["is_inf('+inf'::number)", true], ['is_inf(100)', false], ['is_inf(null)', false]);
529
- });
530
- });
531
- describe('is_nan', () => {
532
- it(`works - ${databaseName}`, async () => {
533
- await funcTestMultiple(["is_nan('NaN'::number)", true], ['is_nan(100)', false], ['is_nan(null)', false]);
534
- });
535
- });
536
- describe('greatest', () => {
537
- it(`works - ${databaseName}`, async () => {
538
- await funcTestMultiple(['greatest(1, 10, -100)', 10], ['greatest(@2003, @2004, @1994) = @2004', true], [
539
- 'greatest(@2023-05-26 11:58:00, @2023-05-26 11:59:00) = @2023-05-26 11:59:00',
540
- true,
541
- ], ["greatest('a', 'b')", 'b'], ['greatest(1, null, 0)', null], ['greatest(null, null)', null]);
542
- });
543
- });
544
- describe('least', () => {
545
- it(`works - ${databaseName}`, async () => {
546
- await funcTestMultiple(['least(1, 10, -100)', -100], ['least(@2003, @2004, @1994) = @1994', true], [
547
- 'least(@2023-05-26 11:58:00, @2023-05-26 11:59:00) = @2023-05-26 11:58:00',
548
- true,
549
- ], ["least('a', 'b')", 'a'], ['least(1, null, 0)', null], ['least(null, null)', null]);
550
- });
551
- });
552
- describe('div', () => {
553
- it(`works - ${databaseName}`, async () => {
554
- await funcTestMultiple(['div(3, 2)', 1], ['div(null, 2)', null], ['div(2, null)', null]);
555
- });
556
- });
557
- describe('strpos', () => {
558
- it(`works - ${databaseName}`, async () => {
559
- await funcTestMultiple(["strpos('123456789', '3')", 3], ["strpos('123456789', '0')", 0], ["strpos(null, '0')", null], ["strpos('123456789', null)", null]);
560
- });
561
- });
562
- describe('starts_with', () => {
563
- it(`works - ${databaseName}`, async () => {
564
- await funcTestMultiple(["starts_with('hello world', 'hello')", true], ["starts_with('hello world', 'world')", false], ["starts_with(null, 'world')", false], ["starts_with('hello world', null)", false]);
565
- });
566
- });
567
- describe('ends_with', () => {
568
- it(`works - ${databaseName}`, async () => {
569
- await funcTestMultiple(["ends_with('hello world', 'world')", true], ["ends_with('hello world', 'hello')", false], ["ends_with(null, 'world')", false], ["ends_with('hello world', null)", false]);
570
- });
571
- });
572
- describe('trim', () => {
573
- it(`works - ${databaseName}`, async () => {
574
- await funcTestMultiple(["trim(' keep this ')", 'keep this'], ["trim('_ _keep_this_ _', '_ ')", 'keep_this'], ["trim(' keep everything ', '')", ' keep everything '], ["trim('null example', null)", null], ["trim(null, 'a')", null], ['trim(null)', null]);
575
- });
576
- });
577
- describe('ltrim', () => {
578
- it(`works - ${databaseName}`, async () => {
579
- await funcTestMultiple(["ltrim(' keep this -> ')", 'keep this -> '], ["ltrim('_ _keep_this -> _ _', '_ ')", 'keep_this -> _ _'], ["ltrim(' keep everything ', '')", ' keep everything '], ["ltrim('null example', null)", null], ["ltrim(null, 'a')", null], ['ltrim(null)', null]);
580
- });
581
- });
582
- describe('rtrim', () => {
583
- it(`works - ${databaseName}`, async () => {
584
- await funcTestMultiple(["rtrim(' <- keep this ')", ' <- keep this'], ["rtrim('_ _ <- keep_this_ _', '_ ')", '_ _ <- keep_this'], ["rtrim(' keep everything ', '')", ' keep everything '], ["rtrim('null example', null)", null], ["rtrim(null, 'a')", null], ['rtrim(null)', null]);
585
- });
586
- });
587
- describe('rand', () => {
588
- it(`is usually not the same value - ${databaseName}`, async () => {
589
- // There are around a billion values that rand() can be, so if this
590
- // test fails, most likely something is broken. Otherwise, you're the lucky
591
- // one in a billion!
592
- await funcTest('rand() = rand()', false);
593
- });
594
- });
595
- describe('pi', () => {
596
- it(`is pi - ${databaseName}`, async () => {
597
- await funcTest('abs(pi() - 3.141592653589793) < 0.0000000000001', true);
598
- });
599
- });
600
- describe('byte_length', () => {
601
- it(`works - ${databaseName}`, async () => {
602
- await funcTestMultiple(["byte_length('hello')", 5], ["byte_length('©')", 2], ['byte_length(null)', null]);
603
- });
604
- });
605
- describe('ifnull', () => {
606
- it(`works - ${databaseName}`, async () => {
607
- await funcTestMultiple(["ifnull('a', 'b')", 'a'], ["ifnull(null, 'b')", 'b'], ["ifnull('a', null)", 'a'], ['ifnull(null, null)', null]);
608
- });
609
- });
610
- describe('coalesce', () => {
611
- it(`works - ${databaseName}`, async () => {
612
- await funcTestMultiple(["coalesce('a')", 'a'], ["coalesce('a', 'b')", 'a'], ["coalesce(null, 'a', 'b')", 'a'], ["coalesce(null, 'b')", 'b'], ["coalesce('a', null)", 'a'], ['coalesce(null, null)', null], ['coalesce(null)', null]);
613
- });
614
- });
615
- describe('nullif', () => {
616
- it(`works - ${databaseName}`, async () => {
617
- await funcTestMultiple(["nullif('a', 'a')", null], ["nullif('a', 'b')", 'a'], ["nullif('a', null)", 'a'], ['nullif(null, null)', null], ['nullif(null, 2)', null]);
618
- });
619
- });
620
- describe('chr', () => {
621
- it(`works - ${databaseName}`, async () => {
622
- await funcTestMultiple(['chr(65)', 'A'], ['chr(255)', 'ÿ'], ['chr(null)', null],
623
- // BigQuery's documentation says that `chr(0)` returns the empty string, but it doesn't,
624
- // it actually returns the null character. We generate code so that it does this.
625
- ['chr(0)', '']);
626
- });
627
- });
628
- describe('ascii', () => {
629
- it(`works - ${databaseName}`, async () => {
630
- await funcTestMultiple(["ascii('A')", 65], ["ascii('ABC')", 65], ["ascii('')", 0], ['ascii(null)', null]);
631
- });
632
- });
633
- describe('unicode', () => {
634
- it(`works - ${databaseName}`, async () => {
635
- await funcTestMultiple(["unicode('A')", 65], ["unicode('â')", 226], ["unicode('âBC')", 226], ["unicode('')", 0], ['unicode(null)', null]);
636
- });
637
- });
638
- describe('repeat', () => {
639
- it(`works - ${databaseName}`, async () => {
640
- await funcTestMultiple(["repeat('foo', 0)", ''], ["repeat('foo', 1)", 'foo'], ["repeat('foo', 2)", 'foofoo'], ['repeat(null, 2)', null], ["repeat('foo', null)", null]);
641
- });
642
- // TODO how does a user do this: the second argument needs to be an integer, but floor doesn't cast to "integer" type.
643
- it.skip(`works floor decimal - ${databaseName}`, async () => {
644
- await funcTest("repeat('foo', floor(2.5))", 'foofoo');
645
- });
646
- // undefined behavior when negative, undefined behavior (likely error) when non-integer
647
- });
648
- describe('reverse', () => {
649
- it(`works - ${databaseName}`, async () => {
650
- await funcTestMultiple(["reverse('foo')", 'oof'], ["reverse('')", ''], ['reverse(null)', null]);
651
- });
652
- });
653
- describe('lead', () => {
654
- it(`works with one param - ${databaseName}`, async () => {
655
- const result = await expressionModel
656
- .loadQuery(`query: state_facts -> {
657
- group_by: state
658
- calculate: next_state is lead(state)
659
- }`)
660
- .run();
661
- expect(result.data.path(0, 'state').value).toBe('AK');
662
- expect(result.data.path(0, 'next_state').value).toBe('AL');
663
- expect(result.data.path(1, 'state').value).toBe('AL');
664
- });
665
- it(`works with offset - ${databaseName}`, async () => {
666
- const result = await expressionModel
667
- .loadQuery(`query: state_facts -> {
668
- group_by: state
669
- calculate: next_next_state is lead(state, 2)
670
- }`)
671
- .run();
672
- expect(result.data.path(0, 'state').value).toBe('AK');
673
- expect(result.data.path(0, 'next_next_state').value).toBe('AR');
674
- expect(result.data.path(1, 'next_next_state').value).toBe('AZ');
675
- expect(result.data.path(1, 'state').value).toBe('AL');
676
- expect(result.data.path(2, 'state').value).toBe('AR');
677
- expect(result.data.path(3, 'state').value).toBe('AZ');
678
- });
679
- it(`works with default value - ${databaseName}`, async () => {
680
- const result = await expressionModel
681
- .loadQuery(`query: state_facts -> { project: *; limit: 10 } -> {
682
- group_by: state
683
- calculate: next_state is lead(state, 1, 'NONE')
684
- }`)
685
- .run();
686
- expect(result.data.path(9, 'next_state').value).toBe('NONE');
687
- });
688
- });
689
- describe('last_value', () => {
690
- it(`works - ${databaseName}`, async () => {
691
- const result = await expressionModel
692
- .loadQuery(`
693
- query: state_facts -> {
694
- group_by: state, births
695
- order_by: births desc
696
- calculate: least_births is last_value(births)
697
- }`)
698
- .run({ rowLimit: 100 });
699
- const numRows = result.data.toObject().length;
700
- const lastBirths = result.data.path(numRows - 1, 'births').value;
701
- expect(result.data.path(0, 'least_births').value).toBe(lastBirths);
702
- expect(result.data.path(1, 'least_births').value).toBe(lastBirths);
703
- });
704
- });
705
- describe('avg_moving', () => {
706
- it(`works - ${databaseName}`, async () => {
707
- const result = await expressionModel
708
- .loadQuery(`
709
- query: state_facts -> {
710
- group_by: state, births
711
- order_by: births desc
712
- calculate: rolling_avg is avg_moving(births, 2)
713
- }`)
714
- .run({ rowLimit: 100 });
715
- const births0 = result.data.path(0, 'births').number.value;
716
- const births1 = result.data.path(1, 'births').number.value;
717
- const births2 = result.data.path(2, 'births').number.value;
718
- const births3 = result.data.path(3, 'births').number.value;
719
- expect(result.data.path(0, 'rolling_avg').number.value).toBe(births0);
720
- expect(Math.floor(result.data.path(1, 'rolling_avg').number.value)).toBe(Math.floor((births0 + births1) / 2));
721
- expect(Math.floor(result.data.path(2, 'rolling_avg').number.value)).toBe(Math.floor((births0 + births1 + births2) / 3));
722
- expect(Math.floor(result.data.path(3, 'rolling_avg').number.value)).toBe(Math.floor((births1 + births2 + births3) / 3));
723
- });
724
- it(`works forward - ${databaseName}`, async () => {
725
- const result = await expressionModel
726
- .loadQuery(`
727
- query: state_facts -> { project: *; limit: 3 } -> {
728
- group_by: state, births
729
- order_by: births desc
730
- calculate: rolling_avg is avg_moving(births, 0, 2)
731
- }`)
732
- .run({ rowLimit: 100 });
733
- const births0 = result.data.path(0, 'births').number.value;
734
- const births1 = result.data.path(1, 'births').number.value;
735
- const births2 = result.data.path(2, 'births').number.value;
736
- expect(Math.floor(result.data.path(0, 'rolling_avg').number.value)).toBe(Math.floor((births0 + births1 + births2) / 3));
737
- expect(Math.floor(result.data.path(1, 'rolling_avg').number.value)).toBe(Math.floor((births1 + births2) / 2));
738
- expect(result.data.path(2, 'rolling_avg').number.value).toBe(births2);
739
- });
740
- });
741
- describe('min, max, sum / window, cumulative', () => {
742
- it(`works - ${databaseName}`, async () => {
743
- const result = await expressionModel
744
- .loadQuery(`
745
- query: state_facts -> { project: *; limit: 5 } -> {
746
- group_by: state, births
747
- order_by: births asc
748
- calculate: min_c is min_cumulative(births)
749
- calculate: max_c is max_cumulative(births)
750
- calculate: sum_c is sum_cumulative(births)
751
- calculate: min_w is min_window(births)
752
- calculate: max_w is max_window(births)
753
- calculate: sum_w is sum_window(births)
754
- }`)
755
- .run({ rowLimit: 100 });
756
- const births0 = result.data.path(0, 'births').number.value;
757
- const births1 = result.data.path(1, 'births').number.value;
758
- const births2 = result.data.path(2, 'births').number.value;
759
- const births3 = result.data.path(3, 'births').number.value;
760
- const births4 = result.data.path(4, 'births').number.value;
761
- const births = [births0, births1, births2, births3, births4];
762
- for (let r = 0; r < 5; r++) {
763
- expect(result.data.path(r, 'min_c').number.value).toBe(births0);
764
- expect(result.data.path(r, 'max_c').number.value).toBe(births[r]);
765
- expect(result.data.path(r, 'sum_c').number.value).toBe(births.slice(0, r + 1).reduce((a, b) => a + b));
766
- expect(result.data.path(r, 'min_w').number.value).toBe(births0);
767
- expect(result.data.path(r, 'max_w').number.value).toBe(births4);
768
- expect(result.data.path(r, 'sum_w').number.value).toBe(births.reduce((a, b) => a + b));
769
- }
770
- });
771
- });
772
- });
773
- afterAll(async () => {
774
- await runtimes.closeAll();
775
- });
776
- };
777
- exports.functionsSharedTests = functionsSharedTests;
28
+ const functions_1 = require("../shared/functions");
778
29
  const runtimes = new runtimes_1.RuntimeList((0, util_1.databasesFromEnvironmentOr)(runtimes_1.allDatabases));
779
30
  /*
780
31
  * This test file reuses common tests definitions.
781
32
  * For actual test development please go to: test/src/databases/shared/functions.spec.ts
782
33
  */
783
- (0, exports.functionsSharedTests)(runtimes);
34
+ (0, functions_1.functionsSharedTests)(runtimes);
784
35
  //# sourceMappingURL=functions.spec.js.map