From bb853aca8e5bb2b1175e608f7eaaaa480a332c2e Mon Sep 17 00:00:00 2001
From: amit <amitlangote09@gmail.com>
Date: Thu, 8 Aug 2019 13:49:29 +0900
Subject: [PATCH v2 1/2] Improve RelOptInfo.partition_qual usage

This includes following improvements:

 1. Initialize partition_qual with necessary polishing in only one
    place, that is, in get_relation_info(), instead of having it be
    duplicated in places where it's used

 2. get_relation_constraints() can use partition_qual instead of
    fetching it from the relcache
---
 src/backend/optimizer/util/plancat.c | 41 ++++++++++++++----------------------
 src/backend/optimizer/util/relnode.c |  2 +-
 src/backend/partitioning/partprune.c | 32 ++++++----------------------
 3 files changed, 23 insertions(+), 52 deletions(-)

diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 98e99481c6..2653a69220 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -115,6 +115,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 	Relation	relation;
 	bool		hasindex;
 	List	   *indexinfos = NIL;
+	List	   *partconstr;
 
 	/*
 	 * We need not lock the relation since it was already locked, either by
@@ -458,6 +459,17 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 	if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
 		set_relation_partition_info(root, rel, relation);
 
+	/* Initialize the partition constraint if any */
+	partconstr = RelationGetPartitionQual(relation);
+	if (partconstr)
+	{
+		partconstr = (List *) expression_planner((Expr *) partconstr);
+		/* Fix Vars to have desired varno. */
+		if (rel->relid != 1)
+			ChangeVarNodes((Node *) partconstr, 1, rel->relid, 0);
+		rel->partition_qual = partconstr;
+	}
+
 	table_close(relation, NoLock);
 
 	/*
@@ -1262,33 +1274,13 @@ get_relation_constraints(PlannerInfo *root,
 		}
 	}
 
+	table_close(relation, NoLock);
+
 	/*
 	 * Add partitioning constraints, if requested.
 	 */
-	if (include_partition && relation->rd_rel->relispartition)
-	{
-		List	   *pcqual = RelationGetPartitionQual(relation);
-
-		if (pcqual)
-		{
-			/*
-			 * Run the partition quals through const-simplification similar to
-			 * check constraints.  We skip canonicalize_qual, though, because
-			 * partition quals should be in canonical form already; also,
-			 * since the qual is in implicit-AND format, we'd have to
-			 * explicitly convert it to explicit-AND format and back again.
-			 */
-			pcqual = (List *) eval_const_expressions(root, (Node *) pcqual);
-
-			/* Fix Vars to have the desired varno */
-			if (varno != 1)
-				ChangeVarNodes((Node *) pcqual, 1, varno, 0);
-
-			result = list_concat(result, pcqual);
-		}
-	}
-
-	table_close(relation, NoLock);
+	if (include_partition)
+		result = list_concat(result, rel->partition_qual);
 
 	return result;
 }
@@ -2149,7 +2141,6 @@ set_relation_partition_info(PlannerInfo *root, RelOptInfo *rel,
 	rel->boundinfo = partdesc->boundinfo;
 	rel->nparts = partdesc->nparts;
 	set_baserel_partition_key_exprs(relation, rel);
-	rel->partition_qual = RelationGetPartitionQual(relation);
 }
 
 /*
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 37d228ce5d..49e1fc5b74 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -239,7 +239,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
 	rel->part_scheme = NULL;
 	rel->nparts = 0;
 	rel->boundinfo = NULL;
-	rel->partition_qual = NIL;
+	rel->partition_qual = NIL;	/* set in get_relation_info() */
 	rel->part_rels = NULL;
 	rel->partexprs = NULL;
 	rel->nullable_partexprs = NULL;
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index 2ed1e44c18..d399df6cf5 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -631,19 +631,10 @@ gen_partprune_steps(RelOptInfo *rel, List *clauses, PartClauseTarget target,
 	 * partition qual to the clause list in this case only.  This may result
 	 * in the default partition being eliminated.
 	 */
-	if (partition_bound_has_default(rel->boundinfo) &&
-		rel->partition_qual != NIL)
+	if (partition_bound_has_default(rel->boundinfo) && rel->partition_qual)
 	{
-		List	   *partqual = rel->partition_qual;
-
-		partqual = (List *) expression_planner((Expr *) partqual);
-
-		/* Fix Vars to have the desired varno */
-		if (rel->relid != 1)
-			ChangeVarNodes((Node *) partqual, 1, rel->relid, 0);
-
 		/* Use list_copy to avoid modifying the passed-in List */
-		clauses = list_concat(list_copy(clauses), partqual);
+		clauses = list_concat(list_copy(clauses), rel->partition_qual);
 	}
 
 	/* Down into the rabbit-hole. */
@@ -1024,22 +1015,11 @@ gen_partprune_steps_internal(GeneratePruningStepsContext *context,
 		 * as contradictory and we're done.  This is particularly helpful to
 		 * prune the default partition.
 		 */
-		if (context->rel->partition_qual)
+		if (predicate_refuted_by(context->rel->partition_qual,
+								 list_make1(clause), false))
 		{
-			List	   *partconstr;
-
-			partconstr = (List *)
-				expression_planner((Expr *) context->rel->partition_qual);
-			if (context->rel->relid != 1)
-				ChangeVarNodes((Node *) partconstr, 1,
-							   context->rel->relid, 0);
-			if (predicate_refuted_by(partconstr,
-									 list_make1(clause),
-									 false))
-			{
-				context->contradictory = true;
-				return NIL;
-			}
+			context->contradictory = true;
+			return NIL;
 		}
 
 		/*
-- 
2.11.0

