@malloydata/malloy-tests 0.0.66-dev230807232724

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 (169) hide show
  1. package/README.md +29 -0
  2. package/bin/dump_malloytest.sh +1 -0
  3. package/bin/postgres_init.sh +9 -0
  4. package/bin/postgres_start.sh +2 -0
  5. package/bin/postgres_stop.sh +2 -0
  6. package/data/duckdb/README.md +4 -0
  7. package/data/duckdb/aircraft.parquet +0 -0
  8. package/data/duckdb/aircraft_models.parquet +0 -0
  9. package/data/duckdb/airports.parquet +0 -0
  10. package/data/duckdb/alltypes.parquet +0 -0
  11. package/data/duckdb/alltypes2.parquet +0 -0
  12. package/data/duckdb/bq_medicare_test.parquet +0 -0
  13. package/data/duckdb/carriers.parquet +0 -0
  14. package/data/duckdb/flights/part.0.parquet +0 -0
  15. package/data/duckdb/flights/part.1.parquet +0 -0
  16. package/data/duckdb/flights/part.2.parquet +0 -0
  17. package/data/duckdb/flights.parquet +0 -0
  18. package/data/duckdb/flights_partitioned.parquet +0 -0
  19. package/data/duckdb/ga_sample.parquet +0 -0
  20. package/data/duckdb/numbers.parquet +0 -0
  21. package/data/duckdb/state_facts.parquet +0 -0
  22. package/data/duckdb/test.json +3 -0
  23. package/data/duckdb/words.parquet +0 -0
  24. package/data/duckdb/words_bigger.parquet +0 -0
  25. package/data/postgres/malloytest-postgres.sql.gz +0 -0
  26. package/data/postgres/state_facts.sql +366 -0
  27. package/dist/api.spec.d.ts +1 -0
  28. package/dist/api.spec.js +77 -0
  29. package/dist/api.spec.js.map +1 -0
  30. package/dist/databases/all/expr.spec.d.ts +3 -0
  31. package/dist/databases/all/expr.spec.js +581 -0
  32. package/dist/databases/all/expr.spec.js.map +1 -0
  33. package/dist/databases/all/functions.spec.d.ts +2 -0
  34. package/dist/databases/all/functions.spec.js +784 -0
  35. package/dist/databases/all/functions.spec.js.map +1 -0
  36. package/dist/databases/all/index.spec.d.ts +2 -0
  37. package/dist/databases/all/index.spec.js +154 -0
  38. package/dist/databases/all/index.spec.js.map +1 -0
  39. package/dist/databases/all/join.spec.d.ts +2 -0
  40. package/dist/databases/all/join.spec.js +309 -0
  41. package/dist/databases/all/join.spec.js.map +1 -0
  42. package/dist/databases/all/nomodel.spec.d.ts +2 -0
  43. package/dist/databases/all/nomodel.spec.js +957 -0
  44. package/dist/databases/all/nomodel.spec.js.map +1 -0
  45. package/dist/databases/all/orderby.spec.d.ts +2 -0
  46. package/dist/databases/all/orderby.spec.js +224 -0
  47. package/dist/databases/all/orderby.spec.js.map +1 -0
  48. package/dist/databases/all/problems.spec.d.ts +2 -0
  49. package/dist/databases/all/problems.spec.js +113 -0
  50. package/dist/databases/all/problems.spec.js.map +1 -0
  51. package/dist/databases/all/sql_expressions.spec.d.ts +2 -0
  52. package/dist/databases/all/sql_expressions.spec.js +96 -0
  53. package/dist/databases/all/sql_expressions.spec.js.map +1 -0
  54. package/dist/databases/all/time.spec.d.ts +3 -0
  55. package/dist/databases/all/time.spec.js +647 -0
  56. package/dist/databases/all/time.spec.js.map +1 -0
  57. package/dist/databases/bigquery/double_truncation.spec.d.ts +1 -0
  58. package/dist/databases/bigquery/double_truncation.spec.js +50 -0
  59. package/dist/databases/bigquery/double_truncation.spec.js.map +1 -0
  60. package/dist/databases/bigquery/handexpr.spec.d.ts +1 -0
  61. package/dist/databases/bigquery/handexpr.spec.js +713 -0
  62. package/dist/databases/bigquery/handexpr.spec.js.map +1 -0
  63. package/dist/databases/bigquery/injestion_time_partitioning.spec.d.ts +1 -0
  64. package/dist/databases/bigquery/injestion_time_partitioning.spec.js +235 -0
  65. package/dist/databases/bigquery/injestion_time_partitioning.spec.js.map +1 -0
  66. package/dist/databases/bigquery/joined_filters.spec.d.ts +1 -0
  67. package/dist/databases/bigquery/joined_filters.spec.js +72 -0
  68. package/dist/databases/bigquery/joined_filters.spec.js.map +1 -0
  69. package/dist/databases/bigquery/json.spec.d.ts +1 -0
  70. package/dist/databases/bigquery/json.spec.js +86 -0
  71. package/dist/databases/bigquery/json.spec.js.map +1 -0
  72. package/dist/databases/bigquery/malloy_query.spec.d.ts +1 -0
  73. package/dist/databases/bigquery/malloy_query.spec.js +906 -0
  74. package/dist/databases/bigquery/malloy_query.spec.js.map +1 -0
  75. package/dist/databases/bigquery/performance.skipped.spec.d.ts +1 -0
  76. package/dist/databases/bigquery/performance.skipped.spec.js +70 -0
  77. package/dist/databases/bigquery/performance.skipped.spec.js.map +1 -0
  78. package/dist/databases/bigquery/time.spec.d.ts +1 -0
  79. package/dist/databases/bigquery/time.spec.js +55 -0
  80. package/dist/databases/bigquery/time.spec.js.map +1 -0
  81. package/dist/databases/bigquery/wildcard_table_names.spec.d.ts +1 -0
  82. package/dist/databases/bigquery/wildcard_table_names.spec.js +212 -0
  83. package/dist/databases/bigquery/wildcard_table_names.spec.js.map +1 -0
  84. package/dist/databases/bigquery-duckdb/nested_source_table.spec.d.ts +1 -0
  85. package/dist/databases/bigquery-duckdb/nested_source_table.spec.js +247 -0
  86. package/dist/databases/bigquery-duckdb/nested_source_table.spec.js.map +1 -0
  87. package/dist/databases/bigquery-postgres/multi_connection.spec.d.ts +1 -0
  88. package/dist/databases/bigquery-postgres/multi_connection.spec.js +138 -0
  89. package/dist/databases/bigquery-postgres/multi_connection.spec.js.map +1 -0
  90. package/dist/databases/bigquery-postgres/streaming.spec.d.ts +1 -0
  91. package/dist/databases/bigquery-postgres/streaming.spec.js +88 -0
  92. package/dist/databases/bigquery-postgres/streaming.spec.js.map +1 -0
  93. package/dist/databases/duckdb/duckdb.spec.d.ts +1 -0
  94. package/dist/databases/duckdb/duckdb.spec.js +116 -0
  95. package/dist/databases/duckdb/duckdb.spec.js.map +1 -0
  96. package/dist/databases/postgres/postgres.spec.d.ts +1 -0
  97. package/dist/databases/postgres/postgres.spec.js +137 -0
  98. package/dist/databases/postgres/postgres.spec.js.map +1 -0
  99. package/dist/databases/shared/test_list.d.ts +3 -0
  100. package/dist/databases/shared/test_list.js +24 -0
  101. package/dist/databases/shared/test_list.js.map +1 -0
  102. package/dist/dependencies.spec.d.ts +1 -0
  103. package/dist/dependencies.spec.js +63 -0
  104. package/dist/dependencies.spec.js.map +1 -0
  105. package/dist/index.d.ts +11 -0
  106. package/dist/index.js +49 -0
  107. package/dist/index.js.map +1 -0
  108. package/dist/model/utils.spec.d.ts +1 -0
  109. package/dist/model/utils.spec.js +38 -0
  110. package/dist/model/utils.spec.js.map +1 -0
  111. package/dist/models/faa_model.d.ts +5 -0
  112. package/dist/models/faa_model.js +977 -0
  113. package/dist/models/faa_model.js.map +1 -0
  114. package/dist/models/medicare_model.d.ts +4 -0
  115. package/dist/models/medicare_model.js +243 -0
  116. package/dist/models/medicare_model.js.map +1 -0
  117. package/dist/render/render.spec.d.ts +1 -0
  118. package/dist/render/render.spec.js +551 -0
  119. package/dist/render/render.spec.js.map +1 -0
  120. package/dist/runtimes.d.ts +33 -0
  121. package/dist/runtimes.js +147 -0
  122. package/dist/runtimes.js.map +1 -0
  123. package/dist/tags.spec.d.ts +1 -0
  124. package/dist/tags.spec.js +259 -0
  125. package/dist/tags.spec.js.map +1 -0
  126. package/dist/util/db-jest-matchers.d.ts +19 -0
  127. package/dist/util/db-jest-matchers.js +90 -0
  128. package/dist/util/db-jest-matchers.js.map +1 -0
  129. package/dist/util/index.d.ts +16 -0
  130. package/dist/util/index.js +171 -0
  131. package/dist/util/index.js.map +1 -0
  132. package/package.json +35 -0
  133. package/src/api.spec.ts +84 -0
  134. package/src/databases/all/expr.spec.ts +704 -0
  135. package/src/databases/all/functions.spec.ts +1135 -0
  136. package/src/databases/all/index.spec.ts +178 -0
  137. package/src/databases/all/join.spec.ts +350 -0
  138. package/src/databases/all/nomodel.spec.ts +1159 -0
  139. package/src/databases/all/orderby.spec.ts +268 -0
  140. package/src/databases/all/problems.spec.ts +121 -0
  141. package/src/databases/all/sql_expressions.spec.ts +107 -0
  142. package/src/databases/all/time.spec.ts +793 -0
  143. package/src/databases/bigquery/double_truncation.spec.ts +51 -0
  144. package/src/databases/bigquery/handexpr.spec.ts +782 -0
  145. package/src/databases/bigquery/injestion_time_partitioning.spec.ts +268 -0
  146. package/src/databases/bigquery/joined_filters.spec.ts +75 -0
  147. package/src/databases/bigquery/json.spec.ts +95 -0
  148. package/src/databases/bigquery/malloy_query.spec.ts +1036 -0
  149. package/src/databases/bigquery/performance.skipped.spec.ts +73 -0
  150. package/src/databases/bigquery/time.spec.ts +59 -0
  151. package/src/databases/bigquery/wildcard_table_names.spec.ts +233 -0
  152. package/src/databases/bigquery-duckdb/nested_source_table.spec.ts +268 -0
  153. package/src/databases/bigquery-postgres/multi_connection.spec.ts +143 -0
  154. package/src/databases/bigquery-postgres/streaming.spec.ts +100 -0
  155. package/src/databases/duckdb/duckdb.spec.ts +131 -0
  156. package/src/databases/postgres/postgres.spec.ts +167 -0
  157. package/src/databases/shared/test_list.ts +24 -0
  158. package/src/dependencies.spec.ts +62 -0
  159. package/src/index.ts +36 -0
  160. package/src/model/utils.spec.ts +37 -0
  161. package/src/models/faa_model.ts +995 -0
  162. package/src/models/medicare_model.ts +246 -0
  163. package/src/render/__snapshots__/render.spec.ts.snap +12574 -0
  164. package/src/render/render.spec.ts +670 -0
  165. package/src/runtimes.ts +182 -0
  166. package/src/tags.spec.ts +277 -0
  167. package/src/util/db-jest-matchers.ts +128 -0
  168. package/src/util/index.ts +191 -0
  169. package/tsconfig.json +25 -0
@@ -0,0 +1,906 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright 2023 Google LLC
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files
7
+ * (the "Software"), to deal in the Software without restriction,
8
+ * including without limitation the rights to use, copy, modify, merge,
9
+ * publish, distribute, sublicense, and/or sell copies of the Software,
10
+ * and to permit persons to whom the Software is furnished to do so,
11
+ * subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ var desc = Object.getOwnPropertyDescriptor(m, k);
27
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
28
+ desc = { enumerable: true, get: function() { return m[k]; } };
29
+ }
30
+ Object.defineProperty(o, k2, desc);
31
+ }) : (function(o, m, k, k2) {
32
+ if (k2 === undefined) k2 = k;
33
+ o[k2] = m[k];
34
+ }));
35
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
36
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
37
+ }) : function(o, v) {
38
+ o["default"] = v;
39
+ });
40
+ var __importStar = (this && this.__importStar) || function (mod) {
41
+ if (mod && mod.__esModule) return mod;
42
+ var result = {};
43
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
44
+ __setModuleDefault(result, mod);
45
+ return result;
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ const globals_1 = require("@jest/globals");
49
+ const malloy = __importStar(require("@malloydata/malloy"));
50
+ const faa_model_1 = require("../../models/faa_model");
51
+ const runtimes_1 = require("../../runtimes");
52
+ const util_1 = require("../../util");
53
+ const runtimeList = new runtimes_1.RuntimeList(['bigquery']);
54
+ const runtime = runtimeList.runtimeMap.get('bigquery');
55
+ if (runtime === undefined) {
56
+ throw new Error("Couldn't build runtime");
57
+ }
58
+ const bq = runtime.connection;
59
+ function compileQueryFromQueryDef(model, query) {
60
+ return model._loadQueryFromQueryDef(query).getSQL();
61
+ }
62
+ async function compileQuery(model, query) {
63
+ return await model.loadQuery(query).getSQL();
64
+ }
65
+ async function runQuery(model, query) {
66
+ return await model.loadQuery(query).run();
67
+ }
68
+ async function bqCompile(sql) {
69
+ try {
70
+ await bq.executeSQLRaw(`WITH test AS(\n${sql}) SELECT 1`);
71
+ }
72
+ catch (e) {
73
+ malloy.Malloy.log.error(`SQL: didn't compile\n=============\n${sql}`);
74
+ throw e;
75
+ }
76
+ return true;
77
+ }
78
+ const [describe] = (0, util_1.describeIfDatabaseAvailable)(['bigquery']);
79
+ describe('BigQuery expression tests', () => {
80
+ const faa = runtime._loadModelFromModelDef(faa_model_1.testModel);
81
+ it('simple_pipeline', async () => {
82
+ const sql = await compileQueryFromQueryDef(faa, {
83
+ structRef: 'flights',
84
+ pipeHead: { name: 'flights_by_carrier' },
85
+ pipeline: [{ fields: ['name', 'flight_count'], type: 'reduce' }],
86
+ });
87
+ await bqCompile(sql);
88
+ });
89
+ // EXPLORE flights
90
+ // ->{
91
+ // carrier,
92
+ // flight_count,
93
+ // routes is { origin_code, destination_code, route_flights is flight_count
94
+ // ORDER BY route_flights DESC
95
+ // LIMIT 5 )
96
+ // | PROJECT
97
+ // carrier,
98
+ // routes.origin_code,
99
+ // routes.route_flights,
100
+ // flight_count / routes.route_flights as percent_of_carrier_flights
101
+ it('turtle_requery', async () => {
102
+ const sql = await compileQueryFromQueryDef(faa, {
103
+ structRef: 'flights',
104
+ pipeline: [
105
+ // top 5 routes per carrier
106
+ {
107
+ type: 'reduce',
108
+ fields: [
109
+ 'carrier',
110
+ 'flight_count',
111
+ {
112
+ type: 'turtle',
113
+ name: 'routes',
114
+ pipeline: [
115
+ {
116
+ type: 'reduce',
117
+ fields: [
118
+ 'origin_code',
119
+ 'destination_code',
120
+ 'flight_count',
121
+ {
122
+ type: 'number',
123
+ name: 'route_flights',
124
+ expressionType: 'aggregate',
125
+ e: [
126
+ {
127
+ type: 'aggregate',
128
+ function: 'count',
129
+ e: [],
130
+ },
131
+ ],
132
+ },
133
+ ],
134
+ },
135
+ ],
136
+ },
137
+ ],
138
+ limit: 5,
139
+ orderBy: [{ dir: 'desc', field: 'carrier' }],
140
+ },
141
+ // carrier top routes
142
+ {
143
+ type: 'project',
144
+ fields: [
145
+ 'carrier',
146
+ 'flight_count',
147
+ 'routes.origin_code',
148
+ 'routes.route_flights',
149
+ ],
150
+ },
151
+ ],
152
+ });
153
+ await bqCompile(sql);
154
+ });
155
+ it('step_0', async () => {
156
+ const sql = await compileQueryFromQueryDef(faa, {
157
+ structRef: 'flights',
158
+ pipeline: [{ type: 'reduce', fields: ['carriers.name', 'flight_count'] }],
159
+ });
160
+ await bqCompile(sql);
161
+ });
162
+ it('filtered_measures', async () => {
163
+ const sql = await compileQueryFromQueryDef(faa, {
164
+ structRef: 'flights',
165
+ filterList: [
166
+ (0, util_1.fStringEq)('origin.state', 'CA'),
167
+ (0, util_1.fStringEq)('destination.state', 'NY'),
168
+ ],
169
+ pipeline: [{ type: 'reduce', fields: ['carriers.name', 'flight_count'] }],
170
+ });
171
+ await bqCompile(sql);
172
+ });
173
+ it('timestamp', async () => {
174
+ const sql = await compileQueryFromQueryDef(faa, {
175
+ structRef: 'flights',
176
+ pipeline: [
177
+ {
178
+ fields: [
179
+ {
180
+ as: 'dep_year',
181
+ name: 'dep_time',
182
+ timeframe: 'year',
183
+ type: 'timestamp',
184
+ },
185
+ {
186
+ as: 'dep_month',
187
+ name: 'dep_time',
188
+ timeframe: 'month',
189
+ type: 'timestamp',
190
+ },
191
+ {
192
+ as: 'dep_week',
193
+ name: 'dep_time',
194
+ timeframe: 'week',
195
+ type: 'timestamp',
196
+ },
197
+ {
198
+ as: 'dep_date',
199
+ name: 'dep_time',
200
+ timeframe: 'day',
201
+ type: 'timestamp',
202
+ },
203
+ {
204
+ as: 'dep_hour',
205
+ name: 'dep_time',
206
+ timeframe: 'hour',
207
+ type: 'timestamp',
208
+ },
209
+ {
210
+ as: 'dep_minute',
211
+ name: 'dep_time',
212
+ timeframe: 'minute',
213
+ type: 'timestamp',
214
+ },
215
+ {
216
+ as: 'dep_second',
217
+ name: 'dep_time',
218
+ timeframe: 'second',
219
+ type: 'timestamp',
220
+ },
221
+ {
222
+ type: 'number',
223
+ name: 'total_distance_ca',
224
+ expressionType: 'aggregate',
225
+ e: [
226
+ {
227
+ type: 'filterExpression',
228
+ filterList: [(0, util_1.fStringEq)('origin.state', 'CA')],
229
+ e: [
230
+ {
231
+ type: 'aggregate',
232
+ function: 'sum',
233
+ e: [{ type: 'field', path: 'distance' }],
234
+ },
235
+ ],
236
+ },
237
+ ],
238
+ },
239
+ ],
240
+ limit: 20,
241
+ type: 'reduce',
242
+ },
243
+ ],
244
+ });
245
+ await bqCompile(sql);
246
+ });
247
+ it('bucket_test', async () => {
248
+ const sql = await compileQueryFromQueryDef(faa, {
249
+ pipeline: [
250
+ {
251
+ fields: [
252
+ {
253
+ bucketFilter: 'AA,WN,DL',
254
+ bucketOther: 'Other Carrier',
255
+ name: 'carrier',
256
+ type: 'string',
257
+ },
258
+ 'flight_count',
259
+ ],
260
+ orderBy: [{ dir: 'asc', field: 2 }],
261
+ type: 'reduce',
262
+ },
263
+ ],
264
+ structRef: 'flights',
265
+ });
266
+ await bqCompile(sql);
267
+ });
268
+ it('flights_by_carrier', async () => {
269
+ const sql = await compileQuery(faa, 'query: flights->flights_by_carrier');
270
+ await bqCompile(sql);
271
+ });
272
+ it('simple_reduce', async () => {
273
+ const sql = await compileQueryFromQueryDef(faa, {
274
+ structRef: 'flights',
275
+ pipeline: [{ type: 'reduce', fields: ['carrier', 'flight_count'] }],
276
+ });
277
+ await bqCompile(sql);
278
+ });
279
+ it('two_sums', async () => {
280
+ const sql = await compileQueryFromQueryDef(faa, {
281
+ structRef: 'flights',
282
+ pipeline: [
283
+ {
284
+ type: 'reduce',
285
+ fields: [
286
+ {
287
+ type: 'number',
288
+ expressionType: 'aggregate',
289
+ name: 'total_distance',
290
+ e: [
291
+ {
292
+ type: 'aggregate',
293
+ function: 'sum',
294
+ e: [{ type: 'field', path: 'distance' }],
295
+ },
296
+ ],
297
+ },
298
+ 'aircraft.aircraft_models.total_seats',
299
+ ],
300
+ },
301
+ ],
302
+ });
303
+ await bqCompile(sql);
304
+ });
305
+ it('first_fragment', async () => {
306
+ const sql = await compileQueryFromQueryDef(faa, {
307
+ structRef: 'flights',
308
+ pipeline: [
309
+ {
310
+ type: 'reduce',
311
+ fields: [
312
+ {
313
+ type: 'string',
314
+ name: 'carrier',
315
+ e: ['UPPER(', { type: 'field', path: 'carriers.nickname' }, ')'],
316
+ },
317
+ 'flight_count',
318
+ ],
319
+ },
320
+ ],
321
+ });
322
+ await bqCompile(sql);
323
+ });
324
+ it('sum_in_expr', async () => {
325
+ const sql = await compileQueryFromQueryDef(faa, {
326
+ structRef: 'flights',
327
+ pipeline: [
328
+ {
329
+ fields: [
330
+ 'carriers.name',
331
+ {
332
+ type: 'number',
333
+ expressionType: 'aggregate',
334
+ name: 'total_distance',
335
+ e: [
336
+ {
337
+ type: 'aggregate',
338
+ function: 'sum',
339
+ e: [{ type: 'field', path: 'distance' }],
340
+ },
341
+ ],
342
+ },
343
+ ],
344
+ type: 'reduce',
345
+ },
346
+ ],
347
+ });
348
+ await bqCompile(sql);
349
+ });
350
+ it('filtered_sum_in_expr', async () => {
351
+ const sql = await compileQueryFromQueryDef(faa, {
352
+ structRef: 'flights',
353
+ pipeline: [
354
+ {
355
+ type: 'reduce',
356
+ fields: [
357
+ 'aircraft.aircraft_models.manufacturer',
358
+ {
359
+ type: 'number',
360
+ expressionType: 'aggregate',
361
+ name: 'total_distance',
362
+ e: [
363
+ {
364
+ type: 'filterExpression',
365
+ filterList: [(0, util_1.fStringEq)('origin_code', 'SFO')],
366
+ e: [
367
+ {
368
+ type: 'aggregate',
369
+ function: 'sum',
370
+ e: [{ type: 'field', path: 'distance' }],
371
+ },
372
+ ],
373
+ },
374
+ ],
375
+ },
376
+ ],
377
+ },
378
+ ],
379
+ });
380
+ await bqCompile(sql);
381
+ });
382
+ it('dynamic_measure', async () => {
383
+ const sql = await compileQueryFromQueryDef(faa, {
384
+ structRef: 'flights',
385
+ pipeline: [
386
+ {
387
+ type: 'reduce',
388
+ fields: [
389
+ 'origin.state',
390
+ 'flight_count',
391
+ {
392
+ type: 'number',
393
+ expressionType: 'aggregate',
394
+ name: 'total_distance',
395
+ e: [
396
+ {
397
+ type: 'filterExpression',
398
+ filterList: [(0, util_1.fStringEq)('origin_code', 'SFO')],
399
+ e: [
400
+ {
401
+ type: 'aggregate',
402
+ function: 'sum',
403
+ e: [{ type: 'field', path: 'distance' }],
404
+ },
405
+ ],
406
+ },
407
+ ],
408
+ },
409
+ ],
410
+ filterList: [(0, util_1.fStringEq)('carriers.code', 'WN')],
411
+ },
412
+ ],
413
+ });
414
+ await bqCompile(sql);
415
+ });
416
+ it('add_filter_to_named_query', async () => {
417
+ const sql = await compileQueryFromQueryDef(faa, {
418
+ structRef: 'flights',
419
+ filterList: [(0, util_1.fStringEq)('destination_code', 'AL')],
420
+ pipeHead: { name: 'flights_by_city_top_5' },
421
+ pipeline: [],
422
+ });
423
+ await bqCompile(sql);
424
+ });
425
+ it('flights.flights_by_model', async () => {
426
+ const sql = await compileQuery(faa, 'query: flights->flights_by_model');
427
+ await bqCompile(sql);
428
+ });
429
+ it('flights.aircraft_facts_test', async () => {
430
+ const sql = await compileQuery(faa, 'query: flights->aircraft_facts_test');
431
+ await bqCompile(sql);
432
+ });
433
+ it('flights.measures_first', async () => {
434
+ const sql = await compileQuery(faa, 'query:flights->measures_first');
435
+ await bqCompile(sql);
436
+ });
437
+ it('flights.carriers_by_total_engines', async () => {
438
+ const sql = await compileQuery(faa, 'query: flights->carriers_by_total_engines');
439
+ await bqCompile(sql);
440
+ });
441
+ it('flights.first_turtle', async () => {
442
+ const sql = await compileQuery(faa, 'query: flights->first_turtle');
443
+ await bqCompile(sql);
444
+ });
445
+ it('flights.top_5_routes_carriers', async () => {
446
+ const sql = await compileQuery(faa, 'query: flights->top_5_routes_carriers');
447
+ await bqCompile(sql);
448
+ });
449
+ it('flights.new_york_airports', async () => {
450
+ const sql = await compileQuery(faa, 'query: flights->new_york_airports');
451
+ await bqCompile(sql);
452
+ });
453
+ it('flights.flights_by_carrier_with_totals', async () => {
454
+ const sql = await compileQuery(faa, 'query: flights->flights_by_carrier_with_totals');
455
+ await bqCompile(sql);
456
+ });
457
+ it('lotsoturtles', async () => {
458
+ const sql = await compileQueryFromQueryDef(faa, {
459
+ structRef: 'flights',
460
+ pipeline: [
461
+ {
462
+ fields: [
463
+ 'origin.state',
464
+ 'flight_count',
465
+ 'flights_by_model',
466
+ 'flights_by_carrier',
467
+ 'measures_first',
468
+ 'first_turtle',
469
+ ],
470
+ type: 'reduce',
471
+ },
472
+ ],
473
+ });
474
+ await bqCompile(sql);
475
+ });
476
+ it('add_filter_to_def', async () => {
477
+ const sql = await compileQueryFromQueryDef(faa, {
478
+ structRef: 'flights',
479
+ filterList: [(0, util_1.fStringEq)('destination_code', 'AL')],
480
+ pipeHead: { name: 'flights_by_carrier_with_totals' },
481
+ pipeline: [
482
+ {
483
+ type: 'reduce',
484
+ fields: [
485
+ 'main.name',
486
+ 'main.flight_count',
487
+ {
488
+ name: 'total_flights',
489
+ type: 'number',
490
+ expressionType: 'scalar',
491
+ e: [{ type: 'field', path: 'totals.flight_count' }],
492
+ },
493
+ ],
494
+ },
495
+ ],
496
+ });
497
+ await bqCompile(sql);
498
+ });
499
+ it('flights.search_index', async () => {
500
+ const sql = await compileQuery(faa, 'query: flights->search_index');
501
+ await bqCompile(sql);
502
+ });
503
+ it('turtle_turtle_filter', async () => {
504
+ const result = await runQuery(faa, `
505
+ query: table('malloytest.airports')->{
506
+ where: faa_region ? ~'A%'
507
+ order_by: 1
508
+ group_by: faa_region
509
+ aggregate: airport_count is COUNT(*)
510
+ nest: state is {
511
+ where: state ?'CA'|'NY'
512
+ group_by: state
513
+ nest: code is {
514
+ where: major='Y'
515
+ top: 10
516
+ order_by: 1
517
+ group_by: code
518
+ }
519
+ }
520
+ }
521
+ -> {
522
+ where: state.code.code != null
523
+ group_by: state.code.code
524
+ }
525
+ `);
526
+ expect(result.data.value[0]['code']).toBe('ACV');
527
+ });
528
+ it('flights.search_index', async () => {
529
+ const sql = await compileQuery(faa, 'query: flights->search_index');
530
+ await bqCompile(sql);
531
+ });
532
+ it('medicare_test.turtle_city_zip', async () => {
533
+ const sql = await compileQuery(faa, 'query: medicare_test->turtle_city_zip');
534
+ await bqCompile(sql);
535
+ });
536
+ it('medicare_test.triple_turtle', async () => {
537
+ const sql = await compileQuery(faa, 'query: medicare_test->triple_turtle');
538
+ await bqCompile(sql);
539
+ });
540
+ it('medicare_test.rollup_by_location', async () => {
541
+ const sql = await compileQuery(faa, 'query: medicare_test->rollup_by_location');
542
+ await bqCompile(sql);
543
+ });
544
+ it('flights.flights_routes_sessionized', async () => {
545
+ const sql = await compileQuery(faa, 'query: flights->flights_routes_sessionized');
546
+ await bqCompile(sql);
547
+ });
548
+ it('flights.flights_aircraft_sessionized', async () => {
549
+ const sql = await compileQuery(faa, 'query: flights->flights_aircraft_sessionized');
550
+ await bqCompile(sql);
551
+ });
552
+ it('flights.flights_by_manufacturer', async () => {
553
+ const sql = await compileQuery(faa, 'query: flights->flights_by_manufacturer');
554
+ await bqCompile(sql);
555
+ });
556
+ it('flights.flights_by_carrier_2001_2002', async () => {
557
+ const sql = await compileQuery(faa, 'query: flights->flights_by_carrier_2001_2002');
558
+ await bqCompile(sql);
559
+ });
560
+ it('timeframes aliased', async () => {
561
+ const sql = await compileQuery(faa, `
562
+ query: flights->{
563
+ group_by: mon is dep_time.month
564
+ }
565
+ `);
566
+ await bqCompile(sql);
567
+ });
568
+ it('count distinct', async () => {
569
+ const sql = await compileQuery(faa, `
570
+ query: flights->{
571
+ aggregate: carrier_count is count(distinct carrier)
572
+ }
573
+ `);
574
+ // console.log(result.sql);
575
+ await bqCompile(sql);
576
+ });
577
+ it('table_base_on_query', async () => {
578
+ const result = await faa
579
+ ._loadQueryFromQueryDef({
580
+ structRef: 'medicare_state_facts',
581
+ pipeline: [
582
+ {
583
+ type: 'reduce',
584
+ fields: ['provider_state', 'num_providers'],
585
+ orderBy: [{ dir: 'desc', field: 2 }],
586
+ },
587
+ ],
588
+ })
589
+ .run();
590
+ expect(result.data.value[0]['num_providers']).toBe(296);
591
+ });
592
+ // const faa2: TestDeclaration[] = [
593
+ it('table_base_on_query2', async () => {
594
+ const result = await faa
595
+ ._loadQueryFromQueryDef({
596
+ structRef: {
597
+ type: 'struct',
598
+ name: 'malloy-data.malloytest.bq_medicare_test',
599
+ dialect: 'standardsql',
600
+ as: 'mtest',
601
+ structRelationship: {
602
+ type: 'basetable',
603
+ connectionName: 'bigquery',
604
+ },
605
+ structSource: {
606
+ type: 'table',
607
+ tablePath: 'malloy-data.malloytest.bq_medicare_test',
608
+ },
609
+ fields: [
610
+ {
611
+ type: 'number',
612
+ name: 'c',
613
+ expressionType: 'aggregate',
614
+ e: [{ type: 'aggregate', function: 'count', e: [] }],
615
+ },
616
+ {
617
+ type: 'turtle',
618
+ name: 'get_count',
619
+ pipeline: [{ type: 'reduce', fields: ['c'] }],
620
+ },
621
+ ],
622
+ },
623
+ pipeHead: { name: 'get_count' },
624
+ pipeline: [],
625
+ })
626
+ .run();
627
+ expect(result.data.value[0]['c']).toBe(202656);
628
+ });
629
+ });
630
+ const airportModelText = `
631
+ source: airports is table('malloy-data.malloytest.airports'){
632
+ primary_key: code
633
+ measure: airport_count is count(*)
634
+
635
+ query: by_fac_type is {
636
+ group_by: fac_type
637
+ aggregate: airport_count
638
+ }
639
+
640
+ query: by_state is {
641
+ group_by: state
642
+ aggregate: airport_count
643
+ }
644
+
645
+ query: by_county is {
646
+ group_by: county
647
+ aggregate: airport_count
648
+ }
649
+ }
650
+
651
+ query: ca_airports is airports->by_fac_type{? state ? 'CA' | 'NY'}
652
+ `;
653
+ describe('airport_tests', () => {
654
+ let model;
655
+ beforeAll(async () => {
656
+ model = runtime.loadModel(airportModelText);
657
+ });
658
+ it('airport_count', async () => {
659
+ const result = await runQuery(model, `
660
+ query: airports->{
661
+ aggregate: a is count(*)
662
+ }
663
+ `);
664
+ expect(result.data.value[0]['a']).toBe(19793);
665
+ });
666
+ it('turtle_from_hell', async () => {
667
+ const result = await runQuery(model, `
668
+ query: airports-> {
669
+ nest: zero is {
670
+ nest: by_faa_region_i is { where: county ~'I%' and state != NULL
671
+ group_by: faa_region
672
+ aggregate: airport_count
673
+ nest: by_state is {
674
+ group_by: state
675
+ aggregate: airport_count
676
+ nest: by_county is {
677
+ group_by: county
678
+ aggregate: airport_count
679
+ }
680
+ }
681
+ }
682
+ nest: by_faa_region_Z is { where: county ~'Z%' and state !=NULL
683
+ group_by: faa_region
684
+ aggregate: airport_count
685
+ nest: by_state is {
686
+ group_by: state
687
+ aggregate: airport_count
688
+ nest: by_county is {
689
+ group_by: county
690
+ aggregate: airport_count
691
+ }
692
+ }
693
+ }
694
+ }
695
+ } -> { limit: 1
696
+ project: zero.by_faa_region_Z.by_state.by_county.county
697
+ }
698
+
699
+ `);
700
+ expect(result.data.value[0]['county']).toBe('ZAVALA');
701
+ });
702
+ it('nested_project', async () => {
703
+ const result = await runQuery(model, `
704
+ query: airports -> {
705
+ group_by: county
706
+ nest: stuff is {
707
+ project: elevation
708
+ order_by: 1 desc
709
+ limit: 10
710
+ }
711
+ order_by: 1
712
+ } -> {
713
+ project: stuff.elevation
714
+ limit: 1
715
+ }
716
+ `);
717
+ expect(result.data.value[0]['elevation']).toBe(1836);
718
+ });
719
+ it('nested_sums', async () => {
720
+ const result = await runQuery(model, `
721
+ query: airports->{
722
+ aggregate: airport_count
723
+ nest: by_state is {
724
+ group_by: state
725
+ aggregate: airport_count
726
+ nest: by_fac_type is {
727
+ group_by: fac_type
728
+ aggregate: airport_count
729
+ }
730
+ }
731
+ } -> {
732
+ group_by: airport_count
733
+ aggregate:
734
+ sum_state is by_state.sum(by_state.airport_count),
735
+ sum_fac is by_state.by_fac_type.sum(by_state.by_fac_type.airport_count)
736
+ }
737
+ `);
738
+ // console.log(result.sql);
739
+ expect(result.data.value[0]['sum_state']).toBe(19793);
740
+ expect(result.data.value[0]['sum_fac']).toBe(19793);
741
+ });
742
+ it('pipeline_as_declared_turtle', async () => {
743
+ const result = await runQuery(model, `
744
+ source: my_airports is airports {
745
+ query: pipe_turtle is {
746
+ aggregate: a is airport_count
747
+ } -> {
748
+ project: a
749
+ }
750
+ }
751
+ query: my_airports->pipe_turtle
752
+ `);
753
+ expect(result.data.value[0]['a']).toBe(19793);
754
+ });
755
+ it('pipeline Turtle', async () => {
756
+ const result = await runQuery(model, `
757
+ query: table('malloytest.airports')->{
758
+ aggregate: airport_count is count()
759
+ nest: pipe_turtle is {
760
+ group_by:
761
+ state
762
+ county
763
+ aggregate: a is count()
764
+ } -> {
765
+ project:
766
+ state is upper(state)
767
+ a
768
+ } -> {
769
+ group_by: state
770
+ aggregate: total_airports is a.sum()
771
+ }
772
+ }
773
+ `);
774
+ expect(
775
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
776
+ result.data.value[0].pipe_turtle[0].total_airports).toBe(1845);
777
+ });
778
+ it.skip('crossjoined turtles', async () => {
779
+ // const result = await runQuery(model,`
780
+ // explore airports
781
+ // ->{
782
+ // top_seaplane is { limit 5 : [fac_type: 'SEAPLANE BASE']
783
+ // state
784
+ // airport_count
785
+ // )
786
+ // by_state is {
787
+ // state
788
+ // airport_count
789
+ // )
790
+ // | project : [top_seaplane.state = by_state.state]
791
+ // by_state.*
792
+ // `);
793
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
794
+ // expect((result.data.value[0] as any).pipe_turtle[0].total_airports).toBe(1845);
795
+ });
796
+ it.skip('crossjoined turtles as turtle', async () => {
797
+ // const result = await runQuery(model,`
798
+ // explore airports
799
+ // ->{
800
+ // airport_count
801
+ // tp is {
802
+ // top_seaplane is { limit 5 : [fac_type: 'SEAPLANE BASE']
803
+ // state
804
+ // airport_count
805
+ // )
806
+ // by_state is {
807
+ // state
808
+ // airport_count
809
+ // )
810
+ // | project : [top_seaplane.state = by_state.state]
811
+ // by_state.*
812
+ // )
813
+ // `);
814
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
815
+ // expect((result.data.value[0] as any).pipe_turtle[0].total_airports).toBe(1845);
816
+ });
817
+ it('string_expressions', async () => {
818
+ const result = await runQuery(model, `
819
+ query: airports->{
820
+ group_by: lower_state is lower(state)
821
+ order_by: 1 DESC
822
+ limit: 10
823
+ }
824
+ `);
825
+ expect(result.data.value[0]['lower_state']).toBe('wy');
826
+ });
827
+ it('half_count', async () => {
828
+ const result = await runQuery(model, `
829
+ query: airports->{
830
+ aggregate: half is airport_count/2.0
831
+ }
832
+ `);
833
+ expect(result.data.value[0]['half']).toBe(9896.5);
834
+ });
835
+ });
836
+ describe('sql injection tests', () => {
837
+ const model = runtime._loadModelFromModelDef(faa_model_1.testModel);
838
+ jest.setTimeout(100000);
839
+ (0, globals_1.test)('string literal escapes quotes', async () => {
840
+ const result = await runQuery(model, `
841
+ query: table('malloytest.state_facts')->{ group_by: test is 'foo\\''
842
+ }
843
+ `);
844
+ expect(result.data.value[0]['test']).toBe("foo'");
845
+ });
846
+ (0, globals_1.test)('string filter escapes quotes', async () => {
847
+ const result = await runQuery(model, `
848
+ query: table('malloytest.state_facts')->{ aggregate: test is count() {? state ? 'foo\\'' } }
849
+ `);
850
+ expect(result.data.value[0]['test']).toBe(0);
851
+ });
852
+ (0, globals_1.test)('string literal escapes backslashes', async () => {
853
+ const result = await runQuery(model, `
854
+ query: table('malloytest.state_facts')->{ group_by: test is 'foo\\\\\\''
855
+ }
856
+ `);
857
+ expect(result.data.value[0]['test']).toBe("foo\\'");
858
+ });
859
+ (0, globals_1.test)('string filter escapes backslashes', async () => {
860
+ const result = await runQuery(model, `
861
+ query: table('malloytest.state_facts')->{ aggregate: test is count() {? state ? 'foo\\\\\\'' }}
862
+ `);
863
+ expect(result.data.value[0]['test']).toBe(0);
864
+ });
865
+ (0, globals_1.test)('comment in string', async () => {
866
+ const result = await runQuery(model, `
867
+ query: table('malloytest.state_facts')->{ group_by: test is 'foo \\\\'--'
868
+ }
869
+ `);
870
+ expect(result.data.value[0]['test']).toBe('foo \\');
871
+ });
872
+ (0, globals_1.test)('comment in string filter', async () => {
873
+ let error;
874
+ try {
875
+ await runQuery(model, `
876
+ query: table('malloytest.state_facts')->{ aggregate: test is count() {? state ? 'foo \\\\' THEN 0 else 1 END) as test--'
877
+ }} `);
878
+ }
879
+ catch (e) {
880
+ error = e;
881
+ }
882
+ expect(error).not.toBeUndefined();
883
+ });
884
+ globals_1.test.todo("'malloytest\\'.tables' produces the wrong error...");
885
+ (0, globals_1.test)('comment in literal', async () => {
886
+ const result = await runQuery(model, `
887
+ query: flights->{ group_by: test is 'foo \\\\'--'
888
+ }
889
+ `);
890
+ expect(result.data.value[0]['test']).toBe('foo \\');
891
+ });
892
+ });
893
+ describe('unsupported type tests', () => {
894
+ it('can read unsupported types in schema', async () => {
895
+ const result = await runtime
896
+ .loadQuery(`
897
+ sql: badType is {
898
+ select: """SELECT ST_GEOGFROMTEXT('LINESTRING(1 2, 3 4)') as geo"""
899
+ }
900
+ query: from_sql(badType)->{ project: *}
901
+ `)
902
+ .run();
903
+ expect(result.data.value[0]['geo']).toBeDefined();
904
+ });
905
+ });
906
+ //# sourceMappingURL=malloy_query.spec.js.map