@malloydata/malloy-tests 0.0.299 → 0.0.301

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.
@@ -23,746 +23,275 @@
23
23
 
24
24
  /* eslint-disable no-console */
25
25
 
26
- import type {ModelDef, Query, StructDef} from '@malloydata/malloy';
27
- import {describeIfDatabaseAvailable, fStringLike, fToQF} from '../../util';
26
+ import {describeIfDatabaseAvailable} from '../../util';
27
+ import '../../util/db-jest-matchers';
28
28
 
29
- import * as malloy from '@malloydata/malloy';
30
29
  import {RuntimeList} from '../../runtimes';
31
- const [describe] = describeIfDatabaseAvailable(['bigquery']);
32
-
33
- describe('BigQuery hand-built expression test', () => {
34
- const runtimes = new RuntimeList(['bigquery']);
35
-
36
- afterAll(async () => {
37
- await runtimes.closeAll();
38
- });
39
-
40
- function withJoin(
41
- sd: malloy.TableSourceDef,
42
- join: 'one' | 'many',
43
- as: string,
44
- keyExpr: string
45
- ): malloy.JoinFieldDef {
46
- const [leftKey, rightKey] = keyExpr.split('=');
47
- const ret: malloy.JoinFieldDef = {
48
- ...sd,
49
- join,
50
- onExpression: {
51
- node: '=',
52
- kids: {
53
- left: {node: 'field', path: leftKey.split('.')},
54
- right: {node: 'field', path: rightKey.split('.')},
55
- },
56
- },
57
- };
58
- if (as !== ret.name) {
59
- ret.as = as;
60
- }
61
- return ret;
62
- }
63
30
 
64
- async function validateCompilation(
65
- databaseName: string,
66
- sql: string
67
- ): Promise<boolean> {
68
- try {
69
- const runtime = runtimes.runtimeMap.get(databaseName);
70
- if (runtime === undefined) {
71
- throw new Error(`Unknown database ${databaseName}`);
31
+ const [describe, databases] = describeIfDatabaseAvailable(['bigquery']);
32
+
33
+ const runtimes = new RuntimeList(databases);
34
+ describe.each(runtimes.runtimeList)(
35
+ 'Used to be hand-written queries tests',
36
+ (databaseName, runtime) => {
37
+ const runtimes = new RuntimeList(['duckdb']);
38
+
39
+ afterAll(async () => {
40
+ await runtimes.closeAll();
41
+ });
42
+
43
+ const makeModel = (databaseName: string) => `
44
+ source: aircraft_models is ${databaseName}.table('malloytest.aircraft_models') extend {
45
+ measure: model_count is count()
46
+ measure: total_seats is seats.sum()
47
+ measure: boeing_seats is seats.sum() { where: manufacturer = 'BOEING' }
48
+ measure: percent_boeing is (boeing_seats / total_seats) * 100
49
+ measure: percent_boeing_floor is floor(percent_boeing)
50
+ primary_key: aircraft_model_code
72
51
  }
73
- await (
74
- await runtime.connections.lookupConnection(databaseName)
75
- ).runSQL(`WITH test AS(\n${sql}) SELECT 1`);
76
- } catch (e) {
77
- console.log(`SQL: didn't compile\n=============\n${sql}`);
78
- throw e;
79
- }
80
- return true;
81
- }
82
52
 
83
- function compileHandQueryToSQL(
84
- model: malloy.ModelMaterializer,
85
- queryDef: Query
86
- ): Promise<string> {
87
- return model._loadQueryFromQueryDef(queryDef).getSQL();
88
- }
53
+ source: aircraft is ${databaseName}.table('malloytest.aircraft') extend {
54
+ measure: aircraft_count is count()
89
55
 
90
- const modelHandBase: malloy.TableSourceDef = {
91
- name: 'malloydata-org.malloytest.aircraft_models',
92
- as: 'aircraft_models',
93
- type: 'table',
94
- dialect: 'standardsql',
95
- tablePath: 'malloydata-org.malloytest.aircraft_models',
96
- connection: 'bigquery',
97
- fields: [
98
- {type: 'string', name: 'aircraft_model_code'},
99
- {type: 'string', name: 'manufacturer'},
100
- {type: 'string', name: 'model'},
101
- {type: 'number', name: 'aircraft_type_id', numberType: 'integer'},
102
- {
103
- type: 'number',
104
- name: 'aircraft_engine_type_id',
105
- numberType: 'integer',
106
- },
107
- {
108
- type: 'number',
109
- name: 'aircraft_category_id',
110
- numberType: 'integer',
111
- },
112
- {type: 'number', name: 'amateur', numberType: 'integer'},
113
- {type: 'number', name: 'engines', numberType: 'integer'},
114
- {type: 'number', name: 'seats', numberType: 'integer'},
115
- {type: 'number', name: 'weight', numberType: 'integer'},
116
- {type: 'number', name: 'speed', numberType: 'integer'},
117
- {
118
- name: 'model_count',
119
- type: 'number',
120
- e: {node: 'aggregate', function: 'count', e: {node: ''}},
121
- expressionType: 'aggregate',
122
- numberType: 'float',
123
- },
124
- {
125
- name: 'total_seats',
126
- type: 'number',
127
- e: {
128
- node: 'aggregate',
129
- function: 'sum',
130
- e: {node: 'field', path: ['seats']},
131
- },
132
- expressionType: 'aggregate',
133
- numberType: 'float',
134
- },
135
- {
136
- name: 'boeing_seats',
137
- type: 'number',
138
- expressionType: 'aggregate',
139
- e: {
140
- node: 'filteredExpr',
141
- kids: {
142
- e: {
143
- node: 'aggregate',
144
- function: 'sum',
145
- e: {node: 'field', path: ['seats']},
146
- },
147
- filterList: [
148
- {
149
- node: 'filterCondition',
150
- expressionType: 'aggregate',
151
- code: "manufacturer='BOEING'",
152
- e: {
153
- node: '=',
154
- kids: {
155
- left: {node: 'field', path: ['manufacturer']},
156
- right: {node: 'stringLiteral', literal: 'BOEING'},
157
- },
158
- },
159
- },
160
- ],
161
- },
162
- },
163
- numberType: 'float',
164
- },
165
- {
166
- name: 'percent_boeing',
167
- type: 'number',
168
- e: malloy.composeSQLExpr([
169
- '(',
170
- {node: 'field', path: ['boeing_seats']},
171
- '/',
172
- {node: 'field', path: ['total_seats']},
173
- ')*100',
174
- ]),
175
- expressionType: 'aggregate',
176
- numberType: 'float',
177
- },
178
- {
179
- name: 'percent_boeing_floor',
180
- type: 'number',
181
- expressionType: 'aggregate',
182
- e: malloy.composeSQLExpr([
183
- 'FLOOR(',
184
- {node: 'field', path: ['percent_boeing']},
185
- ')',
186
- ]),
187
- numberType: 'float',
188
- },
189
- ],
190
- primaryKey: 'aircraft_model_code',
191
- };
192
-
193
- const aircraftHandBase: StructDef = {
194
- name: 'malloydata-org.malloytest.aircraft',
195
- dialect: 'standardsql',
196
- type: 'table',
197
- tablePath: 'malloydata-org.malloytest.aircraft',
198
- connection: 'bigquery',
199
- fields: [
200
- {type: 'string', name: 'tail_num'},
201
- {type: 'string', name: 'aircraft_serial'},
202
- {type: 'string', name: 'aircraft_model_code'},
203
- {type: 'string', name: 'aircraft_engine_code'},
204
- {type: 'number', name: 'year_built', numberType: 'integer'},
205
- {type: 'number', name: 'aircraft_type_id', numberType: 'integer'},
206
- {
207
- type: 'number',
208
- name: 'aircraft_engine_type_id',
209
- numberType: 'integer',
210
- },
211
- {
212
- type: 'number',
213
- name: 'registrant_type_id',
214
- numberType: 'integer',
215
- },
216
- {type: 'string', name: 'name'},
217
- {type: 'string', name: 'address1'},
218
- {type: 'string', name: 'address2'},
219
- {type: 'string', name: 'city'},
220
- {type: 'string', name: 'state'},
221
- {type: 'string', name: 'zip'},
222
- {type: 'string', name: 'region'},
223
- {type: 'string', name: 'county'},
224
- {type: 'string', name: 'country'},
225
- {type: 'string', name: 'certification'},
226
- {type: 'string', name: 'status_code'},
227
- {type: 'string', name: 'mode_s_code'},
228
- {type: 'string', name: 'fract_owner'},
229
- {type: 'date', name: 'last_action_date'},
230
- {type: 'date', name: 'cert_issue_date'},
231
- {type: 'date', name: 'air_worth_date'},
232
- {
233
- name: 'aircraft_count',
234
- type: 'number',
235
- e: {node: 'aggregate', function: 'count', e: {node: ''}},
236
- expressionType: 'aggregate',
237
- numberType: 'float',
238
- },
239
- {
240
- type: 'turtle',
241
- name: 'hand_turtle',
242
- pipeline: [{type: 'reduce', queryFields: fToQF(['aircraft_count'])}],
243
- },
244
- {
245
- type: 'turtle',
246
- name: 'hand_turtle_pipeline',
247
- pipeline: [
248
- {type: 'reduce', queryFields: fToQF(['aircraft_count'])},
249
- {type: 'reduce', queryFields: fToQF(['aircraft_count'])},
250
- ],
251
- },
252
- withJoin(
253
- modelHandBase,
254
- 'one',
255
- 'aircraft_models',
256
- 'aircraft_model_code=aircraft_models.aircraft_model_code'
257
- ),
258
- ],
259
- primaryKey: 'tail_num',
260
- as: 'aircraft',
261
- };
262
-
263
- const handCodedModel: ModelDef = {
264
- name: 'Hand Coded Models',
265
- exports: ['aircraft'],
266
- contents: {
267
- aircraft: aircraftHandBase,
268
- },
269
- queryList: [],
270
- dependencies: {},
271
- };
272
-
273
- // BigQuery tests only on the Hand Coded models.
274
- const bqRuntime = runtimes.runtimeMap.get('bigquery');
275
- if (!bqRuntime) {
276
- throw new Error("Can't create bigquery RUntime");
277
- }
56
+ view: hand_turtle is { aggregate: aircraft_count }
278
57
 
279
- const handModel = bqRuntime._loadModelFromModelDef(handCodedModel);
280
- const databaseName = 'bigquery';
281
-
282
- it(`hand query hand model - ${databaseName}`, async () => {
283
- const sql = await compileHandQueryToSQL(handModel, {
284
- structRef: 'aircraft',
285
- pipeline: [
286
- {
287
- type: 'reduce',
288
- queryFields: [
289
- // "aircraft_models.total_seats",
290
- // "aircraft_models.boeing_seats"
291
- // "aircraft_models.percent_boeing",
292
- // {
293
- // type: "number",
294
- // name: "my_boeing_seats",
295
- // aggregate: true,
296
- // e: [
297
- // {
298
- // type: "filterExpression",
299
- // fieldDef e: [{ type: "field", path: "aircraft_models.total_seats" }],
300
- // },
301
- // ],
302
- // },
303
- {
304
- name: 'total_seats',
305
- type: 'number',
306
- expressionType: 'aggregate',
307
- e: {
308
- node: 'filteredExpr',
309
- kids: {
310
- e: {
311
- node: 'aggregate',
312
- function: 'sum',
313
- e: {node: 'field', path: ['aircraft_models', 'seats']},
314
- },
315
- filterList: [
316
- {
317
- node: 'filterCondition',
318
- expressionType: 'aggregate',
319
- code: "manufacturer='BOEING'",
320
- e: malloy.composeSQLExpr([
321
- {
322
- node: 'field',
323
- path: ['aircraft_models', 'manufacturer'],
324
- },
325
- "='BOEING'",
326
- ]),
327
- },
328
- ],
329
- },
330
- },
331
- },
332
- // {
333
- // name: "aircraft_models.total_seats",
334
- // as: "my_boeing_seats2",
335
- // filterList: [fStringEq("aircraft_models.manufacturer", "BOEING")],
336
- // },
337
- ],
338
- },
339
- ],
58
+ view: hand_turtle_pipeline is {
59
+ aggregate: aircraft_count
60
+ } -> {
61
+ group_by: aircraft_count
62
+ }
63
+
64
+ join_one: aircraft_models
65
+ on aircraft_model_code = aircraft_models.aircraft_model_code
66
+
67
+ primary_key: tail_num
68
+ }
69
+ `;
70
+
71
+ // BigQuery tests only on the Hand Coded models.
72
+ const handModel = runtime.loadModel(makeModel(databaseName));
73
+
74
+ it(`hand query hand model - ${databaseName}`, async () => {
75
+ expect(`
76
+ run: aircraft -> {
77
+ aggregate: total_seats is aircraft_models.seats.sum() {
78
+ where: aircraft_models.manufacturer = 'BOEING'
79
+ }
80
+ }
81
+ `).malloyResultMatches(handModel, {total_seats: 6244});
340
82
  });
341
- await validateCompilation(databaseName, sql);
342
- // console.log(result.sql);
343
- // expect(result.data.value[0].total_seats).toBe(452415);
344
- });
345
-
346
- it(`hand turtle - ${databaseName}`, async () => {
347
- const result = await handModel
348
- ._loadQueryFromQueryDef({
349
- structRef: 'aircraft',
350
- name: 'hand_turtle',
351
- pipeline: [{type: 'reduce', queryFields: fToQF(['aircraft_count'])}],
352
- })
353
- .run();
354
- expect(result.data.value[0]['aircraft_count']).toBe(3599);
355
- });
356
-
357
- it(`hand turtle malloy - ${databaseName}`, async () => {
358
- const result = await handModel
359
- .loadQuery(
360
- `
361
- run: aircraft->hand_turtle
362
- `
363
- )
364
- .run();
365
- expect(result.data.value[0]['aircraft_count']).toBe(3599);
366
- });
367
-
368
- it(`default sort order - ${databaseName}`, async () => {
369
- const result = await handModel
370
- .loadQuery(
371
- `
372
- run: aircraft->{
373
- group_by: state
83
+
84
+ it(`hand turtle - ${databaseName}`, async () => {
85
+ expect(`
86
+ run: aircraft -> {
87
+ aggregate: aircraft_count
88
+ }
89
+ `).malloyResultMatches(handModel, {aircraft_count: 3599});
90
+ });
91
+
92
+ it(`hand turtle malloy - ${databaseName}`, async () => {
93
+ expect(`
94
+ run: aircraft -> hand_turtle
95
+ `).malloyResultMatches(handModel, {aircraft_count: 3599});
96
+ });
97
+
98
+ it(`default sort order - ${databaseName}`, async () => {
99
+ expect(`
100
+ run: aircraft -> {
101
+ group_by: state
102
+ aggregate: aircraft_count
103
+ limit: 10
104
+ }
105
+ `).malloyResultMatches(handModel, {aircraft_count: 367});
106
+ });
107
+
108
+ it(`default sort order by dir - ${databaseName}`, async () => {
109
+ expect(`
110
+ run: aircraft -> {
111
+ group_by: state
112
+ aggregate: aircraft_count
113
+ order_by: 2
114
+ limit: 10
115
+ }
116
+ `).malloyResultMatches(handModel, {aircraft_count: 1});
117
+ });
118
+
119
+ it(`hand turtle2 - ${databaseName}`, async () => {
120
+ expect(`
121
+ run: aircraft -> {
122
+ group_by: state
123
+ aggregate: aircraft_count
124
+ nest: my_turtle is {
125
+ group_by: county
374
126
  aggregate: aircraft_count
375
- limit: 10
376
127
  }
377
- `
378
- )
379
- .run();
380
- expect(result.data.value[0]['aircraft_count']).toBe(367);
381
- });
382
-
383
- it(`default sort order by dir - ${databaseName}`, async () => {
384
- const result = await handModel
385
- .loadQuery(
386
- `
387
- run: aircraft->{
388
- group_by: state
128
+ }
129
+ `).malloyResultMatches(handModel, {aircraft_count: 367});
130
+ });
131
+
132
+ it(`hand total - ${databaseName}`, async () => {
133
+ expect(`
134
+ run: aircraft -> {
135
+ group_by: state
136
+ aggregate: aircraft_count
137
+ aggregate: total_aircraft is all(aircraft_count)
138
+ }
139
+ `).malloyResultMatches(handModel, {total_aircraft: 3599});
140
+ });
141
+
142
+ it(`hand turtle3 - ${databaseName}`, async () => {
143
+ expect(`
144
+ run: aircraft -> {
145
+ group_by: state
146
+ aggregate: aircraft_count
147
+ nest: hand_turtle
148
+ }
149
+ `).malloyResultMatches(handModel, {aircraft_count: 367});
150
+ });
151
+
152
+ it(`hand turtle total - ${databaseName}`, async () => {
153
+ expect(`
154
+ run: aircraft -> {
155
+ group_by: state
156
+ aggregate: aircraft_count
157
+ nest: my_turtle is {
158
+ group_by: county
389
159
  aggregate: aircraft_count
390
- order_by: 2
391
- limit:10
160
+ aggregate: total_aircraft is all(aircraft_count)
392
161
  }
393
- `
394
- )
395
- .run();
396
- expect(result.data.value[0]['aircraft_count']).toBe(1);
397
- });
398
-
399
- it(`hand turtle2 - ${databaseName}`, async () => {
400
- const sql = await compileHandQueryToSQL(handModel, {
401
- structRef: 'aircraft',
402
- pipeline: [
403
- {
404
- type: 'reduce',
405
- queryFields: fToQF([
406
- 'state',
407
- 'aircraft_count',
408
- {
409
- type: 'turtle',
410
- name: 'my_turtle',
411
- pipeline: [
412
- {
413
- type: 'reduce',
414
- queryFields: fToQF(['county', 'aircraft_count']),
415
- },
416
- ],
417
- },
418
- ]),
419
- },
420
- ],
162
+ }
163
+ `).malloyResultMatches(handModel, {aircraft_count: 367});
164
+ });
165
+
166
+ it(`hand: declared pipeline as main query - ${databaseName}`, async () => {
167
+ expect(`
168
+ run: aircraft -> {
169
+ aggregate: aircraft_count
170
+ } -> {
171
+ group_by: aircraft_count
172
+ }
173
+ `).malloyResultMatches(handModel, {aircraft_count: 3599});
421
174
  });
422
- await validateCompilation(databaseName, sql);
423
- // console.log(result.sql);
424
- // expect(result.data.value[0].total_seats).toBe(452415);
425
- });
426
-
427
- it(`hand total - ${databaseName}`, async () => {
428
- const sql = await compileHandQueryToSQL(handModel, {
429
- structRef: 'aircraft',
430
- pipeline: [
431
- {
432
- type: 'reduce',
433
- queryFields: fToQF([
434
- 'state',
435
- 'aircraft_count',
436
- {
437
- name: 'total_aircraft',
438
- type: 'number',
439
- expressionType: 'aggregate',
440
- e: {
441
- node: 'exclude',
442
- e: {node: 'field', path: ['aircraft_count']},
443
- },
444
- },
445
- ]),
446
- },
447
- ],
175
+
176
+ it(`hand: turtle is pipeline - ${databaseName}`, async () => {
177
+ expect(`
178
+ run: aircraft -> {
179
+ aggregate: aircraft_count
180
+ nest: pipe is {
181
+ group_by: state, county
182
+ aggregate: aircraft_count
183
+ } -> {
184
+ where: county ~ '2%'
185
+ group_by: state
186
+ aggregate: total_aircraft is aircraft_count.sum()
187
+ }
188
+ }
189
+ `).malloyResultMatches(handModel, {'pipe.total_aircraft': 61});
190
+ // expect(result.data.path(0, 'pipe', 0, 'total_aircraft').value).toBe(61);
448
191
  });
449
- await validateCompilation(databaseName, sql);
450
- // console.log(sql);
451
- // expect(result.data.value[0].total_seats).toBe(452415);
452
- });
453
-
454
- it(`hand turtle3 - ${databaseName}`, async () => {
455
- const sql = await compileHandQueryToSQL(handModel, {
456
- structRef: 'aircraft',
457
- pipeline: [
458
- {
459
- type: 'reduce',
460
- queryFields: fToQF(['state', 'aircraft_count', 'hand_turtle']),
461
- },
462
- ],
192
+
193
+ // Hand model basic calculations for sum, filtered sum, without a join.
194
+ it(`hand: lots of kinds of sums - ${databaseName}`, async () => {
195
+ expect(`
196
+ run: aircraft->{
197
+ aggregate:
198
+ aircraft_models.total_seats,
199
+ total_seats2 is sum(aircraft_models.seats),
200
+ total_seats3 is aircraft_models.sum(aircraft_models.seats),
201
+ aircraft_models.boeing_seats,
202
+ boeing_seats2 is aircraft_models.sum(aircraft_models.seats) { where: aircraft_models.manufacturer ? 'BOEING'},
203
+ boeing_seats3 is aircraft_models.boeing_seats { where: aircraft_models.manufacturer ? ~'B%'}
204
+ }
205
+ `).malloyResultMatches(handModel, {
206
+ total_seats: 18294,
207
+ total_seats2: 31209,
208
+ total_seats3: 18294,
209
+ boeing_seats: 6244,
210
+ boeing_seats2: 6244,
211
+ boeing_seats3: 6244,
212
+ });
463
213
  });
464
- await validateCompilation(databaseName, sql);
465
- // console.log(result.sql);
466
- // expect(result.data.value[0].total_seats).toBe(452415);
467
- });
468
-
469
- it(`hand turtle total - ${databaseName}`, async () => {
470
- const sql = await compileHandQueryToSQL(handModel, {
471
- structRef: 'aircraft',
472
- pipeline: [
473
- {
474
- type: 'reduce',
475
- queryFields: fToQF([
476
- 'state',
477
- 'aircraft_count',
478
- {
479
- type: 'turtle',
480
- name: 'my_turtle',
481
- pipeline: [
482
- {
483
- type: 'reduce',
484
- queryFields: fToQF([
485
- 'county',
486
- 'aircraft_count',
487
- {
488
- name: 'total_aircraft',
489
- type: 'number',
490
- expressionType: 'aggregate',
491
- e: {
492
- node: 'exclude',
493
- e: {node: 'field', path: ['aircraft_count']},
494
- },
495
- },
496
- ]),
497
- },
498
- ],
499
- },
500
- ]),
501
- },
502
- ],
214
+
215
+ it(`hand: bad root name for pathed sum - ${databaseName}`, async () => {
216
+ expect(`
217
+ run: aircraft -> {
218
+ aggregate: total_seats3 is aircraft_models.sum(aircraft_models.seats)
219
+ }
220
+ `).malloyResultMatches(handModel, {total_seats3: 18294});
503
221
  });
504
- await validateCompilation(databaseName, sql);
505
- // console.log(sql);
506
- // expect(result.data.value[0].total_seats).toBe(452415);
507
- });
508
-
509
- it(`hand: declared pipeline as main query - ${databaseName}`, async () => {
510
- const sql = await compileHandQueryToSQL(handModel, {
511
- structRef: 'aircraft',
512
- name: 'hand_turtle_pipeline',
513
- pipeline: [
514
- {type: 'reduce', queryFields: fToQF(['aircraft_count'])},
515
- {type: 'reduce', queryFields: fToQF(['aircraft_count'])},
516
- ],
222
+
223
+ // WORKs: (hand coded model):
224
+ // Model based version of sums.
225
+ it(`hand: expression fixups. - ${databaseName}`, async () => {
226
+ expect(`
227
+ run: aircraft -> {
228
+ aggregate:
229
+ aircraft_models.total_seats,
230
+ aircraft_models.boeing_seats
231
+ }
232
+ `).malloyResultMatches(handModel, {total_seats: 18294, boeing_seats: 6244});
517
233
  });
518
- // console.log(result.sql);
519
- await validateCompilation(databaseName, sql);
520
- // console.log(result.sql);
521
- // expect(result.data.value[0].total_seats).toBe(452415);
522
- });
523
-
524
- it(`hand: turtle is pipeline - ${databaseName}`, async () => {
525
- const result = await handModel
526
- ._loadQueryFromQueryDef({
527
- structRef: 'aircraft',
528
- pipeline: [
529
- {
530
- type: 'reduce',
531
- queryFields: fToQF([
532
- 'aircraft_count',
533
- {
534
- type: 'turtle',
535
- name: 'pipe',
536
- pipeline: [
537
- {
538
- type: 'reduce',
539
- queryFields: fToQF(['state', 'county', 'aircraft_count']),
540
- },
541
- {
542
- type: 'reduce',
543
- filterList: [fStringLike('county', '2%')],
544
- queryFields: fToQF([
545
- 'state',
546
- {
547
- name: 'total_aircraft',
548
- type: 'number',
549
- e: {
550
- node: 'aggregate',
551
- function: 'sum',
552
- e: {node: 'field', path: ['aircraft_count']},
553
- },
554
- expressionType: 'aggregate',
555
- numberType: 'float',
556
- },
557
- ]),
558
- },
559
- ],
560
- },
561
- ]),
562
- },
563
- ],
564
- })
565
- .run();
566
- expect(result.data.path(0, 'pipe', 0, 'total_aircraft').value).toBe(61);
567
- });
568
-
569
- // Hand model basic calculations for sum, filtered sum, without a join.
570
- it(`hand: lots of kinds of sums - ${databaseName}`, async () => {
571
- const result = await handModel
572
- .loadQuery(
573
- `
574
- run: aircraft->{
575
- aggregate:
576
- aircraft_models.total_seats,
577
- total_seats2 is sum(aircraft_models.seats),
578
- total_seats3 is aircraft_models.sum(aircraft_models.seats),
579
- aircraft_models.boeing_seats,
580
- boeing_seats2 is aircraft_models.sum(aircraft_models.seats) { where: aircraft_models.manufacturer ? 'BOEING'},
581
- boeing_seats3 is aircraft_models.boeing_seats { where: aircraft_models.manufacturer ? ~'B%'}
582
- }
583
- `
584
- )
585
- .run();
586
- // console.log(result.sql);
587
- expect(result.data.value[0]['total_seats']).toBe(18294);
588
- expect(result.data.value[0]['total_seats2']).toBe(31209);
589
- expect(result.data.value[0]['total_seats3']).toBe(18294);
590
- expect(result.data.value[0]['boeing_seats']).toBe(6244);
591
- expect(result.data.value[0]['boeing_seats2']).toBe(6244);
592
- expect(result.data.value[0]['boeing_seats3']).toBe(6244);
593
- });
594
-
595
- it(`hand: bad root name for pathed sum - ${databaseName}`, async () => {
596
- const result = await handModel
597
- .loadQuery(
598
- `
599
- run: aircraft->{
600
- aggregate: total_seats3 is aircraft_models.sum(aircraft_models.seats)
601
- }
602
- `
603
- )
604
- .run();
605
- // console.log(result.sql);
606
- expect(result.data.value[0]['total_seats3']).toBe(18294);
607
- });
608
-
609
- // WORKs: (hand coded model):
610
- // Model based version of sums.
611
- it(`hand: expression fixups. - ${databaseName}`, async () => {
612
- const result = await handModel
613
- .loadQuery(
614
- `
615
- run: aircraft->{
616
- aggregate:
617
- aircraft_models.total_seats,
618
- aircraft_models.boeing_seats
619
- }
620
- `
621
- )
622
- .run();
623
- expect(result.data.value[0]['total_seats']).toBe(18294);
624
- expect(result.data.value[0]['boeing_seats']).toBe(6244);
625
- });
626
-
627
- it(`model: filtered measures - ${databaseName}`, async () => {
628
- const result = await handModel
629
- .loadQuery(
630
- `
631
- run: aircraft->{
632
- aggregate: boeing_seats is aircraft_models.total_seats { where: aircraft_models.manufacturer ?'BOEING'}
633
- }
634
- `
635
- )
636
- .run();
637
- expect(result.data.value[0]['boeing_seats']).toBe(6244);
638
- });
639
-
640
- // does the filter force a join?
641
- it(`model: do filters force dependant joins? - ${databaseName}`, async () => {
642
- const result = await handModel
643
- .loadQuery(
644
- `
645
- run: aircraft->{
646
- aggregate: boeing_aircraft is count() { where:aircraft_models.manufacturer ?'BOEING'}
647
- }
648
- `
649
- )
650
- .run();
651
- expect(result.data.value[0]['boeing_aircraft']).toBe(69);
652
- });
653
-
654
- // Works: Generate query using named alias.
655
- it(`hand: filtered measures - ${databaseName}`, async () => {
656
- const result = await handModel
657
- ._loadQueryFromQueryDef({
658
- structRef: 'aircraft',
659
- pipeline: [
660
- {
661
- type: 'reduce',
662
- queryFields: [
663
- {
664
- name: 'boeing_seats',
665
- type: 'number',
666
- expressionType: 'aggregate',
667
- e: {
668
- node: 'filteredExpr',
669
- kids: {
670
- e: {
671
- node: 'aggregate',
672
- function: 'sum',
673
- structPath: ['aircraft_models'],
674
- e: {node: 'field', path: ['aircraft_models', 'seats']},
675
- },
676
- filterList: [
677
- {
678
- node: 'filterCondition',
679
- expressionType: 'aggregate',
680
- code: "manufacturer='BOEING'",
681
- e: malloy.composeSQLExpr([
682
- {
683
- node: 'field',
684
- path: ['aircraft_models', 'manufacturer'],
685
- },
686
- "='BOEING'",
687
- ]),
688
- },
689
- ],
690
- },
691
- },
692
- },
693
- ],
694
- },
695
- ],
696
- })
697
- .run();
698
- // console.log(result.sql);
699
- expect(result.data.value[0]['boeing_seats']).toBe(6244);
700
- });
701
-
702
- const joinModelAircraftHandStructDef: StructDef = {
703
- ...modelHandBase,
704
- as: 'model_aircraft',
705
- fields: [
706
- ...modelHandBase.fields,
707
- withJoin(
708
- aircraftHandBase,
709
- 'many',
710
- 'aircraft',
711
- 'aircraft_model_code=aircraft.aircraft_model_code'
712
- ),
713
- ],
714
- };
715
-
716
- // Join tests
717
-
718
- const joinModel: ModelDef = {
719
- name: 'Hand Coded Join Models',
720
- exports: ['model_aircraft'],
721
- contents: {
722
- model_aircraft: joinModelAircraftHandStructDef,
723
- },
724
- queryList: [],
725
- dependencies: {},
726
- };
727
-
728
- const handJoinModel = bqRuntime._loadModelFromModelDef(joinModel);
729
-
730
- it(`hand join ON - ${databaseName}`, async () => {
731
- const sql = await handJoinModel
732
- ._loadQueryFromQueryDef({
733
- structRef: 'model_aircraft',
734
- pipeline: [
735
- {
736
- type: 'reduce',
737
- queryFields: fToQF([
738
- 'aircraft.state',
739
- 'aircraft.aircraft_count',
740
- 'model_count',
741
- ]),
742
- },
743
- ],
744
- })
745
- .getSQL();
746
- await validateCompilation(databaseName, sql);
747
- // console.log(result.sql);
748
- // expect(result.data.value[0].total_seats).toBe(452415);
749
- });
750
-
751
- it(`hand join symmetric agg - ${databaseName}`, async () => {
752
- const result = await handJoinModel
753
- ._loadQueryFromQueryDef({
754
- structRef: 'model_aircraft',
755
- pipeline: [
756
- {
757
- type: 'reduce',
758
- queryFields: fToQF(['total_seats', 'aircraft.aircraft_count']),
759
- },
760
- ],
761
- })
762
- .run();
763
- // await bqCompile(databaseName, result.sql);
764
- // console.log(result.data.value);
765
- expect(result.data.value[0]['total_seats']).toBe(452415);
766
- expect(result.data.value[0]['aircraft_count']).toBe(62644);
767
- });
768
- });
234
+
235
+ it(`model: filtered measures - ${databaseName}`, async () => {
236
+ expect(`
237
+ run: aircraft -> {
238
+ aggregate: boeing_seats is aircraft_models.total_seats {
239
+ where: aircraft_models.manufacturer ? 'BOEING'
240
+ }
241
+ }
242
+ `).malloyResultMatches(handModel, {boeing_seats: 6244});
243
+ });
244
+
245
+ // does the filter force a join?
246
+ it(`model: do filters force dependant joins? - ${databaseName}`, async () => {
247
+ expect(`
248
+ run: aircraft -> {
249
+ aggregate: boeing_aircraft is count() {
250
+ where:aircraft_models.manufacturer ? 'BOEING'
251
+ }
252
+ }
253
+ `).malloyResultMatches(handModel, {boeing_aircraft: 69});
254
+ });
255
+
256
+ // Works: Generate query using named alias.
257
+ it(`hand: filtered measures - ${databaseName}`, async () => {
258
+ expect(`
259
+ run: aircraft -> {
260
+ aggregate: boeing_seats is aircraft_models.seats.sum() {
261
+ where: aircraft_models.manufacturer = 'BOEING'
262
+ }
263
+ }
264
+ `).malloyResultMatches(handModel, {boeing_seats: 6244});
265
+ });
266
+
267
+ // Join tests
268
+
269
+ const handJoinModel = handModel.extendModel(`
270
+ source: model_aircraft is aircraft_models extend {
271
+ join_many: aircraft on aircraft_model_code = aircraft.aircraft_model_code
272
+ }
273
+ `);
274
+
275
+ it(`hand join ON - ${databaseName}`, async () => {
276
+ expect(`
277
+ run: model_aircraft -> {
278
+ group_by: aircraft.state
279
+ aggregate: aircraft.aircraft_count
280
+ aggregate: model_count
281
+ }
282
+ `).malloyResultMatches(handJoinModel, {model_count: 59104});
283
+ });
284
+
285
+ it(`hand join symmetric agg - ${databaseName}`, async () => {
286
+ expect(`
287
+ run: model_aircraft -> {
288
+ aggregate: total_seats
289
+ aggregate: aircraft.aircraft_count
290
+ }
291
+ `).malloyResultMatches(handJoinModel, {
292
+ total_seats: 452415,
293
+ aircraft_count: 62644,
294
+ });
295
+ });
296
+ }
297
+ );