| File: | src/switch_pgsql.c |
| Location: | line 529, column 11 |
| Description: | Access to field 'status' results in a dereference of a null pointer (loaded from variable 'result') |
| 1 | /* | |||
| 2 | * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application | |||
| 3 | * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org> | |||
| 4 | * | |||
| 5 | * Version: MPL 1.1 | |||
| 6 | * | |||
| 7 | * The contents of this file are subject to the Mozilla Public License Version | |||
| 8 | * 1.1 (the "License"); you may not use this file except in compliance with | |||
| 9 | * the License. You may obtain a copy of the License at | |||
| 10 | * http://www.mozilla.org/MPL/ | |||
| 11 | * | |||
| 12 | * Software distributed under the License is distributed on an "AS IS" basis, | |||
| 13 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |||
| 14 | * for the specific language governing rights and limitations under the | |||
| 15 | * License. | |||
| 16 | * | |||
| 17 | * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application | |||
| 18 | * | |||
| 19 | * The Initial Developer of the Original Code is | |||
| 20 | * Anthony Minessale II <anthm@freeswitch.org> | |||
| 21 | * Portions created by the Initial Developer are Copyright (C) | |||
| 22 | * the Initial Developer. All Rights Reserved. | |||
| 23 | * | |||
| 24 | * Contributor(s): | |||
| 25 | * | |||
| 26 | * Anthony Minessale II <anthm@freeswitch.org> | |||
| 27 | * Eliot Gable <egable@gmail.com> | |||
| 28 | * | |||
| 29 | * switch_pgsql.c -- PGSQL Driver | |||
| 30 | * | |||
| 31 | */ | |||
| 32 | ||||
| 33 | #include <switch.h> | |||
| 34 | ||||
| 35 | #ifndef WIN32 | |||
| 36 | #include <switch_private.h> | |||
| 37 | #endif | |||
| 38 | ||||
| 39 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 40 | #include <libpq-fe.h> | |||
| 41 | #include <poll.h> | |||
| 42 | ||||
| 43 | ||||
| 44 | struct switch_pgsql_handle { | |||
| 45 | char *dsn; | |||
| 46 | char *sql; | |||
| 47 | PGconn* con; | |||
| 48 | int sock; | |||
| 49 | switch_pgsql_state_t state; | |||
| 50 | int affected_rows; | |||
| 51 | int num_retries; | |||
| 52 | switch_bool_t auto_commit; | |||
| 53 | switch_bool_t in_txn; | |||
| 54 | }; | |||
| 55 | ||||
| 56 | struct switch_pgsql_result { | |||
| 57 | PGresult *result; | |||
| 58 | ExecStatusType status; | |||
| 59 | char *err; | |||
| 60 | int rows; | |||
| 61 | int cols; | |||
| 62 | }; | |||
| 63 | #endif | |||
| 64 | ||||
| 65 | SWITCH_DECLARE(switch_pgsql_handle_t *)__attribute__((visibility("default"))) switch_pgsql_handle_t * switch_pgsql_handle_new(const char *dsn) | |||
| 66 | { | |||
| 67 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 68 | switch_pgsql_handle_t *new_handle; | |||
| 69 | ||||
| 70 | if (!(new_handle = malloc(sizeof(*new_handle)))) { | |||
| 71 | goto err; | |||
| 72 | } | |||
| 73 | ||||
| 74 | memset(new_handle, 0, sizeof(*new_handle)); | |||
| 75 | ||||
| 76 | if (!(new_handle->dsn = strdup(dsn)(__extension__ (__builtin_constant_p (dsn) && ((size_t )(const void *)((dsn) + 1) - (size_t)(const void *)(dsn) == 1 ) ? (((const char *) (dsn))[0] == '\0' ? (char *) calloc ((size_t ) 1, (size_t) 1) : ({ size_t __len = strlen (dsn) + 1; char * __retval = (char *) malloc (__len); if (__retval != ((void*)0 )) __retval = (char *) memcpy (__retval, dsn, __len); __retval ; })) : __strdup (dsn))))) { | |||
| 77 | goto err; | |||
| 78 | } | |||
| 79 | ||||
| 80 | new_handle->sock = 0; | |||
| 81 | new_handle->state = SWITCH_PGSQL_STATE_INIT; | |||
| 82 | new_handle->con = NULL((void*)0); | |||
| 83 | new_handle->affected_rows = 0; | |||
| 84 | new_handle->num_retries = DEFAULT_PGSQL_RETRIES120; | |||
| 85 | new_handle->auto_commit = SWITCH_TRUE; | |||
| 86 | new_handle->in_txn = SWITCH_FALSE; | |||
| 87 | ||||
| 88 | return new_handle; | |||
| 89 | ||||
| 90 | err: | |||
| 91 | if (new_handle) { | |||
| 92 | switch_safe_free(new_handle->dsn)if (new_handle->dsn) {free(new_handle->dsn);new_handle-> dsn=((void*)0);}; | |||
| 93 | switch_safe_free(new_handle)if (new_handle) {free(new_handle);new_handle=((void*)0);}; | |||
| 94 | } | |||
| 95 | #endif | |||
| 96 | return NULL((void*)0); | |||
| 97 | } | |||
| 98 | ||||
| 99 | ||||
| 100 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 101 | static int db_is_up(switch_pgsql_handle_t *handle) | |||
| 102 | { | |||
| 103 | int ret = 0; | |||
| 104 | switch_event_t *event; | |||
| 105 | char *err_str = NULL((void*)0); | |||
| 106 | int max_tries = DEFAULT_PGSQL_RETRIES120; | |||
| 107 | int code = 0, recon = 0; | |||
| 108 | ||||
| 109 | if (handle) { | |||
| 110 | max_tries = handle->num_retries; | |||
| 111 | if (max_tries < 1) | |||
| 112 | max_tries = DEFAULT_PGSQL_RETRIES120; | |||
| 113 | } | |||
| 114 | ||||
| 115 | top: | |||
| 116 | ||||
| 117 | if (!handle) { | |||
| 118 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 118, ((void*)0), SWITCH_LOG_CRIT, "No DB Handle\n"); | |||
| 119 | goto done; | |||
| 120 | } | |||
| 121 | if (!handle->con) { | |||
| 122 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 122, ((void*)0), SWITCH_LOG_CRIT, "No DB Connection\n"); | |||
| 123 | goto done; | |||
| 124 | } | |||
| 125 | ||||
| 126 | /* Try a non-blocking read on the connection to gobble up any EOF from a closed connection and mark the connection BAD if it is closed. */ | |||
| 127 | PQconsumeInput(handle->con); | |||
| 128 | ||||
| 129 | if (PQstatus(handle->con) == CONNECTION_BAD) { | |||
| 130 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 130, ((void*)0), SWITCH_LOG_WARNING, "PQstatus returned bad connection; reconnecting...\n"); | |||
| 131 | handle->state = SWITCH_PGSQL_STATE_ERROR; | |||
| 132 | PQreset(handle->con); | |||
| 133 | if (PQstatus(handle->con) == CONNECTION_BAD) { | |||
| 134 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 134, ((void*)0), SWITCH_LOG_CRIT, "PQstatus returned bad connection -- reconnection failed!\n"); | |||
| 135 | goto error; | |||
| 136 | } | |||
| 137 | handle->state = SWITCH_PGSQL_STATE_CONNECTED; | |||
| 138 | handle->sock = PQsocket(handle->con); | |||
| 139 | } | |||
| 140 | ||||
| 141 | /* if (!PQsendQuery(handle->con, "SELECT 1")) { | |||
| 142 | code = __LINE__; | |||
| 143 | goto error; | |||
| 144 | } | |||
| 145 | ||||
| 146 | if(switch_pgsql_next_result(handle, &result) == SWITCH_PGSQL_FAIL) { | |||
| 147 | code = __LINE__; | |||
| 148 | goto error; | |||
| 149 | } | |||
| 150 | ||||
| 151 | if (!result || result->status != PGRES_COMMAND_OK) { | |||
| 152 | code = __LINE__; | |||
| 153 | goto error; | |||
| 154 | } | |||
| 155 | ||||
| 156 | switch_pgsql_free_result(&result); | |||
| 157 | switch_pgsql_finish_results(handle); | |||
| 158 | */ | |||
| 159 | ret = 1; | |||
| 160 | goto done; | |||
| 161 | ||||
| 162 | error: | |||
| 163 | err_str = switch_pgsql_handle_get_error(handle); | |||
| 164 | ||||
| 165 | if (PQstatus(handle->con) == CONNECTION_BAD) { | |||
| 166 | handle->state = SWITCH_PGSQL_STATE_ERROR; | |||
| 167 | PQreset(handle->con); | |||
| 168 | if (PQstatus(handle->con) == CONNECTION_OK) { | |||
| 169 | handle->state = SWITCH_PGSQL_STATE_CONNECTED; | |||
| 170 | recon = SWITCH_PGSQL_SUCCESS; | |||
| 171 | handle->sock = PQsocket(handle->con); | |||
| 172 | } | |||
| 173 | } | |||
| 174 | ||||
| 175 | max_tries--; | |||
| 176 | ||||
| 177 | if (switch_event_create(&event, SWITCH_EVENT_TRAP)switch_event_create_subclass_detailed("src/switch_pgsql.c", ( const char * )(const char *)__func__, 177, &event, SWITCH_EVENT_TRAP , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
| 178 | switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Failure-Message", "The sql server is not responding for DSN %s [%s][%d]", | |||
| 179 | switch_str_nil(handle->dsn)(handle->dsn ? handle->dsn : ""), switch_str_nil(err_str)(err_str ? err_str : ""), code); | |||
| 180 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 180, ((void*)0), SWITCH_LOG_CRIT, "The sql server is not responding for DSN %s [%s][%d]\n", | |||
| 181 | switch_str_nil(handle->dsn)(handle->dsn ? handle->dsn : ""), switch_str_nil(err_str)(err_str ? err_str : ""), code); | |||
| 182 | ||||
| 183 | if (recon == SWITCH_PGSQL_SUCCESS) { | |||
| 184 | switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection has been re-established"); | |||
| 185 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 185, ((void*)0), SWITCH_LOG_INFO, "The connection has been re-established\n"); | |||
| 186 | } else { | |||
| 187 | switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection could not be re-established"); | |||
| 188 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 188, ((void*)0), SWITCH_LOG_CRIT, "The connection could not be re-established\n"); | |||
| 189 | } | |||
| 190 | if (!max_tries) { | |||
| 191 | switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "Giving up!"); | |||
| 192 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 192, ((void*)0), SWITCH_LOG_CRIT, "Giving up!\n"); | |||
| 193 | } | |||
| 194 | ||||
| 195 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_pgsql.c", (const char * )(const char *)__func__, 195, &event, ((void*)0)); | |||
| 196 | } | |||
| 197 | ||||
| 198 | if (!max_tries) { | |||
| 199 | goto done; | |||
| 200 | } | |||
| 201 | ||||
| 202 | switch_safe_free(err_str)if (err_str) {free(err_str);err_str=((void*)0);}; | |||
| 203 | switch_yield(1000000)switch_sleep(1000000);; | |||
| 204 | goto top; | |||
| 205 | ||||
| 206 | done: | |||
| 207 | ||||
| 208 | switch_safe_free(err_str)if (err_str) {free(err_str);err_str=((void*)0);}; | |||
| 209 | ||||
| 210 | return ret; | |||
| 211 | } | |||
| 212 | #endif | |||
| 213 | ||||
| 214 | ||||
| 215 | SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_pgsql_set_num_retries(switch_pgsql_handle_t *handle, int num_retries) | |||
| 216 | { | |||
| 217 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 218 | if (handle) { | |||
| 219 | handle->num_retries = num_retries; | |||
| 220 | } | |||
| 221 | #endif | |||
| 222 | } | |||
| 223 | ||||
| 224 | SWITCH_DECLARE(switch_pgsql_status_t)__attribute__((visibility("default"))) switch_pgsql_status_t switch_pgsql_handle_disconnect(switch_pgsql_handle_t *handle) | |||
| 225 | { | |||
| 226 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 227 | ||||
| 228 | if (!handle) { | |||
| 229 | return SWITCH_PGSQL_FAIL; | |||
| 230 | } | |||
| 231 | ||||
| 232 | if (handle->state == SWITCH_PGSQL_STATE_CONNECTED) { | |||
| 233 | PQfinish(handle->con); | |||
| 234 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 234, ((void*)0), SWITCH_LOG_DEBUG10, "Disconnected from [%s]\n", handle->dsn); | |||
| 235 | } | |||
| 236 | switch_safe_free(handle->sql)if (handle->sql) {free(handle->sql);handle->sql=((void *)0);}; | |||
| 237 | handle->state = SWITCH_PGSQL_STATE_DOWN; | |||
| 238 | ||||
| 239 | return SWITCH_PGSQL_SUCCESS; | |||
| 240 | #else | |||
| 241 | return SWITCH_PGSQL_FAIL; | |||
| 242 | #endif | |||
| 243 | } | |||
| 244 | ||||
| 245 | SWITCH_DECLARE(switch_pgsql_status_t)__attribute__((visibility("default"))) switch_pgsql_status_t switch_pgsql_send_query(switch_pgsql_handle_t *handle, const char* sql) | |||
| 246 | { | |||
| 247 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 248 | char *err_str; | |||
| 249 | ||||
| 250 | switch_safe_free(handle->sql)if (handle->sql) {free(handle->sql);handle->sql=((void *)0);}; | |||
| 251 | handle->sql = strdup(sql)(__extension__ (__builtin_constant_p (sql) && ((size_t )(const void *)((sql) + 1) - (size_t)(const void *)(sql) == 1 ) ? (((const char *) (sql))[0] == '\0' ? (char *) calloc ((size_t ) 1, (size_t) 1) : ({ size_t __len = strlen (sql) + 1; char * __retval = (char *) malloc (__len); if (__retval != ((void*)0 )) __retval = (char *) memcpy (__retval, sql, __len); __retval ; })) : __strdup (sql))); | |||
| 252 | if (!PQsendQuery(handle->con, sql)) { | |||
| 253 | err_str = switch_pgsql_handle_get_error(handle); | |||
| 254 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 254, ((void*)0), SWITCH_LOG_CRIT, "Failed to send query (%s) to database: %s\n", sql, err_str); | |||
| 255 | switch_pgsql_finish_results(handle)switch_pgsql_finish_results_real("src/switch_pgsql.c", (char * )(const char *)__func__, 255, handle); | |||
| 256 | goto error; | |||
| 257 | } | |||
| 258 | ||||
| 259 | return SWITCH_PGSQL_SUCCESS; | |||
| 260 | error: | |||
| 261 | #endif | |||
| 262 | return SWITCH_PGSQL_FAIL; | |||
| 263 | } | |||
| 264 | ||||
| 265 | SWITCH_DECLARE(switch_pgsql_status_t)__attribute__((visibility("default"))) switch_pgsql_status_t switch_pgsql_cancel_real(const char *file, const char *func, int line, switch_pgsql_handle_t *handle) | |||
| 266 | { | |||
| 267 | switch_pgsql_status_t ret = SWITCH_PGSQL_SUCCESS; | |||
| 268 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 269 | char err_buf[256]; | |||
| 270 | PGcancel *cancel = NULL((void*)0); | |||
| 271 | ||||
| 272 | memset(err_buf, 0, 256); | |||
| 273 | cancel = PQgetCancel(handle->con); | |||
| 274 | if(!PQcancel(cancel, err_buf, 256)) { | |||
| 275 | switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL((void*)0), SWITCH_LOG_CRIT, "Failed to cancel long-running query (%s): %s\n", handle->sql, err_buf); | |||
| 276 | ret = SWITCH_PGSQL_FAIL; | |||
| 277 | } | |||
| 278 | PQfreeCancel(cancel); | |||
| 279 | switch_pgsql_flush(handle); | |||
| 280 | ||||
| 281 | #endif | |||
| 282 | return ret; | |||
| 283 | } | |||
| 284 | ||||
| 285 | ||||
| 286 | SWITCH_DECLARE(switch_pgsql_status_t)__attribute__((visibility("default"))) switch_pgsql_status_t switch_pgsql_next_result_timed(switch_pgsql_handle_t *handle, switch_pgsql_result_t **result_out, int msec) | |||
| 287 | { | |||
| 288 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 289 | switch_pgsql_result_t *res; | |||
| 290 | switch_time_t start; | |||
| 291 | switch_time_t ctime; | |||
| 292 | unsigned int usec = msec * 1000; | |||
| 293 | char *err_str; | |||
| 294 | struct pollfd fds[2] = { {0} }; | |||
| 295 | int poll_res = 0; | |||
| 296 | ||||
| 297 | if(!handle) { | |||
| 298 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 298, ((void*)0), SWITCH_LOG_CRIT, "**BUG** Null handle passed to switch_pgsql_next_result.\n"); | |||
| 299 | return SWITCH_PGSQL_FAIL; | |||
| 300 | } | |||
| 301 | ||||
| 302 | /* Try to consume input that might be waiting right away */ | |||
| 303 | if (PQconsumeInput(handle->con)) { | |||
| 304 | /* And check to see if we have a full result ready for reading */ | |||
| 305 | if (PQisBusy(handle->con)) { | |||
| 306 | ||||
| 307 | /* Wait for a result to become available, up to msec milliseconds */ | |||
| 308 | start = switch_micro_time_now(); | |||
| 309 | while((ctime = switch_micro_time_now()) - start <= usec) { | |||
| 310 | int wait_time = (usec - (ctime - start)) / 1000; | |||
| 311 | fds[0].fd = handle->sock; | |||
| 312 | fds[0].events |= POLLIN0x001; | |||
| 313 | fds[0].events |= POLLERR0x008; | |||
| 314 | fds[0].events |= POLLNVAL0x020; | |||
| 315 | fds[0].events |= POLLHUP0x010; | |||
| 316 | fds[0].events |= POLLPRI0x002; | |||
| 317 | fds[0].events |= POLLRDNORM0x040; | |||
| 318 | fds[0].events |= POLLRDBAND0x080; | |||
| 319 | ||||
| 320 | /* Wait for the PostgreSQL socket to be ready for data reads. */ | |||
| 321 | if ((poll_res = poll(&fds[0], 1, wait_time)) > 0 ) { | |||
| 322 | if (fds[0].revents & POLLHUP0x010 || fds[0].revents & POLLNVAL0x020) { | |||
| 323 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 323, ((void*)0), SWITCH_LOG_CRIT, "PGSQL socket closed or invalid while waiting for result for query (%s)\n", handle->sql); | |||
| 324 | goto error; | |||
| 325 | } else if (fds[0].revents & POLLERR0x008) { | |||
| 326 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 326, ((void*)0), SWITCH_LOG_CRIT, "Poll error trying to read PGSQL socket for query (%s)\n", handle->sql); | |||
| 327 | goto error; | |||
| 328 | } else if (fds[0].revents & POLLIN0x001 || fds[0].revents & POLLPRI0x002 || fds[0].revents & POLLRDNORM0x040 || fds[0].revents & POLLRDBAND0x080) { | |||
| 329 | /* Then try to consume any input waiting. */ | |||
| 330 | if (PQconsumeInput(handle->con)) { | |||
| 331 | if (PQstatus(handle->con) == CONNECTION_BAD) { | |||
| 332 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 332, ((void*)0), SWITCH_LOG_CRIT, "Connection terminated while waiting for result.\n"); | |||
| 333 | handle->state = SWITCH_PGSQL_STATE_ERROR; | |||
| 334 | goto error; | |||
| 335 | } | |||
| 336 | ||||
| 337 | /* And check to see if we have a full result ready for reading */ | |||
| 338 | if (!PQisBusy(handle->con)) { | |||
| 339 | /* If we can pull a full result without blocking, then break this loop */ | |||
| 340 | break; | |||
| 341 | } | |||
| 342 | } else { | |||
| 343 | /* If we had an error trying to consume input, report it and cancel the query. */ | |||
| 344 | err_str = switch_pgsql_handle_get_error(handle); | |||
| 345 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 345, ((void*)0), SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str); | |||
| 346 | switch_safe_free(err_str)if (err_str) {free(err_str);err_str=((void*)0);}; | |||
| 347 | switch_pgsql_cancel(handle)switch_pgsql_cancel_real("src/switch_pgsql.c", (char * )(const char *)__func__, 347, handle); | |||
| 348 | goto error; | |||
| 349 | } | |||
| 350 | } | |||
| 351 | } else if (poll_res == -1) { | |||
| 352 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 352, ((void*)0), SWITCH_LOG_CRIT, "Poll failed trying to read PGSQL socket for query (%s)\n", handle->sql); | |||
| 353 | goto error; | |||
| 354 | } | |||
| 355 | } | |||
| 356 | ||||
| 357 | /* If we broke the loop above because of a timeout, report that and cancel the query. */ | |||
| 358 | if (ctime - start > usec) { | |||
| 359 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 359, ((void*)0), SWITCH_LOG_CRIT, "Query (%s) took too long to complete or database not responding.\n", handle->sql); | |||
| 360 | switch_pgsql_cancel(handle)switch_pgsql_cancel_real("src/switch_pgsql.c", (char * )(const char *)__func__, 360, handle); | |||
| 361 | goto error; | |||
| 362 | } | |||
| 363 | ||||
| 364 | } | |||
| 365 | } else { | |||
| 366 | /* If we had an error trying to consume input, report it and cancel the query. */ | |||
| 367 | err_str = switch_pgsql_handle_get_error(handle); | |||
| 368 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 368, ((void*)0), SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str); | |||
| 369 | switch_safe_free(err_str)if (err_str) {free(err_str);err_str=((void*)0);}; | |||
| 370 | /* switch_pgsql_cancel(handle); */ | |||
| 371 | goto error; | |||
| 372 | } | |||
| 373 | ||||
| 374 | ||||
| 375 | /* At this point, we know we can read a full result without blocking. */ | |||
| 376 | if(!(res = malloc(sizeof(switch_pgsql_result_t)))) { | |||
| 377 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 377, ((void*)0), SWITCH_LOG_CRIT, "Malloc failed!\n"); | |||
| 378 | goto error; | |||
| 379 | } | |||
| 380 | memset(res, 0, sizeof(switch_pgsql_result_t)); | |||
| 381 | ||||
| 382 | ||||
| 383 | res->result = PQgetResult(handle->con); | |||
| 384 | if (res->result) { | |||
| 385 | *result_out = res; | |||
| 386 | res->status = PQresultStatus(res->result); | |||
| 387 | switch(res->status) { | |||
| 388 | #if POSTGRESQL_MAJOR_VERSION9 >= 9 && POSTGRESQL_MINOR_VERSION4 >= 2 | |||
| 389 | case PGRES_SINGLE_TUPLE: | |||
| 390 | /* Added in PostgreSQL 9.2 */ | |||
| 391 | #endif | |||
| 392 | case PGRES_TUPLES_OK: | |||
| 393 | { | |||
| 394 | res->rows = PQntuples(res->result); | |||
| 395 | handle->affected_rows = res->rows; | |||
| 396 | res->cols = PQnfields(res->result); | |||
| 397 | } | |||
| 398 | break; | |||
| 399 | #if POSTGRESQL_MAJOR_VERSION9 >= 9 && POSTGRESQL_MINOR_VERSION4 >= 1 | |||
| 400 | case PGRES_COPY_BOTH: | |||
| 401 | /* Added in PostgreSQL 9.1 */ | |||
| 402 | #endif | |||
| 403 | case PGRES_COPY_OUT: | |||
| 404 | case PGRES_COPY_IN: | |||
| 405 | case PGRES_COMMAND_OK: | |||
| 406 | break; | |||
| 407 | case PGRES_EMPTY_QUERY: | |||
| 408 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 408, ((void*)0), SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_EMPTY_QUERY\n", handle->sql); | |||
| 409 | case PGRES_BAD_RESPONSE: | |||
| 410 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 410, ((void*)0), SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_BAD_RESPONSE\n", handle->sql); | |||
| 411 | case PGRES_NONFATAL_ERROR: | |||
| 412 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 412, ((void*)0), SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_NONFATAL_ERROR\n", handle->sql); | |||
| 413 | case PGRES_FATAL_ERROR: | |||
| 414 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 414, ((void*)0), SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_FATAL_ERROR\n", handle->sql); | |||
| 415 | res->err = PQresultErrorMessage(res->result); | |||
| 416 | goto error; | |||
| 417 | break; | |||
| 418 | } | |||
| 419 | } else { | |||
| 420 | free(res); | |||
| 421 | res = NULL((void*)0); | |||
| 422 | *result_out = NULL((void*)0); | |||
| 423 | } | |||
| 424 | ||||
| 425 | return SWITCH_PGSQL_SUCCESS; | |||
| 426 | error: | |||
| 427 | ||||
| 428 | /* Make sure the failed connection does not have any transactions marked as in progress */ | |||
| 429 | switch_pgsql_flush(handle); | |||
| 430 | ||||
| 431 | /* Try to reconnect to the DB if we were dropped */ | |||
| 432 | db_is_up(handle); | |||
| 433 | ||||
| 434 | #endif | |||
| 435 | return SWITCH_PGSQL_FAIL; | |||
| 436 | } | |||
| 437 | ||||
| 438 | SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_pgsql_free_result(switch_pgsql_result_t **result) | |||
| 439 | { | |||
| 440 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 441 | ||||
| 442 | if (!*result) { | |||
| 443 | return; | |||
| 444 | } | |||
| 445 | ||||
| 446 | if ((*result)->result) { | |||
| 447 | PQclear((*result)->result); | |||
| 448 | } | |||
| 449 | free(*result); | |||
| 450 | *result = NULL((void*)0); | |||
| 451 | #else | |||
| 452 | return; | |||
| 453 | #endif | |||
| 454 | } | |||
| 455 | ||||
| 456 | SWITCH_DECLARE(switch_pgsql_status_t)__attribute__((visibility("default"))) switch_pgsql_status_t switch_pgsql_finish_results_real(const char* file, const char* func, int line, switch_pgsql_handle_t *handle) | |||
| 457 | { | |||
| 458 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 459 | switch_pgsql_result_t *res = NULL((void*)0); | |||
| 460 | switch_pgsql_status_t final_status = SWITCH_PGSQL_SUCCESS; | |||
| 461 | int done = 0; | |||
| 462 | do { | |||
| 463 | switch_pgsql_next_result(handle, &res)switch_pgsql_next_result_timed(handle, &res, 10000); | |||
| 464 | if (res && res->err && !switch_stristr("already exists", res->err) && !switch_stristr("duplicate key name", res->err)) { | |||
| 465 | switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL((void*)0), SWITCH_LOG_ERROR, "Error executing query:\n%s\n", res->err); | |||
| 466 | final_status = SWITCH_PGSQL_FAIL; | |||
| 467 | } | |||
| 468 | if (!res) done = 1; | |||
| 469 | switch_pgsql_free_result(&res); | |||
| 470 | } while (!done); | |||
| 471 | return final_status; | |||
| 472 | #else | |||
| 473 | return SWITCH_PGSQL_FAIL; | |||
| 474 | #endif | |||
| 475 | } | |||
| 476 | ||||
| 477 | ||||
| 478 | SWITCH_DECLARE(switch_pgsql_status_t)__attribute__((visibility("default"))) switch_pgsql_status_t switch_pgsql_handle_connect(switch_pgsql_handle_t *handle) | |||
| 479 | { | |||
| 480 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 481 | if (handle->state == SWITCH_PGSQL_STATE_CONNECTED) { | |||
| 482 | switch_pgsql_handle_disconnect(handle); | |||
| 483 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 483, ((void*)0), SWITCH_LOG_DEBUG1, "Re-connecting %s\n", handle->dsn); | |||
| 484 | } | |||
| 485 | ||||
| 486 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 486, ((void*)0), SWITCH_LOG_DEBUG1, "Connecting %s\n", handle->dsn); | |||
| 487 | ||||
| 488 | handle->con = PQconnectdb(handle->dsn); | |||
| 489 | if (PQstatus(handle->con) != CONNECTION_OK) { | |||
| 490 | char *err_str; | |||
| 491 | if ((err_str = switch_pgsql_handle_get_error(handle))) { | |||
| 492 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 492, ((void*)0), SWITCH_LOG_ERROR, "%s\n", err_str); | |||
| 493 | switch_safe_free(err_str)if (err_str) {free(err_str);err_str=((void*)0);}; | |||
| 494 | } else { | |||
| 495 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 495, ((void*)0), SWITCH_LOG_ERROR, "Failed to connect to the database [%s]\n", handle->dsn); | |||
| 496 | switch_pgsql_handle_disconnect(handle); | |||
| 497 | } | |||
| 498 | return SWITCH_PGSQL_FAIL; | |||
| 499 | } | |||
| 500 | ||||
| 501 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 501, ((void*)0), SWITCH_LOG_DEBUG1, "Connected to [%s]\n", handle->dsn); | |||
| 502 | handle->state = SWITCH_PGSQL_STATE_CONNECTED; | |||
| 503 | handle->sock = PQsocket(handle->con); | |||
| 504 | return SWITCH_PGSQL_SUCCESS; | |||
| 505 | #else | |||
| 506 | return SWITCH_PGSQL_FAIL; | |||
| 507 | #endif | |||
| 508 | } | |||
| 509 | ||||
| 510 | SWITCH_DECLARE(switch_pgsql_status_t)__attribute__((visibility("default"))) switch_pgsql_status_t switch_pgsql_handle_exec_string_detailed(const char *file, const char *func, int line, | |||
| 511 | switch_pgsql_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err) | |||
| 512 | { | |||
| 513 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 514 | switch_pgsql_status_t sstatus = SWITCH_PGSQL_SUCCESS; | |||
| 515 | char *val = NULL((void*)0); | |||
| 516 | switch_pgsql_result_t *result = NULL((void*)0); | |||
| 517 | ||||
| 518 | handle->affected_rows = 0; | |||
| 519 | ||||
| 520 | if (switch_pgsql_handle_exec_base_detailed(file, func, line, handle, sql, err) == SWITCH_PGSQL_FAIL) { | |||
| ||||
| 521 | goto error; | |||
| 522 | } | |||
| 523 | ||||
| 524 | if(switch_pgsql_next_result(handle, &result)switch_pgsql_next_result_timed(handle, &result, 10000) == SWITCH_PGSQL_FAIL) { | |||
| 525 | goto error; | |||
| 526 | } | |||
| 527 | ||||
| 528 | if (!result) { | |||
| 529 | switch (result->status) { | |||
| ||||
| 530 | #if POSTGRESQL_MAJOR_VERSION9 >= 9 && POSTGRESQL_MINOR_VERSION4 >= 2 | |||
| 531 | case PGRES_SINGLE_TUPLE: | |||
| 532 | /* Added in PostgreSQL 9.2 */ | |||
| 533 | #endif | |||
| 534 | case PGRES_COMMAND_OK: | |||
| 535 | case PGRES_TUPLES_OK: | |||
| 536 | break; | |||
| 537 | default: | |||
| 538 | sstatus = SWITCH_PGSQL_FAIL; | |||
| 539 | goto done; | |||
| 540 | } | |||
| 541 | } | |||
| 542 | ||||
| 543 | if (handle->affected_rows <= 0) { | |||
| 544 | goto done; | |||
| 545 | } | |||
| 546 | ||||
| 547 | val = PQgetvalue(result->result, 0, 0); | |||
| 548 | strncpy(resbuf, val, len)__builtin_strncpy (resbuf, val, len); | |||
| 549 | ||||
| 550 | done: | |||
| 551 | ||||
| 552 | switch_pgsql_free_result(&result); | |||
| 553 | if (switch_pgsql_finish_results(handle)switch_pgsql_finish_results_real("src/switch_pgsql.c", (char * )(const char *)__func__, 553, handle) != SWITCH_PGSQL_SUCCESS) { | |||
| 554 | sstatus = SWITCH_PGSQL_FAIL; | |||
| 555 | } | |||
| 556 | ||||
| 557 | return sstatus; | |||
| 558 | error: | |||
| 559 | return SWITCH_PGSQL_FAIL; | |||
| 560 | #else | |||
| 561 | return SWITCH_PGSQL_FAIL; | |||
| 562 | #endif | |||
| 563 | } | |||
| 564 | ||||
| 565 | SWITCH_DECLARE(switch_pgsql_status_t)__attribute__((visibility("default"))) switch_pgsql_status_t switch_pgsql_handle_exec_base_detailed(const char *file, const char *func, int line, | |||
| 566 | switch_pgsql_handle_t *handle, const char *sql, char **err) | |||
| 567 | { | |||
| 568 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 569 | char *err_str = NULL((void*)0), *er = NULL((void*)0); | |||
| 570 | ||||
| 571 | ||||
| 572 | ||||
| 573 | switch_pgsql_flush(handle); | |||
| 574 | handle->affected_rows = 0; | |||
| 575 | ||||
| 576 | if (!db_is_up(handle)) { | |||
| 577 | er = strdup("Database is not up!")(__extension__ (__builtin_constant_p ("Database is not up!") && ((size_t)(const void *)(("Database is not up!") + 1) - (size_t )(const void *)("Database is not up!") == 1) ? (((const char * ) ("Database is not up!"))[0] == '\0' ? (char *) calloc ((size_t ) 1, (size_t) 1) : ({ size_t __len = strlen ("Database is not up!" ) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "Database is not up!" , __len); __retval; })) : __strdup ("Database is not up!"))); | |||
| 578 | goto error; | |||
| 579 | } | |||
| 580 | ||||
| 581 | if (handle->auto_commit == SWITCH_FALSE && handle->in_txn == SWITCH_FALSE) { | |||
| 582 | if (switch_pgsql_send_query(handle, "BEGIN") != SWITCH_PGSQL_SUCCESS) { | |||
| 583 | er = strdup("Error sending BEGIN!")(__extension__ (__builtin_constant_p ("Error sending BEGIN!") && ((size_t)(const void *)(("Error sending BEGIN!") + 1) - (size_t)(const void *)("Error sending BEGIN!") == 1) ? ( ((const char *) ("Error sending BEGIN!"))[0] == '\0' ? (char * ) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ( "Error sending BEGIN!") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "Error sending BEGIN!", __len); __retval; })) : __strdup ("Error sending BEGIN!"))); | |||
| 584 | if (switch_pgsql_finish_results(handle)switch_pgsql_finish_results_real("src/switch_pgsql.c", (char * )(const char *)__func__, 584, handle) != SWITCH_PGSQL_SUCCESS) { | |||
| 585 | db_is_up(handle); /* If finish_results failed, maybe the db went dead */ | |||
| 586 | } | |||
| 587 | goto error; | |||
| 588 | } | |||
| 589 | ||||
| 590 | if (switch_pgsql_finish_results(handle)switch_pgsql_finish_results_real("src/switch_pgsql.c", (char * )(const char *)__func__, 590, handle) != SWITCH_PGSQL_SUCCESS) { | |||
| 591 | db_is_up(handle); | |||
| 592 | er = strdup("Error sending BEGIN!")(__extension__ (__builtin_constant_p ("Error sending BEGIN!") && ((size_t)(const void *)(("Error sending BEGIN!") + 1) - (size_t)(const void *)("Error sending BEGIN!") == 1) ? ( ((const char *) ("Error sending BEGIN!"))[0] == '\0' ? (char * ) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ( "Error sending BEGIN!") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "Error sending BEGIN!", __len); __retval; })) : __strdup ("Error sending BEGIN!"))); | |||
| 593 | goto error; | |||
| 594 | } | |||
| 595 | handle->in_txn = SWITCH_TRUE; | |||
| 596 | } | |||
| 597 | ||||
| 598 | if (switch_pgsql_send_query(handle, sql) != SWITCH_PGSQL_SUCCESS) { | |||
| 599 | er = strdup("Error sending query!")(__extension__ (__builtin_constant_p ("Error sending query!") && ((size_t)(const void *)(("Error sending query!") + 1) - (size_t)(const void *)("Error sending query!") == 1) ? ( ((const char *) ("Error sending query!"))[0] == '\0' ? (char * ) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ( "Error sending query!") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "Error sending query!", __len); __retval; })) : __strdup ("Error sending query!"))); | |||
| 600 | if (switch_pgsql_finish_results(handle)switch_pgsql_finish_results_real("src/switch_pgsql.c", (char * )(const char *)__func__, 600, handle) != SWITCH_PGSQL_SUCCESS) { | |||
| 601 | db_is_up(handle); | |||
| 602 | } | |||
| 603 | goto error; | |||
| 604 | } | |||
| 605 | ||||
| 606 | return SWITCH_PGSQL_SUCCESS; | |||
| 607 | ||||
| 608 | error: | |||
| 609 | err_str = switch_pgsql_handle_get_error(handle); | |||
| 610 | ||||
| 611 | if (zstr(err_str)_zstr(err_str)) { | |||
| 612 | if (zstr(er)_zstr(er)) { | |||
| 613 | err_str = strdup((char *)"SQL ERROR!")(__extension__ (__builtin_constant_p ((char *)"SQL ERROR!") && ((size_t)(const void *)(((char *)"SQL ERROR!") + 1) - (size_t )(const void *)((char *)"SQL ERROR!") == 1) ? (((const char * ) ((char *)"SQL ERROR!"))[0] == '\0' ? (char *) calloc ((size_t ) 1, (size_t) 1) : ({ size_t __len = strlen ((char *)"SQL ERROR!" ) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (char * )"SQL ERROR!", __len); __retval; })) : __strdup ((char *)"SQL ERROR!" ))); | |||
| 614 | } else { | |||
| 615 | err_str = er; | |||
| 616 | } | |||
| 617 | } else { | |||
| 618 | if (!zstr(er)_zstr(er)) { | |||
| 619 | free(er); | |||
| 620 | } | |||
| 621 | } | |||
| 622 | ||||
| 623 | if (err_str) { | |||
| 624 | if (!switch_stristr("already exists", err_str) && !switch_stristr("duplicate key name", err_str)) { | |||
| 625 | switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL((void*)0), SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str)(err_str ? err_str : "")); | |||
| 626 | } | |||
| 627 | if (err) { | |||
| 628 | *err = err_str; | |||
| 629 | } else { | |||
| 630 | free(err_str); | |||
| 631 | } | |||
| 632 | } | |||
| 633 | #endif | |||
| 634 | return SWITCH_PGSQL_FAIL; | |||
| 635 | } | |||
| 636 | ||||
| 637 | SWITCH_DECLARE(switch_pgsql_status_t)__attribute__((visibility("default"))) switch_pgsql_status_t switch_pgsql_handle_exec_detailed(const char *file, const char *func, int line, | |||
| 638 | switch_pgsql_handle_t *handle, const char *sql, char **err) | |||
| 639 | { | |||
| 640 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 641 | if (switch_pgsql_handle_exec_base_detailed(file, func, line, handle, sql, err) == SWITCH_PGSQL_FAIL) { | |||
| 642 | goto error; | |||
| 643 | } | |||
| 644 | ||||
| 645 | return switch_pgsql_finish_results(handle)switch_pgsql_finish_results_real("src/switch_pgsql.c", (char * )(const char *)__func__, 645, handle); | |||
| 646 | error: | |||
| 647 | #endif | |||
| 648 | return SWITCH_PGSQL_FAIL; | |||
| 649 | } | |||
| 650 | ||||
| 651 | SWITCH_DECLARE(switch_pgsql_status_t)__attribute__((visibility("default"))) switch_pgsql_status_t switch_pgsql_handle_callback_exec_detailed(const char *file, const char *func, int line, | |||
| 652 | switch_pgsql_handle_t *handle, | |||
| 653 | const char *sql, switch_core_db_callback_func_t callback, void *pdata, | |||
| 654 | char **err) | |||
| 655 | { | |||
| 656 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 657 | char *err_str = NULL((void*)0); | |||
| 658 | int row = 0, col = 0, err_cnt = 0; | |||
| 659 | switch_pgsql_result_t *result = NULL((void*)0); | |||
| 660 | ||||
| 661 | handle->affected_rows = 0; | |||
| 662 | ||||
| 663 | switch_assert(callback != NULL)((callback != ((void*)0)) ? (void) (0) : __assert_fail ("callback != ((void*)0)" , "src/switch_pgsql.c", 663, __PRETTY_FUNCTION__)); | |||
| 664 | ||||
| 665 | if (switch_pgsql_handle_exec_base(handle, sql, err)switch_pgsql_handle_exec_base_detailed("src/switch_pgsql.c", ( char * )(const char *)__func__, 665, handle, sql, err) == SWITCH_PGSQL_FAIL) { | |||
| 666 | goto error; | |||
| 667 | } | |||
| 668 | ||||
| 669 | if (switch_pgsql_next_result(handle, &result)switch_pgsql_next_result_timed(handle, &result, 10000) == SWITCH_PGSQL_FAIL) { | |||
| 670 | err_cnt++; | |||
| 671 | err_str = switch_pgsql_handle_get_error(handle); | |||
| 672 | if (result && !zstr(result->err)_zstr(result->err)) { | |||
| 673 | switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL((void*)0), SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(result->err)(result->err ? result->err : "")); | |||
| 674 | } | |||
| 675 | if (!zstr(err_str)_zstr(err_str)) { | |||
| 676 | switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL((void*)0), SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str)(err_str ? err_str : "")); | |||
| 677 | } | |||
| 678 | switch_safe_free(err_str)if (err_str) {free(err_str);err_str=((void*)0);}; | |||
| 679 | err_str = NULL((void*)0); | |||
| 680 | } | |||
| 681 | ||||
| 682 | while (result != NULL((void*)0)) { | |||
| 683 | /*switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Processing result with %d rows and %d columns.\n", result->rows, result->cols);*/ | |||
| 684 | for (row = 0; row < result->rows; ++row) { | |||
| 685 | char **names; | |||
| 686 | char **vals; | |||
| 687 | ||||
| 688 | names = calloc(result->cols, sizeof(*names)); | |||
| 689 | vals = calloc(result->cols, sizeof(*vals)); | |||
| 690 | ||||
| 691 | switch_assert(names && vals)((names && vals) ? (void) (0) : __assert_fail ("names && vals" , "src/switch_pgsql.c", 691, __PRETTY_FUNCTION__)); | |||
| 692 | ||||
| 693 | for (col = 0; col < result->cols; ++col) { | |||
| 694 | char * tmp; | |||
| 695 | int len; | |||
| 696 | ||||
| 697 | tmp = PQfname(result->result, col); | |||
| 698 | if (tmp) { | |||
| 699 | len = strlen(tmp); | |||
| 700 | names[col] = malloc(len+1); | |||
| 701 | names[col][len] = '\0'; | |||
| 702 | strncpy(names[col], tmp, len)__builtin_strncpy (names[col], tmp, len); | |||
| 703 | ||||
| 704 | len = PQgetlength(result->result, row, col); | |||
| 705 | vals[col] = malloc(len+1); | |||
| 706 | vals[col][len] = '\0'; | |||
| 707 | tmp = PQgetvalue(result->result, row, col); | |||
| 708 | strncpy(vals[col], tmp, len)__builtin_strncpy (vals[col], tmp, len); | |||
| 709 | /*switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Processing result row %d, col %d: %s => %s\n", row, col, names[col], vals[col]);*/ | |||
| 710 | } else { | |||
| 711 | /*switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Processing result row %d, col %d.\n", row, col);*/ | |||
| 712 | switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL((void*)0), SWITCH_LOG_ERROR, "ERR: Column number %d out of range\n", col); | |||
| 713 | } | |||
| 714 | } | |||
| 715 | ||||
| 716 | /*switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Executing callback for row %d...\n", row);*/ | |||
| 717 | if (callback(pdata, result->cols, vals, names)) { | |||
| 718 | switch_pgsql_finish_results(handle)switch_pgsql_finish_results_real("src/switch_pgsql.c", (char * )(const char *)__func__, 718, handle); /* Makes sure next call to switch_pgsql_next_result will return NULL */ | |||
| 719 | row = result->rows; /* Makes us exit the for loop */ | |||
| 720 | } | |||
| 721 | ||||
| 722 | for (col = 0; col < result->cols; ++col) { | |||
| 723 | free(names[col]); | |||
| 724 | free(vals[col]); | |||
| 725 | } | |||
| 726 | free(names); | |||
| 727 | free(vals); | |||
| 728 | } | |||
| 729 | switch_pgsql_free_result(&result); | |||
| 730 | if (switch_pgsql_next_result(handle, &result)switch_pgsql_next_result_timed(handle, &result, 10000) == SWITCH_PGSQL_FAIL) { | |||
| 731 | err_cnt++; | |||
| 732 | err_str = switch_pgsql_handle_get_error(handle); | |||
| 733 | if (result && !zstr(result->err)_zstr(result->err)) { | |||
| 734 | switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL((void*)0), SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(result->err)(result->err ? result->err : "")); | |||
| 735 | } | |||
| 736 | if (!zstr(err_str)_zstr(err_str)) { | |||
| 737 | switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL((void*)0), SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str)(err_str ? err_str : "")); | |||
| 738 | } | |||
| 739 | switch_safe_free(err_str)if (err_str) {free(err_str);err_str=((void*)0);}; | |||
| 740 | err_str = NULL((void*)0); | |||
| 741 | } | |||
| 742 | } | |||
| 743 | if (err_cnt) { | |||
| 744 | goto error; | |||
| 745 | } | |||
| 746 | ||||
| 747 | return SWITCH_PGSQL_SUCCESS; | |||
| 748 | error: | |||
| 749 | #endif | |||
| 750 | return SWITCH_PGSQL_FAIL; | |||
| 751 | } | |||
| 752 | ||||
| 753 | SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_pgsql_handle_destroy(switch_pgsql_handle_t **handlep) | |||
| 754 | { | |||
| 755 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 756 | ||||
| 757 | switch_pgsql_handle_t *handle = NULL((void*)0); | |||
| 758 | ||||
| 759 | if (!handlep) { | |||
| 760 | return; | |||
| 761 | } | |||
| 762 | handle = *handlep; | |||
| 763 | ||||
| 764 | if (handle) { | |||
| 765 | switch_pgsql_handle_disconnect(handle); | |||
| 766 | ||||
| 767 | switch_safe_free(handle->dsn)if (handle->dsn) {free(handle->dsn);handle->dsn=((void *)0);}; | |||
| 768 | free(handle); | |||
| 769 | } | |||
| 770 | *handlep = NULL((void*)0); | |||
| 771 | #else | |||
| 772 | return; | |||
| 773 | #endif | |||
| 774 | } | |||
| 775 | ||||
| 776 | SWITCH_DECLARE(switch_pgsql_state_t)__attribute__((visibility("default"))) switch_pgsql_state_t switch_pgsql_handle_get_state(switch_pgsql_handle_t *handle) | |||
| 777 | { | |||
| 778 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 779 | return handle ? handle->state : SWITCH_PGSQL_STATE_INIT; | |||
| 780 | #else | |||
| 781 | return SWITCH_PGSQL_STATE_ERROR; | |||
| 782 | #endif | |||
| 783 | } | |||
| 784 | ||||
| 785 | SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_pgsql_handle_get_error(switch_pgsql_handle_t *handle) | |||
| 786 | { | |||
| 787 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 788 | char * err_str; | |||
| 789 | if (!handle) { | |||
| 790 | return NULL((void*)0); | |||
| 791 | }; | |||
| 792 | switch_strdup(err_str, PQerrorMessage(handle->con))(void)(((((err_str) = (__extension__ (__builtin_constant_p (( PQerrorMessage(handle->con))) && ((size_t)(const void *)(((PQerrorMessage(handle->con))) + 1) - (size_t)(const void *)((PQerrorMessage(handle->con))) == 1) ? (((const char * ) ((PQerrorMessage(handle->con))))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((PQerrorMessage (handle->con))) + 1; char *__retval = (char *) malloc (__len ); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , (PQerrorMessage(handle->con)), __len); __retval; })) : __strdup ((PQerrorMessage(handle->con))))))) ? (void) (0) : __assert_fail ("((err_str) = (__extension__ (__builtin_constant_p ((PQerrorMessage(handle->con))) && ((size_t)(const void *)(((PQerrorMessage(handle->con))) + 1) - (size_t)(const void *)((PQerrorMessage(handle->con))) == 1) ? (((const char *) ((PQerrorMessage(handle->con))))[0] == '\\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((PQerrorMessage(handle->con))) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (PQerrorMessage(handle->con)), __len); __retval; })) : __strdup ((PQerrorMessage(handle->con))))))" , "src/switch_pgsql.c", 792, __PRETTY_FUNCTION__)),err_str); | |||
| 793 | return err_str; | |||
| 794 | #else | |||
| 795 | return NULL((void*)0); | |||
| 796 | #endif | |||
| 797 | } | |||
| 798 | ||||
| 799 | SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_pgsql_handle_affected_rows(switch_pgsql_handle_t *handle) | |||
| 800 | { | |||
| 801 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 802 | return handle->affected_rows; | |||
| 803 | #else | |||
| 804 | return 0; | |||
| 805 | #endif | |||
| 806 | } | |||
| 807 | ||||
| 808 | SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_pgsql_available(void) | |||
| 809 | { | |||
| 810 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 811 | return SWITCH_TRUE; | |||
| 812 | #else | |||
| 813 | return SWITCH_FALSE; | |||
| 814 | #endif | |||
| 815 | } | |||
| 816 | ||||
| 817 | SWITCH_DECLARE(switch_pgsql_status_t)__attribute__((visibility("default"))) switch_pgsql_status_t switch_pgsql_SQLSetAutoCommitAttr(switch_pgsql_handle_t *handle, switch_bool_t on) | |||
| 818 | { | |||
| 819 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 820 | if (on) { | |||
| 821 | handle->auto_commit = SWITCH_TRUE; | |||
| 822 | } else { | |||
| 823 | handle->auto_commit = SWITCH_FALSE; | |||
| 824 | } | |||
| 825 | return SWITCH_PGSQL_SUCCESS; | |||
| 826 | #else | |||
| 827 | return (switch_pgsql_status_t) SWITCH_FALSE; | |||
| 828 | #endif | |||
| 829 | } | |||
| 830 | ||||
| 831 | SWITCH_DECLARE(switch_pgsql_status_t)__attribute__((visibility("default"))) switch_pgsql_status_t switch_pgsql_flush(switch_pgsql_handle_t *handle) | |||
| 832 | { | |||
| 833 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 834 | ||||
| 835 | PGresult *tmp = NULL((void*)0); | |||
| 836 | int x = 0; | |||
| 837 | ||||
| 838 | /* Make sure the query is fully cleared */ | |||
| 839 | while ((tmp = PQgetResult(handle->con)) != NULL((void*)0)) { | |||
| 840 | PQclear(tmp); | |||
| 841 | x++; | |||
| 842 | } | |||
| 843 | ||||
| 844 | if (x) { | |||
| 845 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 845, ((void*)0), SWITCH_LOG_DEBUG10, "Flushing %d results\n", x); | |||
| 846 | } | |||
| 847 | ||||
| 848 | return SWITCH_PGSQL_SUCCESS; | |||
| 849 | #else | |||
| 850 | return (switch_pgsql_status_t) SWITCH_FALSE; | |||
| 851 | #endif | |||
| 852 | } | |||
| 853 | ||||
| 854 | SWITCH_DECLARE(switch_pgsql_status_t)__attribute__((visibility("default"))) switch_pgsql_status_t switch_pgsql_SQLEndTran(switch_pgsql_handle_t *handle, switch_bool_t commit) | |||
| 855 | { | |||
| 856 | #ifdef SWITCH_HAVE_PGSQL1 | |||
| 857 | char * err_str = NULL((void*)0); | |||
| 858 | if (commit) { | |||
| 859 | if(!PQsendQuery(handle->con, "COMMIT")) { | |||
| 860 | err_str = switch_pgsql_handle_get_error(handle); | |||
| 861 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 861, ((void*)0), SWITCH_LOG_CRIT, "Could not commit transaction: %s\n", err_str); | |||
| 862 | switch_safe_free(err_str)if (err_str) {free(err_str);err_str=((void*)0);}; | |||
| 863 | return SWITCH_PGSQL_FAIL; | |||
| 864 | } | |||
| 865 | } else { | |||
| 866 | if(!PQsendQuery(handle->con, "ROLLBACK")) { | |||
| 867 | err_str = switch_pgsql_handle_get_error(handle); | |||
| 868 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_pgsql.c", (const char *)__func__ , 868, ((void*)0), SWITCH_LOG_CRIT, "Could not rollback transaction: %s\n", err_str); | |||
| 869 | switch_safe_free(err_str)if (err_str) {free(err_str);err_str=((void*)0);}; | |||
| 870 | return SWITCH_PGSQL_FAIL; | |||
| 871 | } | |||
| 872 | } | |||
| 873 | handle->in_txn = SWITCH_FALSE; | |||
| 874 | return SWITCH_PGSQL_SUCCESS; | |||
| 875 | #else | |||
| 876 | return (switch_pgsql_status_t) SWITCH_FALSE; | |||
| 877 | #endif | |||
| 878 | } | |||
| 879 | ||||
| 880 | ||||
| 881 | /* For Emacs: | |||
| 882 | * Local Variables: | |||
| 883 | * mode:c | |||
| 884 | * indent-tabs-mode:t | |||
| 885 | * tab-width:4 | |||
| 886 | * c-basic-offset:4 | |||
| 887 | * End: | |||
| 888 | * For VIM: | |||
| 889 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: | |||
| 890 | */ |