Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * dest.c
4 : : * support for communication destinations
5 : : *
6 : : *
7 : : * Portions Copyright (c) 1996-2026, 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/explain_dr.h"
37 : : #include "commands/matview.h"
38 : : #include "executor/functions.h"
39 : : #include "executor/tqueue.h"
40 : : #include "executor/tstoreReceiver.h"
41 : : #include "libpq/libpq.h"
42 : : #include "libpq/pqformat.h"
43 : :
44 : :
45 : : /* ----------------
46 : : * dummy DestReceiver functions
47 : : * ----------------
48 : : */
49 : : static bool
7720 tgl@sss.pgh.pa.us 50 :CBC 881146 : donothingReceive(TupleTableSlot *slot, DestReceiver *self)
51 : : {
3620 rhaas@postgresql.org 52 : 881146 : return true;
53 : : }
54 : :
55 : : static void
8398 tgl@sss.pgh.pa.us 56 : 2398 : donothingStartup(DestReceiver *self, int operation, TupleDesc typeinfo)
57 : : {
9960 58 : 2398 : }
59 : :
60 : : static void
9842 bruce@momjian.us 61 : 120254 : donothingCleanup(DestReceiver *self)
62 : : {
63 : : /* this is used for both shutdown and destroy methods */
9960 tgl@sss.pgh.pa.us 64 : 120254 : }
65 : :
66 : : /* ----------------
67 : : * static DestReceiver structs for dest types needing no local state
68 : : * ----------------
69 : : */
70 : : static const DestReceiver donothingDR = {
71 : : donothingReceive, donothingStartup, donothingCleanup, donothingCleanup,
72 : : DestNone
73 : : };
74 : :
75 : : static const DestReceiver debugtupDR = {
76 : : debugtup, debugStartup, donothingCleanup, donothingCleanup,
77 : : DestDebug
78 : : };
79 : :
80 : : static const DestReceiver printsimpleDR = {
81 : : printsimple, printsimple_startup, donothingCleanup, donothingCleanup,
82 : : DestRemoteSimple
83 : : };
84 : :
85 : : static 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 : : */
96 : : DestReceiver *None_Receiver = (DestReceiver *) &donothingDR;
97 : :
98 : : /* ----------------
99 : : * BeginCommand - initialize the destination at start of command
100 : : * ----------------
101 : : */
102 : : void
2255 alvherre@alvh.no-ip. 103 : 461367 : BeginCommand(CommandTag commandTag, CommandDest dest)
104 : : {
105 : : /* Nothing to do at present */
9960 tgl@sss.pgh.pa.us 106 : 461367 : }
107 : :
108 : : /* ----------------
109 : : * CreateDestReceiver - return appropriate receiver function set for dest
110 : : * ----------------
111 : : */
112 : : DestReceiver *
6365 113 : 633429 : CreateDestReceiver(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 : :
9960 120 [ + + + + : 633429 : switch (dest)
+ + - + +
- - - - ]
121 : : {
7488 alvherre@alvh.no-ip. 122 : 410543 : case DestRemote:
123 : : case DestRemoteExecute:
6365 tgl@sss.pgh.pa.us 124 : 410543 : return printtup_create_DR(dest);
125 : :
3388 rhaas@postgresql.org 126 : 2520 : case DestRemoteSimple:
2758 andres@anarazel.de 127 : 2520 : return unconstify(DestReceiver *, &printsimpleDR);
128 : :
7488 alvherre@alvh.no-ip. 129 : 625 : case DestNone:
2758 andres@anarazel.de 130 : 625 : return unconstify(DestReceiver *, &donothingDR);
131 : :
7488 alvherre@alvh.no-ip. 132 : 41041 : case DestDebug:
2758 andres@anarazel.de 133 : 41041 : return unconstify(DestReceiver *, &debugtupDR);
134 : :
7488 alvherre@alvh.no-ip. 135 : 96241 : case DestSPI:
2758 andres@anarazel.de 136 : 96241 : return unconstify(DestReceiver *, &spi_printtupDR);
137 : :
7488 alvherre@alvh.no-ip. 138 : 32987 : case DestTuplestore:
6365 tgl@sss.pgh.pa.us 139 : 32987 : return CreateTuplestoreDestReceiver();
140 : :
7206 tgl@sss.pgh.pa.us 141 :UBC 0 : case DestIntoRel:
5160 142 : 0 : return CreateIntoRelDestReceiver(NULL);
143 : :
7188 tgl@sss.pgh.pa.us 144 :CBC 314 : case DestCopyOut:
145 : 314 : return CreateCopyDestReceiver();
146 : :
6395 147 : 49158 : case DestSQLFunction:
148 : 49158 : return CreateSQLFunctionDestReceiver();
149 : :
4811 kgrittn@postgresql.o 150 :UBC 0 : case DestTransientRel:
151 : 0 : return CreateTransientRelDestReceiver(InvalidOid);
152 : :
3882 rhaas@postgresql.org 153 : 0 : case DestTupleQueue:
154 : 0 : return CreateTupleQueueDestReceiver(NULL);
155 : :
762 tgl@sss.pgh.pa.us 156 : 0 : case DestExplainSerialize:
157 : 0 : return CreateExplainSerializeDestReceiver(NULL);
158 : : }
159 : :
160 : : /* should never get here */
2758 andres@anarazel.de 161 : 0 : pg_unreachable();
162 : : }
163 : :
164 : : /* ----------------
165 : : * EndCommand - clean up the destination at end of command
166 : : * ----------------
167 : : */
168 : :
169 : : void
4 fujii@postgresql.org 170 :GNC 431420 : EndCommandExtended(const QueryCompletion *qc, CommandDest dest,
171 : : bool force_undecorated_output, bool noblock)
172 : : {
173 : : char completionTag[COMPLETION_TAG_BUFSIZE];
174 : : Size len;
175 : :
10467 bruce@momjian.us 176 [ + + - ]:CBC 431420 : switch (dest)
177 : : {
7488 alvherre@alvh.no-ip. 178 : 390379 : case DestRemote:
179 : : case DestRemoteExecute:
180 : : case DestRemoteSimple:
181 : :
1236 drowley@postgresql.o 182 : 390379 : len = BuildQueryCompletionString(completionTag, qc,
183 : : force_undecorated_output);
4 fujii@postgresql.org 184 [ + + ]:GNC 390379 : if (noblock)
185 : 47 : pq_putmessage_noblock(PqMsg_CommandComplete, completionTag, len + 1);
186 : : else
187 : 390332 : pq_putmessage(PqMsg_CommandComplete, completionTag, len + 1);
71 peter@eisentraut.org 188 : 390379 : break;
189 : :
7488 alvherre@alvh.no-ip. 190 :CBC 41041 : case DestNone:
191 : : case DestDebug:
192 : : case DestSPI:
193 : : case DestTuplestore:
194 : : case DestIntoRel:
195 : : case DestCopyOut:
196 : : case DestSQLFunction:
197 : : case DestTransientRel:
198 : : case DestTupleQueue:
199 : : case DestExplainSerialize:
10466 bruce@momjian.us 200 : 41041 : break;
201 : : }
10892 scrappy@hub.org 202 : 431420 : }
203 : :
204 : : void
4 fujii@postgresql.org 205 :GNC 431373 : EndCommand(const QueryCompletion *qc, CommandDest dest, bool force_undecorated_output)
206 : : {
207 : 431373 : EndCommandExtended(qc, dest, force_undecorated_output, false);
208 : 431373 : }
209 : :
210 : : /* ----------------
211 : : * EndReplicationCommand - stripped down version of EndCommand
212 : : *
213 : : * For use by replication commands.
214 : : * ----------------
215 : : */
216 : : void
2057 alvherre@alvh.no-ip. 217 :CBC 2978 : EndReplicationCommand(const char *commandTag)
218 : : {
980 nathan@postgresql.or 219 : 2978 : pq_putmessage(PqMsg_CommandComplete, commandTag, strlen(commandTag) + 1);
2057 alvherre@alvh.no-ip. 220 : 2978 : }
221 : :
222 : : /* ----------------
223 : : * NullCommand - tell dest that an empty query string was recognized
224 : : *
225 : : * This ensures that there will be a recognizable end to the response
226 : : * to an Execute message in the extended query protocol.
227 : : * ----------------
228 : : */
229 : : void
10892 scrappy@hub.org 230 : 1157 : NullCommand(CommandDest dest)
231 : : {
10467 bruce@momjian.us 232 [ + + - ]: 1157 : switch (dest)
233 : : {
7488 alvherre@alvh.no-ip. 234 : 1156 : case DestRemote:
235 : : case DestRemoteExecute:
236 : : case DestRemoteSimple:
237 : :
238 : : /* Tell the FE that we saw an empty query string */
987 nathan@postgresql.or 239 : 1156 : pq_putemptymessage(PqMsg_EmptyQueryResponse);
10226 bruce@momjian.us 240 : 1156 : break;
241 : :
7488 alvherre@alvh.no-ip. 242 : 1 : case DestNone:
243 : : case DestDebug:
244 : : case DestSPI:
245 : : case DestTuplestore:
246 : : case DestIntoRel:
247 : : case DestCopyOut:
248 : : case DestSQLFunction:
249 : : case DestTransientRel:
250 : : case DestTupleQueue:
251 : : case DestExplainSerialize:
10226 bruce@momjian.us 252 : 1 : break;
253 : : }
254 : 1157 : }
255 : :
256 : : /* ----------------
257 : : * ReadyForQuery - tell dest that we are ready for a new query
258 : : *
259 : : * The ReadyForQuery message is sent so that the FE can tell when
260 : : * we are done processing a query string.
261 : : * In versions 3.0 and up, it also carries a transaction state indicator.
262 : : *
263 : : * Note that by flushing the stdio buffer here, we can avoid doing it
264 : : * most other places and thus reduce the number of separate packets sent.
265 : : * ----------------
266 : : */
267 : : void
268 : 457381 : ReadyForQuery(CommandDest dest)
269 : : {
10467 270 [ + + - ]: 457381 : switch (dest)
271 : : {
7488 alvherre@alvh.no-ip. 272 : 420940 : case DestRemote:
273 : : case DestRemoteExecute:
274 : : case DestRemoteSimple:
275 : : {
276 : : StringInfoData buf;
277 : :
987 nathan@postgresql.or 278 : 420940 : pq_beginmessage(&buf, PqMsg_ReadyForQuery);
8410 tgl@sss.pgh.pa.us 279 : 420940 : pq_sendbyte(&buf, TransactionBlockStatusCode());
280 : 420940 : pq_endmessage(&buf);
281 : : }
282 : : /* Flush output at end of cycle in any case. */
9960 283 : 420940 : pq_flush();
10466 bruce@momjian.us 284 : 420940 : break;
285 : :
7488 alvherre@alvh.no-ip. 286 : 36441 : case DestNone:
287 : : case DestDebug:
288 : : case DestSPI:
289 : : case DestTuplestore:
290 : : case DestIntoRel:
291 : : case DestCopyOut:
292 : : case DestSQLFunction:
293 : : case DestTransientRel:
294 : : case DestTupleQueue:
295 : : case DestExplainSerialize:
10466 bruce@momjian.us 296 : 36441 : break;
297 : : }
10892 scrappy@hub.org 298 : 457381 : }
|