From e6ed34f70d57d102da8383919e0046c577d317e7 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri, 16 Sep 2011 12:31:23 -0400
Subject: [PATCH] Ensure generic plan gets used for a plpgsql expression with
 no parameters.

Now that a NULL ParamListInfo pointer causes significantly different
behavior in plancache.c, be sure to pass it that way when the expression
is known not to reference any plpgsql variables.  Saves a few setup
cycles anyway.
---
 src/pl/plpgsql/src/pl_exec.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index df785c98511..1f1acdc5e0a 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -3012,11 +3012,6 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
 	int			rc;
 	PLpgSQL_expr *expr = stmt->sqlstmt;
 
-	/*
-	 * Set up ParamListInfo (hook function and possibly data values)
-	 */
-	paramLI = setup_param_list(estate, expr);
-
 	/*
 	 * On the first call for this statement generate the plan, and detect
 	 * whether the statement is INSERT/UPDATE/DELETE
@@ -3049,6 +3044,11 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
 		}
 	}
 
+	/*
+	 * Set up ParamListInfo (hook function and possibly data values)
+	 */
+	paramLI = setup_param_list(estate, expr);
+
 	/*
 	 * If we have INTO, then we only need one row back ... but if we have INTO
 	 * STRICT, ask for two rows, so that we can verify the statement returns
@@ -5000,12 +5000,18 @@ setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
 {
 	ParamListInfo paramLI;
 
+	/*
+	 * We must have created the SPIPlan already (hence, query text has been
+	 * parsed/analyzed at least once); else we cannot rely on expr->paramnos.
+	 */
+	Assert(expr->plan != NULL);
+
 	/*
 	 * Could we re-use these arrays instead of palloc'ing a new one each time?
 	 * However, we'd have to re-fill the array each time anyway, since new
 	 * values might have been assigned to the variables.
 	 */
-	if (estate->ndatums > 0)
+	if (!bms_is_empty(expr->paramnos))
 	{
 		Bitmapset  *tmpset;
 		int			dno;
@@ -5048,12 +5054,19 @@ setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
 		/*
 		 * Also make sure this is set before parser hooks need it.	There is
 		 * no need to save and restore, since the value is always correct once
-		 * set.
+		 * set.  (Should be set already, but let's be sure.)
 		 */
 		expr->func = estate->func;
 	}
 	else
+	{
+		/*
+		 * Expression requires no parameters.  Be sure we represent this case
+		 * as a NULL ParamListInfo, so that plancache.c knows there is no
+		 * point in a custom plan.
+		 */
 		paramLI = NULL;
+	}
 	return paramLI;
 }
 
-- 
GitLab