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 120218 : donothingCleanup(DestReceiver *self)
62 : {
63 : /* this is used for both shutdown and destroy methods */
64 120218 : }
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 465646 : BeginCommand(CommandTag commandTag, CommandDest dest)
104 : {
105 : /* Nothing to do at present */
106 465646 : }
107 :
108 : /* ----------------
109 : * CreateDestReceiver - return appropriate receiver function set for dest
110 : * ----------------
111 : */
112 : DestReceiver *
113 635991 : 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 635991 : switch (dest)
121 : {
122 414793 : case DestRemote:
123 : case DestRemoteExecute:
124 414793 : return printtup_create_DR(dest);
125 :
126 2513 : case DestRemoteSimple:
127 2513 : return unconstify(DestReceiver *, &printsimpleDR);
128 :
129 611 : case DestNone:
130 611 : return unconstify(DestReceiver *, &donothingDR);
131 :
132 41041 : case DestDebug:
133 41041 : return unconstify(DestReceiver *, &debugtupDR);
134 :
135 94781 : case DestSPI:
136 94781 : return unconstify(DestReceiver *, &spi_printtupDR);
137 :
138 33136 : case DestTuplestore:
139 33136 : return CreateTuplestoreDestReceiver();
140 :
141 0 : case DestIntoRel:
142 0 : return CreateIntoRelDestReceiver(NULL);
143 :
144 314 : case DestCopyOut:
145 314 : return CreateCopyDestReceiver();
146 :
147 48802 : case DestSQLFunction:
148 48802 : 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 435658 : 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 435658 : switch (dest)
177 : {
178 394617 : case DestRemote:
179 : case DestRemoteExecute:
180 : case DestRemoteSimple:
181 :
182 394617 : len = BuildQueryCompletionString(completionTag, qc,
183 : force_undecorated_output);
184 394617 : if (noblock)
185 47 : pq_putmessage_noblock(PqMsg_CommandComplete, completionTag, len + 1);
186 : else
187 394570 : pq_putmessage(PqMsg_CommandComplete, completionTag, len + 1);
188 394617 : break;
189 :
190 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:
200 41041 : break;
201 : }
202 435658 : }
203 :
204 : void
205 435611 : EndCommand(const QueryCompletion *qc, CommandDest dest, bool force_undecorated_output)
206 : {
207 435611 : EndCommandExtended(qc, dest, force_undecorated_output, false);
208 435611 : }
209 :
210 : /* ----------------
211 : * EndReplicationCommand - stripped down version of EndCommand
212 : *
213 : * For use by replication commands.
214 : * ----------------
215 : */
216 : void
217 2991 : EndReplicationCommand(const char *commandTag)
218 : {
219 2991 : pq_putmessage(PqMsg_CommandComplete, commandTag, strlen(commandTag) + 1);
220 2991 : }
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 1028 : NullCommand(CommandDest dest)
231 : {
232 1028 : switch (dest)
233 : {
234 1027 : case DestRemote:
235 : case DestRemoteExecute:
236 : case DestRemoteSimple:
237 :
238 : /* Tell the FE that we saw an empty query string */
239 1027 : pq_putemptymessage(PqMsg_EmptyQueryResponse);
240 1027 : 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 1028 : }
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 462695 : ReadyForQuery(CommandDest dest)
269 : {
270 462695 : switch (dest)
271 : {
272 426254 : case DestRemote:
273 : case DestRemoteExecute:
274 : case DestRemoteSimple:
275 : {
276 : StringInfoData buf;
277 :
278 426254 : pq_beginmessage(&buf, PqMsg_ReadyForQuery);
279 426254 : pq_sendbyte(&buf, TransactionBlockStatusCode());
280 426254 : pq_endmessage(&buf);
281 : }
282 : /* Flush output at end of cycle in any case. */
283 426254 : pq_flush();
284 426254 : break;
285 :
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:
296 36441 : break;
297 : }
298 462695 : }
|