Me again,

Here's a patch for making PL/PgSQL throw an error during compilation (instead of runtime) if the number of parameters passed to RAISE don't match the number of placeholders in error message. I'm sure people can see the pros of doing it this way.


.marko
*** a/src/pl/plpgsql/src/pl_gram.y
--- b/src/pl/plpgsql/src/pl_gram.y
***************
*** 106,111 **** static void                     check_labels(const char 
*start_label,
--- 106,112 ----
  static        PLpgSQL_expr    *read_cursor_args(PLpgSQL_var *cursor,
                                                                                
  int until, const char *expected);
  static        List                    *read_raise_options(void);
+ static        void                    
check_raise_parameters(PLpgSQL_stmt_raise *stmt);
  
  %}
  
***************
*** 1849,1854 **** stmt_raise           : K_RAISE
--- 1850,1857 ----
                                                                new->options = 
read_raise_options();
                                                }
  
+                                               check_raise_parameters(new);
+ 
                                                $$ = (PLpgSQL_stmt *)new;
                                        }
                                ;
***************
*** 3768,3773 **** read_raise_options(void)
--- 3771,3812 ----
  }
  
  /*
+  * Check that the number of parameter placeholders in the message matches the
+  * number of parameters passed to it, if message was defined.
+  */
+ static void
+ check_raise_parameters(PLpgSQL_stmt_raise *stmt)
+ {
+       char *cp;
+       int expected_nparams = 0;
+ 
+       if (stmt->message == NULL)
+               return;
+ 
+       for (cp = stmt->message; *cp; cp++)
+       {
+               if (cp[0] != '%')
+                       continue;
+               /* literal %, ignore */
+               if (cp[1] == '%')
+               {
+                       cp++;
+                       continue;
+               }
+               expected_nparams++;
+       }
+ 
+       if (expected_nparams < list_length(stmt->params))
+               ereport(ERROR,
+                               (errcode(ERRCODE_SYNTAX_ERROR),
+                               errmsg("too many parameters specified for 
RAISE")));
+       if (expected_nparams > list_length(stmt->params))
+               ereport(ERROR,
+                               (errcode(ERRCODE_SYNTAX_ERROR),
+                               errmsg("too few parameters specified for 
RAISE")));
+ }
+ 
+ /*
   * Fix up CASE statement
   */
  static PLpgSQL_stmt *
*** a/src/test/regress/expected/plpgsql.out
--- b/src/test/regress/expected/plpgsql.out
***************
*** 2446,2463 **** begin
      return $1;
  end;
  $$ language plpgsql;
- select raise_test1(5);
  ERROR:  too many parameters specified for RAISE
! CONTEXT:  PL/pgSQL function raise_test1(integer) line 3 at RAISE
  create function raise_test2(int) returns int as $$
  begin
      raise notice 'This message has too few parameters: %, %, %', $1, $1;
      return $1;
  end;
  $$ language plpgsql;
- select raise_test2(10);
  ERROR:  too few parameters specified for RAISE
! CONTEXT:  PL/pgSQL function raise_test2(integer) line 3 at RAISE
  -- Test re-RAISE inside a nested exception block.  This case is allowed
  -- by Oracle's PL/SQL but was handled differently by PG before 9.1.
  CREATE FUNCTION reraise_test() RETURNS void AS $$
--- 2446,2474 ----
      return $1;
  end;
  $$ language plpgsql;
  ERROR:  too many parameters specified for RAISE
! CONTEXT:  compilation of PL/pgSQL function "raise_test1" near line 3
  create function raise_test2(int) returns int as $$
  begin
      raise notice 'This message has too few parameters: %, %, %', $1, $1;
      return $1;
  end;
  $$ language plpgsql;
  ERROR:  too few parameters specified for RAISE
! CONTEXT:  compilation of PL/pgSQL function "raise_test2" near line 3
! create function raise_test3(int) returns int as $$
! begin
!     raise notice 'This message has no parameters (despite having %% signs in 
it)!';
!     return $1;
! end;
! $$ language plpgsql;
! select raise_test3(1);
! NOTICE:  This message has no parameters (despite having % signs in it)!
!  raise_test3 
! -------------
!            1
! (1 row)
! 
  -- Test re-RAISE inside a nested exception block.  This case is allowed
  -- by Oracle's PL/SQL but was handled differently by PG before 9.1.
  CREATE FUNCTION reraise_test() RETURNS void AS $$
*** a/src/test/regress/sql/plpgsql.sql
--- b/src/test/regress/sql/plpgsql.sql
***************
*** 2078,2085 **** begin
  end;
  $$ language plpgsql;
  
- select raise_test1(5);
- 
  create function raise_test2(int) returns int as $$
  begin
      raise notice 'This message has too few parameters: %, %, %', $1, $1;
--- 2078,2083 ----
***************
*** 2087,2093 **** begin
  end;
  $$ language plpgsql;
  
! select raise_test2(10);
  
  -- Test re-RAISE inside a nested exception block.  This case is allowed
  -- by Oracle's PL/SQL but was handled differently by PG before 9.1.
--- 2085,2098 ----
  end;
  $$ language plpgsql;
  
! create function raise_test3(int) returns int as $$
! begin
!     raise notice 'This message has no parameters (despite having %% signs in 
it)!';
!     return $1;
! end;
! $$ language plpgsql;
! 
! select raise_test3(1);
  
  -- Test re-RAISE inside a nested exception block.  This case is allowed
  -- by Oracle's PL/SQL but was handled differently by PG before 9.1.
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to