From 399da7d882dff22b7ad926fb07aafeda2feab999 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri, 25 Jun 2010 16:40:13 +0000
Subject: [PATCH] Fix thinko in tok_is_keyword(): it was looking at the wrong
 union variant of YYSTYPE, and hence returning the wrong answer for cases
 where a plpgsql "unreserved keyword" really does conflict with a variable
 name.  Obviously I didn't test this enough :-(.  Per bug #5524 from Peter
 Gagarinov.

---
 src/pl/plpgsql/src/gram.y             |  6 +++---
 src/test/regress/expected/plpgsql.out | 14 ++++++++++++++
 src/test/regress/sql/plpgsql.sql      | 14 ++++++++++++++
 3 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y
index e866d10a65a..3a78fe69c75 100644
--- a/src/pl/plpgsql/src/gram.y
+++ b/src/pl/plpgsql/src/gram.y
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.142 2010/03/03 01:53:17 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.143 2010/06/25 16:40:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2080,8 +2080,8 @@ tok_is_keyword(int token, union YYSTYPE *lval,
 		 * match composite names (hence an unreserved word followed by "."
 		 * will not be recognized).
 		 */
-		if (!lval->word.quoted && lval->word.ident != NULL &&
-			strcmp(lval->word.ident, kw_str) == 0)
+		if (!lval->wdatum.quoted && lval->wdatum.ident != NULL &&
+			strcmp(lval->wdatum.ident, kw_str) == 0)
 			return true;
 	}
 	return false;				/* not the keyword */
diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out
index 619939ffa38..a22e2bfd0f1 100644
--- a/src/test/regress/expected/plpgsql.out
+++ b/src/test/regress/expected/plpgsql.out
@@ -3578,6 +3578,20 @@ $$ language plpgsql;
 select raise_test();
 ERROR:  RAISE without parameters cannot be used outside an exception handler
 CONTEXT:  PL/pgSQL function "raise_test"
+-- check cases where implicit SQLSTATE variable could be confused with
+-- SQLSTATE as a keyword, cf bug #5524
+create or replace function raise_test() returns void as $$
+begin
+  perform 1/0;
+exception
+  when sqlstate '22012' then
+    raise notice using message = sqlstate;
+    raise sqlstate '22012' using message = 'substitute message';
+end;
+$$ language plpgsql;
+select raise_test();
+NOTICE:  22012
+ERROR:  substitute message
 drop function raise_test();
 -- test CASE statement
 create or replace function case_test(bigint) returns text as $$
diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql
index e181b10898e..612e92d21be 100644
--- a/src/test/regress/sql/plpgsql.sql
+++ b/src/test/regress/sql/plpgsql.sql
@@ -2916,6 +2916,20 @@ $$ language plpgsql;
 
 select raise_test();
 
+-- check cases where implicit SQLSTATE variable could be confused with
+-- SQLSTATE as a keyword, cf bug #5524
+create or replace function raise_test() returns void as $$
+begin
+  perform 1/0;
+exception
+  when sqlstate '22012' then
+    raise notice using message = sqlstate;
+    raise sqlstate '22012' using message = 'substitute message';
+end;
+$$ language plpgsql;
+
+select raise_test();
+
 drop function raise_test();
 
 -- test CASE statement
-- 
GitLab