1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

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.
This commit is contained in:
Tom Lane
2003-05-06 20:26:28 +00:00
parent 299fbb4b37
commit 79913910d4
28 changed files with 698 additions and 349 deletions

View File

@ -1,6 +1,6 @@
/*-------------------------------------------------------------------------
*
* tstore_receiver.c
* tstoreReceiver.c
* an implementation of DestReceiver that stores the result tuples in
* a Tuplestore
*
@ -9,7 +9,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/tstoreReceiver.c,v 1.4 2003/05/06 00:20:31 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/tstoreReceiver.c,v 1.5 2003/05/06 20:26:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -17,8 +17,7 @@
#include "postgres.h"
#include "executor/tstoreReceiver.h"
#include "utils/memutils.h"
#include "utils/portal.h"
typedef struct
{
@ -30,32 +29,13 @@ typedef struct
/*
* Prepare to receive tuples from executor.
*
* XXX: As currently implemented, this routine is a hack: there should
* be no tie between this code and the portal system. Instead, the
* receiver function that is part of DestFunction should be passed a
* QueryDesc, so that the call site of ExecutorRun can "sub-class"
* QueryDesc and pass in any necessary addition information (in this
* case, the Tuplestore to use).
*/
static void
tstoreSetupReceiver(DestReceiver *self, int operation,
const char *portalname,
TupleDesc typeinfo, List *targetlist)
tstoreStartupReceiver(DestReceiver *self, int operation,
const char *portalname,
TupleDesc typeinfo, List *targetlist)
{
TStoreState *myState = (TStoreState *) self;
/* Should only be called within a suitably-prepped portal */
if (CurrentPortal == NULL ||
CurrentPortal->holdStore == NULL)
elog(ERROR, "Tuplestore destination used in wrong context");
/* Debug check: make sure portal's result tuple desc is correct */
Assert(CurrentPortal->tupDesc != NULL);
Assert(equalTupleDescs(CurrentPortal->tupDesc, typeinfo));
myState->tstore = CurrentPortal->holdStore;
myState->cxt = CurrentPortal->holdContext;
/* do nothing */
}
/*
@ -73,28 +53,40 @@ tstoreReceiveTuple(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
}
/*
* Clean up
* Clean up at end of an executor run
*/
static void
tstoreCleanupReceiver(DestReceiver *self)
tstoreShutdownReceiver(DestReceiver *self)
{
/* do nothing */
}
/*
* Destroy receiver when done with it
*/
static void
tstoreDestroyReceiver(DestReceiver *self)
{
pfree(self);
}
/*
* Initially create a DestReceiver object.
*/
DestReceiver *
tstoreReceiverCreateDR(void)
CreateTuplestoreDestReceiver(Tuplestorestate *tStore,
MemoryContext tContext)
{
TStoreState *self = (TStoreState *) palloc(sizeof(TStoreState));
self->pub.receiveTuple = tstoreReceiveTuple;
self->pub.setup = tstoreSetupReceiver;
self->pub.cleanup = tstoreCleanupReceiver;
self->pub.startup = tstoreStartupReceiver;
self->pub.shutdown = tstoreShutdownReceiver;
self->pub.destroy = tstoreDestroyReceiver;
self->pub.mydest = Tuplestore;
self->tstore = NULL;
self->cxt = NULL;
self->tstore = tStore;
self->cxt = tContext;
return (DestReceiver *) self;
}