Branch data 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
50 : 881148 : donothingReceive(TupleTableSlot *slot, DestReceiver *self)
51 : : {
52 : 881148 : return true;
53 : : }
54 : :
55 : : static void
56 : 2403 : donothingStartup(DestReceiver *self, int operation, TupleDesc typeinfo)
57 : : {
58 : 2403 : }
59 : :
60 : : static void
61 : 120347 : donothingCleanup(DestReceiver *self)
62 : : {
63 : : /* this is used for both shutdown and destroy methods */
64 : 120347 : }
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
103 : 460536 : BeginCommand(CommandTag commandTag, CommandDest dest)
104 : : {
105 : : /* Nothing to do at present */
106 : 460536 : }
107 : :
108 : : /* ----------------
109 : : * CreateDestReceiver - return appropriate receiver function set for dest
110 : : * ----------------
111 : : */
112 : : DestReceiver *
113 : 630816 : 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 : :
120 [ + + + + : 630816 : switch (dest)
+ + - + +
- - - - ]
121 : : {
122 : 409518 : case DestRemote:
123 : : case DestRemoteExecute:
124 : 409518 : return printtup_create_DR(dest);
125 : :
126 : 2512 : case DestRemoteSimple:
127 : 2512 : return unconstify(DestReceiver *, &printsimpleDR);
128 : :
129 : 616 : case DestNone:
130 : 616 : return unconstify(DestReceiver *, &donothingDR);
131 : :
132 : 41151 : case DestDebug:
133 : 41151 : return unconstify(DestReceiver *, &debugtupDR);
134 : :
135 : 94907 : case DestSPI:
136 : 94907 : return unconstify(DestReceiver *, &spi_printtupDR);
137 : :
138 : 33200 : case DestTuplestore:
139 : 33200 : return CreateTuplestoreDestReceiver();
140 : :
141 : 0 : case DestIntoRel:
142 : 0 : return CreateIntoRelDestReceiver(NULL);
143 : :
144 : 322 : case DestCopyOut:
145 : 322 : return CreateCopyDestReceiver();
146 : :
147 : 48590 : case DestSQLFunction:
148 : 48590 : return CreateSQLFunctionDestReceiver();
149 : :
150 : 0 : case DestTransientRel:
151 : 0 : return CreateTransientRelDestReceiver(InvalidOid);
152 : :
153 : 0 : case DestTupleQueue:
154 : 0 : return CreateTupleQueueDestReceiver(NULL);
155 : :
156 : 0 : case DestExplainSerialize:
157 : 0 : return CreateExplainSerializeDestReceiver(NULL);
158 : : }
159 : :
160 : : /* should never get here */
161 : 0 : pg_unreachable();
162 : : }
163 : :
164 : : /* ----------------
165 : : * EndCommand - clean up the destination at end of command
166 : : * ----------------
167 : : */
168 : :
169 : : void
170 : 430263 : EndCommandExtended(const QueryCompletion *qc, CommandDest dest,
171 : : bool force_undecorated_output, bool noblock)
172 : : {
173 : : char completionTag[COMPLETION_TAG_BUFSIZE];
174 : : Size len;
175 : :
176 [ + + - ]: 430263 : switch (dest)
177 : : {
178 : 389112 : case DestRemote:
179 : : case DestRemoteExecute:
180 : : case DestRemoteSimple:
181 : :
182 : 389112 : len = BuildQueryCompletionString(completionTag, qc,
183 : : force_undecorated_output);
184 [ + + ]: 389112 : if (noblock)
185 : 48 : pq_putmessage_noblock(PqMsg_CommandComplete, completionTag, len + 1);
186 : : else
187 : 389064 : pq_putmessage(PqMsg_CommandComplete, completionTag, len + 1);
188 : 389112 : break;
189 : :
190 : 41151 : 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:
200 : 41151 : break;
201 : : }
202 : 430263 : }
203 : :
204 : : void
205 : 430215 : EndCommand(const QueryCompletion *qc, CommandDest dest, bool force_undecorated_output)
206 : : {
207 : 430215 : EndCommandExtended(qc, dest, force_undecorated_output, false);
208 : 430215 : }
209 : :
210 : : /* ----------------
211 : : * EndReplicationCommand - stripped down version of EndCommand
212 : : *
213 : : * For use by replication commands.
214 : : * ----------------
215 : : */
216 : : void
217 : 2984 : EndReplicationCommand(const char *commandTag)
218 : : {
219 : 2984 : pq_putmessage(PqMsg_CommandComplete, commandTag, strlen(commandTag) + 1);
220 : 2984 : }
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
230 : 1019 : NullCommand(CommandDest dest)
231 : : {
232 [ + + - ]: 1019 : switch (dest)
233 : : {
234 : 1018 : case DestRemote:
235 : : case DestRemoteExecute:
236 : : case DestRemoteSimple:
237 : :
238 : : /* Tell the FE that we saw an empty query string */
239 : 1018 : pq_putemptymessage(PqMsg_EmptyQueryResponse);
240 : 1018 : break;
241 : :
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:
252 : 1 : break;
253 : : }
254 : 1019 : }
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 : 457197 : ReadyForQuery(CommandDest dest)
269 : : {
270 [ + + - ]: 457197 : switch (dest)
271 : : {
272 : 420646 : case DestRemote:
273 : : case DestRemoteExecute:
274 : : case DestRemoteSimple:
275 : : {
276 : : StringInfoData buf;
277 : :
278 : 420646 : pq_beginmessage(&buf, PqMsg_ReadyForQuery);
279 : 420646 : pq_sendbyte(&buf, TransactionBlockStatusCode());
280 : 420646 : pq_endmessage(&buf);
281 : : }
282 : : /* Flush output at end of cycle in any case. */
283 : 420646 : pq_flush();
284 : 420646 : break;
285 : :
286 : 36551 : 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:
296 : 36551 : break;
297 : : }
298 : 457197 : }
|