Rearrange use of plpgsql_add_initdatums() so that only the parsing of a
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 8 Feb 2007 18:37:52 +0000 (18:37 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 8 Feb 2007 18:37:52 +0000 (18:37 +0000)
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
src/pl/plpgsql/src/pl_comp.c

index cf30200d70ebd9e82b8f3e9e24dccc1be19a8991..c372164541a859bc6f4f0ef88e33de814dcf155b 100644 (file)
@@ -4,7 +4,7 @@
  *                       procedural language
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.82.2.2 2006/08/14 00:46:59 tgl Exp $
+ *   $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.82.2.3 2007/02/08 18:37:52 tgl Exp $
  *
  *   This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -284,7 +284,6 @@ decl_sect       : opt_block_label
                        $$.label      = $1;
                        $$.n_initvars = 0;
                        $$.initvarnos = NULL;
-                       plpgsql_add_initdatums(NULL);
                    }
                | opt_block_label decl_start
                    {
@@ -292,7 +291,6 @@ decl_sect       : opt_block_label
                        $$.label      = $1;
                        $$.n_initvars = 0;
                        $$.initvarnos = NULL;
-                       plpgsql_add_initdatums(NULL);
                    }
                | opt_block_label decl_start decl_stmts
                    {
@@ -301,12 +299,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);
                    }
                ;
@@ -948,9 +950,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;
index c20a2b31837ddbc34ea8d4fc839616e163f47855..186520377ce301d3f2ca9db7797deae50a34b76a 100644 (file)
@@ -3,7 +3,7 @@
  *           procedural language
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.94.2.3 2007/01/30 22:05:25 tgl Exp $
+ *   $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.94.2.4 2007/02/08 18:37:52 tgl Exp $
  *
  *   This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -682,11 +682,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
     */
@@ -2003,11 +1998,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