1 /*-------------------------------------------------------------------------
4 * support for communication destinations
7 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/tcop/dest.c
13 *-------------------------------------------------------------------------
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
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.
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 #include "utils/portal.h"
46 * dummy DestReceiver functions
50 donothingReceive(TupleTableSlot
*slot
, DestReceiver
*self
)
56 donothingStartup(DestReceiver
*self
, int operation
, TupleDesc typeinfo
)
61 donothingCleanup(DestReceiver
*self
)
63 /* this is used for both shutdown and destroy methods */
67 * static DestReceiver structs for dest types needing no local state
70 static const DestReceiver donothingDR
= {
71 donothingReceive
, donothingStartup
, donothingCleanup
, donothingCleanup
,
75 static const DestReceiver debugtupDR
= {
76 debugtup
, debugStartup
, donothingCleanup
, donothingCleanup
,
80 static const DestReceiver printsimpleDR
= {
81 printsimple
, printsimple_startup
, donothingCleanup
, donothingCleanup
,
85 static const DestReceiver spi_printtupDR
= {
86 spi_printtup
, spi_dest_startup
, donothingCleanup
, donothingCleanup
,
91 * Globally available receiver for DestNone.
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).
96 DestReceiver
*None_Receiver
= (DestReceiver
*) &donothingDR
;
99 * BeginCommand - initialize the destination at start of command
103 BeginCommand(CommandTag commandTag
, CommandDest dest
)
105 /* Nothing to do at present */
109 * CreateDestReceiver - return appropriate receiver function set for dest
113 CreateDestReceiver(CommandDest dest
)
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).
123 case DestRemoteExecute
:
124 return printtup_create_DR(dest
);
126 case DestRemoteSimple
:
127 return unconstify(DestReceiver
*, &printsimpleDR
);
130 return unconstify(DestReceiver
*, &donothingDR
);
133 return unconstify(DestReceiver
*, &debugtupDR
);
136 return unconstify(DestReceiver
*, &spi_printtupDR
);
139 return CreateTuplestoreDestReceiver();
142 return CreateIntoRelDestReceiver(NULL
);
145 return CreateCopyDestReceiver();
147 case DestSQLFunction
:
148 return CreateSQLFunctionDestReceiver();
150 case DestTransientRel
:
151 return CreateTransientRelDestReceiver(InvalidOid
);
154 return CreateTupleQueueDestReceiver(NULL
);
157 /* should never get here */
162 * EndCommand - clean up the destination at end of command
166 EndCommand(const QueryCompletion
*qc
, CommandDest dest
, bool force_undecorated_output
)
168 char completionTag
[COMPLETION_TAG_BUFSIZE
];
175 case DestRemoteExecute
:
176 case DestRemoteSimple
:
179 * We assume the tagname is plain ASCII and therefore requires no
180 * encoding conversion.
182 * We no longer display LastOid, but to preserve the wire
183 * protocol, we write InvalidOid where the LastOid used to be
186 * All cases where LastOid was written also write nprocessed
187 * count, so just Assert that rather than having an extra test.
189 tag
= qc
->commandTag
;
190 tagname
= GetCommandTagName(tag
);
192 if (command_tag_display_rowcount(tag
) && !force_undecorated_output
)
193 snprintf(completionTag
, COMPLETION_TAG_BUFSIZE
,
194 tag
== CMDTAG_INSERT
?
195 "%s 0 " UINT64_FORMAT
: "%s " UINT64_FORMAT
,
196 tagname
, qc
->nprocessed
);
198 snprintf(completionTag
, COMPLETION_TAG_BUFSIZE
, "%s", tagname
);
199 pq_putmessage('C', completionTag
, strlen(completionTag
) + 1);
207 case DestSQLFunction
:
208 case DestTransientRel
:
215 * EndReplicationCommand - stripped down version of EndCommand
217 * For use by replication commands.
221 EndReplicationCommand(const char *commandTag
)
223 pq_putmessage('C', commandTag
, strlen(commandTag
) + 1);
227 * NullCommand - tell dest that an empty query string was recognized
229 * This ensures that there will be a recognizable end to the response
230 * to an Execute message in the extended query protocol.
234 NullCommand(CommandDest dest
)
239 case DestRemoteExecute
:
240 case DestRemoteSimple
:
242 /* Tell the FE that we saw an empty query string */
243 pq_putemptymessage('I');
252 case DestSQLFunction
:
253 case DestTransientRel
:
260 * ReadyForQuery - tell dest that we are ready for a new query
262 * The ReadyForQuery message is sent so that the FE can tell when
263 * we are done processing a query string.
264 * In versions 3.0 and up, it also carries a transaction state indicator.
266 * Note that by flushing the stdio buffer here, we can avoid doing it
267 * most other places and thus reduce the number of separate packets sent.
271 ReadyForQuery(CommandDest dest
)
276 case DestRemoteExecute
:
277 case DestRemoteSimple
:
281 pq_beginmessage(&buf
, 'Z');
282 pq_sendbyte(&buf
, TransactionBlockStatusCode());
285 /* Flush output at end of cycle in any case. */
295 case DestSQLFunction
:
296 case DestTransientRel
: