FreeSWITCH API Documentation  1.7.0
switch_odbc.c
Go to the documentation of this file.
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  *
28  * switch_odbc.c -- ODBC
29  *
30  */
31 
32 #include <switch.h>
33 
34 #ifdef SWITCH_HAVE_ODBC
35 #include <sql.h>
36 #ifdef _MSC_VER
37 #pragma warning(push)
38 #pragma warning(disable:4201)
39 #include <sqlext.h>
40 #pragma warning(pop)
41 #else
42 #include <sqlext.h>
43 #endif
44 #include <sqltypes.h>
45 
46 #if (ODBCVER < 0x0300)
47 #define SQL_NO_DATA SQL_SUCCESS
48 #endif
49 
50 struct switch_odbc_handle {
51  char *dsn;
52  char *username;
53  char *password;
54  SQLHENV env;
55  SQLHDBC con;
57  char odbc_driver[256];
58  BOOL is_firebird;
59  BOOL is_oracle;
60  int affected_rows;
61  int num_retries;
62 };
63 #endif
64 
65 SWITCH_DECLARE(switch_odbc_handle_t *) switch_odbc_handle_new(const char *dsn, const char *username, const char *password)
66 {
67 #ifdef SWITCH_HAVE_ODBC
68  switch_odbc_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))) {
77  goto err;
78  }
79 
80  if (username) {
81  if (!(new_handle->username = strdup(username))) {
82  goto err;
83  }
84  }
85 
86  if (password) {
87  if (!(new_handle->password = strdup(password))) {
88  goto err;
89  }
90  }
91 
92  new_handle->env = SQL_NULL_HANDLE;
93  new_handle->state = SWITCH_ODBC_STATE_INIT;
94  new_handle->affected_rows = 0;
95  new_handle->num_retries = DEFAULT_ODBC_RETRIES;
96 
97  return new_handle;
98 
99  err:
100  if (new_handle) {
101  switch_safe_free(new_handle->dsn);
102  switch_safe_free(new_handle->username);
103  switch_safe_free(new_handle->password);
104  switch_safe_free(new_handle);
105  }
106 #endif
107  return NULL;
108 }
109 
111 {
112 #ifdef SWITCH_HAVE_ODBC
113  if (handle) {
114  handle->num_retries = num_retries;
115  }
116 #endif
117 }
118 
120 {
121 #ifdef SWITCH_HAVE_ODBC
122 
123  int result;
124 
125  if (!handle) {
126  return SWITCH_ODBC_FAIL;
127  }
128 
129  if (handle->state == SWITCH_ODBC_STATE_CONNECTED) {
130  result = SQLDisconnect(handle->con);
131  if (result == SWITCH_ODBC_SUCCESS) {
132  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Disconnected %d from [%s]\n", result, handle->dsn);
133  } else {
134  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Disconnecting [%s]\n", handle->dsn);
135  }
136  }
137 
138  handle->state = SWITCH_ODBC_STATE_DOWN;
139 
140  return SWITCH_ODBC_SUCCESS;
141 #else
142  return SWITCH_ODBC_FAIL;
143 #endif
144 }
145 
146 
147 #ifdef SWITCH_HAVE_ODBC
148 static switch_odbc_status_t init_odbc_handles(switch_odbc_handle_t *handle, switch_bool_t do_reinit)
149 {
150  int result;
151 
152  if (!handle) {
153  return SWITCH_ODBC_FAIL;
154  }
155 
156  /* if handle is already initialized, and we're supposed to reinit - free old handle first */
157  if (do_reinit == SWITCH_TRUE && handle->env != SQL_NULL_HANDLE) {
158  SQLFreeHandle(SQL_HANDLE_DBC, handle->con);
159  SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
160  handle->env = SQL_NULL_HANDLE;
161  }
162 
163  if (handle->env == SQL_NULL_HANDLE) {
164  result = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &handle->env);
165 
166  if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
167  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHandle\n");
168  handle->env = SQL_NULL_HANDLE; /* Reset handle value, just in case */
169  return SWITCH_ODBC_FAIL;
170  }
171 
172  result = SQLSetEnvAttr(handle->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
173 
174  if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
176  SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
177  handle->env = SQL_NULL_HANDLE; /* Reset handle value after it's freed */
178  return SWITCH_ODBC_FAIL;
179  }
180 
181  result = SQLAllocHandle(SQL_HANDLE_DBC, handle->env, &handle->con);
182 
183  if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
184  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error AllocHDB %d\n", result);
185  SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
186  handle->env = SQL_NULL_HANDLE; /* Reset handle value after it's freed */
187  return SWITCH_ODBC_FAIL;
188  }
189  SQLSetConnectAttr(handle->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0);
190  }
191 
192  return SWITCH_ODBC_SUCCESS;
193 }
194 
195 static int db_is_up(switch_odbc_handle_t *handle)
196 {
197  int ret = 0;
198  SQLHSTMT stmt = NULL;
199  SQLLEN m = 0;
200  int result;
201  switch_event_t *event;
202  switch_odbc_status_t recon = 0;
203  char *err_str = NULL;
204  SQLCHAR sql[255] = "";
205  int max_tries = DEFAULT_ODBC_RETRIES;
206  int code = 0;
207  SQLRETURN rc;
208  SQLSMALLINT nresultcols;
209 
210 
211  if (handle) {
212  max_tries = handle->num_retries;
213  if (max_tries < 1)
214  max_tries = DEFAULT_ODBC_RETRIES;
215  }
216 
217  top:
218 
219  if (!handle) {
221  goto done;
222  }
223 
224  if (handle->is_oracle) {
225  strcpy((char *) sql, "select 1 from dual");
226  } else if (handle->is_firebird) {
227  strcpy((char *) sql, "select first 1 * from RDB$RELATIONS");
228  } else {
229  strcpy((char *) sql, "select 1");
230  }
231 
232  if (SQLAllocHandle(SQL_HANDLE_STMT, handle->con, &stmt) != SQL_SUCCESS) {
233  code = __LINE__;
234  goto error;
235  }
236 
237  SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER)30, 0);
238 
239  if (SQLPrepare(stmt, sql, SQL_NTS) != SQL_SUCCESS) {
240  code = __LINE__;
241  goto error;
242  }
243 
244  result = SQLExecute(stmt);
245 
246  if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO) {
247  code = __LINE__;
248  goto error;
249  }
250 
251  SQLRowCount(stmt, &m);
252  rc = SQLNumResultCols(stmt, &nresultcols);
253  if (rc != SQL_SUCCESS) {
254  code = __LINE__;
255  goto error;
256  }
257  ret = (int) nresultcols;
258  /* determine statement type */
259  if (nresultcols <= 0) {
260  /* statement is not a select statement */
261  code = __LINE__;
262  goto error;
263  }
264 
265  goto done;
266 
267  error:
268  err_str = switch_odbc_handle_get_error(handle, stmt);
269 
270  /* Make sure to free the handle before we try to reconnect */
271  if (stmt) {
272  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
273  stmt = NULL;
274  }
275 
276  recon = switch_odbc_handle_connect(handle);
277 
278  max_tries--;
279 
281  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Failure-Message", "The sql server is not responding for DSN %s [%s][%d]",
282  switch_str_nil(handle->dsn), switch_str_nil(err_str), code);
283  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The sql server is not responding for DSN %s [%s][%d]\n",
284  switch_str_nil(handle->dsn), switch_str_nil(err_str), code);
285 
286  if (recon == SWITCH_ODBC_SUCCESS) {
287  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection has been re-established");
288  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "The connection has been re-established\n");
289  } else {
290  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection could not be re-established");
291  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The connection could not be re-established\n");
292  }
293  if (!max_tries) {
294  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "Giving up!");
296  }
297 
298  switch_event_fire(&event);
299  }
300 
301  if (!max_tries) {
302  goto done;
303  }
304 
305  switch_safe_free(err_str);
306  switch_yield(1000000);
307  goto top;
308 
309  done:
310 
311  switch_safe_free(err_str);
312 
313  if (stmt) {
314  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
315  }
316 
317  return ret;
318 }
319 #endif
320 
322 {
323  if (!stmt || !*stmt) {
324  return SWITCH_ODBC_FAIL;
325  }
326 #ifdef SWITCH_HAVE_ODBC
327  SQLFreeHandle(SQL_HANDLE_STMT, *stmt);
328  *stmt = NULL;
329  return SWITCH_ODBC_SUCCESS;
330 #else
331  return SWITCH_ODBC_FAIL;
332 #endif
333 }
334 
335 
337 {
338 #ifdef SWITCH_HAVE_ODBC
339  int result;
340  SQLINTEGER err;
341  int16_t mlen;
342  unsigned char msg[200] = "", stat[10] = "";
343  SQLSMALLINT valueLength = 0;
344  int i = 0;
345 
346  init_odbc_handles(handle, SWITCH_FALSE); /* Init ODBC handles, if they are already initialized, don't do it again */
347 
348  if (handle->state == SWITCH_ODBC_STATE_CONNECTED) {
350  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Re-connecting %s\n", handle->dsn);
351  }
352 
353  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Connecting %s\n", handle->dsn);
354 
355  if (!strstr(handle->dsn, "DRIVER")) {
356  result = SQLConnect(handle->con, (SQLCHAR *) handle->dsn, SQL_NTS, (SQLCHAR *) handle->username, SQL_NTS, (SQLCHAR *) handle->password, SQL_NTS);
357  } else {
358  SQLCHAR outstr[1024] = { 0 };
359  SQLSMALLINT outstrlen = 0;
360  result =
361  SQLDriverConnect(handle->con, NULL, (SQLCHAR *) handle->dsn, (SQLSMALLINT) strlen(handle->dsn), outstr, sizeof(outstr), &outstrlen,
362  SQL_DRIVER_NOPROMPT);
363  }
364 
365  if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
366  char *err_str;
367  if ((err_str = switch_odbc_handle_get_error(handle, NULL))) {
369  free(err_str);
370  } else {
371  SQLGetDiagRec(SQL_HANDLE_DBC, handle->con, 1, stat, &err, msg, sizeof(msg), &mlen);
372  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SQLConnect=%d errno=%d [%s]\n", result, (int) err, msg);
373  }
374 
375  /* Deallocate handles again, more chanses to succeed when reconnecting */
376  init_odbc_handles(handle, SWITCH_TRUE); /* Reinit ODBC handles */
377  return SWITCH_ODBC_FAIL;
378  }
379 
380  result = SQLGetInfo(handle->con, SQL_DRIVER_NAME, (SQLCHAR *) handle->odbc_driver, 255, &valueLength);
381  if (result == SQL_SUCCESS || result == SQL_SUCCESS_WITH_INFO) {
382  for (i = 0; i < valueLength; ++i)
383  handle->odbc_driver[i] = (char) toupper(handle->odbc_driver[i]);
384  }
385 
386  if (strstr(handle->odbc_driver, "SQORA32.DLL") != 0 || strstr(handle->odbc_driver, "SQORA64.DLL") != 0) {
387  handle->is_firebird = FALSE;
388  handle->is_oracle = TRUE;
389  } else if (strstr(handle->odbc_driver, "FIREBIRD") != 0 || strstr(handle->odbc_driver, "FB32") != 0 || strstr(handle->odbc_driver, "FB64") != 0) {
390  handle->is_firebird = TRUE;
391  handle->is_oracle = FALSE;
392  } else {
393  handle->is_firebird = FALSE;
394  handle->is_oracle = FALSE;
395  }
396 
397  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Connected to [%s]\n", handle->dsn);
398  handle->state = SWITCH_ODBC_STATE_CONNECTED;
399  return SWITCH_ODBC_SUCCESS;
400 #else
401  return SWITCH_ODBC_FAIL;
402 #endif
403 }
404 
405 SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_exec_string(switch_odbc_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err)
406 {
407 #ifdef SWITCH_HAVE_ODBC
409  switch_odbc_statement_handle_t stmt = NULL;
410  SQLCHAR name[1024];
411  SQLLEN m = 0;
412 
413  handle->affected_rows = 0;
414 
415  if (switch_odbc_handle_exec(handle, sql, &stmt, err) == SWITCH_ODBC_SUCCESS) {
416  SQLSMALLINT NameLength, DataType, DecimalDigits, Nullable;
417  SQLULEN ColumnSize;
418  int result;
419 
420  SQLRowCount(stmt, &m);
421  handle->affected_rows = (int) m;
422 
423  if (m == 0) {
424  goto done;
425  }
426 
427  result = SQLFetch(stmt);
428 
429  if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO && result != SQL_NO_DATA) {
430  goto done;
431  }
432 
433  SQLDescribeCol(stmt, 1, name, sizeof(name), &NameLength, &DataType, &ColumnSize, &DecimalDigits, &Nullable);
434  SQLGetData(stmt, 1, SQL_C_CHAR, (SQLCHAR *) resbuf, (SQLLEN) len, NULL);
435 
436  sstatus = SWITCH_ODBC_SUCCESS;
437  }
438 
439  done:
440 
442 
443  return sstatus;
444 #else
445  return SWITCH_ODBC_FAIL;
446 #endif
447 }
448 
450  char **err)
451 {
452 #ifdef SWITCH_HAVE_ODBC
453  SQLHSTMT stmt = NULL;
454  int result;
455  char *err_str = NULL, *err2 = NULL;
456  SQLLEN m = 0;
457 
458  handle->affected_rows = 0;
459 
460  if (!db_is_up(handle)) {
461  goto error;
462  }
463 
464  if (SQLAllocHandle(SQL_HANDLE_STMT, handle->con, &stmt) != SQL_SUCCESS) {
465  err2 = "SQLAllocHandle failed.";
466  goto error;
467  }
468 
469  if (SQLPrepare(stmt, (unsigned char *) sql, SQL_NTS) != SQL_SUCCESS) {
470  err2 = "SQLPrepare failed.";
471  goto error;
472  }
473 
474  result = SQLExecute(stmt);
475 
476  switch (result) {
477  case SQL_SUCCESS:
478  case SQL_SUCCESS_WITH_INFO:
479  case SQL_NO_DATA:
480  break;
481  case SQL_ERROR:
482  err2 = "SQLExecute returned SQL_ERROR.";
483  goto error;
484  break;
485  case SQL_NEED_DATA:
486  err2 = "SQLExecute returned SQL_NEED_DATA.";
487  goto error;
488  break;
489  default:
490  err2 = "SQLExecute returned unknown result code.";
491  goto error;
492  }
493 
494  SQLRowCount(stmt, &m);
495  handle->affected_rows = (int) m;
496 
497  if (rstmt) {
498  *rstmt = stmt;
499  } else {
500  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
501  }
502 
503  return SWITCH_ODBC_SUCCESS;
504 
505  error:
506 
507 
508  if (stmt) {
509  err_str = switch_odbc_handle_get_error(handle, stmt);
510  }
511 
512  if (zstr(err_str)) {
513  if (err2) {
514  err_str = strdup(err2);
515  } else {
516  err_str = strdup((char *)"SQL ERROR!");
517  }
518  }
519 
520  if (err_str) {
521  if (!switch_stristr("already exists", err_str) && !switch_stristr("duplicate key name", err_str)) {
522  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str));
523  }
524  if (err) {
525  *err = err_str;
526  } else {
527  free(err_str);
528  }
529  }
530 
531  if (rstmt) {
532  *rstmt = stmt;
533  } else if (stmt) {
534  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
535  }
536 #endif
537  return SWITCH_ODBC_FAIL;
538 }
539 
541  switch_odbc_handle_t *handle,
542  const char *sql, switch_core_db_callback_func_t callback, void *pdata,
543  char **err)
544 {
545 #ifdef SWITCH_HAVE_ODBC
546  SQLHSTMT stmt = NULL;
547  SQLSMALLINT c = 0, x = 0;
548  SQLLEN m = 0;
549  char *x_err = NULL, *err_str = NULL;
550  int result;
551  int err_cnt = 0;
552  int done = 0;
553 
554  handle->affected_rows = 0;
555 
556  switch_assert(callback != NULL);
557 
558  if (!db_is_up(handle)) {
559  x_err = "DB is not up!";
560  goto error;
561  }
562 
563  if (SQLAllocHandle(SQL_HANDLE_STMT, handle->con, &stmt) != SQL_SUCCESS) {
564  x_err = "Unable to SQL allocate handle!";
565  goto error;
566  }
567 
568  if (SQLPrepare(stmt, (unsigned char *) sql, SQL_NTS) != SQL_SUCCESS) {
569  x_err = "Unable to prepare SQL statement!";
570  goto error;
571  }
572 
573  result = SQLExecute(stmt);
574 
575  if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO && result != SQL_NO_DATA) {
576  x_err = "execute error!";
577  goto error;
578  }
579 
580  SQLNumResultCols(stmt, &c);
581  SQLRowCount(stmt, &m);
582  handle->affected_rows = (int) m;
583 
584 
585  while (!done) {
586  int name_len = 256;
587  char **names;
588  char **vals;
589  int y = 0;
590 
591  result = SQLFetch(stmt);
592 
593  if (result != SQL_SUCCESS) {
594  if (result != SQL_NO_DATA) {
595  err_cnt++;
596  }
597  break;
598  }
599 
600  names = calloc(c, sizeof(*names));
601  vals = calloc(c, sizeof(*vals));
602 
603  switch_assert(names && vals);
604 
605  for (x = 1; x <= c; x++) {
606  SQLSMALLINT NameLength = 0, DataType = 0, DecimalDigits = 0, Nullable = 0;
607  SQLULEN ColumnSize = 0;
608  names[y] = malloc(name_len);
609  memset(names[y], 0, name_len);
610 
611  SQLDescribeCol(stmt, x, (SQLCHAR *) names[y], (SQLSMALLINT) name_len, &NameLength, &DataType, &ColumnSize, &DecimalDigits, &Nullable);
612 
613  if (!ColumnSize) {
614  ColumnSize = 255;
615  }
616  ColumnSize++;
617 
618  vals[y] = malloc(ColumnSize);
619  memset(vals[y], 0, ColumnSize);
620  SQLGetData(stmt, x, SQL_C_CHAR, (SQLCHAR *) vals[y], ColumnSize, NULL);
621  y++;
622  }
623 
624  if (callback(pdata, y, vals, names)) {
625  done = 1;
626  }
627 
628  for (x = 0; x < y; x++) {
629  free(names[x]);
630  free(vals[x]);
631  }
632  free(names);
633  free(vals);
634  }
635 
636  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
637  stmt = NULL; /* Make sure we don't try to free this handle again */
638 
639  if (!err_cnt) {
640  return SWITCH_ODBC_SUCCESS;
641  }
642 
643  error:
644 
645  if (stmt) {
646  err_str = switch_odbc_handle_get_error(handle, stmt);
647  }
648 
649  if (zstr(err_str) && !zstr(x_err)) {
650  err_str = strdup(x_err);
651  }
652 
653  if (err_str) {
654  switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str));
655  if (err) {
656  *err = err_str;
657  } else {
658  free(err_str);
659  }
660  }
661 
662  if (stmt) {
663  SQLFreeHandle(SQL_HANDLE_STMT, stmt);
664  }
665 
666 
667 #endif
668  return SWITCH_ODBC_FAIL;
669 }
670 
672 {
673 #ifdef SWITCH_HAVE_ODBC
674 
675  switch_odbc_handle_t *handle = NULL;
676 
677  if (!handlep) {
678  return;
679  }
680  handle = *handlep;
681 
682  if (handle) {
684 
685  if (handle->env != SQL_NULL_HANDLE) {
686  SQLFreeHandle(SQL_HANDLE_DBC, handle->con);
687  SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
688  }
689  switch_safe_free(handle->dsn);
690  switch_safe_free(handle->username);
691  switch_safe_free(handle->password);
692  free(handle);
693  }
694  *handlep = NULL;
695 #else
696  return;
697 #endif
698 }
699 
701 {
702 #ifdef SWITCH_HAVE_ODBC
703  return handle ? handle->state : SWITCH_ODBC_STATE_INIT;
704 #else
706 #endif
707 }
708 
710 {
711 #ifdef SWITCH_HAVE_ODBC
712 
713  char buffer[SQL_MAX_MESSAGE_LENGTH + 1] = "";
714  char sqlstate[SQL_SQLSTATE_SIZE + 1] = "";
715  SQLINTEGER sqlcode;
716  SQLSMALLINT length;
717  char *ret = NULL;
718 
719  if (SQLError(handle->env, handle->con, stmt, (SQLCHAR *) sqlstate, &sqlcode, (SQLCHAR *) buffer, sizeof(buffer), &length) == SQL_SUCCESS) {
720  ret = switch_mprintf("STATE: %s CODE %ld ERROR: %s\n", sqlstate, sqlcode, buffer);
721  };
722 
723  return ret;
724 #else
725  return NULL;
726 #endif
727 }
728 
730 {
731 #ifdef SWITCH_HAVE_ODBC
732  return handle->affected_rows;
733 #else
734  return 0;
735 #endif
736 }
737 
739 {
740 #ifdef SWITCH_HAVE_ODBC
741  return SWITCH_TRUE;
742 #else
743  return SWITCH_FALSE;
744 #endif
745 }
746 
748 {
749 #ifdef SWITCH_HAVE_ODBC
750  if (on) {
751  return SQLSetConnectAttr(handle->con, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER *) SQL_AUTOCOMMIT_ON, 0 );
752  } else {
753  return SQLSetConnectAttr(handle->con, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER *) SQL_AUTOCOMMIT_OFF, 0 );
754  }
755 #else
757 #endif
758 }
759 
761 {
762 #ifdef SWITCH_HAVE_ODBC
763  if (commit) {
764  return SQLEndTran(SQL_HANDLE_DBC, handle->con, SQL_COMMIT);
765  } else {
766  return SQLEndTran(SQL_HANDLE_DBC, handle->con, SQL_ROLLBACK);
767  }
768 #else
770 #endif
771 }
772 
773 
774 /* For Emacs:
775  * Local Variables:
776  * mode:c
777  * indent-tabs-mode:t
778  * tab-width:4
779  * c-basic-offset:4
780  * End:
781  * For VIM:
782  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
783  */
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
switch_odbc_status_t switch_odbc_handle_disconnect(switch_odbc_handle_t *handle)
Definition: switch_odbc.c:119
switch_odbc_handle_t * switch_odbc_handle_new(const char *dsn, const char *username, const char *password)
Definition: switch_odbc.c:65
switch_odbc_status_t
Definition: switch_odbc.h:49
switch_odbc_state_t
Definition: switch_odbc.h:42
#define SWITCH_CHANNEL_LOG
void switch_odbc_set_num_retries(switch_odbc_handle_t *handle, int num_retries)
Definition: switch_odbc.c:110
struct switch_odbc_handle switch_odbc_handle_t
switch_odbc_status_t switch_odbc_SQLSetAutoCommitAttr(switch_odbc_handle_t *handle, switch_bool_t on)
Definition: switch_odbc.c:747
switch_odbc_status_t switch_odbc_handle_exec_string(switch_odbc_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err)
Definition: switch_odbc.c:405
int switch_odbc_handle_affected_rows(switch_odbc_handle_t *handle)
Definition: switch_odbc.c:729
switch_bool_t
Definition: switch_types.h:405
switch_odbc_status_t switch_odbc_handle_exec(switch_odbc_handle_t *handle, const char *sql, switch_odbc_statement_handle_t *rstmt, char **err)
Definition: switch_odbc.c:449
switch_status_t switch_event_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *fmt,...) PRINTF_FUNCTION(4
Add a header to an event.
Representation of an event.
Definition: switch_event.h:80
int(* switch_core_db_callback_func_t)(void *pArg, int argc, char **argv, char **columnNames)
void switch_odbc_handle_destroy(switch_odbc_handle_t **handlep)
Definition: switch_odbc.c:671
switch_bool_t switch_odbc_available(void)
Definition: switch_odbc.c:738
#define zstr(x)
Definition: switch_utils.h:281
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
#define DEFAULT_ODBC_RETRIES
Definition: switch_odbc.h:37
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:903
switch_odbc_status_t switch_odbc_SQLEndTran(switch_odbc_handle_t *handle, switch_bool_t commit)
Definition: switch_odbc.c:760
switch_odbc_status_t switch_odbc_handle_callback_exec_detailed(const char *file, const char *func, int line, switch_odbc_handle_t *handle, const char *sql, switch_core_db_callback_func_t callback, void *pdata, char **err)
Execute the sql query and issue a callback for each row returned.
Definition: switch_odbc.c:540
#define FALSE
Main Library Header.
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
#define SWITCH_DECLARE(type)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
const char * switch_stristr(const char *instr, const char *str)
void * switch_odbc_statement_handle_t
Definition: switch_odbc.h:39
#define TRUE
switch_odbc_status_t switch_odbc_handle_connect(switch_odbc_handle_t *handle)
Definition: switch_odbc.c:336
switch_odbc_state_t switch_odbc_handle_get_state(switch_odbc_handle_t *handle)
Definition: switch_odbc.c:700
#define switch_assert(expr)
SWITCH_BEGIN_EXTERN_C char * switch_mprintf(const char *zFormat,...)
char * switch_odbc_handle_get_error(switch_odbc_handle_t *handle, switch_odbc_statement_handle_t stmt)
Definition: switch_odbc.c:709
memset(buf, 0, buflen)
switch_odbc_status_t switch_odbc_statement_handle_free(switch_odbc_statement_handle_t *stmt)
Definition: switch_odbc.c:321