aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/ecpg/ecpglib/execute.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/ecpg/ecpglib/execute.c')
-rw-r--r--src/interfaces/ecpg/ecpglib/execute.c595
1 files changed, 342 insertions, 253 deletions
diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index 5c3ecf6461f..4a9f82cc1ac 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.67 2007/06/11 11:52:08 meskes Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.68 2007/08/14 10:01:52 meskes Exp $ */
/*
* The aim is to get a simpler inteface to the database routines.
@@ -56,7 +56,6 @@ quote_postgres(char *arg, bool quote, int lineno)
res = (char *) ECPGalloc(buffer_len + 3, lineno);
if (!res)
return (res);
-
escaped_len = PQescapeString(res+1, arg, buffer_len);
if (length == escaped_len)
{
@@ -105,24 +104,43 @@ free_statement(struct statement * stmt)
free_variable(stmt->inlist);
free_variable(stmt->outlist);
ECPGfree(stmt->command);
+ ECPGfree(stmt->name);
ECPGfree(stmt);
}
-static char *
-next_insert(char *text)
+static int
+next_insert(char *text, int pos, bool questionmarks)
{
- char *ptr = text;
bool string = false;
+ int p = pos;
- for (; *ptr != '\0' && (*ptr != '?' || string); ptr++)
+ for (; text[p] != '\0'; p++)
{
- if (*ptr == '\\') /* escape character */
- ptr++;
- else if (*ptr == '\'')
+ if (text[p] == '\\') /* escape character */
+ p++;
+ else if (text[p] == '\'')
string = string ? false : true;
+ else if (!string)
+ {
+ if (text[p] == '$' && isdigit(text[p+1]))
+ {
+ /* this can be either a dollar quote or a variable */
+ int i;
+
+ for (i = p + 1; isdigit(text[i]); i++);
+ if (!isalpha(text[i]) && isascii(text[i]) && text[i] != '_')
+ /* not dollar delimeted quote */
+ return p;
+ }
+ else if (questionmarks && text[p] == '?')
+ {
+ /* also allow old style placeholders */
+ return p;
+ }
+ }
}
- return (*ptr == '\0') ? NULL : ptr;
+ return -1;
}
static bool
@@ -257,7 +275,9 @@ ECPGis_type_an_array(int type, const struct statement * stmt, const struct varia
sprintf(array_query, "select typlen from pg_type where oid=%d and typelem<>0", type);
query = PQexec(stmt->connection->connection, array_query);
ECPGfree(array_query);
- if (PQresultStatus(query) == PGRES_TUPLES_OK)
+ if (!ECPGcheck_PQresult(query, stmt->lineno, stmt->connection->connection, stmt->compat))
+ return (ECPG_ARRAY_ERROR);
+ else if (PQresultStatus(query) == PGRES_TUPLES_OK)
{
if (PQntuples(query) == 0)
isarray = ECPG_ARRAY_NONE;
@@ -273,8 +293,11 @@ ECPGis_type_an_array(int type, const struct statement * stmt, const struct varia
isarray = ECPG_ARRAY_NONE;
}
}
+ PQclear(query);
}
- PQclear(query);
+ else
+ return (ECPG_ARRAY_ERROR);
+
ECPGtypeinfocache_push(&(stmt->connection->cache_head), type, isarray, stmt->lineno);
ECPGlog("ECPGis_type_an_array line %d: TYPE database: %d C: %d array: %s\n", stmt->lineno, type, var->type, isarray ? "Yes" : "No");
return isarray;
@@ -428,7 +451,7 @@ ECPGstore_result(const PGresult *results, int act_field,
bool
ECPGstore_input(const int lineno, const bool force_indicator, const struct variable * var,
- const char **tobeinserted_p, bool *malloced_p, bool quote)
+ const char **tobeinserted_p, bool quote)
{
char *mallocedval = NULL;
char *newcopy = NULL;
@@ -450,7 +473,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
* contents to arrive in a comma-separated list on insert (I think).
*/
- *malloced_p = false;
*tobeinserted_p = "";
/* check for null value and set input buffer accordingly */
@@ -459,36 +481,36 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
case ECPGt_short:
case ECPGt_unsigned_short:
if (*(short *) var->ind_value < 0)
- *tobeinserted_p = "null";
+ *tobeinserted_p = NULL;
break;
case ECPGt_int:
case ECPGt_unsigned_int:
if (*(int *) var->ind_value < 0)
- *tobeinserted_p = "null";
+ *tobeinserted_p = NULL;
break;
case ECPGt_long:
case ECPGt_unsigned_long:
if (*(long *) var->ind_value < 0L)
- *tobeinserted_p = "null";
+ *tobeinserted_p = NULL;
break;
#ifdef HAVE_LONG_LONG_INT_64
case ECPGt_long_long:
case ECPGt_unsigned_long_long:
if (*(long long int *) var->ind_value < (long long) 0)
- *tobeinserted_p = "null";
+ *tobeinserted_p = NULL;
break;
#endif /* HAVE_LONG_LONG_INT_64 */
case ECPGt_NO_INDICATOR:
if (force_indicator == false)
{
if (ECPGis_noind_null(var->type, var->value))
- *tobeinserted_p = "null";
+ *tobeinserted_p = NULL;
}
break;
default:
break;
}
- if (**tobeinserted_p == '\0')
+ if (*tobeinserted_p != NULL)
{
int asize = var->arrsize ? var->arrsize : 1;
@@ -513,7 +535,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
sprintf(mallocedval, "%hd", *((short *) var->value));
*tobeinserted_p = mallocedval;
- *malloced_p = true;
break;
case ECPGt_int:
@@ -522,18 +543,17 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
if (asize > 1)
{
- strcpy(mallocedval, "array [");
+ strcpy(mallocedval, "{");
for (element = 0; element < asize; element++)
sprintf(mallocedval + strlen(mallocedval), "%d,", ((int *) var->value)[element]);
- strcpy(mallocedval + strlen(mallocedval) - 1, "]");
+ strcpy(mallocedval + strlen(mallocedval) - 1, "}");
}
else
sprintf(mallocedval, "%d", *((int *) var->value));
*tobeinserted_p = mallocedval;
- *malloced_p = true;
break;
case ECPGt_unsigned_short:
@@ -553,7 +573,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
sprintf(mallocedval, "%hu", *((unsigned short *) var->value));
*tobeinserted_p = mallocedval;
- *malloced_p = true;
break;
case ECPGt_unsigned_int:
@@ -573,7 +592,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
sprintf(mallocedval, "%u", *((unsigned int *) var->value));
*tobeinserted_p = mallocedval;
- *malloced_p = true;
break;
case ECPGt_long:
@@ -593,7 +611,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
sprintf(mallocedval, "%ld", *((long *) var->value));
*tobeinserted_p = mallocedval;
- *malloced_p = true;
break;
case ECPGt_unsigned_long:
@@ -613,7 +630,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
sprintf(mallocedval, "%lu", *((unsigned long *) var->value));
*tobeinserted_p = mallocedval;
- *malloced_p = true;
break;
#ifdef HAVE_LONG_LONG_INT_64
case ECPGt_long_long:
@@ -633,7 +649,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
sprintf(mallocedval, "%lld", *((long long *) var->value));
*tobeinserted_p = mallocedval;
- *malloced_p = true;
break;
case ECPGt_unsigned_long_long:
@@ -653,7 +668,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
sprintf(mallocedval, "%llu", *((unsigned long long *) var->value));
*tobeinserted_p = mallocedval;
- *malloced_p = true;
break;
#endif /* HAVE_LONG_LONG_INT_64 */
case ECPGt_float:
@@ -673,7 +687,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
sprintf(mallocedval, "%.14g", *((float *) var->value));
*tobeinserted_p = mallocedval;
- *malloced_p = true;
break;
case ECPGt_double:
@@ -693,7 +706,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
sprintf(mallocedval, "%.14g", *((double *) var->value));
*tobeinserted_p = mallocedval;
- *malloced_p = true;
break;
case ECPGt_bool:
@@ -722,15 +734,14 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
else
{
if (var->offset == sizeof(char))
- sprintf(mallocedval, "'%c'", (*((char *) var->value)) ? 't' : 'f');
+ sprintf(mallocedval, "%c", (*((char *) var->value)) ? 't' : 'f');
else if (var->offset == sizeof(int))
- sprintf(mallocedval, "'%c'", (*((int *) var->value)) ? 't' : 'f');
+ sprintf(mallocedval, "%c", (*((int *) var->value)) ? 't' : 'f');
else
ECPGraise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, "different size");
}
*tobeinserted_p = mallocedval;
- *malloced_p = true;
break;
case ECPGt_char:
@@ -750,7 +761,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
return false;
*tobeinserted_p = mallocedval;
- *malloced_p = true;
}
break;
case ECPGt_const:
@@ -765,7 +775,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
mallocedval[slen] = '\0';
*tobeinserted_p = mallocedval;
- *malloced_p = true;
}
break;
case ECPGt_varchar:
@@ -784,7 +793,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
return false;
*tobeinserted_p = mallocedval;
- *malloced_p = true;
}
break;
@@ -854,7 +862,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
}
*tobeinserted_p = mallocedval;
- *malloced_p = true;
}
break;
@@ -881,7 +888,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
if (!element)
strcpy(mallocedval, "array [");
- strcpy(mallocedval + strlen(mallocedval), "interval ");
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
strcpy(mallocedval + strlen(mallocedval), ",");
ECPGfree(str);
@@ -901,14 +907,12 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
return false;
}
- strcpy(mallocedval, "interval ");
/* also copy trailing '\0' */
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
ECPGfree(str);
}
*tobeinserted_p = mallocedval;
- *malloced_p = true;
}
break;
@@ -935,7 +939,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
if (!element)
strcpy(mallocedval, "array [");
- strcpy(mallocedval + strlen(mallocedval), "date ");
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
strcpy(mallocedval + strlen(mallocedval), ",");
ECPGfree(str);
@@ -955,14 +958,12 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
return false;
}
- strcpy(mallocedval, "date ");
/* also copy trailing '\0' */
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
ECPGfree(str);
}
*tobeinserted_p = mallocedval;
- *malloced_p = true;
}
break;
@@ -990,7 +991,6 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
if (!element)
strcpy(mallocedval, "array [");
- strcpy(mallocedval + strlen(mallocedval), "timestamp ");
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
strcpy(mallocedval + strlen(mallocedval), ",");
ECPGfree(str);
@@ -1010,14 +1010,12 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
return false;
}
- strcpy(mallocedval, "timestamp ");
/* also copy trailing '\0' */
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
ECPGfree(str);
}
*tobeinserted_p = mallocedval;
- *malloced_p = true;
}
break;
@@ -1034,33 +1032,45 @@ ECPGstore_input(const int lineno, const bool force_indicator, const struct varia
return true;
}
+static void
+free_params(const char **paramValues, int nParams, bool print, int lineno)
+{
+ int n;
+
+ for (n = 0; n < nParams; n++)
+ {
+ if (print)
+ ECPGlog("ECPGexecute line %d: parameter %d = %s\n", lineno, n + 1, paramValues[n] ? paramValues[n] : "null");
+ ECPGfree((void *)(paramValues[n]));
+ }
+ ECPGfree(paramValues);
+}
+
static bool
ECPGexecute(struct statement * stmt)
{
bool status = false;
- char *copiedquery;
char *cmdstat;
PGresult *results;
PGnotify *notify;
struct variable *var;
int desc_counter = 0;
-
- copiedquery = ECPGstrdup(stmt->command, stmt->lineno);
+ const char * *paramValues = NULL;
+ int nParams = 0;
+ int position = 0;
+ struct sqlca_t *sqlca = ECPGget_sqlca();
+ bool clear_result = true;
/*
- * Now, if the type is one of the fill in types then we take the argument
- * and enter that in the string at the first %s position. Then if there
- * are any more fill in types we fill in at the next and so on.
+ * If the type is one of the fill in types then we take the argument
+ * and enter it to our parameter array at the first position. Then if there
+ * are any more fill in types we add more parameters.
*/
var = stmt->inlist;
-
while (var)
{
- char *newcopy = NULL;
const char *tobeinserted;
- char *p;
- bool malloced = FALSE;
- int hostvarl = 0;
+ int counter = 1;
tobeinserted = NULL;
@@ -1087,75 +1097,131 @@ ECPGexecute(struct statement * stmt)
if (desc == NULL)
{
ECPGraise(stmt->lineno, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, var->pointer);
- ECPGfree(copiedquery);
return false;
}
desc_counter++;
- if (desc->count < 0 || desc->count >= desc_counter)
+ for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
{
- for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
+ if (desc_item->num == desc_counter)
{
- if (desc_item->num == desc_counter)
+ desc_inlist.type = ECPGt_char;
+ desc_inlist.value = desc_item->data;
+ desc_inlist.pointer = &(desc_item->data);
+ desc_inlist.varcharsize = strlen(desc_item->data);
+ desc_inlist.arrsize = 1;
+ desc_inlist.offset = 0;
+ if (!desc_item->indicator)
{
- desc_inlist.type = ECPGt_char;
- desc_inlist.value = desc_item->data;
- desc_inlist.pointer = &(desc_item->data);
- desc_inlist.varcharsize = strlen(desc_item->data);
- desc_inlist.arrsize = 1;
- desc_inlist.offset = 0;
- if (!desc_item->indicator)
- {
- desc_inlist.ind_type = ECPGt_NO_INDICATOR;
- desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
- desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
- }
- else
- {
- desc_inlist.ind_type = ECPGt_int;
- desc_inlist.ind_value = &(desc_item->indicator);
- desc_inlist.ind_pointer = &(desc_inlist.ind_value);
- desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
- desc_inlist.ind_offset = 0;
- }
- if (!ECPGstore_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, &malloced, true))
- {
- ECPGfree(copiedquery);
- return false;
- }
-
- break;
+ desc_inlist.ind_type = ECPGt_NO_INDICATOR;
+ desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
+ desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
}
- }
+ else
+ {
+ desc_inlist.ind_type = ECPGt_int;
+ desc_inlist.ind_value = &(desc_item->indicator);
+ desc_inlist.ind_pointer = &(desc_inlist.ind_value);
+ desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
+ desc_inlist.ind_offset = 0;
+ }
+ if (!ECPGstore_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, false))
+ return false;
- if (!desc_item) /* no more entries found in descriptor */
- desc_counter = 0;
+ break;
+ }
}
- else
+ if (desc->count == desc_counter)
desc_counter = 0;
}
else
{
- if (!ECPGstore_input(stmt->lineno, stmt->force_indicator, var, &tobeinserted, &malloced, true))
+ if (!ECPGstore_input(stmt->lineno, stmt->force_indicator, var, &tobeinserted, false))
return false;
}
- if (tobeinserted)
+ /*
+ * now tobeinserted points to an area that contains the next parameter
+ * if var->type=ECPGt_char_variable we have a dynamic cursor
+ * we have to simulate a dynamic cursor because there is no backend functionality for it
+ */
+ if (var->type != ECPGt_char_variable)
{
- /*
- * Now tobeinserted points to an area that is to be inserted at
- * the first %s
- */
- if (!(newcopy = (char *) ECPGalloc(strlen(copiedquery)
+ nParams++;
+ if (!(paramValues = (const char **) ECPGrealloc(paramValues, sizeof(const char *) * nParams, stmt->lineno)))
+ {
+ ECPGfree(paramValues);
+ return false;
+ }
+
+ paramValues[nParams - 1] = tobeinserted;
+
+ if ((position = next_insert(stmt->command, position, stmt->questionmarks) + 1) == 0)
+ {
+ /*
+ * We have an argument but we dont have the matched up
+ * placeholder in the string
+ */
+ ECPGraise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS,
+ ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS,
+ NULL);
+ free_params(paramValues, nParams, false, stmt->lineno);
+ return false;
+ }
+
+ /* let's see if this was an old style placeholder */
+ if (stmt->command[position-1] == '?')
+ {
+ /* yes, replace with new style */
+ int buffersize = sizeof(int) * CHAR_BIT * 10 / 3; /* a rough guess of the size we need */
+ char *buffer, *newcopy;
+
+ if (!(buffer = (char *) ECPGalloc(buffersize, stmt->lineno)))
+ {
+ free_params(paramValues, nParams, false, stmt->lineno);
+ return false;
+ }
+
+ snprintf(buffer, buffersize, "$%d", counter++);
+
+ if (!(newcopy = (char *) ECPGalloc(strlen(stmt->command) + strlen(buffer) + 1, stmt->lineno)))
+ {
+ free_params(paramValues, nParams, false, stmt->lineno);
+ ECPGfree(buffer);
+ return false;
+ }
+
+ strcpy(newcopy, stmt->command);
+
+ /* set positional parameter */
+ strcpy(newcopy + position - 1, buffer);
+
+ /*
+ * The strange thing in the second argument is the rest of the
+ * string from the old string
+ */
+ strcat(newcopy,
+ stmt->command
+ + position + 1);
+ ECPGfree(buffer);
+ ECPGfree(stmt->command);
+ stmt->command = newcopy;
+ }
+ }
+ else
+ {
+ char *newcopy;
+
+ if (!(newcopy = (char *) ECPGalloc(strlen(stmt->command)
+ strlen(tobeinserted)
+ 1, stmt->lineno)))
{
- ECPGfree(copiedquery);
+ free_params(paramValues, nParams, false, stmt->lineno);
return false;
}
- strcpy(newcopy, copiedquery);
- if ((p = next_insert(newcopy + hostvarl)) == NULL)
+ strcpy(newcopy, stmt->command);
+ if ((position = next_insert(stmt->command, position, stmt->questionmarks) + 1) == 0)
{
/*
* We have an argument but we dont have the matched up string
@@ -1164,38 +1230,31 @@ ECPGexecute(struct statement * stmt)
ECPGraise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS,
ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS,
NULL);
- ECPGfree(copiedquery);
+ free_params(paramValues, nParams, false, stmt->lineno);
ECPGfree(newcopy);
return false;
}
else
{
- strcpy(p, tobeinserted);
- hostvarl = strlen(newcopy);
+ int ph_len = (stmt->command[position] == '?') ? strlen("?") : strlen("$1");
+
+ strcpy(newcopy + position - 1, tobeinserted);
/*
* The strange thing in the second argument is the rest of the
* string from the old string
*/
strcat(newcopy,
- copiedquery
- + (p - newcopy)
- + sizeof("?") - 1 /* don't count the '\0' */ );
- }
-
- /*
- * Now everything is safely copied to the newcopy. Lets free the
- * oldcopy and let the copiedquery get the var->value from the
- * newcopy.
- */
- if (malloced)
- {
- ECPGfree((char *) tobeinserted);
- tobeinserted = NULL;
+ stmt->command
+ + position
+ + ph_len - 1);
}
- ECPGfree(copiedquery);
- copiedquery = newcopy;
+ ECPGfree(stmt->command);
+ stmt->command = newcopy;
+
+ ECPGfree((char *)tobeinserted);
+ tobeinserted = NULL;
}
if (desc_counter == 0)
@@ -1203,171 +1262,161 @@ ECPGexecute(struct statement * stmt)
}
/* Check if there are unmatched things left. */
- if (next_insert(copiedquery) != NULL)
+ if (next_insert(stmt->command, position, stmt->questionmarks) >= 0)
{
ECPGraise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS,
ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS, NULL);
- ECPGfree(copiedquery);
+ free_params(paramValues, nParams, false, stmt->lineno);
return false;
}
- /* Now the request is built. */
+ /* The request has been build. */
if (stmt->connection->committed && !stmt->connection->autocommit)
{
- if ((results = PQexec(stmt->connection->connection, "begin transaction")) == NULL)
+ results = PQexec(stmt->connection->connection, "begin transaction");
+ if (!ECPGcheck_PQresult(results, stmt->lineno, stmt->connection->connection, stmt->compat))
{
- ECPGraise(stmt->lineno, ECPG_TRANS,
- ECPG_SQLSTATE_TRANSACTION_RESOLUTION_UNKNOWN, NULL);
- ECPGfree(copiedquery);
+ free_params(paramValues, nParams, false, stmt->lineno);
return false;
}
PQclear(results);
stmt->connection->committed = false;
}
- ECPGlog("ECPGexecute line %d: QUERY: %s on connection %s\n", stmt->lineno, copiedquery, stmt->connection->name);
- results = PQexec(stmt->connection->connection, copiedquery);
- ECPGfree(copiedquery);
-
- if (results == NULL)
+ ECPGlog("ECPGexecute line %d: QUERY: %s with %d parameter on connection %s \n", stmt->lineno, stmt->command, nParams, stmt->connection->name);
+ if (stmt->statement_type == ECPGst_execute)
{
- ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno, PQerrorMessage(stmt->connection->connection));
- ECPGraise_backend(stmt->lineno, NULL, stmt->connection->connection, stmt->compat);
+ results = PQexecPrepared(stmt->connection->connection, stmt->name, nParams, paramValues, NULL, NULL, 0);
+ ECPGlog("ECPGexecute line %d: using PQexecPrepared for %s\n", stmt->lineno, stmt->command);
}
else
+ {
+ if (nParams == 0)
+ {
+ results = PQexec(stmt->connection->connection, stmt->command);
+ ECPGlog("ECPGexecute line %d: using PQexec\n", stmt->lineno);
+ }
+ else
+ {
+ results = PQexecParams(stmt->connection->connection, stmt->command, nParams, NULL, paramValues, NULL, NULL, 0);
+ ECPGlog("ECPGexecute line %d: using PQexecParams \n", stmt->lineno);
+ }
+ }
- /*
- * note: since some of the following code is duplicated in
- * descriptor.c it should go into a separate function
- */
+ free_params(paramValues, nParams, true, stmt->lineno);
+
+ if (!ECPGcheck_PQresult(results, stmt->lineno, stmt->connection->connection, stmt->compat))
+ return (false);
+
+ var = stmt->outlist;
+ switch (PQresultStatus(results))
{
- bool clear_result = TRUE;
- struct sqlca_t *sqlca = ECPGget_sqlca();
+ int nfields,
+ ntuples,
+ act_field;
- var = stmt->outlist;
- switch (PQresultStatus(results))
- {
- int nfields,
- ntuples,
- act_field;
+ case PGRES_TUPLES_OK:
+ nfields = PQnfields(results);
+ sqlca->sqlerrd[2] = ntuples = PQntuples(results);
+ ECPGlog("ECPGexecute line %d: Correctly got %d tuples with %d fields\n", stmt->lineno, ntuples, nfields);
+ status = true;
- case PGRES_TUPLES_OK:
- nfields = PQnfields(results);
- sqlca->sqlerrd[2] = ntuples = PQntuples(results);
- ECPGlog("ECPGexecute line %d: Correctly got %d tuples with %d fields\n", stmt->lineno, ntuples, nfields);
- status = true;
+ if (ntuples < 1)
+ {
+ if (ntuples)
+ ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d\n",
+ stmt->lineno, ntuples);
+ ECPGraise(stmt->lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
+ status = false;
+ break;
+ }
- if (ntuples < 1)
- {
- if (ntuples)
- ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d\n",
- stmt->lineno, ntuples);
- ECPGraise(stmt->lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
+ if (var != NULL && var->type == ECPGt_descriptor)
+ {
+ PGresult **resultpp = ECPGdescriptor_lvalue(stmt->lineno, (const char *) var->pointer);
+
+ if (resultpp == NULL)
status = false;
- break;
+ else
+ {
+ if (*resultpp)
+ PQclear(*resultpp);
+ *resultpp = results;
+ clear_result = FALSE;
+ ECPGlog("ECPGexecute putting result (%d tuples) into descriptor '%s'\n", PQntuples(results), (const char *) var->pointer);
}
-
- if (var != NULL && var->type == ECPGt_descriptor)
+ var = var->next;
+ }
+ else
+ for (act_field = 0; act_field < nfields && status; act_field++)
{
- PGresult **resultpp = ECPGdescriptor_lvalue(stmt->lineno, (const char *) var->pointer);
-
- if (resultpp == NULL)
- status = false;
- else
+ if (var != NULL)
{
- if (*resultpp)
- PQclear(*resultpp);
- *resultpp = results;
- clear_result = FALSE;
- ECPGlog("ECPGexecute putting result (%d tuples) into descriptor '%s'\n", PQntuples(results), (const char *) var->pointer);
+ status = ECPGstore_result(results, act_field, stmt, var);
+ var = var->next;
}
- var = var->next;
- }
- else
- for (act_field = 0; act_field < nfields && status; act_field++)
+ else if (!INFORMIX_MODE(stmt->compat))
{
- if (var != NULL)
- {
- status = ECPGstore_result(results, act_field, stmt, var);
- var = var->next;
- }
- else if (!INFORMIX_MODE(stmt->compat))
- {
- ECPGraise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_TARGETS, NULL);
- return (false);
- }
+ ECPGraise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_TARGETS, NULL);
+ return (false);
}
-
- if (status && var != NULL)
- {
- ECPGraise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_TARGETS, NULL);
- status = false;
}
- break;
- case PGRES_EMPTY_QUERY:
- /* do nothing */
- ECPGraise(stmt->lineno, ECPG_EMPTY, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
- break;
- case PGRES_COMMAND_OK:
- status = true;
- cmdstat = PQcmdStatus(results);
- sqlca->sqlerrd[1] = PQoidValue(results);
- sqlca->sqlerrd[2] = atol(PQcmdTuples(results));
- ECPGlog("ECPGexecute line %d Ok: %s\n", stmt->lineno, cmdstat);
- if (stmt->compat != ECPG_COMPAT_INFORMIX_SE &&
- !sqlca->sqlerrd[2] &&
- (!strncmp(cmdstat, "UPDATE", 6)
- || !strncmp(cmdstat, "INSERT", 6)
- || !strncmp(cmdstat, "DELETE", 6)))
- ECPGraise(stmt->lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
- break;
- case PGRES_NONFATAL_ERROR:
- case PGRES_FATAL_ERROR:
- case PGRES_BAD_RESPONSE:
- ECPGlog("ECPGexecute line %d: Error: %s", stmt->lineno, PQresultErrorMessage(results));
- ECPGraise_backend(stmt->lineno, results, stmt->connection->connection, stmt->compat);
+ if (status && var != NULL)
+ {
+ ECPGraise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS, ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_TARGETS, NULL);
status = false;
- break;
- case PGRES_COPY_OUT:
- {
- char *buffer;
- int res;
+ }
- ECPGlog("ECPGexecute line %d: Got PGRES_COPY_OUT\n", stmt->lineno);
- while ((res = PQgetCopyData(stmt->connection->connection,
- &buffer, 0)) > 0)
- {
- printf("%s", buffer);
- PQfreemem(buffer);
- }
- if (res == -1)
- {
- /* COPY done */
- PQclear(results);
- results = PQgetResult(stmt->connection->connection);
- if (PQresultStatus(results) == PGRES_COMMAND_OK)
- ECPGlog("ECPGexecute line %d: Got PGRES_COMMAND_OK after PGRES_COPY_OUT\n", stmt->lineno);
- else
- ECPGlog("ECPGexecute line %d: Got error after PGRES_COPY_OUT: %s", PQresultErrorMessage(results));
- }
- break;
+ break;
+ case PGRES_COMMAND_OK:
+ status = true;
+ cmdstat = PQcmdStatus(results);
+ sqlca->sqlerrd[1] = PQoidValue(results);
+ sqlca->sqlerrd[2] = atol(PQcmdTuples(results));
+ ECPGlog("ECPGexecute line %d Ok: %s\n", stmt->lineno, cmdstat);
+ if (stmt->compat != ECPG_COMPAT_INFORMIX_SE &&
+ !sqlca->sqlerrd[2] &&
+ (!strncmp(cmdstat, "UPDATE", 6)
+ || !strncmp(cmdstat, "INSERT", 6)
+ || !strncmp(cmdstat, "DELETE", 6)))
+ ECPGraise(stmt->lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
+ break;
+ case PGRES_COPY_OUT:
+ {
+ char *buffer;
+ int res;
+
+ ECPGlog("ECPGexecute line %d: Got PGRES_COPY_OUT\n", stmt->lineno);
+ while ((res = PQgetCopyData(stmt->connection->connection,
+ &buffer, 0)) > 0)
+ {
+ printf("%s", buffer);
+ PQfreemem(buffer);
+ }
+ if (res == -1)
+ {
+ /* COPY done */
+ PQclear(results);
+ results = PQgetResult(stmt->connection->connection);
+ if (PQresultStatus(results) == PGRES_COMMAND_OK)
+ ECPGlog("ECPGexecute line %d: Got PGRES_COMMAND_OK after PGRES_COPY_OUT\n", stmt->lineno);
+ else
+ ECPGlog("ECPGexecute line %d: Got error after PGRES_COPY_OUT: %s", PQresultErrorMessage(results));
}
- case PGRES_COPY_IN:
- ECPGlog("ECPGexecute line %d: Got PGRES_COPY_IN ... tossing.\n", stmt->lineno);
- PQendcopy(stmt->connection->connection);
- break;
- default:
- ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
- stmt->lineno);
- ECPGraise_backend(stmt->lineno, results, stmt->connection->connection, stmt->compat);
- status = false;
break;
- }
- if (clear_result)
- PQclear(results);
+ }
+ default:
+ /* execution should never reach this code because it is already handled in ECPGcheck_PQresult() */
+ ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
+ stmt->lineno);
+ ECPGraise_backend(stmt->lineno, results, stmt->connection->connection, stmt->compat);
+ status = false;
+ break;
}
+ if (clear_result)
+ PQclear(results);
/* check for asynchronous returns */
notify = PQnotifies(stmt->connection->connection);
@@ -1382,7 +1431,7 @@ ECPGexecute(struct statement * stmt)
}
bool
-ECPGdo(int lineno, int compat, int force_indicator, const char *connection_name, const char *query,...)
+ECPGdo(const int lineno, const int compat, const int force_indicator, const char *connection_name, const bool questionmarks, const enum ECPG_statement_type st, const char *query,...)
{
va_list args;
struct statement *stmt;
@@ -1391,6 +1440,14 @@ ECPGdo(int lineno, int compat, int force_indicator, const char *connection_name,
char *oldlocale;
enum ECPGttype type;
struct variable **list;
+ enum ECPG_statement_type statement_type = st;
+ char *prepname;
+
+ if (!query)
+ {
+ ECPGraise(lineno, ECPG_EMPTY, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
+ return(false);
+ }
/* Make sure we do NOT honor the locale for numeric input/output */
/* since the database wants the standard decimal point */
@@ -1435,15 +1492,47 @@ ECPGdo(int lineno, int compat, int force_indicator, const char *connection_name,
{
setlocale(LC_NUMERIC, oldlocale);
ECPGfree(oldlocale);
+ ECPGfree(prepname);
va_end(args);
return false;
}
- stmt->command = ECPGstrdup(query, lineno);
+ /* If statement type is ECPGst_prepnormal we are supposed to prepare
+ * the statement before executing them */
+ if (statement_type == ECPGst_prepnormal)
+ {
+ if (!ECPGauto_prepare(lineno, connection_name, questionmarks, &prepname, query))
+ return(false);
+
+ /* statement is now prepared, so instead of the query we have to execute the name */
+ stmt->command = prepname;
+ statement_type = ECPGst_execute;
+ }
+ else
+ stmt->command = ECPGstrdup(query, lineno);
+
+ stmt->name = NULL;
+
+ if (statement_type == ECPGst_execute)
+ {
+ /* if we have an EXECUTE command, only the name is send */
+ char *command = ECPGprepared(stmt->command, lineno);
+
+ if (command)
+ {
+ stmt->name = stmt->command;
+ stmt->command = ECPGstrdup(command, lineno);
+ }
+ else
+ ECPGraise(lineno, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, stmt->command);
+ }
+
stmt->connection = con;
stmt->lineno = lineno;
stmt->compat = compat;
stmt->force_indicator = force_indicator;
+ stmt->questionmarks = questionmarks;
+ stmt->statement_type = statement_type;
list = &(stmt->inlist);
@@ -1564,7 +1653,7 @@ bool
ECPGdo_descriptor(int line, const char *connection,
const char *descriptor, const char *query)
{
- return ECPGdo(line, ECPG_COMPAT_PGSQL, true, connection, (char *) query, ECPGt_EOIT,
+ return ECPGdo(line, ECPG_COMPAT_PGSQL, true, connection, '\0', 0, (char *) query, ECPGt_EOIT,
ECPGt_descriptor, descriptor, 0L, 0L, 0L,
ECPGt_NO_INDICATOR, NULL, 0L, 0L, 0L, ECPGt_EORT);
}