1 /*-------------------------------------------------------------------------
4 * support for various communication destinations - see lib/H/tcop/dest.h
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/tcop/dest.c,v 1.18 1998/05/06 23:49:59 momjian Exp $
12 *-------------------------------------------------------------------------
16 * BeginCommand - prepare destination for tuples of the given type
17 * EndCommand - tell destination that no more tuples will arrive
18 * NullCommand - tell dest that an empty query string was recognized
19 * ReadyForQuery - tell dest that we are ready for a new query
22 * These routines do the appropriate work before and after
23 * tuples are returned by a query to keep the backend and the
24 * "destination" portals synchronized.
27 #include <stdio.h> /* for sprintf() */
32 #include "access/htup.h"
33 #include "libpq/libpq.h"
34 #include "access/printtup.h"
35 #include "utils/portal.h"
36 #include "utils/palloc.h"
38 #include "executor/executor.h"
40 #include "tcop/dest.h"
42 #include "catalog/pg_type.h"
43 #include "utils/mcxt.h"
45 #include "commands/async.h"
47 static char CommandInfo[32] = {0};
54 donothing(HeapTuple tuple, TupleDesc attrdesc)
58 extern void spi_printtup(HeapTuple tuple, TupleDesc tupdesc);
61 DestToFunction(CommandDest dest)) (HeapTuple, TupleDesc)
66 return printtup_internal;
92 * never gets here, but DECstation lint appears to be stupid...
99 * EndCommand - tell destination that no more tuples will arrive
103 EndCommand(char *commandTag, CommandDest dest)
112 * tell the fe that the query is over
116 sprintf(buf, "%s%s", commandTag, CommandInfo);
130 * These are necessary to sync communications between fe/be processes doing
135 * COPY rel FROM stdin
137 * NOTE: the message code letters are changed at protocol version 2.0
138 * to eliminate possible confusion with data tuple messages.
143 if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
144 pq_putnchar("H", 1); /* new way */
146 pq_putnchar("B", 1); /* old way */
150 ReceiveCopyBegin(void)
152 if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
153 pq_putnchar("G", 1); /* new way */
155 pq_putnchar("D", 1); /* old way */
156 /* We *must* flush here to ensure FE knows it can send. */
161 * NullCommand - tell dest that an empty query string was recognized
163 * In FE/BE protocol version 1.0, this hack is necessary to support
164 * libpq's crufty way of determining whether a multiple-command
165 * query string is done. In protocol 2.0 it's probably not really
166 * necessary to distinguish empty queries anymore, but we still do it
167 * for backwards compatibility with 1.0.
171 NullCommand(CommandDest dest)
179 * tell the fe that we saw an empty query string
195 * ReadyForQuery - tell dest that we are ready for a new query
197 * The ReadyForQuery message is sent in protocol versions 2.0 and up
198 * so that the FE can tell when we are done processing a query string.
200 * Note that by flushing the stdio buffer here, we can avoid doing it
201 * most other places and thus reduce the number of separate packets sent.
205 ReadyForQuery(CommandDest dest)
212 if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
214 /* Flush output at end of cycle in any case. */
228 * BeginCommand - prepare destination for tuples of the given type
232 BeginCommand(char *pname,
241 AttributeTupleForm *attrs = tupdesc->attrs;
242 int natts = tupdesc->natts;
251 * if this is a "retrieve portal" query, just return
252 * because nothing needs to be sent to the fe.
260 * if portal name not specified for remote query,
261 * use the "blank" portal.
268 * send fe info on tuples we're about to send
271 pq_putnchar("P", 1);/* new portal.. */
272 pq_putstr(pname); /* portal name */
275 * if this is a retrieve, then we send back the tuple
276 * descriptor of the tuples. "retrieve into" is an
277 * exception because no tuples are returned in that case.
280 if (operation == CMD_SELECT && !isIntoRel)
282 pq_putnchar("T", 1); /* type info to follow.. */
283 pq_putint(natts, 2); /* number of attributes in tuples */
285 for (i = 0; i < natts; ++i)
287 pq_putstr(attrs[i]->attname.data); /* if 16 char name
289 pq_putint((int) attrs[i]->atttypid, sizeof(attrs[i]->atttypid));
290 pq_putint(attrs[i]->attlen, sizeof(attrs[i]->attlen));
297 * prepare local portal buffer for query results
298 * and setup result for PQexec()
301 entry = be_currentportal();
303 pbuf_setportalinfo(entry, pname);
305 if (operation == CMD_SELECT && !isIntoRel)
307 be_typeinit(entry, tupdesc, natts);
308 p = (char *) palloc(strlen(entry->name) + 2);
310 strcpy(p + 1, entry->name);
314 p = (char *) palloc(strlen(tag) + 2);
323 * show the return type of the tuples
329 showatts(pname, tupdesc);
339 UpdateCommandInfo(int operation, Oid lastoid, uint32 tuples)
345 lastoid = InvalidOid;
346 sprintf(CommandInfo, " %u %u", lastoid, tuples);
350 sprintf(CommandInfo, " %u", tuples);