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 *) ¤t_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