mirror of
https://github.com/postgres/postgres.git
synced 2025-11-12 05:01:15 +03:00
Fix a many-legged critter reported by chifungfan@yahoo.com: under the
right circumstances a hash join executed as a DECLARE CURSOR/FETCH query would crash the backend. Problem as seen in current sources was that the hash tables were stored in a context that was a child of TransactionCommandContext, which got zapped at completion of the FETCH command --- but cursor cleanup executed at COMMIT expected the tables to still be valid. I haven't chased down the details as seen in 7.0.* but I'm sure it's the same general problem.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.37 2000/07/17 03:05:15 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.38 2000/08/22 04:06:20 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -68,8 +68,8 @@ CreateExecutorState(void)
|
||||
state->es_direction = ForwardScanDirection;
|
||||
state->es_range_table = NIL;
|
||||
|
||||
state->es_into_relation_descriptor = NULL;
|
||||
state->es_result_relation_info = NULL;
|
||||
state->es_into_relation_descriptor = NULL;
|
||||
|
||||
state->es_param_list_info = NULL;
|
||||
state->es_param_exec_vals = NULL;
|
||||
@@ -78,6 +78,10 @@ CreateExecutorState(void)
|
||||
|
||||
state->es_junkFilter = NULL;
|
||||
|
||||
state->es_query_cxt = CurrentMemoryContext;
|
||||
|
||||
state->es_per_tuple_exprcontext = NULL;
|
||||
|
||||
/* ----------------
|
||||
* return the executor state structure
|
||||
* ----------------
|
||||
@@ -144,13 +148,11 @@ PreparePortal(char *portalName)
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Create the new portal and make its memory context active.
|
||||
* Create the new portal.
|
||||
* ----------------
|
||||
*/
|
||||
portal = CreatePortal(portalName);
|
||||
|
||||
MemoryContextSwitchTo(PortalGetHeapMemory(portal));
|
||||
|
||||
return portal;
|
||||
}
|
||||
|
||||
@@ -170,8 +172,9 @@ ProcessQuery(Query *parsetree,
|
||||
char *tag;
|
||||
bool isRetrieveIntoPortal;
|
||||
bool isRetrieveIntoRelation;
|
||||
Portal portal = NULL;
|
||||
char *intoName = NULL;
|
||||
Portal portal = NULL;
|
||||
MemoryContext oldContext = NULL;
|
||||
QueryDesc *queryDesc;
|
||||
EState *state;
|
||||
TupleDesc attinfo;
|
||||
@@ -217,14 +220,18 @@ ProcessQuery(Query *parsetree,
|
||||
if (isRetrieveIntoPortal)
|
||||
{
|
||||
portal = PreparePortal(intoName);
|
||||
/* CurrentMemoryContext is now pointing to portal's context */
|
||||
oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
|
||||
parsetree = copyObject(parsetree);
|
||||
plan = copyObject(plan);
|
||||
/*
|
||||
* We stay in portal's memory context for now, so that query desc,
|
||||
* EState, and plan startup info are also allocated in the portal
|
||||
* context.
|
||||
*/
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Now we can create the QueryDesc object (this is also in
|
||||
* the portal context, if portal retrieve).
|
||||
* Now we can create the QueryDesc object.
|
||||
* ----------------
|
||||
*/
|
||||
queryDesc = CreateQueryDesc(parsetree, plan, dest);
|
||||
@@ -241,7 +248,7 @@ ProcessQuery(Query *parsetree,
|
||||
queryDesc->dest = (int) None;
|
||||
|
||||
/* ----------------
|
||||
* create a default executor state..
|
||||
* create a default executor state.
|
||||
* ----------------
|
||||
*/
|
||||
state = CreateExecutorState();
|
||||
@@ -279,9 +286,11 @@ ProcessQuery(Query *parsetree,
|
||||
state,
|
||||
PortalCleanup);
|
||||
|
||||
MemoryContextSwitchTo(TransactionCommandContext);
|
||||
/* Now we can return to caller's memory context. */
|
||||
MemoryContextSwitchTo(oldContext);
|
||||
|
||||
EndCommand(tag, dest);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user