Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * dest.c
4 : * support for communication destinations
5 : *
6 : *
7 : * Portions Copyright (c) 1996-2024, 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.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 1345248 : donothingReceive(TupleTableSlot *slot, DestReceiver *self)
51 : {
52 1345248 : return true;
53 : }
54 :
55 : static void
56 43494 : donothingStartup(DestReceiver *self, int operation, TupleDesc typeinfo)
57 : {
58 43494 : }
59 :
60 : static void
61 268960 : donothingCleanup(DestReceiver *self)
62 : {
63 : /* this is used for both shutdown and destroy methods */
64 268960 : }
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 665004 : BeginCommand(CommandTag commandTag, CommandDest dest)
104 : {
105 : /* Nothing to do at present */
106 665004 : }
107 :
108 : /* ----------------
109 : * CreateDestReceiver - return appropriate receiver function set for dest
110 : * ----------------
111 : */
112 : DestReceiver *
113 990096 : 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 990096 : switch (dest)
121 : {
122 583818 : case DestRemote:
123 : case DestRemoteExecute:
124 583818 : return printtup_create_DR(dest);
125 :
126 4222 : case DestRemoteSimple:
127 4222 : return unconstify(DestReceiver *, &printsimpleDR);
128 :
129 924 : case DestNone:
130 924 : return unconstify(DestReceiver *, &donothingDR);
131 :
132 68456 : case DestDebug:
133 68456 : return unconstify(DestReceiver *, &debugtupDR);
134 :
135 148018 : case DestSPI:
136 148018 : return unconstify(DestReceiver *, &spi_printtupDR);
137 :
138 49088 : case DestTuplestore:
139 49088 : return CreateTuplestoreDestReceiver();
140 :
141 0 : case DestIntoRel:
142 0 : return CreateIntoRelDestReceiver(NULL);
143 :
144 352 : case DestCopyOut:
145 352 : return CreateCopyDestReceiver();
146 :
147 135218 : case DestSQLFunction:
148 135218 : 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 : void
169 625528 : EndCommand(const QueryCompletion *qc, CommandDest dest, bool force_undecorated_output)
170 : {
171 : char completionTag[COMPLETION_TAG_BUFSIZE];
172 : Size len;
173 :
174 625528 : switch (dest)
175 : {
176 557072 : case DestRemote:
177 : case DestRemoteExecute:
178 : case DestRemoteSimple:
179 :
180 557072 : len = BuildQueryCompletionString(completionTag, qc,
181 : force_undecorated_output);
182 557072 : pq_putmessage(PqMsg_CommandComplete, completionTag, len + 1);
183 :
184 625528 : case DestNone:
185 : case DestDebug:
186 : case DestSPI:
187 : case DestTuplestore:
188 : case DestIntoRel:
189 : case DestCopyOut:
190 : case DestSQLFunction:
191 : case DestTransientRel:
192 : case DestTupleQueue:
193 : case DestExplainSerialize:
194 625528 : break;
195 : }
196 625528 : }
197 :
198 : /* ----------------
199 : * EndReplicationCommand - stripped down version of EndCommand
200 : *
201 : * For use by replication commands.
202 : * ----------------
203 : */
204 : void
205 4978 : EndReplicationCommand(const char *commandTag)
206 : {
207 4978 : pq_putmessage(PqMsg_CommandComplete, commandTag, strlen(commandTag) + 1);
208 4978 : }
209 :
210 : /* ----------------
211 : * NullCommand - tell dest that an empty query string was recognized
212 : *
213 : * This ensures that there will be a recognizable end to the response
214 : * to an Execute message in the extended query protocol.
215 : * ----------------
216 : */
217 : void
218 438 : NullCommand(CommandDest dest)
219 : {
220 438 : switch (dest)
221 : {
222 438 : case DestRemote:
223 : case DestRemoteExecute:
224 : case DestRemoteSimple:
225 :
226 : /* Tell the FE that we saw an empty query string */
227 438 : pq_putemptymessage(PqMsg_EmptyQueryResponse);
228 438 : break;
229 :
230 0 : case DestNone:
231 : case DestDebug:
232 : case DestSPI:
233 : case DestTuplestore:
234 : case DestIntoRel:
235 : case DestCopyOut:
236 : case DestSQLFunction:
237 : case DestTransientRel:
238 : case DestTupleQueue:
239 : case DestExplainSerialize:
240 0 : break;
241 : }
242 438 : }
243 :
244 : /* ----------------
245 : * ReadyForQuery - tell dest that we are ready for a new query
246 : *
247 : * The ReadyForQuery message is sent so that the FE can tell when
248 : * we are done processing a query string.
249 : * In versions 3.0 and up, it also carries a transaction state indicator.
250 : *
251 : * Note that by flushing the stdio buffer here, we can avoid doing it
252 : * most other places and thus reduce the number of separate packets sent.
253 : * ----------------
254 : */
255 : void
256 659816 : ReadyForQuery(CommandDest dest)
257 : {
258 659816 : switch (dest)
259 : {
260 598566 : case DestRemote:
261 : case DestRemoteExecute:
262 : case DestRemoteSimple:
263 : {
264 : StringInfoData buf;
265 :
266 598566 : pq_beginmessage(&buf, PqMsg_ReadyForQuery);
267 598566 : pq_sendbyte(&buf, TransactionBlockStatusCode());
268 598566 : pq_endmessage(&buf);
269 : }
270 : /* Flush output at end of cycle in any case. */
271 598566 : pq_flush();
272 598566 : break;
273 :
274 61250 : case DestNone:
275 : case DestDebug:
276 : case DestSPI:
277 : case DestTuplestore:
278 : case DestIntoRel:
279 : case DestCopyOut:
280 : case DestSQLFunction:
281 : case DestTransientRel:
282 : case DestTupleQueue:
283 : case DestExplainSerialize:
284 61250 : break;
285 : }
286 659816 : }
|