aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache/plancache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/cache/plancache.c')
-rw-r--r--src/backend/utils/cache/plancache.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 21aed6eadbe..43297281f5f 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -33,13 +33,14 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.10 2007/06/05 20:00:41 wieck Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.11 2007/09/20 17:56:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "utils/plancache.h"
+#include "access/transam.h"
#include "catalog/namespace.h"
#include "executor/executor.h"
#include "optimizer/clauses.h"
@@ -79,6 +80,7 @@ static void ScanQueryForRelids(Query *parsetree,
void *arg);
static bool ScanQueryWalker(Node *node, ScanQueryWalkerContext *context);
static bool rowmark_member(List *rowMarks, int rt_index);
+static bool plan_list_is_transient(List *stmt_list);
static void PlanCacheCallback(Datum arg, Oid relid);
static void InvalRelid(Oid relid, LOCKMODE lockmode,
InvalRelidContext *context);
@@ -322,6 +324,13 @@ StoreCachedPlan(CachedPlanSource *plansource,
plan->stmt_list = stmt_list;
plan->fully_planned = plansource->fully_planned;
plan->dead = false;
+ if (plansource->fully_planned && plan_list_is_transient(stmt_list))
+ {
+ Assert(TransactionIdIsNormal(TransactionXmin));
+ plan->saved_xmin = TransactionXmin;
+ }
+ else
+ plan->saved_xmin = InvalidTransactionId;
plan->refcount = 1; /* for the parent's link */
plan->generation = ++(plansource->generation);
plan->context = plan_context;
@@ -412,6 +421,15 @@ RevalidateCachedPlan(CachedPlanSource *plansource, bool useResOwner)
AcquirePlannerLocks(plan->stmt_list, true);
/*
+ * If plan was transient, check to see if TransactionXmin has
+ * advanced, and if so invalidate it.
+ */
+ if (!plan->dead &&
+ TransactionIdIsValid(plan->saved_xmin) &&
+ !TransactionIdEquals(plan->saved_xmin, TransactionXmin))
+ plan->dead = true;
+
+ /*
* By now, if any invalidation has happened, PlanCacheCallback
* will have marked the plan dead.
*/
@@ -790,6 +808,28 @@ rowmark_member(List *rowMarks, int rt_index)
}
/*
+ * plan_list_is_transient: check if any of the plans in the list are transient.
+ */
+static bool
+plan_list_is_transient(List *stmt_list)
+{
+ ListCell *lc;
+
+ foreach(lc, stmt_list)
+ {
+ PlannedStmt *plannedstmt = (PlannedStmt *) lfirst(lc);
+
+ if (!IsA(plannedstmt, PlannedStmt))
+ continue; /* Ignore utility statements */
+
+ if (plannedstmt->transientPlan)
+ return true;
+ }
+
+ return false;
+}
+
+/*
* PlanCacheComputeResultDesc: given a list of either fully-planned statements
* or Queries, determine the result tupledesc it will produce. Returns NULL
* if the execution will not return tuples.