verify_em_child.diff

application/octet-stream

Filename: verify_em_child.diff
Type: application/octet-stream
Part: 0
Message: Re: speeding up planning with partitions

Patch

Format: unified
File+
src/backend/optimizer/path/equivclass.c 30 0
src/backend/optimizer/path/pathkeys.c 5 0
src/backend/optimizer/plan/createplan.c 25 19
src/include/optimizer/paths.h 1 0
diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c
index 5ace28eab0..7212f2d3bc 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -675,7 +675,10 @@ get_eclass_for_sort_expr(PlannerInfo *root,
 			 */
 			if (cur_em->em_is_child &&
 				!bms_equal(cur_em->em_relids, rel))
+			{
+				verify_em_child(root, cur_em);
 				continue;
+			}
 
 			/*
 			 * If below an outer join, don't match constants: they're not as
@@ -2002,7 +2005,10 @@ exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2)
 			EquivalenceMember *em = (EquivalenceMember *) lfirst(lc2);
 
 			if (em->em_is_child)
+			{
+				verify_em_child(root, em);
 				continue;		/* ignore children here */
+			}
 			if (equal(item1, em->em_expr))
 				item1member = true;
 			else if (equal(item2, em->em_expr))
@@ -2059,7 +2065,10 @@ match_eclasses_to_foreign_key_col(PlannerInfo *root,
 			Var		   *var;
 
 			if (em->em_is_child)
+			{
+				verify_em_child(root, em);
 				continue;		/* ignore children here */
+			}
 
 			/* EM must be a Var, possibly with RelabelType */
 			var = (Var *) em->em_expr;
@@ -2286,7 +2295,10 @@ generate_implied_equalities_for_column(PlannerInfo *root,
 			RestrictInfo *rinfo;
 
 			if (other_em->em_is_child)
+			{
+				verify_em_child(root, other_em);
 				continue;		/* ignore children here */
+			}
 
 			/* Make sure it'll be a join to a different rel */
 			if (other_em == cur_em ||
@@ -2386,6 +2398,21 @@ have_relevant_eclass_joinclause(PlannerInfo *root,
 	return false;
 }
 
+void
+verify_em_child(PlannerInfo *root, EquivalenceMember *em)
+{
+	int relid;
+	Assert(em->em_is_child);
+
+	relid = -1;
+	while ((relid = bms_next_member(em->em_relids, relid)) >= 0)
+	{
+		if (root->simple_rel_array[relid]->reloptkind == RELOPT_BASEREL)
+			elog(WARNING, "child EquivalenceMember skipped: %s", nodeToString(em->em_expr));
+	}
+}
+
+
 
 /*
  * has_relevant_eclass_joinclause
@@ -2476,7 +2503,10 @@ eclass_useful_for_merging(PlannerInfo *root,
 		EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc);
 
 		if (cur_em->em_is_child)
+		{
+			verify_em_child(root, cur_em);
 			continue;			/* ignore children here */
+		}
 
 		if (!bms_overlap(cur_em->em_relids, relids))
 			return true;
diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c
index ec66cb9c3c..27bff4a56d 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -717,7 +717,10 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
 				ListCell   *k;
 
 				if (sub_member->em_is_child)
+				{
+					verify_em_child(rel->subroot, sub_member);
 					continue;	/* ignore children here */
+				}
 
 				foreach(k, subquery_tlist)
 				{
@@ -1179,6 +1182,8 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
 			if (!em->em_is_const && !em->em_is_child &&
 				!bms_overlap(em->em_relids, joinrel->relids))
 				score++;
+			else if (em->em_is_child)
+				verify_em_child(root, em);
 		}
 
 		ecs[necs] = oeclass;
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 28c4b53fea..56a7c69775 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -237,7 +237,7 @@ static MergeJoin *make_mergejoin(List *tlist,
 static Sort *make_sort(Plan *lefttree, int numCols,
 		  AttrNumber *sortColIdx, Oid *sortOperators,
 		  Oid *collations, bool *nullsFirst);
-static Plan *prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys,
+static Plan *prepare_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys,
 						   Relids relids,
 						   const AttrNumber *reqColIdx,
 						   bool adjust_tlist_in_place,
@@ -246,10 +246,10 @@ static Plan *prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys,
 						   Oid **p_sortOperators,
 						   Oid **p_collations,
 						   bool **p_nullsFirst);
-static EquivalenceMember *find_ec_member_for_tle(EquivalenceClass *ec,
+static EquivalenceMember *find_ec_member_for_tle(PlannerInfo *root,EquivalenceClass *ec,
 					   TargetEntry *tle,
 					   Relids relids);
-static Sort *make_sort_from_pathkeys(Plan *lefttree, List *pathkeys,
+static Sort *make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys,
 						Relids relids);
 static Sort *make_sort_from_groupcols(List *groupcls,
 						 AttrNumber *grpColIdx,
@@ -266,7 +266,7 @@ static Group *make_group(List *tlist, List *qual, int numGroupCols,
 		   AttrNumber *grpColIdx, Oid *grpOperators,
 		   Plan *lefttree);
 static Unique *make_unique_from_sortclauses(Plan *lefttree, List *distinctList);
-static Unique *make_unique_from_pathkeys(Plan *lefttree,
+static Unique *make_unique_from_pathkeys(PlannerInfo *root, Plan *lefttree,
 						  List *pathkeys, int numCols);
 static Gather *make_gather(List *qptlist, List *qpqual,
 			int nworkers, int rescan_param, bool single_copy, Plan *subplan);
@@ -1147,7 +1147,7 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path)
 	plan->righttree = NULL;
 
 	/* Compute sort column info, and adjust MergeAppend's tlist as needed */
-	(void) prepare_sort_from_pathkeys(plan, pathkeys,
+	(void) prepare_sort_from_pathkeys(root, plan, pathkeys,
 									  best_path->path.parent->relids,
 									  NULL,
 									  true,
@@ -1177,7 +1177,7 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path)
 		subplan = create_plan_recurse(root, subpath, CP_EXACT_TLIST);
 
 		/* Compute sort column info, and adjust subplan's tlist as needed */
-		subplan = prepare_sort_from_pathkeys(subplan, pathkeys,
+		subplan = prepare_sort_from_pathkeys(root, subplan, pathkeys,
 											 subpath->parent->relids,
 											 node->sortColIdx,
 											 false,
@@ -1606,7 +1606,7 @@ create_gather_merge_plan(PlannerInfo *root, GatherMergePath *best_path)
 	Assert(pathkeys != NIL);
 
 	/* Compute sort column info, and adjust subplan's tlist as needed */
-	subplan = prepare_sort_from_pathkeys(subplan, pathkeys,
+	subplan = prepare_sort_from_pathkeys(root, subplan, pathkeys,
 										 best_path->subpath->parent->relids,
 										 gm_plan->sortColIdx,
 										 false,
@@ -1788,7 +1788,7 @@ create_sort_plan(PlannerInfo *root, SortPath *best_path, int flags)
 	 * relids. Thus, if this sort path is based on a child relation, we must
 	 * pass its relids.
 	 */
-	plan = make_sort_from_pathkeys(subplan, best_path->path.pathkeys,
+	plan = make_sort_from_pathkeys(root, subplan, best_path->path.pathkeys,
 								   IS_OTHER_REL(best_path->subpath->parent) ?
 								   best_path->path.parent->relids : NULL);
 
@@ -1853,7 +1853,7 @@ create_upper_unique_plan(PlannerInfo *root, UpperUniquePath *best_path, int flag
 	subplan = create_plan_recurse(root, best_path->subpath,
 								  flags | CP_LABEL_TLIST);
 
-	plan = make_unique_from_pathkeys(subplan,
+	plan = make_unique_from_pathkeys(root, subplan,
 									 best_path->path.pathkeys,
 									 best_path->numkeys);
 
@@ -3879,7 +3879,7 @@ create_mergejoin_plan(PlannerInfo *root,
 	if (best_path->outersortkeys)
 	{
 		Relids		outer_relids = outer_path->parent->relids;
-		Sort	   *sort = make_sort_from_pathkeys(outer_plan,
+		Sort	   *sort = make_sort_from_pathkeys(root, outer_plan,
 												   best_path->outersortkeys,
 												   outer_relids);
 
@@ -3893,7 +3893,7 @@ create_mergejoin_plan(PlannerInfo *root,
 	if (best_path->innersortkeys)
 	{
 		Relids		inner_relids = inner_path->parent->relids;
-		Sort	   *sort = make_sort_from_pathkeys(inner_plan,
+		Sort	   *sort = make_sort_from_pathkeys(root, inner_plan,
 												   best_path->innersortkeys,
 												   inner_relids);
 
@@ -5604,7 +5604,7 @@ make_sort(Plan *lefttree, int numCols,
  * or a Result stacked atop lefttree).
  */
 static Plan *
-prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys,
+prepare_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys,
 						   Relids relids,
 						   const AttrNumber *reqColIdx,
 						   bool adjust_tlist_in_place,
@@ -5671,7 +5671,7 @@ prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys,
 			tle = get_tle_by_resno(tlist, reqColIdx[numsortkeys]);
 			if (tle)
 			{
-				em = find_ec_member_for_tle(ec, tle, relids);
+				em = find_ec_member_for_tle(root, ec, tle, relids);
 				if (em)
 				{
 					/* found expr at right place in tlist */
@@ -5702,7 +5702,7 @@ prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys,
 			foreach(j, tlist)
 			{
 				tle = (TargetEntry *) lfirst(j);
-				em = find_ec_member_for_tle(ec, tle, relids);
+				em = find_ec_member_for_tle(root, ec, tle, relids);
 				if (em)
 				{
 					/* found expr already in tlist */
@@ -5745,7 +5745,10 @@ prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys,
 				 */
 				if (em->em_is_child &&
 					!bms_is_subset(em->em_relids, relids))
+				{
+					verify_em_child(root, em);
 					continue;
+				}
 
 				sortexpr = em->em_expr;
 				exprvars = pull_var_clause((Node *) sortexpr,
@@ -5831,7 +5834,7 @@ prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys,
  * Child EC members are ignored unless they belong to given 'relids'.
  */
 static EquivalenceMember *
-find_ec_member_for_tle(EquivalenceClass *ec,
+find_ec_member_for_tle(PlannerInfo *root, EquivalenceClass *ec,
 					   TargetEntry *tle,
 					   Relids relids)
 {
@@ -5860,7 +5863,10 @@ find_ec_member_for_tle(EquivalenceClass *ec,
 		 */
 		if (em->em_is_child &&
 			!bms_is_subset(em->em_relids, relids))
+		{
+			verify_em_child(root, em);
 			continue;
+		}
 
 		/* Match if same expression (after stripping relabel) */
 		emexpr = em->em_expr;
@@ -5883,7 +5889,7 @@ find_ec_member_for_tle(EquivalenceClass *ec,
  *	  'relids' is the set of relations required by prepare_sort_from_pathkeys()
  */
 static Sort *
-make_sort_from_pathkeys(Plan *lefttree, List *pathkeys, Relids relids)
+make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys, Relids relids)
 {
 	int			numsortkeys;
 	AttrNumber *sortColIdx;
@@ -5892,7 +5898,7 @@ make_sort_from_pathkeys(Plan *lefttree, List *pathkeys, Relids relids)
 	bool	   *nullsFirst;
 
 	/* Compute sort column info, and adjust lefttree as needed */
-	lefttree = prepare_sort_from_pathkeys(lefttree, pathkeys,
+	lefttree = prepare_sort_from_pathkeys(root, lefttree, pathkeys,
 										  relids,
 										  NULL,
 										  false,
@@ -6204,7 +6210,7 @@ make_unique_from_sortclauses(Plan *lefttree, List *distinctList)
  * as above, but use pathkeys to identify the sort columns and semantics
  */
 static Unique *
-make_unique_from_pathkeys(Plan *lefttree, List *pathkeys, int numCols)
+make_unique_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys, int numCols)
 {
 	Unique	   *node = makeNode(Unique);
 	Plan	   *plan = &node->plan;
@@ -6265,7 +6271,7 @@ make_unique_from_pathkeys(Plan *lefttree, List *pathkeys, int numCols)
 			foreach(j, plan->targetlist)
 			{
 				tle = (TargetEntry *) lfirst(j);
-				em = find_ec_member_for_tle(ec, tle, NULL);
+				em = find_ec_member_for_tle(root, ec, tle, NULL);
 				if (em)
 				{
 					/* found expr already in tlist */
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index cafde307ad..a3f34a5c8c 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -169,6 +169,7 @@ extern List *generate_implied_equalities_for_column(PlannerInfo *root,
 									   Relids prohibited_rels);
 extern bool have_relevant_eclass_joinclause(PlannerInfo *root,
 								RelOptInfo *rel1, RelOptInfo *rel2);
+extern void verify_em_child(PlannerInfo *root, EquivalenceMember *em);
 extern bool has_relevant_eclass_joinclause(PlannerInfo *root,
 							   RelOptInfo *rel1);
 extern bool eclass_useful_for_merging(PlannerInfo *root,