From e91600d1c2e79914e6c8ac445c340e704c710b66 Mon Sep 17 00:00:00 2001
From: Michael Meskes <meskes@postgresql.org>
Date: Fri, 18 Aug 2006 15:59:35 +0000
Subject: [PATCH] Changed lexer to no longer use the default rule. Synced
 parser and keyword list. Fixed parsing of CONNECT statement so it accepts a C
 string again.

---
 src/interfaces/ecpg/ChangeLog                 |  6 +++
 src/interfaces/ecpg/preproc/keywords.c        |  3 +-
 src/interfaces/ecpg/preproc/pgc.l             | 46 +++++++++----------
 src/interfaces/ecpg/preproc/preproc.y         | 42 +++++++++--------
 src/interfaces/ecpg/test/connect/test3.pgc    |  2 +-
 .../ecpg/test/expected/connect-test3.c        |  2 +-
 6 files changed, 55 insertions(+), 46 deletions(-)

diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog
index bf1e305a8a..af7420b3b2 100644
--- a/src/interfaces/ecpg/ChangeLog
+++ b/src/interfaces/ecpg/ChangeLog
@@ -2095,5 +2095,11 @@ Mo Aug 14 10:39:59 CEST 2006
 	- Fixed broken newline on Windows.
 	- Fixed a nasty buffer underrun that only occured when using Informix
 	  no_indicator NULL setting on timestamps and intervals.
+
+Fr 18. Aug 17:32:54 CEST 2006
+
+	- Changed lexer to no longer use the default rule.
+	- Synced parser and keyword list.
+	- Fixed parsing of CONNECT statement so it accepts a C string again.
 	- Set ecpg library version to 5.2.
 	- Set ecpg version to 4.2.1.
diff --git a/src/interfaces/ecpg/preproc/keywords.c b/src/interfaces/ecpg/preproc/keywords.c
index a1879c9973..3fd8d6d236 100644
--- a/src/interfaces/ecpg/preproc/keywords.c
+++ b/src/interfaces/ecpg/preproc/keywords.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.74 2006/08/02 13:43:23 meskes Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.75 2006/08/18 15:59:35 meskes Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -277,6 +277,7 @@ static ScanKeyword ScanKeywords[] = {
 	{"reset", RESET},
 	{"restart", RESTART},
 	{"restrict", RESTRICT},
+	{"returning", RETURNING},
 	{"returns", RETURNS},
 	{"revoke", REVOKE},
 	{"right", RIGHT},
diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
index 5dff416f6b..e9f87fe183 100644
--- a/src/interfaces/ecpg/preproc/pgc.l
+++ b/src/interfaces/ecpg/preproc/pgc.l
@@ -12,7 +12,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.148 2006/08/02 13:43:23 meskes Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.149 2006/08/18 15:59:35 meskes Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -79,7 +79,7 @@ static struct _if_value
 
 %option yylineno
 
-%s C SQL incl def def_ident undef 
+%x C SQL incl def def_ident undef 
 
 /*
  * OK, here is a short description of lex/flex rules behavior.
@@ -109,7 +109,6 @@ static struct _if_value
 %x xe
 %x xq
 %x xdolq
-%x xpre
 %x xcond
 %x xskip
 
@@ -327,7 +326,7 @@ cppline			{space}*#(.*\\{space})*.*{newline}
 
 <SQL>{whitespace}	{ /* ignore */ }
 
-{xcstart}		{
+<C,SQL>{xcstart}		{
 					token_start = yytext;
 					state_before = YYSTATE;
 					xcdepth = 0;
@@ -545,7 +544,7 @@ cppline			{space}*#(.*\\{space})*.*{newline}
 					   * This is not an EOL marker.
 					   */
 					  if (yytext[0] == ';' && struct_level == 0)
-						 BEGIN C;
+						 BEGIN(C);
 					  return yytext[0];
 					}
 <SQL>{operator}		{
@@ -720,12 +719,12 @@ cppline			{space}*#(.*\\{space})*.*{newline}
 						}
 					}
 <SQL>{other}		{ return yytext[0]; }
-<C>{exec_sql}		{ BEGIN SQL; return SQL_START; }
+<C>{exec_sql}		{ BEGIN(SQL); return SQL_START; }
 <C>{informix_special}	{ 
 						/* are we simulating Informix? */
 						if (INFORMIX_MODE)
 						{
-							BEGIN SQL;
+							BEGIN(SQL);
 							return SQL_START;
 						}
 						else
@@ -896,7 +895,7 @@ cppline			{space}*#(.*\\{space})*.*{newline}
 
 					BEGIN(C);
 				}
-<undef>{other}  		{
+<undef>{other}|\n  		{
 		                	mmerror(PARSE_ERROR, ET_FATAL, "Missing identifier in 'EXEC SQL UNDEF' command");
 			                yyterminate();
 				}
@@ -1077,24 +1076,24 @@ cppline			{space}*#(.*\\{space})*.*{newline}
 					}
 
 					if (stacked_if_value[preproc_tos].condition)
-						BEGIN C;
+						BEGIN(C);
 					else
 						BEGIN(xskip);
 				}
 
-<xcond>{other}	{
-			mmerror(PARSE_ERROR, ET_FATAL, "Missing identifier in 'EXEC SQL IFDEF' command");
-			yyterminate();
-		}
+<xcond>{other}|\n	{
+				mmerror(PARSE_ERROR, ET_FATAL, "Missing identifier in 'EXEC SQL IFDEF' command");
+				yyterminate();
+			}
 <def_ident>{identifier} {
 				old = mm_strdup(yytext);
 				BEGIN(def);
 				startlit();
 			}
-<def_ident>{other}	{
-			mmerror(PARSE_ERROR, ET_FATAL, "Missing identifier in 'EXEC SQL DEFINE' command");
-			yyterminate();
-		}
+<def_ident>{other}|\n	{
+				mmerror(PARSE_ERROR, ET_FATAL, "Missing identifier in 'EXEC SQL DEFINE' command");
+				yyterminate();
+			}	
 <def>{space}*";"	{
 						struct _defines *ptr, *this;
 
@@ -1124,10 +1123,10 @@ cppline			{space}*#(.*\\{space})*.*{newline}
 <incl>\<[^\>]+\>{space}*";"?		{	parse_include(); }
 <incl>{dquote}{xdinside}{dquote}{space}*";"?	{	parse_include(); }
 <incl>[^;\<\>\"]+";"		{ parse_include(); }
-<incl>{other}	{
-			mmerror(PARSE_ERROR, ET_FATAL, "Incorrect 'EXEC SQL INCLUDE' command");
-			yyterminate();
-		}
+<incl>{other}|\n		{
+					mmerror(PARSE_ERROR, ET_FATAL, "Incorrect 'EXEC SQL INCLUDE' command");
+					yyterminate();
+				}
 
 <<EOF>>				{
 			  		if (yy_buffer == NULL)
@@ -1174,6 +1173,7 @@ cppline			{space}*#(.*\\{space})*.*{newline}
 						
 			  		}
 				}
+<INITIAL>{other}|\n     	{ mmerror(PARSE_ERROR, ET_FATAL, "Internal error: unreachable state, please inform pgsql-bugs@postgresql.org"); }
 %%
 void
 lex_init(void)
@@ -1194,7 +1194,7 @@ lex_init(void)
 	}
 	startlit();
 
-	BEGIN C;
+	BEGIN(C);
 }
 
 static void
@@ -1318,7 +1318,7 @@ parse_include(void)
 	yylineno = 1;
 	output_line_number();
 
-  	BEGIN C;
+  	BEGIN(C);
 }
 
 static void
diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y
index ae14e1973a..8824de58d2 100644
--- a/src/interfaces/ecpg/preproc/preproc.y
+++ b/src/interfaces/ecpg/preproc/preproc.y
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.328 2006/08/08 11:51:24 meskes Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.329 2006/08/18 15:59:35 meskes Exp $ */
 
 /* Copyright comment */
 %{
@@ -407,7 +407,7 @@ add_additional_variables(char *name, bool insert)
 	QUOTE
 
 	READ REAL REASSIGN RECHECK REFERENCES REINDEX RELATIVE_P RELEASE RENAME
-	REPEATABLE REPLACE RESET RESTART RESTRICT RETURNS REVOKE RIGHT
+	REPEATABLE REPLACE RESET RESTART RESTRICT RETURNING RETURNS REVOKE RIGHT
 	ROLE ROLLBACK ROW ROWS RULE
 
 	SAVEPOINT SCHEMA SCROLL SECOND_P SECURITY SELECT SEQUENCE
@@ -497,7 +497,7 @@ add_additional_variables(char *name, bool insert)
 %type  <str>	columnList DeleteStmt UpdateStmt DeclareCursorStmt
 %type  <str>	NotifyStmt columnElem UnlistenStmt TableElement
 %type  <str>	copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary
-%type  <str>	FetchStmt from_in CreateOpClassStmt 
+%type  <str>	FetchStmt from_in CreateOpClassStmt returning_clause
 %type  <str>	ClosePortalStmt DropStmt VacuumStmt AnalyzeStmt opt_verbose
 %type  <str>	opt_full func_arg OptWith opt_freeze alter_table_cmd
 %type  <str>	analyze_keyword opt_name_list ExplainStmt index_params
@@ -3090,8 +3090,8 @@ DeallocateStmt: DEALLOCATE name		{ $$ = cat2_str(make_str("deallocate"), $2); }
  *
  *****************************************************************************/
 
-InsertStmt:  INSERT INTO qualified_name insert_rest
-			{ $$ = cat_str(3, make_str("insert into"), $3, $4); }
+InsertStmt:  INSERT INTO qualified_name insert_rest returning_clause
+			{ $$ = cat_str(4, make_str("insert into"), $3, $4, $5); }
 		;
 
 insert_rest:  
@@ -3113,6 +3113,9 @@ insert_column_item:  ColId opt_indirection
 			{ $$ = cat2_str($1, $2); }
 		;
 
+returning_clause:  RETURNING target_list	{ $$ = cat2_str(make_str("returning"), $2); }
+		| /* EMPTY */			{ $$ = EMPTY; }
+		;
 
 /*****************************************************************************
  *
@@ -3121,8 +3124,8 @@ insert_column_item:  ColId opt_indirection
  *
  *****************************************************************************/
 
-DeleteStmt:  DELETE_P FROM relation_expr_opt_alias using_clause where_clause
-			{ $$ = cat_str(4, make_str("delete from"), $3, $4, $5); }
+DeleteStmt:  DELETE_P FROM relation_expr_opt_alias using_clause where_clause returning_clause
+			{ $$ = cat_str(5, make_str("delete from"), $3, $4, $5, $6); }
 		;
 
 using_clause: USING from_list	{ cat2_str(make_str("using"), $2); }
@@ -3164,7 +3167,8 @@ UpdateStmt:  UPDATE relation_expr_opt_alias
 				SET update_target_list
 				from_clause
 				where_clause
-			{$$ = cat_str(6, make_str("update"), $2, make_str("set"), $4, $5, $6); }
+				returning_clause
+			{$$ = cat_str(7, make_str("update"), $2, make_str("set"), $4, $5, $6, $7); }
 		;
 
 
@@ -4615,8 +4619,12 @@ connection_target: database_name opt_server opt_port
 			/* old style: dbname[@server][:port] */
 			if (strlen($2) > 0 && *($2) != '@')
 				mmerror(PARSE_ERROR, ET_ERROR, "Expected '@', found '%s'", $2);
-
-			$$ = make3_str(make_str("\""), make3_str($1, $2, $3), make_str("\""));
+			
+			/* C strings need to be handled differently */
+			if ($1[0] == '\"')
+				$$ = $1;
+			else
+				$$ = make3_str(make_str("\""), make3_str($1, $2, $3), make_str("\""));
 		}
 		|  db_prefix ':' server opt_port '/' database_name opt_options
 		{
@@ -4634,13 +4642,6 @@ connection_target: database_name opt_server opt_port
 
 			$$ = make3_str(make3_str(make_str("\""), $1, make_str(":")), $3, make3_str(make3_str($4, make_str("/"), $6),	$7, make_str("\"")));
 		}
-		| Sconst
-		{
-			if ($1[0] == '\"')
-				$$ = $1;
-			else
-				$$ = make3_str(make_str("\""), $1, make_str("\""));
-		}
 		| char_variable
 		{
 			$$ = $1;
@@ -6509,9 +6510,10 @@ reserved_keyword:
 		| OR				{ $$ = make_str("or"); }
 		| ORDER				{ $$ = make_str("order"); }
 		| PRIMARY			{ $$ = make_str("primary"); }
-		| REFERENCES		{ $$ = make_str("references"); }
+		| REFERENCES			{ $$ = make_str("references"); }
+		| RETURNING			{ $$ = make_str("returning"); }
 		| SELECT			{ $$ = make_str("select"); }
-		| SESSION_USER		{ $$ = make_str("session_user"); }
+		| SESSION_USER			{ $$ = make_str("session_user"); }
 		| SOME				{ $$ = make_str("some"); }
 		| SYMMETRIC			{ $$ = make_str("symmetric"); }
 		| TABLE				{ $$ = make_str("table"); }
@@ -6604,7 +6606,7 @@ cvariable:	CVARIABLE
 		}
 		;
 ident: IDENT				{ $$ = $1; }
-		| CSTRING			{ $$ = make3_str(make_str("\""), $1, make_str("\"")); }
+		| CSTRING		{ $$ = make3_str(make_str("\""), $1, make_str("\"")); }
 		;
 
 quoted_ident_stringvar: name
diff --git a/src/interfaces/ecpg/test/connect/test3.pgc b/src/interfaces/ecpg/test/connect/test3.pgc
index 9910cb1b0c..40c866f1fb 100644
--- a/src/interfaces/ecpg/test/connect/test3.pgc
+++ b/src/interfaces/ecpg/test/connect/test3.pgc
@@ -34,7 +34,7 @@ exec sql end declare section;
 	/* will close "second" */
 	exec sql disconnect DEFAULT;
 
-	exec sql connect to REGRESSDB1 as second;
+	exec sql connect to "connectdb" as second;
 	exec sql disconnect ALL;
 
 	exec sql disconnect CURRENT;
diff --git a/src/interfaces/ecpg/test/expected/connect-test3.c b/src/interfaces/ecpg/test/expected/connect-test3.c
index 62a3cd6809..32d24bedf4 100644
--- a/src/interfaces/ecpg/test/expected/connect-test3.c
+++ b/src/interfaces/ecpg/test/expected/connect-test3.c
@@ -78,7 +78,7 @@ main(void)
 #line 35 "test3.pgc"
 
 
-	{ ECPGconnect(__LINE__, 0, "regress1" , NULL,NULL , "second", 0); }
+	{ ECPGconnect(__LINE__, 0, "connectdb" , NULL,NULL , "second", 0); }
 #line 37 "test3.pgc"
 
 	{ ECPGdisconnect(__LINE__, "ALL");}
-- 
2.40.0