aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/foreign/foreign.c6
-rw-r--r--src/backend/optimizer/path/allpaths.c7
-rw-r--r--src/backend/optimizer/path/equivclass.c19
-rw-r--r--src/backend/optimizer/path/indxpath.c3
-rw-r--r--src/backend/optimizer/plan/createplan.c2
-rw-r--r--src/backend/optimizer/plan/initsplan.c2
-rw-r--r--src/backend/optimizer/plan/planmain.c3
-rw-r--r--src/backend/optimizer/plan/planner.c2
-rw-r--r--src/backend/optimizer/prep/prepunion.c4
-rw-r--r--src/backend/optimizer/util/plancat.c3
-rw-r--r--src/backend/optimizer/util/relnode.c51
-rw-r--r--src/backend/utils/adt/selfuncs.c2
-rw-r--r--src/include/nodes/relation.h20
-rw-r--r--src/include/optimizer/pathnode.h3
14 files changed, 76 insertions, 51 deletions
diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c
index 5a45558b915..a113bf540da 100644
--- a/src/backend/foreign/foreign.c
+++ b/src/backend/foreign/foreign.c
@@ -717,7 +717,7 @@ GetExistingLocalJoinPath(RelOptInfo *joinrel)
{
ListCell *lc;
- Assert(joinrel->reloptkind == RELOPT_JOINREL);
+ Assert(IS_JOIN_REL(joinrel));
foreach(lc, joinrel->pathlist)
{
@@ -782,7 +782,7 @@ GetExistingLocalJoinPath(RelOptInfo *joinrel)
ForeignPath *foreign_path;
foreign_path = (ForeignPath *) joinpath->outerjoinpath;
- if (foreign_path->path.parent->reloptkind == RELOPT_JOINREL)
+ if (IS_JOIN_REL(foreign_path->path.parent))
joinpath->outerjoinpath = foreign_path->fdw_outerpath;
}
@@ -791,7 +791,7 @@ GetExistingLocalJoinPath(RelOptInfo *joinrel)
ForeignPath *foreign_path;
foreign_path = (ForeignPath *) joinpath->innerjoinpath;
- if (foreign_path->path.parent->reloptkind == RELOPT_JOINREL)
+ if (IS_JOIN_REL(foreign_path->path.parent))
joinpath->innerjoinpath = foreign_path->fdw_outerpath;
}
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);
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 5c382a2013e..68b54235b3f 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -3473,7 +3473,7 @@ estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows,
/*
* Sanity check --- don't divide by zero if empty relation.
*/
- Assert(rel->reloptkind == RELOPT_BASEREL);
+ Assert(IS_SIMPLE_REL(rel));
if (rel->tuples > 0)
{
/*
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index ebf9480f377..fc53eb171aa 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -484,6 +484,23 @@ typedef enum RelOptKind
RELOPT_DEADREL
} RelOptKind;
+/*
+ * Is the given relation a simple relation i.e a base or "other" member
+ * relation?
+ */
+#define IS_SIMPLE_REL(rel) \
+ ((rel)->reloptkind == RELOPT_BASEREL || \
+ (rel)->reloptkind == RELOPT_OTHER_MEMBER_REL)
+
+/* Is the given relation a join relation? */
+#define IS_JOIN_REL(rel) ((rel)->reloptkind == RELOPT_JOINREL)
+
+/* Is the given relation an upper relation? */
+#define IS_UPPER_REL(rel) ((rel)->reloptkind == RELOPT_UPPER_REL)
+
+/* Is the given relation an "other" relation? */
+#define IS_OTHER_REL(rel) ((rel)->reloptkind == RELOPT_OTHER_MEMBER_REL)
+
typedef struct RelOptInfo
{
NodeTag type;
@@ -554,6 +571,9 @@ typedef struct RelOptInfo
List *joininfo; /* RestrictInfo structures for join clauses
* involving this rel */
bool has_eclass_joins; /* T means joininfo is incomplete */
+
+ /* used by "other" relations. */
+ Relids top_parent_relids; /* Relids of topmost parents. */
} RelOptInfo;
/*
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
index 82d4e8701c8..2e712c6a35d 100644
--- a/src/include/optimizer/pathnode.h
+++ b/src/include/optimizer/pathnode.h
@@ -256,7 +256,7 @@ extern Path *reparameterize_path(PlannerInfo *root, Path *path,
*/
extern void setup_simple_rel_arrays(PlannerInfo *root);
extern RelOptInfo *build_simple_rel(PlannerInfo *root, int relid,
- RelOptKind reloptkind);
+ RelOptInfo *parent);
extern RelOptInfo *find_base_rel(PlannerInfo *root, int relid);
extern RelOptInfo *find_join_rel(PlannerInfo *root, Relids relids);
extern RelOptInfo *build_join_rel(PlannerInfo *root,
@@ -274,7 +274,6 @@ extern RelOptInfo *fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind,
Relids relids);
extern AppendRelInfo *find_childrel_appendrelinfo(PlannerInfo *root,
RelOptInfo *rel);
-extern RelOptInfo *find_childrel_top_parent(PlannerInfo *root, RelOptInfo *rel);
extern Relids find_childrel_parents(PlannerInfo *root, RelOptInfo *rel);
extern ParamPathInfo *get_baserel_parampathinfo(PlannerInfo *root,
RelOptInfo *baserel,