Index: include/asterisk/res_odbc.h =================================================================== --- include/asterisk/res_odbc.h (revision 15785) +++ include/asterisk/res_odbc.h (working copy) @@ -74,6 +74,17 @@ */ struct odbc_obj *odbc_request_obj(const char *name, int check); +/*! \brief Show diagnostic information + * \param obj The ODBC object + * \param res result code from last ODBC call + * \param type handle type where error occurred + * \param handle handle where error occurred + * \param msg error message to be show to the user + * \param sql statement query used + * \return Returns statement handle or NULL in case of error + */ +void odbc_diag(struct odbc_obj *obj, int res, SQLSMALLINT type, SQLHANDLE handle, char *msg, char *sql); + /*! \brief Releases an ODBC object previously allocated by odbc_request_obj() * \param obj The ODBC object */ @@ -85,6 +96,12 @@ */ int odbc_sanity_check(struct odbc_obj *obj); +/*! \brief Alloc a new ODBC statement + * \param obj The ODBC object + * \return Returns statement handle or NULL in case of error + */ +SQLHSTMT odbc_obj_alloc_statement(struct odbc_obj *obj); + /*! \brief Prepares, executes, and returns the resulting statement handle. * \param obj The ODBC object * \param prepare_cb A function callback, which, when called, should return a statement handle prepared, with any necessary parameters or result columns bound. Index: res/res_config_odbc.c =================================================================== --- res/res_config_odbc.c (revision 15785) +++ res/res_config_odbc.c (working copy) @@ -85,9 +85,8 @@ if (!obj) return NULL; - res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n"); + stmt = odbc_obj_alloc_statement(obj); + if (stmt == SQL_NULL_HANDLE) { odbc_release_obj(obj); return NULL; } @@ -109,7 +108,7 @@ va_end(aq); res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL Prepare", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); return NULL; @@ -126,7 +125,7 @@ res = odbc_smart_execute(obj, stmt); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL smart execute", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); return NULL; @@ -134,7 +133,7 @@ res = SQLNumResultCols(stmt, &colcount); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql); + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL Column Count", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); return NULL; @@ -147,7 +146,7 @@ return NULL; } if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL Fetch", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); return NULL; @@ -158,7 +157,7 @@ res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen, &datatype, &colsize, &decimaldigits, &nullable); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql); + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL Describe Column", sql); if (var) ast_variables_destroy(var); odbc_release_obj(obj); @@ -171,7 +170,7 @@ continue; if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL GetData", sql); if (var) ast_variables_destroy(var); odbc_release_obj(obj); @@ -236,9 +235,8 @@ if (!obj) return NULL; - res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n"); + stmt = odbc_obj_alloc_statement(obj); + if (stmt == SQL_NULL_HANDLE) { odbc_release_obj(obj); return NULL; } @@ -265,7 +263,7 @@ va_end(aq); res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL Prepare", sql); SQLFreeHandle(SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); return NULL; @@ -282,7 +280,7 @@ res = odbc_smart_execute(obj, stmt); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL smart Execute", sql); SQLFreeHandle(SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); return NULL; @@ -290,7 +288,7 @@ res = SQLNumResultCols(stmt, &colcount); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql); + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL Column Count", sql); SQLFreeHandle(SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); return NULL; @@ -307,7 +305,7 @@ while ((res=SQLFetch(stmt)) != SQL_NO_DATA) { var = NULL; if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL Fetch", sql); continue; } cat = ast_category_new(""); @@ -321,7 +319,7 @@ res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen, &datatype, &colsize, &decimaldigits, &nullable); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql); + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL Describe Column", sql); ast_category_destroy(cat); continue; } @@ -332,7 +330,7 @@ continue; if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL GetData", sql); ast_category_destroy(cat); continue; } @@ -375,9 +373,8 @@ if (!obj) return -1; - res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n"); + stmt = odbc_obj_alloc_statement(obj); + if (stmt == SQL_NULL_HANDLE) { odbc_release_obj(obj); return -1; } @@ -399,7 +396,7 @@ res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL Prepare", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); return -1; @@ -418,7 +415,7 @@ res = odbc_smart_execute(obj, stmt); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL smart execute", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); return -1; @@ -429,10 +426,12 @@ odbc_release_obj(obj); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql); + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL Row Count", sql); + odbc_release_obj(obj); return -1; } + odbc_release_obj(obj); if (rowcount >= 0) return (int)rowcount; @@ -460,15 +459,13 @@ res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &sth); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - if (option_verbose > 3) - ast_verbose( VERBOSE_PREFIX_4 "Failure in AllocStatement %d\n", res); + odbc_diag(obj, res, SQL_HANDLE_DBC, obj->con, "SQL AllocStatement Error", NULL); return NULL; } res = SQLPrepare(sth, (unsigned char *)q->sql, SQL_NTS); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - if (option_verbose > 3) - ast_verbose( VERBOSE_PREFIX_4 "Error in PREPARE %d\n", res); + odbc_diag(obj, res, SQL_HANDLE_STMT, sth, "SQL Prepare Error", NULL); SQLFreeHandle(SQL_HANDLE_STMT, sth); return NULL; } @@ -521,7 +518,7 @@ res = SQLNumResultCols(stmt, &rowcount); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL NumResultCols error!\n[%s]\n\n", sql); + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL NumResultCols", sql); SQLFreeHandle(SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); return NULL; Index: res/res_odbc.c =================================================================== --- res/res_odbc.c (revision 15785) +++ res/res_odbc.c (working copy) @@ -57,6 +57,7 @@ char dsn[80]; char username[80]; char password[80]; + char test_sql[80]; SQLHENV env; unsigned int haspool:1; /* Boolean - TDS databases need this */ unsigned int limit:10; /* Gives a limit of 1023 maximum */ @@ -72,12 +73,67 @@ static char *tdesc = "ODBC Resource"; +void odbc_diag(struct odbc_obj *obj, int res, SQLSMALLINT type, SQLHANDLE handle, char *msg, char *sql) +{ + int i; + unsigned char state[10], diagnostic[256]; + SQLINTEGER nativeerror=0, numfields=0; + SQLSMALLINT diagbytes=0; + char *name = (obj && obj->parent && obj->parent->name) ? obj->parent->name : ""; + + i = SQLGetDiagField(type, handle, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes); + if ((i == SQL_INVALID_HANDLE) || (i == SQL_ERROR)) { + ast_log(LOG_WARNING, "%s:%p %s returned an error %d, Unable to get diagnostic information\n", + name, handle, msg, res); + } else if (i == SQL_NO_DATA) { + ast_log(LOG_WARNING, "%s:%p %s returned an error %d, no diagnostic available\n", + name, handle, msg, res); + } else { + for (i=0; i< numfields + 1; i++) { + SQLGetDiagRec(type, handle, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes); + if (i == 0) { + if (ast_strlen_zero(sql)) { + ast_log(LOG_WARNING, "%s:%p %s returned an error %d: %s: %s (%d)\n", + name, handle, msg, res, state, diagnostic, diagbytes); + } else { + ast_log(LOG_WARNING, "%s:%p %s returned an error %d: %s: %s (%d)\n%s\n", + name, handle, msg, res, state, diagnostic, diagbytes, sql); + } + } else { + ast_log(LOG_WARNING, "%s:%p Extra diagnostic : %s: %s (%d)\n", + name, handle, state, diagnostic, diagbytes); + } + if (i > 10) { + ast_log(LOG_WARNING, "%s:%x Oh, that was good. There are really %d diagnostics?\n", + name, handle, (int)numfields); + break; + } + } + } +} + +SQLHSTMT odbc_obj_alloc_statement(struct odbc_obj *obj) +{ + int res = 0; + SQLHSTMT stmt = SQL_NULL_HANDLE; + + if (!obj->up) { + odbc_obj_connect(obj); + } + if (obj->up) { + res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt); + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + odbc_diag(obj, res, SQL_HANDLE_DBC, obj->con, "SQL Alloc Statement", NULL); + odbc_obj_disconnect(obj); + return SQL_NULL_HANDLE; + } + } + return stmt; +} + SQLHSTMT odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT (*prepare_cb)(struct odbc_obj *obj, void *data), void *data) { - int res = 0, i, attempt; - SQLINTEGER nativeerror=0, numfields=0; - SQLSMALLINT diagbytes=0; - unsigned char state[10], diagnostic[256]; + int res = 0, attempt; SQLHSTMT stmt; for (attempt = 0; attempt < 2; attempt++) { @@ -92,19 +148,12 @@ res = SQLExecute(stmt); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) { if (res == SQL_ERROR) { - SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes); - for (i=0; i< numfields + 1; i++) { - SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes); - ast_log(LOG_WARNING, "SQL Execute returned an error %d: %s: %s (%d)\n", res, state, diagnostic, diagbytes); - if (i > 10) { - ast_log(LOG_WARNING, "Oh, that was good. There are really %d diagnostics?\n", (int)numfields); - break; - } - } + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL Execute", data); } ast_log(LOG_WARNING, "SQL Execute error %d! Attempting a reconnect...\n", res); SQLFreeHandle(SQL_HANDLE_STMT, stmt); + stmt = NULL; obj->up = 0; /* @@ -112,7 +161,6 @@ * fail when the statement handle invalidates. */ /* XXX Actually, it might, if we're using a non-pooled connection. Possible race here. XXX */ - odbc_obj_disconnect(obj); odbc_obj_connect(obj); continue; } @@ -125,23 +173,12 @@ int odbc_smart_execute(struct odbc_obj *obj, SQLHSTMT stmt) { - int res = 0, i; - SQLINTEGER nativeerror=0, numfields=0; - SQLSMALLINT diagbytes=0; - unsigned char state[10], diagnostic[256]; + int res = 0; res = SQLExecute(stmt); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) { if (res == SQL_ERROR) { - SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes); - for (i=0; i< numfields + 1; i++) { - SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes); - ast_log(LOG_WARNING, "SQL Execute returned an error %d: %s: %s (%d)\n", res, state, diagnostic, diagbytes); - if (i > 10) { - ast_log(LOG_WARNING, "Oh, that was good. There are really %d diagnostics?\n", (int)numfields); - break; - } - } + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL Execute", NULL); } #if 0 /* This is a really bad method of trying to correct a dead connection. It @@ -155,7 +192,6 @@ ast_mutex_lock(&obj->lock); obj->up = 0; ast_mutex_unlock(&obj->lock); - odbc_obj_disconnect(obj); odbc_obj_connect(obj); res = SQLExecute(stmt); #endif @@ -164,34 +200,35 @@ return res; } - int odbc_sanity_check(struct odbc_obj *obj) { - char *test_sql = "select 1"; SQLHSTMT stmt; - int res = 0; + int res = 0, err = 0; - if (obj->up) { - res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - obj->up = 0; - } else { - res = SQLPrepare(stmt, (unsigned char *)test_sql, SQL_NTS); + ast_mutex_lock(&obj->lock); + if (obj->up) { /* so you say... let's make sure */ + stmt = odbc_obj_alloc_statement(obj); + if (stmt != SQL_NULL_HANDLE) { + res = SQLPrepare(stmt, (unsigned char *)obj->parent->test_sql, SQL_NTS); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - obj->up = 0; + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL Prepare", obj->parent->test_sql); + err = 1; } else { res = SQLExecute(stmt); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - obj->up = 0; + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "Sanity check query", obj->parent->test_sql); + err = 1; + } else { + ast_verbose(VERBOSE_PREFIX_3 "Sanity check passed on %s\n", obj->parent->name); } } + SQLFreeHandle (SQL_HANDLE_STMT, stmt); } - SQLFreeHandle (SQL_HANDLE_STMT, stmt); } + ast_mutex_unlock(&obj->lock); - if (!obj->up) { /* Try to reconnect! */ + if(!obj->up || err) { /* Try to reconnect! */ ast_log(LOG_WARNING, "Connection is down attempting to reconnect...\n"); - odbc_obj_disconnect(obj); odbc_obj_connect(obj); } return obj->up; @@ -202,7 +239,7 @@ static char *cfg = "res_odbc.conf"; struct ast_config *config; struct ast_variable *v; - char *cat, *dsn, *username, *password; + char *cat, *dsn, *username, *password, *test_sql; int enabled, pooling, limit; int connect = 0, res = 0; @@ -218,7 +255,7 @@ } } else { /* Reset all to defaults for each class of odbc connections */ - dsn = username = password = NULL; + dsn = username = password = test_sql = NULL; enabled = 1; connect = 0; pooling = 0; @@ -246,6 +283,8 @@ username = v->value; } else if (!strcasecmp(v->name, "password")) { password = v->value; + } else if (!strcmp(v->name, "test_sql")) { + test_sql = v->value; } } @@ -262,7 +301,30 @@ ast_copy_string(new->dsn, dsn, sizeof(new->dsn)); ast_copy_string(new->username, username, sizeof(new->username)); ast_copy_string(new->password, password, sizeof(new->password)); - SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &new->env); + if (test_sql) { + ast_copy_string(new->test_sql, test_sql, sizeof(new->test_sql)); + } else { + ast_copy_string(new->test_sql, "select 1", sizeof(new->test_sql)); + } + res = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &new->env); + + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + if (option_verbose > 3) + ast_log(LOG_WARNING, "res_odbc: Error Alloc Environment Handle : %d\n", res); + free(new); + break; + } + + res = SQLSetEnvAttr(new->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0); + + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + odbc_diag(NULL, res, SQL_HANDLE_ENV, new->env, "SQL SetEnvAttr", NULL); + SQLFreeHandle(SQL_HANDLE_ENV, new->env); + + free(new); + break; + } + if (pooling) { new->haspool = pooling; if (limit) { @@ -413,7 +475,7 @@ } AST_LIST_UNLOCK(&class->odbc_obj); - if (obj && check) { + if (obj && (check || !obj->up)) { odbc_sanity_check(obj); } return obj; @@ -424,13 +486,15 @@ int res; ast_mutex_lock(&obj->lock); - res = SQLDisconnect(obj->con); + if (obj->con != SQL_NULL_HANDLE) { + res = SQLDisconnect(obj->con); - if (res == ODBC_SUCCESS) { - ast_log(LOG_WARNING, "res_odbc: disconnected %d from %s [%s]\n", res, obj->parent->name, obj->parent->dsn); - } else { - ast_log(LOG_WARNING, "res_odbc: %s [%s] already disconnected\n", - obj->parent->name, obj->parent->dsn); + if (res == ODBC_SUCCESS) { + ast_log(LOG_WARNING, "res_odbc: disconnected from %s [%s]\n", obj->parent->name, obj->parent->dsn); + } else { + ast_log(LOG_WARNING, "res_odbc: %s [%s] already disconnected (%d)\n", + obj->parent->name, obj->parent->dsn, res); + } } obj->up = 0; ast_mutex_unlock(&obj->lock); @@ -440,41 +504,47 @@ static odbc_status odbc_obj_connect(struct odbc_obj *obj) { int res; - SQLINTEGER err; - short int mlen; - unsigned char msg[200], stat[10]; + if(obj->up) { + odbc_obj_disconnect(obj); + ast_log(LOG_NOTICE,"Re-connecting %s\n", obj->parent->name); + } else { + ast_log(LOG_NOTICE, "Connecting %s\n", obj->parent->name); + } + ast_mutex_lock(&obj->lock); - res = SQLAllocHandle(SQL_HANDLE_DBC, obj->parent->env, &obj->con); + if (obj->con == SQL_NULL_HANDLE) { + res = SQLAllocHandle(SQL_HANDLE_DBC, obj->parent->env, &obj->con); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - if (option_verbose > 3) - ast_log(LOG_WARNING, "res_odbc: Error AllocHDB %d\n", res); - SQLFreeHandle(SQL_HANDLE_ENV, obj->parent->env); + odbc_diag(obj, res, SQL_HANDLE_ENV, obj->parent->env, "Alloc Connect Handle", NULL); + if (option_verbose > 3) + ast_log(LOG_WARNING, "res_odbc: Error AllocHDB %d\n", res); + SQLFreeHandle(SQL_HANDLE_ENV, obj->parent->env); + obj->parent->env = SQL_NULL_HANDLE; - ast_mutex_unlock(&obj->lock); - return ODBC_FAIL; - } - SQLSetConnectAttr(obj->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0); + ast_mutex_unlock(&obj->lock); + return ODBC_FAIL; + } + SQLSetConnectAttr(obj->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0); + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + odbc_diag(obj, res, SQL_HANDLE_DBC, obj->con, "SQL SetConnectAttr", NULL); + } - if (obj->up) { - odbc_obj_disconnect(obj); - ast_log(LOG_NOTICE, "Re-connecting %s\n", obj->parent->name); } - - ast_log(LOG_NOTICE, "Connecting %s\n", obj->parent->name); - res = SQLConnect(obj->con, (SQLCHAR *) obj->parent->dsn, SQL_NTS, (SQLCHAR *) obj->parent->username, SQL_NTS, (SQLCHAR *) obj->parent->password, SQL_NTS); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - SQLGetDiagRec(SQL_HANDLE_DBC, obj->con, 1, stat, &err, msg, 100, &mlen); + odbc_diag(obj, res, SQL_HANDLE_DBC, obj->con, "SQLConnect", NULL); + SQLFreeHandle(SQL_HANDLE_DBC, obj->con); + obj->con = SQL_NULL_HANDLE; + ast_mutex_unlock(&obj->lock); - ast_log(LOG_WARNING, "res_odbc: Error SQLConnect=%d errno=%d %s\n", res, (int)err, msg); return ODBC_FAIL; } else { ast_log(LOG_NOTICE, "res_odbc: Connected to %s [%s]\n", obj->parent->name, obj->parent->dsn);