From adfa04293b34ac188c94ca81230348282687d3e9 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 23 Jul 2009 21:27:10 +0000
Subject: [PATCH] Save a few cycles in EXPLAIN and related commands by not
 bothering to form a physical tuple in do_tup_output().  A virtual tuple is
 easier to set up and also easier for most tuple receivers to process.  Per my
 comment on Robert Haas' recent patch in this code.

---
 src/backend/executor/execTuples.c | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index dffc7379cbe..d92ba062d44 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.108 2009/07/22 17:00:20 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.109 2009/07/23 21:27:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1215,27 +1215,28 @@ begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc)
 
 /*
  * write a single tuple
- *
- * XXX This could be made more efficient, since in reality we probably only
- * need a virtual tuple.
  */
 void
 do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull)
 {
-	TupleDesc	tupdesc = tstate->slot->tts_tupleDescriptor;
-	HeapTuple	tuple;
+	TupleTableSlot *slot = tstate->slot;
+	int			natts = slot->tts_tupleDescriptor->natts;
 
-	/* form a tuple */
-	tuple = heap_form_tuple(tupdesc, values, isnull);
+	/* make sure the slot is clear */
+	ExecClearTuple(slot);
 
-	/* put it in a slot */
-	ExecStoreTuple(tuple, tstate->slot, InvalidBuffer, true);
+	/* insert data */
+	memcpy(slot->tts_values, values, natts * sizeof(Datum));
+	memcpy(slot->tts_isnull, isnull, natts * sizeof(bool));
+
+	/* mark slot as containing a virtual tuple */
+	ExecStoreVirtualTuple(slot);
 
 	/* send the tuple to the receiver */
-	(*tstate->dest->receiveSlot) (tstate->slot, tstate->dest);
+	(*tstate->dest->receiveSlot) (slot, tstate->dest);
 
 	/* clean up */
-	ExecClearTuple(tstate->slot);
+	ExecClearTuple(slot);
 }
 
 /*
-- 
GitLab