*** pgsql/src/backend/executor/execUtils.c 2009/06/11 14:48:57 1.159 --- pgsql/src/backend/executor/execUtils.c 2009/07/18 19:15:41 1.160 *************** *** 8,14 **** * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.158 2009/04/02 22:39:30 tgl Exp $ * *------------------------------------------------------------------------- */ --- 8,14 ---- * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.159 2009/06/11 14:48:57 momjian Exp $ * *------------------------------------------------------------------------- */ *************** int NIndexTupleProcessed; *** 68,74 **** static bool get_last_attnums(Node *node, ProjectionInfo *projInfo); ! static void ShutdownExprContext(ExprContext *econtext); /* ---------------------------------------------------------------- --- 68,74 ---- static bool get_last_attnums(Node *node, ProjectionInfo *projInfo); ! static void ShutdownExprContext(ExprContext *econtext, bool isCommit); /* ---------------------------------------------------------------- *************** FreeExecutorState(EState *estate) *** 257,263 **** * XXX: seems there ought to be a faster way to implement this than * repeated list_delete(), no? */ ! FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts)); /* FreeExprContext removed the list link for us */ } --- 257,264 ---- * XXX: seems there ought to be a faster way to implement this than * repeated list_delete(), no? */ ! FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts), ! true); /* FreeExprContext removed the list link for us */ } *************** CreateStandaloneExprContext(void) *** 408,423 **** * Since we free the temporary context used for expression evaluation, * any previously computed pass-by-reference expression result will go away! * * Note we make no assumption about the caller's memory context. * ---------------- */ void ! FreeExprContext(ExprContext *econtext) { EState *estate; /* Call any registered callbacks */ ! ShutdownExprContext(econtext); /* And clean up the memory used */ MemoryContextDelete(econtext->ecxt_per_tuple_memory); /* Unlink self from owning EState, if any */ --- 409,429 ---- * Since we free the temporary context used for expression evaluation, * any previously computed pass-by-reference expression result will go away! * + * If isCommit is false, we are being called in error cleanup, and should + * not call callbacks but only release memory. (It might be better to call + * the callbacks and pass the isCommit flag to them, but that would require + * more invasive code changes than currently seems justified.) + * * Note we make no assumption about the caller's memory context. * ---------------- */ void ! FreeExprContext(ExprContext *econtext, bool isCommit) { EState *estate; /* Call any registered callbacks */ ! ShutdownExprContext(econtext, isCommit); /* And clean up the memory used */ MemoryContextDelete(econtext->ecxt_per_tuple_memory); /* Unlink self from owning EState, if any */ *************** void *** 442,448 **** ReScanExprContext(ExprContext *econtext) { /* Call any registered callbacks */ ! ShutdownExprContext(econtext); /* And clean up the memory used */ MemoryContextReset(econtext->ecxt_per_tuple_memory); } --- 448,454 ---- ReScanExprContext(ExprContext *econtext) { /* Call any registered callbacks */ ! ShutdownExprContext(econtext, true); /* And clean up the memory used */ MemoryContextReset(econtext->ecxt_per_tuple_memory); } *************** UnregisterExprContextCallback(ExprContex *** 1222,1230 **** * * The callback list is emptied (important in case this is only a rescan * reset, and not deletion of the ExprContext). */ static void ! ShutdownExprContext(ExprContext *econtext) { ExprContext_CB *ecxt_callback; MemoryContext oldcontext; --- 1228,1239 ---- * * The callback list is emptied (important in case this is only a rescan * reset, and not deletion of the ExprContext). + * + * If isCommit is false, just clean the callback list but don't call 'em. + * (See comment for FreeExprContext.) */ static void ! ShutdownExprContext(ExprContext *econtext, bool isCommit) { ExprContext_CB *ecxt_callback; MemoryContext oldcontext; *************** ShutdownExprContext(ExprContext *econtex *** 1245,1251 **** while ((ecxt_callback = econtext->ecxt_callbacks) != NULL) { econtext->ecxt_callbacks = ecxt_callback->next; ! (*ecxt_callback->function) (ecxt_callback->arg); pfree(ecxt_callback); } --- 1254,1261 ---- while ((ecxt_callback = econtext->ecxt_callbacks) != NULL) { econtext->ecxt_callbacks = ecxt_callback->next; ! if (isCommit) ! (*ecxt_callback->function) (ecxt_callback->arg); pfree(ecxt_callback); }