commit 0ee438401c8e339912cc693ed9f140ad8c13bd95
Author: Böszörményi Zoltán <zb@cybertec.at>
Date:   Wed Dec 4 14:14:46 2013 +0100

    ECPG: Split ecpg_execute() up into 4 pieces: ecpg_build_params(),
    ecpg_autostart_transaction(), a smaller ecpg_execute() and
    ecpg_process_output().

diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index e3a44f7..00327db 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -1125,17 +1125,17 @@ insert_tobeinserted(int position, int ph_len, struct statement * stmt, char *tob
 	return true;
 }
 
-static bool
-ecpg_execute(struct statement * stmt)
+/*
+ * ecpg_build_params
+ *	Build statement parameters from user variables into
+ *	an array of strings for PQexecParams().
+ */
+bool
+ecpg_build_params(struct statement * stmt)
 {
-	bool		status = false;
-	char	   *cmdstat;
-	PGnotify   *notify;
 	struct variable *var;
 	int			desc_counter = 0;
 	int			position = 0;
-	struct sqlca_t *sqlca = ECPGget_sqlca();
-	bool		clear_result = true;
 
 	/*
 	 * If the type is one of the fill in types then we take the argument and
@@ -1421,8 +1421,17 @@ ecpg_execute(struct statement * stmt)
 		return false;
 	}
 
-	/* The request has been build. */
+	return true;
+}
 
+/*
+ * ecpg_autostart_transaction
+ *	If we are in non-autocommit mode, automatically start
+ *	a transaction.
+ */
+bool
+ecpg_autostart_transaction(struct statement * stmt)
+{
 	if (PQtransactionStatus(stmt->connection->connection) == PQTRANS_IDLE && !stmt->connection->autocommit)
 	{
 		stmt->results = PQexec(stmt->connection->connection, "begin transaction");
@@ -1434,7 +1443,16 @@ ecpg_execute(struct statement * stmt)
 		PQclear(stmt->results);
 		stmt->results = NULL;
 	}
+	return true;
+}
 
+/*
+ * ecpg_execute
+ *	Execute the SQL statement.
+ */
+bool
+ecpg_execute(struct statement * stmt)
+{
 	ecpg_log("ecpg_execute on line %d: query: %s; with %d parameter(s) on connection %s\n", stmt->lineno, stmt->command, stmt->nparams, stmt->connection->name);
 	if (stmt->statement_type == ECPGst_execute)
 	{
@@ -1460,6 +1478,33 @@ ecpg_execute(struct statement * stmt)
 	if (!ecpg_check_PQresult(stmt->results, stmt->lineno, stmt->connection->connection, stmt->compat))
 		return (false);
 
+	return true;
+}
+
+/*
+ * ecpg_process_output
+ *	Process the statement result and store it into application variables.
+ *	This function can be called repeatedly during the same statement
+ *	in case cursor readahed is used and the application does FETCH N which
+ *	overflows the readahead window.
+ *
+ * Parameters
+ *	stmt	statement structure holding the PGresult and
+ *		the list of output variables
+ *	clear_result
+ *		PQclear() the result upon returning from this function
+ *
+ * Returns success as boolean. Also an SQL error is raised in case of failure.
+ */
+bool
+ecpg_process_output(struct statement * stmt, bool clear_result)
+{
+	struct variable *var;
+	bool		status = false;
+	char	   *cmdstat;
+	PGnotify   *notify;
+	struct sqlca_t *sqlca = ECPGget_sqlca();
+
 	var = stmt->outlist;
 	switch (PQresultStatus(stmt->results))
 	{
@@ -1947,7 +1992,6 @@ bool
 ecpg_do(const int lineno, const int compat, const int force_indicator, const char *connection_name, const bool questionmarks, const int st, const char *query, va_list args)
 {
 	struct statement   *stmt;
-	bool		status;
 
 	if (!ecpg_do_prologue(lineno, compat, force_indicator,
 				connection_name, questionmarks,
@@ -1958,12 +2002,33 @@ ecpg_do(const int lineno, const int compat, const int force_indicator, const cha
 		return false;
 	}
 
-	status = ecpg_execute(stmt);
+	if (!ecpg_build_params(stmt))
+	{
+		ecpg_do_epilogue(stmt);
+		return false;
+	}
+
+	if (!ecpg_autostart_transaction(stmt))
+	{
+		ecpg_do_epilogue(stmt);
+		return false;
+	}
+
+	if (!ecpg_execute(stmt))
+	{
+		ecpg_do_epilogue(stmt);
+		return false;
+	}
+
+	if (!ecpg_process_output(stmt, true))
+	{
+		ecpg_do_epilogue(stmt);
+		return false;
+	}
 
-	/* and reset locale value so our application is not affected */
 	ecpg_do_epilogue(stmt);
 
-	return (status);
+	return true;
 }
 
 /*
diff --git a/src/interfaces/ecpg/ecpglib/extern.h b/src/interfaces/ecpg/ecpglib/extern.h
index 50fe87f..1f96869 100644
--- a/src/interfaces/ecpg/ecpglib/extern.h
+++ b/src/interfaces/ecpg/ecpglib/extern.h
@@ -169,10 +169,14 @@ bool ecpg_store_result(const PGresult *results, int act_field,
 				  const struct statement * stmt, struct variable * var);
 bool		ecpg_store_input(const int, const bool, const struct variable *, char **, bool);
 void		ecpg_free_params(struct statement *stmt, bool print);
-void		ecpg_do_epilogue(struct statement *);
 bool		ecpg_do_prologue(int, const int, const int, const char *, const bool,
 				  enum ECPG_statement_type, const char *, va_list,
 				  struct statement **);
+bool		ecpg_build_params(struct statement *);
+bool		ecpg_autostart_transaction(struct statement * stmt);
+bool		ecpg_execute(struct statement * stmt);
+bool		ecpg_process_output(struct statement *, bool);
+void		ecpg_do_epilogue(struct statement *);
 bool		ecpg_do(const int, const int, const int, const char *, const bool,
 				  const int, const char *, va_list);
 
