Commit 7a39b5e4 authored by Robert Haas's avatar Robert Haas

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
parent 93cd7684
...@@ -243,7 +243,7 @@ is_foreign_expr(PlannerInfo *root, ...@@ -243,7 +243,7 @@ is_foreign_expr(PlannerInfo *root,
* because the upperrel's own relids currently aren't set to anything * because the upperrel's own relids currently aren't set to anything
* meaningful by the core code. For other relation, use their own relids. * meaningful by the core code. For other relation, use their own relids.
*/ */
if (baserel->reloptkind == RELOPT_UPPER_REL) if (IS_UPPER_REL(baserel))
glob_cxt.relids = fpinfo->outerrel->relids; glob_cxt.relids = fpinfo->outerrel->relids;
else else
glob_cxt.relids = baserel->relids; glob_cxt.relids = baserel->relids;
...@@ -677,7 +677,7 @@ foreign_expr_walker(Node *node, ...@@ -677,7 +677,7 @@ foreign_expr_walker(Node *node,
ListCell *lc; ListCell *lc;
/* Not safe to pushdown when not in grouping context */ /* Not safe to pushdown when not in grouping context */
if (glob_cxt->foreignrel->reloptkind != RELOPT_UPPER_REL) if (!IS_UPPER_REL(glob_cxt->foreignrel))
return false; return false;
/* Only non-split aggregates are pushable. */ /* Only non-split aggregates are pushable. */
...@@ -874,7 +874,7 @@ build_tlist_to_deparse(RelOptInfo *foreignrel) ...@@ -874,7 +874,7 @@ build_tlist_to_deparse(RelOptInfo *foreignrel)
* For an upper relation, we have already built the target list while * For an upper relation, we have already built the target list while
* checking shippability, so just return that. * checking shippability, so just return that.
*/ */
if (foreignrel->reloptkind == RELOPT_UPPER_REL) if (IS_UPPER_REL(foreignrel))
return fpinfo->grouped_tlist; return fpinfo->grouped_tlist;
/* /*
...@@ -929,17 +929,13 @@ deparseSelectStmtForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *rel, ...@@ -929,17 +929,13 @@ deparseSelectStmtForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *rel,
* We handle relations for foreign tables, joins between those and upper * We handle relations for foreign tables, joins between those and upper
* relations. * relations.
*/ */
Assert(rel->reloptkind == RELOPT_JOINREL || Assert(IS_JOIN_REL(rel) || IS_SIMPLE_REL(rel) || IS_UPPER_REL(rel));
rel->reloptkind == RELOPT_BASEREL ||
rel->reloptkind == RELOPT_OTHER_MEMBER_REL ||
rel->reloptkind == RELOPT_UPPER_REL);
/* Fill portions of context common to upper, join and base relation */ /* Fill portions of context common to upper, join and base relation */
context.buf = buf; context.buf = buf;
context.root = root; context.root = root;
context.foreignrel = rel; context.foreignrel = rel;
context.scanrel = (rel->reloptkind == RELOPT_UPPER_REL) ? context.scanrel = IS_UPPER_REL(rel) ? fpinfo->outerrel : rel;
fpinfo->outerrel : rel;
context.params_list = params_list; context.params_list = params_list;
/* Construct SELECT clause */ /* Construct SELECT clause */
...@@ -950,7 +946,7 @@ deparseSelectStmtForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *rel, ...@@ -950,7 +946,7 @@ deparseSelectStmtForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *rel,
* conditions of the underlying scan relation; otherwise, we can use the * conditions of the underlying scan relation; otherwise, we can use the
* supplied list of remote conditions directly. * supplied list of remote conditions directly.
*/ */
if (rel->reloptkind == RELOPT_UPPER_REL) if (IS_UPPER_REL(rel))
{ {
PgFdwRelationInfo *ofpinfo; PgFdwRelationInfo *ofpinfo;
...@@ -963,7 +959,7 @@ deparseSelectStmtForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *rel, ...@@ -963,7 +959,7 @@ deparseSelectStmtForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *rel,
/* Construct FROM and WHERE clauses */ /* Construct FROM and WHERE clauses */
deparseFromExpr(quals, &context); deparseFromExpr(quals, &context);
if (rel->reloptkind == RELOPT_UPPER_REL) if (IS_UPPER_REL(rel))
{ {
/* Append GROUP BY clause */ /* Append GROUP BY clause */
appendGroupByClause(tlist, &context); appendGroupByClause(tlist, &context);
...@@ -1020,8 +1016,7 @@ deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs, ...@@ -1020,8 +1016,7 @@ deparseSelectSql(List *tlist, bool is_subquery, List **retrieved_attrs,
*/ */
deparseSubqueryTargetList(context); deparseSubqueryTargetList(context);
} }
else if (foreignrel->reloptkind == RELOPT_JOINREL || else if (IS_JOIN_REL(foreignrel) || IS_UPPER_REL(foreignrel))
foreignrel->reloptkind == RELOPT_UPPER_REL)
{ {
/* /*
* For a join or upper relation the input tlist gives the list of * For a join or upper relation the input tlist gives the list of
...@@ -1062,9 +1057,8 @@ deparseFromExpr(List *quals, deparse_expr_cxt *context) ...@@ -1062,9 +1057,8 @@ deparseFromExpr(List *quals, deparse_expr_cxt *context)
RelOptInfo *scanrel = context->scanrel; RelOptInfo *scanrel = context->scanrel;
/* For upper relations, scanrel must be either a joinrel or a baserel */ /* For upper relations, scanrel must be either a joinrel or a baserel */
Assert(context->foreignrel->reloptkind != RELOPT_UPPER_REL || Assert(!IS_UPPER_REL(context->foreignrel) ||
scanrel->reloptkind == RELOPT_JOINREL || IS_JOIN_REL(scanrel) || IS_SIMPLE_REL(scanrel));
scanrel->reloptkind == RELOPT_BASEREL);
/* Construct FROM clause */ /* Construct FROM clause */
appendStringInfoString(buf, " FROM "); appendStringInfoString(buf, " FROM ");
...@@ -1219,7 +1213,7 @@ deparseLockingClause(deparse_expr_cxt *context) ...@@ -1219,7 +1213,7 @@ deparseLockingClause(deparse_expr_cxt *context)
appendStringInfoString(buf, " FOR UPDATE"); appendStringInfoString(buf, " FOR UPDATE");
/* Add the relation alias if we are here for a join relation */ /* Add the relation alias if we are here for a join relation */
if (rel->reloptkind == RELOPT_JOINREL) if (IS_JOIN_REL(rel))
appendStringInfo(buf, " OF %s%d", REL_ALIAS_PREFIX, relid); appendStringInfo(buf, " OF %s%d", REL_ALIAS_PREFIX, relid);
} }
else else
...@@ -1384,8 +1378,7 @@ deparseSubqueryTargetList(deparse_expr_cxt *context) ...@@ -1384,8 +1378,7 @@ deparseSubqueryTargetList(deparse_expr_cxt *context)
ListCell *lc; ListCell *lc;
/* Should only be called in these cases. */ /* Should only be called in these cases. */
Assert(foreignrel->reloptkind == RELOPT_BASEREL || Assert(IS_SIMPLE_REL(foreignrel) || IS_JOIN_REL(foreignrel));
foreignrel->reloptkind == RELOPT_JOINREL);
first = true; first = true;
foreach(lc, foreignrel->reltarget->exprs) foreach(lc, foreignrel->reltarget->exprs)
...@@ -1417,7 +1410,7 @@ deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, ...@@ -1417,7 +1410,7 @@ deparseFromExprForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel,
{ {
PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private; PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
if (foreignrel->reloptkind == RELOPT_JOINREL) if (IS_JOIN_REL(foreignrel))
{ {
StringInfoData join_sql_o; StringInfoData join_sql_o;
StringInfoData join_sql_i; StringInfoData join_sql_i;
...@@ -1495,8 +1488,7 @@ deparseRangeTblRef(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel, ...@@ -1495,8 +1488,7 @@ deparseRangeTblRef(StringInfo buf, PlannerInfo *root, RelOptInfo *foreignrel,
PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private; PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
/* Should only be called in these cases. */ /* Should only be called in these cases. */
Assert(foreignrel->reloptkind == RELOPT_BASEREL || Assert(IS_SIMPLE_REL(foreignrel) || IS_JOIN_REL(foreignrel));
foreignrel->reloptkind == RELOPT_JOINREL);
Assert(fpinfo->local_conds == NIL); Assert(fpinfo->local_conds == NIL);
...@@ -3097,15 +3089,13 @@ is_subquery_var(Var *node, RelOptInfo *foreignrel, int *relno, int *colno) ...@@ -3097,15 +3089,13 @@ is_subquery_var(Var *node, RelOptInfo *foreignrel, int *relno, int *colno)
RelOptInfo *innerrel = fpinfo->innerrel; RelOptInfo *innerrel = fpinfo->innerrel;
/* Should only be called in these cases. */ /* Should only be called in these cases. */
Assert(foreignrel->reloptkind == RELOPT_BASEREL || Assert(IS_SIMPLE_REL(foreignrel) || IS_JOIN_REL(foreignrel));
foreignrel->reloptkind == RELOPT_JOINREL ||
foreignrel->reloptkind == RELOPT_OTHER_MEMBER_REL);
/* /*
* If the given relation isn't a join relation, it doesn't have any lower * If the given relation isn't a join relation, it doesn't have any lower
* subqueries, so the Var isn't a subquery output column. * subqueries, so the Var isn't a subquery output column.
*/ */
if (foreignrel->reloptkind != RELOPT_JOINREL) if (!IS_JOIN_REL(foreignrel))
return false; return false;
/* /*
......
...@@ -729,8 +729,11 @@ get_useful_ecs_for_relation(PlannerInfo *root, RelOptInfo *rel) ...@@ -729,8 +729,11 @@ get_useful_ecs_for_relation(PlannerInfo *root, RelOptInfo *rel)
return useful_eclass_list; return useful_eclass_list;
/* If this is a child rel, we must use the topmost parent rel to search. */ /* If this is a child rel, we must use the topmost parent rel to search. */
if (rel->reloptkind == RELOPT_OTHER_MEMBER_REL) if (IS_OTHER_REL(rel))
relids = find_childrel_top_parent(root, rel)->relids; {
Assert(!bms_is_empty(rel->top_parent_relids));
relids = rel->top_parent_relids;
}
else else
relids = rel->relids; relids = rel->relids;
...@@ -1129,8 +1132,7 @@ postgresGetForeignPlan(PlannerInfo *root, ...@@ -1129,8 +1132,7 @@ postgresGetForeignPlan(PlannerInfo *root,
* For base relations, set scan_relid as the relid of the relation. For * For base relations, set scan_relid as the relid of the relation. For
* other kinds of relations set it to 0. * other kinds of relations set it to 0.
*/ */
if (foreignrel->reloptkind == RELOPT_BASEREL || if (IS_SIMPLE_REL(foreignrel))
foreignrel->reloptkind == RELOPT_OTHER_MEMBER_REL)
scan_relid = foreignrel->relid; scan_relid = foreignrel->relid;
else else
{ {
...@@ -1189,8 +1191,7 @@ postgresGetForeignPlan(PlannerInfo *root, ...@@ -1189,8 +1191,7 @@ postgresGetForeignPlan(PlannerInfo *root,
local_exprs = lappend(local_exprs, rinfo->clause); local_exprs = lappend(local_exprs, rinfo->clause);
} }
if (foreignrel->reloptkind == RELOPT_JOINREL || if (IS_JOIN_REL(foreignrel) || IS_UPPER_REL(foreignrel))
foreignrel->reloptkind == RELOPT_UPPER_REL)
{ {
/* For a join relation, get the conditions from fdw_private structure */ /* For a join relation, get the conditions from fdw_private structure */
remote_conds = fpinfo->remote_conds; remote_conds = fpinfo->remote_conds;
...@@ -1216,7 +1217,7 @@ postgresGetForeignPlan(PlannerInfo *root, ...@@ -1216,7 +1217,7 @@ postgresGetForeignPlan(PlannerInfo *root,
* joins. Queries involving aggregates or grouping do not require * joins. Queries involving aggregates or grouping do not require
* EPQ mechanism, hence should not have an outer plan here. * EPQ mechanism, hence should not have an outer plan here.
*/ */
Assert(foreignrel->reloptkind != RELOPT_UPPER_REL); Assert(!IS_UPPER_REL(foreignrel));
outer_plan->targetlist = fdw_scan_tlist; outer_plan->targetlist = fdw_scan_tlist;
...@@ -1255,8 +1256,7 @@ postgresGetForeignPlan(PlannerInfo *root, ...@@ -1255,8 +1256,7 @@ postgresGetForeignPlan(PlannerInfo *root,
remote_conds, remote_conds,
retrieved_attrs, retrieved_attrs,
makeInteger(fpinfo->fetch_size)); makeInteger(fpinfo->fetch_size));
if (foreignrel->reloptkind == RELOPT_JOINREL || if (IS_JOIN_REL(foreignrel) || IS_UPPER_REL(foreignrel))
foreignrel->reloptkind == RELOPT_UPPER_REL)
fdw_private = lappend(fdw_private, fdw_private = lappend(fdw_private,
makeString(fpinfo->relation_name->data)); makeString(fpinfo->relation_name->data));
...@@ -2535,8 +2535,7 @@ estimate_path_cost_size(PlannerInfo *root, ...@@ -2535,8 +2535,7 @@ estimate_path_cost_size(PlannerInfo *root,
&remote_param_join_conds, &local_param_join_conds); &remote_param_join_conds, &local_param_join_conds);
/* Build the list of columns to be fetched from the foreign server. */ /* Build the list of columns to be fetched from the foreign server. */
if (foreignrel->reloptkind == RELOPT_JOINREL || if (IS_JOIN_REL(foreignrel) || IS_UPPER_REL(foreignrel))
foreignrel->reloptkind == RELOPT_UPPER_REL)
fdw_scan_tlist = build_tlist_to_deparse(foreignrel); fdw_scan_tlist = build_tlist_to_deparse(foreignrel);
else else
fdw_scan_tlist = NIL; fdw_scan_tlist = NIL;
...@@ -2617,7 +2616,7 @@ estimate_path_cost_size(PlannerInfo *root, ...@@ -2617,7 +2616,7 @@ estimate_path_cost_size(PlannerInfo *root,
startup_cost = fpinfo->rel_startup_cost; startup_cost = fpinfo->rel_startup_cost;
run_cost = fpinfo->rel_total_cost - fpinfo->rel_startup_cost; run_cost = fpinfo->rel_total_cost - fpinfo->rel_startup_cost;
} }
else if (foreignrel->reloptkind == RELOPT_JOINREL) else if (IS_JOIN_REL(foreignrel))
{ {
PgFdwRelationInfo *fpinfo_i; PgFdwRelationInfo *fpinfo_i;
PgFdwRelationInfo *fpinfo_o; PgFdwRelationInfo *fpinfo_o;
...@@ -2683,7 +2682,7 @@ estimate_path_cost_size(PlannerInfo *root, ...@@ -2683,7 +2682,7 @@ estimate_path_cost_size(PlannerInfo *root,
run_cost += nrows * remote_conds_cost.per_tuple; run_cost += nrows * remote_conds_cost.per_tuple;
run_cost += fpinfo->local_conds_cost.per_tuple * retrieved_rows; run_cost += fpinfo->local_conds_cost.per_tuple * retrieved_rows;
} }
else if (foreignrel->reloptkind == RELOPT_UPPER_REL) else if (IS_UPPER_REL(foreignrel))
{ {
PgFdwRelationInfo *ofpinfo; PgFdwRelationInfo *ofpinfo;
PathTarget *ptarget = root->upper_targets[UPPERREL_GROUP_AGG]; PathTarget *ptarget = root->upper_targets[UPPERREL_GROUP_AGG];
......
...@@ -717,7 +717,7 @@ GetExistingLocalJoinPath(RelOptInfo *joinrel) ...@@ -717,7 +717,7 @@ GetExistingLocalJoinPath(RelOptInfo *joinrel)
{ {
ListCell *lc; ListCell *lc;
Assert(joinrel->reloptkind == RELOPT_JOINREL); Assert(IS_JOIN_REL(joinrel));
foreach(lc, joinrel->pathlist) foreach(lc, joinrel->pathlist)
{ {
...@@ -782,7 +782,7 @@ GetExistingLocalJoinPath(RelOptInfo *joinrel) ...@@ -782,7 +782,7 @@ GetExistingLocalJoinPath(RelOptInfo *joinrel)
ForeignPath *foreign_path; ForeignPath *foreign_path;
foreign_path = (ForeignPath *) joinpath->outerjoinpath; 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; joinpath->outerjoinpath = foreign_path->fdw_outerpath;
} }
...@@ -791,7 +791,7 @@ GetExistingLocalJoinPath(RelOptInfo *joinrel) ...@@ -791,7 +791,7 @@ GetExistingLocalJoinPath(RelOptInfo *joinrel)
ForeignPath *foreign_path; ForeignPath *foreign_path;
foreign_path = (ForeignPath *) joinpath->innerjoinpath; 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; joinpath->innerjoinpath = foreign_path->fdw_outerpath;
} }
......
...@@ -539,8 +539,7 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel, ...@@ -539,8 +539,7 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
Assert(root->glob->parallelModeOK); Assert(root->glob->parallelModeOK);
/* This should only be called for baserels and appendrel children. */ /* This should only be called for baserels and appendrel children. */
Assert(rel->reloptkind == RELOPT_BASEREL || Assert(IS_SIMPLE_REL(rel));
rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
/* Assorted checks based on rtekind. */ /* Assorted checks based on rtekind. */
switch (rte->rtekind) switch (rte->rtekind)
...@@ -846,7 +845,7 @@ set_foreign_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) ...@@ -846,7 +845,7 @@ set_foreign_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
/* /*
* set_append_rel_size * 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 * The passed-in rel and RTE represent the entire append relation. The
* relation's contents are computed by appending together the output of * relation's contents are computed by appending together the output of
...@@ -867,6 +866,8 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, ...@@ -867,6 +866,8 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
int nattrs; int nattrs;
ListCell *l; ListCell *l;
Assert(IS_SIMPLE_REL(rel));
/* /*
* Initialize to compute size estimates for whole append relation. * Initialize to compute size estimates for whole append relation.
* *
......
...@@ -1060,10 +1060,12 @@ generate_join_implied_equalities_for_ecs(PlannerInfo *root, ...@@ -1060,10 +1060,12 @@ generate_join_implied_equalities_for_ecs(PlannerInfo *root,
ListCell *lc; ListCell *lc;
/* If inner rel is a child, extra setup work is needed */ /* 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 */ /* 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 */ /* ECs will be marked with the parent's relid, not the child's */
nominal_join_relids = bms_union(outer_relids, nominal_inner_relids); nominal_join_relids = bms_union(outer_relids, nominal_inner_relids);
} }
...@@ -1324,8 +1326,7 @@ generate_join_implied_equalities_broken(PlannerInfo *root, ...@@ -1324,8 +1326,7 @@ generate_join_implied_equalities_broken(PlannerInfo *root,
* mentioned in the ec_sources clauses, we have to be prepared to apply * mentioned in the ec_sources clauses, we have to be prepared to apply
* multiple levels of Var translation. * multiple levels of Var translation.
*/ */
if (inner_rel->reloptkind == RELOPT_OTHER_MEMBER_REL && if (IS_OTHER_REL(inner_rel) && result != NIL)
result != NIL)
result = (List *) adjust_appendrel_attrs_multilevel(root, result = (List *) adjust_appendrel_attrs_multilevel(root,
(Node *) result, (Node *) result,
inner_rel); inner_rel);
...@@ -2180,6 +2181,9 @@ generate_implied_equalities_for_column(PlannerInfo *root, ...@@ -2180,6 +2181,9 @@ generate_implied_equalities_for_column(PlannerInfo *root,
Relids parent_relids; Relids parent_relids;
ListCell *lc1; 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 it's a child rel, we'll need to know what its parent(s) are */
if (is_child_rel) if (is_child_rel)
parent_relids = find_childrel_parents(root, rel); parent_relids = find_childrel_parents(root, rel);
...@@ -2413,8 +2417,11 @@ eclass_useful_for_merging(PlannerInfo *root, ...@@ -2413,8 +2417,11 @@ eclass_useful_for_merging(PlannerInfo *root,
*/ */
/* If specified rel is a child, we must consider the topmost parent rel */ /* If specified rel is a child, we must consider the topmost parent rel */
if (rel->reloptkind == RELOPT_OTHER_MEMBER_REL) if (IS_OTHER_REL(rel))
relids = find_childrel_top_parent(root, rel)->relids; {
Assert(!bms_is_empty(rel->top_parent_relids));
relids = rel->top_parent_relids;
}
else else
relids = rel->relids; relids = rel->relids;
......
...@@ -2779,6 +2779,9 @@ check_index_predicates(PlannerInfo *root, RelOptInfo *rel) ...@@ -2779,6 +2779,9 @@ check_index_predicates(PlannerInfo *root, RelOptInfo *rel)
Relids otherrels; Relids otherrels;
ListCell *lc; 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 * Initialize the indrestrictinfo lists to be identical to
* baserestrictinfo, and check whether there are any partial indexes. If * baserestrictinfo, and check whether there are any partial indexes. If
......
...@@ -3461,7 +3461,7 @@ create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path, ...@@ -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 * 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. * 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; scan_plan->fs_relids = root->all_baserels;
else else
scan_plan->fs_relids = best_path->path.parent->relids; scan_plan->fs_relids = best_path->path.parent->relids;
......
...@@ -109,7 +109,7 @@ add_base_rels_to_query(PlannerInfo *root, Node *jtnode) ...@@ -109,7 +109,7 @@ add_base_rels_to_query(PlannerInfo *root, Node *jtnode)
{ {
int varno = ((RangeTblRef *) jtnode)->rtindex; 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)) else if (IsA(jtnode, FromExpr))
{ {
......
...@@ -242,8 +242,7 @@ query_planner(PlannerInfo *root, List *tlist, ...@@ -242,8 +242,7 @@ query_planner(PlannerInfo *root, List *tlist,
Assert(brel->relid == rti); /* sanity check on array */ Assert(brel->relid == rti); /* sanity check on array */
if (brel->reloptkind == RELOPT_BASEREL || if (IS_SIMPLE_REL(brel))
brel->reloptkind == RELOPT_OTHER_MEMBER_REL)
total_pages += (double) brel->pages; total_pages += (double) brel->pages;
} }
root->total_table_pages = total_pages; root->total_table_pages = total_pages;
......
...@@ -6001,7 +6001,7 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid) ...@@ -6001,7 +6001,7 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid)
setup_simple_rel_arrays(root); setup_simple_rel_arrays(root);
/* Build RelOptInfo */ /* Build RelOptInfo */
rel = build_simple_rel(root, 1, RELOPT_BASEREL); rel = build_simple_rel(root, 1, NULL);
/* Locate IndexOptInfo for the target index */ /* Locate IndexOptInfo for the target index */
indexInfo = NULL; indexInfo = NULL;
......
...@@ -271,7 +271,7 @@ recurse_set_operations(Node *setOp, PlannerInfo *root, ...@@ -271,7 +271,7 @@ recurse_set_operations(Node *setOp, PlannerInfo *root,
* used for much here, but it carries the subroot data structures * used for much here, but it carries the subroot data structures
* forward to setrefs.c processing. * 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 */ /* plan_params should not be in use in current query level */
Assert(root->plan_params == NIL); Assert(root->plan_params == NIL);
...@@ -2143,7 +2143,7 @@ adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node, ...@@ -2143,7 +2143,7 @@ adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node,
RelOptInfo *parent_rel = find_base_rel(root, appinfo->parent_relid); RelOptInfo *parent_rel = find_base_rel(root, appinfo->parent_relid);
/* If parent is also a child, first recurse to apply its translations */ /* 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); node = adjust_appendrel_attrs_multilevel(root, node, parent_rel);
else else
Assert(parent_rel->reloptkind == RELOPT_BASEREL); Assert(parent_rel->reloptkind == RELOPT_BASEREL);
......
...@@ -1337,6 +1337,9 @@ relation_excluded_by_constraints(PlannerInfo *root, ...@@ -1337,6 +1337,9 @@ relation_excluded_by_constraints(PlannerInfo *root,
List *safe_constraints; List *safe_constraints;
ListCell *lc; 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 * Regardless of the setting of constraint_exclusion, detect
* constant-FALSE-or-NULL restriction clauses. Because const-folding will * constant-FALSE-or-NULL restriction clauses. Because const-folding will
......
...@@ -88,7 +88,7 @@ setup_simple_rel_arrays(PlannerInfo *root) ...@@ -88,7 +88,7 @@ setup_simple_rel_arrays(PlannerInfo *root)
* Construct a new RelOptInfo for a base relation or 'other' relation. * Construct a new RelOptInfo for a base relation or 'other' relation.
*/ */
RelOptInfo * RelOptInfo *
build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind) build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
{ {
RelOptInfo *rel; RelOptInfo *rel;
RangeTblEntry *rte; RangeTblEntry *rte;
...@@ -103,7 +103,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind) ...@@ -103,7 +103,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
Assert(rte != NULL); Assert(rte != NULL);
rel = makeNode(RelOptInfo); rel = makeNode(RelOptInfo);
rel->reloptkind = reloptkind; rel->reloptkind = parent ? RELOPT_OTHER_MEMBER_REL : RELOPT_BASEREL;
rel->relids = bms_make_singleton(relid); rel->relids = bms_make_singleton(relid);
rel->rows = 0; rel->rows = 0;
/* cheap startup cost is interesting iff not all tuples to be retrieved */ /* 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) ...@@ -144,6 +144,22 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
rel->joininfo = NIL; rel->joininfo = NIL;
rel->has_eclass_joins = false; 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 */ /* Check type of rtable entry */
switch (rte->rtekind) switch (rte->rtekind)
{ {
...@@ -209,7 +225,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind) ...@@ -209,7 +225,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
continue; continue;
(void) build_simple_rel(root, appinfo->child_relid, (void) build_simple_rel(root, appinfo->child_relid,
RELOPT_OTHER_MEMBER_REL); rel);
} }
} }
...@@ -504,6 +520,7 @@ build_join_rel(PlannerInfo *root, ...@@ -504,6 +520,7 @@ build_join_rel(PlannerInfo *root,
joinrel->baserestrict_min_security = UINT_MAX; joinrel->baserestrict_min_security = UINT_MAX;
joinrel->joininfo = NIL; joinrel->joininfo = NIL;
joinrel->has_eclass_joins = false; joinrel->has_eclass_joins = false;
joinrel->top_parent_relids = NULL;
/* Compute information relevant to the foreign relations. */ /* Compute information relevant to the foreign relations. */
set_foreign_rel_properties(joinrel, outer_rel, inner_rel); set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
...@@ -965,32 +982,6 @@ find_childrel_appendrelinfo(PlannerInfo *root, RelOptInfo *rel) ...@@ -965,32 +982,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 * find_childrel_parents
* Compute the set of parent relids of an appendrel child rel. * Compute the set of parent relids of an appendrel child rel.
...@@ -1004,6 +995,8 @@ find_childrel_parents(PlannerInfo *root, RelOptInfo *rel) ...@@ -1004,6 +995,8 @@ find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
{ {
Relids result = NULL; Relids result = NULL;
Assert(rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
do do
{ {
AppendRelInfo *appinfo = find_childrel_appendrelinfo(root, rel); AppendRelInfo *appinfo = find_childrel_appendrelinfo(root, rel);
......
...@@ -3473,7 +3473,7 @@ estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows, ...@@ -3473,7 +3473,7 @@ estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows,
/* /*
* Sanity check --- don't divide by zero if empty relation. * Sanity check --- don't divide by zero if empty relation.
*/ */
Assert(rel->reloptkind == RELOPT_BASEREL); Assert(IS_SIMPLE_REL(rel));
if (rel->tuples > 0) if (rel->tuples > 0)
{ {
/* /*
......
...@@ -484,6 +484,23 @@ typedef enum RelOptKind ...@@ -484,6 +484,23 @@ typedef enum RelOptKind
RELOPT_DEADREL RELOPT_DEADREL
} RelOptKind; } 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 typedef struct RelOptInfo
{ {
NodeTag type; NodeTag type;
...@@ -554,6 +571,9 @@ typedef struct RelOptInfo ...@@ -554,6 +571,9 @@ typedef struct RelOptInfo
List *joininfo; /* RestrictInfo structures for join clauses List *joininfo; /* RestrictInfo structures for join clauses
* involving this rel */ * involving this rel */
bool has_eclass_joins; /* T means joininfo is incomplete */ bool has_eclass_joins; /* T means joininfo is incomplete */
/* used by "other" relations. */
Relids top_parent_relids; /* Relids of topmost parents. */
} RelOptInfo; } RelOptInfo;
/* /*
......
...@@ -256,7 +256,7 @@ extern Path *reparameterize_path(PlannerInfo *root, Path *path, ...@@ -256,7 +256,7 @@ extern Path *reparameterize_path(PlannerInfo *root, Path *path,
*/ */
extern void setup_simple_rel_arrays(PlannerInfo *root); extern void setup_simple_rel_arrays(PlannerInfo *root);
extern RelOptInfo *build_simple_rel(PlannerInfo *root, int relid, 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_base_rel(PlannerInfo *root, int relid);
extern RelOptInfo *find_join_rel(PlannerInfo *root, Relids relids); extern RelOptInfo *find_join_rel(PlannerInfo *root, Relids relids);
extern RelOptInfo *build_join_rel(PlannerInfo *root, extern RelOptInfo *build_join_rel(PlannerInfo *root,
...@@ -274,7 +274,6 @@ extern RelOptInfo *fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, ...@@ -274,7 +274,6 @@ extern RelOptInfo *fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind,
Relids relids); Relids relids);
extern AppendRelInfo *find_childrel_appendrelinfo(PlannerInfo *root, extern AppendRelInfo *find_childrel_appendrelinfo(PlannerInfo *root,
RelOptInfo *rel); RelOptInfo *rel);
extern RelOptInfo *find_childrel_top_parent(PlannerInfo *root, RelOptInfo *rel);
extern Relids find_childrel_parents(PlannerInfo *root, RelOptInfo *rel); extern Relids find_childrel_parents(PlannerInfo *root, RelOptInfo *rel);
extern ParamPathInfo *get_baserel_parampathinfo(PlannerInfo *root, extern ParamPathInfo *get_baserel_parampathinfo(PlannerInfo *root,
RelOptInfo *baserel, RelOptInfo *baserel,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment