@ -49,6 +49,9 @@ static List *subbuild_joinrel_restrictlist(RelOptInfo *joinrel,
static List * subbuild_joinrel_joinlist ( RelOptInfo * joinrel ,
List * joininfo_list ,
List * new_joininfo ) ;
static void set_foreign_rel_properties ( RelOptInfo * joinrel ,
RelOptInfo * outer_rel , RelOptInfo * inner_rel ) ;
static void add_join_rel ( PlannerInfo * root , RelOptInfo * joinrel ) ;
/*
@ -327,6 +330,82 @@ find_join_rel(PlannerInfo *root, Relids relids)
return NULL ;
}
/*
* set_foreign_rel_properties
* Set up foreign - join fields if outer and inner relation are foreign
* tables ( or joins ) belonging to the same server and assigned to the same
* user to check access permissions as .
*
* In addition to an exact match of userid , we allow the case where one side
* has zero userid ( implying current user ) and the other side has explicit
* userid that happens to equal the current user ; but in that case , pushdown of
* the join is only valid for the current user . The useridiscurrent field
* records whether we had to make such an assumption for this join or any
* sub - join .
*
* Otherwise these fields are left invalid , so GetForeignJoinPaths will not be
* called for the join relation .
*
*/
static void
set_foreign_rel_properties ( RelOptInfo * joinrel , RelOptInfo * outer_rel ,
RelOptInfo * inner_rel )
{
if ( OidIsValid ( outer_rel - > serverid ) & &
inner_rel - > serverid = = outer_rel - > serverid )
{
if ( inner_rel - > userid = = outer_rel - > userid )
{
joinrel - > serverid = outer_rel - > serverid ;
joinrel - > userid = outer_rel - > userid ;
joinrel - > useridiscurrent = outer_rel - > useridiscurrent | | inner_rel - > useridiscurrent ;
joinrel - > fdwroutine = outer_rel - > fdwroutine ;
}
else if ( ! OidIsValid ( inner_rel - > userid ) & &
outer_rel - > userid = = GetUserId ( ) )
{
joinrel - > serverid = outer_rel - > serverid ;
joinrel - > userid = outer_rel - > userid ;
joinrel - > useridiscurrent = true ;
joinrel - > fdwroutine = outer_rel - > fdwroutine ;
}
else if ( ! OidIsValid ( outer_rel - > userid ) & &
inner_rel - > userid = = GetUserId ( ) )
{
joinrel - > serverid = outer_rel - > serverid ;
joinrel - > userid = inner_rel - > userid ;
joinrel - > useridiscurrent = true ;
joinrel - > fdwroutine = outer_rel - > fdwroutine ;
}
}
}
/*
* add_join_rel
* Add given join relation to the list of join relations in the given
* PlannerInfo . Also add it to the auxiliary hashtable if there is one .
*/
static void
add_join_rel ( PlannerInfo * root , RelOptInfo * joinrel )
{
/* GEQO requires us to append the new joinrel to the end of the list! */
root - > join_rel_list = lappend ( root - > join_rel_list , joinrel ) ;
/* store it into the auxiliary hashtable if there is one. */
if ( root - > join_rel_hash )
{
JoinHashEntry * hentry ;
bool found ;
hentry = ( JoinHashEntry * ) hash_search ( root - > join_rel_hash ,
& ( joinrel - > relids ) ,
HASH_ENTER ,
& found ) ;
Assert ( ! found ) ;
hentry - > join_rel = joinrel ;
}
}
/*
* build_join_rel
* Returns relation entry corresponding to the union of two given rels ,
@ -425,46 +504,8 @@ build_join_rel(PlannerInfo *root,
joinrel - > joininfo = NIL ;
joinrel - > has_eclass_joins = false ;
/*
* Set up foreign - join fields if outer and inner relation are foreign
* tables ( or joins ) belonging to the same server and assigned to the same
* user to check access permissions as . In addition to an exact match of
* userid , we allow the case where one side has zero userid ( implying
* current user ) and the other side has explicit userid that happens to
* equal the current user ; but in that case , pushdown of the join is only
* valid for the current user . The useridiscurrent field records whether
* we had to make such an assumption for this join or any sub - join .
*
* Otherwise these fields are left invalid , so GetForeignJoinPaths will
* not be called for the join relation .
*/
if ( OidIsValid ( outer_rel - > serverid ) & &
inner_rel - > serverid = = outer_rel - > serverid )
{
if ( inner_rel - > userid = = outer_rel - > userid )
{
joinrel - > serverid = outer_rel - > serverid ;
joinrel - > userid = outer_rel - > userid ;
joinrel - > useridiscurrent = outer_rel - > useridiscurrent | | inner_rel - > useridiscurrent ;
joinrel - > fdwroutine = outer_rel - > fdwroutine ;
}
else if ( ! OidIsValid ( inner_rel - > userid ) & &
outer_rel - > userid = = GetUserId ( ) )
{
joinrel - > serverid = outer_rel - > serverid ;
joinrel - > userid = outer_rel - > userid ;
joinrel - > useridiscurrent = true ;
joinrel - > fdwroutine = outer_rel - > fdwroutine ;
}
else if ( ! OidIsValid ( outer_rel - > userid ) & &
inner_rel - > userid = = GetUserId ( ) )
{
joinrel - > serverid = outer_rel - > serverid ;
joinrel - > userid = inner_rel - > userid ;
joinrel - > useridiscurrent = true ;
joinrel - > fdwroutine = outer_rel - > fdwroutine ;
}
}
/* Compute information relevant to the foreign relations. */
set_foreign_rel_properties ( joinrel , outer_rel , inner_rel ) ;
/*
* Create a new tlist containing just the vars that need to be output from
@ -532,25 +573,8 @@ build_join_rel(PlannerInfo *root,
is_parallel_safe ( root , ( Node * ) joinrel - > reltarget - > exprs ) )
joinrel - > consider_parallel = true ;
/*
* Add the joinrel to the query ' s joinrel list , and store it into the
* auxiliary hashtable if there is one . NB : GEQO requires us to append
* the new joinrel to the end of the list !
*/
root - > join_rel_list = lappend ( root - > join_rel_list , joinrel ) ;
if ( root - > join_rel_hash )
{
JoinHashEntry * hentry ;
bool found ;
hentry = ( JoinHashEntry * ) hash_search ( root - > join_rel_hash ,
& ( joinrel - > relids ) ,
HASH_ENTER ,
& found ) ;
Assert ( ! found ) ;
hentry - > join_rel = joinrel ;
}
/* Add the joinrel to the PlannerInfo. */
add_join_rel ( root , joinrel ) ;
/*
* Also , if dynamic - programming join search is active , add the new joinrel