aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/mmgr/portalmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/mmgr/portalmem.c')
-rw-r--r--src/backend/utils/mmgr/portalmem.c141
1 files changed, 71 insertions, 70 deletions
diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c
index 4f8cba9ba5a..3e3505caf05 100644
--- a/src/backend/utils/mmgr/portalmem.c
+++ b/src/backend/utils/mmgr/portalmem.c
@@ -12,7 +12,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.97 2006/11/23 01:14:59 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.97.2.1 2007/04/26 23:24:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,7 +22,6 @@
#include "access/xact.h"
#include "catalog/pg_type.h"
#include "commands/portalcmds.h"
-#include "funcapi.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
@@ -577,7 +576,9 @@ AtCommit_Portals(void)
/* Zap all non-holdable portals */
PortalDrop(portal, true);
- /* Restart the iteration */
+ /* Restart the iteration in case that led to other drops */
+ /* XXX is this really necessary? */
+ hash_seq_term(&status);
hash_seq_init(&status, PortalHashTable);
}
}
@@ -806,79 +807,68 @@ AtSubCleanup_Portals(SubTransactionId mySubid)
Datum
pg_cursor(PG_FUNCTION_ARGS)
{
- FuncCallContext *funcctx;
- HASH_SEQ_STATUS *hash_seq;
+ ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+ TupleDesc tupdesc;
+ Tuplestorestate *tupstore;
+ MemoryContext per_query_ctx;
+ MemoryContext oldcontext;
+ HASH_SEQ_STATUS hash_seq;
PortalHashEnt *hentry;
- /* stuff done only on the first call of the function */
- if (SRF_IS_FIRSTCALL())
- {
- MemoryContext oldcontext;
- TupleDesc tupdesc;
-
- /* create a function context for cross-call persistence */
- funcctx = SRF_FIRSTCALL_INIT();
-
- /*
- * switch to memory context appropriate for multiple function calls
- */
- oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
-
- if (PortalHashTable)
- {
- hash_seq = (HASH_SEQ_STATUS *) palloc(sizeof(HASH_SEQ_STATUS));
- hash_seq_init(hash_seq, PortalHashTable);
- funcctx->user_fctx = (void *) hash_seq;
- }
- else
- funcctx->user_fctx = NULL;
-
- /*
- * build tupdesc for result tuples. This must match the definition of
- * the pg_cursors view in system_views.sql
- */
- tupdesc = CreateTemplateTupleDesc(6, false);
- TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
- TEXTOID, -1, 0);
- TupleDescInitEntry(tupdesc, (AttrNumber) 2, "statement",
- TEXTOID, -1, 0);
- TupleDescInitEntry(tupdesc, (AttrNumber) 3, "is_holdable",
- BOOLOID, -1, 0);
- TupleDescInitEntry(tupdesc, (AttrNumber) 4, "is_binary",
- BOOLOID, -1, 0);
- TupleDescInitEntry(tupdesc, (AttrNumber) 5, "is_scrollable",
- BOOLOID, -1, 0);
- TupleDescInitEntry(tupdesc, (AttrNumber) 6, "creation_time",
- TIMESTAMPTZOID, -1, 0);
-
- funcctx->tuple_desc = BlessTupleDesc(tupdesc);
- MemoryContextSwitchTo(oldcontext);
- }
-
- /* stuff done on every call of the function */
- funcctx = SRF_PERCALL_SETUP();
- hash_seq = (HASH_SEQ_STATUS *) funcctx->user_fctx;
+ /* check to see if caller supports us returning a tuplestore */
+ if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("set-valued function called in context that cannot accept a set")));
+ if (!(rsinfo->allowedModes & SFRM_Materialize))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("materialize mode required, but it is not " \
+ "allowed in this context")));
+
+ /* need to build tuplestore in query context */
+ per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
+ oldcontext = MemoryContextSwitchTo(per_query_ctx);
- /* if the hash table is uninitialized, we're done */
- if (hash_seq == NULL)
- SRF_RETURN_DONE(funcctx);
+ /*
+ * build tupdesc for result tuples. This must match the definition of
+ * the pg_cursors view in system_views.sql
+ */
+ tupdesc = CreateTemplateTupleDesc(6, false);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
+ TEXTOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 2, "statement",
+ TEXTOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 3, "is_holdable",
+ BOOLOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 4, "is_binary",
+ BOOLOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 5, "is_scrollable",
+ BOOLOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 6, "creation_time",
+ TIMESTAMPTZOID, -1, 0);
- /* loop until we find a visible portal or hit the end of the list */
- while ((hentry = hash_seq_search(hash_seq)) != NULL)
- {
- if (hentry->portal->visible)
- break;
- }
+ /*
+ * We put all the tuples into a tuplestore in one scan of the hashtable.
+ * This avoids any issue of the hashtable possibly changing between calls.
+ */
+ tupstore = tuplestore_begin_heap(true, false, work_mem);
- if (hentry)
+ hash_seq_init(&hash_seq, PortalHashTable);
+ while ((hentry = hash_seq_search(&hash_seq)) != NULL)
{
- Portal portal;
- Datum result;
+ Portal portal = hentry->portal;
HeapTuple tuple;
Datum values[6];
bool nulls[6];
- portal = hentry->portal;
+ /* report only "visible" entries */
+ if (!portal->visible)
+ continue;
+
+ /* generate junk in short-term context */
+ MemoryContextSwitchTo(oldcontext);
+
MemSet(nulls, 0, sizeof(nulls));
values[0] = DirectFunctionCall1(textin, CStringGetDatum(portal->name));
@@ -892,10 +882,21 @@ pg_cursor(PG_FUNCTION_ARGS)
values[4] = BoolGetDatum(portal->cursorOptions & CURSOR_OPT_SCROLL);
values[5] = TimestampTzGetDatum(portal->creation_time);
- tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
- result = HeapTupleGetDatum(tuple);
- SRF_RETURN_NEXT(funcctx, result);
+ tuple = heap_form_tuple(tupdesc, values, nulls);
+
+ /* switch to appropriate context while storing the tuple */
+ MemoryContextSwitchTo(per_query_ctx);
+ tuplestore_puttuple(tupstore, tuple);
}
- SRF_RETURN_DONE(funcctx);
+ /* clean up and return the tuplestore */
+ tuplestore_donestoring(tupstore);
+
+ MemoryContextSwitchTo(oldcontext);
+
+ rsinfo->returnMode = SFRM_Materialize;
+ rsinfo->setResult = tupstore;
+ rsinfo->setDesc = tupdesc;
+
+ return (Datum) 0;
}