@malloydata/malloy-tests 0.0.298 → 0.0.300
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.
- package/package.json +9 -9
- package/src/core/api.spec.ts +16 -0
- package/src/databases/all/orderby.spec.ts +2 -2
- package/src/databases/bigquery/handexpr.spec.ts +255 -726
- package/src/databases/bigquery/malloy_query.spec.ts +165 -317
- package/src/models/faa_model.ts +275 -883
- package/src/models/medicare_model.ts +69 -231
- package/src/util/index.ts +0 -61
|
@@ -22,28 +22,21 @@
|
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
import {test} from '@jest/globals';
|
|
25
|
-
import * as malloy from '@malloydata/malloy';
|
|
26
|
-
import type {Query} from '@malloydata/malloy';
|
|
25
|
+
import type * as malloy from '@malloydata/malloy';
|
|
27
26
|
import {testModel} from '../../models/faa_model';
|
|
28
27
|
import type {BigQueryTestConnection} from '../../runtimes';
|
|
29
28
|
import {RuntimeList} from '../../runtimes';
|
|
30
|
-
import {describeIfDatabaseAvailable
|
|
29
|
+
import {describeIfDatabaseAvailable} from '../../util';
|
|
31
30
|
import '../../util/db-jest-matchers';
|
|
32
31
|
|
|
33
|
-
const
|
|
34
|
-
const
|
|
32
|
+
const bigquery = 'bigquery';
|
|
33
|
+
const runtimeList = new RuntimeList([bigquery]);
|
|
34
|
+
const runtime = runtimeList.runtimeMap.get(bigquery);
|
|
35
35
|
if (runtime === undefined) {
|
|
36
36
|
throw new Error('BigQuery runtime not found');
|
|
37
37
|
}
|
|
38
38
|
const bq = runtime.connection as BigQueryTestConnection;
|
|
39
39
|
|
|
40
|
-
function compileQueryFromQueryDef(
|
|
41
|
-
model: malloy.ModelMaterializer,
|
|
42
|
-
query: Query
|
|
43
|
-
) {
|
|
44
|
-
return model._loadQueryFromQueryDef(query).getSQL();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
40
|
async function compileQuery(model: malloy.ModelMaterializer, query: string) {
|
|
48
41
|
return await model.loadQuery(query).getSQL();
|
|
49
42
|
}
|
|
@@ -57,10 +50,10 @@ async function bqCompile(sql: string): Promise<boolean> {
|
|
|
57
50
|
return true;
|
|
58
51
|
}
|
|
59
52
|
|
|
60
|
-
const [describe] = describeIfDatabaseAvailable([
|
|
53
|
+
const [describe] = describeIfDatabaseAvailable([bigquery]);
|
|
61
54
|
|
|
62
55
|
describe('BigQuery expression tests', () => {
|
|
63
|
-
const faa = runtime.
|
|
56
|
+
const faa = runtime.loadModel(testModel);
|
|
64
57
|
|
|
65
58
|
// EXPLORE flights
|
|
66
59
|
// ->{
|
|
@@ -75,170 +68,101 @@ describe('BigQuery expression tests', () => {
|
|
|
75
68
|
// routes.route_flights,
|
|
76
69
|
// flight_count / routes.route_flights as percent_of_carrier_flights
|
|
77
70
|
it('turtle_requery', async () => {
|
|
78
|
-
const sql = await
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
]),
|
|
104
|
-
},
|
|
105
|
-
],
|
|
106
|
-
},
|
|
107
|
-
]),
|
|
108
|
-
limit: 5,
|
|
109
|
-
orderBy: [{dir: 'desc', field: 'carrier'}],
|
|
110
|
-
},
|
|
111
|
-
// carrier top routes
|
|
112
|
-
{
|
|
113
|
-
type: 'project',
|
|
114
|
-
queryFields: fToQF([
|
|
115
|
-
'carrier',
|
|
116
|
-
'flight_count',
|
|
117
|
-
'routes.origin_code',
|
|
118
|
-
'routes.route_flights',
|
|
119
|
-
]),
|
|
120
|
-
},
|
|
121
|
-
],
|
|
122
|
-
});
|
|
123
|
-
await bqCompile(sql);
|
|
71
|
+
const sql = await compileQuery(
|
|
72
|
+
faa,
|
|
73
|
+
`
|
|
74
|
+
run: flights -> {
|
|
75
|
+
group_by: carrier
|
|
76
|
+
aggregate: flight_count
|
|
77
|
+
nest: routes is {
|
|
78
|
+
group_by:
|
|
79
|
+
origin_code
|
|
80
|
+
destination_code
|
|
81
|
+
aggregate: flight_count
|
|
82
|
+
aggregate: route_flights is count()
|
|
83
|
+
}
|
|
84
|
+
limit: 5
|
|
85
|
+
order_by: carrier desc
|
|
86
|
+
} -> {
|
|
87
|
+
select:
|
|
88
|
+
carrier
|
|
89
|
+
flight_count
|
|
90
|
+
routes.origin_code
|
|
91
|
+
routes.route_flights
|
|
92
|
+
}
|
|
93
|
+
`
|
|
94
|
+
);
|
|
95
|
+
bqCompile(sql);
|
|
124
96
|
});
|
|
125
97
|
|
|
126
98
|
it('step_0', async () => {
|
|
127
|
-
const sql = await
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
99
|
+
const sql = await compileQuery(
|
|
100
|
+
faa,
|
|
101
|
+
`
|
|
102
|
+
run: flights -> {
|
|
103
|
+
group_by: carriers.name
|
|
104
|
+
aggregate: flight_count
|
|
105
|
+
}
|
|
106
|
+
`
|
|
107
|
+
);
|
|
133
108
|
await bqCompile(sql);
|
|
134
109
|
});
|
|
135
110
|
|
|
136
111
|
it('filtered_measures', async () => {
|
|
137
|
-
const sql = await
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
112
|
+
const sql = await compileQuery(
|
|
113
|
+
faa,
|
|
114
|
+
`
|
|
115
|
+
run: flights -> {
|
|
116
|
+
// TODO previously this filter list was just on the QUERY
|
|
117
|
+
// which can't even have a filter list; I assume it's meant that
|
|
118
|
+
// these should be applied to the aggregate...
|
|
119
|
+
where: origin.state = 'CA'
|
|
120
|
+
where: destination.state = 'NY'
|
|
121
|
+
group_by: carriers.name
|
|
122
|
+
aggregate: flight_count
|
|
123
|
+
}
|
|
124
|
+
`
|
|
125
|
+
);
|
|
147
126
|
await bqCompile(sql);
|
|
148
127
|
});
|
|
149
128
|
|
|
150
129
|
it('timestamp', async () => {
|
|
151
|
-
const sql = await
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
{
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
name: 'dep_time',
|
|
171
|
-
timeframe: 'week',
|
|
172
|
-
type: 'timestamp',
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
as: 'dep_date',
|
|
176
|
-
name: 'dep_time',
|
|
177
|
-
timeframe: 'day',
|
|
178
|
-
type: 'timestamp',
|
|
179
|
-
},
|
|
180
|
-
{
|
|
181
|
-
as: 'dep_hour',
|
|
182
|
-
name: 'dep_time',
|
|
183
|
-
timeframe: 'hour',
|
|
184
|
-
type: 'timestamp',
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
as: 'dep_minute',
|
|
188
|
-
name: 'dep_time',
|
|
189
|
-
timeframe: 'minute',
|
|
190
|
-
type: 'timestamp',
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
as: 'dep_second',
|
|
194
|
-
name: 'dep_time',
|
|
195
|
-
timeframe: 'second',
|
|
196
|
-
type: 'timestamp',
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
type: 'number',
|
|
200
|
-
name: 'total_distance_ca',
|
|
201
|
-
expressionType: 'aggregate',
|
|
202
|
-
e: {
|
|
203
|
-
node: 'filteredExpr',
|
|
204
|
-
kids: {
|
|
205
|
-
filterList: [fStringEq('origin.state', 'CA')],
|
|
206
|
-
e: {
|
|
207
|
-
node: 'aggregate',
|
|
208
|
-
function: 'sum',
|
|
209
|
-
e: {node: 'field', path: ['distance']},
|
|
210
|
-
},
|
|
211
|
-
},
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
],
|
|
215
|
-
limit: 20,
|
|
216
|
-
type: 'reduce',
|
|
217
|
-
},
|
|
218
|
-
],
|
|
219
|
-
});
|
|
130
|
+
const sql = await compileQuery(
|
|
131
|
+
faa,
|
|
132
|
+
`
|
|
133
|
+
run: flights -> {
|
|
134
|
+
group_by:
|
|
135
|
+
dep_year is dep_time.year
|
|
136
|
+
dep_month is dep_time.month
|
|
137
|
+
dep_week is dep_time.week
|
|
138
|
+
dep_date is dep_time.day
|
|
139
|
+
dep_hour is dep_time.hour
|
|
140
|
+
dep_minute is dep_time.minute
|
|
141
|
+
dep_second is dep_time.second
|
|
142
|
+
aggregate: total_distance_ca is distance.sum() {
|
|
143
|
+
where: origin.state = 'CA'
|
|
144
|
+
}
|
|
145
|
+
limit: 20
|
|
146
|
+
}
|
|
147
|
+
`
|
|
148
|
+
);
|
|
220
149
|
await bqCompile(sql);
|
|
221
150
|
});
|
|
222
151
|
|
|
223
152
|
it('bucket_test', async () => {
|
|
224
|
-
const sql = await
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
type: 'reduce',
|
|
238
|
-
},
|
|
239
|
-
],
|
|
240
|
-
structRef: 'flights',
|
|
241
|
-
});
|
|
153
|
+
const sql = await compileQuery(
|
|
154
|
+
faa,
|
|
155
|
+
// TODO bucketFilter and bucketOther don't actually exist...
|
|
156
|
+
// bucketFilter: 'AA,WN,DL',
|
|
157
|
+
// bucketOther: 'Other Carrier',
|
|
158
|
+
`
|
|
159
|
+
run: flights -> {
|
|
160
|
+
group_by: carrier
|
|
161
|
+
aggregate: flight_count
|
|
162
|
+
order_by: 2 asc
|
|
163
|
+
}
|
|
164
|
+
`
|
|
165
|
+
);
|
|
242
166
|
await bqCompile(sql);
|
|
243
167
|
});
|
|
244
168
|
|
|
@@ -248,150 +172,81 @@ describe('BigQuery expression tests', () => {
|
|
|
248
172
|
});
|
|
249
173
|
|
|
250
174
|
it('simple_reduce', async () => {
|
|
251
|
-
const sql = await
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
],
|
|
256
|
-
});
|
|
175
|
+
const sql = await compileQuery(
|
|
176
|
+
faa,
|
|
177
|
+
'run: flights -> { group_by: carrier; aggregate: flight_count }'
|
|
178
|
+
);
|
|
257
179
|
await bqCompile(sql);
|
|
258
180
|
});
|
|
259
181
|
|
|
260
182
|
it('two_sums', async () => {
|
|
261
|
-
const sql = await
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
{
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
name: 'total_distance',
|
|
271
|
-
e: {
|
|
272
|
-
node: 'aggregate',
|
|
273
|
-
function: 'sum',
|
|
274
|
-
e: {node: 'field', path: ['distance']},
|
|
275
|
-
},
|
|
276
|
-
},
|
|
277
|
-
'aircraft.aircraft_models.total_seats',
|
|
278
|
-
]),
|
|
279
|
-
},
|
|
280
|
-
],
|
|
281
|
-
});
|
|
183
|
+
const sql = await compileQuery(
|
|
184
|
+
faa,
|
|
185
|
+
`
|
|
186
|
+
run: flights -> {
|
|
187
|
+
aggregate: aircraft.aircraft_models.total_seats
|
|
188
|
+
aggregate: total_distance is distance.sum()
|
|
189
|
+
}
|
|
190
|
+
`
|
|
191
|
+
);
|
|
282
192
|
await bqCompile(sql);
|
|
283
193
|
});
|
|
284
194
|
|
|
285
195
|
it('first_fragment', async () => {
|
|
286
|
-
const sql = await
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
{
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
e: malloy.composeSQLExpr([
|
|
296
|
-
'UPPER(',
|
|
297
|
-
{node: 'field', path: ['carriers', 'nickname']},
|
|
298
|
-
')',
|
|
299
|
-
]),
|
|
300
|
-
},
|
|
301
|
-
'flight_count',
|
|
302
|
-
]),
|
|
303
|
-
},
|
|
304
|
-
],
|
|
305
|
-
});
|
|
196
|
+
const sql = await compileQuery(
|
|
197
|
+
faa,
|
|
198
|
+
`
|
|
199
|
+
run: flights -> {
|
|
200
|
+
group_by: carrier is upper(carriers.nickname)
|
|
201
|
+
aggregate: flight_count
|
|
202
|
+
}
|
|
203
|
+
`
|
|
204
|
+
);
|
|
306
205
|
await bqCompile(sql);
|
|
307
206
|
});
|
|
308
207
|
|
|
309
208
|
it('sum_in_expr', async () => {
|
|
310
|
-
const sql = await
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
{
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
name: 'total_distance',
|
|
320
|
-
e: {
|
|
321
|
-
node: 'aggregate',
|
|
322
|
-
function: 'sum',
|
|
323
|
-
e: {node: 'field', path: ['distance']},
|
|
324
|
-
},
|
|
325
|
-
},
|
|
326
|
-
]),
|
|
327
|
-
type: 'reduce',
|
|
328
|
-
},
|
|
329
|
-
],
|
|
330
|
-
});
|
|
209
|
+
const sql = await compileQuery(
|
|
210
|
+
faa,
|
|
211
|
+
`
|
|
212
|
+
run: flights -> {
|
|
213
|
+
group_by: carriers.name
|
|
214
|
+
aggregate: total_distance is distance.sum()
|
|
215
|
+
}
|
|
216
|
+
`
|
|
217
|
+
);
|
|
331
218
|
await bqCompile(sql);
|
|
332
219
|
});
|
|
333
220
|
|
|
334
221
|
it('filtered_sum_in_expr', async () => {
|
|
335
|
-
const sql = await
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
{
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
'
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
e: {
|
|
347
|
-
node: 'filteredExpr',
|
|
348
|
-
kids: {
|
|
349
|
-
filterList: [fStringEq('origin_code', 'SFO')],
|
|
350
|
-
e: {
|
|
351
|
-
node: 'aggregate',
|
|
352
|
-
function: 'sum',
|
|
353
|
-
e: {node: 'field', path: ['distance']},
|
|
354
|
-
},
|
|
355
|
-
},
|
|
356
|
-
},
|
|
357
|
-
},
|
|
358
|
-
]),
|
|
359
|
-
},
|
|
360
|
-
],
|
|
361
|
-
});
|
|
222
|
+
const sql = await compileQuery(
|
|
223
|
+
faa,
|
|
224
|
+
`
|
|
225
|
+
run: flights -> {
|
|
226
|
+
group_by: aircraft.aircraft_models.manufacturer
|
|
227
|
+
aggregate: total_distance is distance.sum() {
|
|
228
|
+
where: origin_code = 'SFO'
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
`
|
|
232
|
+
);
|
|
362
233
|
await bqCompile(sql);
|
|
363
234
|
});
|
|
364
235
|
|
|
365
236
|
it('dynamic_measure', async () => {
|
|
366
|
-
const sql = await
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
{
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
node: 'filteredExpr',
|
|
380
|
-
kids: {
|
|
381
|
-
filterList: [fStringEq('origin_code', 'SFO')],
|
|
382
|
-
e: {
|
|
383
|
-
node: 'aggregate',
|
|
384
|
-
function: 'sum',
|
|
385
|
-
e: {node: 'field', path: ['distance']},
|
|
386
|
-
},
|
|
387
|
-
},
|
|
388
|
-
},
|
|
389
|
-
},
|
|
390
|
-
]),
|
|
391
|
-
filterList: [fStringEq('carriers.code', 'WN')],
|
|
392
|
-
},
|
|
393
|
-
],
|
|
394
|
-
});
|
|
237
|
+
const sql = await compileQuery(
|
|
238
|
+
faa,
|
|
239
|
+
`
|
|
240
|
+
run: flights -> {
|
|
241
|
+
where: carriers.code = 'WN'
|
|
242
|
+
group_by: origin.state
|
|
243
|
+
aggregate: flight_count
|
|
244
|
+
aggregate: total_distance is distance.sum() {
|
|
245
|
+
where: origin_code = 'SFO'
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
`
|
|
249
|
+
);
|
|
395
250
|
await bqCompile(sql);
|
|
396
251
|
});
|
|
397
252
|
|
|
@@ -442,22 +297,20 @@ describe('BigQuery expression tests', () => {
|
|
|
442
297
|
});
|
|
443
298
|
|
|
444
299
|
it('lotsoturtles', async () => {
|
|
445
|
-
const sql = await
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
{
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
],
|
|
460
|
-
});
|
|
300
|
+
const sql = await compileQuery(
|
|
301
|
+
faa,
|
|
302
|
+
`
|
|
303
|
+
run: flights -> {
|
|
304
|
+
group_by: origin.state
|
|
305
|
+
aggregate: flight_count
|
|
306
|
+
nest:
|
|
307
|
+
flights_by_model
|
|
308
|
+
flights_by_carrier
|
|
309
|
+
measures_first
|
|
310
|
+
first_turtle
|
|
311
|
+
}
|
|
312
|
+
`
|
|
313
|
+
);
|
|
461
314
|
await bqCompile(sql);
|
|
462
315
|
});
|
|
463
316
|
|
|
@@ -576,19 +429,14 @@ describe('BigQuery expression tests', () => {
|
|
|
576
429
|
});
|
|
577
430
|
|
|
578
431
|
it('table_base_on_query', async () => {
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
},
|
|
588
|
-
],
|
|
589
|
-
})
|
|
590
|
-
.run();
|
|
591
|
-
expect(result.data.value[0]['num_providers']).toBe(296);
|
|
432
|
+
expect(`
|
|
433
|
+
run: medicare_state_facts -> {
|
|
434
|
+
group_by:
|
|
435
|
+
provider_state
|
|
436
|
+
num_providers
|
|
437
|
+
order_by: 2 desc
|
|
438
|
+
}
|
|
439
|
+
`).malloyResultMatches(faa, {num_providers: 296});
|
|
592
440
|
});
|
|
593
441
|
});
|
|
594
442
|
|
|
@@ -820,7 +668,7 @@ describe('airport_tests', () => {
|
|
|
820
668
|
});
|
|
821
669
|
|
|
822
670
|
describe('sql injection tests', () => {
|
|
823
|
-
const model = runtime.
|
|
671
|
+
const model = runtime.loadModel(testModel);
|
|
824
672
|
jest.setTimeout(100000);
|
|
825
673
|
|
|
826
674
|
test('string literal escapes quotes', async () => {
|