20.patch
text/x-patch
Filename: 20.patch
Type: text/x-patch
Part: 11
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/interfaces/ecpg/ecpglib/descriptor.c | 1 | 1 |
| src/interfaces/ecpg/ecpglib/execute.c | 27 | 23 |
| src/interfaces/ecpg/ecpglib/extern.h | 8 | 3 |
commit 802f3d7077667e99881aab52853743500cd80abb
Author: Böszörményi Zoltán <zb@cybertec.at>
Date: Thu Nov 28 11:53:56 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);