SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_base(switch_pgsql_handle_t *handle, const char *sql, char **err) { #ifdef SWITCH_HAVE_PGSQL char *err_str = NULL; handle->affected_rows = 0; if (!db_is_up(handle)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not up!\n"); goto error; } if (handle->auto_commit == SWITCH_FALSE && handle->in_txn == SWITCH_FALSE) { if (switch_pgsql_send_query(handle, "BEGIN") != SWITCH_PGSQL_SUCCESS) { switch_pgsql_finish_results(handle); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending BEGIN!\n"); goto error; } if (switch_pgsql_finish_results(handle) != SWITCH_PGSQL_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending BEGIN!\n"); goto error; } handle->in_txn = SWITCH_TRUE; } if (switch_pgsql_send_query(handle, sql) != SWITCH_PGSQL_SUCCESS) { switch_pgsql_finish_results(handle); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending query!\n"); goto error; } return SWITCH_PGSQL_SUCCESS; error: err_str = switch_pgsql_handle_get_error(handle); if (zstr(err_str)) { err_str = strdup((char *)"SQL ERROR!"); } if (err_str) { if (!switch_stristr("already exists", err_str) && !switch_stristr("duplicate key name", err_str)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str)); } if (err) { *err = err_str; } else { free(err_str); } } #endif return SWITCH_PGSQL_FAIL; }
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_string_detailed(const char *file, const char *func, int line, switch_pgsql_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err) { #ifdef SWITCH_HAVE_PGSQL switch_pgsql_status_t sstatus = SWITCH_PGSQL_SUCCESS; char *val = NULL; switch_pgsql_result_t *result = NULL; handle->affected_rows = 0; if (switch_pgsql_handle_exec_base_detailed(file, func, line, handle, sql, err) == SWITCH_PGSQL_FAIL) { goto error; } if(switch_pgsql_next_result(handle, &result) == SWITCH_PGSQL_FAIL) { goto error; } if (result) { switch (result->status) { #if POSTGRESQL_MAJOR_VERSION >= 9 && POSTGRESQL_MINOR_VERSION >= 2 case PGRES_SINGLE_TUPLE: /* Added in PostgreSQL 9.2 */ #endif case PGRES_COMMAND_OK: case PGRES_TUPLES_OK: break; default: sstatus = SWITCH_PGSQL_FAIL; goto done; } } if (handle->affected_rows <= 0) { goto done; } val = PQgetvalue(result->result, 0, 0); strncpy(resbuf, val, len); done: switch_pgsql_free_result(&result); if (switch_pgsql_finish_results(handle) != SWITCH_PGSQL_SUCCESS) { sstatus = SWITCH_PGSQL_FAIL; } return sstatus; error: return SWITCH_PGSQL_FAIL; #else return SWITCH_PGSQL_FAIL; #endif }
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec(switch_pgsql_handle_t *handle, const char *sql, char **err) { #ifdef SWITCH_HAVE_PGSQL if (switch_pgsql_handle_exec_base(handle, sql, err) == SWITCH_PGSQL_FAIL) { goto error; } return switch_pgsql_finish_results(handle); error: #endif return SWITCH_PGSQL_FAIL; }
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_send_query(switch_pgsql_handle_t *handle, const char* sql) { #ifdef SWITCH_HAVE_PGSQL char *err_str; if (!PQsendQuery(handle->con, sql)) { err_str = switch_pgsql_handle_get_error(handle); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to send query (%s) to database: %s\n", sql, err_str); switch_pgsql_finish_results(handle); goto error; } handle->sql = sql; return SWITCH_PGSQL_SUCCESS; error: #endif return SWITCH_PGSQL_FAIL; }
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_string(switch_pgsql_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err) { #ifdef SWITCH_HAVE_PGSQL switch_pgsql_status_t sstatus = SWITCH_PGSQL_SUCCESS; char *val = NULL; switch_pgsql_result_t *result = NULL; handle->affected_rows = 0; if (switch_pgsql_handle_exec_base(handle, sql, err) == SWITCH_PGSQL_FAIL) { goto error; } if(switch_pgsql_next_result(handle, &result) == SWITCH_PGSQL_FAIL) { goto error; } if (!result || result->status != PGRES_COMMAND_OK) { sstatus = SWITCH_PGSQL_FAIL; goto done; } if (handle->affected_rows <= 0) { goto done; } val = PQgetvalue(result->result, 0, 0); strncpy(resbuf, val, len); done: switch_pgsql_free_result(&result); if (switch_pgsql_finish_results(handle) != SWITCH_PGSQL_SUCCESS) { sstatus = SWITCH_PGSQL_FAIL; } return sstatus; error: return SWITCH_PGSQL_FAIL; #else return SWITCH_PGSQL_FAIL; #endif }
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_callback_exec_detailed(const char *file, const char *func, int line, switch_pgsql_handle_t *handle, const char *sql, switch_core_db_callback_func_t callback, void *pdata, char **err) { #ifdef SWITCH_HAVE_PGSQL char *err_str = NULL; int row = 0, col = 0, err_cnt = 0; switch_pgsql_result_t *result = NULL; handle->affected_rows = 0; switch_assert(callback != NULL); if (switch_pgsql_handle_exec_base(handle, sql, err) == SWITCH_PGSQL_FAIL) { goto error; } if (switch_pgsql_next_result(handle, &result) == SWITCH_PGSQL_FAIL) { err_cnt++; err_str = switch_pgsql_handle_get_error(handle); if (result && !zstr(result->err)) { switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(result->err)); } if (!zstr(err_str)) { switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str)); } switch_safe_free(err_str); err_str = NULL; } while (result != NULL) { /*switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Processing result with %d rows and %d columns.\n", result->rows, result->cols);*/ for (row = 0; row < result->rows; ++row) { char **names; char **vals; names = calloc(result->cols, sizeof(*names)); vals = calloc(result->cols, sizeof(*vals)); switch_assert(names && vals); for (col = 0; col < result->cols; ++col) { char * tmp; int len; tmp = PQfname(result->result, col); if (tmp) { len = strlen(tmp); names[col] = malloc(len+1); names[col][len] = '\0'; strncpy(names[col], tmp, len); len = PQgetlength(result->result, row, col); vals[col] = malloc(len+1); vals[col][len] = '\0'; tmp = PQgetvalue(result->result, row, col); strncpy(vals[col], tmp, len); /*switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Processing result row %d, col %d: %s => %s\n", row, col, names[col], vals[col]);*/ } else { /*switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Processing result row %d, col %d.\n", row, col);*/ switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: Column number %d out of range\n", col); } } /*switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Executing callback for row %d...\n", row);*/ if (callback(pdata, result->cols, vals, names)) { switch_pgsql_finish_results(handle); /* Makes sure next call to switch_pgsql_next_result will return NULL */ row = result->rows; /* Makes us exit the for loop */ } for (col = 0; col < result->cols; ++col) { free(names[col]); free(vals[col]); } free(names); free(vals); } switch_pgsql_free_result(&result); if (switch_pgsql_next_result(handle, &result) == SWITCH_PGSQL_FAIL) { err_cnt++; err_str = switch_pgsql_handle_get_error(handle); if (result && !zstr(result->err)) { switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(result->err)); } if (!zstr(err_str)) { switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str)); } switch_safe_free(err_str); err_str = NULL; } } if (err_cnt) { goto error; } return SWITCH_PGSQL_SUCCESS; error: #endif return SWITCH_PGSQL_FAIL; }