From 82a8593dfdb49bf84833dddd7c725a5545e16d04 Mon Sep 17 00:00:00 2001
From: amit <amitlangote09@gmail.com>
Date: Mon, 26 Dec 2016 17:44:14 +0900
Subject: [PATCH 5/7] Avoid tuple coversion in common partitioning cases

Currently, the tuple conversion is performed after a tuple is routed,
even if the attributes of a target leaf partition map one-to-one with
those of the root table, which is wasteful.  Avoid that by making
convert_tuples_by_name() return a NULL map for such cases.

Reported by: n/a
Patch by: Amit Langote
Reports: n/a
---
 src/backend/access/common/tupconvert.c | 8 ++++++--
 src/backend/catalog/partition.c        | 5 ++---
 src/backend/commands/analyze.c         | 1 +
 src/backend/executor/execMain.c        | 7 ++++---
 src/backend/executor/execQual.c        | 2 +-
 src/include/access/tupconvert.h        | 1 +
 6 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/src/backend/access/common/tupconvert.c b/src/backend/access/common/tupconvert.c
index b17ceafa6e..bbbd271e1f 100644
--- a/src/backend/access/common/tupconvert.c
+++ b/src/backend/access/common/tupconvert.c
@@ -202,6 +202,7 @@ convert_tuples_by_position(TupleDesc indesc,
 TupleConversionMap *
 convert_tuples_by_name(TupleDesc indesc,
 					   TupleDesc outdesc,
+					   bool consider_typeid,
 					   const char *msg)
 {
 	TupleConversionMap *map;
@@ -216,11 +217,14 @@ convert_tuples_by_name(TupleDesc indesc,
 	/*
 	 * Check to see if the map is one-to-one and the tuple types are the same.
 	 * (We check the latter because if they're not, we want to do conversion
-	 * to inject the right OID into the tuple datum.)
+	 * to inject the right OID into the tuple datum.  In the partitioning
+	 * case (!consider_typeid), tdhasoids must always match between indesc
+	 * and outdesc, so we need not require tdtypeid's to be the same.)
 	 */
 	if (indesc->natts == outdesc->natts &&
-		indesc->tdtypeid == outdesc->tdtypeid)
+		(!consider_typeid || indesc->tdtypeid == outdesc->tdtypeid))
 	{
+		Assert(!consider_typeid && indesc->tdhasoid == outdesc->tdhasoid);
 		same = true;
 		for (i = 0; i < n; i++)
 		{
diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c
index 874e69d8d6..61ad945062 100644
--- a/src/backend/catalog/partition.c
+++ b/src/backend/catalog/partition.c
@@ -1054,7 +1054,7 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
 			 */
 			pd[i]->tupslot = MakeSingleTupleTableSlot(tupdesc);
 			pd[i]->tupmap = convert_tuples_by_name(RelationGetDescr(parent),
-												   tupdesc,
+												   tupdesc, false,
 								gettext_noop("could not convert row type"));
 		}
 		else
@@ -1660,12 +1660,11 @@ get_partition_for_tuple(PartitionDispatch *pd,
 			return -1;
 		}
 
-		if (myslot != NULL)
+		if (myslot != NULL && map != NULL)
 		{
 			HeapTuple	tuple = ExecFetchSlotTuple(slot);
 
 			ExecClearTuple(myslot);
-			Assert(map != NULL);
 			tuple = do_convert_tuple(tuple, map);
 			ExecStoreTuple(tuple, myslot, InvalidBuffer, true);
 			slot = myslot;
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index e3e1a53072..31bec9f961 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -1419,6 +1419,7 @@ acquire_inherited_sample_rows(Relation onerel, int elevel,
 
 					map = convert_tuples_by_name(RelationGetDescr(childrel),
 												 RelationGetDescr(onerel),
+												 true,
 								 gettext_noop("could not convert row type"));
 					if (map != NULL)
 					{
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 7a073c6df3..d3ebf7e146 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1828,7 +1828,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
 					rel = resultRelInfo->ri_PartitionRoot;
 					tupdesc = RelationGetDescr(rel);
 					/* a reverse map */
-					map = convert_tuples_by_name(orig_tupdesc, tupdesc,
+					map = convert_tuples_by_name(orig_tupdesc, tupdesc, false,
 								gettext_noop("could not convert row type"));
 					if (map != NULL)
 					{
@@ -1875,7 +1875,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
 				rel = resultRelInfo->ri_PartitionRoot;
 				tupdesc = RelationGetDescr(rel);
 				/* a reverse map */
-				map = convert_tuples_by_name(old_tupdesc, tupdesc,
+				map = convert_tuples_by_name(old_tupdesc, tupdesc, false,
 							gettext_noop("could not convert row type"));
 				if (map != NULL)
 				{
@@ -1917,7 +1917,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
 			rel = resultRelInfo->ri_PartitionRoot;
 			tupdesc = RelationGetDescr(rel);
 			/* a reverse map */
-			map = convert_tuples_by_name(old_tupdesc, tupdesc,
+			map = convert_tuples_by_name(old_tupdesc, tupdesc, false,
 						gettext_noop("could not convert row type"));
 			if (map != NULL)
 			{
@@ -3189,6 +3189,7 @@ ExecSetupPartitionTupleRouting(Relation rel,
 		 * partition from the parent's type to the partition's.
 		 */
 		(*tup_conv_maps)[i] = convert_tuples_by_name(tupDesc, part_tupdesc,
+													 false,
 								 gettext_noop("could not convert row type"));
 
 		InitResultRelInfo(leaf_part_rri,
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index bf007b7efd..346b2ff17e 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -2928,7 +2928,7 @@ ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
 
 		/* prepare map from old to new attribute numbers */
 		cstate->map = convert_tuples_by_name(cstate->indesc,
-											 cstate->outdesc,
+											 cstate->outdesc, true,
 								 gettext_noop("could not convert row type"));
 		cstate->initialized = true;
 
diff --git a/src/include/access/tupconvert.h b/src/include/access/tupconvert.h
index e86cfd56c8..231fe872d7 100644
--- a/src/include/access/tupconvert.h
+++ b/src/include/access/tupconvert.h
@@ -36,6 +36,7 @@ extern TupleConversionMap *convert_tuples_by_position(TupleDesc indesc,
 
 extern TupleConversionMap *convert_tuples_by_name(TupleDesc indesc,
 					   TupleDesc outdesc,
+					   bool consider_typeid,
 					   const char *msg);
 
 extern AttrNumber *convert_tuples_by_name_map(TupleDesc indesc,
-- 
2.11.0

