@ -29,19 +29,19 @@ static void sort_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel,
RelOptInfo * outerrel , RelOptInfo * innerrel ,
RelOptInfo * outerrel , RelOptInfo * innerrel ,
List * restrictlist , List * mergeclause_list ,
List * restrictlist , List * mergeclause_list ,
JoinType jointype , SpecialJoinInfo * sjinfo ,
JoinType jointype , SpecialJoinInfo * sjinfo ,
Relids param_source_rels ) ;
Relids param_source_rels , Relids extra_lateral_rels ) ;
static void match_unsorted_outer ( PlannerInfo * root , RelOptInfo * joinrel ,
static void match_unsorted_outer ( PlannerInfo * root , RelOptInfo * joinrel ,
RelOptInfo * outerrel , RelOptInfo * innerrel ,
RelOptInfo * outerrel , RelOptInfo * innerrel ,
List * restrictlist , List * mergeclause_list ,
List * restrictlist , List * mergeclause_list ,
JoinType jointype , SpecialJoinInfo * sjinfo ,
JoinType jointype , SpecialJoinInfo * sjinfo ,
SemiAntiJoinFactors * semifactors ,
SemiAntiJoinFactors * semifactors ,
Relids param_source_rels ) ;
Relids param_source_rels , Relids extra_lateral_rels ) ;
static void hash_inner_and_outer ( PlannerInfo * root , RelOptInfo * joinrel ,
static void hash_inner_and_outer ( PlannerInfo * root , RelOptInfo * joinrel ,
RelOptInfo * outerrel , RelOptInfo * innerrel ,
RelOptInfo * outerrel , RelOptInfo * innerrel ,
List * restrictlist ,
List * restrictlist ,
JoinType jointype , SpecialJoinInfo * sjinfo ,
JoinType jointype , SpecialJoinInfo * sjinfo ,
SemiAntiJoinFactors * semifactors ,
SemiAntiJoinFactors * semifactors ,
Relids param_source_rels ) ;
Relids param_source_rels , Relids extra_lateral_rels ) ;
static List * select_mergejoin_clauses ( PlannerInfo * root ,
static List * select_mergejoin_clauses ( PlannerInfo * root ,
RelOptInfo * joinrel ,
RelOptInfo * joinrel ,
RelOptInfo * outerrel ,
RelOptInfo * outerrel ,
@ -87,6 +87,7 @@ add_paths_to_joinrel(PlannerInfo *root,
bool mergejoin_allowed = true ;
bool mergejoin_allowed = true ;
SemiAntiJoinFactors semifactors ;
SemiAntiJoinFactors semifactors ;
Relids param_source_rels = NULL ;
Relids param_source_rels = NULL ;
Relids extra_lateral_rels = NULL ;
ListCell * lc ;
ListCell * lc ;
/*
/*
@ -162,12 +163,49 @@ add_paths_to_joinrel(PlannerInfo *root,
{
{
LateralJoinInfo * ljinfo = ( LateralJoinInfo * ) lfirst ( lc ) ;
LateralJoinInfo * ljinfo = ( LateralJoinInfo * ) lfirst ( lc ) ;
if ( bms_is_member ( ljinfo - > lateral_rhs , joinrel - > relids ) )
if ( bms_is_subset ( ljinfo - > lateral_rhs , joinrel - > relids ) )
param_source_rels = bms_join ( param_source_rels ,
param_source_rels = bms_join ( param_source_rels ,
bms_difference ( ljinfo - > lateral_lhs ,
bms_difference ( ljinfo - > lateral_lhs ,
joinrel - > relids ) ) ;
joinrel - > relids ) ) ;
}
}
/*
* Another issue created by LATERAL references is that PlaceHolderVars
* that need to be computed at this join level might contain lateral
* references to rels not in the join , meaning that the paths for the join
* would need to be marked as parameterized by those rels , independently
* of all other considerations . Set extra_lateral_rels to the set of such
* rels . This will not affect our decisions as to which paths to
* generate ; we merely add these rels to their required_outer sets .
*/
foreach ( lc , root - > placeholder_list )
{
PlaceHolderInfo * phinfo = ( PlaceHolderInfo * ) lfirst ( lc ) ;
/* PHVs without lateral refs can be skipped over quickly */
if ( phinfo - > ph_lateral = = NULL )
continue ;
/* Is it due to be evaluated at this join, and not in either input? */
if ( bms_is_subset ( phinfo - > ph_eval_at , joinrel - > relids ) & &
! bms_is_subset ( phinfo - > ph_eval_at , outerrel - > relids ) & &
! bms_is_subset ( phinfo - > ph_eval_at , innerrel - > relids ) )
{
/* Yes, remember its lateral rels */
extra_lateral_rels = bms_add_members ( extra_lateral_rels ,
phinfo - > ph_lateral ) ;
}
}
/*
* Make sure extra_lateral_rels doesn ' t list anything within the join , and
* that it ' s NULL if empty . ( This allows us to use bms_add_members to add
* it to required_outer below , while preserving the property that
* required_outer is exactly NULL if empty . )
*/
extra_lateral_rels = bms_del_members ( extra_lateral_rels , joinrel - > relids ) ;
if ( bms_is_empty ( extra_lateral_rels ) )
extra_lateral_rels = NULL ;
/*
/*
* 1. Consider mergejoin paths where both relations must be explicitly
* 1. Consider mergejoin paths where both relations must be explicitly
* sorted . Skip this if we can ' t mergejoin .
* sorted . Skip this if we can ' t mergejoin .
@ -175,7 +213,8 @@ add_paths_to_joinrel(PlannerInfo *root,
if ( mergejoin_allowed )
if ( mergejoin_allowed )
sort_inner_and_outer ( root , joinrel , outerrel , innerrel ,
sort_inner_and_outer ( root , joinrel , outerrel , innerrel ,
restrictlist , mergeclause_list , jointype ,
restrictlist , mergeclause_list , jointype ,
sjinfo , param_source_rels ) ;
sjinfo ,
param_source_rels , extra_lateral_rels ) ;
/*
/*
* 2. Consider paths where the outer relation need not be explicitly
* 2. Consider paths where the outer relation need not be explicitly
@ -187,7 +226,8 @@ add_paths_to_joinrel(PlannerInfo *root,
if ( mergejoin_allowed )
if ( mergejoin_allowed )
match_unsorted_outer ( root , joinrel , outerrel , innerrel ,
match_unsorted_outer ( root , joinrel , outerrel , innerrel ,
restrictlist , mergeclause_list , jointype ,
restrictlist , mergeclause_list , jointype ,
sjinfo , & semifactors , param_source_rels ) ;
sjinfo , & semifactors ,
param_source_rels , extra_lateral_rels ) ;
# ifdef NOT_USED
# ifdef NOT_USED
@ -205,7 +245,8 @@ add_paths_to_joinrel(PlannerInfo *root,
if ( mergejoin_allowed )
if ( mergejoin_allowed )
match_unsorted_inner ( root , joinrel , outerrel , innerrel ,
match_unsorted_inner ( root , joinrel , outerrel , innerrel ,
restrictlist , mergeclause_list , jointype ,
restrictlist , mergeclause_list , jointype ,
sjinfo , & semifactors , param_source_rels ) ;
sjinfo , & semifactors ,
param_source_rels , extra_lateral_rels ) ;
# endif
# endif
/*
/*
@ -216,7 +257,8 @@ add_paths_to_joinrel(PlannerInfo *root,
if ( enable_hashjoin | | jointype = = JOIN_FULL )
if ( enable_hashjoin | | jointype = = JOIN_FULL )
hash_inner_and_outer ( root , joinrel , outerrel , innerrel ,
hash_inner_and_outer ( root , joinrel , outerrel , innerrel ,
restrictlist , jointype ,
restrictlist , jointype ,
sjinfo , & semifactors , param_source_rels ) ;
sjinfo , & semifactors ,
param_source_rels , extra_lateral_rels ) ;
}
}
/*
/*
@ -231,6 +273,7 @@ try_nestloop_path(PlannerInfo *root,
SpecialJoinInfo * sjinfo ,
SpecialJoinInfo * sjinfo ,
SemiAntiJoinFactors * semifactors ,
SemiAntiJoinFactors * semifactors ,
Relids param_source_rels ,
Relids param_source_rels ,
Relids extra_lateral_rels ,
Path * outer_path ,
Path * outer_path ,
Path * inner_path ,
Path * inner_path ,
List * restrict_clauses ,
List * restrict_clauses ,
@ -253,6 +296,12 @@ try_nestloop_path(PlannerInfo *root,
return ;
return ;
}
}
/*
* Independently of that , add parameterization needed for any
* PlaceHolderVars that need to be computed at the join .
*/
required_outer = bms_add_members ( required_outer , extra_lateral_rels ) ;
/*
/*
* Do a precheck to quickly eliminate obviously - inferior paths . We
* Do a precheck to quickly eliminate obviously - inferior paths . We
* calculate a cheap lower bound on the path ' s cost and then use
* calculate a cheap lower bound on the path ' s cost and then use
@ -301,6 +350,7 @@ try_mergejoin_path(PlannerInfo *root,
JoinType jointype ,
JoinType jointype ,
SpecialJoinInfo * sjinfo ,
SpecialJoinInfo * sjinfo ,
Relids param_source_rels ,
Relids param_source_rels ,
Relids extra_lateral_rels ,
Path * outer_path ,
Path * outer_path ,
Path * inner_path ,
Path * inner_path ,
List * restrict_clauses ,
List * restrict_clauses ,
@ -326,6 +376,12 @@ try_mergejoin_path(PlannerInfo *root,
return ;
return ;
}
}
/*
* Independently of that , add parameterization needed for any
* PlaceHolderVars that need to be computed at the join .
*/
required_outer = bms_add_members ( required_outer , extra_lateral_rels ) ;
/*
/*
* If the given paths are already well enough ordered , we can skip doing
* If the given paths are already well enough ordered , we can skip doing
* an explicit sort .
* an explicit sort .
@ -383,6 +439,7 @@ try_hashjoin_path(PlannerInfo *root,
SpecialJoinInfo * sjinfo ,
SpecialJoinInfo * sjinfo ,
SemiAntiJoinFactors * semifactors ,
SemiAntiJoinFactors * semifactors ,
Relids param_source_rels ,
Relids param_source_rels ,
Relids extra_lateral_rels ,
Path * outer_path ,
Path * outer_path ,
Path * inner_path ,
Path * inner_path ,
List * restrict_clauses ,
List * restrict_clauses ,
@ -405,6 +462,12 @@ try_hashjoin_path(PlannerInfo *root,
return ;
return ;
}
}
/*
* Independently of that , add parameterization needed for any
* PlaceHolderVars that need to be computed at the join .
*/
required_outer = bms_add_members ( required_outer , extra_lateral_rels ) ;
/*
/*
* See comments in try_nestloop_path ( ) . Also note that hashjoin paths
* See comments in try_nestloop_path ( ) . Also note that hashjoin paths
* never have any output pathkeys , per comments in create_hashjoin_path .
* never have any output pathkeys , per comments in create_hashjoin_path .
@ -483,6 +546,7 @@ clause_sides_match_join(RestrictInfo *rinfo, RelOptInfo *outerrel,
* ' jointype ' is the type of join to do
* ' jointype ' is the type of join to do
* ' sjinfo ' is extra info about the join for selectivity estimation
* ' sjinfo ' is extra info about the join for selectivity estimation
* ' param_source_rels ' are OK targets for parameterization of result paths
* ' param_source_rels ' are OK targets for parameterization of result paths
* ' extra_lateral_rels ' are additional parameterization for result paths
*/
*/
static void
static void
sort_inner_and_outer ( PlannerInfo * root ,
sort_inner_and_outer ( PlannerInfo * root ,
@ -493,7 +557,8 @@ sort_inner_and_outer(PlannerInfo *root,
List * mergeclause_list ,
List * mergeclause_list ,
JoinType jointype ,
JoinType jointype ,
SpecialJoinInfo * sjinfo ,
SpecialJoinInfo * sjinfo ,
Relids param_source_rels )
Relids param_source_rels ,
Relids extra_lateral_rels )
{
{
Path * outer_path ;
Path * outer_path ;
Path * inner_path ;
Path * inner_path ;
@ -623,6 +688,7 @@ sort_inner_and_outer(PlannerInfo *root,
jointype ,
jointype ,
sjinfo ,
sjinfo ,
param_source_rels ,
param_source_rels ,
extra_lateral_rels ,
outer_path ,
outer_path ,
inner_path ,
inner_path ,
restrictlist ,
restrictlist ,
@ -668,6 +734,7 @@ sort_inner_and_outer(PlannerInfo *root,
* ' sjinfo ' is extra info about the join for selectivity estimation
* ' sjinfo ' is extra info about the join for selectivity estimation
* ' semifactors ' contains valid data if jointype is SEMI or ANTI
* ' semifactors ' contains valid data if jointype is SEMI or ANTI
* ' param_source_rels ' are OK targets for parameterization of result paths
* ' param_source_rels ' are OK targets for parameterization of result paths
* ' extra_lateral_rels ' are additional parameterization for result paths
*/
*/
static void
static void
match_unsorted_outer ( PlannerInfo * root ,
match_unsorted_outer ( PlannerInfo * root ,
@ -679,7 +746,8 @@ match_unsorted_outer(PlannerInfo *root,
JoinType jointype ,
JoinType jointype ,
SpecialJoinInfo * sjinfo ,
SpecialJoinInfo * sjinfo ,
SemiAntiJoinFactors * semifactors ,
SemiAntiJoinFactors * semifactors ,
Relids param_source_rels )
Relids param_source_rels ,
Relids extra_lateral_rels )
{
{
JoinType save_jointype = jointype ;
JoinType save_jointype = jointype ;
bool nestjoinOK ;
bool nestjoinOK ;
@ -809,6 +877,7 @@ match_unsorted_outer(PlannerInfo *root,
sjinfo ,
sjinfo ,
semifactors ,
semifactors ,
param_source_rels ,
param_source_rels ,
extra_lateral_rels ,
outerpath ,
outerpath ,
inner_cheapest_total ,
inner_cheapest_total ,
restrictlist ,
restrictlist ,
@ -834,6 +903,7 @@ match_unsorted_outer(PlannerInfo *root,
sjinfo ,
sjinfo ,
semifactors ,
semifactors ,
param_source_rels ,
param_source_rels ,
extra_lateral_rels ,
outerpath ,
outerpath ,
innerpath ,
innerpath ,
restrictlist ,
restrictlist ,
@ -848,6 +918,7 @@ match_unsorted_outer(PlannerInfo *root,
sjinfo ,
sjinfo ,
semifactors ,
semifactors ,
param_source_rels ,
param_source_rels ,
extra_lateral_rels ,
outerpath ,
outerpath ,
matpath ,
matpath ,
restrictlist ,
restrictlist ,
@ -903,6 +974,7 @@ match_unsorted_outer(PlannerInfo *root,
jointype ,
jointype ,
sjinfo ,
sjinfo ,
param_source_rels ,
param_source_rels ,
extra_lateral_rels ,
outerpath ,
outerpath ,
inner_cheapest_total ,
inner_cheapest_total ,
restrictlist ,
restrictlist ,
@ -1001,6 +1073,7 @@ match_unsorted_outer(PlannerInfo *root,
jointype ,
jointype ,
sjinfo ,
sjinfo ,
param_source_rels ,
param_source_rels ,
extra_lateral_rels ,
outerpath ,
outerpath ,
innerpath ,
innerpath ,
restrictlist ,
restrictlist ,
@ -1046,6 +1119,7 @@ match_unsorted_outer(PlannerInfo *root,
jointype ,
jointype ,
sjinfo ,
sjinfo ,
param_source_rels ,
param_source_rels ,
extra_lateral_rels ,
outerpath ,
outerpath ,
innerpath ,
innerpath ,
restrictlist ,
restrictlist ,
@ -1080,6 +1154,7 @@ match_unsorted_outer(PlannerInfo *root,
* ' sjinfo ' is extra info about the join for selectivity estimation
* ' sjinfo ' is extra info about the join for selectivity estimation
* ' semifactors ' contains valid data if jointype is SEMI or ANTI
* ' semifactors ' contains valid data if jointype is SEMI or ANTI
* ' param_source_rels ' are OK targets for parameterization of result paths
* ' param_source_rels ' are OK targets for parameterization of result paths
* ' extra_lateral_rels ' are additional parameterization for result paths
*/
*/
static void
static void
hash_inner_and_outer ( PlannerInfo * root ,
hash_inner_and_outer ( PlannerInfo * root ,
@ -1090,7 +1165,8 @@ hash_inner_and_outer(PlannerInfo *root,
JoinType jointype ,
JoinType jointype ,
SpecialJoinInfo * sjinfo ,
SpecialJoinInfo * sjinfo ,
SemiAntiJoinFactors * semifactors ,
SemiAntiJoinFactors * semifactors ,
Relids param_source_rels )
Relids param_source_rels ,
Relids extra_lateral_rels )
{
{
bool isouterjoin = IS_OUTER_JOIN ( jointype ) ;
bool isouterjoin = IS_OUTER_JOIN ( jointype ) ;
List * hashclauses ;
List * hashclauses ;
@ -1164,6 +1240,7 @@ hash_inner_and_outer(PlannerInfo *root,
sjinfo ,
sjinfo ,
semifactors ,
semifactors ,
param_source_rels ,
param_source_rels ,
extra_lateral_rels ,
cheapest_total_outer ,
cheapest_total_outer ,
cheapest_total_inner ,
cheapest_total_inner ,
restrictlist ,
restrictlist ,
@ -1183,6 +1260,7 @@ hash_inner_and_outer(PlannerInfo *root,
sjinfo ,
sjinfo ,
semifactors ,
semifactors ,
param_source_rels ,
param_source_rels ,
extra_lateral_rels ,
cheapest_total_outer ,
cheapest_total_outer ,
cheapest_total_inner ,
cheapest_total_inner ,
restrictlist ,
restrictlist ,
@ -1195,6 +1273,7 @@ hash_inner_and_outer(PlannerInfo *root,
sjinfo ,
sjinfo ,
semifactors ,
semifactors ,
param_source_rels ,
param_source_rels ,
extra_lateral_rels ,
cheapest_startup_outer ,
cheapest_startup_outer ,
cheapest_total_inner ,
cheapest_total_inner ,
restrictlist ,
restrictlist ,
@ -1219,6 +1298,7 @@ hash_inner_and_outer(PlannerInfo *root,
sjinfo ,
sjinfo ,
semifactors ,
semifactors ,
param_source_rels ,
param_source_rels ,
extra_lateral_rels ,
cheapest_startup_outer ,
cheapest_startup_outer ,
cheapest_total_inner ,
cheapest_total_inner ,
restrictlist ,
restrictlist ,
@ -1256,6 +1336,7 @@ hash_inner_and_outer(PlannerInfo *root,
sjinfo ,
sjinfo ,
semifactors ,
semifactors ,
param_source_rels ,
param_source_rels ,
extra_lateral_rels ,
outerpath ,
outerpath ,
innerpath ,
innerpath ,
restrictlist ,
restrictlist ,