Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6779c55

Browse files
committed
Clean up BeginCommand and related routines. BeginCommand and EndCommand
are now both invoked once per received SQL command (raw parsetree) from pg_exec_query_string. BeginCommand is actually just an empty routine at the moment --- all its former operations have been pushed into tuple receiver setup routines in printtup.c. This makes for a clean distinction between BeginCommand/EndCommand (once per command) and the tuple receiver setup/teardown routines (once per ExecutorRun call), whereas the old code was quite ad hoc. Along the way, clean up the calling conventions for ExecutorRun a little bit.
1 parent e22c9c4 commit 6779c55

File tree

15 files changed

+266
-361
lines changed

15 files changed

+266
-361
lines changed

src/backend/access/common/printtup.c

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
/*-------------------------------------------------------------------------
22
*
33
* printtup.c
4-
* Routines to print out tuples to the destination (binary or non-binary
5-
* portals, frontend/interactive backend, etc.).
4+
* Routines to print out tuples to the destination (both frontend
5+
* clients and interactive backends are supported here).
6+
*
67
*
78
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
89
* Portions Copyright (c) 1994, Regents of the University of California
910
*
10-
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.60 2001/10/25 05:49:20 momjian Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.61 2002/02/27 19:34:09 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -18,10 +18,12 @@
1818
#include "access/heapam.h"
1919
#include "access/printtup.h"
2020
#include "catalog/pg_type.h"
21+
#include "libpq/libpq.h"
2122
#include "libpq/pqformat.h"
2223
#include "utils/syscache.h"
2324

24-
static void printtup_setup(DestReceiver *self, TupleDesc typeinfo);
25+
static void printtup_setup(DestReceiver *self, int operation,
26+
const char *portalName, TupleDesc typeinfo);
2527
static void printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self);
2628
static void printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self);
2729
static void printtup_cleanup(DestReceiver *self);
@@ -97,17 +99,56 @@ printtup_create_DR(bool isBinary)
9799
}
98100

99101
static void
100-
printtup_setup(DestReceiver *self, TupleDesc typeinfo)
102+
printtup_setup(DestReceiver *self, int operation,
103+
const char *portalName, TupleDesc typeinfo)
101104
{
105+
/*
106+
* Send portal name to frontend.
107+
*
108+
* If portal name not specified, use "blank" portal.
109+
*/
110+
if (portalName == NULL)
111+
portalName = "blank";
112+
113+
pq_puttextmessage('P', portalName);
114+
115+
/*
116+
* if this is a retrieve, then we send back the tuple
117+
* descriptor of the tuples.
118+
*/
119+
if (operation == CMD_SELECT)
120+
{
121+
Form_pg_attribute *attrs = typeinfo->attrs;
122+
int natts = typeinfo->natts;
123+
int i;
124+
StringInfoData buf;
125+
126+
pq_beginmessage(&buf);
127+
pq_sendbyte(&buf, 'T'); /* tuple descriptor message type */
128+
pq_sendint(&buf, natts, 2); /* # of attrs in tuples */
129+
130+
for (i = 0; i < natts; ++i)
131+
{
132+
pq_sendstring(&buf, NameStr(attrs[i]->attname));
133+
pq_sendint(&buf, (int) attrs[i]->atttypid,
134+
sizeof(attrs[i]->atttypid));
135+
pq_sendint(&buf, attrs[i]->attlen,
136+
sizeof(attrs[i]->attlen));
137+
if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
138+
pq_sendint(&buf, attrs[i]->atttypmod,
139+
sizeof(attrs[i]->atttypmod));
140+
}
141+
pq_endmessage(&buf);
142+
}
143+
102144
/* ----------------
103145
* We could set up the derived attr info at this time, but we postpone it
104-
* until the first call of printtup, for 3 reasons:
146+
* until the first call of printtup, for 2 reasons:
105147
* 1. We don't waste time (compared to the old way) if there are no
106148
* tuples at all to output.
107149
* 2. Checking in printtup allows us to handle the case that the tuples
108150
* change type midway through (although this probably can't happen in
109151
* the current executor).
110-
* 3. Right now, ExecutorRun passes a NULL for typeinfo anyway :-(
111152
* ----------------
112153
*/
113154
}
@@ -267,12 +308,12 @@ printatt(unsigned attributeId,
267308
* showatts
268309
* ----------------
269310
*/
270-
void
271-
showatts(char *name, TupleDesc tupleDesc)
311+
static void
312+
showatts(const char *name, TupleDesc tupleDesc)
272313
{
273-
int i;
274314
int natts = tupleDesc->natts;
275315
Form_pg_attribute *attinfo = tupleDesc->attrs;
316+
int i;
276317

277318
puts(name);
278319
for (i = 0; i < natts; ++i)
@@ -281,7 +322,24 @@ showatts(char *name, TupleDesc tupleDesc)
281322
}
282323

283324
/* ----------------
284-
* debugtup
325+
* debugSetup - prepare to print tuples for an interactive backend
326+
* ----------------
327+
*/
328+
void
329+
debugSetup(DestReceiver *self, int operation,
330+
const char *portalName, TupleDesc typeinfo)
331+
{
332+
/*
333+
* show the return type of the tuples
334+
*/
335+
if (portalName == NULL)
336+
portalName = "blank";
337+
338+
showatts(portalName, typeinfo);
339+
}
340+
341+
/* ----------------
342+
* debugtup - print one tuple for an interactive backend
285343
* ----------------
286344
*/
287345
void

src/backend/access/common/tupdesc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.76 2001/10/25 05:49:20 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.77 2002/02/27 19:34:11 tgl Exp $
1212
*
1313
* NOTES
1414
* some of the executor utility code such as "ExecTypeFromTL" should be
@@ -432,7 +432,7 @@ TupleDescInitEntry(TupleDesc desc,
432432
*
433433
* (Why not just make the atttypid point to the OID type, instead of the
434434
* type the query returns? Because the executor uses the atttypid to
435-
* tell the front end what type will be returned (in BeginCommand),
435+
* tell the front end what type will be returned,
436436
* and in the end the type returned will be the result of the query,
437437
* not an OID.)
438438
*

src/backend/commands/command.c

Lines changed: 35 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.155 2002/02/26 22:47:04 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.156 2002/02/27 19:34:38 tgl Exp $
1212
*
1313
* NOTES
1414
* The PerformAddAttribute() code, like most of the relation
@@ -113,6 +113,7 @@ PerformPortalFetch(char *name,
113113
QueryDesc *queryDesc;
114114
EState *estate;
115115
MemoryContext oldcontext;
116+
ScanDirection direction;
116117
CommandId savedId;
117118
bool temp_desc = false;
118119

@@ -145,6 +146,9 @@ PerformPortalFetch(char *name,
145146
*/
146147
oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
147148

149+
queryDesc = PortalGetQueryDesc(portal);
150+
estate = PortalGetState(portal);
151+
148152
/*
149153
* If the requested destination is not the same as the query's
150154
* original destination, make a temporary QueryDesc with the proper
@@ -156,9 +160,6 @@ PerformPortalFetch(char *name,
156160
* original dest. This is necessary since a FETCH command will pass
157161
* dest = Remote, not knowing whether the cursor is binary or not.
158162
*/
159-
queryDesc = PortalGetQueryDesc(portal);
160-
estate = PortalGetState(portal);
161-
162163
if (dest != queryDesc->dest &&
163164
!(queryDesc->dest == RemoteInternal && dest == Remote))
164165
{
@@ -170,19 +171,6 @@ PerformPortalFetch(char *name,
170171
temp_desc = true;
171172
}
172173

173-
/*
174-
* Tell the destination to prepare to receive some tuples.
175-
*/
176-
BeginCommand(name,
177-
queryDesc->operation,
178-
PortalGetTupleDesc(portal),
179-
false, /* portal fetches don't end up in
180-
* relations */
181-
false, /* this is a portal fetch, not a "retrieve
182-
* portal" */
183-
NULL, /* not used */
184-
queryDesc->dest);
185-
186174
/*
187175
* Restore the scanCommandId that was current when the cursor was
188176
* opened. This ensures that we see the same tuples throughout the
@@ -194,47 +182,49 @@ PerformPortalFetch(char *name,
194182
/*
195183
* Determine which direction to go in, and check to see if we're
196184
* already at the end of the available tuples in that direction. If
197-
* so, do nothing. (This check exists because not all plan node types
185+
* so, set the direction to NoMovement to avoid trying to fetch any
186+
* tuples. (This check exists because not all plan node types
198187
* are robust about being called again if they've already returned
199-
* NULL once.) If it's OK to do the fetch, call the executor. Then,
200-
* update the atStart/atEnd state depending on the number of tuples
201-
* that were retrieved.
188+
* NULL once.) Then call the executor (we must not skip this, because
189+
* the destination needs to see a setup and shutdown even if no tuples
190+
* are available). Finally, update the atStart/atEnd state depending
191+
* on the number of tuples that were retrieved.
202192
*/
203193
if (forward)
204194
{
205-
if (!portal->atEnd)
206-
{
207-
ExecutorRun(queryDesc, estate, EXEC_FOR, (long) count);
195+
if (portal->atEnd)
196+
direction = NoMovementScanDirection;
197+
else
198+
direction = ForwardScanDirection;
208199

209-
if (estate->es_processed > 0)
210-
portal->atStart = false; /* OK to back up now */
211-
if (count <= 0 || (int) estate->es_processed < count)
212-
portal->atEnd = true; /* we retrieved 'em all */
200+
ExecutorRun(queryDesc, estate, direction, (long) count);
213201

214-
if (completionTag)
215-
snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "%s %u",
216-
(dest == None) ? "MOVE" : "FETCH",
217-
estate->es_processed);
218-
}
202+
if (estate->es_processed > 0)
203+
portal->atStart = false; /* OK to back up now */
204+
if (count <= 0 || (int) estate->es_processed < count)
205+
portal->atEnd = true; /* we retrieved 'em all */
219206
}
220207
else
221208
{
222-
if (!portal->atStart)
223-
{
224-
ExecutorRun(queryDesc, estate, EXEC_BACK, (long) count);
209+
if (portal->atStart)
210+
direction = NoMovementScanDirection;
211+
else
212+
direction = BackwardScanDirection;
225213

226-
if (estate->es_processed > 0)
227-
portal->atEnd = false; /* OK to go forward now */
228-
if (count <= 0 || (int) estate->es_processed < count)
229-
portal->atStart = true; /* we retrieved 'em all */
214+
ExecutorRun(queryDesc, estate, direction, (long) count);
230215

231-
if (completionTag)
232-
snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "%s %u",
233-
(dest == None) ? "MOVE" : "FETCH",
234-
estate->es_processed);
235-
}
216+
if (estate->es_processed > 0)
217+
portal->atEnd = false; /* OK to go forward now */
218+
if (count <= 0 || (int) estate->es_processed < count)
219+
portal->atStart = true; /* we retrieved 'em all */
236220
}
237221

222+
/* Return command status if wanted */
223+
if (completionTag)
224+
snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "%s %u",
225+
(dest == None) ? "MOVE" : "FETCH",
226+
estate->es_processed);
227+
238228
/*
239229
* Restore outer command ID.
240230
*/

0 commit comments

Comments
 (0)