1/*-------------------------------------------------------------------------
2 *
3 * dest.c
4 * support for communication destinations
5 *
6 *
7 * Portions Copyright (c) 1996-2019, 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 */
49static bool
50donothingReceive(TupleTableSlot *slot, DestReceiver *self)
51{
52 return true;
53}
54
55static void
56donothingStartup(DestReceiver *self, int operation, TupleDesc typeinfo)
57{
58}
59
60static void
61donothingCleanup(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 */
70static const DestReceiver donothingDR = {
71 donothingReceive, donothingStartup, donothingCleanup, donothingCleanup,
72 DestNone
73};
74
75static const DestReceiver debugtupDR = {
76 debugtup, debugStartup, donothingCleanup, donothingCleanup,
77 DestDebug
78};
79
80static const DestReceiver printsimpleDR = {
81 printsimple, printsimple_startup, donothingCleanup, donothingCleanup,
82 DestRemoteSimple
83};
84
85static const DestReceiver spi_printtupDR = {
86 spi_printtup, spi_dest_startup, donothingCleanup, donothingCleanup,
87 DestSPI
88};
89
90/*
91 * Globally available receiver for DestNone.
92 *
93 * It's ok to cast the constness away as any modification of the none receiver
94 * would be a bug (which gets easier to catch this way).
95 */
96DestReceiver *None_Receiver = (DestReceiver *) &donothingDR;
97
98/* ----------------
99 * BeginCommand - initialize the destination at start of command
100 * ----------------
101 */
102void
103BeginCommand(const char *commandTag, CommandDest dest)
104{
105 /* Nothing to do at present */
106}
107
108/* ----------------
109 * CreateDestReceiver - return appropriate receiver function set for dest
110 * ----------------
111 */
112DestReceiver *
113CreateDestReceiver(CommandDest dest)
114{
115 /*
116 * It's ok to cast the constness away as any modification of the none
117 * receiver would be a bug (which gets easier to catch this way).
118 */
119
120 switch (dest)
121 {
122 case DestRemote:
123 case DestRemoteExecute:
124 return printtup_create_DR(dest);
125
126 case DestRemoteSimple:
127 return unconstify(DestReceiver *, &printsimpleDR);
128
129 case DestNone:
130 return unconstify(DestReceiver *, &donothingDR);
131
132 case DestDebug:
133 return unconstify(DestReceiver *, &debugtupDR);
134
135 case DestSPI:
136 return unconstify(DestReceiver *, &spi_printtupDR);
137
138 case DestTuplestore:
139 return CreateTuplestoreDestReceiver();
140
141 case DestIntoRel:
142 return CreateIntoRelDestReceiver(NULL);
143
144 case DestCopyOut:
145 return CreateCopyDestReceiver();
146
147 case DestSQLFunction:
148 return CreateSQLFunctionDestReceiver();
149
150 case DestTransientRel:
151 return CreateTransientRelDestReceiver(InvalidOid);
152
153 case DestTupleQueue:
154 return CreateTupleQueueDestReceiver(NULL);
155 }
156
157 /* should never get here */
158 pg_unreachable();
159}
160
161/* ----------------
162 * EndCommand - clean up the destination at end of command
163 * ----------------
164 */
165void
166EndCommand(const char *commandTag, CommandDest dest)
167{
168 switch (dest)
169 {
170 case DestRemote:
171 case DestRemoteExecute:
172 case DestRemoteSimple:
173
174 /*
175 * We assume the commandTag is plain ASCII and therefore requires
176 * no encoding conversion.
177 */
178 pq_putmessage('C', commandTag, strlen(commandTag) + 1);
179 break;
180
181 case DestNone:
182 case DestDebug:
183 case DestSPI:
184 case DestTuplestore:
185 case DestIntoRel:
186 case DestCopyOut:
187 case DestSQLFunction:
188 case DestTransientRel:
189 case DestTupleQueue:
190 break;
191 }
192}
193
194/* ----------------
195 * NullCommand - tell dest that an empty query string was recognized
196 *
197 * In FE/BE protocol version 1.0, this hack is necessary to support
198 * libpq's crufty way of determining whether a multiple-command
199 * query string is done. In protocol 2.0 it's probably not really
200 * necessary to distinguish empty queries anymore, but we still do it
201 * for backwards compatibility with 1.0. In protocol 3.0 it has some
202 * use again, since it ensures that there will be a recognizable end
203 * to the response to an Execute message.
204 * ----------------
205 */
206void
207NullCommand(CommandDest dest)
208{
209 switch (dest)
210 {
211 case DestRemote:
212 case DestRemoteExecute:
213 case DestRemoteSimple:
214
215 /*
216 * tell the fe that we saw an empty query string. In protocols
217 * before 3.0 this has a useless empty-string message body.
218 */
219 if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
220 pq_putemptymessage('I');
221 else
222 pq_putmessage('I', "", 1);
223 break;
224
225 case DestNone:
226 case DestDebug:
227 case DestSPI:
228 case DestTuplestore:
229 case DestIntoRel:
230 case DestCopyOut:
231 case DestSQLFunction:
232 case DestTransientRel:
233 case DestTupleQueue:
234 break;
235 }
236}
237
238/* ----------------
239 * ReadyForQuery - tell dest that we are ready for a new query
240 *
241 * The ReadyForQuery message is sent so that the FE can tell when
242 * we are done processing a query string.
243 * In versions 3.0 and up, it also carries a transaction state indicator.
244 *
245 * Note that by flushing the stdio buffer here, we can avoid doing it
246 * most other places and thus reduce the number of separate packets sent.
247 * ----------------
248 */
249void
250ReadyForQuery(CommandDest dest)
251{
252 switch (dest)
253 {
254 case DestRemote:
255 case DestRemoteExecute:
256 case DestRemoteSimple:
257 if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
258 {
259 StringInfoData buf;
260
261 pq_beginmessage(&buf, 'Z');
262 pq_sendbyte(&buf, TransactionBlockStatusCode());
263 pq_endmessage(&buf);
264 }
265 else
266 pq_putemptymessage('Z');
267 /* Flush output at end of cycle in any case. */
268 pq_flush();
269 break;
270
271 case DestNone:
272 case DestDebug:
273 case DestSPI:
274 case DestTuplestore:
275 case DestIntoRel:
276 case DestCopyOut:
277 case DestSQLFunction:
278 case DestTransientRel:
279 case DestTupleQueue:
280 break;
281 }
282}
283