aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/mmgr/mcxt.c5
-rw-r--r--src/backend/utils/mmgr/portalmem.c116
-rw-r--r--src/backend/utils/sort/logtape.c4
-rw-r--r--src/backend/utils/sort/tuplestore.c32
4 files changed, 124 insertions, 33 deletions
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index 48545b15128..729137a1b92 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/mcxt.c,v 1.38 2002/12/16 16:22:46 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/mcxt.c,v 1.39 2003/03/27 16:51:29 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -36,7 +36,8 @@
MemoryContext CurrentMemoryContext = NULL;
/*
- * Standard top-level contexts
+ * Standard top-level contexts. For a description of the purpose of each
+ * of these contexts, refer to src/backend/utils/mmgr/README
*/
MemoryContext TopMemoryContext = NULL;
MemoryContext ErrorContext = NULL;
diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c
index 66ee72718cf..e6486d4b16d 100644
--- a/src/backend/utils/mmgr/portalmem.c
+++ b/src/backend/utils/mmgr/portalmem.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.53 2003/03/11 19:40:23 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.54 2003/03/27 16:51:29 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,8 +20,8 @@
* "PortalData" structure, plans the query and then stores the query
* in the portal without executing it. Later, when the backend
* sees a
- * fetch 1 from FOO
- * the system looks up the portal named "FOO" in the portal table,
+ * fetch 1 from foo
+ * the system looks up the portal named "foo" in the portal table,
* gets the planned query and then calls the executor with a count
* of 1. The executor then runs the query and returns a single
* tuple. The problem is that we have to hold onto the state of the
@@ -38,7 +38,6 @@
#include "utils/memutils.h"
#include "utils/portal.h"
-
/*
* estimate of the maximum number of open portals a user would have,
* used in initially sizing the PortalHashTable in EnablePortalManager()
@@ -131,8 +130,8 @@ EnablePortalManager(void)
ctl.entrysize = sizeof(PortalHashEnt);
/*
- * use PORTALS_PER_USER, defined in utils/portal.h as a guess of how
- * many hash table entries to create, initially
+ * use PORTALS_PER_USER as a guess of how many hash table entries to
+ * create, initially
*/
PortalHashTable = hash_create("Portal hash", PORTALS_PER_USER,
&ctl, HASH_ELEM);
@@ -157,7 +156,9 @@ GetPortalByName(const char *name)
/*
* PortalSetQuery
- * Attaches a "query" to portal.
+ * Attaches a "query" to the specified portal. Note that in the
+ * case of DECLARE CURSOR, some Portal options have already been
+ * set based upon the parsetree of the original DECLARE statement.
*/
void
PortalSetQuery(Portal portal,
@@ -166,9 +167,25 @@ PortalSetQuery(Portal portal,
{
AssertArg(PortalIsValid(portal));
+ /*
+ * If the user didn't specify a SCROLL type, allow or disallow
+ * scrolling based on whether it would require any additional
+ * runtime overhead to do so.
+ */
+ if (portal->scrollType == DEFAULT_SCROLL)
+ {
+ bool backwardPlan;
+
+ backwardPlan = ExecSupportsBackwardScan(queryDesc->plantree);
+
+ if (backwardPlan)
+ portal->scrollType = ENABLE_SCROLL;
+ else
+ portal->scrollType = DISABLE_SCROLL;
+ }
+
portal->queryDesc = queryDesc;
portal->cleanup = cleanup;
- portal->backwardOK = ExecSupportsBackwardScan(queryDesc->plantree);
portal->atStart = true;
portal->atEnd = false; /* allow fetches */
portal->portalPos = 0;
@@ -179,10 +196,8 @@ PortalSetQuery(Portal portal,
* CreatePortal
* Returns a new portal given a name.
*
- * Exceptions:
- * BadState if called when disabled.
- * BadArg if portal name is invalid.
- * "WARNING" if portal name is in use (existing portal is returned!)
+ * An elog(WARNING) is emitted if portal name is in use (existing
+ * portal is returned!)
*/
Portal
CreatePortal(const char *name)
@@ -214,7 +229,11 @@ CreatePortal(const char *name)
/* initialize portal query */
portal->queryDesc = NULL;
portal->cleanup = NULL;
- portal->backwardOK = false;
+ portal->scrollType = DEFAULT_SCROLL;
+ portal->holdOpen = false;
+ portal->holdStore = NULL;
+ portal->holdContext = NULL;
+ portal->createXact = GetCurrentTransactionId();
portal->atStart = true;
portal->atEnd = true; /* disallow fetches until query is set */
portal->portalPos = 0;
@@ -228,17 +247,47 @@ CreatePortal(const char *name)
/*
* PortalDrop
- * Destroys portal.
+ * Destroy the portal.
*
- * Exceptions:
- * BadState if called when disabled.
- * BadArg if portal is invalid.
+ * keepHoldable: if true, holdable portals should not be removed by
+ * this function. More specifically, invoking this function with
+ * keepHoldable = true on a holdable portal prepares the portal for
+ * access outside of its creating transaction.
*/
void
-PortalDrop(Portal portal)
+PortalDrop(Portal portal, bool persistHoldable)
{
AssertArg(PortalIsValid(portal));
+ if (portal->holdOpen && persistHoldable)
+ {
+ /*
+ * We're "dropping" a holdable portal, but what we really need
+ * to do is prepare the portal for access outside of its
+ * creating transaction.
+ */
+
+ /*
+ * Create the memory context that is used for storage of
+ * long-term (cross transaction) data needed by the holdable
+ * portal.
+ */
+ portal->holdContext =
+ AllocSetContextCreate(PortalMemory,
+ "PortalHeapMemory",
+ ALLOCSET_DEFAULT_MINSIZE,
+ ALLOCSET_DEFAULT_INITSIZE,
+ ALLOCSET_DEFAULT_MAXSIZE);
+
+ /*
+ * Note that PersistHoldablePortal() releases any resources used
+ * by the portal that are local to the creating txn.
+ */
+ PersistHoldablePortal(portal);
+
+ return;
+ }
+
/* remove portal from hash table */
PortalHashTableDelete(portal);
@@ -246,8 +295,20 @@ PortalDrop(Portal portal)
if (PointerIsValid(portal->cleanup))
(*portal->cleanup) (portal);
- /* release subsidiary storage */
- MemoryContextDelete(PortalGetHeapMemory(portal));
+ /*
+ * delete short-term memory context; in the case of a holdable
+ * portal, this has already been done
+ */
+ if (PortalGetHeapMemory(portal))
+ MemoryContextDelete(PortalGetHeapMemory(portal));
+
+ /*
+ * delete long-term memory context; in the case of a non-holdable
+ * portal, this context has never been created, so we don't need to
+ * do anything
+ */
+ if (portal->holdContext)
+ MemoryContextDelete(portal->holdContext);
/* release name and portal data (both are in PortalMemory) */
pfree(portal->name);
@@ -255,7 +316,12 @@ PortalDrop(Portal portal)
}
/*
- * Destroy all portals created in the current transaction (ie, all of them).
+ * Cleanup the portals created in the current transaction. If the
+ * transaction was aborted, all the portals created in this transaction
+ * should be removed. If the transaction was successfully committed, any
+ * holdable cursors created in this transaction need to be kept
+ * open. Only cursors created in the current transaction should be
+ * removed in this fashion.
*
* XXX This assumes that portals can be deleted in a random order, ie,
* no portal has a reference to any other (at least not one that will be
@@ -264,13 +330,17 @@ PortalDrop(Portal portal)
* references...
*/
void
-AtEOXact_portals(void)
+AtEOXact_portals(bool isCommit)
{
HASH_SEQ_STATUS status;
PortalHashEnt *hentry;
+ TransactionId xact = GetCurrentTransactionId();
hash_seq_init(&status, PortalHashTable);
while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
- PortalDrop(hentry->portal);
+ {
+ if (hentry->portal->createXact == xact)
+ PortalDrop(hentry->portal, isCommit);
+ }
}
diff --git a/src/backend/utils/sort/logtape.c b/src/backend/utils/sort/logtape.c
index 1c28028f5f7..643b7a76018 100644
--- a/src/backend/utils/sort/logtape.c
+++ b/src/backend/utils/sort/logtape.c
@@ -64,7 +64,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/sort/logtape.c,v 1.8 2002/06/20 20:29:40 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/sort/logtape.c,v 1.9 2003/03/27 16:51:29 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -470,7 +470,7 @@ LogicalTapeSetCreate(int ntapes)
Assert(ntapes > 0);
lts = (LogicalTapeSet *) palloc(sizeof(LogicalTapeSet) +
(ntapes - 1) *sizeof(LogicalTape *));
- lts->pfile = BufFileCreateTemp();
+ lts->pfile = BufFileCreateTemp(false);
lts->nFileBlocks = 0L;
lts->freeBlocksLen = 32; /* reasonable initial guess */
lts->freeBlocks = (long *) palloc(lts->freeBlocksLen * sizeof(long));
diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c
index 65804d5484d..89970b2495b 100644
--- a/src/backend/utils/sort/tuplestore.c
+++ b/src/backend/utils/sort/tuplestore.c
@@ -36,7 +36,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplestore.c,v 1.11 2003/03/09 02:19:13 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplestore.c,v 1.12 2003/03/27 16:51:29 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -65,6 +65,7 @@ struct Tuplestorestate
{
TupStoreStatus status; /* enumerated value as shown above */
bool randomAccess; /* did caller request random access? */
+ bool interTxn; /* keep open through transactions? */
long availMem; /* remaining memory available, in bytes */
BufFile *myfile; /* underlying file, or NULL if none */
@@ -190,7 +191,8 @@ struct Tuplestorestate
static Tuplestorestate *tuplestore_begin_common(bool randomAccess,
- int maxKBytes);
+ bool interTxn,
+ int maxKBytes);
static void dumptuples(Tuplestorestate *state);
static unsigned int getlen(Tuplestorestate *state, bool eofOK);
static void *copytup_heap(Tuplestorestate *state, void *tup);
@@ -205,7 +207,7 @@ static void *readtup_heap(Tuplestorestate *state, unsigned int len);
*/
static Tuplestorestate *
-tuplestore_begin_common(bool randomAccess, int maxKBytes)
+tuplestore_begin_common(bool randomAccess, bool interTxn, int maxKBytes)
{
Tuplestorestate *state;
@@ -213,6 +215,7 @@ tuplestore_begin_common(bool randomAccess, int maxKBytes)
state->status = TSS_INMEM;
state->randomAccess = randomAccess;
+ state->interTxn = interTxn;
state->availMem = maxKBytes * 1024L;
state->myfile = NULL;
@@ -231,10 +234,27 @@ tuplestore_begin_common(bool randomAccess, int maxKBytes)
return state;
}
+/*
+ * tuplestore_begin_heap
+ *
+ * Create a new tuplestore; other types of tuple stores (other than
+ * "heap" tuple stores, for heap tuples) are possible, but not presently
+ * implemented.
+ *
+ * randomAccess: if true, both forward and backward accesses to the
+ * tuple store are allowed.
+ *
+ * interTxn: if true, the files used by on-disk storage persist beyond
+ * the end of the current transaction.
+ *
+ * maxKBytes: how much data to store in memory (any data beyond this
+ * amount is paged to disk).
+ */
Tuplestorestate *
-tuplestore_begin_heap(bool randomAccess, int maxKBytes)
+tuplestore_begin_heap(bool randomAccess, bool interTxn, int maxKBytes)
{
- Tuplestorestate *state = tuplestore_begin_common(randomAccess, maxKBytes);
+ Tuplestorestate *state = tuplestore_begin_common(randomAccess,
+ interTxn, maxKBytes);
state->copytup = copytup_heap;
state->writetup = writetup_heap;
@@ -321,7 +341,7 @@ tuplestore_puttuple(Tuplestorestate *state, void *tuple)
/*
* Nope; time to switch to tape-based operation.
*/
- state->myfile = BufFileCreateTemp();
+ state->myfile = BufFileCreateTemp(state->interTxn);
state->status = TSS_WRITEFILE;
dumptuples(state);
break;