static void ECPGnoticeReceiver(void *arg, const PGresult *result) { char *sqlstate = PQresultErrorField(result, PG_DIAG_SQLSTATE); char *message = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY); struct sqlca_t *sqlca = ECPGget_sqlca(); int sqlcode; if (sqlstate == NULL) sqlstate = ECPG_SQLSTATE_ECPG_INTERNAL_ERROR; if (message == NULL) /* Shouldn't happen, but need to be sure */ message = "No message received"; /* these are not warnings */ if (strncmp(sqlstate, "00", 2) == 0) return; ECPGlog("%s", message); /* map to SQLCODE for backward compatibility */ if (strcmp(sqlstate, ECPG_SQLSTATE_INVALID_CURSOR_NAME) == 0) sqlcode = ECPG_WARNING_UNKNOWN_PORTAL; else if (strcmp(sqlstate, ECPG_SQLSTATE_ACTIVE_SQL_TRANSACTION) == 0) sqlcode = ECPG_WARNING_IN_TRANSACTION; else if (strcmp(sqlstate, ECPG_SQLSTATE_NO_ACTIVE_SQL_TRANSACTION) == 0) sqlcode = ECPG_WARNING_NO_TRANSACTION; else if (strcmp(sqlstate, ECPG_SQLSTATE_DUPLICATE_CURSOR) == 0) sqlcode = ECPG_WARNING_PORTAL_EXISTS; else sqlcode = 0; strncpy(sqlca->sqlstate, sqlstate, sizeof(sqlca->sqlstate)); sqlca->sqlcode = sqlcode; sqlca->sqlwarn[2] = 'W'; sqlca->sqlwarn[0] = 'W'; strncpy(sqlca->sqlerrm.sqlerrmc, message, sizeof(sqlca->sqlerrm.sqlerrmc)); sqlca->sqlerrm.sqlerrmc[sizeof(sqlca->sqlerrm.sqlerrmc) - 1] = 0; sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc); ECPGlog("raising sqlcode %d\n", sqlcode); }
static void ecpg_finish(struct connection * act) { if (act != NULL) { struct ECPGtype_information_cache *cache, *ptr; PQfinish(act->connection); /* * no need to lock connections_mutex - we're always called by * ECPGdisconnect or ECPGconnect, which are holding the lock */ /* remove act from the list */ if (act == all_connections) all_connections = act->next; else { struct connection *con; for (con = all_connections; con->next && con->next != act; con = con->next); if (con->next) con->next = act->next; } #ifdef ENABLE_THREAD_SAFETY if (pthread_getspecific(actual_connection_key) == act) pthread_setspecific(actual_connection_key, all_connections); #endif if (actual_connection == act) actual_connection = all_connections; ECPGlog("ecpg_finish: Connection %s closed.\n", act->name); for (cache = act->cache_head; cache; ptr = cache, cache = cache->next, ECPGfree(ptr)); ECPGfree(act->name); ECPGfree(act); } else ECPGlog("ecpg_finish: called an extra time.\n"); }
struct connection * ECPGget_connection(const char *connection_name) { struct connection *ret = NULL; if ((connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0)) { #ifdef ENABLE_THREAD_SAFETY ret = pthread_getspecific(actual_connection_key); /* * if no connection in TSD for this thread, get the global default * connection and hope the user knows what they're doing (i.e. using * their own mutex to protect that connection from concurrent accesses */ if (NULL == ret) { ECPGlog("no TSD connection here either, using global\n"); ret = actual_connection; } else ECPGlog("got TSD connection\n"); #else ret = actual_connection; #endif } else { #ifdef ENABLE_THREAD_SAFETY pthread_mutex_lock(&connections_mutex); #endif ret = ecpg_get_connection_nr(connection_name); #ifdef ENABLE_THREAD_SAFETY pthread_mutex_unlock(&connections_mutex); #endif } return (ret); }
static struct connection * ecpg_get_connection_nr(const char *connection_name) { struct connection *ret = NULL; if ((connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0)) { #ifdef ENABLE_THREAD_SAFETY ret = pthread_getspecific(actual_connection_key); /* * if no connection in TSD for this thread, get the global default * connection and hope the user knows what they're doing (i.e. using * their own mutex to protect that connection from concurrent accesses */ if (NULL == ret) { ECPGlog("no TSD connection, going for global\n"); ret = actual_connection; } else ECPGlog("got the TSD connection\n"); #else ret = actual_connection; #endif } else { struct connection *con; for (con = all_connections; con != NULL; con = con->next) { if (strcmp(connection_name, con->name) == 0) break; } ret = con; } return (ret); }
void ECPGraise_backend(int line, PGresult *result, PGconn *conn, int compat) { struct sqlca_t *sqlca = ECPGget_sqlca(); char *sqlstate; char *message; if (result) { sqlstate = PQresultErrorField(result, PG_DIAG_SQLSTATE); if (sqlstate == NULL) sqlstate = ECPG_SQLSTATE_ECPG_INTERNAL_ERROR; message = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY); } else { sqlstate = ECPG_SQLSTATE_ECPG_INTERNAL_ERROR; message = PQerrorMessage(conn); } /* copy error message */ snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "'%s' in line %d.", message, line); sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc); /* copy SQLSTATE */ strncpy(sqlca->sqlstate, sqlstate, sizeof(sqlca->sqlstate)); /* assign SQLCODE for backward compatibility */ if (strncmp(sqlca->sqlstate, "23505", sizeof(sqlca->sqlstate)) == 0) sqlca->sqlcode = INFORMIX_MODE(compat) ? ECPG_INFORMIX_DUPLICATE_KEY : ECPG_DUPLICATE_KEY; else if (strncmp(sqlca->sqlstate, "21000", sizeof(sqlca->sqlstate)) == 0) sqlca->sqlcode = INFORMIX_MODE(compat) ? ECPG_INFORMIX_SUBSELECT_NOT_ONE : ECPG_SUBSELECT_NOT_ONE; else sqlca->sqlcode = ECPG_PGSQL; ECPGlog("raising sqlstate %.*s in line %d, '%s'.\n", sizeof(sqlca->sqlstate), sqlca->sqlstate, line, sqlca->sqlerrm.sqlerrmc); /* free all memory we have allocated for the user */ ECPGfree_auto_mem(); }
bool ECPGsetcommit(int lineno, const char *mode, const char *connection_name) { struct connection *con = ECPGget_connection(connection_name); PGresult *results; if (!ECPGinit(con, connection_name, lineno)) return (false); ECPGlog("ECPGsetcommit line %d action = %s connection = %s\n", lineno, mode, con->name); if (con->autocommit == true && strncmp(mode, "off", strlen("off")) == 0) { if (con->committed) { if ((results = PQexec(con->connection, "begin transaction")) == NULL) { ECPGraise(lineno, ECPG_TRANS, ECPG_SQLSTATE_TRANSACTION_RESOLUTION_UNKNOWN, NULL); return false; } PQclear(results); con->committed = false; } con->autocommit = false; } else if (con->autocommit == false && strncmp(mode, "on", strlen("on")) == 0) { if (!con->committed) { if ((results = PQexec(con->connection, "commit")) == NULL) { ECPGraise(lineno, ECPG_TRANS, ECPG_SQLSTATE_TRANSACTION_RESOLUTION_UNKNOWN, NULL); return false; } PQclear(results); con->committed = true; } con->autocommit = true; } return true; }
bool ECPGget_data(const PGresult *results, int act_tuple, int act_field, 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) { struct sqlca_t *sqlca = ECPGget_sqlca(); char *pval = (char *) PQgetvalue(results, act_tuple, act_field); int binary = PQfformat(results, act_field); int size = PQgetlength(results, act_tuple, act_field); int value_for_indicator = 0; long log_offset; /* * use a global variable to see if the environment variable * ECPG_REGRESSION is set or not. Remember the state in order to avoid * subsequent calls to getenv() for this purpose. */ if (ECPG_regression_mode == NOT_CHECKED) { if (getenv("ECPG_REGRESSION")) ECPG_regression_mode = REGRESS; else ECPG_regression_mode = NORMAL; } /* * If we are running in a regression test, do not log the offset variable, * it depends on the machine's alignment. */ if (ECPG_regression_mode == REGRESS) log_offset = -1; else log_offset = offset; ECPGlog("ECPGget_data line %d: RESULT: %s offset: %ld array: %s\n", lineno, pval ? (binary ? "BINARY" : pval) : "EMPTY", log_offset, isarray ? "Yes" : "No"); /* We will have to decode the value */ /* * check for null value and set indicator accordingly, i.e. -1 if NULL and * 0 if not */ if (PQgetisnull(results, act_tuple, act_field)) value_for_indicator = -1; switch (ind_type) { case ECPGt_short: case ECPGt_unsigned_short: *((short *) (ind + ind_offset * act_tuple)) = value_for_indicator; break; case ECPGt_int: case ECPGt_unsigned_int: *((int *) (ind + ind_offset * act_tuple)) = value_for_indicator; break; case ECPGt_long: case ECPGt_unsigned_long: *((long *) (ind + ind_offset * act_tuple)) = value_for_indicator; break; #ifdef HAVE_LONG_LONG_INT_64 case ECPGt_long_long: case ECPGt_unsigned_long_long: *((long long int *) (ind + ind_offset * act_tuple)) = value_for_indicator; break; #endif /* HAVE_LONG_LONG_INT_64 */ case ECPGt_NO_INDICATOR: if (value_for_indicator == -1) { if (force_indicator == false) { /* * 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); } else { ECPGraise(lineno, ECPG_MISSING_INDICATOR, ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER, NULL); return (false); } } break; default: ECPGraise(lineno, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, ECPGtype_name(ind_type)); return (false); break; } if (value_for_indicator == -1) return (true); /* pval is a pointer to the value */ /* let's check if it really is an array if it should be one */ if (isarray == ECPG_ARRAY_ARRAY) { if (!pval || *pval != '{') { ECPGraise(lineno, ECPG_DATA_NOT_ARRAY, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL); return (false); } switch (type) { case ECPGt_char: case ECPGt_unsigned_char: case ECPGt_varchar: break; default: pval++; break; } } do { if (binary) { if (pval) { if (varcharsize == 0 || varcharsize * offset >= size) memcpy((char *) ((long) var + offset * act_tuple), pval, size); else { memcpy((char *) ((long) var + offset * act_tuple), pval, varcharsize * offset); if (varcharsize * offset < size) { /* truncation */ switch (ind_type) { case ECPGt_short: case ECPGt_unsigned_short: *((short *) (ind + ind_offset * act_tuple)) = size; break; case ECPGt_int: case ECPGt_unsigned_int: *((int *) (ind + ind_offset * act_tuple)) = size; break; case ECPGt_long: case ECPGt_unsigned_long: *((long *) (ind + ind_offset * act_tuple)) = size; break; #ifdef HAVE_LONG_LONG_INT_64 case ECPGt_long_long: case ECPGt_unsigned_long_long: *((long long int *) (ind + ind_offset * act_tuple)) = size; break; #endif /* HAVE_LONG_LONG_INT_64 */ default: break; } sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W'; } } pval += size; } } else { switch (type) { long res; unsigned long ures; double dres; char *scan_length; numeric *nres; date ddres; timestamp tres; interval *ires; case ECPGt_short: case ECPGt_int: case ECPGt_long: if (pval) { res = strtol(pval, &scan_length, 10); if (garbage_left(isarray, scan_length, compat)) { ECPGraise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } pval = scan_length; } else res = 0L; switch (type) { case ECPGt_short: *((short *) (var + offset * act_tuple)) = (short) res; break; case ECPGt_int: *((int *) (var + offset * act_tuple)) = (int) res; break; case ECPGt_long: *((long *) (var + offset * act_tuple)) = (long) 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 (garbage_left(isarray, scan_length, compat)) { ECPGraise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } pval = scan_length; } else ures = 0L; switch (type) { case ECPGt_unsigned_short: *((unsigned short *) (var + offset * act_tuple)) = (unsigned short) ures; break; case ECPGt_unsigned_int: *((unsigned int *) (var + offset * act_tuple)) = (unsigned int) ures; break; case ECPGt_unsigned_long: *((unsigned long *) (var + offset * act_tuple)) = (unsigned long) ures; break; default: /* Cannot happen */ break; } break; #ifdef HAVE_LONG_LONG_INT_64 #ifdef HAVE_STRTOLL case ECPGt_long_long: if (pval) { *((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10); if (garbage_left(isarray, scan_length, compat)) { ECPGraise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } pval = scan_length; } else *((long long int *) (var + offset * act_tuple)) = (long long) 0; break; #endif /* HAVE_STRTOLL */ #ifdef HAVE_STRTOULL case ECPGt_unsigned_long_long: if (pval) { *((unsigned long long int *) (var + offset * act_tuple)) = strtoull(pval, &scan_length, 10); if ((isarray && *scan_length != ',' && *scan_length != '}') || (!isarray && !(INFORMIX_MODE(compat) && *scan_length == '.') && *scan_length != '\0' && *scan_length != ' ')) /* Garbage left */ { ECPGraise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } pval = scan_length; } else *((unsigned long long int *) (var + offset * act_tuple)) = (long long) 0; break; #endif /* HAVE_STRTOULL */ #endif /* HAVE_LONG_LONG_INT_64 */ case ECPGt_float: case ECPGt_double: if (pval) { if (isarray && *pval == '"') dres = strtod(pval + 1, &scan_length); else dres = strtod(pval, &scan_length); if (isarray && *scan_length == '"') scan_length++; if (garbage_left(isarray, scan_length, compat)) { ECPGraise(lineno, ECPG_FLOAT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } pval = scan_length; } else dres = 0.0; switch (type) { case ECPGt_float: *((float *) (var + offset * act_tuple)) = dres; break; case ECPGt_double: *((double *) (var + offset * act_tuple)) = dres; break; default: /* Cannot happen */ break; } break; case ECPGt_bool: if (pval) { if (pval[0] == 'f' && pval[1] == '\0') { if (offset == sizeof(char)) *((char *) (var + offset * act_tuple)) = false; else if (offset == sizeof(int)) *((int *) (var + offset * act_tuple)) = false; else ECPGraise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, "different size"); break; } else if (pval[0] == 't' && pval[1] == '\0') { if (offset == sizeof(char)) *((char *) (var + offset * act_tuple)) = true; else if (offset == sizeof(int)) *((int *) (var + offset * act_tuple)) = true; else ECPGraise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, "different size"); break; } else if (pval[0] == '\0' && PQgetisnull(results, act_tuple, act_field)) { /* NULL is valid */ break; } } ECPGraise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); break; case ECPGt_char: case ECPGt_unsigned_char: if (pval) { if (varcharsize == 0 || varcharsize > size) strncpy((char *) ((long) var + offset * act_tuple), pval, size + 1); else { strncpy((char *) ((long) var + offset * act_tuple), pval, varcharsize); if (varcharsize < size) { /* truncation */ switch (ind_type) { case ECPGt_short: case ECPGt_unsigned_short: *((short *) (ind + ind_offset * act_tuple)) = size; break; case ECPGt_int: case ECPGt_unsigned_int: *((int *) (ind + ind_offset * act_tuple)) = size; break; case ECPGt_long: case ECPGt_unsigned_long: *((long *) (ind + ind_offset * act_tuple)) = size; break; #ifdef HAVE_LONG_LONG_INT_64 case ECPGt_long_long: case ECPGt_unsigned_long_long: *((long long int *) (ind + ind_offset * act_tuple)) = size; break; #endif /* HAVE_LONG_LONG_INT_64 */ default: break; } sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W'; } } pval += size; } break; case ECPGt_varchar: if (pval) { struct ECPGgeneric_varchar *variable = (struct ECPGgeneric_varchar *) ((long) var + offset * act_tuple); variable->len = size; if (varcharsize == 0) strncpy(variable->arr, pval, variable->len); else { strncpy(variable->arr, pval, varcharsize); if (variable->len > varcharsize) { /* truncation */ switch (ind_type) { case ECPGt_short: case ECPGt_unsigned_short: *((short *) (ind + offset * act_tuple)) = variable->len; break; case ECPGt_int: case ECPGt_unsigned_int: *((int *) (ind + offset * act_tuple)) = variable->len; break; case ECPGt_long: case ECPGt_unsigned_long: *((long *) (ind + offset * act_tuple)) = variable->len; break; #ifdef HAVE_LONG_LONG_INT_64 case ECPGt_long_long: case ECPGt_unsigned_long_long: *((long long int *) (ind + ind_offset * act_tuple)) = variable->len; break; #endif /* HAVE_LONG_LONG_INT_64 */ default: break; } sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W'; variable->len = varcharsize; } } pval += size; } break; case ECPGt_decimal: case ECPGt_numeric: if (pval) { if (isarray && *pval == '"') nres = PGTYPESnumeric_from_asc(pval + 1, &scan_length); else nres = PGTYPESnumeric_from_asc(pval, &scan_length); /* did we get an error? */ if (nres == NULL) { ECPGlog("ECPGget_data line %d: RESULT: %s errno %d\n", lineno, pval ? pval : "", errno); if (INFORMIX_MODE(compat)) { /* * Informix wants its own NULL value here * instead of an error */ nres = PGTYPESnumeric_new(); if (nres) ECPGset_noind_null(ECPGt_numeric, nres); else { ECPGraise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL); return (false); } } else { ECPGraise(lineno, ECPG_NUMERIC_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } else { if (isarray && *scan_length == '"') scan_length++; if (garbage_left(isarray, scan_length, compat)) { free(nres); ECPGraise(lineno, ECPG_NUMERIC_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } pval = scan_length; } else nres = PGTYPESnumeric_from_asc("0.0", &scan_length); if (type == ECPGt_numeric) PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple)); else PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple)); free(nres); break; case ECPGt_interval: if (pval) { if (isarray && *pval == '"') ires = PGTYPESinterval_from_asc(pval + 1, &scan_length); else ires = PGTYPESinterval_from_asc(pval, &scan_length); /* did we get an error? */ if (ires == NULL) { if (INFORMIX_MODE(compat)) { /* * Informix wants its own NULL value here * instead of an error */ ires = (interval *) ECPGalloc(sizeof(interval), lineno); if (!ires) return (false); ECPGset_noind_null(ECPGt_interval, ires); } else { ECPGraise(lineno, ECPG_INTERVAL_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } else { if (isarray && *scan_length == '"') scan_length++; if (garbage_left(isarray, scan_length, compat)) { free(ires); ECPGraise(lineno, ECPG_INTERVAL_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } pval = scan_length; } else ires = PGTYPESinterval_from_asc("0 seconds", NULL); PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple)); free(ires); break; case ECPGt_date: if (pval) { if (isarray && *pval == '"') ddres = PGTYPESdate_from_asc(pval + 1, &scan_length); else ddres = PGTYPESdate_from_asc(pval, &scan_length); /* did we get an error? */ if (errno != 0) { if (INFORMIX_MODE(compat)) { /* * Informix wants its own NULL value here * instead of an error */ ECPGset_noind_null(ECPGt_date, &ddres); } else { ECPGraise(lineno, ECPG_DATE_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } else { if (isarray && *scan_length == '"') scan_length++; if (garbage_left(isarray, scan_length, compat)) { ECPGraise(lineno, ECPG_DATE_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } *((date *) (var + offset * act_tuple)) = ddres; pval = scan_length; } break; case ECPGt_timestamp: if (pval) { if (isarray && *pval == '"') tres = PGTYPEStimestamp_from_asc(pval + 1, &scan_length); else tres = PGTYPEStimestamp_from_asc(pval, &scan_length); /* did we get an error? */ if (errno != 0) { if (INFORMIX_MODE(compat)) { /* * Informix wants its own NULL value here * instead of an error */ ECPGset_noind_null(ECPGt_timestamp, &tres); } else { ECPGraise(lineno, ECPG_TIMESTAMP_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } else { if (isarray && *scan_length == '"') scan_length++; if (garbage_left(isarray, scan_length, compat)) { ECPGraise(lineno, ECPG_TIMESTAMP_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } *((timestamp *) (var + offset * act_tuple)) = tres; pval = scan_length; } break; default: ECPGraise(lineno, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, ECPGtype_name(type)); return (false); break; } if (isarray == ECPG_ARRAY_ARRAY) { bool string = false; /* set array to next entry */ ++act_tuple; /* set pval to the next entry */ for (; string || (*pval != ',' && *pval != '}' && *pval != '\0'); ++pval) if (*pval == '"') string = string ? false : true; if (*pval == ',') ++pval; } else if (isarray == ECPG_ARRAY_VECTOR) { bool string = false; /* set array to next entry */ ++act_tuple; /* set pval to the next entry */ for (; string || (*pval != ' ' && *pval != '\0'); ++pval) if (*pval == '"') string = string ? false : true; if (*pval == ' ') ++pval; } } } while (*pval != '\0' && ((isarray == ECPG_ARRAY_ARRAY && *pval != '}') || isarray == ECPG_ARRAY_VECTOR)); return (true); }
void ECPGraise(int line, int code, const char *sqlstate, const char *str) { struct sqlca_t *sqlca = ECPGget_sqlca(); sqlca->sqlcode = code; strncpy(sqlca->sqlstate, sqlstate, sizeof(sqlca->sqlstate)); switch (code) { case ECPG_NOT_FOUND: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "No data found in line %d.", line); break; case ECPG_OUT_OF_MEMORY: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Out of memory in line %d.", line); break; case ECPG_UNSUPPORTED: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Unsupported type %s in line %d.", str, line); break; case ECPG_TOO_MANY_ARGUMENTS: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Too many arguments in line %d.", line); break; case ECPG_TOO_FEW_ARGUMENTS: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Too few arguments in line %d.", line); break; case ECPG_INT_FORMAT: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Not correctly formatted int type: %s line %d.", str, line); break; case ECPG_UINT_FORMAT: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Not correctly formatted unsigned type: %s in line %d.", str, line); break; case ECPG_FLOAT_FORMAT: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Not correctly formatted floating-point type: %s in line %d.", str, line); break; case ECPG_CONVERT_BOOL: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Unable to convert %s to bool on line %d.", str, line); break; case ECPG_EMPTY: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Empty query in line %d.", line); break; case ECPG_MISSING_INDICATOR: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "NULL value without indicator in line %d.", line); break; case ECPG_NO_ARRAY: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Variable is not an array in line %d.", line); break; case ECPG_DATA_NOT_ARRAY: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Data read from backend is not an array in line %d.", line); break; case ECPG_ARRAY_INSERT: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Trying to insert an array of variables in line %d.", line); break; case ECPG_NO_CONN: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "No such connection %s in line %d.", str, line); break; case ECPG_NOT_CONN: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Not connected to '%s' in line %d.", str, line); break; case ECPG_INVALID_STMT: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Invalid statement name %s in line %d.", str, line); break; case ECPG_UNKNOWN_DESCRIPTOR: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Descriptor %s not found in line %d.", str, line); break; case ECPG_INVALID_DESCRIPTOR_INDEX: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Descriptor index out of range in line %d.", line); break; case ECPG_UNKNOWN_DESCRIPTOR_ITEM: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Unknown descriptor item %s in line %d.", str, line); break; case ECPG_VAR_NOT_NUMERIC: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Variable is not a numeric type in line %d.", line); break; case ECPG_VAR_NOT_CHAR: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Variable is not a character type in line %d.", line); break; case ECPG_TRANS: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Error in transaction processing in line %d.", line); break; case ECPG_CONNECT: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "Could not connect to database %s in line %d.", str, line); break; default: snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "SQL error #%d in line %d.", code, line); break; } sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc); ECPGlog("raising sqlcode %d in line %d, '%s'.\n", code, line, sqlca->sqlerrm.sqlerrmc); /* free all memory we have allocated for the user */ ECPGfree_auto_mem(); }
/* this contains some quick hacks, needs to be cleaned up, but it works */ bool ECPGconnect(int lineno, int c, const char *name, const char *user, const char *passwd, const char *connection_name, int autocommit) { struct sqlca_t *sqlca = ECPGget_sqlca(); enum COMPAT_MODE compat = c; struct connection *this; char *dbname = name ? ECPGstrdup(name, lineno) : NULL, *host = NULL, *tmp, *port = NULL, *realname = NULL, *options = NULL; ECPGinit_sqlca(sqlca); ECPGclear_auto_mem(); if (INFORMIX_MODE(compat)) { char *envname; /* * Informix uses an environment variable DBPATH that overrides the * connection parameters given here. We do the same with PG_DBPATH as * the syntax is different. */ envname = getenv("PG_DBPATH"); if (envname) { ECPGfree(dbname); dbname = ECPGstrdup(envname, lineno); } } if ((this = (struct connection *) ECPGalloc(sizeof(struct connection), lineno)) == NULL) return false; if (dbname == NULL && connection_name == NULL) connection_name = "DEFAULT"; if (dbname != NULL) { /* get the detail information out of dbname */ if (strchr(dbname, '@') != NULL) { /* old style: dbname[@server][:port] */ tmp = strrchr(dbname, ':'); if (tmp != NULL) /* port number given */ { port = ECPGstrdup(tmp + 1, lineno); *tmp = '\0'; } tmp = strrchr(dbname, '@'); if (tmp != NULL) /* host name given */ { host = ECPGstrdup(tmp + 1, lineno); *tmp = '\0'; } realname = ECPGstrdup(dbname, lineno); } else if (strncmp(dbname, "tcp:", 4) == 0 || strncmp(dbname, "unix:", 5) == 0) { int offset = 0; /* * only allow protocols tcp and unix */ if (strncmp(dbname, "tcp:", 4) == 0) offset = 4; else if (strncmp(dbname, "unix:", 5) == 0) offset = 5; if (strncmp(dbname + offset, "postgresql://", strlen("postgresql://")) == 0) { /*------ * new style: * <tcp|unix>:postgresql://server[:port|:/unixsocket/path:] * [/db name][?options] *------ */ offset += strlen("postgresql://"); tmp = strrchr(dbname + offset, '?'); if (tmp != NULL) /* options given */ { options = ECPGstrdup(tmp + 1, lineno); *tmp = '\0'; } tmp = last_dir_separator(dbname + offset); if (tmp != NULL) /* database name given */ { realname = ECPGstrdup(tmp + 1, lineno); *tmp = '\0'; } tmp = strrchr(dbname + offset, ':'); if (tmp != NULL) /* port number or Unix socket path given */ { char *tmp2; *tmp = '\0'; if ((tmp2 = strchr(tmp + 1, ':')) != NULL) { *tmp2 = '\0'; host = ECPGstrdup(tmp + 1, lineno); if (strncmp(dbname, "unix:", 5) != 0) { ECPGlog("connect: socketname %s given for TCP connection in line %d\n", host, lineno); ECPGraise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, realname ? realname : "<DEFAULT>"); if (host) ECPGfree(host); if (port) ECPGfree(port); if (options) ECPGfree(options); if (realname) ECPGfree(realname); if (dbname) ECPGfree(dbname); return false; } } else port = ECPGstrdup(tmp + 1, lineno); } if (strncmp(dbname, "unix:", 5) == 0) { if (strcmp(dbname + offset, "localhost") != 0 && strcmp(dbname + offset, "127.0.0.1") != 0) { ECPGlog("connect: non-localhost access via sockets in line %d\n", lineno); ECPGraise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, realname ? realname : "<DEFAULT>"); if (host) ECPGfree(host); if (port) ECPGfree(port); if (options) ECPGfree(options); if (realname) ECPGfree(realname); if (dbname) ECPGfree(dbname); ecpg_finish(this); return false; } } else host = ECPGstrdup(dbname + offset, lineno); } else realname = ECPGstrdup(dbname, lineno); } else realname = ECPGstrdup(dbname, lineno); } else realname = NULL; /* add connection to our list */ #ifdef ENABLE_THREAD_SAFETY pthread_mutex_lock(&connections_mutex); #endif if (connection_name != NULL) this->name = ECPGstrdup(connection_name, lineno); else this->name = ECPGstrdup(realname, lineno); this->cache_head = NULL; if (all_connections == NULL) this->next = NULL; else this->next = all_connections; all_connections = this; #ifdef ENABLE_THREAD_SAFETY pthread_once(&actual_connection_key_once, ecpg_actual_connection_init); pthread_setspecific(actual_connection_key, all_connections); #endif actual_connection = all_connections; ECPGlog("ECPGconnect: opening database %s on %s port %s %s%s%s%s\n", realname ? realname : "<DEFAULT>", host ? host : "<DEFAULT>", port ? port : "<DEFAULT>", options ? "with options " : "", options ? options : "", user ? "for user " : "", user ? user : ""); this->connection = PQsetdbLogin(host, port, options, NULL, realname, user, passwd); if (PQstatus(this->connection) == CONNECTION_BAD) { const char *errmsg = PQerrorMessage(this->connection); char *db = realname ? realname : "<DEFAULT>"; ECPGlog("connect: could not open database %s on %s port %s %s%s%s%s in line %d\n\t%s\n", db, host ? host : "<DEFAULT>", port ? port : "<DEFAULT>", options ? "with options " : "", options ? options : "", user ? "for user " : "", user ? user : "", lineno, errmsg); ecpg_finish(this); #ifdef ENABLE_THREAD_SAFETY pthread_mutex_unlock(&connections_mutex); #endif ECPGraise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, db); if (host) ECPGfree(host); if (port) ECPGfree(port); if (options) ECPGfree(options); if (realname) ECPGfree(realname); if (dbname) ECPGfree(dbname); return false; } #ifdef ENABLE_THREAD_SAFETY pthread_mutex_unlock(&connections_mutex); #endif if (host) ECPGfree(host); if (port) ECPGfree(port); if (options) ECPGfree(options); if (realname) ECPGfree(realname); if (dbname) ECPGfree(dbname); this->committed = true; this->autocommit = autocommit; PQsetNoticeReceiver(this->connection, &ECPGnoticeReceiver, (void *) this); return true; }