Commit 05bba3d1 authored by Tom Lane's avatar Tom Lane

Be more tense about not creating tuplestores with randomAccess = true unless

backwards scan could actually happen.  In particular, pass a flag to
materialize-mode SRFs that tells them whether they need to require random
access.  In passing, also suppress unneeded backward-scan overhead for a
Portal's holdStore tuplestore.  Per my proposal about reducing I/O costs for
tuplestores.
parent e3e3d2a7
/* /*
* $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 * tablefunc
...@@ -51,7 +51,8 @@ static HTAB *load_categories_hash(char *cats_sql, MemoryContext per_query_ctx); ...@@ -51,7 +51,8 @@ static HTAB *load_categories_hash(char *cats_sql, MemoryContext per_query_ctx);
static Tuplestorestate *get_crosstab_tuplestore(char *sql, static Tuplestorestate *get_crosstab_tuplestore(char *sql,
HTAB *crosstab_hash, HTAB *crosstab_hash,
TupleDesc tupdesc, TupleDesc tupdesc,
MemoryContext per_query_ctx); MemoryContext per_query_ctx,
bool randomAccess);
static void validateConnectbyTupleDesc(TupleDesc tupdesc, bool show_branch, bool show_serial); static void validateConnectbyTupleDesc(TupleDesc tupdesc, bool show_branch, bool show_serial);
static bool compatCrosstabTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2); static bool compatCrosstabTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2);
static bool compatConnectbyTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2); static bool compatConnectbyTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2);
...@@ -66,6 +67,7 @@ static Tuplestorestate *connectby(char *relname, ...@@ -66,6 +67,7 @@ static Tuplestorestate *connectby(char *relname,
bool show_branch, bool show_branch,
bool show_serial, bool show_serial,
MemoryContext per_query_ctx, MemoryContext per_query_ctx,
bool randomAccess,
AttInMetadata *attinmeta); AttInMetadata *attinmeta);
static Tuplestorestate *build_tuplestore_recursively(char *key_fld, static Tuplestorestate *build_tuplestore_recursively(char *key_fld,
char *parent_key_fld, char *parent_key_fld,
...@@ -745,7 +747,8 @@ crosstab_hash(PG_FUNCTION_ARGS) ...@@ -745,7 +747,8 @@ crosstab_hash(PG_FUNCTION_ARGS)
rsinfo->setResult = get_crosstab_tuplestore(sql, rsinfo->setResult = get_crosstab_tuplestore(sql,
crosstab_hash, crosstab_hash,
tupdesc, tupdesc,
per_query_ctx); per_query_ctx,
rsinfo->allowedModes & SFRM_Materialize_Random);
/* /*
* SFRM_Materialize mode expects us to return a NULL Datum. The actual * SFRM_Materialize mode expects us to return a NULL Datum. The actual
...@@ -852,7 +855,8 @@ static Tuplestorestate * ...@@ -852,7 +855,8 @@ static Tuplestorestate *
get_crosstab_tuplestore(char *sql, get_crosstab_tuplestore(char *sql,
HTAB *crosstab_hash, HTAB *crosstab_hash,
TupleDesc tupdesc, TupleDesc tupdesc,
MemoryContext per_query_ctx) MemoryContext per_query_ctx,
bool randomAccess)
{ {
Tuplestorestate *tupstore; Tuplestorestate *tupstore;
int num_categories = hash_get_num_entries(crosstab_hash); int num_categories = hash_get_num_entries(crosstab_hash);
...@@ -863,8 +867,8 @@ get_crosstab_tuplestore(char *sql, ...@@ -863,8 +867,8 @@ get_crosstab_tuplestore(char *sql,
int proc; int proc;
MemoryContext SPIcontext; MemoryContext SPIcontext;
/* initialize our tuplestore */ /* initialize our tuplestore (while still in query context!) */
tupstore = tuplestore_begin_heap(true, false, work_mem); tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
/* Connect to SPI manager */ /* Connect to SPI manager */
if ((ret = SPI_connect()) < 0) if ((ret = SPI_connect()) < 0)
...@@ -1113,6 +1117,7 @@ connectby_text(PG_FUNCTION_ARGS) ...@@ -1113,6 +1117,7 @@ connectby_text(PG_FUNCTION_ARGS)
show_branch, show_branch,
show_serial, show_serial,
per_query_ctx, per_query_ctx,
rsinfo->allowedModes & SFRM_Materialize_Random,
attinmeta); attinmeta);
rsinfo->setDesc = tupdesc; rsinfo->setDesc = tupdesc;
...@@ -1192,6 +1197,7 @@ connectby_text_serial(PG_FUNCTION_ARGS) ...@@ -1192,6 +1197,7 @@ connectby_text_serial(PG_FUNCTION_ARGS)
show_branch, show_branch,
show_serial, show_serial,
per_query_ctx, per_query_ctx,
rsinfo->allowedModes & SFRM_Materialize_Random,
attinmeta); attinmeta);
rsinfo->setDesc = tupdesc; rsinfo->setDesc = tupdesc;
...@@ -1222,6 +1228,7 @@ connectby(char *relname, ...@@ -1222,6 +1228,7 @@ connectby(char *relname,
bool show_branch, bool show_branch,
bool show_serial, bool show_serial,
MemoryContext per_query_ctx, MemoryContext per_query_ctx,
bool randomAccess,
AttInMetadata *attinmeta) AttInMetadata *attinmeta)
{ {
Tuplestorestate *tupstore = NULL; Tuplestorestate *tupstore = NULL;
...@@ -1239,7 +1246,7 @@ connectby(char *relname, ...@@ -1239,7 +1246,7 @@ connectby(char *relname,
oldcontext = MemoryContextSwitchTo(per_query_ctx); oldcontext = MemoryContextSwitchTo(per_query_ctx);
/* initialize our tuplestore */ /* initialize our tuplestore */
tupstore = tuplestore_begin_heap(true, false, work_mem); tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
MemoryContextSwitchTo(oldcontext); 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 * Parser interface for DOM-based parser (libxml) rather than
stream-based SAX-type parser */ stream-based SAX-type parser */
...@@ -688,7 +688,9 @@ xpath_table(PG_FUNCTION_ARGS) ...@@ -688,7 +688,9 @@ xpath_table(PG_FUNCTION_ARGS)
* Create the tuplestore - work_mem is the max in-memory size before a * Create the tuplestore - work_mem is the max in-memory size before a
* file is created on disk to hold it. * 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); MemoryContextSwitchTo(oldcontext);
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Copyright (c) 2002-2008, PostgreSQL Global Development Group * Copyright (c) 2002-2008, PostgreSQL Global Development Group
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -766,7 +766,9 @@ pg_prepared_statement(PG_FUNCTION_ARGS) ...@@ -766,7 +766,9 @@ pg_prepared_statement(PG_FUNCTION_ARGS)
* We put all the tuples into a tuplestore in one scan of the hashtable. * 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. * 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 */ /* hash table might be uninitialized */
if (prepared_queries) if (prepared_queries)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1429,6 +1429,7 @@ restart: ...@@ -1429,6 +1429,7 @@ restart:
rsinfo.econtext = econtext; rsinfo.econtext = econtext;
rsinfo.expectedDesc = fcache->funcResultDesc; rsinfo.expectedDesc = fcache->funcResultDesc;
rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize); rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize);
/* note we do not set SFRM_Materialize_Random */
rsinfo.returnMode = SFRM_ValuePerCall; rsinfo.returnMode = SFRM_ValuePerCall;
/* isDone is filled below */ /* isDone is filled below */
rsinfo.setResult = NULL; rsinfo.setResult = NULL;
...@@ -1702,7 +1703,8 @@ ExecMakeFunctionResultNoSets(FuncExprState *fcache, ...@@ -1702,7 +1703,8 @@ ExecMakeFunctionResultNoSets(FuncExprState *fcache,
Tuplestorestate * Tuplestorestate *
ExecMakeTableFunctionResult(ExprState *funcexpr, ExecMakeTableFunctionResult(ExprState *funcexpr,
ExprContext *econtext, ExprContext *econtext,
TupleDesc expectedDesc) TupleDesc expectedDesc,
bool randomAccess)
{ {
Tuplestorestate *tupstore = NULL; Tuplestorestate *tupstore = NULL;
TupleDesc tupdesc = NULL; TupleDesc tupdesc = NULL;
...@@ -1736,6 +1738,8 @@ ExecMakeTableFunctionResult(ExprState *funcexpr, ...@@ -1736,6 +1738,8 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
rsinfo.econtext = econtext; rsinfo.econtext = econtext;
rsinfo.expectedDesc = expectedDesc; rsinfo.expectedDesc = expectedDesc;
rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize); rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize);
if (randomAccess)
rsinfo.allowedModes |= (int) SFRM_Materialize_Random;
rsinfo.returnMode = SFRM_ValuePerCall; rsinfo.returnMode = SFRM_ValuePerCall;
/* isDone is filled below */ /* isDone is filled below */
rsinfo.setResult = NULL; rsinfo.setResult = NULL;
...@@ -1909,7 +1913,7 @@ ExecMakeTableFunctionResult(ExprState *funcexpr, ...@@ -1909,7 +1913,7 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
-1, -1,
0); 0);
} }
tupstore = tuplestore_begin_heap(true, false, work_mem); tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
rsinfo.setResult = tupstore; rsinfo.setResult = tupstore;
rsinfo.setDesc = tupdesc; rsinfo.setDesc = tupdesc;
...@@ -1976,7 +1980,7 @@ no_function_result: ...@@ -1976,7 +1980,7 @@ no_function_result:
if (rsinfo.setResult == NULL) if (rsinfo.setResult == NULL)
{ {
MemoryContextSwitchTo(econtext->ecxt_per_query_memory); 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; rsinfo.setResult = tupstore;
if (!returnsSet) if (!returnsSet)
{ {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -64,7 +64,8 @@ FunctionNext(FunctionScanState *node) ...@@ -64,7 +64,8 @@ FunctionNext(FunctionScanState *node)
node->tuplestorestate = tuplestorestate = node->tuplestorestate = tuplestorestate =
ExecMakeTableFunctionResult(node->funcexpr, ExecMakeTableFunctionResult(node->funcexpr,
node->ss.ps.ps_ExprContext, node->ss.ps.ps_ExprContext,
node->tupdesc); node->tupdesc,
node->eflags & EXEC_FLAG_BACKWARD);
} }
/* /*
...@@ -123,6 +124,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags) ...@@ -123,6 +124,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
scanstate = makeNode(FunctionScanState); scanstate = makeNode(FunctionScanState);
scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.plan = (Plan *) node;
scanstate->ss.ps.state = estate; scanstate->ss.ps.state = estate;
scanstate->eflags = eflags;
/* /*
* Miscellaneous initialization * 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 Function Manager
================ ================
...@@ -432,6 +432,10 @@ function is called in). The function stores pointers to the Tuplestore and ...@@ -432,6 +432,10 @@ function is called in). The function stores pointers to the Tuplestore and
TupleDesc into ReturnSetInfo, sets returnMode to indicate materialize mode, TupleDesc into ReturnSetInfo, sets returnMode to indicate materialize mode,
and returns null. isDone is not used and should be left at ExprSingleResult. 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; If available, the expected tuple descriptor is passed in ReturnSetInfo;
in other contexts the expectedDesc field will be NULL. The function need 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. not pay attention to expectedDesc, but it may be useful in special cases.
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -354,11 +354,17 @@ PortalCreateHoldStore(Portal portal) ...@@ -354,11 +354,17 @@ PortalCreateHoldStore(Portal portal)
ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE); 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); oldcxt = MemoryContextSwitchTo(portal->holdContext);
/* XXX: Should maintenance_work_mem be used for the portal size? */ portal->holdStore =
portal->holdStore = tuplestore_begin_heap(true, true, work_mem); tuplestore_begin_heap(portal->cursorOptions & CURSOR_OPT_SCROLL,
true, work_mem);
MemoryContextSwitchTo(oldcxt); MemoryContextSwitchTo(oldcxt);
} }
...@@ -913,7 +919,9 @@ pg_cursor(PG_FUNCTION_ARGS) ...@@ -913,7 +919,9 @@ pg_cursor(PG_FUNCTION_ARGS)
* We put all the tuples into a tuplestore in one scan of the hashtable. * 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. * 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); hash_seq_init(&hash_seq, PortalHashTable);
while ((hentry = hash_seq_search(&hash_seq)) != NULL) while ((hentry = hash_seq_search(&hash_seq)) != NULL)
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -178,7 +178,8 @@ extern Datum GetAttributeByName(HeapTupleHeader tuple, const char *attname, ...@@ -178,7 +178,8 @@ extern Datum GetAttributeByName(HeapTupleHeader tuple, const char *attname,
bool *isNull); bool *isNull);
extern Tuplestorestate *ExecMakeTableFunctionResult(ExprState *funcexpr, extern Tuplestorestate *ExecMakeTableFunctionResult(ExprState *funcexpr,
ExprContext *econtext, ExprContext *econtext,
TupleDesc expectedDesc); TupleDesc expectedDesc,
bool randomAccess);
extern Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext, extern Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
extern ExprState *ExecInitExpr(Expr *node, PlanState *parent); extern ExprState *ExecInitExpr(Expr *node, PlanState *parent);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -156,7 +156,8 @@ typedef enum ...@@ -156,7 +156,8 @@ typedef enum
typedef enum typedef enum
{ {
SFRM_ValuePerCall = 0x01, /* one value returned per call */ 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; } SetFunctionReturnMode;
/* /*
...@@ -1180,6 +1181,7 @@ typedef struct SubqueryScanState ...@@ -1180,6 +1181,7 @@ typedef struct SubqueryScanState
* Function nodes are used to scan the results of a * Function nodes are used to scan the results of a
* function appearing in FROM (typically a function returning set). * function appearing in FROM (typically a function returning set).
* *
* eflags node's capability flags
* tupdesc expected return tuple description * tupdesc expected return tuple description
* tuplestorestate private state of tuplestore.c * tuplestorestate private state of tuplestore.c
* funcexpr state for function expression being evaluated * funcexpr state for function expression being evaluated
...@@ -1188,6 +1190,7 @@ typedef struct SubqueryScanState ...@@ -1188,6 +1190,7 @@ typedef struct SubqueryScanState
typedef struct FunctionScanState typedef struct FunctionScanState
{ {
ScanState ss; /* its first field is NodeTag */ ScanState ss; /* its first field is NodeTag */
int eflags;
TupleDesc tupdesc; TupleDesc tupdesc;
Tuplestorestate *tuplestorestate; Tuplestorestate *tuplestorestate;
ExprState *funcexpr; ExprState *funcexpr;
......
/********************************************************************** /**********************************************************************
* plperl.c - perl as a procedural language for PostgreSQL * 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 $
* *
**********************************************************************/ **********************************************************************/
...@@ -1922,7 +1922,8 @@ plperl_return_next(SV *sv) ...@@ -1922,7 +1922,8 @@ plperl_return_next(SV *sv)
current_call_data->ret_tdesc = CreateTupleDescCopy(tupdesc); current_call_data->ret_tdesc = CreateTupleDescCopy(tupdesc);
current_call_data->tuple_store = 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) if (prodesc->fn_retistuple)
{ {
current_call_data->attinmeta = current_call_data->attinmeta =
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2357,7 +2357,9 @@ exec_init_tuple_store(PLpgSQL_execstate *estate) ...@@ -2357,7 +2357,9 @@ exec_init_tuple_store(PLpgSQL_execstate *estate)
estate->tuple_store_cxt = rsi->econtext->ecxt_per_query_memory; estate->tuple_store_cxt = rsi->econtext->ecxt_per_query_memory;
oldcxt = MemoryContextSwitchTo(estate->tuple_store_cxt); 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); MemoryContextSwitchTo(oldcxt);
estate->rettupdesc = rsi->expectedDesc; estate->rettupdesc = rsi->expectedDesc;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment