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/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 :
43 :
44 : /* ----------------
45 : * dummy DestReceiver functions
46 : * ----------------
47 : */
48 : static bool
49 1320436 : donothingReceive(TupleTableSlot *slot, DestReceiver *self)
50 : {
51 1320436 : return true;
52 : }
53 :
54 : static void
55 43410 : donothingStartup(DestReceiver *self, int operation, TupleDesc typeinfo)
56 : {
57 43410 : }
58 :
59 : static void
60 232754 : donothingCleanup(DestReceiver *self)
61 : {
62 : /* this is used for both shutdown and destroy methods */
63 232754 : }
64 :
65 : /* ----------------
66 : * static DestReceiver structs for dest types needing no local state
67 : * ----------------
68 : */
69 : static const DestReceiver donothingDR = {
70 : donothingReceive, donothingStartup, donothingCleanup, donothingCleanup,
71 : DestNone
72 : };
73 :
74 : static const DestReceiver debugtupDR = {
75 : debugtup, debugStartup, donothingCleanup, donothingCleanup,
76 : DestDebug
77 : };
78 :
79 : static const DestReceiver printsimpleDR = {
80 : printsimple, printsimple_startup, donothingCleanup, donothingCleanup,
81 : DestRemoteSimple
82 : };
83 :
84 : static const DestReceiver spi_printtupDR = {
85 : spi_printtup, spi_dest_startup, donothingCleanup, donothingCleanup,
86 : DestSPI
87 : };
88 :
89 : /*
90 : * Globally available receiver for DestNone.
91 : *
92 : * It's ok to cast the constness away as any modification of the none receiver
93 : * would be a bug (which gets easier to catch this way).
94 : */
95 : DestReceiver *None_Receiver = (DestReceiver *) &donothingDR;
96 :
97 : /* ----------------
98 : * BeginCommand - initialize the destination at start of command
99 : * ----------------
100 : */
101 : void
102 631946 : BeginCommand(CommandTag commandTag, CommandDest dest)
103 : {
104 : /* Nothing to do at present */
105 631946 : }
106 :
107 : /* ----------------
108 : * CreateDestReceiver - return appropriate receiver function set for dest
109 : * ----------------
110 : */
111 : DestReceiver *
112 930158 : CreateDestReceiver(CommandDest dest)
113 : {
114 : /*
115 : * It's ok to cast the constness away as any modification of the none
116 : * receiver would be a bug (which gets easier to catch this way).
117 : */
118 :
119 930158 : switch (dest)
120 : {
121 559500 : case DestRemote:
122 : case DestRemoteExecute:
123 559500 : return printtup_create_DR(dest);
124 :
125 3908 : case DestRemoteSimple:
126 3908 : return unconstify(DestReceiver *, &printsimpleDR);
127 :
128 834 : case DestNone:
129 834 : return unconstify(DestReceiver *, &donothingDR);
130 :
131 60192 : case DestDebug:
132 60192 : return unconstify(DestReceiver *, &debugtupDR);
133 :
134 129546 : case DestSPI:
135 129546 : return unconstify(DestReceiver *, &spi_printtupDR);
136 :
137 45146 : case DestTuplestore:
138 45146 : return CreateTuplestoreDestReceiver();
139 :
140 0 : case DestIntoRel:
141 0 : return CreateIntoRelDestReceiver(NULL);
142 :
143 322 : case DestCopyOut:
144 322 : return CreateCopyDestReceiver();
145 :
146 130710 : case DestSQLFunction:
147 130710 : return CreateSQLFunctionDestReceiver();
148 :
149 0 : case DestTransientRel:
150 0 : return CreateTransientRelDestReceiver(InvalidOid);
151 :
152 0 : case DestTupleQueue:
153 0 : return CreateTupleQueueDestReceiver(NULL);
154 : }
155 :
156 : /* should never get here */
157 0 : pg_unreachable();
158 : }
159 :
160 : /* ----------------
161 : * EndCommand - clean up the destination at end of command
162 : * ----------------
163 : */
164 : void
165 594052 : EndCommand(const QueryCompletion *qc, CommandDest dest, bool force_undecorated_output)
166 : {
167 : char completionTag[COMPLETION_TAG_BUFSIZE];
168 : Size len;
169 :
170 594052 : switch (dest)
171 : {
172 533860 : case DestRemote:
173 : case DestRemoteExecute:
174 : case DestRemoteSimple:
175 :
176 533860 : len = BuildQueryCompletionString(completionTag, qc,
177 : force_undecorated_output);
178 533860 : pq_putmessage(PqMsg_CommandComplete, completionTag, len + 1);
179 :
180 594052 : case DestNone:
181 : case DestDebug:
182 : case DestSPI:
183 : case DestTuplestore:
184 : case DestIntoRel:
185 : case DestCopyOut:
186 : case DestSQLFunction:
187 : case DestTransientRel:
188 : case DestTupleQueue:
189 594052 : break;
190 : }
191 594052 : }
192 :
193 : /* ----------------
194 : * EndReplicationCommand - stripped down version of EndCommand
195 : *
196 : * For use by replication commands.
197 : * ----------------
198 : */
199 : void
200 4656 : EndReplicationCommand(const char *commandTag)
201 : {
202 4656 : pq_putmessage(PqMsg_CommandComplete, commandTag, strlen(commandTag) + 1);
203 4656 : }
204 :
205 : /* ----------------
206 : * NullCommand - tell dest that an empty query string was recognized
207 : *
208 : * This ensures that there will be a recognizable end to the response
209 : * to an Execute message in the extended query protocol.
210 : * ----------------
211 : */
212 : void
213 428 : NullCommand(CommandDest dest)
214 : {
215 428 : switch (dest)
216 : {
217 428 : case DestRemote:
218 : case DestRemoteExecute:
219 : case DestRemoteSimple:
220 :
221 : /* Tell the FE that we saw an empty query string */
222 428 : pq_putemptymessage(PqMsg_EmptyQueryResponse);
223 428 : break;
224 :
225 0 : 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 0 : break;
235 : }
236 428 : }
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 : */
249 : void
250 622816 : ReadyForQuery(CommandDest dest)
251 : {
252 622816 : switch (dest)
253 : {
254 568990 : case DestRemote:
255 : case DestRemoteExecute:
256 : case DestRemoteSimple:
257 : {
258 : StringInfoData buf;
259 :
260 568990 : pq_beginmessage(&buf, PqMsg_ReadyForQuery);
261 568990 : pq_sendbyte(&buf, TransactionBlockStatusCode());
262 568990 : pq_endmessage(&buf);
263 : }
264 : /* Flush output at end of cycle in any case. */
265 568990 : pq_flush();
266 568990 : break;
267 :
268 53826 : case DestNone:
269 : case DestDebug:
270 : case DestSPI:
271 : case DestTuplestore:
272 : case DestIntoRel:
273 : case DestCopyOut:
274 : case DestSQLFunction:
275 : case DestTransientRel:
276 : case DestTupleQueue:
277 53826 : break;
278 : }
279 622816 : }
|