From d03e98737c5aec12332bbbaf12abe2e2642048c4 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 24 Jan 1999 05:40:49 +0000
Subject: [PATCH] Replace typtoout() and gettypelem() with a single routine, so
 that fetching an attribute value needs only one SearchSysCacheTuple call
 instead of two redundant searches.  This speeds up a large SELECT by about
 ten percent, and probably will help GROUP BY and SELECT DISTINCT too.

---
 src/backend/access/common/printtup.c | 89 ++++++++++++++--------------
 src/backend/executor/nodeGroup.c     | 14 ++---
 src/backend/executor/nodeUnique.c    | 19 +++---
 src/backend/executor/spi.c           | 12 ++--
 src/backend/libpq/be-dumpdata.c      | 13 ++--
 src/include/access/printtup.h        |  5 +-
 6 files changed, 74 insertions(+), 78 deletions(-)

diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c
index 641ef80126b..d8feb3a8128 100644
--- a/src/backend/access/common/printtup.c
+++ b/src/backend/access/common/printtup.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.37 1998/12/12 22:04:09 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.38 1999/01/24 05:40:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,11 +33,15 @@
  */
 
 /* ----------------
- *		typtoout - used by printtup and debugtup
+ *		getTypeOutAndElem -- get both typoutput and typelem for a type
+ *
+ * We used to fetch these with two separate function calls,
+ * typtoout() and gettypelem(), which each called SearchSysCacheTuple.
+ * This way takes half the time.
  * ----------------
  */
-Oid
-typtoout(Oid type)
+int
+getTypeOutAndElem(Oid type, Oid* typOutput, Oid* typElem)
 {
 	HeapTuple	typeTuple;
 
@@ -46,26 +50,18 @@ typtoout(Oid type)
 									0, 0, 0);
 
 	if (HeapTupleIsValid(typeTuple))
-		return (Oid) ((Form_pg_type) GETSTRUCT(typeTuple))->typoutput;
-
-	elog(ERROR, "typtoout: Cache lookup of type %d failed", type);
-	return InvalidOid;
-}
-
-Oid
-gettypelem(Oid type)
-{
-	HeapTuple	typeTuple;
-
-	typeTuple = SearchSysCacheTuple(TYPOID,
-									ObjectIdGetDatum(type),
-									0, 0, 0);
+	{
+		Form_pg_type pt = (Form_pg_type) GETSTRUCT(typeTuple);
+		*typOutput = (Oid) pt->typoutput;
+		*typElem = (Oid) pt->typelem;
+		return OidIsValid(*typOutput);
+	}
 
-	if (HeapTupleIsValid(typeTuple))
-		return (Oid) ((Form_pg_type) GETSTRUCT(typeTuple))->typelem;
+	elog(ERROR, "getTypeOutAndElem: Cache lookup of type %d failed", type);
 
-	elog(ERROR, "typtoout: Cache lookup of type %d failed", type);
-	return InvalidOid;
+	*typOutput = InvalidOid;
+	*typElem = InvalidOid;
+	return 0;
 }
 
 /* ----------------
@@ -77,19 +73,19 @@ printtup(HeapTuple tuple, TupleDesc typeinfo)
 {
 	int			i,
 				j,
-				k;
+				k,
+				outputlen;
 	char	   *outputstr;
 	Datum		attr;
 	bool		isnull;
-	Oid			typoutput;
-
+	Oid			typoutput,
+				typelem;
 #ifdef MULTIBYTE
 	unsigned char *p;
-
 #endif
 
 	/* ----------------
-	 *	tell the frontend to expect new tuple data
+	 *	tell the frontend to expect new tuple data (in ASCII style)
 	 * ----------------
 	 */
 	pq_putnchar("D", 1);
@@ -127,28 +123,29 @@ printtup(HeapTuple tuple, TupleDesc typeinfo)
 		attr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
 		if (isnull)
 			continue;
-
-		typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
-		if (OidIsValid(typoutput))
+		if (getTypeOutAndElem((Oid) typeinfo->attrs[i]->atttypid,
+							  &typoutput, &typelem))
 		{
-			outputstr = fmgr(typoutput, attr,
-							 gettypelem(typeinfo->attrs[i]->atttypid),
+			outputstr = fmgr(typoutput, attr, typelem,
 							 typeinfo->attrs[i]->atttypmod);
 #ifdef MULTIBYTE
 			p = pg_server_to_client(outputstr, strlen(outputstr));
-			pq_putint(strlen(p) + VARHDRSZ, VARHDRSZ);
-			pq_putnchar(p, strlen(p));
+			outputlen = strlen(p);
+			pq_putint(outputlen + VARHDRSZ, VARHDRSZ);
+			pq_putnchar(p, outputlen);
 #else
-			pq_putint(strlen(outputstr) + VARHDRSZ, VARHDRSZ);
-			pq_putnchar(outputstr, strlen(outputstr));
+			outputlen = strlen(outputstr);
+			pq_putint(outputlen + VARHDRSZ, VARHDRSZ);
+			pq_putnchar(outputstr, outputlen);
 #endif
 			pfree(outputstr);
 		}
 		else
 		{
 			outputstr = "<unprintable>";
-			pq_putint(strlen(outputstr) + VARHDRSZ, VARHDRSZ);
-			pq_putnchar(outputstr, strlen(outputstr));
+			outputlen = strlen(outputstr);
+			pq_putint(outputlen + VARHDRSZ, VARHDRSZ);
+			pq_putnchar(outputstr, outputlen);
 		}
 	}
 }
@@ -202,17 +199,18 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo)
 	Datum		attr;
 	char	   *value;
 	bool		isnull;
-	Oid			typoutput;
+	Oid			typoutput,
+				typelem;
 
 	for (i = 0; i < tuple->t_data->t_natts; ++i)
 	{
 		attr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
-		typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
-
-		if (!isnull && OidIsValid(typoutput))
+		if (isnull)
+			continue;
+		if (getTypeOutAndElem((Oid) typeinfo->attrs[i]->atttypid,
+							  &typoutput, &typelem))
 		{
-			value = fmgr(typoutput, attr,
-						 gettypelem(typeinfo->attrs[i]->atttypid),
+			value = fmgr(typoutput, attr, typelem,
 						 typeinfo->attrs[i]->atttypmod);
 			printatt((unsigned) i + 1, typeinfo->attrs[i], value);
 			pfree(value);
@@ -223,7 +221,6 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo)
 
 /* ----------------
  *		printtup_internal
- *		Protocol expects either T, D, C, E, or N.
  *		We use a different data prefix, e.g. 'B' instead of 'D' to
  *		indicate a tuple in internal (binary) form.
  *
@@ -240,7 +237,7 @@ printtup_internal(HeapTuple tuple, TupleDesc typeinfo)
 	bool		isnull;
 
 	/* ----------------
-	 *	tell the frontend to expect new tuple data
+	 *	tell the frontend to expect new tuple data (in binary style)
 	 * ----------------
 	 */
 	pq_putnchar("B", 1);
diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c
index 54cf97ca3e1..0f86f73a2b1 100644
--- a/src/backend/executor/nodeGroup.c
+++ b/src/backend/executor/nodeGroup.c
@@ -13,7 +13,7 @@
  *	  columns. (ie. tuples from the same group are consecutive)
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.23 1998/11/27 19:52:01 vadim Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.24 1999/01/24 05:40:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -364,12 +364,14 @@ sameGroup(HeapTuple oldtuple,
 			   *val2;
 	int			i;
 	AttrNumber	att;
-	Oid			typoutput;
+	Oid			typoutput,
+				typelem;
 
 	for (i = 0; i < numCols; i++)
 	{
 		att = grpColIdx[i];
-		typoutput = typtoout((Oid) tupdesc->attrs[att - 1]->atttypid);
+		getTypeOutAndElem((Oid) tupdesc->attrs[att - 1]->atttypid,
+						  &typoutput, &typelem);
 
 		attr1 = heap_getattr(oldtuple,
 							 att,
@@ -386,11 +388,9 @@ sameGroup(HeapTuple oldtuple,
 			if (isNull1)		/* both are null, they are equal */
 				continue;
 
-			val1 = fmgr(typoutput, attr1,
-						gettypelem(tupdesc->attrs[att - 1]->atttypid),
+			val1 = fmgr(typoutput, attr1, typelem,
 						tupdesc->attrs[att - 1]->atttypmod);
-			val2 = fmgr(typoutput, attr2,
-						gettypelem(tupdesc->attrs[att - 1]->atttypid),
+			val2 = fmgr(typoutput, attr2, typelem,
 						tupdesc->attrs[att - 1]->atttypmod);
 
 			/*
diff --git a/src/backend/executor/nodeUnique.c b/src/backend/executor/nodeUnique.c
index c04c44fa0d1..999362ab69d 100644
--- a/src/backend/executor/nodeUnique.c
+++ b/src/backend/executor/nodeUnique.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeUnique.c,v 1.18 1998/11/27 19:52:03 vadim Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeUnique.c,v 1.19 1999/01/24 05:40:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,7 +31,7 @@
 #include "executor/nodeUnique.h"
 #include "optimizer/clauses.h"
 #include "access/heapam.h"
-#include "access/printtup.h"	/* for typtoout() */
+#include "access/printtup.h"	/* for getTypeOutAndElem() */
 #include "utils/builtins.h"		/* for namecpy() */
 
 /* ----------------------------------------------------------------
@@ -117,7 +117,8 @@ ExecUnique(Unique *node)
 	char	   *uniqueAttr;
 	AttrNumber	uniqueAttrNum;
 	TupleDesc	tupDesc;
-	Oid			typoutput;
+	Oid			typoutput,
+				typelem;
 
 	/* ----------------
 	 *	get information from the node
@@ -132,12 +133,14 @@ ExecUnique(Unique *node)
 	if (uniqueAttr)
 	{
 		tupDesc = ExecGetResultType(uniquestate);
-		typoutput = typtoout((Oid) tupDesc->attrs[uniqueAttrNum - 1]->atttypid);
+		getTypeOutAndElem((Oid) tupDesc->attrs[uniqueAttrNum - 1]->atttypid,
+						  &typoutput, &typelem);
 	}
 	else
 	{							/* keep compiler quiet */
 		tupDesc = NULL;
-		typoutput = 0;
+		typoutput = InvalidOid;
+		typelem = InvalidOid;
 	}
 
 	/* ----------------
@@ -196,11 +199,9 @@ ExecUnique(Unique *node)
 			{
 				if (isNull1)	/* both are null, they are equal */
 					continue;
-				val1 = fmgr(typoutput, attr1,
-				 gettypelem(tupDesc->attrs[uniqueAttrNum - 1]->atttypid),
+				val1 = fmgr(typoutput, attr1, typelem,
 							tupDesc->attrs[uniqueAttrNum - 1]->atttypmod);
-				val2 = fmgr(typoutput, attr2,
-				 gettypelem(tupDesc->attrs[uniqueAttrNum - 1]->atttypid),
+				val2 = fmgr(typoutput, attr2, typelem,
 							tupDesc->attrs[uniqueAttrNum - 1]->atttypmod);
 
 				/*
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 125a36241ad..5620cf78916 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -3,7 +3,7 @@
  * spi.c--
  *				Server Programming Interface
  *
- * $Id: spi.c,v 1.29 1998/12/14 05:18:51 scrappy Exp $
+ * $Id: spi.c,v 1.30 1999/01/24 05:40:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -409,7 +409,8 @@ SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
 {
 	Datum		val;
 	bool		isnull;
-	Oid			foutoid;
+	Oid			foutoid,
+				typelem;
 
 	SPI_result = 0;
 	if (tuple->t_data->t_natts < fnumber || fnumber <= 0)
@@ -421,15 +422,14 @@ SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
 	val = heap_getattr(tuple, fnumber, tupdesc, &isnull);
 	if (isnull)
 		return NULL;
-	foutoid = typtoout((Oid) tupdesc->attrs[fnumber - 1]->atttypid);
-	if (!OidIsValid(foutoid))
+	if (! getTypeOutAndElem((Oid) tupdesc->attrs[fnumber - 1]->atttypid,
+							&foutoid, &typelem))
 	{
 		SPI_result = SPI_ERROR_NOOUTFUNC;
 		return NULL;
 	}
 
-	return (fmgr(foutoid, val,
-				 gettypelem(tupdesc->attrs[fnumber - 1]->atttypid),
+	return (fmgr(foutoid, val, typelem,
 				 tupdesc->attrs[fnumber - 1]->atttypmod));
 }
 
diff --git a/src/backend/libpq/be-dumpdata.c b/src/backend/libpq/be-dumpdata.c
index 116fb0c80bf..70d01e4dcf8 100644
--- a/src/backend/libpq/be-dumpdata.c
+++ b/src/backend/libpq/be-dumpdata.c
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- *  $Id: be-dumpdata.c,v 1.19 1998/12/14 06:50:23 scrappy Exp $
+ *  $Id: be-dumpdata.c,v 1.20 1999/01/24 05:40:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -213,7 +213,8 @@ be_printtup(HeapTuple tuple, TupleDesc typeinfo)
 	int			i;
 	Datum		attr;
 	bool		isnull;
-	Oid			typoutput;
+	Oid			typoutput,
+				typelem;
 
 	PortalEntry *entry = NULL;
 	PortalBuffer *portal = NULL;
@@ -298,7 +299,8 @@ be_printtup(HeapTuple tuple, TupleDesc typeinfo)
 	for (i = 0; i < tuple->t_data->t_natts; i++)
 	{
 		attr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
-		typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
+		getTypeOutAndElem((Oid) typeinfo->attrs[i]->atttypid,
+						  &typoutput, &typelem);
 
 		lengths[i] = typeinfo->attrs[i]->attlen;
 
@@ -311,11 +313,8 @@ be_printtup(HeapTuple tuple, TupleDesc typeinfo)
 		}
 
 		if (!isnull && OidIsValid(typoutput))
-		{
-			values[i] = fmgr(typoutput, attr,
-							 gettypelem(typeinfo->attrs[i]->atttypid),
+			values[i] = fmgr(typoutput, attr, typelem,
 							 typeinfo->attrs[i]->atttypmod);
-		}
 		else
 			values[i] = NULL;
 
diff --git a/src/include/access/printtup.h b/src/include/access/printtup.h
index 4b7aa7c2dd6..0b4f7b0f042 100644
--- a/src/include/access/printtup.h
+++ b/src/include/access/printtup.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: printtup.h,v 1.5 1998/09/01 04:34:22 momjian Exp $
+ * $Id: printtup.h,v 1.6 1999/01/24 05:40:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,11 +16,10 @@
 #include <access/htup.h>
 #include <access/tupdesc.h>
 
-extern Oid	typtoout(Oid type);
+extern int	getTypeOutAndElem(Oid type, Oid* typOutput, Oid* typElem);
 extern void printtup(HeapTuple tuple, TupleDesc typeinfo);
 extern void showatts(char *name, TupleDesc attinfo);
 extern void debugtup(HeapTuple tuple, TupleDesc typeinfo);
 extern void printtup_internal(HeapTuple tuple, TupleDesc typeinfo);
-extern Oid	gettypelem(Oid type);
 
 #endif	 /* PRINTTUP_H */
-- 
GitLab