1 /*-------------------------------------------------------------------------
2  *
3  * dest.c
4  *	  support for communication destinations
5  *
6  *
7  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  * IDENTIFICATION
11  *	  src/backend/tcop/dest.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 /*
16  *	 INTERFACE ROUTINES
17  *		BeginCommand - initialize the destination at start of command
18  *		CreateDestReceiver - create tuple receiver object for destination
19  *		EndCommand - clean up the destination at end of command
20  *		NullCommand - tell dest that an empty query string was recognized
21  *		ReadyForQuery - tell dest that we are ready for a new query
22  *
23  *	 NOTES
24  *		These routines do the appropriate work before and after
25  *		tuples are returned by a query to keep the backend and the
26  *		"destination" portals synchronized.
27  */
28 
29 #include "postgres.h"
30 
31 #include "access/printsimple.h"
32 #include "access/printtup.h"
33 #include "access/xact.h"
34 #include "commands/copy.h"
35 #include "commands/createas.h"
36 #include "commands/matview.h"
37 #include "executor/functions.h"
38 #include "executor/tqueue.h"
39 #include "executor/tstoreReceiver.h"
40 #include "libpq/libpq.h"
41 #include "libpq/pqformat.h"
42 #include "utils/portal.h"
43 
44 
45 /* ----------------
46  *		dummy DestReceiver functions
47  * ----------------
48  */
49 static bool
donothingReceive(TupleTableSlot * slot,DestReceiver * self)50 donothingReceive(TupleTableSlot *slot, DestReceiver *self)
51 {
52 	return true;
53 }
54 
55 static void
donothingStartup(DestReceiver * self,int operation,TupleDesc typeinfo)56 donothingStartup(DestReceiver *self, int operation, TupleDesc typeinfo)
57 {
58 }
59 
60 static void
donothingCleanup(DestReceiver * self)61 donothingCleanup(DestReceiver *self)
62 {
63 	/* this is used for both shutdown and destroy methods */
64 }
65 
66 /* ----------------
67  *		static DestReceiver structs for dest types needing no local state
68  * ----------------
69  */
70 static DestReceiver donothingDR = {
71 	donothingReceive, donothingStartup, donothingCleanup, donothingCleanup,
72 	DestNone
73 };
74 
75 static DestReceiver debugtupDR = {
76 	debugtup, debugStartup, donothingCleanup, donothingCleanup,
77 	DestDebug
78 };
79 
80 static DestReceiver printsimpleDR = {
81 	printsimple, printsimple_startup, donothingCleanup, donothingCleanup,
82 	DestRemoteSimple
83 };
84 
85 static DestReceiver spi_printtupDR = {
86 	spi_printtup, spi_dest_startup, donothingCleanup, donothingCleanup,
87 	DestSPI
88 };
89 
90 /* Globally available receiver for DestNone */
91 DestReceiver *None_Receiver = &donothingDR;
92 
93 
94 /* ----------------
95  *		BeginCommand - initialize the destination at start of command
96  * ----------------
97  */
98 void
BeginCommand(const char * commandTag,CommandDest dest)99 BeginCommand(const char *commandTag, CommandDest dest)
100 {
101 	/* Nothing to do at present */
102 }
103 
104 /* ----------------
105  *		CreateDestReceiver - return appropriate receiver function set for dest
106  * ----------------
107  */
108 DestReceiver *
CreateDestReceiver(CommandDest dest)109 CreateDestReceiver(CommandDest dest)
110 {
111 	switch (dest)
112 	{
113 		case DestRemote:
114 		case DestRemoteExecute:
115 			return printtup_create_DR(dest);
116 
117 		case DestRemoteSimple:
118 			return &printsimpleDR;
119 
120 		case DestNone:
121 			return &donothingDR;
122 
123 		case DestDebug:
124 			return &debugtupDR;
125 
126 		case DestSPI:
127 			return &spi_printtupDR;
128 
129 		case DestTuplestore:
130 			return CreateTuplestoreDestReceiver();
131 
132 		case DestIntoRel:
133 			return CreateIntoRelDestReceiver(NULL);
134 
135 		case DestCopyOut:
136 			return CreateCopyDestReceiver();
137 
138 		case DestSQLFunction:
139 			return CreateSQLFunctionDestReceiver();
140 
141 		case DestTransientRel:
142 			return CreateTransientRelDestReceiver(InvalidOid);
143 
144 		case DestTupleQueue:
145 			return CreateTupleQueueDestReceiver(NULL);
146 	}
147 
148 	/* should never get here */
149 	return &donothingDR;
150 }
151 
152 /* ----------------
153  *		EndCommand - clean up the destination at end of command
154  * ----------------
155  */
156 void
EndCommand(const char * commandTag,CommandDest dest)157 EndCommand(const char *commandTag, CommandDest dest)
158 {
159 	switch (dest)
160 	{
161 		case DestRemote:
162 		case DestRemoteExecute:
163 		case DestRemoteSimple:
164 
165 			/*
166 			 * We assume the commandTag is plain ASCII and therefore requires
167 			 * no encoding conversion.
168 			 */
169 			pq_putmessage('C', commandTag, strlen(commandTag) + 1);
170 			break;
171 
172 		case DestNone:
173 		case DestDebug:
174 		case DestSPI:
175 		case DestTuplestore:
176 		case DestIntoRel:
177 		case DestCopyOut:
178 		case DestSQLFunction:
179 		case DestTransientRel:
180 		case DestTupleQueue:
181 			break;
182 	}
183 }
184 
185 /* ----------------
186  *		NullCommand - tell dest that an empty query string was recognized
187  *
188  *		In FE/BE protocol version 1.0, this hack is necessary to support
189  *		libpq's crufty way of determining whether a multiple-command
190  *		query string is done.  In protocol 2.0 it's probably not really
191  *		necessary to distinguish empty queries anymore, but we still do it
192  *		for backwards compatibility with 1.0.  In protocol 3.0 it has some
193  *		use again, since it ensures that there will be a recognizable end
194  *		to the response to an Execute message.
195  * ----------------
196  */
197 void
NullCommand(CommandDest dest)198 NullCommand(CommandDest dest)
199 {
200 	switch (dest)
201 	{
202 		case DestRemote:
203 		case DestRemoteExecute:
204 		case DestRemoteSimple:
205 
206 			/*
207 			 * tell the fe that we saw an empty query string.  In protocols
208 			 * before 3.0 this has a useless empty-string message body.
209 			 */
210 			if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
211 				pq_putemptymessage('I');
212 			else
213 				pq_putmessage('I', "", 1);
214 			break;
215 
216 		case DestNone:
217 		case DestDebug:
218 		case DestSPI:
219 		case DestTuplestore:
220 		case DestIntoRel:
221 		case DestCopyOut:
222 		case DestSQLFunction:
223 		case DestTransientRel:
224 		case DestTupleQueue:
225 			break;
226 	}
227 }
228 
229 /* ----------------
230  *		ReadyForQuery - tell dest that we are ready for a new query
231  *
232  *		The ReadyForQuery message is sent so that the FE can tell when
233  *		we are done processing a query string.
234  *		In versions 3.0 and up, it also carries a transaction state indicator.
235  *
236  *		Note that by flushing the stdio buffer here, we can avoid doing it
237  *		most other places and thus reduce the number of separate packets sent.
238  * ----------------
239  */
240 void
ReadyForQuery(CommandDest dest)241 ReadyForQuery(CommandDest dest)
242 {
243 	switch (dest)
244 	{
245 		case DestRemote:
246 		case DestRemoteExecute:
247 		case DestRemoteSimple:
248 			if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
249 			{
250 				StringInfoData buf;
251 
252 				pq_beginmessage(&buf, 'Z');
253 				pq_sendbyte(&buf, TransactionBlockStatusCode());
254 				pq_endmessage(&buf);
255 			}
256 			else
257 				pq_putemptymessage('Z');
258 			/* Flush output at end of cycle in any case. */
259 			pq_flush();
260 			break;
261 
262 		case DestNone:
263 		case DestDebug:
264 		case DestSPI:
265 		case DestTuplestore:
266 		case DestIntoRel:
267 		case DestCopyOut:
268 		case DestSQLFunction:
269 		case DestTransientRel:
270 		case DestTupleQueue:
271 			break;
272 	}
273 }
274