From ecf76b433a30591b259f2c62c8e7348b36dcd851 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Sat, 19 Jan 2019 23:22:39 -0800
Subject: [PATCH v18 09/18] tableam: slotify CREATE TABLE AS and CREATE
 MATERIALIZED VIEW.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/commands/createas.c | 26 ++++++++++++++++----------
 src/backend/commands/matview.c  | 26 ++++++++++++++------------
 2 files changed, 30 insertions(+), 22 deletions(-)

diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index 55f61854614..31b8691c988 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -27,6 +27,7 @@
 #include "access/heapam.h"
 #include "access/reloptions.h"
 #include "access/htup_details.h"
+#include "access/tableam.h"
 #include "access/sysattr.h"
 #include "access/tableam.h"
 #include "access/xact.h"
@@ -61,7 +62,8 @@ typedef struct
 	ObjectAddress reladdr;		/* address of rel, for ExecCreateTableAs */
 	CommandId	output_cid;		/* cmin to insert in output tuples */
 	int			hi_options;		/* heap_insert performance options */
-	BulkInsertState bistate;	/* bulk insert state */
+	BulkInsertState bistate;		/* bulk insert state */
+	TupleTableSlot *slot;
 } DR_intorel;
 
 /* utility functions for CTAS definition creation */
@@ -553,6 +555,7 @@ intorel_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
 	myState->rel = intoRelationDesc;
 	myState->reladdr = intoRelationAddr;
 	myState->output_cid = GetCurrentCommandId(true);
+	myState->slot = table_slot_create(intoRelationDesc, NULL);
 
 	/*
 	 * We can skip WAL-logging the insertions, unless PITR or streaming
@@ -573,19 +576,21 @@ static bool
 intorel_receive(TupleTableSlot *slot, DestReceiver *self)
 {
 	DR_intorel *myState = (DR_intorel *) self;
-	HeapTuple	tuple;
 
 	/*
-	 * get the heap tuple out of the tuple table slot, making sure we have a
-	 * writable copy
+	 * Ensure input tuple is the right format for the target relation.
 	 */
-	tuple = ExecCopySlotHeapTuple(slot);
+	if (slot->tts_ops != myState->slot->tts_ops)
+	{
+		ExecCopySlot(myState->slot, slot);
+		slot = myState->slot;
+	}
 
-	heap_insert(myState->rel,
-				tuple,
-				myState->output_cid,
-				myState->hi_options,
-				myState->bistate);
+	table_insert(myState->rel,
+				 slot,
+				 myState->output_cid,
+				 myState->hi_options,
+				 myState->bistate);
 
 	/* We know this is a newly created relation, so there are no indexes */
 
@@ -600,6 +605,7 @@ intorel_shutdown(DestReceiver *self)
 {
 	DR_intorel *myState = (DR_intorel *) self;
 
+	ExecDropSingleTupleTableSlot(myState->slot);
 	FreeBulkInsertState(myState->bistate);
 
 	table_finish_bulk_insert(myState->rel, myState->hi_options);
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index 62b76cfd358..e291ad0c547 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -56,6 +56,7 @@ typedef struct
 	CommandId	output_cid;		/* cmin to insert in output tuples */
 	int			hi_options;		/* heap_insert performance options */
 	BulkInsertState bistate;	/* bulk insert state */
+	TupleTableSlot *slot;
 } DR_transientrel;
 
 static int	matview_maintenance_depth = 0;
@@ -457,6 +458,7 @@ transientrel_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
 	 */
 	myState->transientrel = transientrel;
 	myState->output_cid = GetCurrentCommandId(true);
+	myState->slot = table_slot_create(transientrel, NULL);
 
 	/*
 	 * We can skip WAL-logging the insertions, unless PITR or streaming
@@ -478,25 +480,24 @@ static bool
 transientrel_receive(TupleTableSlot *slot, DestReceiver *self)
 {
 	DR_transientrel *myState = (DR_transientrel *) self;
-	HeapTuple	tuple;
 
 	/*
-	 * get the heap tuple out of the tuple table slot, making sure we have a
-	 * writable copy
+	 * Ensure input tuple is the right format for the target relation.
 	 */
-	tuple = ExecCopySlotHeapTuple(slot);
+	if (slot->tts_ops != myState->slot->tts_ops)
+	{
+		ExecCopySlot(myState->slot, slot);
+		slot = myState->slot;
+	}
 
-	heap_insert(myState->transientrel,
-				tuple,
-				myState->output_cid,
-				myState->hi_options,
-				myState->bistate);
+	table_insert(myState->transientrel,
+				 slot,
+				 myState->output_cid,
+				 myState->hi_options,
+				 myState->bistate);
 
 	/* We know this is a newly created relation, so there are no indexes */
 
-	/* Free the copied tuple. */
-	heap_freetuple(tuple);
-
 	return true;
 }
 
@@ -508,6 +509,7 @@ transientrel_shutdown(DestReceiver *self)
 {
 	DR_transientrel *myState = (DR_transientrel *) self;
 
+	ExecDropSingleTupleTableSlot(myState->slot);
 	FreeBulkInsertState(myState->bistate);
 
 	table_finish_bulk_insert(myState->transientrel, myState->hi_options);
-- 
2.21.0.dirty

