diff options
author | Robert Haas <rhaas@postgresql.org> | 2017-04-03 22:41:31 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2017-04-03 22:41:31 -0400 |
commit | 7a39b5e4d11229ece930a51fd7cb29e535db4494 (patch) | |
tree | 00bb00bac5129ead888147abec54bcd02f23273d /src/backend/optimizer | |
parent | 93cd7684ee2bba227fa371daa81b88f25456dcb2 (diff) | |
download | postgresql-7a39b5e4d11229ece930a51fd7cb29e535db4494.tar.gz postgresql-7a39b5e4d11229ece930a51fd7cb29e535db4494.zip |
Abstract logic to allow for multiple kinds of child rels.
Currently, the only type of child relation is an "other member rel",
which is the child of a baserel, but in the future joins and even
upper relations may have child rels. To facilitate that, introduce
macros that test to test for particular RelOptKind values, and use
them in various places where they help to clarify the sense of a test.
(For example, a test may allow RELOPT_OTHER_MEMBER_REL either because
it intends to allow child rels, or because it intends to allow simple
rels.)
Also, remove find_childrel_top_parent, which will not work for a
child rel that is not a baserel. Instead, add a new RelOptInfo
member top_parent_relids to track the same kind of information in a
more generic manner.
Ashutosh Bapat, slightly tweaked by me. Review and testing of the
patch set from which this was taken by Rajkumar Raghuwanshi and Rafia
Sabih.
Discussion: http://postgr.es/m/CA+TgmoagTnF2yqR3PT2rv=om=wJiZ4-A+ATwdnriTGku1CLYxA@mail.gmail.com
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r-- | src/backend/optimizer/path/allpaths.c | 7 | ||||
-rw-r--r-- | src/backend/optimizer/path/equivclass.c | 19 | ||||
-rw-r--r-- | src/backend/optimizer/path/indxpath.c | 3 | ||||
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 2 | ||||
-rw-r--r-- | src/backend/optimizer/plan/initsplan.c | 2 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planmain.c | 3 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 2 | ||||
-rw-r--r-- | src/backend/optimizer/prep/prepunion.c | 4 | ||||
-rw-r--r-- | src/backend/optimizer/util/plancat.c | 3 | ||||
-rw-r--r-- | src/backend/optimizer/util/relnode.c | 51 |
10 files changed, 51 insertions, 45 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 343b35aa326..b93b4fc7736 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -539,8 +539,7 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel, Assert(root->glob->parallelModeOK); /* This should only be called for baserels and appendrel children. */ - Assert(rel->reloptkind == RELOPT_BASEREL || - rel->reloptkind == RELOPT_OTHER_MEMBER_REL); + Assert(IS_SIMPLE_REL(rel)); /* Assorted checks based on rtekind. */ switch (rte->rtekind) @@ -846,7 +845,7 @@ set_foreign_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) /* * set_append_rel_size - * Set size estimates for an "append relation" + * Set size estimates for a simple "append relation" * * The passed-in rel and RTE represent the entire append relation. The * relation's contents are computed by appending together the output of @@ -867,6 +866,8 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, int nattrs; ListCell *l; + Assert(IS_SIMPLE_REL(rel)); + /* * Initialize to compute size estimates for whole append relation. * diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c index a329dd1e10d..67bd760fb47 100644 --- a/src/backend/optimizer/path/equivclass.c +++ b/src/backend/optimizer/path/equivclass.c @@ -1060,10 +1060,12 @@ generate_join_implied_equalities_for_ecs(PlannerInfo *root, ListCell *lc; /* If inner rel is a child, extra setup work is needed */ - if (inner_rel->reloptkind == RELOPT_OTHER_MEMBER_REL) + if (IS_OTHER_REL(inner_rel)) { + Assert(!bms_is_empty(inner_rel->top_parent_relids)); + /* Fetch relid set for the topmost parent rel */ - nominal_inner_relids = find_childrel_top_parent(root, inner_rel)->relids; + nominal_inner_relids = inner_rel->top_parent_relids; /* ECs will be marked with the parent's relid, not the child's */ nominal_join_relids = bms_union(outer_relids, nominal_inner_relids); } @@ -1324,8 +1326,7 @@ generate_join_implied_equalities_broken(PlannerInfo *root, * mentioned in the ec_sources clauses, we have to be prepared to apply * multiple levels of Var translation. */ - if (inner_rel->reloptkind == RELOPT_OTHER_MEMBER_REL && - result != NIL) + if (IS_OTHER_REL(inner_rel) && result != NIL) result = (List *) adjust_appendrel_attrs_multilevel(root, (Node *) result, inner_rel); @@ -2180,6 +2181,9 @@ generate_implied_equalities_for_column(PlannerInfo *root, Relids parent_relids; ListCell *lc1; + /* Indexes are available only on base or "other" member relations. */ + Assert(IS_SIMPLE_REL(rel)); + /* If it's a child rel, we'll need to know what its parent(s) are */ if (is_child_rel) parent_relids = find_childrel_parents(root, rel); @@ -2413,8 +2417,11 @@ eclass_useful_for_merging(PlannerInfo *root, */ /* If specified rel is a child, we must consider the topmost parent rel */ - if (rel->reloptkind == RELOPT_OTHER_MEMBER_REL) - relids = find_childrel_top_parent(root, rel)->relids; + if (IS_OTHER_REL(rel)) + { + Assert(!bms_is_empty(rel->top_parent_relids)); + relids = rel->top_parent_relids; + } else relids = rel->relids; diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index a5d19f9b1c5..cec9822cb79 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -2779,6 +2779,9 @@ check_index_predicates(PlannerInfo *root, RelOptInfo *rel) Relids otherrels; ListCell *lc; + /* Indexes are available only on base or "other" member relations. */ + Assert(IS_SIMPLE_REL(rel)); + /* * Initialize the indrestrictinfo lists to be identical to * baserestrictinfo, and check whether there are any partial indexes. If diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 2a78595e1f2..b121f40ff8c 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -3461,7 +3461,7 @@ create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path, * upper rel doesn't have relids set, but it covers all the base relations * participating in the underlying scan, so use root's all_baserels. */ - if (rel->reloptkind == RELOPT_UPPER_REL) + if (IS_UPPER_REL(rel)) scan_plan->fs_relids = root->all_baserels; else scan_plan->fs_relids = best_path->path.parent->relids; diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 53aefbd1a3d..ebd442ad4db 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -109,7 +109,7 @@ add_base_rels_to_query(PlannerInfo *root, Node *jtnode) { int varno = ((RangeTblRef *) jtnode)->rtindex; - (void) build_simple_rel(root, varno, RELOPT_BASEREL); + (void) build_simple_rel(root, varno, NULL); } else if (IsA(jtnode, FromExpr)) { diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c index 3c58d0596c6..ef0de3fb1a9 100644 --- a/src/backend/optimizer/plan/planmain.c +++ b/src/backend/optimizer/plan/planmain.c @@ -242,8 +242,7 @@ query_planner(PlannerInfo *root, List *tlist, Assert(brel->relid == rti); /* sanity check on array */ - if (brel->reloptkind == RELOPT_BASEREL || - brel->reloptkind == RELOPT_OTHER_MEMBER_REL) + if (IS_SIMPLE_REL(brel)) total_pages += (double) brel->pages; } root->total_table_pages = total_pages; diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 9d1a98220a7..17cd683d853 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -6001,7 +6001,7 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid) setup_simple_rel_arrays(root); /* Build RelOptInfo */ - rel = build_simple_rel(root, 1, RELOPT_BASEREL); + rel = build_simple_rel(root, 1, NULL); /* Locate IndexOptInfo for the target index */ indexInfo = NULL; diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index e327e66f6b9..b5cb4de6a26 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -271,7 +271,7 @@ recurse_set_operations(Node *setOp, PlannerInfo *root, * used for much here, but it carries the subroot data structures * forward to setrefs.c processing. */ - rel = build_simple_rel(root, rtr->rtindex, RELOPT_BASEREL); + rel = build_simple_rel(root, rtr->rtindex, NULL); /* plan_params should not be in use in current query level */ Assert(root->plan_params == NIL); @@ -2143,7 +2143,7 @@ adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node, RelOptInfo *parent_rel = find_base_rel(root, appinfo->parent_relid); /* If parent is also a child, first recurse to apply its translations */ - if (parent_rel->reloptkind == RELOPT_OTHER_MEMBER_REL) + if (IS_OTHER_REL(parent_rel)) node = adjust_appendrel_attrs_multilevel(root, node, parent_rel); else Assert(parent_rel->reloptkind == RELOPT_BASEREL); diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 1cd21c0fdcb..19904b54bd5 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -1337,6 +1337,9 @@ relation_excluded_by_constraints(PlannerInfo *root, List *safe_constraints; ListCell *lc; + /* As of now, constraint exclusion works only with simple relations. */ + Assert(IS_SIMPLE_REL(rel)); + /* * Regardless of the setting of constraint_exclusion, detect * constant-FALSE-or-NULL restriction clauses. Because const-folding will diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index 7912df0baaa..3aa701fd843 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -88,7 +88,7 @@ setup_simple_rel_arrays(PlannerInfo *root) * Construct a new RelOptInfo for a base relation or 'other' relation. */ RelOptInfo * -build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind) +build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent) { RelOptInfo *rel; RangeTblEntry *rte; @@ -103,7 +103,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind) Assert(rte != NULL); rel = makeNode(RelOptInfo); - rel->reloptkind = reloptkind; + rel->reloptkind = parent ? RELOPT_OTHER_MEMBER_REL : RELOPT_BASEREL; rel->relids = bms_make_singleton(relid); rel->rows = 0; /* cheap startup cost is interesting iff not all tuples to be retrieved */ @@ -144,6 +144,22 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind) rel->joininfo = NIL; rel->has_eclass_joins = false; + /* + * Pass top parent's relids down the inheritance hierarchy. If the parent + * has top_parent_relids set, it's a direct or an indirect child of the top + * parent indicated by top_parent_relids. By extention this child is also + * an indirect child of that parent. + */ + if (parent) + { + if (parent->top_parent_relids) + rel->top_parent_relids = parent->top_parent_relids; + else + rel->top_parent_relids = bms_copy(parent->relids); + } + else + rel->top_parent_relids = NULL; + /* Check type of rtable entry */ switch (rte->rtekind) { @@ -209,7 +225,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind) continue; (void) build_simple_rel(root, appinfo->child_relid, - RELOPT_OTHER_MEMBER_REL); + rel); } } @@ -504,6 +520,7 @@ build_join_rel(PlannerInfo *root, joinrel->baserestrict_min_security = UINT_MAX; joinrel->joininfo = NIL; joinrel->has_eclass_joins = false; + joinrel->top_parent_relids = NULL; /* Compute information relevant to the foreign relations. */ set_foreign_rel_properties(joinrel, outer_rel, inner_rel); @@ -966,32 +983,6 @@ find_childrel_appendrelinfo(PlannerInfo *root, RelOptInfo *rel) /* - * find_childrel_top_parent - * Fetch the topmost appendrel parent rel of an appendrel child rel. - * - * Since appendrels can be nested, a child could have multiple levels of - * appendrel ancestors. This function locates the topmost ancestor, - * which will be a regular baserel not an otherrel. - */ -RelOptInfo * -find_childrel_top_parent(PlannerInfo *root, RelOptInfo *rel) -{ - do - { - AppendRelInfo *appinfo = find_childrel_appendrelinfo(root, rel); - Index prelid = appinfo->parent_relid; - - /* traverse up to the parent rel, loop if it's also a child rel */ - rel = find_base_rel(root, prelid); - } while (rel->reloptkind == RELOPT_OTHER_MEMBER_REL); - - Assert(rel->reloptkind == RELOPT_BASEREL); - - return rel; -} - - -/* * find_childrel_parents * Compute the set of parent relids of an appendrel child rel. * @@ -1004,6 +995,8 @@ find_childrel_parents(PlannerInfo *root, RelOptInfo *rel) { Relids result = NULL; + Assert(rel->reloptkind == RELOPT_OTHER_MEMBER_REL); + do { AppendRelInfo *appinfo = find_childrel_appendrelinfo(root, rel); |