@@ -3,6 +3,7 @@ import { prepareJsCompiler } from '../../unit/PrepareCompiler';
33import { DataSchemaCompiler } from '../../../src/compiler/DataSchemaCompiler' ;
44import { JoinGraph } from '../../../src/compiler/JoinGraph' ;
55import { CubeEvaluator } from '../../../src/compiler/CubeEvaluator' ;
6+ import { testWithPreAggregation } from './pre-aggregation-utils' ;
67
78describe ( 'Multiple join paths' , ( ) => {
89 jest . setTimeout ( 200000 ) ;
@@ -20,7 +21,8 @@ describe('Multiple join paths', () => {
2021 // └-->F-------┘
2122 // View, pre-aggregations and all interesting parts should use ADEX path
2223 // It should NOT be the shortest one from A to X (that's AFX), nor first in join edges declaration (that's ABCX)
23- // All join conditions would be essentially `FALSE`, but with different syntax, to be able to test SQL generation
24+ // All join conditions would be essentially `TRUE` for ADEX joins and `FALSE` for everything else
25+ // But they would use different syntax, to be able to test SQL generation
2426 // Also, there should be only one way to cover cubes A and D with joins: A->D join
2527
2628 // TODO in this model queries like [A.a_id, X.x_id] become ambiguous, probably we want to handle this better
@@ -37,7 +39,7 @@ describe('Multiple join paths', () => {
3739 },
3840 D: {
3941 relationship: 'many_to_one',
40- sql: "'A' = 'D'",
42+ sql: "'A' = 'D' OR TRUE ",
4143 },
4244 F: {
4345 relationship: 'many_to_one',
@@ -78,7 +80,6 @@ describe('Multiple join paths', () => {
7880 a_id,
7981 A.D.d_id,
8082 A.D.d_name_for_join_paths,
81- // D.d_id,
8283 A.D.E.X.x_id,
8384 ],
8485 measures: [
@@ -93,6 +94,19 @@ describe('Multiple join paths', () => {
9394 granularity: 'day',
9495 },
9596
97+ adex_cumulative_with_join_paths: {
98+ type: 'rollup',
99+ dimensions: [
100+ a_id,
101+ A.D.E.X.x_id,
102+ ],
103+ measures: [
104+ A.D.E.X.x_cumulative_sum,
105+ ],
106+ timeDimension: A.D.E.X.x_time,
107+ granularity: 'day',
108+ },
109+
96110 ad_without_join_paths: {
97111 type: 'rollup',
98112 dimensions: [
@@ -183,7 +197,7 @@ describe('Multiple join paths', () => {
183197 joins: {
184198 E: {
185199 relationship: 'many_to_one',
186- sql: "'D' = 'E'",
200+ sql: "'D' = 'E' OR TRUE ",
187201 },
188202 },
189203
@@ -228,7 +242,7 @@ describe('Multiple join paths', () => {
228242 joins: {
229243 X: {
230244 relationship: 'many_to_one',
231- sql: "'E' = 'X'",
245+ sql: "'E' = 'X' OR TRUE ",
232246 },
233247 },
234248
@@ -319,6 +333,13 @@ describe('Multiple join paths', () => {
319333 sql: 'x_value',
320334 type: 'sum',
321335 },
336+ x_cumulative_sum: {
337+ sql: 'x_value',
338+ type: 'sum',
339+ rolling_window: {
340+ trailing: 'unbounded',
341+ },
342+ },
322343 },
323344
324345 segments: {
@@ -515,33 +536,100 @@ describe('Multiple join paths', () => {
515536 expect ( preAggregation ) . toBeDefined ( ) ;
516537 } ) ;
517538
518- const preAggregationIds = [
519- 'A.adex_with_join_paths' ,
520- 'A.ad_without_join_paths' ,
539+ function makeReferenceQueryFor ( preAggregationId : string , withDateRange : boolean = false ) : PostgresQuery {
540+ const preAggregations = cubeEvaluator . preAggregations ( { } ) ;
541+
542+ const preAggregation = preAggregations
543+ . find ( p => p . id === preAggregationId ) ;
544+ if ( preAggregation === undefined ) {
545+ throw expect ( preAggregation ) . toBeDefined ( ) ;
546+ }
547+
548+ if ( withDateRange ) {
549+ preAggregation . references . timeDimensions = preAggregation . references . timeDimensions . map ( td => ( {
550+ ...td ,
551+ dateRange : [ '1970-01-01' , '1970-01-02' ] ,
552+ } ) ) ;
553+ }
554+
555+ return new PostgresQuery ( { joinGraph, cubeEvaluator, compiler } , {
556+ ...preAggregation . references ,
557+ preAggregationId : preAggregation . id ,
558+ preAggregationsSchema : '' ,
559+ timezone : 'UTC' ,
560+ } ) ;
561+ }
562+
563+ const preAggregationTests = [
564+ {
565+ preAggregationId : 'A.adex_with_join_paths' ,
566+ addTimeRange : false ,
567+ expectedData : [
568+ {
569+ a__a_id : 1 ,
570+ a__a_seg : false ,
571+ a__a_sum : '100' ,
572+ d__d_id : 1 ,
573+ d__d_name_for_join_paths : 'foo' ,
574+ d__d_seg : false ,
575+ x__x_id : 1 ,
576+ x__x_seg : false ,
577+ x__x_time_day : '1970-01-01T00:00:00.000Z' ,
578+ } ,
579+ ] ,
580+ } ,
581+ {
582+ preAggregationId : 'A.adex_cumulative_with_join_paths' ,
583+ addTimeRange : true ,
584+ expectedData : [ ] ,
585+ } ,
586+ {
587+ preAggregationId : 'A.ad_without_join_paths' ,
588+ addTimeRange : false ,
589+ expectedData : [
590+ {
591+ a__a_id : 1 ,
592+ a__a_seg : false ,
593+ a__a_sum : '100' ,
594+ d__d_id : 1 ,
595+ d__d_name_for_no_join_paths : 'foo' ,
596+ d__d_seg : false ,
597+ d__d_time_day : '1970-01-01T00:00:00.000Z' ,
598+ } ,
599+ ] ,
600+ } ,
521601 ] ;
522- for ( const preAggregationId of preAggregationIds ) {
602+ for ( const { preAggregationId, addTimeRange , expectedData } of preAggregationTests ) {
523603 // eslint-disable-next-line no-loop-func
524604 it ( `pre-aggregation ${ preAggregationId } should match its own references` , async ( ) => {
525- const preAggregations = cubeEvaluator . preAggregations ( { } ) ;
605+ // Always not using range, because reference query would have no range to start from
606+ // but should match pre-aggregation anyway
607+ const query = makeReferenceQueryFor ( preAggregationId ) ;
526608
527- const preAggregation = preAggregations
528- . find ( p => p . id === preAggregationId ) ;
529- if ( preAggregation === undefined ) {
530- throw expect ( preAggregation ) . toBeDefined ( ) ;
609+ const preAggregationsDescription : any = query . preAggregations ?. preAggregationsDescription ( ) ;
610+ const preAggregationFromQuery = preAggregationsDescription . find ( p => p . preAggregationId === preAggregationId ) ;
611+ if ( preAggregationFromQuery === undefined ) {
612+ throw expect ( preAggregationFromQuery ) . toBeDefined ( ) ;
531613 }
532614
533- const query = new PostgresQuery ( { joinGraph, cubeEvaluator, compiler } , {
534- ...preAggregation . references ,
535- preAggregationId : preAggregation . id ,
536- } ) ;
615+ expect ( preAggregationFromQuery . preAggregationId ) . toBe ( preAggregationId ) ;
616+ } ) ;
617+
618+ // eslint-disable-next-line no-loop-func
619+ it ( `pre-aggregation ${ preAggregationId } reference query should be executable` , async ( ) => {
620+ // Adding date range for rolling window measure
621+ const query = makeReferenceQueryFor ( preAggregationId , addTimeRange ) ;
537622
538623 const preAggregationsDescription : any = query . preAggregations ?. preAggregationsDescription ( ) ;
539- const preAggregationFromQuery = preAggregationsDescription . find ( p => p . preAggregationId === preAggregation . id ) ;
624+ const preAggregationFromQuery = preAggregationsDescription . find ( p => p . preAggregationId === preAggregationId ) ;
540625 if ( preAggregationFromQuery === undefined ) {
541626 throw expect ( preAggregationFromQuery ) . toBeDefined ( ) ;
542627 }
543628
544629 expect ( preAggregationFromQuery . preAggregationId ) . toBe ( preAggregationId ) ;
630+
631+ const res = await testWithPreAggregation ( preAggregationFromQuery , query ) ;
632+ expect ( res ) . toEqual ( expectedData ) ;
545633 } ) ;
546634 }
547635 } ) ;
0 commit comments