diff --git a/conf/autoload_configs/switch.conf.xml b/conf/autoload_configs/switch.conf.xml index e861b1b61a..896dd0e712 100644 --- a/conf/autoload_configs/switch.conf.xml +++ b/conf/autoload_configs/switch.conf.xml @@ -86,6 +86,7 @@ + diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index ea02f22fa0..3df9001b0c 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -193,6 +193,11 @@ struct switch_media_bug { struct switch_media_bug *next; }; +typedef enum { + DBTYPE_DEFAULT = 0, + DBTYPE_MSSQL = 1, +} switch_dbtype_t; + struct switch_runtime { switch_time_t initiated; switch_time_t reference; @@ -237,6 +242,7 @@ struct switch_runtime { double min_idle_time; int sql_buffer_len; int max_sql_buffer_len; + switch_dbtype_t odbc_dbtype; }; extern struct switch_runtime runtime; diff --git a/src/include/switch_odbc.h b/src/include/switch_odbc.h index 81039f113d..b8d4bc2f17 100644 --- a/src/include/switch_odbc.h +++ b/src/include/switch_odbc.h @@ -58,6 +58,8 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_exec(switch_odbc_handle_ char **err); 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); SWITCH_DECLARE(switch_bool_t) switch_odbc_available(void); +SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_SQLSetAutoCommitAttr(switch_odbc_handle_t *handle, switch_bool_t on); +SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_SQLEndTran(switch_odbc_handle_t *handle, switch_bool_t commit); SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_statement_handle_free(switch_odbc_statement_handle_t *stmt); /*! diff --git a/src/switch_core.c b/src/switch_core.c index 2f89c7bca7..bd4b00d2ed 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1237,6 +1237,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc runtime.max_dtmf_duration = SWITCH_MAX_DTMF_DURATION; runtime.default_dtmf_duration = SWITCH_DEFAULT_DTMF_DURATION; runtime.min_dtmf_duration = SWITCH_MIN_DTMF_DURATION; + runtime.odbc_dbtype = DBTYPE_DEFAULT; /* INIT APR and Create the pool context */ if (apr_initialize() != SWITCH_STATUS_SUCCESS) { @@ -1590,6 +1591,12 @@ static void switch_load_core_config(const char *file) } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n"); } + } else if (!strcasecmp(var, "core-dbtype") && !zstr(val)) { + if (!strcasecmp(val, "MSSQL")) { + runtime.odbc_dbtype = DBTYPE_MSSQL; + } else { + runtime.odbc_dbtype = DBTYPE_DEFAULT; + } #ifdef ENABLE_ZRTP } else if (!strcasecmp(var, "rtp-enable-zrtp")) { switch_core_set_variable("zrtp_enabled", val); diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 7f995040e9..a85766c60c 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -699,7 +699,13 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_ while (begin_retries > 0) { again = 0; - switch_cache_db_execute_sql_real(dbh, "BEGIN", &errmsg); + if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { + switch_cache_db_execute_sql_real(dbh, "BEGIN", &errmsg); + } else { + if (switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 0) != SWITCH_ODBC_SUCCESS) { + errmsg = strdup("Unable to Set AutoCommit Off.");; + } + } if (errmsg) { begin_retries--; @@ -712,7 +718,13 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_ errmsg = NULL; if (again) { - switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL); + if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { + switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL); + } else { + switch_odbc_SQLEndTran(dbh->native_handle.odbc_dbh, 1); + switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 1); + } + goto again; } @@ -750,7 +762,12 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_ done: - switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL); + if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { + switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL); + } else { + switch_odbc_SQLEndTran(dbh->native_handle.odbc_dbh, 1); + switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 1); + } if (dbh->io_mutex) { switch_mutex_unlock(dbh->io_mutex); @@ -1304,6 +1321,7 @@ static void core_event_handler(switch_event_t *event) case SWITCH_EVENT_CHANNEL_BRIDGE: { const char *callee_cid_name, *callee_cid_num, *direction; + char *func_name; direction = switch_event_get_header(event, "other-leg-direction"); @@ -1319,10 +1337,19 @@ static void core_event_handler(switch_event_t *event) new_sql() = switch_mprintf("update channels set call_uuid='%q' where uuid='%s' and hostname='%q'", switch_event_get_header_nil(event, "channel-call-uuid"), switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname")); - new_sql() = switch_mprintf("insert into calls (call_uuid,call_created,call_created_epoch,function,caller_cid_name," + + if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { + func_name = "function"; + } + else { + func_name = "call_function"; + } + + new_sql() = switch_mprintf("insert into calls (call_uuid,call_created,call_created_epoch,%s,caller_cid_name," "caller_cid_num,caller_dest_num,caller_chan_name,caller_uuid,callee_cid_name," "callee_cid_num,callee_dest_num,callee_chan_name,callee_uuid,hostname) " "values ('%s', '%s', '%ld', '%s','%q','%q','%q','%q','%s','%q','%q','%q','%q','%s','%q')", + func_name, switch_event_get_header_nil(event, "channel-call-uuid"), switch_event_get_header_nil(event, "event-date-local"), (long) switch_epoch_time_now(NULL), @@ -1622,11 +1649,21 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ { char *err; switch_cache_db_test_reactive(dbh, "select call_uuid, read_bit_rate from channels", "DROP TABLE channels", create_channels_sql); - switch_cache_db_test_reactive(dbh, "select call_uuid from calls", "DROP TABLE calls", create_calls_sql); + if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { + switch_cache_db_test_reactive(dbh, "select call_uuid from calls", "DROP TABLE calls", create_calls_sql); + } else { + char *tmp = switch_string_replace(create_calls_sql, "function", "call_function"); + switch_cache_db_test_reactive(dbh, "select call_uuid from calls", "DROP TABLE calls", tmp); + free(tmp); + } switch_cache_db_test_reactive(dbh, "select ikey from interfaces", "DROP TABLE interfaces", create_interfaces_sql); switch_cache_db_test_reactive(dbh, "select hostname from tasks", "DROP TABLE tasks", create_tasks_sql); - switch_cache_db_execute_sql(dbh, "begin;delete from channels where hostname='';delete from channels where hostname='';commit;", &err); + if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { + switch_cache_db_execute_sql(dbh, "begin;delete from channels where hostname='';delete from channels where hostname='';commit;", &err); + } else { + switch_cache_db_execute_sql(dbh, "delete from channels where hostname='';delete from channels where hostname='';", &err); + } if (err) { runtime.odbc_dsn = NULL; diff --git a/src/switch_odbc.c b/src/switch_odbc.c index c853e14c4c..36c3c996e8 100644 --- a/src/switch_odbc.c +++ b/src/switch_odbc.c @@ -629,6 +629,32 @@ SWITCH_DECLARE(switch_bool_t) switch_odbc_available(void) #endif } +SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_SQLSetAutoCommitAttr(switch_odbc_handle_t *handle, switch_bool_t on) +{ +#ifdef SWITCH_HAVE_ODBC + if (on) { + return SQLSetConnectAttr(handle->con, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER *) SQL_AUTOCOMMIT_ON, 0 ); + } else { + return SQLSetConnectAttr(handle->con, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER *) SQL_AUTOCOMMIT_OFF, 0 ); + } +#else + return SWITCH_FALSE; +#endif +} + +SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_SQLEndTran(switch_odbc_handle_t *handle, switch_bool_t commit) +{ +#ifdef SWITCH_HAVE_ODBC + if (commit) { + return SQLEndTran(SQL_HANDLE_DBC, handle->con, SQL_COMMIT); + } else { + return SQLEndTran(SQL_HANDLE_DBC, handle->con, SQL_ROLLBACK); + } +#else + return SWITCH_FALSE; +#endif +} + /* For Emacs: * Local Variables: