diff options
Diffstat (limited to 'src/interfaces/ecpg/lib/ecpglib.c')
-rw-r--r-- | src/interfaces/ecpg/lib/ecpglib.c | 626 |
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) { |