@malloydata/malloy-tests 0.0.246-dev250320195825 → 0.0.246-dev250320220920
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
CHANGED
|
@@ -21,14 +21,14 @@
|
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@jest/globals": "^29.4.3",
|
|
24
|
-
"@malloydata/db-bigquery": "^0.0.246-
|
|
25
|
-
"@malloydata/db-duckdb": "^0.0.246-
|
|
26
|
-
"@malloydata/db-postgres": "^0.0.246-
|
|
27
|
-
"@malloydata/db-snowflake": "^0.0.246-
|
|
28
|
-
"@malloydata/db-trino": "^0.0.246-
|
|
29
|
-
"@malloydata/malloy": "^0.0.246-
|
|
30
|
-
"@malloydata/malloy-tag": "^0.0.246-
|
|
31
|
-
"@malloydata/render": "^0.0.246-
|
|
24
|
+
"@malloydata/db-bigquery": "^0.0.246-dev250320220920",
|
|
25
|
+
"@malloydata/db-duckdb": "^0.0.246-dev250320220920",
|
|
26
|
+
"@malloydata/db-postgres": "^0.0.246-dev250320220920",
|
|
27
|
+
"@malloydata/db-snowflake": "^0.0.246-dev250320220920",
|
|
28
|
+
"@malloydata/db-trino": "^0.0.246-dev250320220920",
|
|
29
|
+
"@malloydata/malloy": "^0.0.246-dev250320220920",
|
|
30
|
+
"@malloydata/malloy-tag": "^0.0.246-dev250320220920",
|
|
31
|
+
"@malloydata/render": "^0.0.246-dev250320220920",
|
|
32
32
|
"events": "^3.3.0",
|
|
33
33
|
"jsdom": "^22.1.0",
|
|
34
34
|
"luxon": "^2.4.0",
|
|
@@ -38,5 +38,5 @@
|
|
|
38
38
|
"@types/jsdom": "^21.1.1",
|
|
39
39
|
"@types/luxon": "^2.4.0"
|
|
40
40
|
},
|
|
41
|
-
"version": "0.0.246-
|
|
41
|
+
"version": "0.0.246-dev250320220920"
|
|
42
42
|
}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import {RuntimeList, allDatabases} from '../../runtimes';
|
|
9
9
|
import '../../util/db-jest-matchers';
|
|
10
10
|
import {databasesFromEnvironmentOr} from '../../util';
|
|
11
|
+
import {DateTime as LuxonDateTime} from 'luxon';
|
|
11
12
|
|
|
12
13
|
const runtimes = new RuntimeList(databasesFromEnvironmentOr(allDatabases));
|
|
13
14
|
|
|
@@ -349,4 +350,262 @@ describe.each(runtimes.runtimeList)('filter expressions %s', (dbName, db) => {
|
|
|
349
350
|
}`).malloyResultMatches(facts, [{t: 'false'}, {t: 'true'}]);
|
|
350
351
|
});
|
|
351
352
|
});
|
|
353
|
+
|
|
354
|
+
type TL = 'timeLiteral';
|
|
355
|
+
type TS = {type: 'timestamp'};
|
|
356
|
+
|
|
357
|
+
describe('temporal filters', () => {
|
|
358
|
+
function ts(t: string): string {
|
|
359
|
+
const node: TL = 'timeLiteral';
|
|
360
|
+
const typeDef: TS = {type: 'timestamp'};
|
|
361
|
+
const n = {node, typeDef, literal: t};
|
|
362
|
+
return db.dialect.sqlLiteralTime({}, n);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const fTimestamp = 'yyyy-LL-dd HH:mm:ss';
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Create a source for testing a range. It will have five rows
|
|
369
|
+
* { t: 1 second before start, n: 'before' }
|
|
370
|
+
* { t: start, n: 'first' }
|
|
371
|
+
* { t: 1 second before end, n: 'last' }
|
|
372
|
+
* { t: end, n: 'zend' }
|
|
373
|
+
* { t: NULL n: ' null ' }
|
|
374
|
+
* Use malloyResultMatches(range, inRange) or (range, notInRange)
|
|
375
|
+
*/
|
|
376
|
+
const inRange = [{n: 'first'}, {n: 'last'}];
|
|
377
|
+
const notInRange = [{n: 'before'}, {n: 'zend'}];
|
|
378
|
+
function mkRange(start: string, end: string) {
|
|
379
|
+
const begin = LuxonDateTime.fromFormat(start, fTimestamp);
|
|
380
|
+
const b4 = begin.minus({second: 1});
|
|
381
|
+
const last = LuxonDateTime.fromFormat(end, fTimestamp).minus({second: 1});
|
|
382
|
+
const rangeModel = `
|
|
383
|
+
query: range is ${dbName}.sql("""
|
|
384
|
+
SELECT ${ts(b4.toFormat(fTimestamp))} AS ${q`t`}, 'before' AS ${q`n`}
|
|
385
|
+
UNION ALL SELECT ${ts(start)}, 'first'
|
|
386
|
+
UNION ALL SELECT ${ts(last.toFormat(fTimestamp))} , 'last'
|
|
387
|
+
UNION ALL SELECT ${ts(end)}, 'zend'
|
|
388
|
+
UNION ALL SELECT NULL, ' null '
|
|
389
|
+
""")
|
|
390
|
+
-> {select: *; order_by: n}`;
|
|
391
|
+
return db.loadModel(rangeModel);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* All the relative time tests need a way to set what time it is now
|
|
396
|
+
*/
|
|
397
|
+
function nowIs(timeStr: string) {
|
|
398
|
+
const spyNow = jest.spyOn(db.dialect, 'sqlNowExpr');
|
|
399
|
+
spyNow.mockImplementation(() => ts(timeStr));
|
|
400
|
+
}
|
|
401
|
+
afterEach(() => jest.restoreAllMocks());
|
|
402
|
+
|
|
403
|
+
test('null', async () => {
|
|
404
|
+
const range = mkRange('2001-01-01 00:00:00', '2002-01-01 00:00:00');
|
|
405
|
+
await expect(`
|
|
406
|
+
run: range + { where: t ~ f'null' }
|
|
407
|
+
`).malloyResultMatches(range, [{n: ' null '}]);
|
|
408
|
+
});
|
|
409
|
+
test('not null', async () => {
|
|
410
|
+
const range = mkRange('2001-01-01 00:00:00', '2002-01-01 00:00:00');
|
|
411
|
+
await expect(`
|
|
412
|
+
run: range + { where: t ~ f'not null' }
|
|
413
|
+
`).malloyResultMatches(range, [
|
|
414
|
+
{n: 'before'},
|
|
415
|
+
{n: 'first'},
|
|
416
|
+
{n: 'last'},
|
|
417
|
+
{n: 'zend'},
|
|
418
|
+
]);
|
|
419
|
+
});
|
|
420
|
+
test('year literal', async () => {
|
|
421
|
+
const range = mkRange('2001-01-01 00:00:00', '2002-01-01 00:00:00');
|
|
422
|
+
await expect(`
|
|
423
|
+
run: range + { where: t ~ f'2001' }
|
|
424
|
+
`).malloyResultMatches(range, inRange);
|
|
425
|
+
});
|
|
426
|
+
test('not month literal', async () => {
|
|
427
|
+
const range = mkRange('2001-06-01 00:00:00', '2001-07-01 00:00:00');
|
|
428
|
+
await expect(`
|
|
429
|
+
run: range + { where: t ~ f'not 2001-06' }
|
|
430
|
+
`).malloyResultMatches(range, notInRange);
|
|
431
|
+
});
|
|
432
|
+
test('day literal', async () => {
|
|
433
|
+
const range = mkRange('2001-06-15 00:00:00', '2001-06-16 00:00:00');
|
|
434
|
+
await expect(`
|
|
435
|
+
run: range + { where: t ~ f'2001-06-15' }
|
|
436
|
+
`).malloyResultMatches(range, inRange);
|
|
437
|
+
});
|
|
438
|
+
test('hour literal', async () => {
|
|
439
|
+
const range = mkRange('2001-02-03 04:00:00', '2001-02-03 05:00:00');
|
|
440
|
+
await expect(`
|
|
441
|
+
run: range + { where: t ~ f'2001-02-03 04' }
|
|
442
|
+
`).malloyResultMatches(range, inRange);
|
|
443
|
+
});
|
|
444
|
+
test('minute literal', async () => {
|
|
445
|
+
const range = mkRange('2001-02-03 04:05:00', '2001-02-03 04:06:00');
|
|
446
|
+
await expect(`
|
|
447
|
+
run: range + { where: t ~ f'2001-02-03 04:05' }
|
|
448
|
+
`).malloyResultMatches(range, inRange);
|
|
449
|
+
});
|
|
450
|
+
test('quarter literal', async () => {
|
|
451
|
+
const range = mkRange('2001-01-01 00:00:00', '2001-04-01 00:00:00');
|
|
452
|
+
await expect(`
|
|
453
|
+
run: range + { where: t ~ f'2001-Q1' }
|
|
454
|
+
`).malloyResultMatches(range, inRange);
|
|
455
|
+
});
|
|
456
|
+
test('week literal', async () => {
|
|
457
|
+
const range = mkRange('2023-01-01 00:00:00', '2023-01-08 00:00:00');
|
|
458
|
+
await expect(`
|
|
459
|
+
run: range + { where: t ~ f'2023-01-01-WK' }
|
|
460
|
+
`).malloyResultMatches(range, inRange);
|
|
461
|
+
});
|
|
462
|
+
test('today', async () => {
|
|
463
|
+
nowIs('2001-02-03 12:00:00');
|
|
464
|
+
const range = mkRange('2001-02-03 00:00:00', '2001-02-04 00:00:00');
|
|
465
|
+
await expect(`
|
|
466
|
+
run: range + { where: t ~ f'today' }
|
|
467
|
+
`).malloyResultMatches(range, inRange);
|
|
468
|
+
});
|
|
469
|
+
test('yesterday', async () => {
|
|
470
|
+
nowIs('2001-02-03 12:00:00');
|
|
471
|
+
const range = mkRange('2001-02-02 00:00:00', '2001-02-03 00:00:00');
|
|
472
|
+
await expect(`
|
|
473
|
+
run: range + { where: t ~ f'yesterday' }
|
|
474
|
+
`).malloyResultMatches(range, inRange);
|
|
475
|
+
});
|
|
476
|
+
test('tomorrow', async () => {
|
|
477
|
+
nowIs('2001-02-03 12:00:00');
|
|
478
|
+
const range = mkRange('2001-02-04 00:00:00', '2001-02-05 00:00:00');
|
|
479
|
+
await expect(`
|
|
480
|
+
run: range + { where: t ~ f'tomorrow' }
|
|
481
|
+
`).malloyResultMatches(range, inRange);
|
|
482
|
+
});
|
|
483
|
+
test('this week', async () => {
|
|
484
|
+
nowIs('2023-01-03 00:00:00');
|
|
485
|
+
const range = mkRange('2023-01-01 00:00:00', '2023-01-08 00:00:00');
|
|
486
|
+
await expect(`
|
|
487
|
+
run: range + { where: t ~ f'this week' }
|
|
488
|
+
`).malloyResultMatches(range, inRange);
|
|
489
|
+
});
|
|
490
|
+
test('last month', async () => {
|
|
491
|
+
nowIs('2001-02-01 12:00:00');
|
|
492
|
+
const range = mkRange('2001-01-01 00:00:00', '2001-02-01 00:00:00');
|
|
493
|
+
await expect(`
|
|
494
|
+
run: range + { where: t ~ f'last month' }
|
|
495
|
+
`).malloyResultMatches(range, inRange);
|
|
496
|
+
});
|
|
497
|
+
test('next quarter', async () => {
|
|
498
|
+
nowIs('2001-01-02 12:00:00');
|
|
499
|
+
const range = mkRange('2001-04-01 00:00:00', '2001-07-01 00:00:00');
|
|
500
|
+
await expect(`
|
|
501
|
+
run: range + { where: t ~ f'next quarter' }
|
|
502
|
+
`).malloyResultMatches(range, inRange);
|
|
503
|
+
});
|
|
504
|
+
test('this year', async () => {
|
|
505
|
+
nowIs('2001-01-02 12:00:00');
|
|
506
|
+
const range = mkRange('2001-01-01 00:00:00', '2002-01-01 00:00:00');
|
|
507
|
+
await expect(`
|
|
508
|
+
run: range + { where: t ~ f'this year' }
|
|
509
|
+
`).malloyResultMatches(range, inRange);
|
|
510
|
+
});
|
|
511
|
+
// 2023-01-01 is a sunday
|
|
512
|
+
test('(last) sunday', async () => {
|
|
513
|
+
nowIs('2023-01-03 00:00:00');
|
|
514
|
+
const range = mkRange('2023-01-01 00:00:00', '2023-01-02 00:00:00');
|
|
515
|
+
await expect(`
|
|
516
|
+
run: range + { where: t ~ f'sunday' }
|
|
517
|
+
`).malloyResultMatches(range, inRange);
|
|
518
|
+
});
|
|
519
|
+
test('last monday', async () => {
|
|
520
|
+
nowIs('2023-01-03 00:00:00');
|
|
521
|
+
const range = mkRange('2023-01-02 00:00:00', '2023-01-03 00:00:00');
|
|
522
|
+
await expect(`
|
|
523
|
+
run: range + { where: t ~ f'last monday' }
|
|
524
|
+
`).malloyResultMatches(range, inRange);
|
|
525
|
+
});
|
|
526
|
+
test('last-tuesday', async () => {
|
|
527
|
+
nowIs('2023-01-03 00:00:00');
|
|
528
|
+
const range = mkRange('2022-12-27 00:00:00', '2022-12-28 00:00:00');
|
|
529
|
+
await expect(`
|
|
530
|
+
run: range + { where: t ~ f'tuesday' }
|
|
531
|
+
`).malloyResultMatches(range, inRange);
|
|
532
|
+
});
|
|
533
|
+
test('last-wednesday', async () => {
|
|
534
|
+
nowIs('2023-01-03 00:00:00');
|
|
535
|
+
const range = mkRange('2022-12-28 00:00:00', '2022-12-29 00:00:00');
|
|
536
|
+
await expect(`
|
|
537
|
+
run: range + { where: t ~ f'wednesday' }
|
|
538
|
+
`).malloyResultMatches(range, inRange);
|
|
539
|
+
});
|
|
540
|
+
test('last-thursday', async () => {
|
|
541
|
+
nowIs('2023-01-03 00:00:00');
|
|
542
|
+
const range = mkRange('2022-12-29 00:00:00', '2022-12-30 00:00:00');
|
|
543
|
+
await expect(`
|
|
544
|
+
run: range + { where: t ~ f'thursday' }
|
|
545
|
+
`).malloyResultMatches(range, inRange);
|
|
546
|
+
});
|
|
547
|
+
test('last-friday', async () => {
|
|
548
|
+
nowIs('2023-01-03 00:00:00');
|
|
549
|
+
const range = mkRange('2022-12-30 00:00:00', '2022-12-31 00:00:00');
|
|
550
|
+
await expect(`
|
|
551
|
+
run: range + { where: t ~ f'friday' }
|
|
552
|
+
`).malloyResultMatches(range, inRange);
|
|
553
|
+
});
|
|
554
|
+
test('last saturday', async () => {
|
|
555
|
+
nowIs('2023-01-03 00:00:00');
|
|
556
|
+
const range = mkRange('2022-12-31 00:00:00', '2023-01-01 00:00:00');
|
|
557
|
+
await expect(`
|
|
558
|
+
run: range + { where: t ~ f'last saturday' }
|
|
559
|
+
`).malloyResultMatches(range, inRange);
|
|
560
|
+
});
|
|
561
|
+
test('next sunday', async () => {
|
|
562
|
+
nowIs('2023-01-03 00:00:00');
|
|
563
|
+
const range = mkRange('2023-01-08 00:00:00', '2023-01-09 00:00:00');
|
|
564
|
+
await expect(`
|
|
565
|
+
run: range + { where: t ~ f'next sunday' }
|
|
566
|
+
`).malloyResultMatches(range, inRange);
|
|
567
|
+
});
|
|
568
|
+
test('next monday', async () => {
|
|
569
|
+
nowIs('2023-01-03 00:00:00');
|
|
570
|
+
const range = mkRange('2023-01-09 00:00:00', '2023-01-10 00:00:00');
|
|
571
|
+
await expect(`
|
|
572
|
+
run: range + { where: t ~ f'next monday' }
|
|
573
|
+
`).malloyResultMatches(range, inRange);
|
|
574
|
+
});
|
|
575
|
+
test('next tuesday', async () => {
|
|
576
|
+
nowIs('2023-01-03 00:00:00');
|
|
577
|
+
const range = mkRange('2023-01-10 00:00:00', '2023-01-11 00:00:00');
|
|
578
|
+
await expect(`
|
|
579
|
+
run: range + { where: t ~ f'next tuesday' }
|
|
580
|
+
`).malloyResultMatches(range, inRange);
|
|
581
|
+
});
|
|
582
|
+
test('next wednesday', async () => {
|
|
583
|
+
nowIs('2023-01-03 00:00:00');
|
|
584
|
+
const range = mkRange('2023-01-04 00:00:00', '2023-01-05 00:00:00');
|
|
585
|
+
await expect(`
|
|
586
|
+
run: range + { where: t ~ f'next wednesday' }
|
|
587
|
+
`).malloyResultMatches(range, inRange);
|
|
588
|
+
});
|
|
589
|
+
test('next thursday', async () => {
|
|
590
|
+
nowIs('2023-01-03 00:00:00');
|
|
591
|
+
const range = mkRange('2023-01-05 00:00:00', '2023-01-06 00:00:00');
|
|
592
|
+
await expect(`
|
|
593
|
+
run: range + { where: t ~ f'next thursday' }
|
|
594
|
+
`).malloyResultMatches(range, inRange);
|
|
595
|
+
});
|
|
596
|
+
test('next friday', async () => {
|
|
597
|
+
nowIs('2023-01-03 00:00:00');
|
|
598
|
+
const range = mkRange('2023-01-06 00:00:00', '2023-01-07 00:00:00');
|
|
599
|
+
await expect(`
|
|
600
|
+
run: range + { where: t ~ f'next friday' }
|
|
601
|
+
`).malloyResultMatches(range, inRange);
|
|
602
|
+
});
|
|
603
|
+
test('next saturday', async () => {
|
|
604
|
+
nowIs('2023-01-03 00:00:00');
|
|
605
|
+
const range = mkRange('2023-01-07 00:00:00', '2023-01-08 00:00:00');
|
|
606
|
+
await expect(`
|
|
607
|
+
run: range + { where: t ~ f'next saturday' }
|
|
608
|
+
`).malloyResultMatches(range, inRange);
|
|
609
|
+
});
|
|
610
|
+
});
|
|
352
611
|
});
|