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];
74 #ifdef SWITCH_HAVE_ODBC 77 if (!(new_handle = malloc(
sizeof(*new_handle)))) {
81 memset(new_handle, 0,
sizeof(*new_handle));
83 if (!(new_handle->dsn = strdup(dsn))) {
88 if (!(new_handle->username = strdup(username))) {
94 if (!(new_handle->password = strdup(password))) {
99 new_handle->env = SQL_NULL_HANDLE;
101 new_handle->affected_rows = 0;
119 #ifdef SWITCH_HAVE_ODBC 121 handle->num_retries = num_retries;
128 #ifdef SWITCH_HAVE_ODBC 137 result = SQLDisconnect(handle->con);
154 #ifdef SWITCH_HAVE_ODBC 164 if (do_reinit ==
SWITCH_TRUE && handle->env != SQL_NULL_HANDLE) {
165 SQLFreeHandle(SQL_HANDLE_DBC, handle->con);
166 SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
167 handle->env = SQL_NULL_HANDLE;
170 if (handle->env == SQL_NULL_HANDLE) {
171 result = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &handle->env);
173 if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
175 handle->env = SQL_NULL_HANDLE;
179 result = SQLSetEnvAttr(handle->env, SQL_ATTR_ODBC_VERSION, (
void *) SQL_OV_ODBC3, 0);
181 if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
183 SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
184 handle->env = SQL_NULL_HANDLE;
188 result = SQLAllocHandle(SQL_HANDLE_DBC, handle->env, &handle->con);
190 if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
192 SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
193 handle->env = SQL_NULL_HANDLE;
196 SQLSetConnectAttr(handle->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0);
205 SQLHSTMT stmt = NULL;
210 char *err_str = NULL;
211 SQLCHAR sql[255] =
"";
215 SQLSMALLINT nresultcols;
219 max_tries = handle->num_retries;
231 if (handle->is_oracle) {
232 strcpy((
char *) sql,
"select 1 from dual");
233 }
else if (handle->is_firebird) {
234 strcpy((
char *) sql,
"select first 1 * from RDB$RELATIONS");
236 strcpy((
char *) sql,
"select 1");
239 if (SQLAllocHandle(SQL_HANDLE_STMT, handle->con, &stmt) != SQL_SUCCESS) {
244 SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER)30, 0);
246 if (SQLPrepare(stmt, sql, SQL_NTS) != SQL_SUCCESS) {
251 result = SQLExecute(stmt);
253 if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO) {
258 SQLRowCount(stmt, &m);
259 rc = SQLNumResultCols(stmt, &nresultcols);
260 if (rc != SQL_SUCCESS) {
264 ret = (int) nresultcols;
266 if (nresultcols <= 0) {
279 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
321 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
330 if (!stmt || !*stmt) {
333 #ifdef SWITCH_HAVE_ODBC 334 SQLFreeHandle(SQL_HANDLE_STMT, *stmt);
345 #ifdef SWITCH_HAVE_ODBC 349 unsigned char msg[200] =
"", stat[10] =
"";
350 SQLSMALLINT valueLength = 0;
362 if (!strstr(handle->dsn,
"DRIVER")) {
363 result = SQLConnect(handle->con, (SQLCHAR *) handle->dsn, SQL_NTS, (SQLCHAR *) handle->username, SQL_NTS, (SQLCHAR *) handle->password, SQL_NTS);
365 SQLCHAR outstr[1024] = { 0 };
366 SQLSMALLINT outstrlen = 0;
368 SQLDriverConnect(handle->con, NULL, (SQLCHAR *) handle->dsn, (SQLSMALLINT) strlen(handle->dsn), outstr,
sizeof(outstr), &outstrlen,
369 SQL_DRIVER_NOPROMPT);
372 if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
378 SQLGetDiagRec(SQL_HANDLE_DBC, handle->con, 1, stat, &err, msg,
sizeof(msg), &mlen);
387 result = SQLGetInfo(handle->con, SQL_DRIVER_NAME, (SQLCHAR *) handle->odbc_driver, 255, &valueLength);
388 if (result == SQL_SUCCESS || result == SQL_SUCCESS_WITH_INFO) {
389 for (i = 0; i < valueLength; ++i)
390 handle->odbc_driver[i] = (
char) toupper(handle->odbc_driver[i]);
393 if (strstr(handle->odbc_driver,
"SQORA32.DLL") != 0 || strstr(handle->odbc_driver,
"SQORA64.DLL") != 0) {
394 handle->is_firebird =
FALSE;
395 handle->is_oracle =
TRUE;
396 }
else if (strstr(handle->odbc_driver,
"FIREBIRD") != 0 || strstr(handle->odbc_driver,
"FB32") != 0 || strstr(handle->odbc_driver,
"FB64") != 0) {
397 handle->is_firebird =
TRUE;
398 handle->is_oracle =
FALSE;
400 handle->is_firebird =
FALSE;
401 handle->is_oracle =
FALSE;
414 #ifdef SWITCH_HAVE_ODBC 420 handle->affected_rows = 0;
423 SQLSMALLINT NameLength, DataType, DecimalDigits, Nullable;
427 SQLRowCount(stmt, &m);
428 handle->affected_rows = (int) m;
434 result = SQLFetch(stmt);
436 if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO && result != SQL_NO_DATA) {
440 SQLDescribeCol(stmt, 1, name,
sizeof(name), &NameLength, &DataType, &ColumnSize, &DecimalDigits, &Nullable);
441 SQLGetData(stmt, 1, SQL_C_CHAR, (SQLCHAR *) resbuf, (SQLLEN) len, NULL);
459 #ifdef SWITCH_HAVE_ODBC 460 SQLHSTMT stmt = NULL;
462 char *err_str = NULL, *err2 = NULL;
465 handle->affected_rows = 0;
467 if (!db_is_up(handle)) {
471 if (SQLAllocHandle(SQL_HANDLE_STMT, handle->con, &stmt) != SQL_SUCCESS) {
472 err2 =
"SQLAllocHandle failed.";
476 if (SQLPrepare(stmt, (
unsigned char *) sql, SQL_NTS) != SQL_SUCCESS) {
477 err2 =
"SQLPrepare failed.";
481 result = SQLExecute(stmt);
485 case SQL_SUCCESS_WITH_INFO:
489 err2 =
"SQLExecute returned SQL_ERROR.";
493 err2 =
"SQLExecute returned SQL_NEED_DATA.";
497 err2 =
"SQLExecute returned unknown result code.";
501 SQLRowCount(stmt, &m);
502 handle->affected_rows = (int) m;
507 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
521 err_str = strdup(err2);
523 err_str = strdup((
char *)
"SQL ERROR!");
541 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
552 #ifdef SWITCH_HAVE_ODBC 553 SQLHSTMT stmt = NULL;
554 SQLSMALLINT c = 0, x = 0;
556 char *x_err = NULL, *err_str = NULL;
561 handle->affected_rows = 0;
565 if (!db_is_up(handle)) {
566 x_err =
"DB is not up!";
570 if (SQLAllocHandle(SQL_HANDLE_STMT, handle->con, &stmt) != SQL_SUCCESS) {
571 x_err =
"Unable to SQL allocate handle!";
575 if (SQLPrepare(stmt, (
unsigned char *) sql, SQL_NTS) != SQL_SUCCESS) {
576 x_err =
"Unable to prepare SQL statement!";
580 result = SQLExecute(stmt);
582 if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO && result != SQL_NO_DATA) {
583 x_err =
"execute error!";
587 SQLNumResultCols(stmt, &c);
588 SQLRowCount(stmt, &m);
589 handle->affected_rows = (int) m;
598 result = SQLFetch(stmt);
600 if (result != SQL_SUCCESS) {
601 if (result != SQL_NO_DATA) {
607 names = calloc(c,
sizeof(*names));
608 vals = calloc(c,
sizeof(*vals));
612 for (x = 1; x <= c; x++) {
613 SQLSMALLINT NameLength = 0, DataType = 0, DecimalDigits = 0, Nullable = 0;
614 SQLULEN ColumnSize = 0;
616 SQLCHAR SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH];
617 SQLINTEGER NativeError;
618 SQLSMALLINT diagCount, MsgLen;
619 names[y] = malloc(name_len);
621 memset(names[y], 0, name_len);
623 SQLDescribeCol(stmt, x, (SQLCHAR *) names[y], (SQLSMALLINT) name_len, &NameLength, &DataType, &ColumnSize, &DecimalDigits, &Nullable);
625 if (ColumnSize <= 16383 || ColumnSize == 2147483647) {
626 SQLCHAR val[16384] = { 0 };
627 SQLLEN StrLen_or_IndPtr;
635 rc = SQLGetData(stmt, x, SQL_C_CHAR, val, ColumnSize, &StrLen_or_IndPtr);
637 if (rc == SQL_SUCCESS_WITH_INFO) {
641 SQLGetDiagField(SQL_HANDLE_STMT, stmt, 0, SQL_DIAG_NUMBER, &numRecs, 0, 0);
643 while (diagCount <= numRecs) {
644 SQLGetDiagRec(SQL_HANDLE_STMT, stmt, diagCount, SqlState, &NativeError,Msg,
sizeof(Msg), &MsgLen);
645 if (!strcmp((
char*)SqlState,
"01004")){
654 if (StrLen_or_IndPtr && StrLen_or_IndPtr <= 268435456) {
655 int ValLen = strlen((
char*)val);
656 ColumnSize = StrLen_or_IndPtr + 1;
657 vals[y] = malloc(ColumnSize);
659 memset(vals[y], 0, ColumnSize);
660 strcpy(vals[y], (
char*)val);
661 rc = SQLGetData(stmt, x, SQL_C_CHAR, (SQLCHAR *)vals[y] + ValLen, ColumnSize - ValLen, NULL);
662 if (rc != SQL_SUCCESS
663 #
if (ODBCVER >= 0x0300)
678 }
else if (rc == SQL_SUCCESS){
679 vals[y] = strdup((
char *)val);
687 vals[y] = malloc(ColumnSize);
689 memset(vals[y], 0, ColumnSize);
690 SQLGetData(stmt, x, SQL_C_CHAR, (SQLCHAR *) vals[y], ColumnSize, NULL);
695 if (callback(pdata, y, vals, names)) {
699 for (x = 0; x < y; x++) {
707 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
720 if (
zstr(err_str) && !
zstr(x_err)) {
721 err_str = strdup(x_err);
734 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
744 #ifdef SWITCH_HAVE_ODBC 756 if (handle->env != SQL_NULL_HANDLE) {
757 SQLFreeHandle(SQL_HANDLE_DBC, handle->con);
758 SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
773 #ifdef SWITCH_HAVE_ODBC 782 #ifdef SWITCH_HAVE_ODBC 784 char buffer[SQL_MAX_MESSAGE_LENGTH + 1] =
"";
785 char sqlstate[SQL_SQLSTATE_SIZE + 1] =
"";
790 if (SQLError(handle->env, handle->con, stmt, (SQLCHAR *) sqlstate, &sqlcode, (SQLCHAR *) buffer,
sizeof(buffer), &length) == SQL_SUCCESS) {
791 ret =
switch_mprintf(
"STATE: %s CODE %ld ERROR: %s\n", sqlstate, sqlcode, buffer);
802 #ifdef SWITCH_HAVE_ODBC 803 return handle->affected_rows;
811 #ifdef SWITCH_HAVE_ODBC 820 #ifdef SWITCH_HAVE_ODBC 826 return SQLSetConnectAttr(handle->con, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER *) SQL_AUTOCOMMIT_ON, 0 );
828 return SQLSetConnectAttr(handle->con, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER *) SQL_AUTOCOMMIT_OFF, 0 );
837 #ifdef SWITCH_HAVE_ODBC 839 return SQLEndTran(SQL_HANDLE_DBC, handle->con, SQL_COMMIT);
841 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.
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.
int(* switch_core_db_callback_func_t)(void *pArg, int argc, char **argv, char **columnNames)
#define DEFAULT_ODBC_RETRIES
uint8_t skip_autocommit_flip
#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_odbc_skip_autocommit_flip(void)
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)