34 #ifdef SWITCH_HAVE_ODBC
38 #pragma warning(disable:4201)
46 #if (ODBCVER < 0x0300)
47 #define SQL_NO_DATA SQL_SUCCESS
50 struct switch_odbc_handle {
57 char odbc_driver[256];
67 #ifdef SWITCH_HAVE_ODBC
70 if (!(new_handle = malloc(
sizeof(*new_handle)))) {
74 memset(new_handle, 0,
sizeof(*new_handle));
76 if (!(new_handle->dsn = strdup(dsn))) {
81 if (!(new_handle->username = strdup(username))) {
87 if (!(new_handle->password = strdup(password))) {
92 new_handle->env = SQL_NULL_HANDLE;
94 new_handle->affected_rows = 0;
112 #ifdef SWITCH_HAVE_ODBC
114 handle->num_retries = num_retries;
121 #ifdef SWITCH_HAVE_ODBC
130 result = SQLDisconnect(handle->con);
147 #ifdef SWITCH_HAVE_ODBC
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;
163 if (handle->env == SQL_NULL_HANDLE) {
164 result = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &handle->env);
166 if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
168 handle->env = SQL_NULL_HANDLE;
172 result = SQLSetEnvAttr(handle->env, SQL_ATTR_ODBC_VERSION, (
void *) SQL_OV_ODBC3, 0);
174 if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
176 SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
177 handle->env = SQL_NULL_HANDLE;
181 result = SQLAllocHandle(SQL_HANDLE_DBC, handle->env, &handle->con);
183 if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
185 SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
186 handle->env = SQL_NULL_HANDLE;
189 SQLSetConnectAttr(handle->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0);
198 SQLHSTMT stmt = NULL;
203 char *err_str = NULL;
204 SQLCHAR sql[255] =
"";
208 SQLSMALLINT nresultcols;
212 max_tries = handle->num_retries;
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");
229 strcpy((
char *) sql,
"select 1");
232 if (SQLAllocHandle(SQL_HANDLE_STMT, handle->con, &stmt) != SQL_SUCCESS) {
237 SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER)30, 0);
239 if (SQLPrepare(stmt, sql, SQL_NTS) != SQL_SUCCESS) {
244 result = SQLExecute(stmt);
246 if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO) {
251 SQLRowCount(stmt, &m);
252 rc = SQLNumResultCols(stmt, &nresultcols);
253 if (rc != SQL_SUCCESS) {
257 ret = (int) nresultcols;
259 if (nresultcols <= 0) {
272 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
314 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
323 if (!stmt || !*stmt) {
326 #ifdef SWITCH_HAVE_ODBC
327 SQLFreeHandle(SQL_HANDLE_STMT, *stmt);
338 #ifdef SWITCH_HAVE_ODBC
342 unsigned char msg[200] =
"", stat[10] =
"";
343 SQLSMALLINT valueLength = 0;
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);
358 SQLCHAR outstr[1024] = { 0 };
359 SQLSMALLINT outstrlen = 0;
361 SQLDriverConnect(handle->con, NULL, (SQLCHAR *) handle->dsn, (SQLSMALLINT) strlen(handle->dsn), outstr,
sizeof(outstr), &outstrlen,
362 SQL_DRIVER_NOPROMPT);
365 if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
371 SQLGetDiagRec(SQL_HANDLE_DBC, handle->con, 1, stat, &err, msg,
sizeof(msg), &mlen);
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]);
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;
393 handle->is_firebird =
FALSE;
394 handle->is_oracle =
FALSE;
407 #ifdef SWITCH_HAVE_ODBC
413 handle->affected_rows = 0;
416 SQLSMALLINT NameLength, DataType, DecimalDigits, Nullable;
420 SQLRowCount(stmt, &m);
421 handle->affected_rows = (int) m;
427 result = SQLFetch(stmt);
429 if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO && result != SQL_NO_DATA) {
433 SQLDescribeCol(stmt, 1, name,
sizeof(name), &NameLength, &DataType, &ColumnSize, &DecimalDigits, &Nullable);
434 SQLGetData(stmt, 1, SQL_C_CHAR, (SQLCHAR *) resbuf, (SQLLEN) len, NULL);
452 #ifdef SWITCH_HAVE_ODBC
453 SQLHSTMT stmt = NULL;
455 char *err_str = NULL, *err2 = NULL;
458 handle->affected_rows = 0;
460 if (!db_is_up(handle)) {
464 if (SQLAllocHandle(SQL_HANDLE_STMT, handle->con, &stmt) != SQL_SUCCESS) {
465 err2 =
"SQLAllocHandle failed.";
469 if (SQLPrepare(stmt, (
unsigned char *) sql, SQL_NTS) != SQL_SUCCESS) {
470 err2 =
"SQLPrepare failed.";
474 result = SQLExecute(stmt);
478 case SQL_SUCCESS_WITH_INFO:
482 err2 =
"SQLExecute returned SQL_ERROR.";
486 err2 =
"SQLExecute returned SQL_NEED_DATA.";
490 err2 =
"SQLExecute returned unknown result code.";
494 SQLRowCount(stmt, &m);
495 handle->affected_rows = (int) m;
500 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
514 err_str = strdup(err2);
516 err_str = strdup((
char *)
"SQL ERROR!");
534 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
545 #ifdef SWITCH_HAVE_ODBC
546 SQLHSTMT stmt = NULL;
547 SQLSMALLINT c = 0, x = 0;
549 char *x_err = NULL, *err_str = NULL;
554 handle->affected_rows = 0;
558 if (!db_is_up(handle)) {
559 x_err =
"DB is not up!";
563 if (SQLAllocHandle(SQL_HANDLE_STMT, handle->con, &stmt) != SQL_SUCCESS) {
564 x_err =
"Unable to SQL allocate handle!";
568 if (SQLPrepare(stmt, (
unsigned char *) sql, SQL_NTS) != SQL_SUCCESS) {
569 x_err =
"Unable to prepare SQL statement!";
573 result = SQLExecute(stmt);
575 if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO && result != SQL_NO_DATA) {
576 x_err =
"execute error!";
580 SQLNumResultCols(stmt, &c);
581 SQLRowCount(stmt, &m);
582 handle->affected_rows = (int) m;
591 result = SQLFetch(stmt);
593 if (result != SQL_SUCCESS) {
594 if (result != SQL_NO_DATA) {
600 names = calloc(c,
sizeof(*names));
601 vals = calloc(c,
sizeof(*vals));
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);
611 SQLDescribeCol(stmt, x, (SQLCHAR *) names[y], (SQLSMALLINT) name_len, &NameLength, &DataType, &ColumnSize, &DecimalDigits, &Nullable);
618 vals[y] = malloc(ColumnSize);
619 memset(vals[y], 0, ColumnSize);
620 SQLGetData(stmt, x, SQL_C_CHAR, (SQLCHAR *) vals[y], ColumnSize, NULL);
624 if (callback(pdata, y, vals, names)) {
628 for (x = 0; x < y; x++) {
636 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
649 if (
zstr(err_str) && !
zstr(x_err)) {
650 err_str = strdup(x_err);
663 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
673 #ifdef SWITCH_HAVE_ODBC
685 if (handle->env != SQL_NULL_HANDLE) {
686 SQLFreeHandle(SQL_HANDLE_DBC, handle->con);
687 SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
702 #ifdef SWITCH_HAVE_ODBC
711 #ifdef SWITCH_HAVE_ODBC
713 char buffer[SQL_MAX_MESSAGE_LENGTH + 1] =
"";
714 char sqlstate[SQL_SQLSTATE_SIZE + 1] =
"";
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);
731 #ifdef SWITCH_HAVE_ODBC
732 return handle->affected_rows;
740 #ifdef SWITCH_HAVE_ODBC
749 #ifdef SWITCH_HAVE_ODBC
751 return SQLSetConnectAttr(handle->con, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER *) SQL_AUTOCOMMIT_ON, 0 );
753 return SQLSetConnectAttr(handle->con, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER *) SQL_AUTOCOMMIT_OFF, 0 );
762 #ifdef SWITCH_HAVE_ODBC
764 return SQLEndTran(SQL_HANDLE_DBC, handle->con, SQL_COMMIT);
766 return SQLEndTran(SQL_HANDLE_DBC, handle->con, SQL_ROLLBACK);
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
switch_odbc_status_t switch_odbc_handle_disconnect(switch_odbc_handle_t *handle)
switch_odbc_handle_t * switch_odbc_handle_new(const char *dsn, const char *username, const char *password)
#define SWITCH_CHANNEL_LOG
void switch_odbc_set_num_retries(switch_odbc_handle_t *handle, int num_retries)
struct switch_odbc_handle switch_odbc_handle_t
switch_odbc_status_t switch_odbc_SQLSetAutoCommitAttr(switch_odbc_handle_t *handle, switch_bool_t on)
switch_odbc_status_t switch_odbc_handle_exec_string(switch_odbc_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err)
int switch_odbc_handle_affected_rows(switch_odbc_handle_t *handle)
switch_odbc_status_t switch_odbc_handle_exec(switch_odbc_handle_t *handle, const char *sql, switch_odbc_statement_handle_t *rstmt, char **err)
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.
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)
switch_bool_t switch_odbc_available(void)
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
#define DEFAULT_ODBC_RETRIES
#define switch_str_nil(s)
Make a null string a blank string instead.
switch_odbc_status_t switch_odbc_SQLEndTran(switch_odbc_handle_t *handle, switch_bool_t commit)
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.
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
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
switch_odbc_status_t switch_odbc_handle_connect(switch_odbc_handle_t *handle)
switch_odbc_state_t switch_odbc_handle_get_state(switch_odbc_handle_t *handle)
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)
switch_odbc_status_t switch_odbc_statement_handle_free(switch_odbc_statement_handle_t *stmt)