From 7ad33cebfdb7523642e5efff133f743fbb1947bb Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 8 Feb 2007 18:37:14 +0000
Subject: [PATCH] Rearrange use of plpgsql_add_initdatums() so that only the
 parsing of a DECLARE section needs to know about it.  Formerly, everyplace
 besides DECLARE that created variables needed to do
 "plpgsql_add_initdatums(NULL)" to prevent those variables from being sucked
 up as part of a subsequent DECLARE block. This is obviously error-prone, and
 in fact the SQLSTATE/SQLERRM patch had failed to do it for those two
 variables, leading to the bug recently exhibited by Asif Ali Rehman: a
 DECLARE within an exception handler tried to reinitialize SQLERRM.

Although the SQLSTATE/SQLERRM patch isn't in any pre-8.1 branches, and so
I can't point to a demonstrable failure there, it seems wise to back-patch
this into the older branches anyway, just to keep the logic similar to HEAD.
---
 src/pl/plpgsql/src/gram.y    | 11 +++++------
 src/pl/plpgsql/src/pl_comp.c | 23 ++++++++++++-----------
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y
index 0e6e017a828..ad76d80b1a5 100644
--- a/src/pl/plpgsql/src/gram.y
+++ b/src/pl/plpgsql/src/gram.y
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.97 2007/02/01 19:10:29 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.98 2007/02/08 18:37:14 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -272,7 +272,6 @@ decl_sect		: opt_block_label
 						$$.label	  = $1;
 						$$.n_initvars = 0;
 						$$.initvarnos = NULL;
-						plpgsql_add_initdatums(NULL);
 					}
 				| opt_block_label decl_start
 					{
@@ -280,7 +279,6 @@ decl_sect		: opt_block_label
 						$$.label	  = $1;
 						$$.n_initvars = 0;
 						$$.initvarnos = NULL;
-						plpgsql_add_initdatums(NULL);
 					}
 				| opt_block_label decl_start decl_stmts
 					{
@@ -289,12 +287,16 @@ decl_sect		: opt_block_label
 							$$.label = $3;
 						else
 							$$.label = $1;
+						/* Remember variables declared in decl_stmts */
 						$$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
 					}
 				;
 
 decl_start		: K_DECLARE
 					{
+						/* Forget any variables created before block */
+						plpgsql_add_initdatums(NULL);
+						/* Make variable names be local to block */
 						plpgsql_ns_setlocal(true);
 					}
 				;
@@ -990,9 +992,6 @@ for_control		:
 																				  -1),
 														   true);
 
-								/* put the for-variable into the local block */
-								plpgsql_add_initdatums(NULL);
-
 								new = palloc0(sizeof(PLpgSQL_stmt_fori));
 								new->cmd_type = PLPGSQL_STMT_FORI;
 								new->lineno   = $1;
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 3ca2ca28b3f..c342ed3e85b 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.111 2007/02/01 19:10:29 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.112 2007/02/08 18:37:14 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -666,11 +666,6 @@ do_compile(FunctionCallInfo fcinfo,
 								 true);
 	function->found_varno = var->dno;
 
-	/*
-	 * Forget about the above created variables
-	 */
-	plpgsql_add_initdatums(NULL);
-
 	/*
 	 * Now parse the function's text
 	 */
@@ -1893,11 +1888,17 @@ plpgsql_adddatum(PLpgSQL_datum *new)
 
 
 /* ----------
- * plpgsql_add_initdatums		Put all datum entries created
- *					since the last call into the
- *					finishing code block so the
- *					block knows which variables to
- *					reinitialize when entered.
+ * plpgsql_add_initdatums		Make an array of the datum numbers of
+ *					all the simple VAR datums created since the last call
+ *					to this function.
+ *
+ * If varnos is NULL, we just forget any datum entries created since the
+ * last call.
+ *
+ * This is used around a DECLARE section to create a list of the VARs
+ * that have to be initialized at block entry.  Note that VARs can also
+ * be created elsewhere than DECLARE, eg by a FOR-loop, but it is then
+ * the responsibility of special-purpose code to initialize them.
  * ----------
  */
 int
-- 
GitLab