diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index a770daf..b77d023 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -282,6 +282,8 @@ ExplainOneQuery(Query *query, ExplainState *es,
 		return;
 	}
 
+	query->oneshot = true;
+
 	/* if an advisor plugin is present, let it manage things */
 	if (ExplainOneQuery_hook)
 		(*ExplainOneQuery_hook) (query, es, queryString, params);
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index d848926..7119ccd 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -701,6 +701,7 @@ execute_sql_string(const char *sql, const char *filename)
 	 * Do parse analysis, rule rewrite, planning, and execution for each raw
 	 * parsetree.  We must fully execute each query before beginning parse
 	 * analysis on the next one, since there may be interdependencies.
+	 * Use one time plans so that we don't cache anything from this execution.
 	 */
 	foreach(lc1, raw_parsetree_list)
 	{
@@ -712,7 +713,7 @@ execute_sql_string(const char *sql, const char *filename)
 										   sql,
 										   NULL,
 										   0);
-		stmt_list = pg_plan_queries(stmt_list, 0, NULL);
+		stmt_list = pg_plan_queries(stmt_list, 0, NULL, true);
 
 		foreach(lc2, stmt_list)
 		{
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index dfa2ab0..6d8fd8c 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -145,7 +145,7 @@ PrepareQuery(PrepareStmt *stmt, const char *queryString)
 	query_list = QueryRewrite(query);
 
 	/* Generate plans for queries. */
-	plan_list = pg_plan_queries(query_list, 0, NULL);
+	plan_list = pg_plan_queries(query_list, 0, NULL, false);
 
 	/*
 	 * Save the results.
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 6e723ca..cf87c6e 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -1714,7 +1714,7 @@ _SPI_prepare_plan(const char *src, SPIPlanPtr plan, ParamListInfo boundParams)
 											   plan->argtypes,
 											   plan->nargs);
 		}
-		stmt_list = pg_plan_queries(stmt_list, cursor_options, boundParams);
+		stmt_list = pg_plan_queries(stmt_list, cursor_options, boundParams, false);
 
 		plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
 		cplan = (CachedPlan *) palloc0(sizeof(CachedPlan));
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 9aafc8a..2e322e6 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -170,6 +170,14 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
 	glob->lastRowMarkId = 0;
 	glob->transientPlan = false;
 
+	/*
+	 * Record whether the plan will be used once and immediately by executor.
+	 * If this is a oneshot plan we can evaluate pseudoconstants during
+	 * planning, so we can take advantage of parameter values as constants,
+	 * and new in 9.2, evaluate stable functions into constants.
+	 */
+	glob->oneshot = parse->oneshot;
+
 	/* Determine what fraction of the plan is likely to be scanned */
 	if (cursorOptions & CURSOR_OPT_FAST_PLAN)
 	{
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 2914c39..a743920 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -61,6 +61,7 @@ typedef struct
 	List	   *active_fns;
 	Node	   *case_val;
 	bool		estimate;
+	bool		oneshot;
 } eval_const_expressions_context;
 
 typedef struct
@@ -2097,11 +2098,13 @@ eval_const_expressions(PlannerInfo *root, Node *node)
 	{
 		context.boundParams = root->glob->boundParams;	/* bound Params */
 		context.glob = root->glob;		/* for inlined-function dependencies */
+		context.oneshot = root->glob->oneshot; /* can we optimise for oneshot plans? */
 	}
 	else
 	{
 		context.boundParams = NULL;
 		context.glob = NULL;
+		context.oneshot = false;
 	}
 	context.active_fns = NIL;	/* nothing being recursively simplified */
 	context.case_val = NULL;	/* no CASE being examined */
@@ -2137,6 +2140,7 @@ estimate_expression_value(PlannerInfo *root, Node *node)
 	context.active_fns = NIL;	/* nothing being recursively simplified */
 	context.case_val = NULL;	/* no CASE being examined */
 	context.estimate = true;	/* unsafe transformations OK */
+	context.oneshot = root->glob->oneshot; /* can we optimise for oneshot plans? */
 	return eval_const_expressions_mutator(node, &context);
 }
 
@@ -3786,7 +3790,7 @@ evaluate_function(Oid funcid, Oid result_type, int32 result_typmod,
 	 */
 	if (funcform->provolatile == PROVOLATILE_IMMUTABLE)
 		 /* okay */ ;
-	else if (context->estimate && funcform->provolatile == PROVOLATILE_STABLE)
+	else if (funcform->provolatile == PROVOLATILE_STABLE && (context->estimate || context->oneshot))
 		 /* okay */ ;
 	else
 		return NULL;
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index a07661f..ff9f3cd 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -762,7 +762,7 @@ pg_plan_query(Query *querytree, int cursorOptions, ParamListInfo boundParams)
  * list.  Utility statements are simply represented by their statement nodes.
  */
 List *
-pg_plan_queries(List *querytrees, int cursorOptions, ParamListInfo boundParams)
+pg_plan_queries(List *querytrees, int cursorOptions, ParamListInfo boundParams, bool oneshotplan)
 {
 	List	   *stmt_list = NIL;
 	ListCell   *query_list;
@@ -779,6 +779,7 @@ pg_plan_queries(List *querytrees, int cursorOptions, ParamListInfo boundParams)
 		}
 		else
 		{
+			query->oneshot = oneshotplan;
 			stmt = (Node *) pg_plan_query(query, cursorOptions, boundParams);
 		}
 
@@ -944,7 +945,7 @@ exec_simple_query(const char *query_string)
 		querytree_list = pg_analyze_and_rewrite(parsetree, query_string,
 												NULL, 0);
 
-		plantree_list = pg_plan_queries(querytree_list, 0, NULL);
+		plantree_list = pg_plan_queries(querytree_list, 0, NULL, true);
 
 		/* Done with the snapshot used for parsing/planning */
 		if (snapshot_set)
@@ -1284,7 +1285,7 @@ exec_parse_message(const char *query_string,	/* string to execute */
 		}
 		else
 		{
-			stmt_list = pg_plan_queries(querytree_list, 0, NULL);
+			stmt_list = pg_plan_queries(querytree_list, 0, NULL, false);
 			fully_planned = true;
 		}
 
@@ -1739,7 +1740,7 @@ exec_bind_message(StringInfo input_message)
 		 */
 		oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
 		query_list = copyObject(cplan->stmt_list);
-		plan_list = pg_plan_queries(query_list, 0, params);
+		plan_list = pg_plan_queries(query_list, 0, params, true);
 		MemoryContextSwitchTo(oldContext);
 
 		/* We no longer need the cached plan refcount ... */
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 08ddfa9..e65ba82 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -563,7 +563,7 @@ RevalidateCachedPlan(CachedPlanSource *plansource, bool useResOwner)
 
 			pushed = SPI_push_conditional();
 
-			slist = pg_plan_queries(slist, plansource->cursor_options, NULL);
+			slist = pg_plan_queries(slist, plansource->cursor_options, NULL, false);
 
 			SPI_pop_conditional(pushed);
 		}
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 14937d4..568262e 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -103,6 +103,7 @@ typedef struct Query
 
 	QuerySource querySource;	/* where did I come from? */
 
+	bool		oneshot;		/* can plan potentially be used more than once? */
 	bool		canSetTag;		/* do I set the command result tag? */
 
 	Node	   *utilityStmt;	/* non-null if this is DECLARE CURSOR or a
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index f659269..e655542 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -76,6 +76,8 @@ typedef struct PlannerGlobal
 
 	ParamListInfo boundParams;	/* Param values provided to planner() */
 
+	bool		oneshot;		/* Are we planning a non-reusable plan? */
+
 	List	   *paramlist;		/* to keep track of cross-level Params */
 
 	List	   *subplans;		/* Plans for SubPlan nodes */
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index d5192d9..3be6467 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -55,7 +55,7 @@ extern List *pg_analyze_and_rewrite_params(Node *parsetree,
 extern PlannedStmt *pg_plan_query(Query *querytree, int cursorOptions,
 			  ParamListInfo boundParams);
 extern List *pg_plan_queries(List *querytrees, int cursorOptions,
-				ParamListInfo boundParams);
+				ParamListInfo boundParams, bool oneshotplan);
 
 extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
 extern void assign_max_stack_depth(int newval, void *extra);