Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 7991391

Browse files
committed
Restructure command destination handling so that we pass around
DestReceiver pointers instead of just CommandDest values. The DestReceiver is made at the point where the destination is selected, rather than deep inside the executor. This cleans up the original kluge implementation of tstoreReceiver.c, and makes it easy to support retrieving results from utility statements inside portals. Thus, you can now do fun things like Bind and Execute a FETCH or EXPLAIN command, and it'll all work as expected (e.g., you can Describe the portal, or use Execute's count parameter to suspend the output partway through). Implementation involves stuffing the utility command's output into a Tuplestore, which would be kind of annoying for huge output sets, but should be quite acceptable for typical uses of utility commands.
1 parent 299fbb4 commit 7991391

28 files changed

+698
-349
lines changed

src/backend/access/common/printtup.c

+56-15
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
*
33
* printtup.c
44
* Routines to print out tuples to the destination (both frontend
5-
* clients and interactive backends are supported here).
5+
* clients and standalone backends are supported here).
66
*
77
*
88
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.69 2003/05/06 00:20:31 tgl Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.70 2003/05/06 20:26:26 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -22,11 +22,13 @@
2222
#include "utils/lsyscache.h"
2323

2424

25-
static void printtup_setup(DestReceiver *self, int operation,
25+
static void printtup_startup(DestReceiver *self, int operation,
2626
const char *portalName, TupleDesc typeinfo, List *targetlist);
2727
static void printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self);
2828
static void printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self);
29-
static void printtup_cleanup(DestReceiver *self);
29+
static void printtup_shutdown(DestReceiver *self);
30+
static void printtup_destroy(DestReceiver *self);
31+
3032

3133
/* ----------------------------------------------------------------
3234
* printtup / debugtup support
@@ -59,13 +61,41 @@ typedef struct
5961
* ----------------
6062
*/
6163
DestReceiver *
62-
printtup_create_DR(bool isBinary, bool sendDescrip)
64+
printtup_create_DR(CommandDest dest)
6365
{
6466
DR_printtup *self = (DR_printtup *) palloc(sizeof(DR_printtup));
67+
bool isBinary;
68+
bool sendDescrip;
69+
70+
switch (dest)
71+
{
72+
case Remote:
73+
isBinary = false;
74+
sendDescrip = true;
75+
break;
76+
case RemoteInternal:
77+
isBinary = true;
78+
sendDescrip = true;
79+
break;
80+
case RemoteExecute:
81+
isBinary = false;
82+
sendDescrip = false; /* no T message for Execute */
83+
break;
84+
case RemoteExecuteInternal:
85+
isBinary = true;
86+
sendDescrip = false; /* no T message for Execute */
87+
break;
88+
89+
default:
90+
elog(ERROR, "printtup_create_DR: unsupported dest");
91+
return NULL;
92+
}
6593

6694
self->pub.receiveTuple = isBinary ? printtup_internal : printtup;
67-
self->pub.setup = printtup_setup;
68-
self->pub.cleanup = printtup_cleanup;
95+
self->pub.startup = printtup_startup;
96+
self->pub.shutdown = printtup_shutdown;
97+
self->pub.destroy = printtup_destroy;
98+
self->pub.mydest = dest;
6999

70100
self->sendDescrip = sendDescrip;
71101

@@ -77,8 +107,8 @@ printtup_create_DR(bool isBinary, bool sendDescrip)
77107
}
78108

79109
static void
80-
printtup_setup(DestReceiver *self, int operation,
81-
const char *portalName, TupleDesc typeinfo, List *targetlist)
110+
printtup_startup(DestReceiver *self, int operation,
111+
const char *portalName, TupleDesc typeinfo, List *targetlist)
82112
{
83113
DR_printtup *myState = (DR_printtup *) self;
84114

@@ -288,17 +318,28 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
288318
}
289319

290320
/* ----------------
291-
* printtup_cleanup
321+
* printtup_shutdown
292322
* ----------------
293323
*/
294324
static void
295-
printtup_cleanup(DestReceiver *self)
325+
printtup_shutdown(DestReceiver *self)
296326
{
297327
DR_printtup *myState = (DR_printtup *) self;
298328

299329
if (myState->myinfo)
300330
pfree(myState->myinfo);
301-
pfree(myState);
331+
myState->myinfo = NULL;
332+
myState->attrinfo = NULL;
333+
}
334+
335+
/* ----------------
336+
* printtup_destroy
337+
* ----------------
338+
*/
339+
static void
340+
printtup_destroy(DestReceiver *self)
341+
{
342+
pfree(self);
302343
}
303344

304345
/* ----------------
@@ -340,12 +381,12 @@ showatts(const char *name, TupleDesc tupleDesc)
340381
}
341382

342383
/* ----------------
343-
* debugSetup - prepare to print tuples for an interactive backend
384+
* debugStartup - prepare to print tuples for an interactive backend
344385
* ----------------
345386
*/
346387
void
347-
debugSetup(DestReceiver *self, int operation,
348-
const char *portalName, TupleDesc typeinfo, List *targetlist)
388+
debugStartup(DestReceiver *self, int operation,
389+
const char *portalName, TupleDesc typeinfo, List *targetlist)
349390
{
350391
/*
351392
* show the return type of the tuples

src/backend/commands/explain.c

+20-10
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994-5, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.107 2003/05/06 00:20:31 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.108 2003/05/06 20:26:26 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -67,21 +67,15 @@ static Node *make_ors_ands_explicit(List *orclauses);
6767
* execute an EXPLAIN command
6868
*/
6969
void
70-
ExplainQuery(ExplainStmt *stmt, CommandDest dest)
70+
ExplainQuery(ExplainStmt *stmt, DestReceiver *dest)
7171
{
7272
Query *query = stmt->query;
7373
TupOutputState *tstate;
74-
TupleDesc tupdesc;
7574
List *rewritten;
7675
List *l;
7776

78-
/* need a tuple descriptor representing a single TEXT column */
79-
tupdesc = CreateTemplateTupleDesc(1, false);
80-
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
81-
TEXTOID, -1, 0, false);
82-
8377
/* prepare for projection of tuples */
84-
tstate = begin_tup_output_tupdesc(dest, tupdesc);
78+
tstate = begin_tup_output_tupdesc(dest, ExplainResultDesc(stmt));
8579

8680
if (query->commandType == CMD_UTILITY)
8781
{
@@ -119,6 +113,22 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest)
119113
end_tup_output(tstate);
120114
}
121115

116+
/*
117+
* ExplainResultDesc -
118+
* construct the result tupledesc for an EXPLAIN
119+
*/
120+
TupleDesc
121+
ExplainResultDesc(ExplainStmt *stmt)
122+
{
123+
TupleDesc tupdesc;
124+
125+
/* need a tuple descriptor representing a single TEXT column */
126+
tupdesc = CreateTemplateTupleDesc(1, false);
127+
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
128+
TEXTOID, -1, 0, false);
129+
return tupdesc;
130+
}
131+
122132
/*
123133
* ExplainOneQuery -
124134
* print out the execution plan for one query
@@ -169,7 +179,7 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
169179
plan = planner(query, isCursor, cursorOptions);
170180

171181
/* Create a QueryDesc requesting no output */
172-
queryDesc = CreateQueryDesc(query, plan, None, NULL, NULL,
182+
queryDesc = CreateQueryDesc(query, plan, None_Receiver, NULL, NULL,
173183
stmt->analyze);
174184

175185
ExplainOnePlan(queryDesc, stmt, tstate);

src/backend/commands/portalcmds.c

+28-41
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
*
1515
*
1616
* IDENTIFICATION
17-
* $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.14 2003/05/05 00:44:55 tgl Exp $
17+
* $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.15 2003/05/06 20:26:26 tgl Exp $
1818
*
1919
*-------------------------------------------------------------------------
2020
*/
@@ -23,9 +23,9 @@
2323

2424
#include <limits.h>
2525

26-
#include "miscadmin.h"
2726
#include "commands/portalcmds.h"
2827
#include "executor/executor.h"
28+
#include "executor/tstoreReceiver.h"
2929
#include "optimizer/planner.h"
3030
#include "rewrite/rewriteHandler.h"
3131
#include "tcop/pquery.h"
@@ -37,7 +37,7 @@
3737
* Execute SQL DECLARE CURSOR command.
3838
*/
3939
void
40-
PerformCursorOpen(DeclareCursorStmt *stmt, CommandDest dest)
40+
PerformCursorOpen(DeclareCursorStmt *stmt)
4141
{
4242
List *rewritten;
4343
Query *query;
@@ -142,9 +142,10 @@ PerformCursorOpen(DeclareCursorStmt *stmt, CommandDest dest)
142142
*/
143143
void
144144
PerformPortalFetch(FetchStmt *stmt,
145-
CommandDest dest,
145+
DestReceiver *dest,
146146
char *completionTag)
147147
{
148+
DestReceiver *mydest = dest;
148149
Portal portal;
149150
long nprocessed;
150151

@@ -168,29 +169,34 @@ PerformPortalFetch(FetchStmt *stmt,
168169
}
169170

170171
/*
171-
* Adjust dest if needed. MOVE wants dest = None.
172+
* Adjust dest if needed. MOVE wants destination None.
172173
*
173174
* If fetching from a binary cursor and the requested destination is
174175
* Remote, change it to RemoteInternal. Note we do NOT change if the
175176
* destination is RemoteExecute --- so the Execute message's format
176177
* specification wins out over the cursor's type.
177178
*/
178179
if (stmt->ismove)
179-
dest = None;
180-
else if (dest == Remote && (portal->cursorOptions & CURSOR_OPT_BINARY))
181-
dest = RemoteInternal;
180+
mydest = CreateDestReceiver(None);
181+
else if (dest->mydest == Remote &&
182+
(portal->cursorOptions & CURSOR_OPT_BINARY))
183+
mydest = CreateDestReceiver(RemoteInternal);
182184

183185
/* Do it */
184186
nprocessed = PortalRunFetch(portal,
185187
stmt->direction,
186188
stmt->howMany,
187-
dest);
189+
mydest);
188190

189191
/* Return command status if wanted */
190192
if (completionTag)
191193
snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "%s %ld",
192194
stmt->ismove ? "MOVE" : "FETCH",
193195
nprocessed);
196+
197+
/* Clean up if we created a local destination */
198+
if (mydest != dest)
199+
(mydest->destroy) (mydest);
194200
}
195201

196202
/*
@@ -243,21 +249,6 @@ PortalCleanup(Portal portal, bool isError)
243249
AssertArg(PortalIsValid(portal));
244250
AssertArg(portal->cleanup == PortalCleanup);
245251

246-
/*
247-
* Delete tuplestore if present. (Note: portalmem.c is responsible
248-
* for removing holdContext.) We should do this even under error
249-
* conditions; since the tuplestore would have been using cross-
250-
* transaction storage, its temp files need to be explicitly deleted.
251-
*/
252-
if (portal->holdStore)
253-
{
254-
MemoryContext oldcontext;
255-
256-
oldcontext = MemoryContextSwitchTo(portal->holdContext);
257-
tuplestore_end(portal->holdStore);
258-
MemoryContextSwitchTo(oldcontext);
259-
portal->holdStore = NULL;
260-
}
261252
/*
262253
* Shut down executor, if still running. We skip this during error
263254
* abort, since other mechanisms will take care of releasing executor
@@ -284,7 +275,6 @@ void
284275
PersistHoldablePortal(Portal portal)
285276
{
286277
QueryDesc *queryDesc = PortalGetQueryDesc(portal);
287-
Portal saveCurrentPortal;
288278
MemoryContext savePortalContext;
289279
MemoryContext saveQueryContext;
290280
MemoryContext oldcxt;
@@ -294,26 +284,22 @@ PersistHoldablePortal(Portal portal)
294284
* inside the transaction that originally created it.
295285
*/
296286
Assert(portal->createXact == GetCurrentTransactionId());
297-
Assert(portal->holdStore == NULL);
298287
Assert(queryDesc != NULL);
299288
Assert(portal->portalReady);
300289
Assert(!portal->portalDone);
301290

302291
/*
303-
* This context is used to store the tuple set.
304-
* Caller must have created it already.
292+
* Caller must have created the tuplestore already.
305293
*/
306294
Assert(portal->holdContext != NULL);
307-
oldcxt = MemoryContextSwitchTo(portal->holdContext);
308-
309-
/* XXX: Should SortMem be used for this? */
310-
portal->holdStore = tuplestore_begin_heap(true, true, SortMem);
295+
Assert(portal->holdStore != NULL);
311296

312297
/*
313-
* Before closing down the executor, we must copy the tupdesc, since
314-
* it was created in executor memory. Note we are copying it into
315-
* the holdContext.
298+
* Before closing down the executor, we must copy the tupdesc into
299+
* long-term memory, since it was created in executor memory.
316300
*/
301+
oldcxt = MemoryContextSwitchTo(portal->holdContext);
302+
317303
portal->tupDesc = CreateTupleDescCopy(portal->tupDesc);
318304

319305
MemoryContextSwitchTo(oldcxt);
@@ -326,10 +312,8 @@ PersistHoldablePortal(Portal portal)
326312
portal->portalActive = true;
327313

328314
/*
329-
* Set global portal and context pointers.
315+
* Set global portal context pointers.
330316
*/
331-
saveCurrentPortal = CurrentPortal;
332-
CurrentPortal = portal;
333317
savePortalContext = PortalContext;
334318
PortalContext = PortalGetHeapMemory(portal);
335319
saveQueryContext = QueryContext;
@@ -344,12 +328,16 @@ PersistHoldablePortal(Portal portal)
344328
*/
345329
ExecutorRewind(queryDesc);
346330

347-
/* Set the destination to output to the tuplestore */
348-
queryDesc->dest = Tuplestore;
331+
/* Change the destination to output to the tuplestore */
332+
queryDesc->dest = CreateTuplestoreDestReceiver(portal->holdStore,
333+
portal->holdContext);
349334

350335
/* Fetch the result set into the tuplestore */
351336
ExecutorRun(queryDesc, ForwardScanDirection, 0L);
352337

338+
(*queryDesc->dest->destroy) (queryDesc->dest);
339+
queryDesc->dest = NULL;
340+
353341
/*
354342
* Now shut down the inner executor.
355343
*/
@@ -359,7 +347,6 @@ PersistHoldablePortal(Portal portal)
359347
/* Mark portal not active */
360348
portal->portalActive = false;
361349

362-
CurrentPortal = saveCurrentPortal;
363350
PortalContext = savePortalContext;
364351
QueryContext = saveQueryContext;
365352

0 commit comments

Comments
 (0)