2013-11-20 14:41 keltezéssel, Boszormenyi Zoltan írta:
2013-11-12 07:15 keltezéssel, Boszormenyi Zoltan írta:
2013-11-12 07:01 keltezéssel, Noah Misch írta:
On Mon, Nov 11, 2013 at 10:17:54AM +0100, Boszormenyi Zoltan wrote:
The old contents of my GIT repository was removed so you need to
clone it fresh. https://github.com/zboszor/ecpg-readahead.git
I won't post the humongous patch again, since sending a 90KB
compressed file to everyone on the list is rude.
Patches of that weight show up on a regular basis.  I don't think it's rude.

OK, here it is.

...
Subsequent patches will come as reply to this email.

Further ecpglib/execute.c changes.

Best regards,
Zoltán Böszörményi

--
----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
Gröhrmühlgasse 26
A-2700 Wiener Neustadt, Austria
Web: http://www.postgresql-support.de
     http://www.postgresql.at/

commit c901afd59894f49001b743982d38a51b23bac8e1
Author: Böszörményi Zoltán <z...@cybertec.at>
Date:   Wed Nov 20 11:05:34 2013 +0100

    ECPG: Explicitly decouple the tuple index from the array index
    in ecpg_get_data(). Document the function arguments.

diff --git a/src/interfaces/ecpg/ecpglib/data.c b/src/interfaces/ecpg/ecpglib/data.c
index 5f9a3d4..7f3c7cb 100644
--- a/src/interfaces/ecpg/ecpglib/data.c
+++ b/src/interfaces/ecpg/ecpglib/data.c
@@ -119,8 +119,35 @@ check_special_value(char *ptr, double *retval, char **endptr)
 	return false;
 }
 
+/*
+ * ecpg_get_data
+ *   Store one field data from PQgetvalue(results, act_tuple, act_field)
+ *   into a target variable. If the field is NULL, store the indication or
+ *   emit an error about the fact that there is no NULL indicator given.
+ * Parameters:
+ *   results:     result set
+ *   act_tuple:   row index in the result set
+ *   act_field:   column index in the result set
+ *   var_index:   array index in the target variable
+ *   lineno:      line number in the ECPG source file for debugging
+ *   type:        type of target variable
+ *   ind_type:    type of NULL indicator variable
+ *   var:         target variable
+ *   ind:         NULL indicator variable
+ *   varcharsize: size of the variable if it's varchar
+ *   offset:      size of the target variable
+ *                (used for indexing in an array)
+ *   ind_offset:  size of the NULL indicator variable
+ *                (used for indexing in an array)
+ *   isarray:     array type
+ *   compat:      native PostgreSQL or Informix compatibility mode
+ *   force_indicator:
+ *                if Informix compatibility mode is set and no NULL indicator
+ *                is given, provide a way to indicate NULL value in the
+ *                target variable itself
+ */
 bool
-ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
+ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int var_index, int lineno,
 			  enum ECPGttype type, enum ECPGttype ind_type,
 			  char *var, char *ind, long varcharsize, long offset,
 			  long ind_offset, enum ARRAY_TYPE isarray, enum COMPAT_MODE compat, bool force_indicator)
@@ -167,20 +194,20 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 	{
 		case ECPGt_short:
 		case ECPGt_unsigned_short:
-			*((short *) (ind + ind_offset * act_tuple)) = value_for_indicator;
+			*((short *) (ind + ind_offset * var_index)) = value_for_indicator;
 			break;
 		case ECPGt_int:
 		case ECPGt_unsigned_int:
-			*((int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
+			*((int *) (ind + ind_offset * var_index)) = value_for_indicator;
 			break;
 		case ECPGt_long:
 		case ECPGt_unsigned_long:
-			*((long *) (ind + ind_offset * act_tuple)) = value_for_indicator;
+			*((long *) (ind + ind_offset * var_index)) = value_for_indicator;
 			break;
 #ifdef HAVE_LONG_LONG_INT
 		case ECPGt_long_long:
 		case ECPGt_unsigned_long_long:
-			*((long long int *) (ind + ind_offset * act_tuple)) = value_for_indicator;
+			*((long long int *) (ind + ind_offset * var_index)) = value_for_indicator;
 			break;
 #endif   /* HAVE_LONG_LONG_INT */
 		case ECPGt_NO_INDICATOR:
@@ -192,7 +219,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 					 * Informix has an additional way to specify NULLs note
 					 * that this uses special values to denote NULL
 					 */
-					ECPGset_noind_null(type, var + offset * act_tuple);
+					ECPGset_noind_null(type, var + offset * var_index);
 				}
 				else
 				{
@@ -243,10 +270,10 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 		if (binary)
 		{
 			if (varcharsize == 0 || varcharsize * offset >= size)
-				memcpy(var + offset * act_tuple, pval, size);
+				memcpy(var + offset * var_index, pval, size);
 			else
 			{
-				memcpy(var + offset * act_tuple, pval, varcharsize * offset);
+				memcpy(var + offset * var_index, pval, varcharsize * offset);
 
 				if (varcharsize * offset < size)
 				{
@@ -255,20 +282,20 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 					{
 						case ECPGt_short:
 						case ECPGt_unsigned_short:
-							*((short *) (ind + ind_offset * act_tuple)) = size;
+							*((short *) (ind + ind_offset * var_index)) = size;
 							break;
 						case ECPGt_int:
 						case ECPGt_unsigned_int:
-							*((int *) (ind + ind_offset * act_tuple)) = size;
+							*((int *) (ind + ind_offset * var_index)) = size;
 							break;
 						case ECPGt_long:
 						case ECPGt_unsigned_long:
-							*((long *) (ind + ind_offset * act_tuple)) = size;
+							*((long *) (ind + ind_offset * var_index)) = size;
 							break;
 #ifdef HAVE_LONG_LONG_INT
 						case ECPGt_long_long:
 						case ECPGt_unsigned_long_long:
-							*((long long int *) (ind + ind_offset * act_tuple)) = size;
+							*((long long int *) (ind + ind_offset * var_index)) = size;
 							break;
 #endif   /* HAVE_LONG_LONG_INT */
 						default:
@@ -307,13 +334,13 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 					switch (type)
 					{
 						case ECPGt_short:
-							*((short *) (var + offset * act_tuple)) = (short) res;
+							*((short *) (var + offset * var_index)) = (short) res;
 							break;
 						case ECPGt_int:
-							*((int *) (var + offset * act_tuple)) = (int) res;
+							*((int *) (var + offset * var_index)) = (int) res;
 							break;
 						case ECPGt_long:
-							*((long *) (var + offset * act_tuple)) = (long) res;
+							*((long *) (var + offset * var_index)) = (long) res;
 							break;
 						default:
 							/* Cannot happen */
@@ -336,13 +363,13 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 					switch (type)
 					{
 						case ECPGt_unsigned_short:
-							*((unsigned short *) (var + offset * act_tuple)) = (unsigned short) ures;
+							*((unsigned short *) (var + offset * var_index)) = (unsigned short) ures;
 							break;
 						case ECPGt_unsigned_int:
-							*((unsigned int *) (var + offset * act_tuple)) = (unsigned int) ures;
+							*((unsigned int *) (var + offset * var_index)) = (unsigned int) ures;
 							break;
 						case ECPGt_unsigned_long:
-							*((unsigned long *) (var + offset * act_tuple)) = (unsigned long) ures;
+							*((unsigned long *) (var + offset * var_index)) = (unsigned long) ures;
 							break;
 						default:
 							/* Cannot happen */
@@ -353,7 +380,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 #ifdef HAVE_LONG_LONG_INT
 #ifdef HAVE_STRTOLL
 				case ECPGt_long_long:
-					*((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10);
+					*((long long int *) (var + offset * var_index)) = strtoll(pval, &scan_length, 10);
 					if (garbage_left(isarray, scan_length, compat))
 					{
 						ecpg_raise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
@@ -365,7 +392,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 #endif   /* HAVE_STRTOLL */
 #ifdef HAVE_STRTOULL
 				case ECPGt_unsigned_long_long:
-					*((unsigned long long int *) (var + offset * act_tuple)) = strtoull(pval, &scan_length, 10);
+					*((unsigned long long int *) (var + offset * var_index)) = strtoull(pval, &scan_length, 10);
 					if ((isarray && *scan_length != ',' && *scan_length != '}')
 						|| (!isarray && !(INFORMIX_MODE(compat) && *scan_length == '.') && *scan_length != '\0' && *scan_length != ' '))		/* Garbage left */
 					{
@@ -400,10 +427,10 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 					switch (type)
 					{
 						case ECPGt_float:
-							*((float *) (var + offset * act_tuple)) = dres;
+							*((float *) (var + offset * var_index)) = dres;
 							break;
 						case ECPGt_double:
-							*((double *) (var + offset * act_tuple)) = dres;
+							*((double *) (var + offset * var_index)) = dres;
 							break;
 						default:
 							/* Cannot happen */
@@ -415,9 +442,9 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 					if (pval[0] == 'f' && pval[1] == '\0')
 					{
 						if (offset == sizeof(char))
-							*((char *) (var + offset * act_tuple)) = false;
+							*((char *) (var + offset * var_index)) = false;
 						else if (offset == sizeof(int))
-							*((int *) (var + offset * act_tuple)) = false;
+							*((int *) (var + offset * var_index)) = false;
 						else
 							ecpg_raise(lineno, ECPG_CONVERT_BOOL,
 									   ECPG_SQLSTATE_DATATYPE_MISMATCH,
@@ -428,9 +455,9 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 					else if (pval[0] == 't' && pval[1] == '\0')
 					{
 						if (offset == sizeof(char))
-							*((char *) (var + offset * act_tuple)) = true;
+							*((char *) (var + offset * var_index)) = true;
 						else if (offset == sizeof(int))
-							*((int *) (var + offset * act_tuple)) = true;
+							*((int *) (var + offset * var_index)) = true;
 						else
 							ecpg_raise(lineno, ECPG_CONVERT_BOOL,
 									   ECPG_SQLSTATE_DATATYPE_MISMATCH,
@@ -453,7 +480,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 				case ECPGt_unsigned_char:
 				case ECPGt_string:
 					{
-						char	   *str = (char *) (var + offset * act_tuple);
+						char	   *str = (char *) (var + offset * var_index);
 
 						if (varcharsize == 0 || varcharsize > size)
 						{
@@ -481,20 +508,20 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 								{
 									case ECPGt_short:
 									case ECPGt_unsigned_short:
-										*((short *) (ind + ind_offset * act_tuple)) = size;
+										*((short *) (ind + ind_offset * var_index)) = size;
 										break;
 									case ECPGt_int:
 									case ECPGt_unsigned_int:
-										*((int *) (ind + ind_offset * act_tuple)) = size;
+										*((int *) (ind + ind_offset * var_index)) = size;
 										break;
 									case ECPGt_long:
 									case ECPGt_unsigned_long:
-										*((long *) (ind + ind_offset * act_tuple)) = size;
+										*((long *) (ind + ind_offset * var_index)) = size;
 										break;
 #ifdef HAVE_LONG_LONG_INT
 									case ECPGt_long_long:
 									case ECPGt_unsigned_long_long:
-										*((long long int *) (ind + ind_offset * act_tuple)) = size;
+										*((long long int *) (ind + ind_offset * var_index)) = size;
 										break;
 #endif   /* HAVE_LONG_LONG_INT */
 									default:
@@ -510,7 +537,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 				case ECPGt_varchar:
 					{
 						struct ECPGgeneric_varchar *variable =
-						(struct ECPGgeneric_varchar *) (var + offset * act_tuple);
+						(struct ECPGgeneric_varchar *) (var + offset * var_index);
 
 						variable->len = size;
 						if (varcharsize == 0)
@@ -526,20 +553,20 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 								{
 									case ECPGt_short:
 									case ECPGt_unsigned_short:
-										*((short *) (ind + ind_offset * act_tuple)) = variable->len;
+										*((short *) (ind + ind_offset * var_index)) = variable->len;
 										break;
 									case ECPGt_int:
 									case ECPGt_unsigned_int:
-										*((int *) (ind + ind_offset * act_tuple)) = variable->len;
+										*((int *) (ind + ind_offset * var_index)) = variable->len;
 										break;
 									case ECPGt_long:
 									case ECPGt_unsigned_long:
-										*((long *) (ind + ind_offset * act_tuple)) = variable->len;
+										*((long *) (ind + ind_offset * var_index)) = variable->len;
 										break;
 #ifdef HAVE_LONG_LONG_INT
 									case ECPGt_long_long:
 									case ECPGt_unsigned_long_long:
-										*((long long int *) (ind + ind_offset * act_tuple)) = variable->len;
+										*((long long int *) (ind + ind_offset * var_index)) = variable->len;
 										break;
 #endif   /* HAVE_LONG_LONG_INT */
 									default:
@@ -606,9 +633,9 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 					pval = scan_length;
 
 					if (type == ECPGt_numeric)
-						PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple));
+						PGTYPESnumeric_copy(nres, (numeric *) (var + offset * var_index));
 					else
-						PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple));
+						PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * var_index));
 
 					PGTYPESnumeric_free(nres);
 					break;
@@ -659,7 +686,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 					}
 					pval = scan_length;
 
-					PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple));
+					PGTYPESinterval_copy(ires, (interval *) (var + offset * var_index));
 					free(ires);
 					break;
 
@@ -703,7 +730,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 						}
 					}
 
-					*((date *) (var + offset * act_tuple)) = ddres;
+					*((date *) (var + offset * var_index)) = ddres;
 					pval = scan_length;
 					break;
 
@@ -747,7 +774,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 						}
 					}
 
-					*((timestamp *) (var + offset * act_tuple)) = tres;
+					*((timestamp *) (var + offset * var_index)) = tres;
 					pval = scan_length;
 					break;
 
@@ -764,6 +791,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
 
 				/* set array to next entry */
 				++act_tuple;
+				++var_index;
 
 				/* set pval to the next entry */
 
diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index ca3e0ba..438d3ab 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -433,7 +433,7 @@ ecpg_store_result(const PGresult *results, int act_field,
 		{
 			int			len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
 
-			if (!ecpg_get_data(results, act_tuple, act_field, stmt->lineno,
+			if (!ecpg_get_data(results, act_tuple, act_field, act_tuple, stmt->lineno,
 							 var->type, var->ind_type, current_data_location,
 							   var->ind_value, len, 0, var->ind_offset, isarray, stmt->compat, stmt->force_indicator))
 				status = false;
@@ -452,7 +452,7 @@ ecpg_store_result(const PGresult *results, int act_field,
 	{
 		for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
 		{
-			if (!ecpg_get_data(results, act_tuple, act_field, stmt->lineno,
+			if (!ecpg_get_data(results, act_tuple, act_field, act_tuple, stmt->lineno,
 							   var->type, var->ind_type, var->value,
 							   var->ind_value, var->varcharsize, var->offset, var->ind_offset, isarray, stmt->compat, stmt->force_indicator))
 				status = false;
diff --git a/src/interfaces/ecpg/ecpglib/extern.h b/src/interfaces/ecpg/ecpglib/extern.h
index 1f96869..f91867c 100644
--- a/src/interfaces/ecpg/ecpglib/extern.h
+++ b/src/interfaces/ecpg/ecpglib/extern.h
@@ -139,7 +139,7 @@ extern struct var_list *ivlist;
 /* Returns a pointer to a string containing a simple type name. */
 void		ecpg_add_mem(void *ptr, int lineno);
 
-bool ecpg_get_data(const PGresult *, int, int, int, enum ECPGttype type,
+bool ecpg_get_data(const PGresult *, int, int, int, int, enum ECPGttype type,
 			  enum ECPGttype, char *, char *, long, long, long,
 			  enum ARRAY_TYPE, enum COMPAT_MODE, bool);
 
diff --git a/src/interfaces/ecpg/ecpglib/sqlda.c b/src/interfaces/ecpg/ecpglib/sqlda.c
index bc94f2f..9985a6c 100644
--- a/src/interfaces/ecpg/ecpglib/sqlda.c
+++ b/src/interfaces/ecpg/ecpglib/sqlda.c
@@ -393,7 +393,7 @@ ecpg_set_compat_sqlda(int lineno, struct sqlda_compat ** _sqlda, const PGresult
 		if (!isnull)
 		{
 			if (set_data)
-				ecpg_get_data(res, row, i, lineno,
+				ecpg_get_data(res, row, i, 0, lineno,
 							  sqlda->sqlvar[i].sqltype, ECPGt_NO_INDICATOR,
 							  sqlda->sqlvar[i].sqldata, NULL, 0, 0, 0,
 							  ECPG_ARRAY_NONE, compat, false);
@@ -578,7 +578,7 @@ ecpg_set_native_sqlda(int lineno, struct sqlda_struct ** _sqlda, const PGresult
 		if (!isnull)
 		{
 			if (set_data)
-				ecpg_get_data(res, row, i, lineno,
+				ecpg_get_data(res, row, i, 0, lineno,
 							  sqlda->sqlvar[i].sqltype, ECPGt_NO_INDICATOR,
 							  sqlda->sqlvar[i].sqldata, NULL, 0, 0, 0,
 							  ECPG_ARRAY_NONE, compat, false);
commit 3021ae9aeea085ff6f60ef736fe58126afb4f96f
Author: Böszörményi Zoltán <z...@cybertec.at>
Date:   Wed Nov 20 11:06:37 2013 +0100

    ECPG: Make SQLDA loops go forward. One regression test .stderr changed.

diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index 438d3ab..1fcfebc 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -1551,6 +1551,7 @@ ecpg_process_output(struct statement * stmt, bool clear_result)
 				{
 					struct sqlda_compat **_sqlda = (struct sqlda_compat **) var->pointer;
 					struct sqlda_compat *sqlda = *_sqlda;
+					struct sqlda_compat *sqlda_last;
 					struct sqlda_compat *sqlda_new;
 					int			i;
 
@@ -1564,8 +1565,8 @@ ecpg_process_output(struct statement * stmt, bool clear_result)
 						free(sqlda);
 						sqlda = sqlda_new;
 					}
-					*_sqlda = sqlda = sqlda_new = NULL;
-					for (i = ntuples - 1; i >= 0; i--)
+					*_sqlda = sqlda = sqlda_last = sqlda_new = NULL;
+					for (i = 0; i < ntuples; i++)
 					{
 						/*
 						 * Build a new sqlda structure. Note that only
@@ -1592,14 +1593,19 @@ ecpg_process_output(struct statement * stmt, bool clear_result)
 						{
 							ecpg_log("ecpg_process_output on line %d: new sqlda was built\n", stmt->lineno);
 
-							*_sqlda = sqlda_new;
+							if (sqlda_last)
+							{
+								sqlda_last->desc_next = sqlda_new;
+								sqlda_last = sqlda_new;
+							}
+							else
+							{
+								*_sqlda = sqlda = sqlda_last = sqlda_new;
+							}
 
-							ecpg_set_compat_sqlda(stmt->lineno, _sqlda, stmt->results, i, stmt->compat);
+							ecpg_set_compat_sqlda(stmt->lineno, &sqlda_new, stmt->results, i, stmt->compat);
 							ecpg_log("ecpg_process_output on line %d: putting result (1 tuple %d fields) into sqlda descriptor\n",
 									 stmt->lineno, PQnfields(stmt->results));
-
-							sqlda_new->desc_next = sqlda;
-							sqlda = sqlda_new;
 						}
 					}
 				}
@@ -1607,6 +1613,7 @@ ecpg_process_output(struct statement * stmt, bool clear_result)
 				{
 					struct sqlda_struct **_sqlda = (struct sqlda_struct **) var->pointer;
 					struct sqlda_struct *sqlda = *_sqlda;
+					struct sqlda_struct *sqlda_last;
 					struct sqlda_struct *sqlda_new;
 					int			i;
 
@@ -1620,8 +1627,8 @@ ecpg_process_output(struct statement * stmt, bool clear_result)
 						free(sqlda);
 						sqlda = sqlda_new;
 					}
-					*_sqlda = sqlda = sqlda_new = NULL;
-					for (i = ntuples - 1; i >= 0; i--)
+					*_sqlda = sqlda = sqlda_last = sqlda_new = NULL;
+					for (i = 0; i < ntuples; i++)
 					{
 						/*
 						 * Build a new sqlda structure. Note that only
@@ -1648,14 +1655,19 @@ ecpg_process_output(struct statement * stmt, bool clear_result)
 						{
 							ecpg_log("ecpg_process_output on line %d: new sqlda was built\n", stmt->lineno);
 
-							*_sqlda = sqlda_new;
+							if (sqlda_last)
+							{
+								sqlda_last->desc_next = sqlda_new;
+								sqlda_last = sqlda_new;
+							}
+							else
+							{
+								*_sqlda = sqlda = sqlda_last = sqlda_new;
+							}
 
-							ecpg_set_native_sqlda(stmt->lineno, _sqlda, stmt->results, i, stmt->compat);
+							ecpg_set_native_sqlda(stmt->lineno, &sqlda_new, stmt->results, i, stmt->compat);
 							ecpg_log("ecpg_process_output on line %d: putting result (1 tuple %d fields) into sqlda descriptor\n",
 									 stmt->lineno, PQnfields(stmt->results));
-
-							sqlda_new->desc_next = sqlda;
-							sqlda = sqlda_new;
 						}
 					}
 				}
diff --git a/src/interfaces/ecpg/test/expected/sql-sqlda.stderr b/src/interfaces/ecpg/test/expected/sql-sqlda.stderr
index a93ea07..d01aeea 100644
--- a/src/interfaces/ecpg/test/expected/sql-sqlda.stderr
+++ b/src/interfaces/ecpg/test/expected/sql-sqlda.stderr
@@ -148,23 +148,23 @@
 [NO_PID]: sqlca: code: 0, state: 00000
 [NO_PID]: ecpg_process_output on line 141: new sqlda was built
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_set_native_sqlda on line 141 row 2 col 0 IS NOT NULL
+[NO_PID]: ecpg_set_native_sqlda on line 141 row 0 col 0 IS NOT NULL
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 141: RESULT: 4 offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 141: RESULT: 1 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_set_native_sqlda on line 141 row 2 col 1 IS NOT NULL
+[NO_PID]: ecpg_set_native_sqlda on line 141 row 0 col 1 IS NOT NULL
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 141: RESULT: d offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 141: RESULT: a offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_set_native_sqlda on line 141 row 2 col 2 IS NOT NULL
+[NO_PID]: ecpg_set_native_sqlda on line 141 row 0 col 2 IS NOT NULL
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_set_native_sqlda on line 141 row 2 col 3 IS NOT NULL
+[NO_PID]: ecpg_set_native_sqlda on line 141 row 0 col 3 IS NOT NULL
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 141: RESULT: 4 offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 141: RESULT: 1 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_set_native_sqlda on line 141 row 2 col 4 IS NOT NULL
+[NO_PID]: ecpg_set_native_sqlda on line 141 row 0 col 4 IS NOT NULL
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 141: RESULT: d          offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 141: RESULT: a          offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
 [NO_PID]: ecpg_process_output on line 141: putting result (1 tuple 5 fields) into sqlda descriptor
 [NO_PID]: sqlca: code: 0, state: 00000
@@ -190,23 +190,23 @@
 [NO_PID]: sqlca: code: 0, state: 00000
 [NO_PID]: ecpg_process_output on line 141: new sqlda was built
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_set_native_sqlda on line 141 row 0 col 0 IS NOT NULL
+[NO_PID]: ecpg_set_native_sqlda on line 141 row 2 col 0 IS NOT NULL
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 141: RESULT: 1 offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 141: RESULT: 4 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_set_native_sqlda on line 141 row 0 col 1 IS NOT NULL
+[NO_PID]: ecpg_set_native_sqlda on line 141 row 2 col 1 IS NOT NULL
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 141: RESULT: a offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 141: RESULT: d offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_set_native_sqlda on line 141 row 0 col 2 IS NOT NULL
+[NO_PID]: ecpg_set_native_sqlda on line 141 row 2 col 2 IS NOT NULL
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_set_native_sqlda on line 141 row 0 col 3 IS NOT NULL
+[NO_PID]: ecpg_set_native_sqlda on line 141 row 2 col 3 IS NOT NULL
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 141: RESULT: 1 offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 141: RESULT: 4 offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_set_native_sqlda on line 141 row 0 col 4 IS NOT NULL
+[NO_PID]: ecpg_set_native_sqlda on line 141 row 2 col 4 IS NOT NULL
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_get_data on line 141: RESULT: a          offset: -1; array: no
+[NO_PID]: ecpg_get_data on line 141: RESULT: d          offset: -1; array: no
 [NO_PID]: sqlca: code: 0, state: 00000
 [NO_PID]: ecpg_process_output on line 141: putting result (1 tuple 5 fields) into sqlda descriptor
 [NO_PID]: sqlca: code: 0, state: 00000
commit 0e4077fd13266f9870ef620c4a81795ad86dbc82
Author: Böszörményi Zoltán <z...@cybertec.at>
Date:   Wed Nov 20 11:07:50 2013 +0100

    ECPG: Allow returning partial results in any order from the result set
    into an arbitrary index if the user variable is an array.

diff --git a/src/interfaces/ecpg/ecpglib/descriptor.c b/src/interfaces/ecpg/ecpglib/descriptor.c
index b2990ca..5d86c53 100644
--- a/src/interfaces/ecpg/ecpglib/descriptor.c
+++ b/src/interfaces/ecpg/ecpglib/descriptor.c
@@ -481,7 +481,7 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
 
 		/* desperate try to guess something sensible */
 		stmt.connection = ecpg_get_connection(NULL);
-		ecpg_store_result(ECPGresult, index, &stmt, &data_var);
+		ecpg_store_result(ECPGresult, 0, PQntuples(ECPGresult), LOOP_FORWARD, index, &stmt, &data_var, 0);
 
 		setlocale(LC_NUMERIC, oldlocale);
 		ecpg_free(oldlocale);
diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index 1fcfebc..ace6c11 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -307,12 +307,14 @@ ecpg_is_type_an_array(int type, const struct statement * stmt, const struct vari
 
 
 bool
-ecpg_store_result(const PGresult *results, int act_field,
-				  const struct statement * stmt, struct variable * var)
+ecpg_store_result(const PGresult *results,
+				  int start, int ntuples, int direction,
+				  int act_field,
+				  const struct statement * stmt,
+				  struct variable * var, int var_index)
 {
 	enum ARRAY_TYPE isarray;
-	int			act_tuple,
-				ntuples = PQntuples(results);
+	int			tuples_left, act_tuple, act_index;
 	bool		status = true;
 
 	if ((isarray = ecpg_is_type_an_array(PQftype(results, act_field), stmt, var)) == ECPG_ARRAY_ERROR)
@@ -363,7 +365,7 @@ ecpg_store_result(const PGresult *results, int act_field,
 					if (!var->varcharsize && !var->arrsize)
 					{
 						/* special mode for handling char**foo=0 */
-						for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
+						for (tuples_left = ntuples, act_tuple = start; tuples_left; tuples_left--, act_tuple += direction)
 							len += strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
 						len *= var->offset;		/* should be 1, but YMNK */
 						len += (ntuples + 1) * sizeof(char *);
@@ -372,7 +374,7 @@ ecpg_store_result(const PGresult *results, int act_field,
 					{
 						var->varcharsize = 0;
 						/* check strlen for each tuple */
-						for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
+						for (tuples_left = ntuples, act_tuple = start; tuples_left; tuples_left--, act_tuple += direction)
 						{
 							int			len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
 
@@ -393,7 +395,7 @@ ecpg_store_result(const PGresult *results, int act_field,
 		}
 		else
 		{
-			for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
+			for (tuples_left = ntuples, act_tuple = start; tuples_left; tuples_left--, act_tuple += direction)
 				len += PQgetlength(results, act_tuple, act_field);
 		}
 
@@ -429,11 +431,11 @@ ecpg_store_result(const PGresult *results, int act_field,
 		/* storing the data (after the last array element) */
 		char	   *current_data_location = (char *) &current_string[ntuples + 1];
 
-		for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
+		for (tuples_left = ntuples, act_tuple = start, act_index = var_index; tuples_left && status; tuples_left--, act_tuple += direction, act_index++)
 		{
 			int			len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
 
-			if (!ecpg_get_data(results, act_tuple, act_field, act_tuple, stmt->lineno,
+			if (!ecpg_get_data(results, act_tuple, act_field, act_index, stmt->lineno,
 							 var->type, var->ind_type, current_data_location,
 							   var->ind_value, len, 0, var->ind_offset, isarray, stmt->compat, stmt->force_indicator))
 				status = false;
@@ -450,9 +452,9 @@ ecpg_store_result(const PGresult *results, int act_field,
 	}
 	else
 	{
-		for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
+		for (tuples_left = ntuples, act_tuple = start, act_index = var_index; tuples_left && status; tuples_left--, act_tuple += direction, act_index++)
 		{
-			if (!ecpg_get_data(results, act_tuple, act_field, act_tuple, stmt->lineno,
+			if (!ecpg_get_data(results, act_tuple, act_field, act_index, stmt->lineno,
 							   var->type, var->ind_type, var->value,
 							   var->ind_value, var->varcharsize, var->offset, var->ind_offset, isarray, stmt->compat, stmt->force_indicator))
 				status = false;
@@ -1489,15 +1491,18 @@ ecpg_execute(struct statement * stmt)
  *	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
+ *	stmt:		statement structure holding the PGresult and
+ *			the list of output variables
+ *	start:		start index in PGresult
+ *	ntuples:	number of tuples to process
+ *	direction:	in this direction
+ *	var_index:	start index in the user variable if it's an array
+ *	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)
+ecpg_process_output(struct statement * stmt, int start, int ntuples, int direction, int var_index, bool clear_result)
 {
 	struct variable *var;
 	bool		status = false;
@@ -1509,12 +1514,11 @@ ecpg_process_output(struct statement * stmt, bool clear_result)
 	switch (PQresultStatus(stmt->results))
 	{
 			int			nfields,
-						ntuples,
 						act_field;
 
 		case PGRES_TUPLES_OK:
 			nfields = PQnfields(stmt->results);
-			sqlca->sqlerrd[2] = ntuples = PQntuples(stmt->results);
+			sqlca->sqlerrd[2] = ntuples;
 			ecpg_log("ecpg_process_output on line %d: correctly got %d tuples with %d fields\n", stmt->lineno, ntuples, nfields);
 			status = true;
 
@@ -1541,7 +1545,7 @@ ecpg_process_output(struct statement * stmt, bool clear_result)
 					desc->result = stmt->results;
 					clear_result = false;
 					ecpg_log("ecpg_process_output on line %d: putting result (%d tuples) into descriptor %s\n",
-							 stmt->lineno, PQntuples(stmt->results), (const char *) var->pointer);
+							 stmt->lineno, ntuples, (const char *) var->pointer);
 				}
 				var = var->next;
 			}
@@ -1566,7 +1570,7 @@ ecpg_process_output(struct statement * stmt, bool clear_result)
 						sqlda = sqlda_new;
 					}
 					*_sqlda = sqlda = sqlda_last = sqlda_new = NULL;
-					for (i = 0; i < ntuples; i++)
+					for (i = start; ntuples; ntuples--, i += direction)
 					{
 						/*
 						 * Build a new sqlda structure. Note that only
@@ -1628,7 +1632,7 @@ ecpg_process_output(struct statement * stmt, bool clear_result)
 						sqlda = sqlda_new;
 					}
 					*_sqlda = sqlda = sqlda_last = sqlda_new = NULL;
-					for (i = 0; i < ntuples; i++)
+					for (i = start; ntuples; ntuples--, i += direction)
 					{
 						/*
 						 * Build a new sqlda structure. Note that only
@@ -1679,7 +1683,7 @@ ecpg_process_output(struct statement * stmt, bool clear_result)
 				{
 					if (var != NULL)
 					{
-						status = ecpg_store_result(stmt->results, act_field, stmt, var);
+						status = ecpg_store_result(stmt->results, start, ntuples, direction, act_field, stmt, var, var_index);
 						var = var->next;
 					}
 					else if (!INFORMIX_MODE(stmt->compat))
@@ -2032,7 +2036,7 @@ ecpg_do(const int lineno, const int compat, const int force_indicator, const cha
 		return false;
 	}
 
-	if (!ecpg_process_output(stmt, true))
+	if (!ecpg_process_output(stmt, 0, PQntuples(stmt->results), LOOP_FORWARD, 0, true))
 	{
 		ecpg_do_epilogue(stmt);
 		return false;
diff --git a/src/interfaces/ecpg/ecpglib/extern.h b/src/interfaces/ecpg/ecpglib/extern.h
index f91867c..e09e351 100644
--- a/src/interfaces/ecpg/ecpglib/extern.h
+++ b/src/interfaces/ecpg/ecpglib/extern.h
@@ -29,6 +29,9 @@ enum ARRAY_TYPE
 
 #define ECPG_IS_ARRAY(X) ((X) == ECPG_ARRAY_ARRAY || (X) == ECPG_ARRAY_VECTOR)
 
+#define LOOP_FORWARD	(1)
+#define LOOP_BACKWARD	(-1)
+
 /* A generic varchar type. */
 struct ECPGgeneric_varchar
 {
@@ -165,8 +168,10 @@ struct descriptor *ecpg_find_desc(int line, const char *name);
 struct prepared_statement *ecpg_find_prepared_statement(const char *,
 						  struct connection *, struct prepared_statement **);
 
-bool ecpg_store_result(const PGresult *results, int act_field,
-				  const struct statement * stmt, struct variable * var);
+bool ecpg_store_result(const PGresult *results,
+				  int start, int ntuples, int direction, int act_field,
+				  const struct statement * stmt,
+				  struct variable * var, int var_index);
 bool		ecpg_store_input(const int, const bool, const struct variable *, char **, bool);
 void		ecpg_free_params(struct statement *stmt, bool print);
 bool		ecpg_do_prologue(int, const int, const int, const char *, const bool,
@@ -175,7 +180,7 @@ bool		ecpg_do_prologue(int, const int, const int, const char *, const bool,
 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);
+bool		ecpg_process_output(struct statement *, int, int, int, int, 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);
commit 762f9119ded05920771af083df336a76a15a746c
Author: Böszörményi Zoltán <z...@cybertec.at>
Date:   Wed Nov 20 11:09:16 2013 +0100

    ECPG: Allow appending a new result set to descriptors.

diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index ace6c11..b28ab9c 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -1498,11 +1498,13 @@ ecpg_execute(struct statement * stmt)
  *	direction:	in this direction
  *	var_index:	start index in the user variable if it's an array
  *	clear_result:	PQclear() the result upon returning from this function
+ *	append_result:	the user variable is an SQL or SQLDA descriptor,
+ *			may already contain data, append to it.
  *
  * Returns success as boolean. Also an SQL error is raised in case of failure.
  */
 bool
-ecpg_process_output(struct statement * stmt, int start, int ntuples, int direction, int var_index, bool clear_result)
+ecpg_process_output(struct statement * stmt, int start, int ntuples, int direction, int var_index, bool clear_result, bool append_result)
 {
 	struct variable *var;
 	bool		status = false;
@@ -1514,6 +1516,7 @@ ecpg_process_output(struct statement * stmt, int start, int ntuples, int directi
 	switch (PQresultStatus(stmt->results))
 	{
 			int			nfields,
+						tuples_left,
 						act_field;
 
 		case PGRES_TUPLES_OK:
@@ -1540,12 +1543,35 @@ ecpg_process_output(struct statement * stmt, int start, int ntuples, int directi
 					status = false;
 				else
 				{
-					if (desc->result)
-						PQclear(desc->result);
-					desc->result = stmt->results;
-					clear_result = false;
-					ecpg_log("ecpg_process_output on line %d: putting result (%d tuples) into descriptor %s\n",
-							 stmt->lineno, ntuples, (const char *) var->pointer);
+					if (append_result && desc->result)
+					{
+						int		tuples_left, act_tuple, col,
+								row = PQntuples(desc->result);
+
+						for (tuples_left = ntuples, act_tuple = start; tuples_left; tuples_left--, act_tuple += direction, row++)
+							for (col = 0; col < nfields; col++)
+							{
+								bool	isnull = PQgetisnull(stmt->results, act_tuple, col);
+
+								if (!PQsetvalue(desc->result, row, col,
+										isnull ? NULL : PQgetvalue(stmt->results, act_tuple, col),
+										isnull ? -1 : PQgetlength(stmt->results, act_tuple, col)))
+								{
+									ecpg_raise(stmt->lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
+									status = false;
+									break;
+								}
+							}
+					}
+					else
+					{
+						if (desc->result)
+							PQclear(desc->result);
+						desc->result = stmt->results;
+						clear_result = false;
+						ecpg_log("ecpg_process_output on line %d: putting result (%d tuples) into descriptor %s\n",
+								 stmt->lineno, ntuples, (const char *) var->pointer);
+					}
 				}
 				var = var->next;
 			}
@@ -1559,17 +1585,26 @@ ecpg_process_output(struct statement * stmt, int start, int ntuples, int directi
 					struct sqlda_compat *sqlda_new;
 					int			i;
 
-					/*
-					 * If we are passed in a previously existing sqlda (chain)
-					 * then free it.
-					 */
-					while (sqlda)
+					if (append_result)
+					{
+						sqlda_last = sqlda;
+						while (sqlda_last && sqlda_last->desc_next)
+							sqlda_last = sqlda_last->desc_next;
+					}
+					else
 					{
-						sqlda_new = sqlda->desc_next;
-						free(sqlda);
-						sqlda = sqlda_new;
+						/*
+						 * If we are passed in a previously existing sqlda (chain)
+						 * then free it.
+						 */
+						while (sqlda)
+						{
+							sqlda_new = sqlda->desc_next;
+							free(sqlda);
+							sqlda = sqlda_new;
+						}
+						*_sqlda = sqlda = sqlda_last = NULL;
 					}
-					*_sqlda = sqlda = sqlda_last = sqlda_new = NULL;
 					for (i = start; ntuples; ntuples--, i += direction)
 					{
 						/*
@@ -1621,17 +1656,26 @@ ecpg_process_output(struct statement * stmt, int start, int ntuples, int directi
 					struct sqlda_struct *sqlda_new;
 					int			i;
 
-					/*
-					 * If we are passed in a previously existing sqlda (chain)
-					 * then free it.
-					 */
-					while (sqlda)
+					if (append_result)
 					{
-						sqlda_new = sqlda->desc_next;
-						free(sqlda);
-						sqlda = sqlda_new;
+						sqlda_last = sqlda;
+						while (sqlda_last && sqlda_last->desc_next)
+							sqlda_last = sqlda_last->desc_next;
+					}
+					else
+					{
+						/*
+						 * If we are passed in a previously existing sqlda (chain)
+						 * then free it.
+						 */
+						while (sqlda)
+						{
+							sqlda_new = sqlda->desc_next;
+							free(sqlda);
+							sqlda = sqlda_new;
+						}
+						*_sqlda = sqlda = sqlda_last = NULL;
 					}
-					*_sqlda = sqlda = sqlda_last = sqlda_new = NULL;
 					for (i = start; ntuples; ntuples--, i += direction)
 					{
 						/*
@@ -2036,7 +2080,7 @@ ecpg_do(const int lineno, const int compat, const int force_indicator, const cha
 		return false;
 	}
 
-	if (!ecpg_process_output(stmt, 0, PQntuples(stmt->results), LOOP_FORWARD, 0, true))
+	if (!ecpg_process_output(stmt, 0, PQntuples(stmt->results), LOOP_FORWARD, 0, true, false))
 	{
 		ecpg_do_epilogue(stmt);
 		return false;
diff --git a/src/interfaces/ecpg/ecpglib/extern.h b/src/interfaces/ecpg/ecpglib/extern.h
index e09e351..ff12acb 100644
--- a/src/interfaces/ecpg/ecpglib/extern.h
+++ b/src/interfaces/ecpg/ecpglib/extern.h
@@ -180,7 +180,7 @@ bool		ecpg_do_prologue(int, const int, const int, const char *, const bool,
 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 *, int, int, int, int, bool);
+bool		ecpg_process_output(struct statement *, int, int, int, int, bool, 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);
commit 2bb97fdf7ec4fcffec2767eb21f87e73db890503
Author: Böszörményi Zoltán <z...@cybertec.at>
Date:   Wed Nov 20 11:10:13 2013 +0100

    ECPG: Use the more descriptive "act_tuple" variable name instead of "i".
    Use the variables declared for the function scope, don't alias them.

diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index b28ab9c..1326870 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -1517,6 +1517,7 @@ ecpg_process_output(struct statement * stmt, int start, int ntuples, int directi
 	{
 			int			nfields,
 						tuples_left,
+						act_tuple,
 						act_field;
 
 		case PGRES_TUPLES_OK:
@@ -1545,23 +1546,24 @@ ecpg_process_output(struct statement * stmt, int start, int ntuples, int directi
 				{
 					if (append_result && desc->result)
 					{
-						int		tuples_left, act_tuple, col,
-								row = PQntuples(desc->result);
+						int		row = PQntuples(desc->result);
 
 						for (tuples_left = ntuples, act_tuple = start; tuples_left; tuples_left--, act_tuple += direction, row++)
-							for (col = 0; col < nfields; col++)
+							for (act_field = 0; act_field < nfields; act_field++)
 							{
-								bool	isnull = PQgetisnull(stmt->results, act_tuple, col);
+								bool	isnull = PQgetisnull(stmt->results, act_tuple, act_field);
 
-								if (!PQsetvalue(desc->result, row, col,
-										isnull ? NULL : PQgetvalue(stmt->results, act_tuple, col),
-										isnull ? -1 : PQgetlength(stmt->results, act_tuple, col)))
+								if (!PQsetvalue(desc->result, row, act_field,
+										isnull ? NULL : PQgetvalue(stmt->results, act_tuple, act_field),
+										isnull ? -1 : PQgetlength(stmt->results, act_tuple, act_field)))
 								{
 									ecpg_raise(stmt->lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
 									status = false;
 									break;
 								}
 							}
+						ecpg_log("ecpg_process_output on line %d: appending result (%d tuples) to descriptor %s\n",
+								 stmt->lineno, ntuples, (const char *) var->pointer);
 					}
 					else
 					{
@@ -1583,7 +1585,6 @@ ecpg_process_output(struct statement * stmt, int start, int ntuples, int directi
 					struct sqlda_compat *sqlda = *_sqlda;
 					struct sqlda_compat *sqlda_last;
 					struct sqlda_compat *sqlda_new;
-					int			i;
 
 					if (append_result)
 					{
@@ -1605,13 +1606,13 @@ ecpg_process_output(struct statement * stmt, int start, int ntuples, int directi
 						}
 						*_sqlda = sqlda = sqlda_last = NULL;
 					}
-					for (i = start; ntuples; ntuples--, i += direction)
+					for (tuples_left = ntuples, act_tuple = start; tuples_left; tuples_left--, act_tuple += direction)
 					{
 						/*
 						 * Build a new sqlda structure. Note that only
 						 * fetching 1 record is supported
 						 */
-						sqlda_new = ecpg_build_compat_sqlda(stmt->lineno, stmt->results, i, stmt->compat);
+						sqlda_new = ecpg_build_compat_sqlda(stmt->lineno, stmt->results, act_tuple, stmt->compat);
 
 						if (!sqlda_new)
 						{
@@ -1642,7 +1643,7 @@ ecpg_process_output(struct statement * stmt, int start, int ntuples, int directi
 								*_sqlda = sqlda = sqlda_last = sqlda_new;
 							}
 
-							ecpg_set_compat_sqlda(stmt->lineno, &sqlda_new, stmt->results, i, stmt->compat);
+							ecpg_set_compat_sqlda(stmt->lineno, &sqlda_new, stmt->results, act_tuple, stmt->compat);
 							ecpg_log("ecpg_process_output on line %d: putting result (1 tuple %d fields) into sqlda descriptor\n",
 									 stmt->lineno, PQnfields(stmt->results));
 						}
@@ -1654,7 +1655,6 @@ ecpg_process_output(struct statement * stmt, int start, int ntuples, int directi
 					struct sqlda_struct *sqlda = *_sqlda;
 					struct sqlda_struct *sqlda_last;
 					struct sqlda_struct *sqlda_new;
-					int			i;
 
 					if (append_result)
 					{
@@ -1676,13 +1676,13 @@ ecpg_process_output(struct statement * stmt, int start, int ntuples, int directi
 						}
 						*_sqlda = sqlda = sqlda_last = NULL;
 					}
-					for (i = start; ntuples; ntuples--, i += direction)
+					for (tuples_left = ntuples, act_tuple = start; tuples_left; tuples_left--, act_tuple += direction)
 					{
 						/*
 						 * Build a new sqlda structure. Note that only
 						 * fetching 1 record is supported
 						 */
-						sqlda_new = ecpg_build_native_sqlda(stmt->lineno, stmt->results, i, stmt->compat);
+						sqlda_new = ecpg_build_native_sqlda(stmt->lineno, stmt->results, act_tuple, stmt->compat);
 
 						if (!sqlda_new)
 						{
@@ -1713,7 +1713,7 @@ ecpg_process_output(struct statement * stmt, int start, int ntuples, int directi
 								*_sqlda = sqlda = sqlda_last = sqlda_new;
 							}
 
-							ecpg_set_native_sqlda(stmt->lineno, &sqlda_new, stmt->results, i, stmt->compat);
+							ecpg_set_native_sqlda(stmt->lineno, &sqlda_new, stmt->results, act_tuple, stmt->compat);
 							ecpg_log("ecpg_process_output on line %d: putting result (1 tuple %d fields) into sqlda descriptor\n",
 									 stmt->lineno, PQnfields(stmt->results));
 						}
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to