diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
index c043c78fea3efb3ddf8ded119967a3be8b28067f..13897275278748b1dfc0d1ea3a498dc83df33196 100644
--- a/doc/src/sgml/plpgsql.sgml
+++ b/doc/src/sgml/plpgsql.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.71 2005/06/10 16:23:09 neilc Exp $
+$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.72 2005/06/14 06:43:14 neilc Exp $
 -->
 
 <chapter id="plpgsql"> 
@@ -2533,9 +2533,9 @@ RAISE <replaceable class="parameter">level</replaceable> '<replaceable class="pa
    <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.
+    <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>
 
    <!--
diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y
index 48164d983b5586059cae992763e27c3d2e28638a..e8350686eee3f2cb7897e0b00429e2d8d9b5dbec 100644
--- a/src/pl/plpgsql/src/gram.y
+++ b/src/pl/plpgsql/src/gram.y
@@ -4,7 +4,7 @@
  *						  procedural language
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.75 2005/06/10 16:23:11 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.76 2005/06/14 06:43:14 neilc Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -135,8 +135,8 @@ static	void			 plpgsql_sql_error_callback(void *arg);
 %type <exception>	proc_exception
 %type <condition>	proc_conditions
 
-%type <list>	raise_params
-%type <ival>	raise_level raise_param
+
+%type <ival>	raise_level
 %type <str>		raise_msg
 
 %type <list>	getdiag_list
@@ -1157,9 +1157,10 @@ stmt_return_next: K_RETURN_NEXT lno
 					}
 				;
 
-stmt_raise		: K_RAISE lno raise_level raise_msg raise_params ';'
+stmt_raise		: K_RAISE lno raise_level raise_msg
 					{
 						PLpgSQL_stmt_raise		*new;
+						int	tok;
 
 						new = palloc(sizeof(PLpgSQL_stmt_raise));
 
@@ -1167,21 +1168,33 @@ stmt_raise		: K_RAISE lno raise_level raise_msg raise_params ';'
 						new->lineno		= $2;
 						new->elog_level = $3;
 						new->message	= $4;
-						new->params		= $5;
+						new->params		= NIL;
 
-						$$ = (PLpgSQL_stmt *)new;
-					}
-				| K_RAISE lno raise_level raise_msg ';'
-					{
-						PLpgSQL_stmt_raise		*new;
+						tok = yylex();
 
-						new = palloc(sizeof(PLpgSQL_stmt_raise));
+						/*
+						 * We expect either a semi-colon, which
+						 * indicates no parameters, or a comma that
+						 * begins the list of parameter expressions
+						 */
+						if (tok != ',' && tok != ';')
+							yyerror("syntax error");
 
-						new->cmd_type	= PLPGSQL_STMT_RAISE;
-						new->lineno		= $2;
-						new->elog_level = $3;
-						new->message	= $4;
-						new->params		= NIL;
+						if (tok == ',')
+						{
+							PLpgSQL_expr *expr;
+							int term;
+
+							for (;;)
+							{
+								expr = read_sql_construct(',', ';', ", or ;",
+														  "SELECT ",
+														  true, true, &term);
+								new->params = lappend(new->params, expr);
+								if (term == ';')
+									break;
+							}
+						}
 
 						$$ = (PLpgSQL_stmt *)new;
 					}
@@ -1219,22 +1232,6 @@ raise_level		: K_EXCEPTION
 					}
 				;
 
-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; }
 				;
@@ -1658,7 +1655,7 @@ read_sql_stmt(const char *sqlstart)
  * expected:	text to use in complaining that terminator was not found
  * sqlstart:	text to prefix to the accumulated SQL text
  * isexpression: whether to say we're reading an "expression" or a "statement"
- * valid_sql:   whether to check the syntax of the expression (plus sqlstart)
+ * valid_sql:   whether to check the syntax of the expr (prefixed with sqlstart)
  * endtoken:	if not NULL, ending token is stored at *endtoken
  *				(this is only interesting if until2 isn't zero)
  */
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index ae5f7473146c1bfefcb5663a6289bc268d4a845d..a2a1f7cb6b0d8e13838023e1eb86d8accbbb8753 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -3,7 +3,7 @@
  *			  procedural language
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.143 2005/06/10 16:23:11 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.144 2005/06/14 06:43:14 neilc Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -594,7 +594,7 @@ plpgsql_exec_trigger(PLpgSQL_function *func,
 	error_context_stack = plerrcontext.previous;
 
 	/*
-	 * Return the triggers result
+	 * Return the trigger's result
 	 */
 	return rettup;
 }
@@ -1095,22 +1095,9 @@ static int
 exec_stmt_perform(PLpgSQL_execstate *estate, PLpgSQL_stmt_perform *stmt)
 {
 	PLpgSQL_expr *expr = stmt->expr;
-	int			rc;
-
-	/*
-	 * If not already done create a plan for this expression
-	 */
-	if (expr->plan == NULL)
-		exec_prepare_plan(estate, expr);
-
-	rc = exec_run_select(estate, expr, 0, NULL);
-	if (rc != SPI_OK_SELECT)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-			   errmsg("query \"%s\" did not return data", expr->query)));
 
+	(void) exec_run_select(estate, expr, 0, NULL);
 	exec_set_found(estate, (estate->eval_processed != 0));
-
 	exec_eval_cleanup(estate);
 
 	return PLPGSQL_RC_OK;
@@ -1941,15 +1928,18 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
 						(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);
+			paramvalue = exec_eval_expr(estate,
+										(PLpgSQL_expr *) lfirst(current_param),
+										&paramisnull,
+										&paramtypeid);
+
 			if (paramisnull)
 				extval = "<NULL>";
 			else
 				extval = convert_value_to_string(paramvalue, paramtypeid);
 			plpgsql_dstring_append(&ds, extval);
 			current_param = lnext(current_param);
+			exec_eval_cleanup(estate);
 			continue;
 		}
 
diff --git a/src/pl/plpgsql/src/pl_funcs.c b/src/pl/plpgsql/src/pl_funcs.c
index 21d8d9b7f7d8bd2ccbf01cd1e2e593ecd4e0e409..553eef7c49ca505aeb19bece78e1b1cbd355c7df 100644
--- a/src/pl/plpgsql/src/pl_funcs.c
+++ b/src/pl/plpgsql/src/pl_funcs.c
@@ -3,7 +3,7 @@
  *			  procedural language
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.42 2005/06/14 00:10:02 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.43 2005/06/14 06:43:14 neilc Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -885,13 +885,20 @@ dump_return_next(PLpgSQL_stmt_return_next *stmt)
 static void
 dump_raise(PLpgSQL_stmt_raise *stmt)
 {
-	ListCell *l;
+	ListCell *lc;
+	int i = 0;
 
 	dump_ind();
-	printf("RAISE '%s'", stmt->message);
-	foreach (l, stmt->params)
-		printf(" %d", lfirst_int(l));
-	printf("\n");
+	printf("RAISE '%s'\n", stmt->message);
+	dump_indent += 2;
+	foreach (lc, stmt->params)
+	{
+		dump_ind();
+		printf("    parameter %d: ", i++);
+		dump_expr((PLpgSQL_expr *) lfirst(lc));
+		printf("\n");
+	}
+	dump_indent -= 2;
 }
 
 static void
@@ -916,7 +923,8 @@ dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt)
 	{
 		dump_ind();
 		printf("    target = %d %s\n", stmt->rec->recno, stmt->rec->refname);
-	} else if (stmt->row != NULL)
+	}
+	else if (stmt->row != NULL)
 	{
 		dump_ind();
 		printf("    target = %d %s\n", stmt->row->rowno, stmt->row->refname);
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index 580439c88c5682720e2c364ee022c478f93d997d..a724df67963b45808622af67c13032379f7623ab 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -3,7 +3,7 @@
  *			  procedural language
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.62 2005/06/10 16:23:11 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.63 2005/06/14 06:43:14 neilc Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -515,7 +515,7 @@ typedef struct
 	int			lineno;
 	int			elog_level;
 	char	   *message;
-	List	   *params;
+	List	   *params;			/* list of expressions */
 } PLpgSQL_stmt_raise;
 
 
diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out
index 2650cbb908a55dbd22d13c03b65b21ec70a89742..21101958ab4366c865e0d7353af5e8a08677857c 100644
--- a/src/test/regress/expected/plpgsql.out
+++ b/src/test/regress/expected/plpgsql.out
@@ -2418,17 +2418,17 @@ drop type eitype cascade;
 --
 -- SQLSTATE and SQLERRM test
 --
--- should fail: SQLSTATE and SQLERRM are only in defined EXCEPTION
--- blocks
-create function excpt_test() returns void as $$
+create function excpt_test1() 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 $$
+-- should fail: SQLSTATE and SQLERRM are only in defined EXCEPTION
+-- blocks
+select excpt_test1();
+ERROR:  column "sqlstate" does not exist
+CONTEXT:  SQL statement "SELECT  sqlstate"
+PL/pgSQL function "excpt_test1" line 2 at raise
+create function excpt_test2() returns void as $$
 begin
     begin
         begin
@@ -2436,10 +2436,12 @@ begin
         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 $$
+-- should fail
+select excpt_test2();
+ERROR:  column "sqlstate" does not exist
+CONTEXT:  SQL statement "SELECT  sqlstate"
+PL/pgSQL function "excpt_test2" line 4 at raise
+create function excpt_test3() returns void as $$
 begin
     begin
     	raise exception 'user exception';
@@ -2458,14 +2460,34 @@ begin
 	    raise notice '% %', sqlstate, sqlerrm;
     end;
 end; $$ language plpgsql;
-select excpt_test();
+select excpt_test3();
 NOTICE:  caught exception P0001 user exception
 NOTICE:  P0001 user exception
 NOTICE:  caught exception 22012 division by zero
 NOTICE:  P0001 user exception
- excpt_test 
-------------
+ excpt_test3 
+-------------
+ 
+(1 row)
+
+drop function excpt_test1();
+drop function excpt_test2();
+drop function excpt_test3();
+-- 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',NULL,30), NULL;
+end;$$ language plpgsql;
+select raise_exprs();
+NOTICE:  {10,20,30}; 20; xyz; xyzabc; (10,aaa,,30); <NULL>
+ raise_exprs 
+-------------
  
 (1 row)
 
-drop function excpt_test();
+drop function raise_exprs();
diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql
index 9dc00f2f1e5b7b15103d0d4b4bb3a69d62b0b39b..375eef8959cdc88006acb92822d45b90aeaeed55 100644
--- a/src/test/regress/sql/plpgsql.sql
+++ b/src/test/regress/sql/plpgsql.sql
@@ -2055,15 +2055,15 @@ drop type eitype cascade;
 -- SQLSTATE and SQLERRM test
 --
 
--- should fail: SQLSTATE and SQLERRM are only in defined EXCEPTION
--- blocks
-create function excpt_test() returns void as $$
+create function excpt_test1() returns void as $$
 begin
     raise notice '% %', sqlstate, sqlerrm;
 end; $$ language plpgsql;
+-- should fail: SQLSTATE and SQLERRM are only in defined EXCEPTION
+-- blocks
+select excpt_test1();
 
--- should fail
-create function excpt_test() returns void as $$
+create function excpt_test2() returns void as $$
 begin
     begin
         begin
@@ -2071,8 +2071,10 @@ begin
         end;
     end;
 end; $$ language plpgsql;
+-- should fail
+select excpt_test2();
 
-create function excpt_test() returns void as $$
+create function excpt_test3() returns void as $$
 begin
     begin
     	raise exception 'user exception';
@@ -2092,5 +2094,21 @@ begin
     end;
 end; $$ language plpgsql;
 
-select excpt_test();
-drop function excpt_test();
+select excpt_test3();
+drop function excpt_test1();
+drop function excpt_test2();
+drop function excpt_test3();
+
+-- 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',NULL,30), NULL;
+end;$$ language plpgsql;
+
+select raise_exprs();
+drop function raise_exprs();