commit ccd75504ccc56b52e6c8774564cb0fac190381f8
Author: Böszörményi Zoltán <zboszor@pr.hu>
Date:   Wed Apr 16 10:18:40 2014 +0200

    ECPG: Modify the parameters of ECPGsetcommit() so it takes a bool
    instead of a string with the "on" / "off" values. This way the
    parser checks for the string value, not the runtime, making it
    less error-prone against hand-crafted C files.
    
    Also add a check to not execute BEGIN if the transaction has
    already failed. Extend the same check in ecpg_do_prologue() to
    match these two checks.

diff --git a/src/interfaces/ecpg/ecpglib/connect.c b/src/interfaces/ecpg/ecpglib/connect.c
index 0c4af66..a52d616 100644
--- a/src/interfaces/ecpg/ecpglib/connect.c
+++ b/src/interfaces/ecpg/ecpglib/connect.c
@@ -155,42 +155,47 @@ ecpg_finish(struct connection * act)
 			struct var_list *iv_ptr;
 
 			for (; ivlist; iv_ptr = ivlist, ivlist = ivlist->next, ecpg_free(iv_ptr));
 		}
 	}
 	else
 		ecpg_log("ecpg_finish: called an extra time\n");
 }
 
 bool
-ECPGsetcommit(int lineno, const char *mode, const char *connection_name)
+ECPGsetcommit(int lineno, const bool turn_on, const char *connection_name)
 {
 	struct connection *con = ecpg_get_connection(connection_name);
 	PGresult   *results;
 
 	if (!ecpg_init(con, connection_name, lineno))
 		return (false);
 
-	ecpg_log("ECPGsetcommit on line %d: action \"%s\"; connection \"%s\"\n", lineno, mode, con->name);
+	ecpg_log("ECPGsetcommit on line %d: action \"%s\"; connection \"%s\"\n", lineno, turn_on ? "on" : "off", con->name);
 
-	if (con->autocommit && strncmp(mode, "off", strlen("off")) == 0)
+	if (con->autocommit && !turn_on)
 	{
+		if (con->client_side_error || PQtransactionStatus(con->connection) == PQTRANS_INERROR)
+		{
+			ecpg_raise(lineno, ECPG_TRANS, ECPG_SQLSTATE_IN_FAILED_SQL_TRANSACTION, NULL);
+			return false;
+		}
 		if (PQtransactionStatus(con->connection) == PQTRANS_IDLE)
 		{
 			results = PQexec(con->connection, "begin transaction");
 			if (!ecpg_check_PQresult(results, lineno, con->connection, ECPG_COMPAT_PGSQL))
 				return false;
 			PQclear(results);
 		}
 		con->autocommit = false;
 	}
-	else if (!con->autocommit && strncmp(mode, "on", strlen("on")) == 0)
+	else if (!con->autocommit && turn_on)
 	{
 		if (PQtransactionStatus(con->connection) != PQTRANS_IDLE)
 		{
 			results = PQexec(con->connection, "commit");
 			if (!ecpg_check_PQresult(results, lineno, con->connection, ECPG_COMPAT_PGSQL))
 				return false;
 			PQclear(results);
 		}
 		con->autocommit = true;
 	}
diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index 499143a..5bc84af 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -1891,21 +1891,21 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
 #endif
 
 	con = ecpg_get_connection(connection_name);
 
 	if (!ecpg_init(con, connection_name, lineno))
 	{
 		ecpg_do_epilogue(stmt);
 		return false;
 	}
 
-	if (con->client_side_error)
+	if (con->client_side_error || PQtransactionStatus(con->connection) == PQTRANS_INERROR)
 	{
 		ecpg_do_epilogue(stmt);
 		ecpg_raise(lineno, ECPG_TRANS, ECPG_SQLSTATE_IN_FAILED_SQL_TRANSACTION, NULL);
 		return false;
 	}
 
 	/*
 	 * If statement type is ECPGst_prepnormal we are supposed to prepare the
 	 * statement before executing them
 	 */
diff --git a/src/interfaces/ecpg/include/ecpglib.h b/src/interfaces/ecpg/include/ecpglib.h
index 02f319d..1ac15d5 100644
--- a/src/interfaces/ecpg/include/ecpglib.h
+++ b/src/interfaces/ecpg/include/ecpglib.h
@@ -41,21 +41,21 @@ __attribute__((format_arg(1)));
 #define FALSE	0
 #endif   /* FALSE */
 
 #ifdef __cplusplus
 extern		"C"
 {
 #endif
 
 void		ECPGdebug(int, FILE *);
 bool		ECPGstatus(int, const char *);
-bool		ECPGsetcommit(int, const char *, const char *);
+bool		ECPGsetcommit(int, const bool, const char *);
 bool		ECPGsetconn(int, const char *);
 bool		ECPGconnect(int, int, const char *, const char *, const char *, const char *, int);
 bool		ECPGdo(const int, const int, const int, const char *, const bool, const int, const char *,...);
 bool		ECPGtrans(int, const char *, const char *, bool, bool, bool, const char *);
 bool		ECPGdisconnect(int, const char *);
 bool		ECPGprepare(int, const char *, const bool, const char *, const char *);
 bool		ECPGdeallocate(int, int, const char *, const char *);
 bool		ECPGdeallocate_all(int, int, const char *);
 char	   *ECPGprepared_statement(const char *, const char *, int);
 PGconn	   *ECPGget_PGconn(const char *);
diff --git a/src/interfaces/ecpg/preproc/ecpg.addons b/src/interfaces/ecpg/preproc/ecpg.addons
index ebc9b16..df85424 100644
--- a/src/interfaces/ecpg/preproc/ecpg.addons
+++ b/src/interfaces/ecpg/preproc/ecpg.addons
@@ -215,21 +215,21 @@ ECPG: stmtViewStmt rule
 
 		if ((ptr = add_additional_variables($1, true)) != NULL)
 		{
 			connection = ptr->connection ? mm_strdup(ptr->connection) : NULL;
 			output_open_statement(mm_strdup(ptr->command), 0, ECPGst_normal);
 			ptr->opened = true;
 		}
 	}
 	| ECPGSetAutocommit
 	{
-		fprintf(yyout, "{ ECPGsetcommit(__LINE__, \"%s\", %s);", $1, connection ? connection : "NULL");
+		fprintf(yyout, "{ ECPGsetcommit(__LINE__, %d, %s);", (strcmp($1, "on") == 0), connection ? connection : "NULL");
 		whenever_action(2);
 		free($1);
 	}
 	| ECPGSetConnection
 	{
 		if (connection)
 			mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in SET CONNECTION statement");
 
 		fprintf(yyout, "{ ECPGsetconn(__LINE__, %s);", $1);
 		whenever_action(2);
diff --git a/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.c b/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.c
index c139e41..5abbf4f 100644
--- a/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.c
+++ b/src/interfaces/ecpg/test/expected/pgtypeslib-num_test.c
@@ -54,21 +54,21 @@ main(void)
 #line 30 "num_test.pgc"
 
 
 	{ ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , NULL, 0); 
 #line 32 "num_test.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint ( );}
 #line 32 "num_test.pgc"
 
 
-	{ ECPGsetcommit(__LINE__, "off", NULL);
+	{ ECPGsetcommit(__LINE__, 0, NULL);
 #line 34 "num_test.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint ( );}
 #line 34 "num_test.pgc"
 
 	{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table test ( text char ( 5 ) , num numeric ( 14 , 7 ) )", ECPGt_EOIT, ECPGt_EORT);
 #line 35 "num_test.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint ( );}
 #line 35 "num_test.pgc"
diff --git a/src/interfaces/ecpg/test/expected/sql-array.c b/src/interfaces/ecpg/test/expected/sql-array.c
index f770c09..befa89f 100644
--- a/src/interfaces/ecpg/test/expected/sql-array.c
+++ b/src/interfaces/ecpg/test/expected/sql-array.c
@@ -134,21 +134,21 @@ main (void)
 
 	ECPGdebug(1, stderr);
 
         { ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , NULL, 0); 
 #line 27 "array.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
 #line 27 "array.pgc"
 
 
-	{ ECPGsetcommit(__LINE__, "on", NULL);
+	{ ECPGsetcommit(__LINE__, 1, NULL);
 #line 29 "array.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
 #line 29 "array.pgc"
 
 
 	{ ECPGtrans(__LINE__, NULL, "begin work", 0, 1, 0, NULL);
 #line 31 "array.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
diff --git a/src/interfaces/ecpg/test/expected/sql-func.c b/src/interfaces/ecpg/test/expected/sql-func.c
index 5d524b8..823c5b4 100644
--- a/src/interfaces/ecpg/test/expected/sql-func.c
+++ b/src/interfaces/ecpg/test/expected/sql-func.c
@@ -28,21 +28,21 @@ int main() {
  char text [ 25 ] ;
 
 #line 8 "func.pgc"
 
 
   ECPGdebug(1, stderr);
   { ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , NULL, 0); }
 #line 11 "func.pgc"
 
 
-  { ECPGsetcommit(__LINE__, "on", NULL);}
+  { ECPGsetcommit(__LINE__, 1, NULL);}
 #line 13 "func.pgc"
 
   /* exec sql whenever sql_warning  sqlprint ; */
 #line 14 "func.pgc"
 
   /* exec sql whenever sqlerror  sqlprint ; */
 #line 15 "func.pgc"
 
 
   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table My_Table ( Item1 int , Item2 text )", ECPGt_EOIT, ECPGt_EORT);
diff --git a/src/interfaces/ecpg/test/expected/sql-indicators.c b/src/interfaces/ecpg/test/expected/sql-indicators.c
index 22aacc1..168ccd4 100644
--- a/src/interfaces/ecpg/test/expected/sql-indicators.c
+++ b/src/interfaces/ecpg/test/expected/sql-indicators.c
@@ -104,21 +104,21 @@ int main()
  int nullind = - 1 ;
 /* exec sql end declare section */
 #line 11 "indicators.pgc"
 
 
 	ECPGdebug(1,stderr);
 
 	{ ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , NULL, 0); }
 #line 15 "indicators.pgc"
 
-	{ ECPGsetcommit(__LINE__, "off", NULL);}
+	{ ECPGsetcommit(__LINE__, 0, NULL);}
 #line 16 "indicators.pgc"
 
 
 	{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table indicator_test ( \"id\" int primary key , \"str\" text not null , val int null )", ECPGt_EOIT, ECPGt_EORT);}
 #line 21 "indicators.pgc"
 
 	{ ECPGtrans(__LINE__, NULL, "commit work", 0, 0, 0, NULL);}
 #line 22 "indicators.pgc"
 
 
diff --git a/src/interfaces/ecpg/test/expected/sql-parser.c b/src/interfaces/ecpg/test/expected/sql-parser.c
index 616135d..1d6c0d3 100644
--- a/src/interfaces/ecpg/test/expected/sql-parser.c
+++ b/src/interfaces/ecpg/test/expected/sql-parser.c
@@ -31,21 +31,21 @@ int main() {
  int item [ 3 ] , ind [ 3 ] , i ;
 /* exec sql end declare section */
 #line 11 "parser.pgc"
 
 
   ECPGdebug(1, stderr);
   { ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , NULL, 0); }
 #line 14 "parser.pgc"
 
 
-  { ECPGsetcommit(__LINE__, "on", NULL);}
+  { ECPGsetcommit(__LINE__, 1, NULL);}
 #line 16 "parser.pgc"
 
   /* exec sql whenever sql_warning  sqlprint ; */
 #line 17 "parser.pgc"
 
   /* exec sql whenever sqlerror  sqlprint ; */
 #line 18 "parser.pgc"
 
 
   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table T ( Item1 int , Item2 int )", ECPGt_EOIT, ECPGt_EORT);
diff --git a/src/interfaces/ecpg/test/expected/sql-quote.c b/src/interfaces/ecpg/test/expected/sql-quote.c
index 6c4d84f..bfb75ca 100644
--- a/src/interfaces/ecpg/test/expected/sql-quote.c
+++ b/src/interfaces/ecpg/test/expected/sql-quote.c
@@ -34,21 +34,21 @@ int main() {
  int i ;
 /* exec sql end declare section */
 #line 11 "quote.pgc"
 
 
   ECPGdebug(1, stderr);
   { ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , NULL, 0); }
 #line 14 "quote.pgc"
 
 
-  { ECPGsetcommit(__LINE__, "on", NULL);}
+  { ECPGsetcommit(__LINE__, 1, NULL);}
 #line 16 "quote.pgc"
 
   /* exec sql whenever sql_warning  sqlprint ; */
 #line 17 "quote.pgc"
 
   /* exec sql whenever sqlerror  sqlprint ; */
 #line 18 "quote.pgc"
 
 
   { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table \"My_Table\" ( Item1 int , Item2 text )", ECPGt_EOIT, ECPGt_EORT);
diff --git a/src/interfaces/ecpg/test/expected/thread-alloc.c b/src/interfaces/ecpg/test/expected/thread-alloc.c
index 199a77e..c74ea26 100644
--- a/src/interfaces/ecpg/test/expected/thread-alloc.c
+++ b/src/interfaces/ecpg/test/expected/thread-alloc.c
@@ -146,21 +146,21 @@ static void* fn(void* arg)
 
 	value = (long)arg;
 	sprintf(name, "Connection: %d", value);
 
 	{ ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , name, 0); 
 #line 47 "alloc.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
 #line 47 "alloc.pgc"
 
-	{ ECPGsetcommit(__LINE__, "on", NULL);
+	{ ECPGsetcommit(__LINE__, 1, NULL);
 #line 48 "alloc.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
 #line 48 "alloc.pgc"
 
 	for (i = 1; i <= REPEATS; ++i)
 	{
 		{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select relname from pg_class where relname = 'pg_class'", ECPGt_EOIT, 
 	ECPGt_char,&(r),(long)0,(long)0,(1)*sizeof(char), 
 	ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
diff --git a/src/interfaces/ecpg/test/expected/thread-prep.c b/src/interfaces/ecpg/test/expected/thread-prep.c
index cd28c85..3a559ce 100644
--- a/src/interfaces/ecpg/test/expected/thread-prep.c
+++ b/src/interfaces/ecpg/test/expected/thread-prep.c
@@ -146,21 +146,21 @@ static void* fn(void* arg)
 
 	value = (long)arg;
 	sprintf(name, "Connection: %d", value);
 
 	{ ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , name, 0); 
 #line 47 "prep.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
 #line 47 "prep.pgc"
 
-	{ ECPGsetcommit(__LINE__, "on", NULL);
+	{ ECPGsetcommit(__LINE__, 1, NULL);
 #line 48 "prep.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
 #line 48 "prep.pgc"
 
 	for (i = 1; i <= REPEATS; ++i)
 	{
 		{ ECPGprepare(__LINE__, NULL, 0, "i", query);
 #line 51 "prep.pgc"
 
@@ -203,21 +203,21 @@ int main ()
 #else
 	pthread_t threads[THREADS];
 #endif
 
 	{ ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , NULL, 0); 
 #line 69 "prep.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
 #line 69 "prep.pgc"
 
-	{ ECPGsetcommit(__LINE__, "on", NULL);
+	{ ECPGsetcommit(__LINE__, 1, NULL);
 #line 70 "prep.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
 #line 70 "prep.pgc"
 
 	{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table if exists T", ECPGt_EOIT, ECPGt_EORT);
 #line 71 "prep.pgc"
 
 if (sqlca.sqlcode < 0) sqlprint();}
 #line 71 "prep.pgc"
