@@ -2180,15 +2180,16 @@ export class BaseQuery {
21802180 const memberPathArray = [ cubeName , name ] ;
21812181 const memberPath = this . cubeEvaluator . pathFromArray ( memberPathArray ) ;
21822182 let type = memberExpressionType ;
2183- if ( ! type && this . cubeEvaluator . isMeasure ( memberPathArray ) ) {
2184- type = 'measure' ;
2185- }
2186- if ( ! type && this . cubeEvaluator . isDimension ( memberPathArray ) ) {
2187- type = 'dimension' ;
2188- }
2189- if ( ! type && this . cubeEvaluator . isSegment ( memberPathArray ) ) {
2190- type = 'segment' ;
2183+ if ( ! type ) {
2184+ if ( this . cubeEvaluator . isMeasure ( memberPathArray ) ) {
2185+ type = 'measure' ;
2186+ } else if ( this . cubeEvaluator . isDimension ( memberPathArray ) ) {
2187+ type = 'dimension' ;
2188+ } else if ( this . cubeEvaluator . isSegment ( memberPathArray ) ) {
2189+ type = 'segment' ;
2190+ }
21912191 }
2192+
21922193 const parentMember = this . safeEvaluateSymbolContext ( ) . currentMember ;
21932194 if ( this . safeEvaluateSymbolContext ( ) . memberChildren && parentMember ) {
21942195 this . safeEvaluateSymbolContext ( ) . memberChildren [ parentMember ] = this . safeEvaluateSymbolContext ( ) . memberChildren [ parentMember ] || [ ] ;
@@ -2358,7 +2359,7 @@ export class BaseQuery {
23582359
23592360 /**
23602361 * Evaluate escaped SQL-alias for cube or cube's property
2361- * (measure, dimention ).
2362+ * (measure, dimension ).
23622363 * @param {string } cubeName
23632364 * @returns string
23642365 */
@@ -3529,25 +3530,29 @@ export class BaseQuery {
35293530 static extractFilterMembers ( filter ) {
35303531 if ( filter . operator === 'and' || filter . operator === 'or' ) {
35313532 return filter . values . map ( f => BaseQuery . extractFilterMembers ( f ) ) . reduce ( ( a , b ) => ( ( a && b ) ? { ...a , ...b } : null ) , { } ) ;
3532- } else if ( filter . measure || filter . dimension ) {
3533+ } else if ( filter . measure ) {
3534+ return {
3535+ [ filter . measure ] : true
3536+ } ;
3537+ } else if ( filter . dimension ) {
35333538 return {
3534- [ filter . measure || filter . dimension ] : true
3539+ [ filter . dimension ] : true
35353540 } ;
35363541 } else {
35373542 return null ;
35383543 }
35393544 }
35403545
3541- static findAndSubTreeForFilterGroup ( filter , groupMembers , newGroupFilter ) {
3546+ static findAndSubTreeForFilterGroup ( filter , groupMembers , newGroupFilter , aliases ) {
35423547 if ( ( filter . operator === 'and' || filter . operator === 'or' ) && ! filter . values ?. length ) {
35433548 return null ;
35443549 }
35453550 const filterMembers = BaseQuery . extractFilterMembers ( filter ) ;
3546- if ( filterMembers && Object . keys ( filterMembers ) . every ( m => groupMembers . indexOf ( m ) !== - 1 ) ) {
3551+ if ( filterMembers && Object . keys ( filterMembers ) . every ( m => ( groupMembers . indexOf ( m ) !== - 1 || aliases . indexOf ( m ) !== - 1 ) ) ) {
35473552 return filter ;
35483553 }
35493554 if ( filter . operator === 'and' ) {
3550- const result = filter . values . map ( f => BaseQuery . findAndSubTreeForFilterGroup ( f , groupMembers , newGroupFilter ) ) . filter ( f => ! ! f ) ;
3555+ const result = filter . values . map ( f => BaseQuery . findAndSubTreeForFilterGroup ( f , groupMembers , newGroupFilter , aliases ) ) . filter ( f => ! ! f ) ;
35513556 if ( ! result . length ) {
35523557 return null ;
35533558 }
@@ -3572,21 +3577,30 @@ export class BaseQuery {
35723577 ) ;
35733578 }
35743579
3575- static renderFilterParams ( filter , filterParamArgs , allocateParam , newGroupFilter ) {
3580+ static renderFilterParams ( filter , filterParamArgs , allocateParam , newGroupFilter , aliases ) {
35763581 if ( ! filter ) {
35773582 return '1 = 1' ;
35783583 }
35793584
35803585 if ( filter . operator === 'and' || filter . operator === 'or' ) {
35813586 const values = filter . values
3582- . map ( f => BaseQuery . renderFilterParams ( f , filterParamArgs , allocateParam , newGroupFilter ) )
3587+ . map ( f => BaseQuery . renderFilterParams ( f , filterParamArgs , allocateParam , newGroupFilter , aliases ) )
35833588 . map ( v => ( { filterToWhere : ( ) => v } ) ) ;
35843589
35853590 return newGroupFilter ( { operator : filter . operator , values } ) . filterToWhere ( ) ;
35863591 }
35873592
3588- const filterParams = filter && filter . filterParams ( ) ;
3589- const filterParamArg = filterParamArgs . filter ( p => p . __member ( ) === filter . measure || p . __member ( ) === filter . dimension ) [ 0 ] ;
3593+ const filterParams = filter . filterParams ( ) ;
3594+ const filterParamArg = filterParamArgs . filter ( p => {
3595+ const member = p . __member ( ) ;
3596+ return member === filter . measure ||
3597+ member === filter . dimension ||
3598+ ( aliases [ member ] && (
3599+ aliases [ member ] === filter . measure ||
3600+ aliases [ member ] === filter . dimension
3601+ ) ) ;
3602+ } ) [ 0 ] ;
3603+
35903604 if ( ! filterParamArg ) {
35913605 throw new Error ( `FILTER_PARAMS arg not found for ${ filter . measure || filter . dimension } ` ) ;
35923606 }
@@ -3619,15 +3633,25 @@ export class BaseQuery {
36193633 return f . __member ( ) ;
36203634 } ) ;
36213635
3622- const filter = BaseQuery . findAndSubTreeForFilterGroup ( newGroupFilter ( { operator : 'and' , values : allFilters } ) , groupMembers , newGroupFilter ) ;
3636+ const aliases = allFilters ?
3637+ allFilters
3638+ . map ( v => ( v . query ? v . query . allBackAliasMembersExceptSegments ( ) : { } ) )
3639+ . reduce ( ( a , b ) => ( { ...a , ...b } ) , { } )
3640+ : { } ;
3641+ const filter = BaseQuery . findAndSubTreeForFilterGroup (
3642+ newGroupFilter ( { operator : 'and' , values : allFilters } ) ,
3643+ groupMembers ,
3644+ newGroupFilter ,
3645+ Object . values ( aliases )
3646+ ) ;
36233647
3624- return `(${ BaseQuery . renderFilterParams ( filter , filterParamArgs , allocateParam , newGroupFilter ) } )` ;
3648+ return `(${ BaseQuery . renderFilterParams ( filter , filterParamArgs , allocateParam , newGroupFilter , aliases ) } )` ;
36253649 } ;
36263650 }
36273651
36283652 static filterProxyFromAllFilters ( allFilters , cubeEvaluator , allocateParam , newGroupFilter ) {
36293653 return new Proxy ( { } , {
3630- get : ( target , name ) => {
3654+ get : ( _target , name ) => {
36313655 if ( name === '_objectWithResolvedProperties' ) {
36323656 return true ;
36333657 }
@@ -3644,17 +3668,75 @@ export class BaseQuery {
36443668 return cubeEvaluator . pathFromArray ( [ cubeNameObj . cube , propertyName ] ) ;
36453669 } ,
36463670 toString ( ) {
3671+ // Segments should be excluded because they are evaluated separately in cubeReferenceProxy
3672+ // In other case this falls into the recursive loop/stack exceeded caused by:
3673+ // collectFrom() -> traverseSymbol() -> evaluateSymbolSql() ->
3674+ // evaluateSql() -> resolveSymbolsCall() -> cubeReferenceProxy->toString() ->
3675+ // evaluateSymbolSql() -> evaluateSql()... -> and got here again
3676+ const aliases = allFilters ?
3677+ allFilters
3678+ . map ( v => ( v . query ? v . query . allBackAliasMembersExceptSegments ( ) : { } ) )
3679+ . reduce ( ( a , b ) => ( { ...a , ...b } ) , { } )
3680+ : { } ;
3681+ // Filtering aliases that somehow relate to this cube
3682+ const filteredAliases = Object . entries ( aliases )
3683+ . filter ( ( [ key , value ] ) => key . startsWith ( cubeNameObj . cube ) || value . startsWith ( cubeNameObj . cube ) )
3684+ . reduce ( ( acc , [ key , value ] ) => ( { ...acc , [ key ] : value } ) , { } ) ;
36473685 const filter = BaseQuery . findAndSubTreeForFilterGroup (
36483686 newGroupFilter ( { operator : 'and' , values : allFilters } ) ,
36493687 [ cubeEvaluator . pathFromArray ( [ cubeNameObj . cube , propertyName ] ) ] ,
3650- newGroupFilter
3688+ newGroupFilter ,
3689+ Object . values ( filteredAliases )
36513690 ) ;
3652- return `(${ BaseQuery . renderFilterParams ( filter , [ this ] , allocateParam , newGroupFilter ) } )` ;
3691+
3692+ return `(${ BaseQuery . renderFilterParams ( filter , [ this ] , allocateParam , newGroupFilter , aliases ) } )` ;
36533693 }
36543694 } )
36553695 } )
36563696 } ) ;
36573697 }
36583698 } ) ;
36593699 }
3700+
3701+ flattenAllMembers ( excludeSegments = false ) {
3702+ return R . flatten (
3703+ this . measures
3704+ . concat ( this . dimensions )
3705+ . concat ( excludeSegments ? [ ] : this . segments )
3706+ . concat ( this . filters )
3707+ . concat ( this . measureFilters )
3708+ . concat ( this . timeDimensions )
3709+ . map ( m => m . getMembers ( ) ) ,
3710+ ) ;
3711+ }
3712+
3713+ allBackAliasMembersExceptSegments ( ) {
3714+ return this . backAliasMembers ( this . flattenAllMembers ( true ) ) ;
3715+ }
3716+
3717+ allBackAliasMembers ( ) {
3718+ return this . backAliasMembers ( this . flattenAllMembers ( ) ) ;
3719+ }
3720+
3721+ backAliasMembers ( members ) {
3722+ const query = this ;
3723+ return members . map (
3724+ member => {
3725+ const collectedMembers = query
3726+ . collectFrom ( [ member ] , query . collectMemberNamesFor . bind ( query ) , 'collectMemberNamesFor' ) ;
3727+ const memberPath = member . expressionPath ( ) ;
3728+ let nonAliasSeen = false ;
3729+ return collectedMembers
3730+ . filter ( d => {
3731+ if ( ! query . cubeEvaluator . byPathAnyType ( d ) . aliasMember ) {
3732+ nonAliasSeen = true ;
3733+ }
3734+ return ! nonAliasSeen ;
3735+ } )
3736+ . map ( d => (
3737+ { [ query . cubeEvaluator . byPathAnyType ( d ) . aliasMember ] : memberPath }
3738+ ) ) . reduce ( ( a , b ) => ( { ...a , ...b } ) , { } ) ;
3739+ }
3740+ ) . reduce ( ( a , b ) => ( { ...a , ...b } ) , { } ) ;
3741+ }
36603742}
0 commit comments