From 133924e13e004db8979424bf5436e21b0a09a069 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 28 Jul 2010 04:50:50 +0000 Subject: Fix potential failure when hashing the output of a subplan that produces a pass-by-reference datatype with a nontrivial projection step. We were using the same memory context for the projection operation as for the temporary context used by the hashtable routines in execGrouping.c. However, the hashtable routines feel free to reset their temp context at any time, which'd lead to destroying input data that was still needed. Report and diagnosis by Tao Ma. Back-patch to 8.1, where the problem was introduced by the changes that allowed us to work with "virtual" tuples instead of materializing intermediate tuple values everywhere. The earlier code looks quite similar, but it doesn't suffer the problem because the data gets copied into another context as a result of having to materialize ExecProject's output tuple. --- src/backend/executor/nodeSubplan.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'src/backend/executor/nodeSubplan.c') diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index 419f3f36bd2..c02bd70d889 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.102 2010/07/12 17:01:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.103 2010/07/28 04:50:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -89,7 +89,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 */ @@ -126,12 +125,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 @@ -438,7 +431,6 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext) 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; @@ -460,7 +452,7 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext) * 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; @@ -476,8 +468,8 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext) node->tab_hash_funcs, nbuckets, sizeof(TupleHashEntryData), - node->tablecxt, - tempcxt); + node->hashtablecxt, + node->hashtempcxt); if (!subplan->unknownEqFalse) { @@ -495,8 +487,8 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext) node->tab_hash_funcs, nbuckets, sizeof(TupleHashEntryData), - node->tablecxt, - tempcxt); + node->hashtablecxt, + node->hashtempcxt); } /* @@ -555,7 +547,7 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext) /* * Reset innerecontext after each inner tuple to free any memory used - * in hash computation or comparison routines. + * during ExecProject. */ ResetExprContext(innerecontext); } @@ -680,7 +672,8 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) sstate->projRight = NULL; sstate->hashtable = NULL; sstate->hashnulls = NULL; - sstate->tablecxt = NULL; + sstate->hashtablecxt = NULL; + sstate->hashtempcxt = NULL; sstate->innerecontext = NULL; sstate->keyColIdx = NULL; sstate->tab_hash_funcs = NULL; @@ -730,12 +723,19 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) ListCell *l; /* We need a memory context to hold the hash table(s) */ - sstate->tablecxt = + sstate->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 */ + sstate->hashtempcxt = + AllocSetContextCreate(CurrentMemoryContext, + "Subplan HashTable Temp Context", + ALLOCSET_SMALL_MINSIZE, + ALLOCSET_SMALL_INITSIZE, + ALLOCSET_SMALL_MAXSIZE); /* and a short-lived exprcontext for function evaluation */ sstate->innerecontext = CreateExprContext(estate); /* Silly little array of column numbers 1..n */ -- cgit v1.2.3