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