Bug Summary

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')

Annotated Source Code

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
44struct 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
56struct switch_pgsql_result {
57 PGresult *result;
58 ExecStatusType status;
59 char *err;
60 int rows;
61 int cols;
62};
63#endif
64
65SWITCH_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
101static 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
215SWITCH_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
224SWITCH_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
245SWITCH_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
265SWITCH_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
286SWITCH_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
438SWITCH_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
456SWITCH_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
478SWITCH_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
510SWITCH_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) {
1
Taking false branch
521 goto error;
522 }
523
524 if(switch_pgsql_next_result(handle, &result)switch_pgsql_next_result_timed(handle, &result, 10000) == SWITCH_PGSQL_FAIL) {
2
Within the expansion of the macro 'switch_pgsql_next_result':
a
Value assigned to 'result'
3
Taking false branch
525 goto error;
526 }
527
528 if (!result) {
4
Assuming 'result' is null
5
Taking true branch
529 switch (result->status) {
6
Access to field 'status' results in a dereference of a null pointer (loaded from variable 'result')
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
565SWITCH_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
637SWITCH_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
651SWITCH_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
753SWITCH_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
776SWITCH_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
785SWITCH_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
799SWITCH_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
808SWITCH_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
817SWITCH_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
831SWITCH_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
854SWITCH_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 */