/*
- * $PostgreSQL: pgsql/contrib/tablefunc/tablefunc.c,v 1.54 2008/10/28 22:02:05 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/tablefunc/tablefunc.c,v 1.55 2008/10/29 00:00:38 tgl Exp $
*
*
* tablefunc
static Tuplestorestate *get_crosstab_tuplestore(char *sql,
HTAB *crosstab_hash,
TupleDesc tupdesc,
- MemoryContext per_query_ctx);
+ MemoryContext per_query_ctx,
+ bool randomAccess);
static void validateConnectbyTupleDesc(TupleDesc tupdesc, bool show_branch, bool show_serial);
static bool compatCrosstabTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2);
static bool compatConnectbyTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2);
bool show_branch,
bool show_serial,
MemoryContext per_query_ctx,
+ bool randomAccess,
AttInMetadata *attinmeta);
static Tuplestorestate *build_tuplestore_recursively(char *key_fld,
char *parent_key_fld,
rsinfo->setResult = get_crosstab_tuplestore(sql,
crosstab_hash,
tupdesc,
- per_query_ctx);
+ per_query_ctx,
+ rsinfo->allowedModes & SFRM_Materialize_Random);
/*
* SFRM_Materialize mode expects us to return a NULL Datum. The actual
get_crosstab_tuplestore(char *sql,
HTAB *crosstab_hash,
TupleDesc tupdesc,
- MemoryContext per_query_ctx)
+ MemoryContext per_query_ctx,
+ bool randomAccess)
{
Tuplestorestate *tupstore;
int num_categories = hash_get_num_entries(crosstab_hash);
int proc;
MemoryContext SPIcontext;
- /* initialize our tuplestore */
- tupstore = tuplestore_begin_heap(true, false, work_mem);
+ /* initialize our tuplestore (while still in query context!) */
+ tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
/* Connect to SPI manager */
if ((ret = SPI_connect()) < 0)
show_branch,
show_serial,
per_query_ctx,
+ rsinfo->allowedModes & SFRM_Materialize_Random,
attinmeta);
rsinfo->setDesc = tupdesc;
show_branch,
show_serial,
per_query_ctx,
+ rsinfo->allowedModes & SFRM_Materialize_Random,
attinmeta);
rsinfo->setDesc = tupdesc;
bool show_branch,
bool show_serial,
MemoryContext per_query_ctx,
+ bool randomAccess,
AttInMetadata *attinmeta)
{
Tuplestorestate *tupstore = NULL;
oldcontext = MemoryContextSwitchTo(per_query_ctx);
/* initialize our tuplestore */
- tupstore = tuplestore_begin_heap(true, false, work_mem);
+ tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
MemoryContextSwitchTo(oldcontext);
/*
- * $PostgreSQL: pgsql/contrib/xml2/xpath.c,v 1.20 2008/05/17 01:28:22 adunstan Exp $
+ * $PostgreSQL: pgsql/contrib/xml2/xpath.c,v 1.21 2008/10/29 00:00:38 tgl Exp $
*
* Parser interface for DOM-based parser (libxml) rather than
stream-based SAX-type parser */
* Create the tuplestore - work_mem is the max in-memory size before a
* file is created on disk to hold it.
*/
- tupstore = tuplestore_begin_heap(true, false, work_mem);
+ tupstore =
+ tuplestore_begin_heap(rsinfo->allowedModes & SFRM_Materialize_Random,
+ false, work_mem);
MemoryContextSwitchTo(oldcontext);
* Copyright (c) 2002-2008, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.91 2008/08/28 23:09:45 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.92 2008/10/29 00:00:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* 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);
+ tupstore =
+ tuplestore_begin_heap(rsinfo->allowedModes & SFRM_Materialize_Random,
+ false, work_mem);
/* hash table might be uninitialized */
if (prepared_queries)
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.234 2008/10/28 22:02:05 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.235 2008/10/29 00:00:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
rsinfo.econtext = econtext;
rsinfo.expectedDesc = fcache->funcResultDesc;
rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize);
+ /* note we do not set SFRM_Materialize_Random */
rsinfo.returnMode = SFRM_ValuePerCall;
/* isDone is filled below */
rsinfo.setResult = NULL;
Tuplestorestate *
ExecMakeTableFunctionResult(ExprState *funcexpr,
ExprContext *econtext,
- TupleDesc expectedDesc)
+ TupleDesc expectedDesc,
+ bool randomAccess)
{
Tuplestorestate *tupstore = NULL;
TupleDesc tupdesc = NULL;
rsinfo.econtext = econtext;
rsinfo.expectedDesc = expectedDesc;
rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize);
+ if (randomAccess)
+ rsinfo.allowedModes |= (int) SFRM_Materialize_Random;
rsinfo.returnMode = SFRM_ValuePerCall;
/* isDone is filled below */
rsinfo.setResult = NULL;
-1,
0);
}
- tupstore = tuplestore_begin_heap(true, false, work_mem);
+ tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
MemoryContextSwitchTo(oldcontext);
rsinfo.setResult = tupstore;
rsinfo.setDesc = tupdesc;
if (rsinfo.setResult == NULL)
{
MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
- tupstore = tuplestore_begin_heap(true, false, work_mem);
+ tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
rsinfo.setResult = tupstore;
if (!returnsSet)
{
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.48 2008/10/28 22:02:05 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.49 2008/10/29 00:00:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
node->tuplestorestate = tuplestorestate =
ExecMakeTableFunctionResult(node->funcexpr,
node->ss.ps.ps_ExprContext,
- node->tupdesc);
+ node->tupdesc,
+ node->eflags & EXEC_FLAG_BACKWARD);
}
/*
scanstate = makeNode(FunctionScanState);
scanstate->ss.ps.plan = (Plan *) node;
scanstate->ss.ps.state = estate;
+ scanstate->eflags = eflags;
/*
* Miscellaneous initialization
-$PostgreSQL: pgsql/src/backend/utils/fmgr/README,v 1.14 2008/10/28 22:02:05 tgl Exp $
+$PostgreSQL: pgsql/src/backend/utils/fmgr/README,v 1.15 2008/10/29 00:00:38 tgl Exp $
Function Manager
================
TupleDesc into ReturnSetInfo, sets returnMode to indicate materialize mode,
and returns null. isDone is not used and should be left at ExprSingleResult.
+The Tuplestore must be created with randomAccess = true if
+SFRM_Materialize_Random is set in allowedModes, but it can (and preferably
+should) be created with randomAccess = false if not.
+
If available, the expected tuple descriptor is passed in ReturnSetInfo;
in other contexts the expectedDesc field will be NULL. The function need
not pay attention to expectedDesc, but it may be useful in special cases.
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.111 2008/07/18 20:26:06 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.112 2008/10/29 00:00:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
- /* Create the tuple store, selecting cross-transaction temp files. */
+ /*
+ * Create the tuple store, selecting cross-transaction temp files, and
+ * enabling random access only if cursor requires scrolling.
+ *
+ * XXX: Should maintenance_work_mem be used for the portal size?
+ */
oldcxt = MemoryContextSwitchTo(portal->holdContext);
- /* XXX: Should maintenance_work_mem be used for the portal size? */
- portal->holdStore = tuplestore_begin_heap(true, true, work_mem);
+ portal->holdStore =
+ tuplestore_begin_heap(portal->cursorOptions & CURSOR_OPT_SCROLL,
+ true, work_mem);
MemoryContextSwitchTo(oldcxt);
}
* 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);
+ tupstore =
+ tuplestore_begin_heap(rsinfo->allowedModes & SFRM_Materialize_Random,
+ false, work_mem);
hash_seq_init(&hash_seq, PortalHashTable);
while ((hentry = hash_seq_search(&hash_seq)) != NULL)
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.150 2008/10/28 22:02:05 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.151 2008/10/29 00:00:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
bool *isNull);
extern Tuplestorestate *ExecMakeTableFunctionResult(ExprState *funcexpr,
ExprContext *econtext,
- TupleDesc expectedDesc);
+ TupleDesc expectedDesc,
+ bool randomAccess);
extern Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
extern ExprState *ExecInitExpr(Expr *node, PlanState *parent);
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.192 2008/10/28 22:02:05 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.193 2008/10/29 00:00:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
typedef enum
{
SFRM_ValuePerCall = 0x01, /* one value returned per call */
- SFRM_Materialize = 0x02 /* result set instantiated in Tuplestore */
+ SFRM_Materialize = 0x02, /* result set instantiated in Tuplestore */
+ SFRM_Materialize_Random = 0x04 /* Tuplestore needs randomAccess */
} SetFunctionReturnMode;
/*
* Function nodes are used to scan the results of a
* function appearing in FROM (typically a function returning set).
*
+ * eflags node's capability flags
* tupdesc expected return tuple description
* tuplestorestate private state of tuplestore.c
* funcexpr state for function expression being evaluated
typedef struct FunctionScanState
{
ScanState ss; /* its first field is NodeTag */
+ int eflags;
TupleDesc tupdesc;
Tuplestorestate *tuplestorestate;
ExprState *funcexpr;
/**********************************************************************
* plperl.c - perl as a procedural language for PostgreSQL
*
- * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.140 2008/10/09 17:24:05 alvherre Exp $
+ * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.141 2008/10/29 00:00:39 tgl Exp $
*
**********************************************************************/
current_call_data->ret_tdesc = CreateTupleDescCopy(tupdesc);
current_call_data->tuple_store =
- tuplestore_begin_heap(true, false, work_mem);
+ tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
+ false, work_mem);
if (prodesc->fn_retistuple)
{
current_call_data->attinmeta =
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.221 2008/09/24 14:40:00 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.222 2008/10/29 00:00:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
estate->tuple_store_cxt = rsi->econtext->ecxt_per_query_memory;
oldcxt = MemoryContextSwitchTo(estate->tuple_store_cxt);
- estate->tuple_store = tuplestore_begin_heap(true, false, work_mem);
+ estate->tuple_store =
+ tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
+ false, work_mem);
MemoryContextSwitchTo(oldcxt);
estate->rettupdesc = rsi->expectedDesc;