Pavel Stehule wrote:
        I did trivial patch which eliminate limit raise command.

Looks pretty good. Attached is a cleaned-up version that I'll apply to HEAD tomorrow, barring any objections.

BTW, one regression is that an undefined variable in the RAISE list is no longer a compile-time error:

create function foo() returns void as '
begin
raise notice ''hello, world: %'', baz;
end;' language plpgsql;

neilc=#  select foo();
ERROR:  column "baz" does not exist

I don't see an easy way to get around this, though, and it's not too concerning. Amusingly it does completely break the SQLSTATE and SQLERRM tests we added a few days ago :)

BTW, another easy improvement in this area is changing the RAISE format string to allow it to be an expression, rather than only a string literal.

-Neil
Index: doc/src/sgml/plpgsql.sgml
===================================================================
RCS file: /var/lib/cvs/pgsql/doc/src/sgml/plpgsql.sgml,v
retrieving revision 1.71
diff -c -r1.71 plpgsql.sgml
*** doc/src/sgml/plpgsql.sgml	10 Jun 2005 16:23:09 -0000	1.71
--- doc/src/sgml/plpgsql.sgml	13 Jun 2005 05:38:55 -0000
***************
*** 2533,2541 ****
     <para>
      Inside the format string, <literal>%</literal> is replaced by the
      next optional argument's string representation. Write
!     <literal>%%</literal> to emit a literal <literal>%</literal>. Note
!     that the optional arguments must presently be simple variables,
!     not expressions, and the format must be a simple string literal.
     </para>
  
     <!--
--- 2533,2541 ----
     <para>
      Inside the format string, <literal>%</literal> is replaced by the
      next optional argument's string representation. Write
!     <literal>%%</literal> to emit a literal <literal>%</literal>. 
!     Arguments can be simple variables or expressions, 
!     and the format must be a simple string literal.
     </para>
  
     <!--
Index: src/pl/plpgsql/src/gram.y
===================================================================
RCS file: /var/lib/cvs/pgsql/src/pl/plpgsql/src/gram.y,v
retrieving revision 1.75
diff -c -r1.75 gram.y
*** src/pl/plpgsql/src/gram.y	10 Jun 2005 16:23:11 -0000	1.75
--- src/pl/plpgsql/src/gram.y	13 Jun 2005 05:44:02 -0000
***************
*** 135,142 ****
  %type <exception>	proc_exception
  %type <condition>	proc_conditions
  
! %type <list>	raise_params
! %type <ival>	raise_level raise_param
  %type <str>		raise_msg
  
  %type <list>	getdiag_list
--- 135,142 ----
  %type <exception>	proc_exception
  %type <condition>	proc_conditions
  
! 
! %type <ival>	raise_level
  %type <str>		raise_msg
  
  %type <list>	getdiag_list
***************
*** 1157,1163 ****
  					}
  				;
  
! stmt_raise		: K_RAISE lno raise_level raise_msg raise_params ';'
  					{
  						PLpgSQL_stmt_raise		*new;
  
--- 1157,1163 ----
  					}
  				;
  
! stmt_raise		: K_RAISE lno raise_level raise_msg
  					{
  						PLpgSQL_stmt_raise		*new;
  
***************
*** 1167,1187 ****
  						new->lineno		= $2;
  						new->elog_level = $3;
  						new->message	= $4;
- 						new->params		= $5;
  
! 						$$ = (PLpgSQL_stmt *)new;
! 					}
! 				| K_RAISE lno raise_level raise_msg ';'
! 					{
! 						PLpgSQL_stmt_raise		*new;
  
! 						new = palloc(sizeof(PLpgSQL_stmt_raise));
  
! 						new->cmd_type	= PLPGSQL_STMT_RAISE;
! 						new->lineno		= $2;
! 						new->elog_level = $3;
! 						new->message	= $4;
! 						new->params		= NIL;
  
  						$$ = (PLpgSQL_stmt *)new;
  					}
--- 1167,1186 ----
  						new->lineno		= $2;
  						new->elog_level = $3;
  						new->message	= $4;
  
! 						switch (yylex())
! 						{
! 							case ';':
! 								new->params_expr = NULL;
! 								break;
  
! 							case ',':
! 								new->params_expr = plpgsql_read_expression(';', ";");
! 								break;
  
! 							default:
! 								yyerror("syntax error");
! 						}
  
  						$$ = (PLpgSQL_stmt *)new;
  					}
***************
*** 1219,1240 ****
  					}
  				;
  
- raise_params	: raise_params raise_param
- 					{
- 						$$ = lappend_int($1, $2);
- 					}
- 				| raise_param
- 					{
- 						$$ = list_make1_int($1);
- 					}
- 				;
- 
- raise_param		: ',' T_SCALAR
- 					{
- 						$$ = yylval.scalar->dno;
- 					}
- 				;
- 
  loop_body		: proc_sect K_END K_LOOP ';'
  					{ $$ = $1; }
  				;
--- 1218,1223 ----
Index: src/pl/plpgsql/src/pl_exec.c
===================================================================
RCS file: /var/lib/cvs/pgsql/src/pl/plpgsql/src/pl_exec.c,v
retrieving revision 1.143
diff -c -r1.143 pl_exec.c
*** src/pl/plpgsql/src/pl_exec.c	10 Jun 2005 16:23:11 -0000	1.143
--- src/pl/plpgsql/src/pl_exec.c	13 Jun 2005 06:04:21 -0000
***************
*** 1911,1920 ****
  {
  	char	   *cp;
  	PLpgSQL_dstring ds;
! 	ListCell   *current_param;
  
  	plpgsql_dstring_init(&ds);
! 	current_param = list_head(stmt->params);
  
  	for (cp = stmt->message; *cp; cp++)
  	{
--- 1911,1939 ----
  {
  	char	   *cp;
  	PLpgSQL_dstring ds;
! 	int   param_idx = 0;
! 	int params_count = 0;
  
  	plpgsql_dstring_init(&ds);
! 
! 	if (stmt->params_expr)
! 	{
! 		int rc = exec_run_select(estate, stmt->params_expr, 2, NULL);
! 
! 		if (rc != SPI_OK_SELECT || estate->eval_processed == 0)
! 			ereport(ERROR,
! 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
! 					 errmsg("query \"%s\" did not return data", stmt->params_expr->query)));
! 
! 		/* Check that the expression returned a single Datum */
! 		if (estate->eval_processed > 1)
! 			ereport(ERROR,
! 					(errcode(ERRCODE_CARDINALITY_VIOLATION),
! 					 errmsg("query \"%s\" returned more than one row",
! 							stmt->params_expr->query)));
! 
! 		params_count = estate->eval_tuptable->tupdesc->natts;
! 	}
  
  	for (cp = stmt->message; *cp; cp++)
  	{
***************
*** 1936,1966 ****
  				continue;
  			}
  
! 			if (current_param == NULL)
  				ereport(ERROR,
  						(errcode(ERRCODE_SYNTAX_ERROR),
  						 errmsg("too few parameters specified for RAISE")));
  
! 			exec_eval_datum(estate, estate->datums[lfirst_int(current_param)],
! 							InvalidOid,
! 							&paramtypeid, &paramvalue, &paramisnull);
  			if (paramisnull)
  				extval = "<NULL>";
  			else
  				extval = convert_value_to_string(paramvalue, paramtypeid);
  			plpgsql_dstring_append(&ds, extval);
! 			current_param = lnext(current_param);
  			continue;
  		}
  
  		plpgsql_dstring_append_char(&ds, cp[0]);
  	}
  
  	/*
  	 * If more parameters were specified than were required to process
  	 * the format string, throw an error
  	 */
! 	if (current_param != NULL)
  		ereport(ERROR,
  				(errcode(ERRCODE_SYNTAX_ERROR),
  				 errmsg("too many parameters specified for RAISE")));
--- 1955,1989 ----
  				continue;
  			}
  
! 			if (param_idx == params_count)
  				ereport(ERROR,
  						(errcode(ERRCODE_SYNTAX_ERROR),
  						 errmsg("too few parameters specified for RAISE")));
  
! 			paramvalue = SPI_getbinval(estate->eval_tuptable->vals[0], 
! 									   estate->eval_tuptable->tupdesc,
! 									   param_idx + 1, &paramisnull);
! 			paramtypeid = SPI_gettypeid(estate->eval_tuptable->tupdesc, param_idx + 1);
! 
  			if (paramisnull)
  				extval = "<NULL>";
  			else
  				extval = convert_value_to_string(paramvalue, paramtypeid);
  			plpgsql_dstring_append(&ds, extval);
! 			param_idx++;
  			continue;
  		}
  
  		plpgsql_dstring_append_char(&ds, cp[0]);
  	}
  
+ 	exec_eval_cleanup(estate);
+ 
  	/*
  	 * If more parameters were specified than were required to process
  	 * the format string, throw an error
  	 */
! 	if (param_idx != params_count)
  		ereport(ERROR,
  				(errcode(ERRCODE_SYNTAX_ERROR),
  				 errmsg("too many parameters specified for RAISE")));
Index: src/pl/plpgsql/src/pl_funcs.c
===================================================================
RCS file: /var/lib/cvs/pgsql/src/pl/plpgsql/src/pl_funcs.c,v
retrieving revision 1.41
diff -c -r1.41 pl_funcs.c
*** src/pl/plpgsql/src/pl_funcs.c	10 Jun 2005 16:23:11 -0000	1.41
--- src/pl/plpgsql/src/pl_funcs.c	13 Jun 2005 05:57:17 -0000
***************
*** 883,894 ****
  static void
  dump_raise(PLpgSQL_stmt_raise *stmt)
  {
- 	ListCell *l;
- 
  	dump_ind();
  	printf("RAISE '%s'", stmt->message);
! 	foreach (l, stmt->params)
! 		printf(" %d", lfirst_int(l));
  	printf("\n");
  }
  
--- 883,891 ----
  static void
  dump_raise(PLpgSQL_stmt_raise *stmt)
  {
  	dump_ind();
  	printf("RAISE '%s'", stmt->message);
! 	dump_expr(stmt->params_expr);
  	printf("\n");
  }
  
Index: src/pl/plpgsql/src/plpgsql.h
===================================================================
RCS file: /var/lib/cvs/pgsql/src/pl/plpgsql/src/plpgsql.h,v
retrieving revision 1.62
diff -c -r1.62 plpgsql.h
*** src/pl/plpgsql/src/plpgsql.h	10 Jun 2005 16:23:11 -0000	1.62
--- src/pl/plpgsql/src/plpgsql.h	13 Jun 2005 05:38:55 -0000
***************
*** 515,521 ****
  	int			lineno;
  	int			elog_level;
  	char	   *message;
! 	List	   *params;
  } PLpgSQL_stmt_raise;
  
  
--- 515,521 ----
  	int			lineno;
  	int			elog_level;
  	char	   *message;
! 	PLpgSQL_expr  *params_expr;
  } PLpgSQL_stmt_raise;
  
  
Index: src/test/regress/expected/plpgsql.out
===================================================================
RCS file: /var/lib/cvs/pgsql/src/test/regress/expected/plpgsql.out,v
retrieving revision 1.33
diff -c -r1.33 plpgsql.out
*** src/test/regress/expected/plpgsql.out	10 Jun 2005 16:23:11 -0000	1.33
--- src/test/regress/expected/plpgsql.out	13 Jun 2005 06:28:26 -0000
***************
*** 2418,2444 ****
  --
  -- SQLSTATE and SQLERRM test
  --
- -- should fail: SQLSTATE and SQLERRM are only in defined EXCEPTION
- -- blocks
- create function excpt_test() returns void as $$
- begin
-     raise notice '% %', sqlstate, sqlerrm;
- end; $$ language plpgsql;
- ERROR:  syntax error at or near "sqlstate" at character 79
- LINE 3:     raise notice '% %', sqlstate, sqlerrm;
-                                 ^
- -- should fail
- create function excpt_test() returns void as $$
- begin
-     begin
-         begin
-     	    raise notice '% %', sqlstate, sqlerrm;
-         end;
-     end;
- end; $$ language plpgsql;
- ERROR:  syntax error at or near "sqlstate" at character 108
- LINE 5:          raise notice '% %', sqlstate, sqlerrm;
-                                      ^
  create function excpt_test() returns void as $$
  begin
      begin
--- 2418,2423 ----
***************
*** 2469,2471 ****
--- 2448,2468 ----
  (1 row)
  
  drop function excpt_test();
+ -- parameters of raise stmt can be expressions
+ create function raise_exprs() returns void as $$
+ declare
+     a integer[] = '{10,20,30}';
+     c varchar = 'xyz';
+     i integer;
+ begin
+     i := 2;
+     raise notice '%; %; %; %; %', a, a[i], c, (select c || 'abc'), row(10,'aaa',30);
+ end;$$ language plpgsql;
+ select raise_exprs();
+ NOTICE:  {10,20,30}; 20; xyz; xyzabc; (10,aaa,30)
+  raise_exprs 
+ -------------
+  
+ (1 row)
+ 
+ drop function raise_exprs();
Index: src/test/regress/sql/plpgsql.sql
===================================================================
RCS file: /var/lib/cvs/pgsql/src/test/regress/sql/plpgsql.sql,v
retrieving revision 1.28
diff -c -r1.28 plpgsql.sql
*** src/test/regress/sql/plpgsql.sql	10 Jun 2005 16:23:11 -0000	1.28
--- src/test/regress/sql/plpgsql.sql	13 Jun 2005 06:25:17 -0000
***************
*** 2054,2077 ****
  --
  -- SQLSTATE and SQLERRM test
  --
- 
- -- should fail: SQLSTATE and SQLERRM are only in defined EXCEPTION
- -- blocks
- create function excpt_test() returns void as $$
- begin
-     raise notice '% %', sqlstate, sqlerrm;
- end; $$ language plpgsql;
- 
- -- should fail
- create function excpt_test() returns void as $$
- begin
-     begin
-         begin
-     	    raise notice '% %', sqlstate, sqlerrm;
-         end;
-     end;
- end; $$ language plpgsql;
- 
  create function excpt_test() returns void as $$
  begin
      begin
--- 2054,2059 ----
***************
*** 2094,2096 ****
--- 2076,2092 ----
  
  select excpt_test();
  drop function excpt_test();
+ 
+ -- parameters of raise stmt can be expressions
+ create function raise_exprs() returns void as $$
+ declare
+     a integer[] = '{10,20,30}';
+     c varchar = 'xyz';
+     i integer;
+ begin
+     i := 2;
+     raise notice '%; %; %; %; %', a, a[i], c, (select c || 'abc'), row(10,'aaa',30);
+ end;$$ language plpgsql;
+ 
+ select raise_exprs();
+ drop function raise_exprs();
---------------------------(end of broadcast)---------------------------
TIP 8: explain analyze is your friend

Reply via email to