aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/ecpg/lib/ecpglib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/ecpg/lib/ecpglib.c')
-rw-r--r--src/interfaces/ecpg/lib/ecpglib.c626
1 files changed, 318 insertions, 308 deletions
diff --git a/src/interfaces/ecpg/lib/ecpglib.c b/src/interfaces/ecpg/lib/ecpglib.c
index 815f4bff0bc..4f40a2e1020 100644
--- a/src/interfaces/ecpg/lib/ecpglib.c
+++ b/src/interfaces/ecpg/lib/ecpglib.c
@@ -24,6 +24,8 @@
#include <ecpglib.h>
#include <sqlca.h>
+extern int no_auto_trans;
+
static PGconn *simple_connection = NULL;
static int simple_debug = 0;
static FILE *debugstream = NULL;
@@ -80,6 +82,11 @@ ECPGdo(int lineno, char *query,...)
PGresult *results;
PGnotify *notify;
enum ECPGttype type;
+ void *value = NULL, *ind_value;
+ long varcharsize, ind_varcharsize;
+ long arrsize, ind_arrsize;
+ long offset, ind_offset;
+ enum ECPGttype ind_type;
va_start(ap, query);
@@ -96,12 +103,6 @@ ECPGdo(int lineno, char *query,...)
*/
while (type != ECPGt_EOIT)
{
- void *value = NULL, *ind_value;
- long varcharsize, ind_varcharsize;
- long size, ind_size;
- long arrsize, ind_arrsize;
- enum ECPGttype ind_type;
-
char *newcopy;
char *mallocedval = NULL;
char *tobeinserted = NULL;
@@ -116,13 +117,13 @@ ECPGdo(int lineno, char *query,...)
value = va_arg(ap, void *);
varcharsize = va_arg(ap, long);
- size = va_arg(ap, long);
arrsize = va_arg(ap, long);
+ offset = va_arg(ap, long);
ind_type = va_arg(ap, enum ECPGttype);
ind_value = va_arg(ap, void *);
ind_varcharsize = va_arg(ap, long);
- ind_size = va_arg(ap, long);
ind_arrsize = va_arg(ap, long);
+ ind_offset = va_arg(ap, long);
buff[0] = '\0';
@@ -211,7 +212,6 @@ ECPGdo(int lineno, char *query,...)
break;
case ECPGt_varchar:
- case ECPGt_varchar2:
{
struct ECPGgeneric_varchar *var =
(struct ECPGgeneric_varchar *) value;
@@ -233,7 +233,7 @@ ECPGdo(int lineno, char *query,...)
default:
/* Not implemented yet */
- register_error(-1, "Unsupported type %s on line %d.",
+ register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.",
ECPGtype_name(type), lineno);
return false;
break;
@@ -257,7 +257,7 @@ ECPGdo(int lineno, char *query,...)
* We have an argument but we dont have the matched up string
* in the string
*/
- register_error(-1, "Too many arguments line %d.", lineno);
+ register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", lineno);
return false;
}
else
@@ -293,17 +293,17 @@ ECPGdo(int lineno, char *query,...)
/* Check if there are unmatched things left. */
if (strstr(copiedquery, ";;") != NULL)
{
- register_error(-1, "Too few arguments line %d.", lineno);
+ register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", lineno);
return false;
}
/* Now the request is built. */
- if (committed)
+ if (committed && !no_auto_trans)
{
if ((results = PQexec(simple_connection, "begin transaction")) == NULL)
{
- register_error(-1, "Error starting transaction line %d.", lineno);
+ register_error(ECPG_TRANS, "Error starting transaction line %d.", lineno);
return false;
}
PQclear(results);
@@ -318,15 +318,15 @@ ECPGdo(int lineno, char *query,...)
{
ECPGlog("ECPGdo line %d: error: %s", lineno,
PQerrorMessage(simple_connection));
- register_error(-1, "Postgres error: %s line %d.",
+ register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
PQerrorMessage(simple_connection), lineno);
}
else
+ {
+ sqlca.sqlerrd[2] = 0;
switch (PQresultStatus(results))
{
- int m,
- n,
- x;
+ int nfields, ntuples, act_tuple, act_field;
case PGRES_TUPLES_OK:
@@ -336,306 +336,308 @@ ECPGdo(int lineno, char *query,...)
* !!
*/
- m = PQnfields(results);
- n = PQntuples(results);
-
- if (n < 1)
+ nfields = PQnfields(results);
+ sqlca.sqlerrd[2] = ntuples = PQntuples(results);
+ status = true;
+
+ if (ntuples < 1)
{
ECPGlog("ECPGdo line %d: Incorrect number of matches: %d\n",
- lineno, n);
- register_error(1, "Data not found line %d.", lineno);
+ lineno, ntuples);
+ register_error(ECPG_NOT_FOUND, "Data not found line %d.", lineno);
+ status = false;
break;
}
- if (n > 1)
- {
- ECPGlog("ECPGdo line %d: Incorrect number of matches: %d\n",
- lineno, n);
- register_error(-1, "To many matches line %d.", lineno);
- break;
- }
-
- status = true;
-
- for (x = 0; x < m && status; x++)
- {
- void *value = NULL, *ind_value;
- long varcharsize, ind_varcharsize;
- long size, ind_size;
- long arrsize, ind_arrsize;
- enum ECPGttype ind_type;
-
- char *pval = PQgetvalue(results, 0, x);
-
- /*
- * long int * res_int; char ** res_charstar; char *
- * res_char; int res_len;
- */
- char *scan_length;
-
- ECPGlog("ECPGdo line %d: RESULT: %s\n", lineno, pval ? pval : "");
-
- /* Now the pval is a pointer to the value. */
- /* We will have to decode the value */
- type = va_arg(ap, enum ECPGttype);
- value = va_arg(ap, void *);
- varcharsize = va_arg(ap, long);
- size = va_arg(ap, long);
- arrsize = va_arg(ap, long);
- ind_type = va_arg(ap, enum ECPGttype);
- ind_value = va_arg(ap, void *);
- ind_varcharsize = va_arg(ap, long);
- ind_size = va_arg(ap, long);
- ind_arrsize = va_arg(ap, long);
-
- /* check for null value and set indicator accordingly */
- switch (ind_type)
- {
- case ECPGt_short:
- case ECPGt_unsigned_short:
- *(short *) ind_value = -PQgetisnull(results, 0, x);
- break;
- case ECPGt_int:
- case ECPGt_unsigned_int:
- *(int *) ind_value = -PQgetisnull(results, 0, x);
- break;
- case ECPGt_long:
- case ECPGt_unsigned_long:
- *(long *) ind_value = -PQgetisnull(results, 0, x);
- break;
- default:
- break;
- }
-
- switch (type)
- {
- long res;
- unsigned long ures;
- double dres;
-
- case ECPGt_short:
- case ECPGt_int:
- case ECPGt_long:
- if (pval)
- {
- res = strtol(pval, &scan_length, 10);
- if (*scan_length != '\0') /* Garbage left */
- {
- register_error(-1, "Not correctly formatted int type: %s line %d.",
- pval, lineno);
- status = false;
- res = 0L;
- }
- }
- else
- res = 0L;
-
- /* Again?! Yes */
- switch (type)
- {
- case ECPGt_short:
- *(short *) value = (short) res;
- break;
- case ECPGt_int:
- *(int *) value = (int) res;
- break;
- case ECPGt_long:
- *(long *) value = res;
- break;
- default:
- /* Cannot happen */
- break;
- }
- break;
-
- case ECPGt_unsigned_short:
- case ECPGt_unsigned_int:
- case ECPGt_unsigned_long:
- if (pval)
- {
- ures = strtoul(pval, &scan_length, 10);
- if (*scan_length != '\0') /* Garbage left */
- {
- register_error(-1, "Not correctly formatted unsigned type: %s line %d.",
- pval, lineno);
- status = false;
- ures = 0L;
- }
- }
- else
- ures = 0L;
-
- /* Again?! Yes */
- switch (type)
- {
- case ECPGt_unsigned_short:
- *(unsigned short *) value = (unsigned short) ures;
- break;
- case ECPGt_unsigned_int:
- *(unsigned int *) value = (unsigned int) ures;
- break;
- case ECPGt_unsigned_long:
- *(unsigned long *) value = ures;
- break;
- default:
- /* Cannot happen */
- break;
- }
- break;
-
-
- case ECPGt_float:
- case ECPGt_double:
- if (pval)
- {
- dres = strtod(pval, &scan_length);
- if (*scan_length != '\0') /* Garbage left */
- {
- register_error(-1, "Not correctly formatted floating point type: %s line %d.",
- pval, lineno);
- status = false;
- dres = 0.0;
- }
- }
- else
- dres = 0.0;
-
- /* Again?! Yes */
- switch (type)
- {
- case ECPGt_float:
- *(float *) value = dres;
- break;
- case ECPGt_double:
- *(double *) value = dres;
- break;
- default:
- /* Cannot happen */
- break;
- }
- break;
-
- case ECPGt_bool:
- if (pval)
- {
- if (pval[0] == 'f' && pval[1] == '\0')
- {
- *(char *) value = false;
- break;
- }
- else if (pval[0] == 't' && pval[1] == '\0')
- {
- *(char *) value = true;
- break;
- }
- }
-
- register_error(-1, "Unable to convert %s to bool on line %d.",
- (pval ? pval : "NULL"),
- lineno);
- return false;
- break;
-
- case ECPGt_char:
- case ECPGt_unsigned_char:
- {
- if (varcharsize == 0)
- {
- /* char* */
- strncpy((char *) value, pval, strlen(pval));
- ((char *) value)[strlen(pval)] = '\0';
- }
- else
- {
- strncpy((char *) value, pval, varcharsize);
- if (varcharsize < strlen(pval))
- {
- /* truncation */
- switch (ind_type)
- {
- case ECPGt_short:
- case ECPGt_unsigned_short:
- *(short *) ind_value = varcharsize;
- break;
- case ECPGt_int:
- case ECPGt_unsigned_int:
- *(int *) ind_value = varcharsize;
- break;
- case ECPGt_long:
- case ECPGt_unsigned_long:
- *(long *) ind_value = varcharsize;
- break;
- default:
- break;
- }
- }
- }
- }
- break;
-
- case ECPGt_varchar:
- {
- struct ECPGgeneric_varchar *var =
- (struct ECPGgeneric_varchar *) value;
-
- strncpy(var->arr, pval, varcharsize);
- var->len = strlen(pval);
- if (var->len > varcharsize)
- {
- /* truncation */
- switch (ind_type)
- {
- case ECPGt_short:
- case ECPGt_unsigned_short:
- *(short *) ind_value = varcharsize;
- break;
- case ECPGt_int:
- case ECPGt_unsigned_int:
- *(int *) ind_value = varcharsize;
- break;
- case ECPGt_long:
- case ECPGt_unsigned_long:
- *(long *) ind_value = varcharsize;
- break;
- default:
- break;
- }
-
- var->len = varcharsize;
- }
- }
- break;
-
- case ECPGt_EORT:
- ECPGlog("ECPGdo line %d: Too few arguments.\n", lineno);
- register_error(-1, "Too few arguments line %d.", lineno);
- status = false;
- break;
-
- default:
- register_error(-1, "Unsupported type %s on line %d.",
- ECPGtype_name(type), lineno);
- return false;
- break;
- }
+ for (act_field = 0; act_field < nfields && status; act_field++)
+ {
+ char *pval;
+ char *scan_length;
+
+ type = va_arg(ap, enum ECPGttype);
+ value = va_arg(ap, void *);
+ varcharsize = va_arg(ap, long);
+ arrsize = va_arg(ap, long);
+ offset = va_arg(ap, long);
+ ind_type = va_arg(ap, enum ECPGttype);
+ ind_value = va_arg(ap, void *);
+ ind_varcharsize = va_arg(ap, long);
+ ind_arrsize = va_arg(ap, long);
+ ind_offset = va_arg(ap, long);
+
+ /* if we don't have enough space, we cannot read all tuples */
+ if ((arrsize > 0 && ntuples > arrsize) || (ind_arrsize > 0 && ntuples > ind_arrsize))
+ {
+ ECPGlog("ECPGdo line %d: Incorrect number of matches: %d don't fit into array of %d\n",
+ lineno, ntuples, arrsize);
+ register_error(ECPG_TOO_MANY_MATCHES, "Too many matches line %d.", lineno);
+ status = false;
+ break;
+ }
+ for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
+ {
+ pval = PQgetvalue(results, act_tuple, act_field);
+
+ ECPGlog("ECPGdo line %d: RESULT: %s\n", lineno, pval ? pval : "");
+
+ /* Now the pval is a pointer to the value. */
+ /* We will have to decode the value */
+
+ /* check for null value and set indicator accordingly */
+ switch (ind_type)
+ {
+ case ECPGt_short:
+ case ECPGt_unsigned_short:
+ ((short *) ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
+ break;
+ case ECPGt_int:
+ case ECPGt_unsigned_int:
+ ((int *) ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
+ break;
+ case ECPGt_long:
+ case ECPGt_unsigned_long:
+ ((long *) ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
+ break;
+ default:
+ break;
+ }
+
+ switch (type)
+ {
+ long res;
+ unsigned long ures;
+ double dres;
+
+ case ECPGt_short:
+ case ECPGt_int:
+ case ECPGt_long:
+ if (pval)
+ {
+ res = strtol(pval, &scan_length, 10);
+ if (*scan_length != '\0') /* Garbage left */
+ {
+ register_error(ECPG_INT_FORMAT, "Not correctly formatted int type: %s line %d.",
+ pval, lineno);
+ status = false;
+ res = 0L;
+ }
+ }
+ else
+ res = 0L;
+
+ /* Again?! Yes */
+ switch (type)
+ {
+ case ECPGt_short:
+ ((short *) value)[act_tuple] = (short) res;
+ break;
+ case ECPGt_int:
+ ((int *) value)[act_tuple] = (int) res;
+ break;
+ case ECPGt_long:
+ ((long *) value)[act_tuple] = res;
+ break;
+ default:
+ /* Cannot happen */
+ break;
+ }
+ break;
+
+ case ECPGt_unsigned_short:
+ case ECPGt_unsigned_int:
+ case ECPGt_unsigned_long:
+ if (pval)
+ {
+ ures = strtoul(pval, &scan_length, 10);
+ if (*scan_length != '\0') /* Garbage left */
+ {
+ register_error(ECPG_UINT_FORMAT, "Not correctly formatted unsigned type: %s line %d.",
+ pval, lineno);
+ status = false;
+ ures = 0L;
+ }
+ }
+ else
+ ures = 0L;
+
+ /* Again?! Yes */
+ switch (type)
+ {
+ case ECPGt_unsigned_short:
+ ((unsigned short *) value)[act_tuple] = (unsigned short) ures;
+ break;
+ case ECPGt_unsigned_int:
+ ((unsigned int *) value)[act_tuple] = (unsigned int) ures;
+ break;
+ case ECPGt_unsigned_long:
+ ((unsigned long *) value)[act_tuple] = ures;
+ break;
+ default:
+ /* Cannot happen */
+ break;
+ }
+ break;
+
+
+ case ECPGt_float:
+ case ECPGt_double:
+ if (pval)
+ {
+ dres = strtod(pval, &scan_length);
+ if (*scan_length != '\0') /* Garbage left */
+ {
+ register_error(ECPG_FLOAT_FORMAT, "Not correctly formatted floating point type: %s line %d.",
+ pval, lineno);
+ status = false;
+ dres = 0.0;
+ }
+ }
+ else
+ dres = 0.0;
+
+ /* Again?! Yes */
+ switch (type)
+ {
+ case ECPGt_float:
+ ((float *) value)[act_tuple] = dres;
+ break;
+ case ECPGt_double:
+ ((double *) value)[act_tuple] = dres;
+ break;
+ default:
+ /* Cannot happen */
+ break;
+ }
+ break;
+
+ case ECPGt_bool:
+ if (pval)
+ {
+ if (pval[0] == 'f' && pval[1] == '\0')
+ {
+ ((char *) value)[act_tuple] = false;
+ break;
+ }
+ else if (pval[0] == 't' && pval[1] == '\0')
+ {
+ ((char *) value)[act_tuple] = true;
+ break;
+ }
+ }
+
+ register_error(ECPG_CONVERT_BOOL, "Unable to convert %s to bool on line %d.",
+ (pval ? pval : "NULL"),
+ lineno);
+ status = false;
+ break;
+
+ case ECPGt_char:
+ case ECPGt_unsigned_char:
+ {
+ if (varcharsize == 0)
+ {
+ /* char* */
+ strncpy(((char **) value)[act_tuple], pval, strlen(pval));
+ (((char **) value)[act_tuple])[strlen(pval)] = '\0';
+ }
+ else
+ {
+ strncpy((char *) (value + offset * act_tuple), pval, varcharsize);
+ if (varcharsize < strlen(pval))
+ {
+ /* truncation */
+ switch (ind_type)
+ {
+ case ECPGt_short:
+ case ECPGt_unsigned_short:
+ ((short *) ind_value)[act_tuple] = varcharsize;
+ break;
+ case ECPGt_int:
+ case ECPGt_unsigned_int:
+ ((int *) ind_value)[act_tuple] = varcharsize;
+ break;
+ case ECPGt_long:
+ case ECPGt_unsigned_long:
+ ((long *) ind_value)[act_tuple] = varcharsize;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case ECPGt_varchar:
+ {
+ struct ECPGgeneric_varchar *var =
+ (struct ECPGgeneric_varchar *) (value + offset * act_tuple);
+
+ if (varcharsize == 0)
+ strncpy(var->arr, pval, strlen(pval));
+ else
+ strncpy(var->arr, pval, varcharsize);
+
+ var->len = strlen(pval);
+ if (varcharsize > 0 && var->len > varcharsize)
+ {
+ /* truncation */
+ switch (ind_type)
+ {
+ case ECPGt_short:
+ case ECPGt_unsigned_short:
+ ((short *) ind_value)[act_tuple] = varcharsize;
+ break;
+ case ECPGt_int:
+ case ECPGt_unsigned_int:
+ ((int *) ind_value)[act_tuple] = varcharsize;
+ break;
+ case ECPGt_long:
+ case ECPGt_unsigned_long:
+ ((long *) ind_value)[act_tuple] = varcharsize;
+ break;
+ default:
+ break;
+ }
+
+ var->len = varcharsize;
+ }
+ }
+ break;
+
+ case ECPGt_EORT:
+ ECPGlog("ECPGdo line %d: Too few arguments.\n", lineno);
+ register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", lineno);
+ status = false;
+ break;
+
+ default:
+ register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.",
+ ECPGtype_name(type), lineno);
+ status = false;
+ break;
+ }
+ }
}
type = va_arg(ap, enum ECPGttype);
if (status && type != ECPGt_EORT)
{
- register_error(-1, "Too many arguments line %d.", lineno);
- return false;
+ register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", lineno);
+ status = false;
}
PQclear(results);
break;
case PGRES_EMPTY_QUERY:
/* do nothing */
- register_error(-1, "Empty query line %d.", lineno);
+ register_error(ECPG_EMPTY, "Empty query line %d.", lineno);
break;
case PGRES_COMMAND_OK:
status = true;
+ sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
+ ECPGlog("TEST: %s\n", PQcmdTuples(results));
ECPGlog("ECPGdo line %d Ok: %s\n", lineno, PQcmdStatus(results));
break;
case PGRES_NONFATAL_ERROR:
@@ -643,8 +645,9 @@ ECPGdo(int lineno, char *query,...)
case PGRES_BAD_RESPONSE:
ECPGlog("ECPGdo line %d: Error: %s",
lineno, PQerrorMessage(simple_connection));
- register_error(-1, "Error: %s line %d.",
+ register_error(ECPG_PGSQL, "Error: %s line %d.",
PQerrorMessage(simple_connection), lineno);
+ status = false;
break;
case PGRES_COPY_OUT:
ECPGlog("ECPGdo line %d: Got PGRES_COPY_OUT ... tossing.\n", lineno);
@@ -657,9 +660,11 @@ ECPGdo(int lineno, char *query,...)
default:
ECPGlog("ECPGdo line %d: Got something else, postgres error.\n",
lineno);
- register_error(-1, "Postgres error line %d.", lineno);
+ register_error(ECPG_PGSQL, "Postgres error line %d.", lineno);
+ status = false;
break;
}
+ }
/* check for asynchronous returns */
notify = PQnotifies(simple_connection);
@@ -683,11 +688,12 @@ ECPGtrans(int lineno, const char * transaction)
ECPGlog("ECPGtrans line %d action = %s\n", lineno, transaction);
if ((res = PQexec(simple_connection, transaction)) == NULL)
{
- register_error(-1, "Error in transaction processing line %d.", lineno);
+ register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
return (FALSE);
}
PQclear(res);
- committed = 1;
+ if (strcmp(transaction, "commit") == 0 || strcmp(transaction, "rollback") == 0)
+ committed = 1;
return (TRUE);
}
@@ -716,21 +722,25 @@ ECPGconnect(const char *dbname)
if (PQstatus(simple_connection) == CONNECTION_BAD)
{
ECPGfinish();
- ECPGlog("ECPGconnect: could not open database %s\n", dbname);
- register_error(-1, "ECPGconnect: could not open database %s.", dbname);
+ ECPGlog("connect: could not open database %s\n", dbname);
+ register_error(ECPG_CONNECT, "connect: could not open database %s.", dbname);
return false;
}
return true;
}
-
bool
-ECPGstatus(void)
+ECPGdisconnect(const char *dbname)
{
- return PQstatus(simple_connection) != CONNECTION_BAD;
+ if (strlen(dbname) > 0 && strcmp(PQdb(simple_connection), dbname) != 0)
+ {
+ ECPGlog("disconnect: not connected to database %s\n", dbname);
+ register_error(ECPG_DISCONNECT, "disconnect: not connected to database %s.", dbname);
+ return false;
+ }
+ return ECPGfinish();
}
-
bool
ECPGfinish(void)
{