* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.32 2010/01/02 16:57:55 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.33 2010/01/13 16:56:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
void
ResetPlanCache(void)
{
- ListCell *lc;
+ ListCell *lc1;
- foreach(lc, cached_plans_list)
+ foreach(lc1, cached_plans_list)
{
- CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
+ CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc1);
CachedPlan *plan = plansource->plan;
+ ListCell *lc2;
- if (plan)
- plan->dead = true;
+ /* No work if it's already invalidated */
+ if (!plan || plan->dead)
+ continue;
+
+ /*
+ * We *must not* mark transaction control statements as dead,
+ * particularly not ROLLBACK, because they may need to be executed in
+ * aborted transactions when we can't revalidate them (cf bug #5269).
+ * In general there is no point in invalidating utility statements
+ * since they have no plans anyway. So mark it dead only if it
+ * contains at least one non-utility statement.
+ */
+ if (plan->fully_planned)
+ {
+ /* Search statement list for non-utility statements */
+ foreach(lc2, plan->stmt_list)
+ {
+ PlannedStmt *plannedstmt = (PlannedStmt *) lfirst(lc2);
+
+ Assert(!IsA(plannedstmt, Query));
+ if (IsA(plannedstmt, PlannedStmt))
+ {
+ /* non-utility statement, so invalidate */
+ plan->dead = true;
+ break; /* out of stmt_list scan */
+ }
+ }
+ }
+ else
+ {
+ /* Search Query list for non-utility statements */
+ foreach(lc2, plan->stmt_list)
+ {
+ Query *query = (Query *) lfirst(lc2);
+
+ Assert(IsA(query, Query));
+ if (query->commandType != CMD_UTILITY)
+ {
+ /* non-utility statement, so invalidate */
+ plan->dead = true;
+ break; /* out of stmt_list scan */
+ }
+ }
+ }
}
}