1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-15 03:41:20 +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

@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.122 2003/05/02 22:02:47 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.123 2003/05/06 20:26:27 tgl Exp $
*
*--------------------------------------------------------------------
*/
@@ -2438,12 +2438,41 @@ set_config_by_name(PG_FUNCTION_ARGS)
* SHOW command
*/
void
GetPGVariable(const char *name)
GetPGVariable(const char *name, DestReceiver *dest)
{
if (strcasecmp(name, "all") == 0)
ShowAllGUCConfig();
ShowAllGUCConfig(dest);
else
ShowGUCConfigOption(name);
ShowGUCConfigOption(name, dest);
}
TupleDesc
GetPGVariableResultDesc(const char *name)
{
TupleDesc tupdesc;
if (strcasecmp(name, "all") == 0)
{
/* need a tuple descriptor representing two TEXT columns */
tupdesc = CreateTemplateTupleDesc(2, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
TEXTOID, -1, 0, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
TEXTOID, -1, 0, false);
}
else
{
const char *varname;
/* Get the canonical spelling of name */
(void) GetConfigOptionByName(name, &varname);
/* need a tuple descriptor representing a single TEXT column */
tupdesc = CreateTemplateTupleDesc(1, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, (char *) varname,
TEXTOID, -1, 0, false);
}
return tupdesc;
}
/*
@@ -2468,11 +2497,10 @@ ResetPGVariable(const char *name)
* SHOW command
*/
void
ShowGUCConfigOption(const char *name)
ShowGUCConfigOption(const char *name, DestReceiver *dest)
{
TupOutputState *tstate;
TupleDesc tupdesc;
CommandDest dest = whereToSendOutput;
const char *varname;
char *value;
@@ -2497,12 +2525,11 @@ ShowGUCConfigOption(const char *name)
* SHOW ALL command
*/
void
ShowAllGUCConfig(void)
ShowAllGUCConfig(DestReceiver *dest)
{
int i;
TupOutputState *tstate;
TupleDesc tupdesc;
CommandDest dest = whereToSendOutput;
char *values[2];
/* need a tuple descriptor representing two TEXT columns */

View File

@@ -12,12 +12,13 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.57 2003/05/05 00:44:56 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.58 2003/05/06 20:26:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "miscadmin.h"
#include "commands/portalcmds.h"
#include "executor/executor.h"
#include "utils/hsearch.h"
@@ -36,9 +37,6 @@
* ----------------
*/
Portal CurrentPortal = NULL; /* globally visible pointer */
#define MAX_PORTALNAME_LEN NAMEDATALEN
typedef struct portalhashent
@@ -251,6 +249,38 @@ PortalDefineQuery(Portal portal,
portal->queryContext = queryContext;
}
/*
* PortalCreateHoldStore
* Create the tuplestore for a portal.
*/
void
PortalCreateHoldStore(Portal portal)
{
MemoryContext oldcxt;
Assert(portal->holdContext == NULL);
Assert(portal->holdStore == NULL);
/*
* Create the memory context that is used for storage of the tuple set.
* Note this is NOT a child of the portal's heap memory.
*/
portal->holdContext =
AllocSetContextCreate(PortalMemory,
"PortalHeapMemory",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
/* Create the tuple store, selecting cross-transaction temp files. */
oldcxt = MemoryContextSwitchTo(portal->holdContext);
/* XXX: Should SortMem be used for this? */
portal->holdStore = tuplestore_begin_heap(true, true, SortMem);
MemoryContextSwitchTo(oldcxt);
}
/*
* PortalDrop
* Destroy the portal.
@@ -279,6 +309,21 @@ PortalDrop(Portal portal, bool isError)
if (PointerIsValid(portal->cleanup))
(*portal->cleanup) (portal, isError);
/*
* Delete tuplestore if present. We should do this even under error
* conditions; since the tuplestore would have been using cross-
* transaction storage, its temp files need to be explicitly deleted.
*/
if (portal->holdStore)
{
MemoryContext oldcontext;
oldcontext = MemoryContextSwitchTo(portal->holdContext);
tuplestore_end(portal->holdStore);
MemoryContextSwitchTo(oldcontext);
portal->holdStore = NULL;
}
/* delete tuplestore storage, if any */
if (portal->holdContext)
MemoryContextDelete(portal->holdContext);
@@ -360,27 +405,12 @@ AtCommit_Portals(void)
* We are exiting the transaction that created a holdable
* cursor. Instead of dropping the portal, prepare it for
* access by later transactions.
*/
/*
* Create the memory context that is used for storage of
* the held cursor's tuple set. Note this is NOT a child
* of the portal's heap memory.
*/
portal->holdContext =
AllocSetContextCreate(PortalMemory,
"PortalHeapMemory",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
/*
* Transfer data into the held tuplestore.
*
* Note that PersistHoldablePortal() must release all
* resources used by the portal that are local to the creating
* transaction.
*/
PortalCreateHoldStore(portal);
PersistHoldablePortal(portal);
}
else