diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index 02a00b15a7..e456fdb619 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.80.2.3 2007/04/26 23:24:56 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.80.2.4 2010/07/28 04:51:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -79,7 +79,6 @@ ExecHashSubPlan(SubPlanState *node, { SubPlan *subplan = (SubPlan *) node->xprstate.expr; PlanState *planstate = node->planstate; - ExprContext *innerecontext = node->innerecontext; TupleTableSlot *slot; /* Shouldn't have any direct correlation Vars */ @@ -116,12 +115,6 @@ ExecHashSubPlan(SubPlanState *node, * it still needs to free the tuple. */ - /* - * Since the hashtable routines will use innerecontext's per-tuple memory - * as working memory, be sure to reset it for each tuple. - */ - ResetExprContext(innerecontext); - /* * If the LHS is all non-null, probe for an exact match in the main hash * table. If we find one, the result is TRUE. Otherwise, scan the @@ -419,7 +412,6 @@ buildSubPlanHash(SubPlanState *node) PlanState *planstate = node->planstate; int ncols = list_length(subplan->paramIds); ExprContext *innerecontext = node->innerecontext; - MemoryContext tempcxt = innerecontext->ecxt_per_tuple_memory; MemoryContext oldcontext; int nbuckets; TupleTableSlot *slot; @@ -441,7 +433,7 @@ buildSubPlanHash(SubPlanState *node) * If it's not necessary to distinguish FALSE and UNKNOWN, then we don't * need to store subplan output rows that contain NULL. */ - MemoryContextReset(node->tablecxt); + MemoryContextReset(node->hashtablecxt); node->hashtable = NULL; node->hashnulls = NULL; node->havehashrows = false; @@ -457,8 +449,8 @@ buildSubPlanHash(SubPlanState *node) node->hashfunctions, nbuckets, sizeof(TupleHashEntryData), - node->tablecxt, - tempcxt); + node->hashtablecxt, + node->hashtempcxt); if (!subplan->unknownEqFalse) { @@ -476,8 +468,8 @@ buildSubPlanHash(SubPlanState *node) node->hashfunctions, nbuckets, sizeof(TupleHashEntryData), - node->tablecxt, - tempcxt); + node->hashtablecxt, + node->hashtempcxt); } /* @@ -536,7 +528,7 @@ buildSubPlanHash(SubPlanState *node) /* * Reset innerecontext after each inner tuple to free any memory used - * in hash computation or comparison routines. + * during ExecProject. */ ResetExprContext(innerecontext); } @@ -654,7 +646,8 @@ ExecInitSubPlan(SubPlanState *node, EState *estate, int eflags) node->projRight = NULL; node->hashtable = NULL; node->hashnulls = NULL; - node->tablecxt = NULL; + node->hashtablecxt = NULL; + node->hashtempcxt = NULL; node->innerecontext = NULL; node->keyColIdx = NULL; node->eqfunctions = NULL; @@ -735,12 +728,19 @@ ExecInitSubPlan(SubPlanState *node, EState *estate, int eflags) ListCell *l; /* We need a memory context to hold the hash table(s) */ - node->tablecxt = + node->hashtablecxt = AllocSetContextCreate(CurrentMemoryContext, "Subplan HashTable Context", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + /* and a small one for the hash tables to use as temp storage */ + node->hashtempcxt = + AllocSetContextCreate(CurrentMemoryContext, + "Subplan HashTable Temp Context", + ALLOCSET_SMALL_MINSIZE, + ALLOCSET_SMALL_INITSIZE, + ALLOCSET_SMALL_MAXSIZE); /* and a short-lived exprcontext for function evaluation */ node->innerecontext = CreateExprContext(estate); /* Silly little array of column numbers 1..n */ diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index e981a6a933..84bf53f956 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.161.2.2 2007/04/26 23:24:57 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.161.2.3 2010/07/28 04:51:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -589,8 +589,9 @@ typedef struct SubPlanState TupleHashTable hashnulls; /* hash table for rows with null(s) */ bool havehashrows; /* TRUE if hashtable is not empty */ bool havenullrows; /* TRUE if hashnulls is not empty */ - MemoryContext tablecxt; /* memory context containing tables */ - ExprContext *innerecontext; /* working context for comparisons */ + MemoryContext hashtablecxt; /* memory context containing hash tables */ + MemoryContext hashtempcxt; /* temp memory context for hash tables */ + ExprContext *innerecontext; /* econtext for computing inner tuples */ AttrNumber *keyColIdx; /* control data for hash tables */ FmgrInfo *eqfunctions; /* comparison functions for hash tables */ FmgrInfo *hashfunctions; /* lookup data for hash functions */ diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out index 339b46f297..7dd2db728b 100644 --- a/src/test/regress/expected/subselect.out +++ b/src/test/regress/expected/subselect.out @@ -449,3 +449,12 @@ from ----- (0 rows) +-- +-- Test case for premature memory release during hashing of subplan output +-- +select '1'::text in (select '1'::name union all select '1'::name); + ?column? +---------- + t +(1 row) + diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql index 46b46b4c45..257ff9a6a5 100644 --- a/src/test/regress/sql/subselect.sql +++ b/src/test/regress/sql/subselect.sql @@ -289,3 +289,9 @@ from from int8_tbl) sq0 join int4_tbl i4 on dummy = i4.f1; + +-- +-- Test case for premature memory release during hashing of subplan output +-- + +select '1'::text in (select '1'::name union all select '1'::name);