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 | */ |