Index: res/res_odbc.c =================================================================== --- res/res_odbc.c (revision 34550) +++ res/res_odbc.c (working copy) @@ -60,6 +60,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 */ @@ -68,21 +69,107 @@ AST_LIST_HEAD(, odbc_obj) odbc_obj; }; +#define DEFAULT_TEST_SQL "select 1" + AST_LIST_HEAD_STATIC(odbc_list, odbc_class); static odbc_status odbc_obj_connect(struct odbc_obj *obj); static odbc_status odbc_obj_disconnect(struct odbc_obj *obj); static int odbc_register_class(struct odbc_class *class, int connect); +static void odbc_diag_class(struct odbc_class *class, struct odbc_obj *obj, int res, SQLSMALLINT type, SQLHANDLE handle, char *msg, char *sql); -SQLHSTMT odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT (*prepare_cb)(struct odbc_obj *obj, void *data), void *data) +static void odbc_diag_class(struct odbc_class *class, struct odbc_obj *obj, int res, SQLSMALLINT type, SQLHANDLE handle, char *msg, char *sql) { - int res = 0, i, attempt; + int i; + unsigned char state[10], diagnostic[256]; SQLINTEGER nativeerror=0, numfields=0; SQLSMALLINT diagbytes=0; - unsigned char state[10], diagnostic[256]; + char *name = (class && class->name) ? class->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:obj=%p:h=%p %s returned an error %d, Unable to get diagnostic information\n", + name, obj, handle, msg, res); + } else if (i == SQL_NO_DATA) { + ast_log(LOG_WARNING, "%s:obj=%p:h=%p %s returned an error %d, no diagnostic available\n", + name, obj, 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:obj=%p:h=%p %s returned an error %d: %s: %s (%d)\n", + name, obj, handle, msg, res, state, diagnostic, diagbytes); + } else { + ast_log(LOG_WARNING, "%s:obj=%p:h=%p %s returned an error %d: %s: %s (%d)\n%s\n", + name, obj, handle, msg, res, state, diagnostic, diagbytes, sql); + } + } else { + ast_log(LOG_WARNING, "%s:obj=%p:h=%p Extra diagnostic : %s: %s (%d)\n", + name, obj, handle, state, diagnostic, diagbytes); + } + if (i > 10) { + ast_log(LOG_WARNING, "%s:obj=%p:h=%p Oh, that was good. There are really %d diagnostics?\n", + name, obj, handle, (int)numfields); + break; + } + } + } +} + +void odbc_diag(struct odbc_obj *obj, int res, SQLSMALLINT type, SQLHANDLE handle, char *msg, char *sql) +{ + odbc_diag_class((obj != NULL) ? obj->parent : NULL, obj, res, type, handle, msg, sql); +} + +SQLHSTMT odbc_alloc_statement(struct odbc_obj *obj) +{ + int res; + SQLHSTMT stmt = SQL_NULL_HANDLE; + + if (!obj->up) { + if (odbc_obj_connect(obj) != ODBC_SUCCESS) { + return SQL_NULL_HANDLE; + } + } + 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 AllocStatement failed!", NULL); + if (obj->class->haspool) { + // we probably have problem with this connection, disconnect is a good option + odbc_obj_disconnect(obj); + } + return SQL_NULL_HANDLE; + } else { + // XXX todo create a list of active statements to be automaticaly freed on odbc_release_obj + // XXX check carefully because will work for pooled only + } + return stmt; +} + +SQLHSTMT odbc_prepare_statement(struct odbc_obj *obj, char *sql) +{ SQLHSTMT stmt; + + stmt = odbc_alloc_statement(obj); + if (stmt != SQL_NULL_HANDLE) { + int res; + res = SQLPrepare(stmt, sql, SQL_NTS); + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL Prepare error!", sql); + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + stmt = 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, attempt; + SQLHSTMT stmt = SQL_NULL_HANDLE; + for (attempt = 0; attempt < 2; attempt++) { /* This prepare callback may do more than just prepare -- it may also * bind parameters, bind results, etc. The real key, here, is that @@ -94,20 +181,11 @@ if (stmt) { 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 = SQL_NULL_HANDLE; obj->up = 0; /* @@ -128,24 +206,11 @@ 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 Smart Execute", NULL); #if 0 /* This is a really bad method of trying to correct a dead connection. It * only ever really worked with MySQL. It will not work with any other @@ -170,7 +235,6 @@ int odbc_sanity_check(struct odbc_obj *obj) { - char *test_sql = "select 1"; SQLHSTMT stmt; int res = 0; @@ -179,7 +243,7 @@ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { obj->up = 0; } else { - res = SQLPrepare(stmt, (unsigned char *)test_sql, SQL_NTS); + res = SQLPrepare(stmt, (unsigned char *)obj->parent->test_sql, SQL_NTS); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { obj->up = 0; } else { @@ -205,7 +269,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; @@ -221,7 +285,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; @@ -249,6 +313,8 @@ username = v->value; } else if (!strcasecmp(v->name, "password")) { password = v->value; + } else if (!strcasecmp(v->name, "test_sql")) { + test_sql = v->value; } } @@ -268,14 +334,26 @@ ast_copy_string(new->username, username, sizeof(new->username)); if (password) ast_copy_string(new->password, password, sizeof(new->password)); + if (test_sql) + ast_copy_string(new->test_sql, test_sql, sizeof(new->test_sql)); + else + ast_copy_string(new->test_sql, DEFAULT_TEST_SQL, sizeof(new->test_sql)); - SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &new->env); + res = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &new->env); + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + ast_log(LOG_WARNING, "res_odbc: Error AllocHandle Environment: %d\n", res); + free(new); + // continue with next database + continue; + } res = SQLSetEnvAttr(new->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "res_odbc: Error SetEnv\n"); + odbc_diag_class(new, NULL, res, SQL_HANDLE_ENV, new->env, "Error in SetEnv", NULL); SQLFreeHandle(SQL_HANDLE_ENV, new->env); - return res; + free(new); + // continue with next database + continue; } if (pooling) { @@ -379,8 +457,10 @@ } AST_LIST_UNLOCK(&odbc_list); - if (!class) + if (!class) { + ast_log(LOG_WARNING, "No ODBC database configured for name : %s\n", name); return NULL; + } AST_LIST_LOCK(&class->odbc_obj); if (class->haspool) { @@ -424,6 +504,7 @@ ast_log(LOG_WARNING, "Failed to connect\n"); ast_mutex_destroy(&obj->lock); free(obj); + obj = NULL; } else { AST_LIST_INSERT_HEAD(&class->odbc_obj, obj, list); } @@ -442,13 +523,16 @@ 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:obj=%p disconnected %d from %s [%s]\n", + obj, res, obj->parent->name, obj->parent->dsn); + } else { + ast_log(LOG_WARNING, "res_odbc:obj=%p %s [%s] already disconnected (%d)\n", + obj, obj->parent->name, obj->parent->dsn, res); + } } obj->up = 0; ast_mutex_unlock(&obj->lock); @@ -458,9 +542,6 @@ static odbc_status odbc_obj_connect(struct odbc_obj *obj) { int res; - SQLINTEGER err; - short int mlen; - unsigned char msg[200], stat[10]; #ifdef NEEDTRACE SQLINTEGER enable = 1; char *tracefile = "/tmp/odbc.trace"; @@ -471,8 +552,8 @@ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - 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); + //XXX here maybe we must try to realloc ENV ??? ast_mutex_unlock(&obj->lock); return ODBC_FAIL; @@ -485,9 +566,9 @@ if (obj->up) { odbc_obj_disconnect(obj); - ast_log(LOG_NOTICE, "Re-connecting %s\n", obj->parent->name); + ast_log(LOG_NOTICE, "res_odbc:obj=%p Re-connecting %s\n", obj, obj->parent->name); } else { - ast_log(LOG_NOTICE, "Connecting %s\n", obj->parent->name); + ast_log(LOG_NOTICE, "res_odbc:obj=%p Connecting %s\n", obj, obj->parent->name); } res = SQLConnect(obj->con, @@ -496,12 +577,14 @@ (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); + ast_log(LOG_NOTICE, "res_odbc:obj=%p Connected to %s [%s]\n", + obj, obj->parent->name, obj->parent->dsn); obj->up = 1; } @@ -516,7 +599,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; @@ -539,7 +622,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; @@ -567,6 +650,8 @@ username = v->value; } else if (!strcasecmp(v->name, "password")) { password = v->value; + } else if (!strcasecmp(v->name, "test_sql")) { + test_sql = v->value; } } @@ -598,15 +683,22 @@ ast_copy_string(new->username, username, sizeof(new->username)); if (password) ast_copy_string(new->password, password, sizeof(new->password)); + if (test_sql) + ast_copy_string(new->test_sql, test_sql, sizeof(new->test_sql)); + else + ast_copy_string(new->test_sql, DEFAULT_TEST_SQL, sizeof(new->test_sql)); if (!class) { SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &new->env); res = SQLSetEnvAttr(new->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "res_odbc: Error SetEnv\n"); + odbc_diag_class(new, NULL, res, SQL_HANDLE_ENV, new->env, "Error in SetEnv", NULL); SQLFreeHandle(SQL_HANDLE_ENV, new->env); AST_LIST_UNLOCK(&odbc_list); + if (new != class) { + free(new); + } return res; } } Index: include/asterisk/res_odbc.h =================================================================== --- include/asterisk/res_odbc.h (revision 34550) +++ include/asterisk/res_odbc.h (working copy) @@ -93,4 +93,27 @@ */ SQLHSTMT odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT (*prepare_cb)(struct odbc_obj *obj, void *data), void *data); +/*! \brief Show diagnostic information about odbc error + * \param obj The ODBC object + * \param res result code from ODBC function which resulted in error + * \param type type of handle used + * \param handle handle which resulted in the error + * \param msg message to user + * \param sql sql statement which resulted in the error + */ +void odbc_diag(struct odbc_obj *obj, int res, SQLSMALLINT type, SQLHANDLE handle, char *msg, char *sql); + +/*! \brief Allocate a new ODBC statement + * \param obj The ODBC object + * \return the statement handle or SQL_NULL_HANDLE in case of error + */ +SQLHSTMT odbc_alloc_statement(struct odbc_obj *obj); + +/*! \brief Allocate a new ODBC statement and prepare it + * \param obj The ODBC object + * \param sql the statement sql + * \return the prepared statement handle or SQL_NULL_HANDLE in case of error + */ +SQLHSTMT odbc_prepare_statement(struct odbc_obj *obj, char *sql); + #endif /* _ASTERISK_RES_ODBC_H */ Index: apps/app_voicemail.c =================================================================== --- apps/app_voicemail.c (revision 34550) +++ apps/app_voicemail.c (working copy) @@ -893,17 +893,9 @@ snprintf(full_fn, sizeof(full_fn), "%s.txt", fn); f = fopen(full_fn, "w+"); snprintf(full_fn, sizeof(full_fn), "%s.%s", fn, fmt); - 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"); - odbc_release_obj(obj); - goto yuck; - } snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE dir=? AND msgnum=?",odbc_table); - res = SQLPrepare(stmt, sql, SQL_NTS); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); + stmt = odbc_prepare_statement(obj, sql); + if (stmt == SQL_NULL_HANDLE) { odbc_release_obj(obj); goto yuck; } @@ -911,19 +903,20 @@ SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL); 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); + ast_log(LOG_WARNING, "unable to execute statement %s\n", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; } res = SQLFetch(stmt); if (res == SQL_NO_DATA) { + ast_log(LOG_WARNING, "Message %s/%s not found on ODBC storage\n", dir, msgnums); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; } else 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 error!", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; @@ -937,7 +930,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 error!", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; @@ -950,13 +943,19 @@ res = SQLDescribeCol(stmt, x + 1, 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 error!", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; } if (!strcasecmp(coltitle, "recording")) { res = SQLGetData(stmt, x + 1, SQL_BINARY, NULL, 0, &colsize); + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + odbc_diag(obj, res, SQL_HANDLE_STMT, stmt, "SQL Get Data error!", sql); + SQLFreeHandle (SQL_HANDLE_STMT, stmt); + odbc_release_obj(obj); + goto yuck; + } fdlen = colsize; if (fd > -1) { char tmp[1]=""; @@ -973,7 +972,7 @@ memset(fdm, 0, fdlen); res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm, fdlen, &colsize); 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 Get Data error!", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; @@ -982,7 +981,7 @@ } else { res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL); 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 Get Data error!", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; @@ -1033,38 +1032,30 @@ struct odbc_obj *obj; obj = odbc_request_obj(odbc_database, 0); if (obj) { - 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"); - odbc_release_obj(obj); - goto yuck; - } snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir=?",odbc_table); - res = SQLPrepare(stmt, sql, SQL_NTS); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); + stmt = odbc_prepare_statement(obj, sql); + if (stmt == SQL_NULL_HANDLE) { odbc_release_obj(obj); goto yuck; } SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dir), 0, (void *)dir, 0, NULL); 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); + ast_log(LOG_WARNING, "unable to execute statement %s\n", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; } res = SQLFetch(stmt); 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 error!", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; } res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL); 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 error!", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; @@ -1092,17 +1083,9 @@ obj = odbc_request_obj(odbc_database, 0); if (obj) { snprintf(msgnums, sizeof(msgnums), "%d", msgnum); - 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"); - odbc_release_obj(obj); - goto yuck; - } snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir=? AND msgnum=?",odbc_table); - res = SQLPrepare(stmt, sql, SQL_NTS); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); + stmt = odbc_prepare_statement(obj, sql); + if (stmt == SQL_NULL_HANDLE) { odbc_release_obj(obj); goto yuck; } @@ -1110,21 +1093,21 @@ SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL); 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); + ast_log(LOG_WARNING, "unable to execute statement %s\n", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; } res = SQLFetch(stmt); 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 error!", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; } res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL); 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 error!", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; @@ -1155,25 +1138,17 @@ obj = odbc_request_obj(odbc_database, 0); if (obj) { snprintf(msgnums, sizeof(msgnums), "%d", smsg); - 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"); - odbc_release_obj(obj); - goto yuck; - } snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE dir=? AND msgnum=?",odbc_table); - res = SQLPrepare(stmt, sql, SQL_NTS); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); + stmt = odbc_prepare_statement(obj, sql); + if (stmt == SQL_NULL_HANDLE) { odbc_release_obj(obj); goto yuck; } SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(sdir), 0, (void *)sdir, 0, NULL); SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL); 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); + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) { + ast_log(LOG_WARNING, "unable to execute statement %s\n", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; @@ -1200,21 +1175,13 @@ if (obj) { snprintf(msgnums, sizeof(msgnums), "%d", smsg); snprintf(msgnumd, sizeof(msgnumd), "%d", dmsg); - 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"); - odbc_release_obj(obj); - goto yuck; - } #ifdef EXTENDED_ODBC_STORAGE snprintf(sql, sizeof(sql), "INSERT INTO %s (dir, msgnum, context, macrocontext, callerid, origtime, duration, recording, mailboxuser, mailboxcontext) SELECT ?,?,context,macrocontext,callerid,origtime,duration,recording,?,? FROM %s WHERE dir=? AND msgnum=?",odbc_table,odbc_table); #else snprintf(sql, sizeof(sql), "INSERT INTO %s (dir, msgnum, context, macrocontext, callerid, origtime, duration, recording) SELECT ?,?,context,macrocontext,callerid,origtime,duration,recording FROM %s WHERE dir=? AND msgnum=?",odbc_table,odbc_table); #endif - res = SQLPrepare(stmt, sql, SQL_NTS); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); + stmt = odbc_prepare_statement(obj, sql); + if (stmt == SQL_NULL_HANDLE) { odbc_release_obj(obj); goto yuck; } @@ -1231,7 +1198,7 @@ #endif res = odbc_smart_execute(obj, stmt); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Execute error!\n[%s] (You probably don't have MySQL 4.1 or later installed)\n\n", sql); + ast_log(LOG_WARNING, "unable to execute statement %s\n", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; @@ -1310,12 +1277,6 @@ odbc_release_obj(obj); goto yuck; } - 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"); - odbc_release_obj(obj); - goto yuck; - } if (!ast_strlen_zero(category)) #ifdef EXTENDED_ODBC_STORAGE snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,category) VALUES (?,?,?,?,?,?,?,?,?,?,?)",odbc_table); @@ -1328,10 +1289,8 @@ #else snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration) VALUES (?,?,?,?,?,?,?,?)",odbc_table); #endif - res = SQLPrepare(stmt, sql, SQL_NTS); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); + stmt = odbc_prepare_statement(obj, sql); + if (stmt == SQL_NULL_HANDLE) { odbc_release_obj(obj); goto yuck; } @@ -1355,7 +1314,7 @@ #endif 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); + ast_log(LOG_WARNING, "unable to execute statement %s\n", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; @@ -1388,21 +1347,13 @@ if (obj) { snprintf(msgnums, sizeof(msgnums), "%d", smsg); snprintf(msgnumd, sizeof(msgnumd), "%d", dmsg); - 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"); - odbc_release_obj(obj); - goto yuck; - } #ifdef EXTENDED_ODBC_STORAGE snprintf(sql, sizeof(sql), "UPDATE %s SET dir=?, msgnum=?, mailboxuser=?, mailboxcontext=? WHERE dir=? AND msgnum=?",odbc_table); #else snprintf(sql, sizeof(sql), "UPDATE %s SET dir=?, msgnum=? WHERE dir=? AND msgnum=?",odbc_table); #endif - res = SQLPrepare(stmt, sql, SQL_NTS); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); + stmt = odbc_prepare_statement(obj, sql); + if (stmt == SQL_NULL_HANDLE) { odbc_release_obj(obj); goto yuck; } @@ -1419,7 +1370,7 @@ #endif 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); + ast_log(LOG_WARNING, "unable to execute statement %s\n", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; @@ -2060,37 +2011,29 @@ obj = odbc_request_obj(odbc_database, 0); if (obj) { - 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"); - odbc_release_obj(obj); - goto yuck; - } snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, tmp, "INBOX"); - res = SQLPrepare(stmt, sql, SQL_NTS); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); + stmt = odbc_prepare_statement(obj, sql); + if (stmt == SQL_NULL_HANDLE) { odbc_release_obj(obj); goto yuck; } 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); + ast_log(LOG_WARNING, "unable to execute statement %s\n", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; } res = SQLFetch(stmt); 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 error!", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; } res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL); 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 error!", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; @@ -2098,37 +2041,29 @@ *newmsgs = atoi(rowdata); SQLFreeHandle (SQL_HANDLE_STMT, stmt); - 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"); - odbc_release_obj(obj); - goto yuck; - } snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, tmp, "Old"); - res = SQLPrepare(stmt, sql, SQL_NTS); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); + stmt = odbc_prepare_statement(obj, sql); + if (stmt == SQL_NULL_HANDLE) { odbc_release_obj(obj); goto yuck; } 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); + ast_log(LOG_WARNING, "unable to execute statement %s\n", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; } res = SQLFetch(stmt); 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 error!", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; } res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL); 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 error!", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); goto yuck; @@ -2160,33 +2095,26 @@ obj = odbc_request_obj(odbc_database, 0); if (obj) { - 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"); - goto yuck; - } snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, mailbox, folder); - res = SQLPrepare(stmt, sql, SQL_NTS); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); - SQLFreeHandle(SQL_HANDLE_STMT, stmt); + stmt = odbc_prepare_statement(obj, sql); + if (stmt == SQL_NULL_HANDLE) { goto yuck; } 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); + ast_log(LOG_WARNING, "unable to execute statement %s\n", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); goto yuck; } res = SQLFetch(stmt); 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 error!", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); goto yuck; } res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL); 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 error!", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); goto yuck; }