|
|
|
@ -348,12 +348,12 @@ try_nestloop_path(PlannerInfo *root, |
|
|
|
|
*/ |
|
|
|
|
static void |
|
|
|
|
try_partial_nestloop_path(PlannerInfo *root, |
|
|
|
|
RelOptInfo *joinrel, |
|
|
|
|
Path *outer_path, |
|
|
|
|
Path *inner_path, |
|
|
|
|
List *pathkeys, |
|
|
|
|
JoinType jointype, |
|
|
|
|
JoinPathExtraData *extra) |
|
|
|
|
RelOptInfo *joinrel, |
|
|
|
|
Path *outer_path, |
|
|
|
|
Path *inner_path, |
|
|
|
|
List *pathkeys, |
|
|
|
|
JoinType jointype, |
|
|
|
|
JoinPathExtraData *extra) |
|
|
|
|
{ |
|
|
|
|
JoinCostWorkspace workspace; |
|
|
|
|
|
|
|
|
@ -373,8 +373,8 @@ try_partial_nestloop_path(PlannerInfo *root, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Before creating a path, get a quick lower bound on what it is likely |
|
|
|
|
* to cost. Bail out right away if it looks terrible. |
|
|
|
|
* Before creating a path, get a quick lower bound on what it is likely to |
|
|
|
|
* cost. Bail out right away if it looks terrible. |
|
|
|
|
*/ |
|
|
|
|
initial_cost_nestloop(root, &workspace, jointype, |
|
|
|
|
outer_path, inner_path, |
|
|
|
@ -384,17 +384,17 @@ try_partial_nestloop_path(PlannerInfo *root, |
|
|
|
|
|
|
|
|
|
/* Might be good enough to be worth trying, so let's try it. */ |
|
|
|
|
add_partial_path(joinrel, (Path *) |
|
|
|
|
create_nestloop_path(root, |
|
|
|
|
joinrel, |
|
|
|
|
jointype, |
|
|
|
|
&workspace, |
|
|
|
|
extra->sjinfo, |
|
|
|
|
&extra->semifactors, |
|
|
|
|
outer_path, |
|
|
|
|
inner_path, |
|
|
|
|
extra->restrictlist, |
|
|
|
|
pathkeys, |
|
|
|
|
NULL)); |
|
|
|
|
create_nestloop_path(root, |
|
|
|
|
joinrel, |
|
|
|
|
jointype, |
|
|
|
|
&workspace, |
|
|
|
|
extra->sjinfo, |
|
|
|
|
&extra->semifactors, |
|
|
|
|
outer_path, |
|
|
|
|
inner_path, |
|
|
|
|
extra->restrictlist, |
|
|
|
|
pathkeys, |
|
|
|
|
NULL)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -571,8 +571,8 @@ try_partial_hashjoin_path(PlannerInfo *root, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Before creating a path, get a quick lower bound on what it is likely |
|
|
|
|
* to cost. Bail out right away if it looks terrible. |
|
|
|
|
* Before creating a path, get a quick lower bound on what it is likely to |
|
|
|
|
* cost. Bail out right away if it looks terrible. |
|
|
|
|
*/ |
|
|
|
|
initial_cost_hashjoin(root, &workspace, jointype, hashclauses, |
|
|
|
|
outer_path, inner_path, |
|
|
|
@ -582,17 +582,17 @@ try_partial_hashjoin_path(PlannerInfo *root, |
|
|
|
|
|
|
|
|
|
/* Might be good enough to be worth trying, so let's try it. */ |
|
|
|
|
add_partial_path(joinrel, (Path *) |
|
|
|
|
create_hashjoin_path(root, |
|
|
|
|
joinrel, |
|
|
|
|
jointype, |
|
|
|
|
&workspace, |
|
|
|
|
extra->sjinfo, |
|
|
|
|
&extra->semifactors, |
|
|
|
|
outer_path, |
|
|
|
|
inner_path, |
|
|
|
|
extra->restrictlist, |
|
|
|
|
NULL, |
|
|
|
|
hashclauses)); |
|
|
|
|
create_hashjoin_path(root, |
|
|
|
|
joinrel, |
|
|
|
|
jointype, |
|
|
|
|
&workspace, |
|
|
|
|
extra->sjinfo, |
|
|
|
|
&extra->semifactors, |
|
|
|
|
outer_path, |
|
|
|
|
inner_path, |
|
|
|
|
extra->restrictlist, |
|
|
|
|
NULL, |
|
|
|
|
hashclauses)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -1189,11 +1189,11 @@ match_unsorted_outer(PlannerInfo *root, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If the joinrel is parallel-safe and the join type supports nested loops, |
|
|
|
|
* we may be able to consider a partial nestloop plan. However, we can't |
|
|
|
|
* handle JOIN_UNIQUE_OUTER, because the outer path will be partial, and |
|
|
|
|
* therefore we won't be able to properly guarantee uniqueness. Nor can |
|
|
|
|
* we handle extra_lateral_rels, since partial paths must not be |
|
|
|
|
* If the joinrel is parallel-safe and the join type supports nested |
|
|
|
|
* loops, we may be able to consider a partial nestloop plan. However, we |
|
|
|
|
* can't handle JOIN_UNIQUE_OUTER, because the outer path will be partial, |
|
|
|
|
* and therefore we won't be able to properly guarantee uniqueness. Nor |
|
|
|
|
* can we handle extra_lateral_rels, since partial paths must not be |
|
|
|
|
* parameterized. |
|
|
|
|
*/ |
|
|
|
|
if (joinrel->consider_parallel && nestjoinOK && |
|
|
|
@ -1235,10 +1235,10 @@ consider_parallel_nestloop(PlannerInfo *root, |
|
|
|
|
outerpath->pathkeys); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Try the cheapest parameterized paths; only those which will |
|
|
|
|
* produce an unparameterized path when joined to this outerrel |
|
|
|
|
* will survive try_partial_nestloop_path. The cheapest |
|
|
|
|
* unparameterized path is also in this list. |
|
|
|
|
* Try the cheapest parameterized paths; only those which will produce |
|
|
|
|
* an unparameterized path when joined to this outerrel will survive |
|
|
|
|
* try_partial_nestloop_path. The cheapest unparameterized path is |
|
|
|
|
* also in this list. |
|
|
|
|
*/ |
|
|
|
|
foreach(lc2, innerrel->cheapest_parameterized_paths) |
|
|
|
|
{ |
|
|
|
@ -1250,16 +1250,17 @@ consider_parallel_nestloop(PlannerInfo *root, |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Like match_unsorted_outer, we only consider a single nestloop |
|
|
|
|
* path when the jointype is JOIN_UNIQUE_INNER. But we have to scan |
|
|
|
|
* cheapest_parameterized_paths to find the one we want to consider, |
|
|
|
|
* because cheapest_total_path might not be parallel-safe. |
|
|
|
|
* path when the jointype is JOIN_UNIQUE_INNER. But we have to |
|
|
|
|
* scan cheapest_parameterized_paths to find the one we want to |
|
|
|
|
* consider, because cheapest_total_path might not be |
|
|
|
|
* parallel-safe. |
|
|
|
|
*/ |
|
|
|
|
if (jointype == JOIN_UNIQUE_INNER) |
|
|
|
|
{ |
|
|
|
|
if (!bms_is_empty(PATH_REQ_OUTER(innerpath))) |
|
|
|
|
continue; |
|
|
|
|
innerpath = (Path *) create_unique_path(root, innerrel, |
|
|
|
|
innerpath, extra->sjinfo); |
|
|
|
|
innerpath, extra->sjinfo); |
|
|
|
|
Assert(innerpath); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1456,8 +1457,8 @@ hash_inner_and_outer(PlannerInfo *root, |
|
|
|
|
outerrel->partial_pathlist != NIL && |
|
|
|
|
bms_is_empty(joinrel->lateral_relids)) |
|
|
|
|
{ |
|
|
|
|
Path *cheapest_partial_outer; |
|
|
|
|
Path *cheapest_safe_inner = NULL; |
|
|
|
|
Path *cheapest_partial_outer; |
|
|
|
|
Path *cheapest_safe_inner = NULL; |
|
|
|
|
|
|
|
|
|
cheapest_partial_outer = |
|
|
|
|
(Path *) linitial(outerrel->partial_pathlist); |
|
|
|
|