@malloydata/malloy-tests 0.0.138-dev240404193102 → 0.0.138-dev240404233606

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 (133) hide show
  1. package/jest.setup.ts +28 -0
  2. package/package.json +8 -8
  3. package/src/databases/all/db_index.spec.ts +4 -6
  4. package/src/databases/all/expr.spec.ts +27 -36
  5. package/src/databases/all/join.spec.ts +4 -4
  6. package/src/databases/all/nomodel.spec.ts +79 -99
  7. package/src/databases/all/orderby.spec.ts +7 -7
  8. package/src/databases/all/time.spec.ts +22 -30
  9. package/src/render/render.spec.ts +52 -55
  10. package/src/util/index.ts +0 -11
  11. package/tsconfig.json +2 -2
  12. package/types/jest.d.ts +8 -0
  13. package/dist/bin/ping_db.d.ts +0 -1
  14. package/dist/bin/ping_db.js +0 -44
  15. package/dist/bin/ping_db.js.map +0 -1
  16. package/dist/src/api.spec.d.ts +0 -1
  17. package/dist/src/api.spec.js +0 -113
  18. package/dist/src/api.spec.js.map +0 -1
  19. package/dist/src/databases/all/db_index.spec.d.ts +0 -1
  20. package/dist/src/databases/all/db_index.spec.js +0 -126
  21. package/dist/src/databases/all/db_index.spec.js.map +0 -1
  22. package/dist/src/databases/all/expr.spec.d.ts +0 -1
  23. package/dist/src/databases/all/expr.spec.js +0 -717
  24. package/dist/src/databases/all/expr.spec.js.map +0 -1
  25. package/dist/src/databases/all/functions.spec.d.ts +0 -1
  26. package/dist/src/databases/all/functions.spec.js +0 -1180
  27. package/dist/src/databases/all/functions.spec.js.map +0 -1
  28. package/dist/src/databases/all/join.spec.d.ts +0 -1
  29. package/dist/src/databases/all/join.spec.js +0 -255
  30. package/dist/src/databases/all/join.spec.js.map +0 -1
  31. package/dist/src/databases/all/lenses.spec.d.ts +0 -1
  32. package/dist/src/databases/all/lenses.spec.js +0 -374
  33. package/dist/src/databases/all/lenses.spec.js.map +0 -1
  34. package/dist/src/databases/all/nomodel.spec.d.ts +0 -1
  35. package/dist/src/databases/all/nomodel.spec.js +0 -1071
  36. package/dist/src/databases/all/nomodel.spec.js.map +0 -1
  37. package/dist/src/databases/all/orderby.spec.d.ts +0 -1
  38. package/dist/src/databases/all/orderby.spec.js +0 -170
  39. package/dist/src/databases/all/orderby.spec.js.map +0 -1
  40. package/dist/src/databases/all/problems.spec.d.ts +0 -1
  41. package/dist/src/databases/all/problems.spec.js +0 -106
  42. package/dist/src/databases/all/problems.spec.js.map +0 -1
  43. package/dist/src/databases/all/sql_expressions.spec.d.ts +0 -1
  44. package/dist/src/databases/all/sql_expressions.spec.js +0 -73
  45. package/dist/src/databases/all/sql_expressions.spec.js.map +0 -1
  46. package/dist/src/databases/all/time.spec.d.ts +0 -1
  47. package/dist/src/databases/all/time.spec.js +0 -602
  48. package/dist/src/databases/all/time.spec.js.map +0 -1
  49. package/dist/src/databases/bigquery/double_truncation.spec.d.ts +0 -1
  50. package/dist/src/databases/bigquery/double_truncation.spec.js +0 -50
  51. package/dist/src/databases/bigquery/double_truncation.spec.js.map +0 -1
  52. package/dist/src/databases/bigquery/handexpr.spec.d.ts +0 -1
  53. package/dist/src/databases/bigquery/handexpr.spec.js +0 -723
  54. package/dist/src/databases/bigquery/handexpr.spec.js.map +0 -1
  55. package/dist/src/databases/bigquery/injestion_time_partitioning.spec.d.ts +0 -1
  56. package/dist/src/databases/bigquery/injestion_time_partitioning.spec.js +0 -235
  57. package/dist/src/databases/bigquery/injestion_time_partitioning.spec.js.map +0 -1
  58. package/dist/src/databases/bigquery/joined_filters.spec.d.ts +0 -1
  59. package/dist/src/databases/bigquery/joined_filters.spec.js +0 -72
  60. package/dist/src/databases/bigquery/joined_filters.spec.js.map +0 -1
  61. package/dist/src/databases/bigquery/json.spec.d.ts +0 -1
  62. package/dist/src/databases/bigquery/json.spec.js +0 -66
  63. package/dist/src/databases/bigquery/json.spec.js.map +0 -1
  64. package/dist/src/databases/bigquery/malloy_query.spec.d.ts +0 -1
  65. package/dist/src/databases/bigquery/malloy_query.spec.js +0 -840
  66. package/dist/src/databases/bigquery/malloy_query.spec.js.map +0 -1
  67. package/dist/src/databases/bigquery/performance.skipped.spec.d.ts +0 -1
  68. package/dist/src/databases/bigquery/performance.skipped.spec.js +0 -70
  69. package/dist/src/databases/bigquery/performance.skipped.spec.js.map +0 -1
  70. package/dist/src/databases/bigquery/time.spec.d.ts +0 -1
  71. package/dist/src/databases/bigquery/time.spec.js +0 -52
  72. package/dist/src/databases/bigquery/time.spec.js.map +0 -1
  73. package/dist/src/databases/bigquery/wildcard_table_names.spec.d.ts +0 -1
  74. package/dist/src/databases/bigquery/wildcard_table_names.spec.js +0 -212
  75. package/dist/src/databases/bigquery/wildcard_table_names.spec.js.map +0 -1
  76. package/dist/src/databases/bigquery-duckdb/nested_source_table.spec.d.ts +0 -1
  77. package/dist/src/databases/bigquery-duckdb/nested_source_table.spec.js +0 -213
  78. package/dist/src/databases/bigquery-duckdb/nested_source_table.spec.js.map +0 -1
  79. package/dist/src/databases/duckdb/duckdb.spec.d.ts +0 -1
  80. package/dist/src/databases/duckdb/duckdb.spec.js +0 -124
  81. package/dist/src/databases/duckdb/duckdb.spec.js.map +0 -1
  82. package/dist/src/databases/duckdb/streaming.spec.d.ts +0 -1
  83. package/dist/src/databases/duckdb/streaming.spec.js +0 -142
  84. package/dist/src/databases/duckdb/streaming.spec.js.map +0 -1
  85. package/dist/src/databases/multi-connection/multi_connection.spec.d.ts +0 -1
  86. package/dist/src/databases/multi-connection/multi_connection.spec.js +0 -120
  87. package/dist/src/databases/multi-connection/multi_connection.spec.js.map +0 -1
  88. package/dist/src/databases/postgres/postgres.spec.d.ts +0 -1
  89. package/dist/src/databases/postgres/postgres.spec.js +0 -140
  90. package/dist/src/databases/postgres/postgres.spec.js.map +0 -1
  91. package/dist/src/databases/shared/test_list.d.ts +0 -3
  92. package/dist/src/databases/shared/test_list.js +0 -5
  93. package/dist/src/databases/shared/test_list.js.map +0 -1
  94. package/dist/src/databases/streaming/streaming.spec.d.ts +0 -1
  95. package/dist/src/databases/streaming/streaming.spec.js +0 -93
  96. package/dist/src/databases/streaming/streaming.spec.js.map +0 -1
  97. package/dist/src/dependencies.spec.d.ts +0 -1
  98. package/dist/src/dependencies.spec.js +0 -63
  99. package/dist/src/dependencies.spec.js.map +0 -1
  100. package/dist/src/index.d.ts +0 -4
  101. package/dist/src/index.js +0 -49
  102. package/dist/src/index.js.map +0 -1
  103. package/dist/src/jestMatcher.spec.d.ts +0 -1
  104. package/dist/src/jestMatcher.spec.js +0 -81
  105. package/dist/src/jestMatcher.spec.js.map +0 -1
  106. package/dist/src/model/sql_source.spec.d.ts +0 -1
  107. package/dist/src/model/sql_source.spec.js +0 -47
  108. package/dist/src/model/sql_source.spec.js.map +0 -1
  109. package/dist/src/models/faa_model.d.ts +0 -5
  110. package/dist/src/models/faa_model.js +0 -997
  111. package/dist/src/models/faa_model.js.map +0 -1
  112. package/dist/src/models/medicare_model.d.ts +0 -4
  113. package/dist/src/models/medicare_model.js +0 -259
  114. package/dist/src/models/medicare_model.js.map +0 -1
  115. package/dist/src/render/drill.spec.d.ts +0 -1
  116. package/dist/src/render/drill.spec.js +0 -107
  117. package/dist/src/render/drill.spec.js.map +0 -1
  118. package/dist/src/render/render.spec.d.ts +0 -1
  119. package/dist/src/render/render.spec.js +0 -548
  120. package/dist/src/render/render.spec.js.map +0 -1
  121. package/dist/src/runtimes.d.ts +0 -35
  122. package/dist/src/runtimes.js +0 -181
  123. package/dist/src/runtimes.js.map +0 -1
  124. package/dist/src/tags.spec.d.ts +0 -8
  125. package/dist/src/tags.spec.js +0 -490
  126. package/dist/src/tags.spec.js.map +0 -1
  127. package/dist/src/util/db-jest-matchers.d.ts +0 -30
  128. package/dist/src/util/db-jest-matchers.js +0 -157
  129. package/dist/src/util/db-jest-matchers.js.map +0 -1
  130. package/dist/src/util/index.d.ts +0 -15
  131. package/dist/src/util/index.js +0 -182
  132. package/dist/src/util/index.js.map +0 -1
  133. package/jest.setup.js +0 -8
@@ -1,717 +0,0 @@
1
- "use strict";
2
- /* eslint-disable no-console */
3
- /*
4
- * Copyright 2023 Google LLC
5
- *
6
- * Permission is hereby granted, free of charge, to any person obtaining
7
- * a copy of this software and associated documentation files
8
- * (the "Software"), to deal in the Software without restriction,
9
- * including without limitation the rights to use, copy, modify, merge,
10
- * publish, distribute, sublicense, and/or sell copies of the Software,
11
- * and to permit persons to whom the Software is furnished to do so,
12
- * subject to the following conditions:
13
- *
14
- * The above copyright notice and this permission notice shall be
15
- * included in all copies or substantial portions of the Software.
16
- *
17
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
- */
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- const runtimes_1 = require("../../runtimes");
27
- require("../../util/db-jest-matchers");
28
- const util_1 = require("../../util");
29
- const assert_1 = require("assert");
30
- const runtimes = new runtimes_1.RuntimeList((0, util_1.databasesFromEnvironmentOr)(runtimes_1.allDatabases));
31
- function modelText(databaseName) {
32
- return `
33
- source: aircraft_models is ${databaseName}.table('malloytest.aircraft_models') extend {
34
- primary_key: aircraft_model_code
35
- measure:
36
- aircraft_model_count is count(),
37
- total_seats is sum(seats),
38
- boeing_seats is sum(seats) { where: manufacturer ? 'BOEING'},
39
- percent_boeing is boeing_seats / total_seats * 100,
40
- percent_boeing_floor is floor(boeing_seats / total_seats * 100),
41
- dimension: seats_bucketed is floor(seats/20)*20.0
42
- }
43
-
44
- source: aircraft is ${databaseName}.table('malloytest.aircraft') extend {
45
- primary_key: tail_num
46
- join_one: aircraft_models with aircraft_model_code
47
- measure: aircraft_count is count()
48
- view: by_manufacturer is {
49
- top: 5
50
- group_by: aircraft_models.manufacturer
51
- aggregate: aircraft_count
52
- }
53
- }
54
- `;
55
- }
56
- describe.each(runtimes.runtimeList)('%s', (databaseName, runtime) => {
57
- const expressionModel = runtime.loadModel(modelText(databaseName));
58
- // basic calculations for sum, filtered sum, without a join.
59
- const q = runtime.getQuoter();
60
- it('basic calculations', async () => {
61
- await expect(`
62
- run: aircraft_models->{
63
- aggregate:
64
- total_seats,
65
- total_seats2 is sum(seats),
66
- boeing_seats,
67
- boeing_seats2 is sum(seats) { where: manufacturer ? 'BOEING'},
68
- boeing_seats3 is total_seats { where: manufacturer ? 'BOEING'},
69
- percent_boeing_floor,
70
- }
71
- `).malloyResultMatches(expressionModel, {
72
- total_seats: 452415,
73
- total_seats2: 452415,
74
- boeing_seats: 252771,
75
- boeing_seats2: 252771,
76
- boeing_seats3: 252771,
77
- percent_boeing_floor: 55,
78
- });
79
- });
80
- // Floor was broken (wouldn't compile because the expression returned isn't an aggregate.)
81
- it('Floor() -or any function bustage with aggregates', async () => {
82
- await expect(`
83
- run: aircraft_models->{
84
- aggregate:
85
- percent_boeing_floor
86
- percent_boeing_floor2 is floor(boeing_seats / total_seats * 100)
87
- }
88
- `).malloyResultMatches(expressionModel, {
89
- percent_boeing_floor: 55,
90
- percent_boeing_floor2: 55,
91
- });
92
- });
93
- // Model based version of sums.
94
- it('model: expression fixups.', async () => {
95
- await expect(`
96
- run: aircraft->{
97
- aggregate:
98
- aircraft_models.total_seats
99
- aircraft_models.boeing_seats
100
- }
101
- `).malloyResultMatches(expressionModel, {
102
- total_seats: 18294,
103
- boeing_seats: 6244,
104
- });
105
- });
106
- // simple turtle expressions
107
- it('simple turtle', async () => {
108
- await expect(`
109
- run: ${databaseName}.table('malloytest.state_facts') -> {
110
- group_by: popular_name
111
- aggregate: airport_count.sum()
112
- nest: by_state is {
113
- group_by: state
114
- aggregate: airport_count.sum()
115
- limit: 2
116
- }
117
- limit: 3
118
- }
119
- `).malloyResultMatches(expressionModel, {
120
- 'by_state.state': 'TX',
121
- 'by_state.airport_count': 1845,
122
- });
123
- });
124
- it('double turtle', async () => {
125
- await expect(`
126
- run: ${databaseName}.table('malloytest.state_facts') -> {
127
- aggregate: airport_count.sum()
128
- nest: o is {
129
- group_by: popular_name
130
- aggregate: airport_count.sum()
131
- nest: by_state is {
132
- group_by: state
133
- aggregate: airport_count.sum()
134
- limit: 2
135
- }
136
- limit: 3
137
- nest: inline is {
138
- aggregate: inline_sum is airport_count.sum()
139
- }
140
- }
141
- }
142
- `).malloyResultMatches(expressionModel, {
143
- 'o.by_state.state': 'TX',
144
- 'o.by_state.airport_count': 1845,
145
- //'o.inline.inline_sum': 19701, // this should work.. @mtoy
146
- 'airport_count': 19701,
147
- });
148
- });
149
- it('double turtle - pipeline', async () => {
150
- await expect(`
151
- run: ${databaseName}.table('malloytest.state_facts') -> {
152
- aggregate: airport_count.sum()
153
- nest: o is {
154
- group_by: popular_name
155
- aggregate: airport_count.sum()
156
- nest: by_state is {
157
- group_by: state
158
- aggregate: airport_count.sum()
159
- limit: 2
160
- }
161
- limit: 3
162
- }
163
- } -> {
164
- aggregate: o.by_state.airport_count.sum()
165
- }
166
- `).malloyResultMatches(expressionModel, {
167
- 'airport_count': 5023,
168
- });
169
- });
170
- // turtle expressions
171
- it('model: turtle', async () => {
172
- await expect('run: aircraft->by_manufacturer').malloyResultMatches(expressionModel, { manufacturer: 'CESSNA' });
173
- });
174
- // filtered turtle expressions
175
- test('model: filtered turtle', (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
176
- await expect(`
177
- run: aircraft->{
178
- nest: b is by_manufacturer + { where: aircraft_models.manufacturer ?~'B%'}
179
- }
180
- `).malloyResultMatches(expressionModel, { 'b.manufacturer': 'BEECH' });
181
- }));
182
- // having.
183
- it('model: simple having', async () => {
184
- await expect(`
185
- run: aircraft->{
186
- having: aircraft_count >90
187
- group_by: state
188
- aggregate: aircraft_count
189
- order_by: 2
190
- limit: 2
191
- }
192
- `).malloyResultMatches(expressionModel, { aircraft_count: 91 });
193
- });
194
- test('model: having in a nest', (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
195
- await expect(`
196
- run: aircraft->{
197
- top: 10
198
- order_by: 1
199
- where: region != NULL
200
- group_by: region
201
- nest: by_state is {
202
- top: 10
203
- order_by: 1 desc
204
- having: aircraft_count > 50
205
- group_by: state
206
- aggregate: aircraft_count
207
- }
208
- }
209
- `).malloyResultMatches(expressionModel, { 'by_state.state': 'VA' });
210
- }));
211
- test('model: turtle having on main', (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
212
- await expect(`
213
- run: aircraft->{
214
- order_by: 2 asc
215
- having: aircraft_count ? >500
216
- group_by: region
217
- aggregate: aircraft_count
218
- nest: by_state is {
219
- order_by: 2 asc
220
- having: aircraft_count >45
221
- group_by: state
222
- aggregate: aircraft_count
223
- nest: by_city is {
224
- order_by: 2 asc
225
- having: aircraft_count ? >5
226
- group_by: city
227
- aggregate: aircraft_count
228
- }
229
- }
230
- }
231
- `).malloyResultMatches(expressionModel, {
232
- 'by_state.by_city.city': 'ALBUQUERQUE',
233
- });
234
- }));
235
- // bigquery doesn't like to partition by floats,
236
- test('model: having float group by partition', (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
237
- await expect(`${modelText(databaseName)}
238
- run: aircraft_models->{
239
- order_by: 1
240
- where: seats_bucketed > 0
241
- having: aircraft_model_count > 400
242
- group_by: seats_bucketed
243
- aggregate: aircraft_model_count
244
- nest: foo is {
245
- group_by: engines
246
- aggregate: aircraft_model_count
247
- }
248
- }`).malloyResultMatches(runtime, { aircraft_model_count: 448 });
249
- }));
250
- it('model: aggregate functions distinct min max', async () => {
251
- await expect(`
252
- run: aircraft_models->{
253
- aggregate:
254
- distinct_seats is count(seats),
255
- boeing_distinct_seats is count(seats) { where:manufacturer ? 'BOEING'},
256
- min_seats is min(seats),
257
- cessna_min_seats is min(seats) { where: manufacturer ? 'CESSNA'},
258
- max_seats is max(seats),
259
- cessna_max_seats is max(seats) { where: manufacturer ? 'CESSNA'},
260
- min_code is min(aircraft_model_code),
261
- boeing_min_model is min(model) { where: manufacturer ? 'BOEING'},
262
- max_model is max(model),
263
- boeing_max_model is max(model) { where: manufacturer ? 'BOEING'},
264
- }
265
- `).malloyResultMatches(expressionModel, {
266
- distinct_seats: 187,
267
- boeing_distinct_seats: 85,
268
- min_seats: 0,
269
- cessna_min_seats: 1,
270
- max_seats: 660,
271
- min_code: '0030109',
272
- cessna_max_seats: 14,
273
- boeing_min_model: '100',
274
- max_model: 'ZWEIFEL PA18',
275
- boeing_max_model: 'YL-15',
276
- });
277
- });
278
- // TODO not sure why this test needs to be skipped on postgres, feels like an oversight
279
- // NOTE: unless underlying type is stored as a timestamp snowflake does not support extraction
280
- test('model: dates named', (0, util_1.onlyIf)(!['postgres', 'snowflake'].includes(databaseName), async () => {
281
- await expect(`
282
- run: ${databaseName}.table('malloytest.alltypes')->{
283
- group_by:
284
- t_date,
285
- t_date_month is t_date.month,
286
- t_date_year is t_date.year,
287
- t_timestamp,
288
- t_timestamp_date is t_timestamp.day,
289
- t_timestamp_hour is t_timestamp.hour,
290
- t_timestamp_minute is t_timestamp.minute,
291
- t_timestamp_second is t_timestamp.second,
292
- t_timestamp_month is t_timestamp.month,
293
- t_timestamp_year is t_timestamp.year,
294
- }
295
- `).malloyResultMatches(runtime, {
296
- t_date: new Date('2020-03-02'),
297
- t_date_month: new Date('2020-03-01'),
298
- t_date_year: new Date('2020-01-01'),
299
- t_timestamp: new Date('2020-03-02T12:35:56.000Z'),
300
- t_timestamp_second: new Date('2020-03-02T12:35:56.000Z'),
301
- t_timestamp_minute: new Date('2020-03-02T12:35:00.000Z'),
302
- t_timestamp_hour: new Date('2020-03-02T12:00:00.000Z'),
303
- t_timestamp_date: new Date('2020-03-02'),
304
- t_timestamp_month: new Date('2020-03-01'),
305
- t_timestamp_year: new Date('2020-01-01'),
306
- });
307
- }));
308
- it('named query metadata undefined', async () => {
309
- const result = await expressionModel
310
- .loadQuery(`
311
- run: aircraft->{
312
- aggregate: aircraft_count is count()
313
- }
314
- `)
315
- .run();
316
- // TODO The result explore should really be unnamed. This test currently
317
- // inspects inner information because we have no way to have unnamed
318
- // explores today.
319
- // expect(result.getResultExplore().name).toBe(undefined);
320
- expect(result._queryResult.queryName).toBe(undefined);
321
- });
322
- it('named query metadata named', async () => {
323
- const result = await expressionModel
324
- .loadQuery('run: aircraft->by_manufacturer')
325
- .run();
326
- expect(result.resultExplore.name).toBe('by_manufacturer');
327
- });
328
- it('named query metadata named head of pipeline', async () => {
329
- const result = await expressionModel
330
- .loadQuery(`
331
- run: aircraft->by_manufacturer->{ aggregate: c is count()}
332
- `)
333
- .run();
334
- // TODO Same as above -- this test should check the explore name
335
- // expect(result.resultExplore.name).toBe(undefined);
336
- expect(result._queryResult.queryName).toBe(undefined);
337
- });
338
- it('filtered explores basic', async () => {
339
- await expect(`
340
- run: aircraft extend { where: aircraft_models.manufacturer ? ~'B%' }
341
- -> {aggregate: m_count is count(aircraft_models.manufacturer) }
342
- `).malloyResultMatches(expressionModel, { m_count: 63 });
343
- });
344
- it('sql cast', async () => {
345
- await expect(`
346
- run: aircraft -> {
347
- group_by: a is "312"::"integer"
348
- }
349
- `).malloyResultMatches(expressionModel, { a: 312 });
350
- });
351
- test('sql safe cast', (0, util_1.onlyIf)(!['postgres', 'snowflake'].includes(runtime.connection.name), async () => {
352
- await expect(`
353
- run: ${databaseName}.sql('SELECT 1 as one') -> { select:
354
- bad_date is '123':::date
355
- bad_number is 'abc':::number
356
- good_number is "312":::"integer"
357
- }
358
- `).malloyResultMatches(expressionModel, {
359
- bad_date: null,
360
- bad_number: null,
361
- good_number: 312,
362
- });
363
- }));
364
- it('many_field.sum() has correct locality', async () => {
365
- await expect(`
366
- source: a is ${databaseName}.table('malloytest.aircraft')
367
- source: am is ${databaseName}.table('malloytest.aircraft_models') extend {
368
- join_many: a on a.aircraft_model_code = a.aircraft_model_code
369
- dimension: a_year_built is a.year_built
370
- }
371
-
372
- run: am -> {
373
- aggregate: avg_a_year_built1 is floor(a_year_built.avg())
374
- aggregate: avg_a_year_built2 is floor(a.avg(a_year_built))
375
- }
376
- `).malloyResultMatches(runtime, {
377
- avg_a_year_built1: 1969,
378
- avg_a_year_built2: 1969,
379
- });
380
- });
381
- describe('sql expr functions', () => {
382
- it('sql_string', async () => {
383
- await expect(`
384
- ##! experimental { sql_functions }
385
- source: a is ${databaseName}.table('malloytest.aircraft_models') extend { where: aircraft_model_code ? '0270202' }
386
-
387
- run: a -> {
388
- group_by: string_1 is sql_string("UPPER(\${manufacturer})")
389
- }
390
- `).malloyResultMatches(expressionModel, {
391
- string_1: 'AHRENS AIRCRAFT CORP.',
392
- });
393
- });
394
- it('sql_number', async () => {
395
- await expect(`
396
- ##! experimental { sql_functions }
397
- source: a is ${databaseName}.table('malloytest.aircraft_models') extend { where: aircraft_model_code ? '0270202' }
398
-
399
- run: a -> {
400
- group_by: seats
401
- group_by: number_1 is sql_number("\${seats} * 2")
402
- }
403
- `).malloyResultMatches(expressionModel, {
404
- seats: 29,
405
- number_1: 58,
406
- });
407
- });
408
- it('sql_number can be sum()med', async () => {
409
- await expect(`
410
- ##! experimental { sql_functions }
411
- source: a is ${databaseName}.table('malloytest.aircraft_models') extend {
412
- where: aircraft_model_code ? '0270202'
413
- dimension: number_1 is sql_number("\${seats} * 2")
414
- }
415
-
416
- run: a -> {
417
- aggregate: s is number_1.sum()
418
- }
419
- `).malloyResultMatches(expressionModel, {
420
- s: 58,
421
- });
422
- });
423
- it('sql_boolean', async () => {
424
- await expect(`
425
- ##! experimental { sql_functions }
426
- source: a is ${databaseName}.table('malloytest.aircraft_models') extend { where: aircraft_model_code ? '0270202' }
427
-
428
- run: a -> {
429
- group_by: boolean_1 is sql_boolean("\${seats} > 20")
430
- group_by: boolean_2 is sql_boolean("\${engines} = 2")
431
- }
432
- `).malloyResultMatches(expressionModel, {
433
- boolean_1: true,
434
- boolean_2: false,
435
- });
436
- });
437
- it('sql_date', async () => {
438
- await expect(`
439
- ##! experimental { sql_functions }
440
- source: a is ${databaseName}.table('malloytest.aircraft') extend { where: tail_num ? 'N110WL' }
441
-
442
- run: a -> {
443
- group_by: date_1 is sql_date("\${last_action_date}")
444
- }
445
- `).malloyResultMatches(expressionModel, {
446
- date_1: new Date('2000-01-04T00:00:00.000Z'),
447
- });
448
- });
449
- it('sql_timestamp', async () => {
450
- await expect(`
451
- ##! experimental { sql_functions }
452
- source: a is ${databaseName}.table('malloytest.aircraft') extend { where: tail_num ? 'N110WL' }
453
-
454
- run: a -> {
455
- group_by: timestamp_1 is sql_timestamp("\${last_action_date}")
456
- }
457
- `).malloyResultMatches(expressionModel, {
458
- timestamp_1: new Date('2000-01-04T00:00:00.000Z'),
459
- });
460
- });
461
- it('with ${TABLE}.field', async () => {
462
- await expect(`
463
- ##! experimental { sql_functions }
464
- source: a is ${databaseName}.table('malloytest.aircraft_models') extend { where: aircraft_model_code ? '0270202' }
465
-
466
- run: a -> {
467
- group_by: string_1 is sql_string('UPPER(\${TABLE}.${q `manufacturer`})')
468
- }
469
- `).malloyResultMatches(expressionModel, {
470
- string_1: 'AHRENS AIRCRAFT CORP.',
471
- });
472
- });
473
- it('with ${field}', async () => {
474
- await expect(`
475
- ##! experimental { sql_functions }
476
- source: a is ${databaseName}.table('malloytest.aircraft_models') extend { where: aircraft_model_code ? '0270202' }
477
-
478
- run: a -> {
479
- group_by: string_1 is sql_string("UPPER(\${manufacturer})")
480
- }
481
- `).malloyResultMatches(expressionModel, {
482
- string_1: 'AHRENS AIRCRAFT CORP.',
483
- });
484
- });
485
- it('sql_functions - experimental feature is ignored', async () => {
486
- const query = await expressionModel.loadQuery(`
487
- source: a is ${databaseName}.table('malloytest.aircraft_models') extend { where: aircraft_model_code ? '0270202' }
488
-
489
- run: a -> {
490
- group_by: manufacturer
491
- group_by: string_1 is sql_string("UPPER(\${manufacturer})")
492
- }
493
- `);
494
- const runResult = await query.run();
495
- const dataResult = runResult.data.toObject();
496
- expect(dataResult.length).toEqual(1);
497
- const firstRow = dataResult.at(0);
498
- if (firstRow !== undefined) {
499
- expect(firstRow['manufacturer']).toEqual('AHRENS AIRCRAFT CORP.');
500
- expect('string_1' in firstRow).toBeFalsy();
501
- }
502
- else {
503
- (0, assert_1.fail)('exepected a single row, but found none');
504
- }
505
- });
506
- describe('[not yet supported]', () => {
507
- // See ${...} documentation for lookml here for guidance on remaining work:
508
- // https://cloud.google.com/looker/docs/reference/param-field-sql#sql_for_dimensions
509
- it('${view_name.dimension_name} - one path', async () => {
510
- const query = await expressionModel.loadQuery(`
511
- ##! experimental { sql_functions }
512
- source: a is ${databaseName}.table('malloytest.aircraft_models') extend { where: aircraft_model_code ? '0270202' }
513
-
514
- run: a -> {
515
- group_by: string_1 is sql_string("UPPER(\${a.manufacturer})")
516
- }
517
- `);
518
- await expect(query.run()).rejects.toThrow("'.' paths are not yet supported in sql interpolations, found ${a.manufacturer}");
519
- });
520
- it('${view_name.dimension_name} - multiple paths', async () => {
521
- const query = await expressionModel.loadQuery(`
522
- ##! experimental { sql_functions }
523
- source: a is ${databaseName}.table('malloytest.aircraft_models') extend { where: aircraft_model_code ? '0270202' }
524
-
525
- run: a -> {
526
- group_by: number_1 is sql_number("\${a.seats} * \${a.seats} + \${a.total_seats}")
527
- }
528
- `);
529
- await expect(query.run()).rejects.toThrow("'.' paths are not yet supported in sql interpolations, found [${a.seats}, ${a.seats}, ${a.total_seats}]");
530
- });
531
- it('${view_name.SQL_TABLE_NAME}', async () => {
532
- const query = await expressionModel.loadQuery(`
533
- ##! experimental { sql_functions }
534
- source: a is ${databaseName}.table('malloytest.aircraft_models') extend { where: aircraft_model_code ? '0270202' }
535
-
536
- run: a -> {
537
- group_by: number_1 is sql_number("\${a.SQL_TABLE_NAME}.seats")
538
- }
539
- `);
540
- await expect(query.run()).rejects.toThrow("'.' paths are not yet supported in sql interpolations, found ${a.SQL_TABLE_NAME}");
541
- });
542
- });
543
- });
544
- test('query with aliasname used twice', (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
545
- await expect(`
546
- run: aircraft->{
547
- group_by: first is substr(city,1,1)
548
- aggregate: aircraft_count is count()
549
- nest: aircraft is {
550
- group_by: first_two is substr(city,1,2)
551
- aggregate: aircraft_count is count()
552
- nest: aircraft is {
553
- group_by: first_three is substr(city,1,3)
554
- aggregate: aircraft_count is count()
555
- }
556
- }
557
- } -> {
558
- select:
559
- aircraft.aircraft.first_three
560
- aircraft_count
561
- order_by: 2 desc, 1
562
- }
563
- `).malloyResultMatches(expressionModel, { first_three: 'SAB' });
564
- }));
565
- it('joined filtered sources', async () => {
566
- await expect(`
567
- source: a_models is ${databaseName}.table('malloytest.aircraft_models') extend {
568
- where: manufacturer ? ~'B%'
569
- primary_key: aircraft_model_code
570
- measure:model_count is count()
571
- }
572
-
573
- source: aircraft2 is ${databaseName}.table('malloytest.aircraft') extend {
574
- join_one: model is a_models with aircraft_model_code
575
- measure: aircraft_count is count()
576
- }
577
-
578
- run: aircraft2->{
579
- aggregate:
580
- model.model_count
581
- aircraft_count
582
- }
583
- `).malloyResultMatches(expressionModel, {
584
- model_count: 244,
585
- aircraft_count: 3599,
586
- });
587
- });
588
- it('joined filtered explores with dependencies', async () => {
589
- await expect(`
590
- source: bo_models is
591
- ${databaseName}.table('malloytest.aircraft_models') extend { where: manufacturer ? ~ 'BO%' }
592
- -> { select: aircraft_model_code, manufacturer, seats }
593
- extend {
594
- primary_key: aircraft_model_code
595
- measure: bo_count is count()
596
- }
597
- source: b_models is
598
- ${databaseName}.table('malloytest.aircraft_models') extend { where: manufacturer ? ~ 'B%' }
599
- -> { select: aircraft_model_code, manufacturer, seats }
600
- extend {
601
- where: bo_models.seats > 200
602
- primary_key: aircraft_model_code
603
- measure: b_count is count()
604
- join_one: bo_models with aircraft_model_code
605
- }
606
-
607
- source: models is ${databaseName}.table('malloytest.aircraft_models') extend {
608
- join_one: b_models with aircraft_model_code
609
- measure: model_count is count()
610
- }
611
-
612
- run: models -> {
613
- aggregate: model_count
614
- aggregate: b_models.b_count
615
- -- aggregate: b_models.bo_models.bo_count
616
- }
617
- `).malloyResultMatches(runtime, { model_count: 60461, b_count: 355 });
618
- });
619
- });
620
- describe.each(runtimes.runtimeList)('%s', (databaseName, runtime) => {
621
- const q = runtime.getQuoter();
622
- const sqlEq = (0, util_1.mkSqlEqWith)(runtime, databaseName, {
623
- malloy: `extend {
624
- dimension: friName is 'friday'
625
- dimension: friDay is 5
626
- dimension: satName is 'saturday'
627
- dimension: satDay is 6
628
- }`,
629
- });
630
- describe.skip('alternations with not-eq', () => {
631
- /*
632
- Here's the desired truth table ...
633
-
634
- x x != y | z
635
- ====== ============
636
- y false
637
- z false
638
- ^[yz] true
639
- */
640
- test('x not-eq y or z : x eq y', async () => {
641
- const result = await sqlEq('6 != (6|7)', false);
642
- expect(result).isSqlEq();
643
- });
644
- test('x not-eq y or z : x eq z', async () => {
645
- const result = await sqlEq('7 != (6|7)', false);
646
- expect(result).isSqlEq();
647
- });
648
- test('x not-eq y or z : else', async () => {
649
- const result = await sqlEq('5 != (6|7)', true);
650
- expect(result).isSqlEq();
651
- });
652
- /*
653
- Writing this the old way, should have the same truth table ...
654
- x != y & != z
655
- */
656
- test('x not-eq y and not-eq z : x eq y', async () => {
657
- const result = await sqlEq('6 != (6 & !=7)', false);
658
- expect(result).isSqlEq();
659
- });
660
- test('x not-eq y and not-eq z : x eq z', async () => {
661
- const result = await sqlEq('7 != (6 & != 7)', false);
662
- expect(result).isSqlEq();
663
- });
664
- test('x not-eq y and not-eq z : else', async () => {
665
- const result = await sqlEq('5 != (6 & !=7)', true);
666
- expect(result).isSqlEq();
667
- });
668
- });
669
- describe('string literal quoting', () => {
670
- const dq = '"';
671
- const tick = "'";
672
- const back = '\\';
673
- test('quote single character', async () => {
674
- expect(await sqlEq(`'${back}x'`, 'x')).isSqlEq();
675
- });
676
- test('quote single quote', async () => {
677
- expect(await sqlEq(`'${back}${tick}'`, tick)).isSqlEq();
678
- });
679
- test('quote double quote', async () => {
680
- await expect(`run: ${databaseName}.sql("SELECT 1 as one") -> {
681
- select: double_quote is "${back}${dq}"
682
- }`).malloyResultMatches(runtime, { double_quote: '"' });
683
- });
684
- test('quote backslash', async () => {
685
- expect(await sqlEq(`'${back}${back}'`, back)).isSqlEq();
686
- });
687
- });
688
- test('nullish ?? operator', async () => {
689
- await expect(`run: ${databaseName}.sql("""
690
- SELECT '' as ${q `null_value`}, '' as ${q `string_value`}
691
- UNION ALL SELECT null, 'correct'
692
- """) -> {
693
- where: null_value = null
694
- select:
695
- found_null is null_value ?? 'correct',
696
- else_pass is string_value ?? 'incorrect'
697
- literal_null is null ?? 'correct'
698
- }`).malloyResultMatches(runtime, {
699
- found_null: 'correct',
700
- else_pass: 'correct',
701
- literal_null: 'correct',
702
- });
703
- });
704
- test('dimension expressions expanded with parens properly', async () => {
705
- await expect(`run: ${databaseName}.sql("SELECT 1 as one") extend {
706
- dimension: fot is (false) or (true)
707
- } -> {
708
- select:
709
- no_paren is false and fot
710
- paren is false and (fot)
711
- }`).malloyResultMatches(runtime, { paren: false, no_paren: false });
712
- });
713
- });
714
- afterAll(async () => {
715
- await runtimes.closeAll();
716
- });
717
- //# sourceMappingURL=expr.spec.js.map