@malloydata/malloy-tests 0.0.135 → 0.0.136-dev240326234246

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 (118) hide show
  1. package/dist/api.spec.d.ts +1 -0
  2. package/dist/api.spec.js +113 -0
  3. package/dist/api.spec.js.map +1 -0
  4. package/dist/databases/all/db_index.spec.d.ts +1 -0
  5. package/dist/databases/all/db_index.spec.js +126 -0
  6. package/dist/databases/all/db_index.spec.js.map +1 -0
  7. package/dist/databases/all/expr.spec.d.ts +1 -0
  8. package/dist/databases/all/expr.spec.js +652 -0
  9. package/dist/databases/all/expr.spec.js.map +1 -0
  10. package/dist/databases/all/functions.spec.d.ts +1 -0
  11. package/dist/databases/all/functions.spec.js +1180 -0
  12. package/dist/databases/all/functions.spec.js.map +1 -0
  13. package/dist/databases/all/join.spec.d.ts +1 -0
  14. package/dist/databases/all/join.spec.js +255 -0
  15. package/dist/databases/all/join.spec.js.map +1 -0
  16. package/dist/databases/all/lenses.spec.d.ts +1 -0
  17. package/dist/databases/all/lenses.spec.js +374 -0
  18. package/dist/databases/all/lenses.spec.js.map +1 -0
  19. package/dist/databases/all/nomodel.spec.d.ts +1 -0
  20. package/dist/databases/all/nomodel.spec.js +1070 -0
  21. package/dist/databases/all/nomodel.spec.js.map +1 -0
  22. package/dist/databases/all/orderby.spec.d.ts +1 -0
  23. package/dist/databases/all/orderby.spec.js +170 -0
  24. package/dist/databases/all/orderby.spec.js.map +1 -0
  25. package/dist/databases/all/problems.spec.d.ts +1 -0
  26. package/dist/databases/all/problems.spec.js +106 -0
  27. package/dist/databases/all/problems.spec.js.map +1 -0
  28. package/dist/databases/all/sql_expressions.spec.d.ts +1 -0
  29. package/dist/databases/all/sql_expressions.spec.js +73 -0
  30. package/dist/databases/all/sql_expressions.spec.js.map +1 -0
  31. package/dist/databases/all/time.spec.d.ts +1 -0
  32. package/dist/databases/all/time.spec.js +602 -0
  33. package/dist/databases/all/time.spec.js.map +1 -0
  34. package/dist/databases/bigquery/double_truncation.spec.d.ts +1 -0
  35. package/dist/databases/bigquery/double_truncation.spec.js +50 -0
  36. package/dist/databases/bigquery/double_truncation.spec.js.map +1 -0
  37. package/dist/databases/bigquery/handexpr.spec.d.ts +1 -0
  38. package/dist/databases/bigquery/handexpr.spec.js +723 -0
  39. package/dist/databases/bigquery/handexpr.spec.js.map +1 -0
  40. package/dist/databases/bigquery/injestion_time_partitioning.spec.d.ts +1 -0
  41. package/dist/databases/bigquery/injestion_time_partitioning.spec.js +235 -0
  42. package/dist/databases/bigquery/injestion_time_partitioning.spec.js.map +1 -0
  43. package/dist/databases/bigquery/joined_filters.spec.d.ts +1 -0
  44. package/dist/databases/bigquery/joined_filters.spec.js +72 -0
  45. package/dist/databases/bigquery/joined_filters.spec.js.map +1 -0
  46. package/dist/databases/bigquery/json.spec.d.ts +1 -0
  47. package/dist/databases/bigquery/json.spec.js +66 -0
  48. package/dist/databases/bigquery/json.spec.js.map +1 -0
  49. package/dist/databases/bigquery/malloy_query.spec.d.ts +1 -0
  50. package/dist/databases/bigquery/malloy_query.spec.js +840 -0
  51. package/dist/databases/bigquery/malloy_query.spec.js.map +1 -0
  52. package/dist/databases/bigquery/performance.skipped.spec.d.ts +1 -0
  53. package/dist/databases/bigquery/performance.skipped.spec.js +70 -0
  54. package/dist/databases/bigquery/performance.skipped.spec.js.map +1 -0
  55. package/dist/databases/bigquery/time.spec.d.ts +1 -0
  56. package/dist/databases/bigquery/time.spec.js +52 -0
  57. package/dist/databases/bigquery/time.spec.js.map +1 -0
  58. package/dist/databases/bigquery/wildcard_table_names.spec.d.ts +1 -0
  59. package/dist/databases/bigquery/wildcard_table_names.spec.js +212 -0
  60. package/dist/databases/bigquery/wildcard_table_names.spec.js.map +1 -0
  61. package/dist/databases/bigquery-duckdb/nested_source_table.spec.d.ts +1 -0
  62. package/dist/databases/bigquery-duckdb/nested_source_table.spec.js +213 -0
  63. package/dist/databases/bigquery-duckdb/nested_source_table.spec.js.map +1 -0
  64. package/dist/databases/duckdb/duckdb.spec.d.ts +1 -0
  65. package/dist/databases/duckdb/duckdb.spec.js +124 -0
  66. package/dist/databases/duckdb/duckdb.spec.js.map +1 -0
  67. package/dist/databases/duckdb/streaming.spec.d.ts +1 -0
  68. package/dist/databases/duckdb/streaming.spec.js +142 -0
  69. package/dist/databases/duckdb/streaming.spec.js.map +1 -0
  70. package/dist/databases/multi-connection/multi_connection.spec.d.ts +1 -0
  71. package/dist/databases/multi-connection/multi_connection.spec.js +120 -0
  72. package/dist/databases/multi-connection/multi_connection.spec.js.map +1 -0
  73. package/dist/databases/postgres/postgres.spec.d.ts +1 -0
  74. package/dist/databases/postgres/postgres.spec.js +140 -0
  75. package/dist/databases/postgres/postgres.spec.js.map +1 -0
  76. package/dist/databases/shared/test_list.d.ts +3 -0
  77. package/dist/databases/shared/test_list.js +5 -0
  78. package/dist/databases/shared/test_list.js.map +1 -0
  79. package/dist/databases/streaming/streaming.spec.d.ts +1 -0
  80. package/dist/databases/streaming/streaming.spec.js +93 -0
  81. package/dist/databases/streaming/streaming.spec.js.map +1 -0
  82. package/dist/dependencies.spec.d.ts +1 -0
  83. package/dist/dependencies.spec.js +63 -0
  84. package/dist/dependencies.spec.js.map +1 -0
  85. package/dist/index.d.ts +4 -0
  86. package/dist/index.js +49 -0
  87. package/dist/index.js.map +1 -0
  88. package/dist/jestMatcher.spec.d.ts +1 -0
  89. package/dist/jestMatcher.spec.js +81 -0
  90. package/dist/jestMatcher.spec.js.map +1 -0
  91. package/dist/model/sql_source.spec.d.ts +1 -0
  92. package/dist/model/sql_source.spec.js +47 -0
  93. package/dist/model/sql_source.spec.js.map +1 -0
  94. package/dist/models/faa_model.d.ts +5 -0
  95. package/dist/models/faa_model.js +997 -0
  96. package/dist/models/faa_model.js.map +1 -0
  97. package/dist/models/medicare_model.d.ts +4 -0
  98. package/dist/models/medicare_model.js +259 -0
  99. package/dist/models/medicare_model.js.map +1 -0
  100. package/dist/render/drill.spec.d.ts +1 -0
  101. package/dist/render/drill.spec.js +107 -0
  102. package/dist/render/drill.spec.js.map +1 -0
  103. package/dist/render/render.spec.d.ts +1 -0
  104. package/dist/render/render.spec.js +548 -0
  105. package/dist/render/render.spec.js.map +1 -0
  106. package/dist/runtimes.d.ts +35 -0
  107. package/dist/runtimes.js +180 -0
  108. package/dist/runtimes.js.map +1 -0
  109. package/dist/tags.spec.d.ts +8 -0
  110. package/dist/tags.spec.js +490 -0
  111. package/dist/tags.spec.js.map +1 -0
  112. package/dist/util/db-jest-matchers.d.ts +30 -0
  113. package/dist/util/db-jest-matchers.js +157 -0
  114. package/dist/util/db-jest-matchers.js.map +1 -0
  115. package/dist/util/index.d.ts +15 -0
  116. package/dist/util/index.js +182 -0
  117. package/dist/util/index.js.map +1 -0
  118. package/package.json +8 -8
@@ -0,0 +1,1070 @@
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
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
+ const runtimes_1 = require("../../runtimes");
28
+ const util_1 = require("../../util");
29
+ require("../../util/db-jest-matchers");
30
+ const runtimes = new runtimes_1.RuntimeList((0, util_1.databasesFromEnvironmentOr)(runtimes_1.allDatabases));
31
+ // No prebuilt shared model, each test is complete. Makes debugging easier.
32
+ function rootDbPath(databaseName) {
33
+ return databaseName === 'bigquery' ? 'malloy-data.' : '';
34
+ }
35
+ // TODO: Figure out how to generalize this.
36
+ function getSplitFunction(db) {
37
+ return {
38
+ 'bigquery': (column, splitChar) => `split(${column}, '${splitChar}')`,
39
+ 'postgres': (column, splitChar) => `string_to_array(${column}, '${splitChar}')`,
40
+ 'duckdb': (column, splitChar) => `string_to_array(${column}, '${splitChar}')`,
41
+ 'duckdb_wasm': (column, splitChar) => `string_to_array(${column}, '${splitChar}')`,
42
+ 'motherduck': (column, splitChar) => `string_to_array(${column}, '${splitChar}')`,
43
+ 'snowflake': (column, splitChar) => `split(${column}, '${splitChar}')`,
44
+ }[db];
45
+ }
46
+ afterAll(async () => {
47
+ await runtimes.closeAll();
48
+ });
49
+ runtimes.runtimeMap.forEach((runtime, databaseName) => {
50
+ const q = runtime.getQuoter();
51
+ // Issue: #1284
52
+ it(`parenthesize output field values - ${databaseName}`, async () => {
53
+ await expect(`
54
+ run: ${databaseName}.table('malloytest.aircraft') -> {
55
+ group_by: r is 1
56
+
57
+ calculate:
58
+ zero is 1 - rank()
59
+ zero_bare is 0 - zero
60
+ zero_paren is 0 - (zero)
61
+ }
62
+ `).malloyResultMatches(runtime, { zero_bare: 0, zero_paren: 0 });
63
+ });
64
+ // Issue: #151
65
+ it(`bug 151 which used to throw unknown dialect is still fixed- ${databaseName}`, async () => {
66
+ await expect(`
67
+ query: q is ${databaseName}.table('malloytest.aircraft')->{
68
+ where: state != null
69
+ group_by: state
70
+ }
71
+ run: q extend {
72
+ view: foo is {
73
+ order_by: 1 desc
74
+ group_by: state
75
+ }
76
+ } -> foo
77
+ `).malloyResultMatches(runtime, { state: 'WY' });
78
+ });
79
+ // Issue #149
80
+ it(`refine query from query - ${databaseName}`, async () => {
81
+ await expect(`
82
+ run: ${databaseName}.table('malloytest.state_facts')
83
+ -> {group_by: state; order_by: 1 desc; limit: 1}
84
+ extend {
85
+ dimension: lower_state is lower(state)
86
+ } -> {select: lower_state}
87
+ `).malloyResultMatches(runtime, { lower_state: 'wy' });
88
+ });
89
+ // issue #157
90
+ it(`source- not -found - ${databaseName}`, async () => {
91
+ // console.log(result.data.toObject());
92
+ let error;
93
+ try {
94
+ await runtime
95
+ .loadQuery(`
96
+ source: foo is ${databaseName}.table('malloytest.state_facts') extend {primary_key: state}
97
+ run: foox->{aggregate: c is count()}
98
+ `)
99
+ .run();
100
+ }
101
+ catch (e) {
102
+ error = e;
103
+ }
104
+ expect(error.toString()).not.toContain('Unknown Dialect');
105
+ });
106
+ it(`join_many - ${databaseName}`, async () => {
107
+ await expect(`
108
+ source: m is ${databaseName}.table('malloytest.aircraft_models') extend {
109
+ join_many:
110
+ a is ${databaseName}.table('malloytest.aircraft') extend {
111
+ measure: avg_year is floor(avg(year_built))
112
+ } on a.aircraft_model_code=aircraft_model_code
113
+ measure: avg_seats is floor(avg(seats))
114
+ }
115
+ run: m->{aggregate: avg_seats, a.avg_year}
116
+ `).malloyResultMatches(runtime, { avg_year: 1969, avg_seats: 7 });
117
+ });
118
+ it(`join_many condition no primary key - ${databaseName}`, async () => {
119
+ await expect(`
120
+ source: a is ${databaseName}.table('malloytest.airports')
121
+ source: b is ${databaseName}.table('malloytest.state_facts') extend {
122
+ join_many: a on state=a.state
123
+ }
124
+ run: b->{aggregate: c is airport_count.sum()}
125
+ `).malloyResultMatches(runtime, { c: 19701 });
126
+ });
127
+ it(`join_many filter multiple values - ${databaseName}`, async () => {
128
+ await expect(`
129
+ source: a is ${databaseName}.table('malloytest.airports') extend {
130
+ where: state = 'NH' | 'CA'
131
+ }
132
+ run: ${databaseName}.table('malloytest.state_facts') extend {
133
+ join_many: a on state=a.state
134
+ } -> {
135
+ aggregate: c is airport_count.sum()
136
+ group_by: a.state
137
+ }
138
+ `).malloyResultMatches(runtime, [
139
+ { state: null, c: 18605 },
140
+ { state: 'CA', c: 984 },
141
+ { state: 'NH', c: 112 },
142
+ ]);
143
+ });
144
+ it(`join_one condition no primary key - ${databaseName}`, async () => {
145
+ await expect(`
146
+ source: a is ${databaseName}.table('malloytest.state_facts')
147
+ source: b is ${databaseName}.table('malloytest.airports') extend {
148
+ join_one: a on state=a.state
149
+ }
150
+ run: b -> {
151
+ aggregate: c is a.airport_count.sum()
152
+ }
153
+ `).malloyResultMatches(runtime, { c: 19701 });
154
+ });
155
+ it(`join_one filter multiple values - ${databaseName}`, async () => {
156
+ await expect(`
157
+ source: a is ${databaseName}.table('malloytest.state_facts') extend {
158
+ where: state = 'TX' | 'LA'
159
+ }
160
+ source: b is ${databaseName}.table('malloytest.airports') extend {
161
+ join_one: a on state=a.state
162
+ }
163
+ run: b-> {
164
+ aggregate: c is a.airport_count.sum()
165
+ group_by: a.state
166
+ }
167
+ `).malloyResultMatches(runtime, [
168
+ { state: 'TX', c: 1845 },
169
+ { state: 'LA', c: 500 },
170
+ { state: null, c: 0 },
171
+ ]);
172
+ });
173
+ it(`join_many cross from - ${databaseName}`, async () => {
174
+ // a cross join produces a Many to Many result.
175
+ // symmetric aggregate are needed on both sides of the join
176
+ // Check the row count and that sums on each side work properly.
177
+ await expect(`
178
+ source: a is ${databaseName}.table('malloytest.state_facts')
179
+ source: f is a extend {
180
+ join_cross: a
181
+ }
182
+ run: f->{
183
+ aggregate:
184
+ row_count is count(concat(state,a.state))
185
+ left_count is count()
186
+ right_count is a.count()
187
+ left_sum is airport_count.sum()
188
+ right_sum is a.airport_count.sum()
189
+ }
190
+ `).malloyResultMatches(runtime, {
191
+ row_count: 51 * 51,
192
+ left_sum: 19701,
193
+ right_sum: 19701,
194
+ });
195
+ });
196
+ it(`join_one only - ${databaseName}`, async () => {
197
+ // a cross join produces a Many to Many result.
198
+ // symmetric aggregate are needed on both sides of the join
199
+ // Check the row count and that sums on each side work properly.
200
+ await expect(`
201
+ query: q is ${databaseName}.table('malloytest.state_facts')->{
202
+ aggregate: r is airport_count.sum()
203
+ }
204
+ source: f is ${databaseName}.table('malloytest.state_facts') extend {
205
+ join_one: a is q
206
+ }
207
+ run: f->{
208
+ aggregate:
209
+ row_count is count(concat(state,a.r))
210
+ left_sum is airport_count.sum()
211
+ right_sum is a.r.sum()
212
+ sum_sum is sum(airport_count + a.r)
213
+ }
214
+ `).malloyResultMatches(runtime, {
215
+ row_count: 51,
216
+ left_sum: 19701,
217
+ right_sum: 19701,
218
+ sum_sum: 19701 + 51 * 19701,
219
+ });
220
+ });
221
+ it(`join_many cross ON - ${databaseName}`, async () => {
222
+ // a cross join produces a Many to Many result.
223
+ // symmetric aggregate are needed on both sides of the join
224
+ // Check the row count and that sums on each side work properly.
225
+ await expect(`
226
+ source: a is ${databaseName}.table('malloytest.state_facts')
227
+ source: f is a extend {
228
+ join_cross: a on a.state = 'CA' | 'NY'
229
+ }
230
+ run: f->{
231
+ aggregate:
232
+ row_count is count(concat(state,a.state))
233
+ left_sum is airport_count.sum()
234
+ right_sum is a.airport_count.sum()
235
+ }
236
+ `).malloyResultMatches(runtime, {
237
+ row_count: 51 * 2,
238
+ left_sum: 19701,
239
+ right_sum: 1560,
240
+ });
241
+ });
242
+ it(`limit - provided - ${databaseName}`, async () => {
243
+ // a cross join produces a Many to Many result.
244
+ // symmetric aggregate are needed on both sides of the join
245
+ // Check the row count and that sums on each side work properly.
246
+ const result = await runtime
247
+ .loadQuery(`
248
+ run: ${databaseName}.table('malloytest.state_facts') -> {
249
+ group_by: state
250
+ aggregate: c is count()
251
+ limit: 3
252
+ }
253
+ `)
254
+ .run();
255
+ expect(result.resultExplore.limit).toBe(3);
256
+ });
257
+ const matrixModel = `
258
+ ##! experimental.join_types
259
+ source: am_states is ${databaseName}.table('malloytest.state_facts') -> {
260
+ select: *
261
+ where: state ~ r'^(A|M)'
262
+ } extend {
263
+ measure:
264
+ am_count is count()
265
+ am_sum is airport_count.sum()
266
+ }
267
+
268
+ query: ac_states_base is ${databaseName}.table('malloytest.state_facts') -> {
269
+ select: *
270
+ where: state ~ r'^(A|C)'
271
+ }
272
+
273
+ // mulitply the number of rows in ac_states so we have a many to one join
274
+ source: ac_states is ac_states_base -> {
275
+ extend: {
276
+ join_cross: b is ac_states_base
277
+ }
278
+ select:
279
+ b.state
280
+ b.airport_count
281
+ } extend {
282
+ measure:
283
+ ac_count is count()
284
+ ac_sum is airport_count.sum()
285
+ }
286
+ `;
287
+ it(`join inner- ${databaseName}`, async () => {
288
+ // a cross join produces a Many to Many result.
289
+ // symmetric aggregate are needed on both sides of the join
290
+ // Check the row count and that sums on each side work properly.
291
+ await expect(`
292
+ ${matrixModel}
293
+ run: ac_states -> {
294
+ extend: {
295
+ join_one: am_states inner on state = am_states.state
296
+ }
297
+ aggregate:
298
+ ac_count
299
+ ac_sum
300
+ am_states.am_sum
301
+ am_states.am_count
302
+
303
+ }
304
+ `).malloyResultMatches(runtime, {
305
+ ac_count: 28,
306
+ ac_sum: 10402,
307
+ am_count: 4,
308
+ am_sum: 1486,
309
+ //show_sql_fail: 1,
310
+ });
311
+ });
312
+ it(`join left - ${databaseName}`, async () => {
313
+ // a cross join produces a Many to Many result.
314
+ // symmetric aggregate are needed on both sides of the join
315
+ // Check the row count and that sums on each side work properly.
316
+ await expect(`
317
+ ${matrixModel}
318
+ run: ac_states -> {
319
+ extend: {
320
+ join_one: am_states left on state = am_states.state
321
+ }
322
+ aggregate:
323
+ ac_count
324
+ ac_sum
325
+ am_states.am_sum
326
+ am_states.am_count
327
+
328
+ }
329
+ `).malloyResultMatches(runtime, {
330
+ ac_count: 49,
331
+ ac_sum: 21336,
332
+ am_count: 4,
333
+ am_sum: 1486,
334
+ //show_sql_fail: 1,
335
+ });
336
+ });
337
+ it(`join right - ${databaseName}`, async () => {
338
+ // a cross join produces a Many to Many result.
339
+ // symmetric aggregate are needed on both sides of the join
340
+ // Check the row count and that sums on each side work properly.
341
+ await expect(`
342
+ ${matrixModel}
343
+ run: ac_states -> {
344
+ extend: {
345
+ join_one: am_states right on state = am_states.state
346
+ }
347
+ aggregate:
348
+ ac_count
349
+ ac_sum
350
+ am_states.am_sum
351
+ am_states.am_count
352
+
353
+ }
354
+ `).malloyResultMatches(runtime, {
355
+ ac_count: 28,
356
+ ac_sum: 10402,
357
+ am_count: 12,
358
+ am_sum: 4139,
359
+ //show_sql_fail: 1,
360
+ });
361
+ });
362
+ it(`join full - ${databaseName}`, async () => {
363
+ // a cross join produces a Many to Many result.
364
+ // symmetric aggregate are needed on both sides of the join
365
+ // Check the row count and that sums on each side work properly.
366
+ await expect(`
367
+ ${matrixModel}
368
+ run: ac_states -> {
369
+ extend: {
370
+ join_one: am_states full on state = am_states.state
371
+ }
372
+ aggregate:
373
+ ac_count
374
+ ac_sum
375
+ am_states.am_sum
376
+ am_states.am_count
377
+
378
+ }
379
+ `).malloyResultMatches(runtime, {
380
+ ac_count: 49,
381
+ ac_sum: 21336,
382
+ am_count: 12,
383
+ am_sum: 4139,
384
+ });
385
+ });
386
+ it(`leafy count - ${databaseName}`, async () => {
387
+ // in a joined table when the joined is leafiest
388
+ // we need to make sure we don't count rows that
389
+ // don't match the join.
390
+ await expect(`
391
+ source: am_states is ${databaseName}.table('malloytest.state_facts') -> {
392
+ select: *
393
+ where: state ~ r'^(A|M)'
394
+ }
395
+
396
+ source: states is ${databaseName}.table('malloytest.state_facts') extend {
397
+ join_many: am_states on state=am_states.state
398
+ }
399
+
400
+ run: states -> {
401
+ where: state = 'CA'
402
+ aggregate:
403
+ leafy_count is am_states.count()
404
+ root_count is count()
405
+ }
406
+ `).malloyResultMatches(runtime, {
407
+ leafy_count: 0,
408
+ root_count: 1,
409
+ });
410
+ });
411
+ it(`nest/unnest -basic - ${databaseName}`, async () => {
412
+ // in a joined table when the joined is leafiest
413
+ // we need to make sure we don't count rows that
414
+ // don't match the join.
415
+ await expect(`
416
+ run: ${databaseName}.table('malloytest.state_facts') -> {
417
+ group_by: state
418
+ aggregate: c is airport_count.sum()
419
+ nest: p is {
420
+ group_by: popular_name
421
+ aggregate: d is airport_count.sum()
422
+ }
423
+ } -> {
424
+ group_by: state, c
425
+ aggregate: p.d.sum()
426
+ }
427
+ `).malloyResultMatches(runtime, {
428
+ state: 'TX',
429
+ c: 1845,
430
+ d: 1845,
431
+ });
432
+ });
433
+ it(`count at root should not use distinct key - ${databaseName}`, async () => {
434
+ const q = await runtime
435
+ .loadQuery(`
436
+ source: states is ${databaseName}.table('malloytest.state_facts')
437
+
438
+ run: states -> { aggregate: c is count() }
439
+ `)
440
+ .run();
441
+ expect(q.sql.toLowerCase()).not.toContain('distinct');
442
+ });
443
+ it(`leafy nested count - ${databaseName}`, async () => {
444
+ // in a joined table when the joined is leafiest
445
+ // we need to make sure we don't count rows that
446
+ // don't match the join.
447
+ await expect(`
448
+ source: am_states is ${databaseName}.table('malloytest.state_facts') -> {
449
+ group_by: state,popular_name
450
+ where: state ~ r'^(A|M)'
451
+ nest: nested_state is {
452
+ group_by: state,popular_name
453
+ }
454
+ }
455
+
456
+ source: states is ${databaseName}.table('malloytest.state_facts') extend {
457
+ join_many: am_states on state=am_states.state
458
+ }
459
+
460
+ run: states -> {
461
+ where: state = 'CA'
462
+ group_by:
463
+ state
464
+ am_state is am_states.state
465
+ aggregate:
466
+ leafy_count is am_states.nested_state.count()
467
+ root_count is count()
468
+ }
469
+ `).malloyResultMatches(runtime, {
470
+ leafy_count: 0,
471
+ root_count: 1,
472
+ state: 'CA',
473
+ am_state: null,
474
+ });
475
+ });
476
+ it(`basic index - ${databaseName}`, async () => {
477
+ // Make sure basic indexing works.
478
+ await expect(`
479
+ run: ${databaseName}.table('malloytest.flights') -> {
480
+ index: *
481
+ }
482
+ -> {
483
+ select: *
484
+ order_by: fieldValue
485
+ where: fieldName = 'carrier'
486
+ }
487
+ `).malloyResultMatches(runtime, {
488
+ fieldValue: 'AA',
489
+ });
490
+ });
491
+ test(`number as null 2 - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
492
+ // a cross join produces a Many to Many result.
493
+ // symmetric aggregate are needed on both sides of the join
494
+ // Check the row count and that sums on each side work properly.
495
+ await expect(`
496
+ run: ${databaseName}.table('malloytest.state_facts') -> {
497
+ group_by: state
498
+ nest: ugly is {
499
+ group_by: popular_name
500
+ aggregate: foo is NULLIF(sum(airport_count)*0,0)+1
501
+ }
502
+ }
503
+ `).malloyResultMatches(runtime, { 'ugly.foo': null });
504
+ }));
505
+ // average should only include non-null values in the denominator
506
+ it(`avg ignore null- ${databaseName}`, async () => {
507
+ await expect(`
508
+ source: one is ${databaseName}.sql("""
509
+ SELECT 2 as ${q `a`}
510
+ UNION ALL SELECT 4
511
+ UNION ALL SELECT null
512
+ """)
513
+ run: one -> {
514
+ extend: { join_cross: x1 is one }
515
+ aggregate:
516
+ avg_a is a.avg()
517
+ avg_b is x1.a.avg()
518
+ }`).malloyResultMatches(runtime, { avg_a: 3 });
519
+ });
520
+ it(`limit - not provided - ${databaseName}`, async () => {
521
+ // a cross join produces a Many to Many result.
522
+ // symmetric aggregate are needed on both sides of the join
523
+ // Check the row count and that sums on each side work properly.
524
+ const result = await runtime
525
+ .loadQuery(`run: ${databaseName}.table('malloytest.state_facts') -> {
526
+ group_by: state
527
+ aggregate: c is count()
528
+ }`)
529
+ .run();
530
+ expect(result.resultExplore.limit).toBe(undefined);
531
+ });
532
+ it(`ungrouped top level - ${databaseName}`, async () => {
533
+ await expect(`
534
+ run: ${databaseName}.table('malloytest.state_facts') extend {
535
+ measure: total_births is births.sum()
536
+ measure: births_per_100k is floor(total_births/ all(total_births) * 100000)
537
+ } -> {
538
+ group_by: state
539
+ aggregate: births_per_100k
540
+ }`).malloyResultMatches(runtime, { births_per_100k: 9742 });
541
+ });
542
+ test(`ungrouped top level with nested - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
543
+ await expect(`
544
+ run: ${databaseName}.table('malloytest.state_facts') extend {
545
+ measure: total_births is births.sum()
546
+ measure: births_per_100k is floor(total_births/ all(total_births) * 100000)
547
+ } -> {
548
+ group_by: state
549
+ aggregate: births_per_100k
550
+ nest: by_name is {
551
+ group_by: popular_name
552
+ aggregate: total_births
553
+ }
554
+ limit: 1000
555
+ }`).malloyResultMatches(runtime, { births_per_100k: 9742 });
556
+ }));
557
+ it(`ungrouped - eliminate rows - ${databaseName}`, async () => {
558
+ await expect(`
559
+ run : ${databaseName}.table('malloytest.state_facts') extend {
560
+ measure: m is all(births.sum())
561
+ where: state='CA' | 'NY'
562
+ } -> {
563
+ order_by: state
564
+ group_by: state
565
+ aggregate: m
566
+ }`).malloyResultMatches(runtime, [
567
+ { state: 'CA', m: 52504699 },
568
+ { state: 'NY', m: 52504699 },
569
+ ]);
570
+ });
571
+ test(`ungrouped nested with no grouping above - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
572
+ await expect(`
573
+ run: ${databaseName}.table('malloytest.state_facts') extend {
574
+ measure: total_births is births.sum()
575
+ measure: births_per_100k is floor(total_births/ all(total_births) * 100000)
576
+ } -> {
577
+ aggregate: total_births
578
+ nest: by_name is {
579
+ group_by: popular_name
580
+ aggregate: births_per_100k
581
+ }
582
+ }`).malloyResultMatches(runtime, { 'by_name.births_per_100k': 66703 });
583
+ }));
584
+ test(`ungrouped - partial grouping - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
585
+ await expect(`
586
+ run: ${databaseName}.table('malloytest.airports') extend {
587
+ measure: c is count()
588
+ } -> {
589
+ where: state = 'TX' | 'NY'
590
+ group_by:
591
+ faa_region
592
+ state
593
+ aggregate:
594
+ c
595
+ all_ is all(c)
596
+ airport_count is c { where: fac_type = 'AIRPORT'}
597
+ nest: fac_type is {
598
+ group_by: fac_type
599
+ aggregate:
600
+ c
601
+ all_ is all(c)
602
+ all_state_region is exclude(c,fac_type)
603
+ all_of_this_type is exclude(c, state, faa_region)
604
+ all_top is exclude(c, state, faa_region, fac_type)
605
+ }
606
+ }
607
+ `).malloyResultMatches(runtime, {
608
+ 'fac_type.all_': 1845,
609
+ 'fac_type.all_state_region': 1845,
610
+ 'fac_type.all_of_this_type': 1782,
611
+ 'fac_type.all_top': 2421,
612
+ });
613
+ }));
614
+ test(`ungrouped - all nested - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
615
+ await expect(`
616
+ run: ${databaseName}.table('malloytest.airports') extend {
617
+ measure: c is count()
618
+ } -> {
619
+ where: state = 'TX' | 'NY'
620
+ group_by:
621
+ state
622
+ aggregate:
623
+ c
624
+ all_ is all(c)
625
+ airport_count is c { where: fac_type = 'AIRPORT'}
626
+ nest: fac_type is {
627
+ group_by: fac_type, major
628
+ aggregate:
629
+ c
630
+ all_ is all(c)
631
+ all_major is all(c,major)
632
+ }
633
+ }
634
+ `).malloyResultMatches(runtime, {
635
+ 'fac_type.all_': 1845,
636
+ 'fac_type.all_major': 1819,
637
+ });
638
+ }));
639
+ test(`ungrouped nested - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
640
+ await expect(`
641
+ run: ${databaseName}.table('malloytest.state_facts') extend {
642
+ measure: total_births is births.sum()
643
+ measure: births_per_100k is floor(total_births/ all(total_births) * 100000)
644
+ } -> {
645
+ group_by: popular_name
646
+ nest: by_state is {
647
+ group_by: state
648
+ aggregate: births_per_100k
649
+ }
650
+ }
651
+ `).malloyResultMatches(runtime, { 'by_state.births_per_100k': 36593 });
652
+ }));
653
+ test(`ungrouped nested expression - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
654
+ await expect(`
655
+ run: ${databaseName}.table('malloytest.state_facts') extend {
656
+ measure: total_births is births.sum()
657
+ measure: births_per_100k is floor(total_births/ all(total_births) * 100000)
658
+ } -> {
659
+ group_by: upper_name is upper(popular_name)
660
+ nest: by_state is {
661
+ group_by: state
662
+ aggregate: births_per_100k
663
+ }
664
+ }
665
+ `).malloyResultMatches(runtime, { 'by_state.births_per_100k': 36593 });
666
+ }));
667
+ test(`ungrouped nested group by float - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
668
+ await expect(`
669
+ run: ${databaseName}.table('malloytest.state_facts') extend {
670
+ measure: total_births is births.sum()
671
+ measure: ug is all(total_births)
672
+ } -> {
673
+ group_by: f is floor(airport_count/300.0)
674
+ nest: by_state is {
675
+ group_by: state
676
+ aggregate: ug
677
+ }
678
+ }
679
+ `).malloyResultMatches(runtime, { 'by_state.ug': 62742230 });
680
+ }));
681
+ it(`run simple sql - ${databaseName}`, async () => {
682
+ const result = await runtime
683
+ .loadQuery(`run: conn.sql('select 1 as ${q `one`}')`)
684
+ .run();
685
+ expect(result.data.value[0]['one']).toBe(1);
686
+ });
687
+ it(`simple sql is exactly as written - ${databaseName}`, async () => {
688
+ const result = await runtime
689
+ .loadQuery(`run: conn.sql('select 1 as ${q `one`}')`)
690
+ .run();
691
+ if (databaseName === 'postgres') {
692
+ expect(result.sql).toBe(`WITH __stage0 AS (
693
+ select 1 as ${q `one`})
694
+ SELECT row_to_json(finalStage) as row FROM __stage0 AS finalStage`);
695
+ }
696
+ else {
697
+ expect(result.sql).toBe(`select 1 as ${q `one`}`);
698
+ }
699
+ expect(result.resultExplore).not.toBeUndefined();
700
+ });
701
+ it(`source from query defined as sql query - ${databaseName}`, async () => {
702
+ const result = await runtime
703
+ .loadQuery(`
704
+ query: q is conn.sql('select 1 as ${q `one`}')
705
+ source: s is q
706
+ run: s -> { select: * }
707
+ `)
708
+ .run();
709
+ expect(result.data.path(0, 'one').number.value).toBe(1);
710
+ });
711
+ it(`source from query defined as other query - ${databaseName}`, async () => {
712
+ const result = await runtime
713
+ .loadQuery(`
714
+ query: q is conn.table('malloytest.flights') -> { group_by: carrier }
715
+ source: s is q
716
+ run: s -> { select: *; order_by: carrier }
717
+ `)
718
+ .run();
719
+ expect(result.data.path(0, 'carrier').string.value).toBe('AA');
720
+ });
721
+ it(`all with parameters - basic - ${databaseName}`, async () => {
722
+ await expect(`
723
+ run: ${databaseName}.table('malloytest.state_facts') extend {
724
+ measure: total_births is births.sum()
725
+ } -> {
726
+ group_by: popular_name, state
727
+ aggregate:
728
+ total_births
729
+ all_births is all(total_births)
730
+ all_name is exclude(total_births, state)
731
+ }
732
+ `).malloyResultMatches(runtime, {
733
+ all_births: 295727065,
734
+ all_name: 197260594,
735
+ });
736
+ });
737
+ test(`all with parameters - nest - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
738
+ await expect(`
739
+ run: ${databaseName}.table('malloytest.state_facts') extend {
740
+ measure: total_births is births.sum()
741
+ dimension: abc is floor(airport_count/300)
742
+ } -> {
743
+ group_by: abc
744
+ aggregate: total_births
745
+ nest: by_stuff is {
746
+ group_by: popular_name, state
747
+ aggregate:
748
+ total_births
749
+ all_births is all(total_births)
750
+ all_name is exclude(total_births, state)
751
+ }
752
+ }
753
+ `).malloyResultMatches(runtime, {
754
+ 'by_stuff.all_births': 119809719,
755
+ 'by_stuff.all_name': 61091215,
756
+ });
757
+ }));
758
+ test(`single value to udf - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting && runtime.dialect.supportsPipelinesInViews, async () => {
759
+ await expect(`
760
+ run: ${databaseName}.table('malloytest.state_facts') extend {
761
+ view: fun is {
762
+ aggregate: t is count()
763
+ } -> { select: t1 is t+1 }
764
+ } -> { nest: fun }
765
+ `).malloyResultMatches(runtime, { 'fun.t1': 52 });
766
+ }));
767
+ test(`Multi value to udf - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting && runtime.dialect.supportsPipelinesInViews, async () => {
768
+ await expect(`
769
+ run: ${databaseName}.table('malloytest.state_facts') extend {
770
+ view: fun is {
771
+ group_by: one is 1
772
+ aggregate: t is count()
773
+ } -> { select: t1 is t+1 }
774
+ } -> {
775
+ nest: fun
776
+ }
777
+ `).malloyResultMatches(runtime, { 'fun.t1': 52 });
778
+ }));
779
+ test(`Multi value to udf group by - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting && runtime.dialect.supportsPipelinesInViews, async () => {
780
+ await expect(`
781
+ run: ${databaseName}.table('malloytest.state_facts') extend {
782
+ view: fun is {
783
+ group_by: one is 1
784
+ aggregate: t is count()
785
+ } -> { group_by: t1 is t+1 }
786
+ } -> {
787
+ nest: fun
788
+ }
789
+ `).malloyResultMatches(runtime, { 'fun.t1': 52 });
790
+ }));
791
+ const sql1234 = `${databaseName}.sql('SELECT 1 as ${q `a`}, 2 as ${q `b`} UNION ALL SELECT 3, 4')`;
792
+ it(`sql as source - ${databaseName}`, async () => {
793
+ await expect(`
794
+ run: ${sql1234} -> { select: a }
795
+ `).malloyResultMatches(runtime, { a: 1 });
796
+ });
797
+ it(`sql directly - ${databaseName}`, async () => {
798
+ await expect(`run: ${sql1234}`).malloyResultMatches(runtime, { a: 1 });
799
+ });
800
+ it(`sql with turducken- ${databaseName}`, async () => {
801
+ const turduckenQuery = `
802
+ run: ${databaseName}.sql("""
803
+ SELECT
804
+ 'something' as SOMETHING,
805
+ *
806
+ FROM %{
807
+ ${databaseName}.table('malloytest.state_facts') -> {
808
+ group_by: popular_name
809
+ aggregate: state_count is count()
810
+ }
811
+ } AS by_name_query
812
+ """) -> {
813
+ select: *; where: popular_name = 'Emma'
814
+ }`;
815
+ await expect(turduckenQuery).malloyResultMatches(runtime, { state_count: 6 });
816
+ });
817
+ // local declarations
818
+ it(`local declarations external query - ${databaseName}`, async () => {
819
+ await expect(`
820
+ run: ${sql1234} -> {
821
+ extend: { dimension: c is a + 1 }
822
+ select: c
823
+ }
824
+ `).malloyResultMatches(runtime, { c: 2 });
825
+ });
826
+ it(`local declarations named query - ${databaseName}`, async () => {
827
+ await expect(`
828
+ run: ${sql1234} extend {
829
+ view: bar is {
830
+ extend: { dimension: c is a + 1 }
831
+ select: c
832
+ }
833
+ } -> bar
834
+ `).malloyResultMatches(runtime, { c: 2 });
835
+ });
836
+ it(`local declarations refined named query - ${databaseName}`, async () => {
837
+ await expect(`
838
+ run: ${sql1234} extend {
839
+ view: bar is {
840
+ extend: {dimension: c is a + 1}
841
+ select: c
842
+ }
843
+ view: baz is bar + {
844
+ extend: {dimension: d is c + 1}
845
+ select: d
846
+ }
847
+ } -> baz
848
+ `).malloyResultMatches(runtime, { d: 3 });
849
+ });
850
+ it(`regexp match- ${databaseName}`, async () => {
851
+ await expect(`
852
+ run: ${databaseName}.sql("""
853
+ SELECT 'hello mom' as ${q `a`}, 'cheese tastes good' as ${q `b`}
854
+ UNION ALL SELECT 'lloyd is a bozo', 'michael likes poetry'
855
+ """) -> {
856
+ aggregate: llo is count() {where: a ~ r'llo'}
857
+ aggregate: m2 is count() {where: a !~ r'bozo'}
858
+ }
859
+ `).malloyResultMatches(runtime, { llo: 2, m2: 1 });
860
+ });
861
+ it(`substitution precedence- ${databaseName}`, async () => {
862
+ await expect(`
863
+ run: ${databaseName}.sql("""
864
+ SELECT 5 as ${q `a`}, 2 as ${q `b`}
865
+ UNION ALL SELECT 3, 4
866
+ """) -> {
867
+ extend: {dimension: c is b + 4}
868
+ select: x is a * c
869
+ }
870
+ `).malloyResultMatches(runtime, { x: 30 });
871
+ });
872
+ test(`array unnest - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting && runtime.dialect.supportsArraysInData, async () => {
873
+ const splitFN = getSplitFunction(databaseName);
874
+ await expect(`
875
+ run: ${databaseName}.sql("""
876
+ SELECT
877
+ ${q `city`},
878
+ ${splitFN(q `city`, ' ')} as ${q `words`}
879
+ FROM ${rootDbPath(databaseName)}malloytest.aircraft
880
+ """) -> {
881
+ where: words.value != null
882
+ group_by: words.value
883
+ aggregate: c is count()
884
+ }
885
+ `).malloyResultMatches(runtime, { c: 145 });
886
+ }));
887
+ // make sure we can count the total number of elements when fanning out.
888
+ test(`array unnest x 2 - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting && runtime.dialect.supportsArraysInData, async () => {
889
+ const splitFN = getSplitFunction(databaseName);
890
+ await expect(`
891
+ run: ${databaseName}.sql("""
892
+ SELECT
893
+ ${q `city`},
894
+ ${splitFN(q `city`, ' ')} as ${q `words`},
895
+ ${splitFN(q `city`, 'A')} as ${q `abreak`}
896
+ FROM ${rootDbPath(databaseName)}malloytest.aircraft
897
+ WHERE ${q `city`} IS NOT null
898
+ """) -> {
899
+ aggregate:
900
+ b is count()
901
+ c is words.count()
902
+ a is abreak.count()
903
+ }`).malloyResultMatches(runtime, { b: 3552, c: 4586, a: 6601 });
904
+ }));
905
+ test(`can unnest from file - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting && runtime.dialect.readsNestedData, async () => {
906
+ await expect(`
907
+ source: ga_sample is ${databaseName}.table('malloytest.ga_sample')
908
+
909
+ run: ga_sample -> {
910
+ where: hits.product.productBrand != null
911
+ group_by:
912
+ hits.product.productBrand
913
+ hits.product.productSKU
914
+ aggregate:
915
+ h is hits.count()
916
+ c is count()
917
+ p is hits.product.count()
918
+ }
919
+ `).malloyResultMatches(runtime, { h: 1192, c: 681, p: 1192 });
920
+ }));
921
+ test(`nest null - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
922
+ const result = await runtime
923
+ .loadQuery(`
924
+ run: ${databaseName}.table('malloytest.airports') -> {
925
+ where: faa_region = null
926
+ group_by: faa_region
927
+ aggregate: airport_count is count()
928
+ nest: by_state is {
929
+ where: state != null
930
+ group_by: state
931
+ aggregate: airport_count is count()
932
+ }
933
+ nest: by_state1 is {
934
+ where: state != null
935
+ group_by: state
936
+ aggregate: airport_count is count()
937
+ limit: 1
938
+ }
939
+ }
940
+ `)
941
+ .run();
942
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
943
+ const d = result.data.toObject();
944
+ expect(d[0]['by_state']).not.toBe(null);
945
+ expect(d[0]['by_state1']).not.toBe(null);
946
+ }));
947
+ test(`number as null- ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
948
+ const result = await runtime
949
+ .loadQuery(`
950
+ source: s is ${databaseName}.table('malloytest.state_facts') extend {
951
+ }
952
+ run: s-> {
953
+ group_by: state
954
+ nest: ugly is {
955
+ group_by: popular_name
956
+ aggregate: foo is NULLIF(sum(airport_count)*0,0)+1
957
+ }
958
+ }
959
+ `)
960
+ .run();
961
+ expect(result.data.path(0, 'ugly', 0, 'foo').value).toBe(null);
962
+ }));
963
+ it(`removes surpuflous order_by - solo aggregates - ${databaseName}`, async () => {
964
+ const result = await runtime
965
+ .loadQuery(`
966
+ run: ${databaseName}.table('malloytest.state_facts') -> {
967
+ aggregate: airport_count.sum()
968
+ }
969
+ `)
970
+ .run();
971
+ expect(result.sql).not.toContain('ORDER BY');
972
+ });
973
+ it(`removes surpuflous order_by - pipeline - ${databaseName}`, async () => {
974
+ const result = await runtime
975
+ .loadQuery(`
976
+ run: ${databaseName}.table('malloytest.state_facts') -> {
977
+ group_by: state
978
+ aggregate: airport_count.sum()
979
+ order_by: state desc
980
+ }
981
+ -> {
982
+ aggregate: airport_count.sum()
983
+ }
984
+ `)
985
+ .run();
986
+ expect(result.sql).not.toContain('ORDER BY');
987
+ });
988
+ it(`removes surpuflous order_by - joined_query - ${databaseName}`, async () => {
989
+ const result = await runtime
990
+ .loadQuery(`
991
+ query: foo is ${databaseName}.table('malloytest.state_facts') -> {
992
+ group_by: state
993
+ aggregate: airport_count.sum()
994
+ order_by: state desc
995
+ }
996
+
997
+ run: ${databaseName}.table('malloytest.state_facts') -> {
998
+ extend: {
999
+ join_one: foo on state = foo.state
1000
+ }
1001
+ aggregate: x is foo.airport_count.sum()
1002
+ }
1003
+ `)
1004
+ .run();
1005
+ expect(result.sql).not.toContain('ORDER BY');
1006
+ });
1007
+ it(`removes surpuflous order_by - joined_query pipeline - ${databaseName}`, async () => {
1008
+ const result = await runtime
1009
+ .loadQuery(`
1010
+ query: foo is ${databaseName}.table('malloytest.state_facts') -> {
1011
+ group_by: state
1012
+ aggregate: airport_count.sum()
1013
+ order_by: state desc
1014
+ } -> {
1015
+ group_by: state
1016
+ aggregate: airport_count.sum()
1017
+ order_by: state desc
1018
+ }
1019
+
1020
+ run: ${databaseName}.table('malloytest.state_facts') -> {
1021
+ extend: {
1022
+ join_one: foo on state = foo.state
1023
+ }
1024
+ aggregate: x is foo.airport_count.sum()
1025
+ }
1026
+ `)
1027
+ .run();
1028
+ expect(result.sql).not.toContain('ORDER BY');
1029
+ });
1030
+ describe('quoting and strings', () => {
1031
+ const tick = "'";
1032
+ const back = '\\';
1033
+ test('backslash quote', async () => {
1034
+ await expect(`
1035
+ run: ${databaseName}.sql('SELECT 1 as one') -> {
1036
+ select: tick is '${back}${tick}'
1037
+ }
1038
+ `).malloyResultMatches(runtime, { tick });
1039
+ });
1040
+ test('backslash backslash', async () => {
1041
+ await expect(`
1042
+ run: ${databaseName}.sql("SELECT 1 as one") -> {
1043
+ select: back is '${back}${back}'
1044
+ }
1045
+ `).malloyResultMatches(runtime, { back });
1046
+ });
1047
+ test('spaces in names', (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
1048
+ await expect(`
1049
+ source: \`space race\` is ${databaseName}.table('malloytest.state_facts') extend {
1050
+ join_one: \`j space\` is ${databaseName}.table('malloytest.state_facts') on \`j space\`.state=state
1051
+ view: \`q u e r y\` is {
1052
+ group_by:
1053
+ \`P O P\` is popular_name
1054
+ \`J P O P\` is \`j space\`.popular_name
1055
+ aggregate: \`c o u n t\` is count()
1056
+ calculate:
1057
+ \`R O W\` is row_number()
1058
+ \`l a g\` is lag(\`P O P\`, 1)
1059
+ nest: \`by state\` is {
1060
+ group_by: \`J S\` is \`j space\`.state
1061
+ aggregate: \`c o u n t\` is count()
1062
+ }
1063
+ }
1064
+ }
1065
+ run: \`space race\` -> \`q u e r y\`
1066
+ `).malloyResultMatches(runtime, { 'c o u n t': 24 });
1067
+ }));
1068
+ });
1069
+ });
1070
+ //# sourceMappingURL=nomodel.spec.js.map