Skip to content
Open

Jppd #90

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
320 changes: 263 additions & 57 deletions src/backend/optimizer/path/allpaths.c

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/backend/optimizer/path/costsize.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ int max_parallel_workers_per_gather = 2;
bool enable_seqscan = true;
bool enable_indexscan = true;
bool enable_indexonlyscan = true;
bool enable_join_predicate_pushdown = true;
bool enable_bitmapscan = true;
bool enable_tidscan = true;
bool enable_sort = true;
Expand Down Expand Up @@ -6044,9 +6045,8 @@ get_foreign_key_join_selectivity(PlannerInfo *root,
* We set the same fields as set_baserel_size_estimates.
*/
void
set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel)
set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel, PlannerInfo *subroot)
{
PlannerInfo *subroot = rel->subroot;
RelOptInfo *sub_final_rel;
ListCell *lc;

Expand Down
58 changes: 56 additions & 2 deletions src/backend/optimizer/plan/createplan.c
Original file line number Diff line number Diff line change
Expand Up @@ -3544,17 +3544,69 @@ create_subqueryscan_plan(PlannerInfo *root, SubqueryScanPath *best_path,
RelOptInfo *rel = best_path->path.parent;
Index scan_relid = rel->relid;
Plan *subplan;
ListCell *l;
List *qpqual;
List *sq_quals = best_path->pushed_down_clauses;

/* it should be a subquery base rel... */
Assert(scan_relid > 0);
Assert(rel->rtekind == RTE_SUBQUERY);
Assert(rel->chosen_plan == NULL);

/*
* Recursively create Plan from Path for subquery. Since we are entering
* a different planner context (subroot), recurse to create_plan not
* create_plan_recurse.
*/
subplan = create_plan(rel->subroot, best_path->subpath);
subplan = create_plan(best_path->subroot, best_path->subpath);

/*
* If this path used join quals that were pushed down to the subquery,
* we don't need to re-check those quals on the SubqueryScan node itself.
*/
if (best_path->pushed_down_clauses)
{
List *new_clauses = NIL;
ListCell *l;

foreach(l, scan_clauses)
{
RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);

if (list_member_ptr(best_path->pushed_down_clauses, rinfo))
continue;

new_clauses = lappend(new_clauses, rinfo);
}
scan_clauses = new_clauses;
}

/*
* If we had pushed down any join clauses to the subquery, we don't need
* to re-check them in the SubqueryScan node.
*
* This only applies to join clauses derived from equivalence classes.
* Non-join quals, and non-EC-derived join clauses are immediately removed
* from 'baserestrictinfo' and 'joininfo' when they're pushed down, so we
* won't need to worry about them here.
*/
qpqual = NIL;
foreach (l, scan_clauses)
{
RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);

if (rinfo->pseudoconstant)
continue; /* we may drop pseudoconstants here */
if (list_member_ptr(sq_quals, rinfo))
continue; /* simple duplicate */
if (is_redundant_derived_clause(rinfo, sq_quals))
continue; /* derived from same EquivalenceClass */
if (!contain_mutable_functions((Node *) rinfo->clause) &&
predicate_implied_by(list_make1(rinfo->clause), sq_quals, false))
continue; /* provably implied by indexquals */
qpqual = lappend(qpqual, rinfo);
}
scan_clauses = qpqual;

/* Sort clauses into best execution order */
scan_clauses = order_qual_clauses(root, scan_clauses);
Expand All @@ -3575,7 +3627,7 @@ create_subqueryscan_plan(PlannerInfo *root, SubqueryScanPath *best_path,
if (best_path->path.param_info)
{
process_subquery_nestloop_params(root,
rel->subplan_params);
best_path->subplan_params);
scan_clauses = (List *)
replace_nestloop_params(root, (Node *) scan_clauses);
}
Expand All @@ -3587,6 +3639,8 @@ create_subqueryscan_plan(PlannerInfo *root, SubqueryScanPath *best_path,

copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);

rel->chosen_plan = best_path->subroot;

return scan_plan;
}

Expand Down
8 changes: 4 additions & 4 deletions src/backend/optimizer/plan/setrefs.c
Original file line number Diff line number Diff line change
Expand Up @@ -488,12 +488,12 @@ add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing)
* that some upper query level is treating this one as dummy,
* and so we won't scan this level's plan tree at all.
*/
if (rel->subroot == NULL)
if (rel->chosen_plan == NULL)
flatten_unplanned_rtes(glob, rte);
else if (recursing ||
IS_DUMMY_REL(fetch_upper_rel(rel->subroot,
IS_DUMMY_REL(fetch_upper_rel(rel->chosen_plan,
UPPERREL_FINAL, NULL)))
add_rtes_to_flat_rtable(rel->subroot, true);
add_rtes_to_flat_rtable(rel->chosen_plan, true);
}
}
rti++;
Expand Down Expand Up @@ -1460,7 +1460,7 @@ set_subqueryscan_references(PlannerInfo *root,
rel = find_base_rel(root, plan->scan.scanrelid);

/* Recursively process the subplan */
plan->subplan = set_plan_references(rel->subroot, plan->subplan);
plan->subplan = set_plan_references(rel->chosen_plan, plan->subplan);

if (trivial_subqueryscan(plan))
{
Expand Down
4 changes: 2 additions & 2 deletions src/backend/optimizer/plan/subselect.c
Original file line number Diff line number Diff line change
Expand Up @@ -2735,11 +2735,11 @@ finalize_plan(PlannerInfo *root, Plan *plan,

/* We must run finalize_plan on the subquery */
rel = find_base_rel(root, sscan->scan.scanrelid);
subquery_params = rel->subroot->outer_params;
subquery_params = rel->chosen_plan->outer_params;
if (gather_param >= 0)
subquery_params = bms_add_member(bms_copy(subquery_params),
gather_param);
finalize_plan(rel->subroot, sscan->subplan, gather_param,
finalize_plan(rel->chosen_plan, sscan->subplan, gather_param,
subquery_params, NULL);

/* Now we can add its extParams to the parent's params */
Expand Down
20 changes: 12 additions & 8 deletions src/backend/optimizer/prep/prepunion.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ recurse_set_operations(Node *setOp, PlannerInfo *root,
* suitably-sorted Paths.
*/
plan_name = choose_plan_name(root->glob, "setop", true);
subroot = rel->subroot = subquery_planner(root->glob, subquery,
subroot = subquery_planner(root->glob, subquery,
plan_name, root, NULL,
false, root->tuple_fraction,
parentOp);
Expand Down Expand Up @@ -491,7 +491,7 @@ build_setop_child_paths(PlannerInfo *root, RelOptInfo *rel,
List *interesting_pathkeys, double *pNumGroups)
{
RelOptInfo *final_rel;
List *setop_pathkeys = rel->subroot->setop_pathkeys;
List *setop_pathkeys = subroot->setop_pathkeys;
ListCell *lc;

/* it can't be a set op child rel if it's not a subquery */
Expand All @@ -509,13 +509,13 @@ build_setop_child_paths(PlannerInfo *root, RelOptInfo *rel,
* do this before generating outer-query paths, else cost_subqueryscan is
* not happy.
*/
set_subquery_size_estimates(root, rel);
set_subquery_size_estimates(root, rel, subroot);

/*
* Since we may want to add a partial path to this relation, we must set
* its consider_parallel flag correctly.
*/
final_rel = fetch_upper_rel(rel->subroot, UPPERREL_FINAL, NULL);
final_rel = fetch_upper_rel(subroot, UPPERREL_FINAL, NULL);
rel->consider_parallel = final_rel->consider_parallel;

/* Generate subquery scan paths for any interesting path in final_rel */
Expand Down Expand Up @@ -548,10 +548,12 @@ build_setop_child_paths(PlannerInfo *root, RelOptInfo *rel,
/* Generate outer path using this subpath */
add_path(rel, (Path *) create_subqueryscan_path(root,
rel,
rel->subroot,
NIL,
subpath,
trivial_tlist,
pathkeys,
NULL));
NULL, NIL));
}

/* skip dealing with sorted paths if the setop doesn't need them */
Expand Down Expand Up @@ -616,10 +618,12 @@ build_setop_child_paths(PlannerInfo *root, RelOptInfo *rel,
/* Generate outer path using this subpath */
add_path(rel, (Path *) create_subqueryscan_path(root,
rel,
rel->subroot,
NIL,
subpath,
trivial_tlist,
pathkeys,
NULL));
NULL, NIL));
}
}

Expand All @@ -640,9 +644,9 @@ build_setop_child_paths(PlannerInfo *root, RelOptInfo *rel,

partial_subpath = linitial(final_rel->partial_pathlist);
partial_path = (Path *)
create_subqueryscan_path(root, rel, partial_subpath,
create_subqueryscan_path(root, rel, rel->subroot, NIL, partial_subpath,
trivial_tlist,
NIL, NULL);
NIL, NULL, NIL);
add_partial_path(rel, partial_path);
}

Expand Down
15 changes: 12 additions & 3 deletions src/backend/optimizer/util/pathnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1906,9 +1906,12 @@ create_gather_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
* efficiently (or at least amortize it over multiple calls).
*/
SubqueryScanPath *
create_subqueryscan_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
create_subqueryscan_path(PlannerInfo *root, RelOptInfo *rel,
PlannerInfo *subroot,
List *subplan_params,
Path *subpath,
bool trivial_pathtarget,
List *pathkeys, Relids required_outer)
List *pathkeys, Relids required_outer, List *pushed_down_ec_joins)
{
SubqueryScanPath *pathnode = makeNode(SubqueryScanPath);

Expand All @@ -1923,6 +1926,9 @@ create_subqueryscan_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
pathnode->path.parallel_workers = subpath->parallel_workers;
pathnode->path.pathkeys = pathkeys;
pathnode->subpath = subpath;
pathnode->subplan_params = subplan_params;
pathnode->subroot = subroot;
pathnode->pushed_down_clauses = pushed_down_clauses;

cost_subqueryscan(pathnode, root, rel, pathnode->path.param_info,
trivial_pathtarget);
Expand Down Expand Up @@ -3977,9 +3983,12 @@ reparameterize_path(PlannerInfo *root, Path *path,
return (Path *) create_subqueryscan_path(root,
rel,
subpath,
spath->subroot,
spath->subplan_params,
trivial_pathtarget,
spath->path.pathkeys,
required_outer);
required_outer,
spath->pushed_down_clauses);
}
case T_Result:
/* Supported only for RTE_RESULT scan paths */
Expand Down
1 change: 1 addition & 0 deletions src/backend/optimizer/util/relnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,7 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
joinrel->subroot = NULL;
joinrel->subplan_params = NIL;
joinrel->amflags = 0;
joinrel->chosen_plan = NULL;
joinrel->serverid = InvalidOid;
joinrel->userid = InvalidOid;
joinrel->useridiscurrent = false;
Expand Down
9 changes: 6 additions & 3 deletions src/backend/rewrite/rewriteManip.c
Original file line number Diff line number Diff line change
Expand Up @@ -1758,6 +1758,7 @@ typedef struct
int result_relation;
ReplaceVarsNoMatchOption nomatch_option;
int nomatch_varno;
int min_sublevels_up;
} ReplaceVarsFromTargetList_context;

static Node *
Expand All @@ -1774,9 +1775,10 @@ ReplaceVarsFromTargetList_callback(const Var *var,
rcon->nomatch_option,
rcon->nomatch_varno);

/* Must adjust varlevelsup if replaced Var is within a subquery */
if (var->varlevelsup > 0)
IncrementVarSublevelsUp(newnode, var->varlevelsup, 0);
/* Must adjust varlevelsup if tlist item is from higher query */
if (var->varlevelsup + rcon->min_sublevels_up > 0)
IncrementVarSublevelsUp((Node *) newnode, var->varlevelsup - rcon->min_sublevels_up, 0);


return newnode;
}
Expand Down Expand Up @@ -1967,6 +1969,7 @@ ReplaceVarsFromTargetList(Node *node,
context.result_relation = result_relation;
context.nomatch_option = nomatch_option;
context.nomatch_varno = nomatch_varno;
context.min_sublevels_up = sublevels_up;

return replace_rte_variables(node, target_varno, sublevels_up,
ReplaceVarsFromTargetList_callback,
Expand Down
19 changes: 17 additions & 2 deletions src/backend/utils/adt/selfuncs.c
Original file line number Diff line number Diff line change
Expand Up @@ -6111,6 +6111,7 @@ examine_simple_variable(PlannerInfo *root, Var *var,
Query *subquery;
List *subtlist;
TargetEntry *ste;
PlannerInfo *subroot;

/*
* Punt if it's a whole-row var rather than a plain column reference.
Expand Down Expand Up @@ -6182,9 +6183,23 @@ examine_simple_variable(PlannerInfo *root, Var *var,
subroot = list_nth(root->glob->subroots, plan_id - 1);
}

/* If the subquery hasn't been planned yet, we have to punt */
if (subroot == NULL)
if (rel->chosen_plan)
subroot = rel->chosen_plan;
else if (rel->pathlist && IsA(linitial(rel->pathlist), SubqueryScanPath))
{
/*
* Use the estimates from the first path. XXX: what if it's a parameterized
* path?
*/
SubqueryScanPath *sqpath = (SubqueryScanPath *) linitial(rel->pathlist);

subroot = sqpath->subroot;
}
else
{
/* If the subquery hasn't been planned yet, we have to punt */
return;
}
Assert(IsA(subroot, PlannerInfo));

/*
Expand Down
8 changes: 8 additions & 0 deletions src/backend/utils/misc/guc_parameters.dat
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,13 @@
boot_val => 'true',
},

{ name => 'enable_join_predicate_pushdown', type => 'bool', context => 'PGC_USERSET', group => 'QUERY_TUNING_METHOD',
short_desc => 'Enables pusing down join in subqueries.',
flags => 'GUC_EXPLAIN',
variable => 'enable_join_predicate_pushdown',
boot_val => 'true',
},

{ name => 'enable_material', type => 'bool', context => 'PGC_USERSET', group => 'QUERY_TUNING_METHOD',
short_desc => 'Enables the planner\'s use of materialization.',
flags => 'GUC_EXPLAIN',
Expand Down Expand Up @@ -3653,3 +3660,4 @@
},

]

6 changes: 4 additions & 2 deletions src/include/nodes/pathnodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1097,8 +1097,7 @@ typedef struct RelOptInfo
double allvisfrac;
/* indexes in PlannerInfo's eq_classes list of ECs that mention this rel */
Bitmapset *eclass_indexes;
PlannerInfo *subroot; /* if subquery */
List *subplan_params; /* if subquery */
PlannerInfo *chosen_plan;
/* wanted number of parallel workers */
int rel_parallel_workers;
/* Bitmask of optional features supported by the table AM */
Expand Down Expand Up @@ -2194,6 +2193,9 @@ typedef struct SubqueryScanPath
{
Path path;
Path *subpath; /* path representing subquery execution */
PlannerInfo *subroot; /* */
List *subplan_params; /* */
List *pushed_down_joins; /* pushed-down quals */
} SubqueryScanPath;

/*
Expand Down
3 changes: 2 additions & 1 deletion src/include/optimizer/cost.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ extern PGDLLIMPORT int max_parallel_workers_per_gather;
extern PGDLLIMPORT bool enable_seqscan;
extern PGDLLIMPORT bool enable_indexscan;
extern PGDLLIMPORT bool enable_indexonlyscan;
extern PGDLLIMPORT bool enable_join_predicate_pushdown;
extern PGDLLIMPORT bool enable_bitmapscan;
extern PGDLLIMPORT bool enable_tidscan;
extern PGDLLIMPORT bool enable_sort;
Expand Down Expand Up @@ -208,7 +209,7 @@ extern void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
RelOptInfo *inner_rel,
SpecialJoinInfo *sjinfo,
List *restrictlist);
extern void set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel);
extern void set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel, PlannerInfo *subroot);
extern void set_function_size_estimates(PlannerInfo *root, RelOptInfo *rel);
extern void set_values_size_estimates(PlannerInfo *root, RelOptInfo *rel);
extern void set_cte_size_estimates(PlannerInfo *root, RelOptInfo *rel,
Expand Down
Loading