diff options
Diffstat (limited to 'src/backend/utils')
-rw-r--r-- | src/backend/utils/mmgr/mcxt.c | 5 | ||||
-rw-r--r-- | src/backend/utils/mmgr/portalmem.c | 116 | ||||
-rw-r--r-- | src/backend/utils/sort/logtape.c | 4 | ||||
-rw-r--r-- | src/backend/utils/sort/tuplestore.c | 32 |
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; |