Index: res/res_odbc.c =================================================================== --- res/res_odbc.c (revision 34575) +++ 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,58 +69,130 @@ 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]; - SQLHSTMT stmt; + 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); +} + +int odbc_just_prepare(struct odbc_obj *obj, SQLHSTMT stmt, void *data) +{ + int res; + char *sql = (char *)data; + + 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); + return PREPARE_ODBC_ERROR; + } + + return PREPARE_OK; +} + +SQLHSTMT odbc_prepare_and_execute(struct odbc_obj *obj, int (*prepare_cb)(struct odbc_obj *obj, SQLHSTMT stmt, 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 * when we disconnect, all handles become invalid for most databases. * We must therefore redo everything when we establish a new * connection. */ - stmt = prepare_cb(obj, data); + + 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); + /* 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; + } else { + res = prepare_cb(obj, stmt, data); - 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; - } - } + if (res == PREPARE_OK) { + res = SQLExecute(stmt); + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) { + 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; + /* + * While this isn't the best way to try to correct an error, this won't automatically + * 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; } - - ast_log(LOG_WARNING, "SQL Execute error %d! Attempting a reconnect...\n", res); + break; + } else if (res == PREPARE_ODBC_ERROR) { SQLFreeHandle(SQL_HANDLE_STMT, stmt); - - obj->up = 0; - /* - * While this isn't the best way to try to correct an error, this won't automatically - * fail when the statement handle invalidates. - */ + stmt = SQL_NULL_HANDLE; + /* 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; + } else { + // Generic error not related to ODBC + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + stmt = SQL_NULL_HANDLE; + break; } - break; } } @@ -128,24 +201,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 +230,6 @@ int odbc_sanity_check(struct odbc_obj *obj) { - char *test_sql = "select 1"; SQLHSTMT stmt; int res = 0; @@ -179,7 +238,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 +264,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 +280,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 +308,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 +329,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, "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 +452,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 +499,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 +518,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, "obj=%p disconnected %d from %s [%s]\n", + obj, res, obj->parent->name, obj->parent->dsn); + } else { + ast_log(LOG_WARNING, "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 +537,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 +547,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 maybe we must try to realloc ENV ??? this will invalidate all other connections */ ast_mutex_unlock(&obj->lock); return ODBC_FAIL; @@ -485,9 +561,9 @@ if (obj->up) { odbc_obj_disconnect(obj); - ast_log(LOG_NOTICE, "Re-connecting %s\n", obj->parent->name); + ast_log(LOG_NOTICE, "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, "obj=%p Connecting %s\n", obj, obj->parent->name); } res = SQLConnect(obj->con, @@ -496,12 +572,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, "obj=%p Connected to %s [%s]\n", + obj, obj->parent->name, obj->parent->dsn); obj->up = 1; } @@ -516,7 +594,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 +617,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 +645,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 +678,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: res/res_config_odbc.c =================================================================== --- res/res_config_odbc.c (revision 34575) +++ res/res_config_odbc.c (working copy) @@ -454,27 +454,16 @@ SQLINTEGER err; }; -static SQLHSTMT config_odbc_prepare(struct odbc_obj *obj, void *data) +static int config_odbc_prepare(struct odbc_obj *obj, SQLHSTMT sth, void *data) { struct config_odbc_obj *q = data; - SQLHSTMT sth; int res; - 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); - return NULL; + res = odbc_just_prepare(obj, sth, q->sql); + if (res != PREPARE_OK) { + return res; } - 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); - SQLFreeHandle(SQL_HANDLE_STMT, sth); - return NULL; - } - SQLBindCol(sth, 1, SQL_C_ULONG, &q->id, sizeof(q->id), &q->err); SQLBindCol(sth, 2, SQL_C_ULONG, &q->cat_metric, sizeof(q->cat_metric), &q->err); SQLBindCol(sth, 3, SQL_C_ULONG, &q->var_metric, sizeof(q->var_metric), &q->err); @@ -484,7 +473,7 @@ SQLBindCol(sth, 7, SQL_C_CHAR, q->var_name, sizeof(q->var_name), &q->err); SQLBindCol(sth, 8, SQL_C_CHAR, q->var_val, sizeof(q->var_val), &q->err); - return sth; + return PREPARE_OK; } static struct ast_config *config_odbc(const char *database, const char *table, const char *file, struct ast_config *cfg) Index: include/asterisk/res_odbc.h =================================================================== --- include/asterisk/res_odbc.h (revision 34575) +++ include/asterisk/res_odbc.h (working copy) @@ -85,12 +85,38 @@ */ int odbc_sanity_check(struct odbc_obj *obj); +/* + * Return codes for prepare statement callback + */ +#define PREPARE_OK 0 +#define PREPARE_ODBC_ERROR 1 +#define PREPARE_ERROR 2 + /*! \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. * \param data A parameter to be passed to the prepare_cb parameter function, indicating which statement handle is to be prepared. * \return Returns a statement handle or NULL on error. */ -SQLHSTMT odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT (*prepare_cb)(struct odbc_obj *obj, void *data), void *data); +SQLHSTMT odbc_prepare_and_execute(struct odbc_obj *obj, int (*prepare_cb)(struct odbc_obj *obj, SQLHSTMT stmt, void *data), void *data); + +/*! \brief simple callback for prepare_and_execute which receive an SQL as data and prepare it + * \param obj The ODBC object + * \param stmt the statement to be prepared + * \param data the SQL to be prepared + * \return Returns PREPARE_* codes + */ +int odbc_just_prepare(struct odbc_obj *obj, SQLHSTMT stmt, 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); + #endif /* _ASTERISK_RES_ODBC_H */ Index: apps/app_voicemail.c =================================================================== --- apps/app_voicemail.c (revision 34575) +++ apps/app_voicemail.c (working copy) @@ -852,6 +852,56 @@ #ifdef ODBC_STORAGE + +struct sql_args_obj { + char* sql; + int count; + SQLUINTEGER columnSize[20]; + SQLSMALLINT valueType[20]; + SQLSMALLINT parameterType[20]; + SQLPOINTER buffer[20]; + SQLINTEGER bufferLen[20]; + SQLINTEGER* strlen_or_ind[20]; +}; + +#define ODBC_PARAM_INIT(obj, sql) \ + obj.sql = sql; \ + obj.count = 0; + +#define ODBC_PARAM(obj, _valueType, _parameterType, _columnSize, _buffer, _bufferLen, _strlen_or_ind) \ + obj.valueType[obj.count] = _valueType; \ + obj.parameterType[obj.count] = _parameterType; \ + obj.columnSize[obj.count] = _columnSize; \ + obj.buffer[obj.count] = (void *)_buffer; \ + obj.bufferLen[obj.count] = _bufferLen; \ + obj.strlen_or_ind[obj.count] = _strlen_or_ind; \ + obj.count++; + +#define ODBC_PARAM_STRING(obj, param) \ + ODBC_PARAM(obj, SQL_C_CHAR, SQL_CHAR, strlen(param), param, 0, NULL) + +static int prepare_with_args(struct odbc_obj *obj, SQLHSTMT stmt, void *data) +{ + struct sql_args_obj *args = data; + int i, res; + + ast_log(LOG_NOTICE, "%d %s\n", args->count, args->sql); + res = odbc_just_prepare(obj, stmt, args->sql); + if (res != PREPARE_OK) { + return res; + } + for (i = 0; i < args->count; i++) { + ast_log(LOG_NOTICE, "%d - %s\n", i, (char *)args->buffer[i]); + SQLBindParameter(stmt, i+1, SQL_PARAM_INPUT, + args->valueType[i], args->parameterType[i], + args->columnSize[i], 0, + args->buffer[i], args->bufferLen, + args->strlen_or_ind[i]); + } + + return PREPARE_OK; +} + static int retrieve_file(char *dir, int msgnum) { int x = 0; @@ -875,6 +925,7 @@ char fn[256]; char full_fn[256]; char msgnums[80]; + struct sql_args_obj args; struct odbc_obj *obj; obj = odbc_request_obj(odbc_database, 0); @@ -893,37 +944,26 @@ 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); + + ODBC_PARAM_INIT(args, sql); + ODBC_PARAM_STRING(args, dir); + ODBC_PARAM_STRING(args, msgnums); + + stmt = odbc_prepare_and_execute(obj, prepare_with_args, &args); + 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); - 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); - 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 +977,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 +990,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 +1019,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 +1028,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; @@ -1029,42 +1075,30 @@ SQLHSTMT stmt; char sql[256]; char rowdata[20]; + struct sql_args_obj args; 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); + ODBC_PARAM_INIT(args, sql); + ODBC_PARAM_STRING(args, dir); + + stmt = odbc_prepare_and_execute(obj, prepare_with_args, &args); + 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); - 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; @@ -1087,44 +1121,32 @@ char sql[256]; char rowdata[20]; char msgnums[20]; + struct sql_args_obj args; struct odbc_obj *obj; 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); + ODBC_PARAM_INIT(args, sql); + ODBC_PARAM_STRING(args, dir); + ODBC_PARAM_STRING(args, msgnums); + + stmt = odbc_prepare_and_execute(obj, prepare_with_args, &args); + 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); - 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); - 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; @@ -1146,38 +1168,25 @@ static void delete_file(char *sdir, int smsg) { - int res; SQLHSTMT stmt; char sql[256]; char msgnums[20]; + struct sql_args_obj args; struct odbc_obj *obj; 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); + ODBC_PARAM_INIT(args, sql); + ODBC_PARAM_STRING(args, sdir); + ODBC_PARAM_STRING(args, msgnums); + + stmt = odbc_prepare_and_execute(obj, prepare_with_args, &args); + 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); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - odbc_release_obj(obj); - goto yuck; - } SQLFreeHandle (SQL_HANDLE_STMT, stmt); odbc_release_obj(obj); } else @@ -1188,51 +1197,35 @@ static void copy_file(char *sdir, int smsg, char *ddir, int dmsg, char *dmailboxuser, char *dmailboxcontext) { - int res; SQLHSTMT stmt; char sql[512]; char msgnums[20]; char msgnumd[20]; struct odbc_obj *obj; + struct sql_args_obj args; delete_file(ddir, dmsg); obj = odbc_request_obj(odbc_database, 0); 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); - odbc_release_obj(obj); - goto yuck; - } - SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(ddir), 0, (void *)ddir, 0, NULL); - SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnumd), 0, (void *)msgnumd, 0, NULL); + ODBC_PARAM_INIT(args, sql); + ODBC_PARAM_STRING(args, ddir); + ODBC_PARAM_STRING(args, msgnumd); #ifdef EXTENDED_ODBC_STORAGE - SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dmailboxuser), 0, (void *)dmailboxuser, 0, NULL); - SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dmailboxcontext), 0, (void *)dmailboxcontext, 0, NULL); - SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(sdir), 0, (void *)sdir, 0, NULL); - SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL); -#else - SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(sdir), 0, (void *)sdir, 0, NULL); - SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL); + ODBC_PARAM_STRING(args, dmailboxuser); + ODBC_PARAM_STRING(args, dmailboxcontext); #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); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); + ODBC_PARAM_STRING(args, sdir); + ODBC_PARAM_STRING(args, msgnums); + + stmt = odbc_prepare_and_execute(obj, prepare_with_args, &args); + if (stmt == SQL_NULL_HANDLE) { odbc_release_obj(obj); goto yuck; } @@ -1247,7 +1240,6 @@ static int store_file(char *dir, char *mailboxuser, char *mailboxcontext, int msgnum) { int x = 0; - int res; int fd = -1; void *fdm=NULL; size_t fdlen = -1; @@ -1263,6 +1255,7 @@ char *category = ""; struct ast_config *cfg=NULL; struct odbc_obj *obj; + struct sql_args_obj args; delete_file(dir, msgnum); obj = odbc_request_obj(odbc_database, 0); @@ -1310,12 +1303,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,35 +1315,27 @@ #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); - odbc_release_obj(obj); - goto yuck; - } + + len = fdlen; /* SQL_LEN_DATA_AT_EXEC(fdlen); */ - SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dir), 0, (void *)dir, 0, NULL); - SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL); - SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, fdlen, 0, (void *)fdm, fdlen, &len); - SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(context), 0, (void *)context, 0, NULL); - SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(macrocontext), 0, (void *)macrocontext, 0, NULL); - SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(callerid), 0, (void *)callerid, 0, NULL); - SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(origtime), 0, (void *)origtime, 0, NULL); - SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(duration), 0, (void *)duration, 0, NULL); + ODBC_PARAM_INIT(args, sql); + ODBC_PARAM_STRING(args, dir); + ODBC_PARAM_STRING(args, msgnums); + ODBC_PARAM(args, SQL_C_BINARY, SQL_LONGVARBINARY, fdlen, (void *)fdm, fdlen, &len); + ODBC_PARAM_STRING(args, context); + ODBC_PARAM_STRING(args, macrocontext); + ODBC_PARAM_STRING(args, callerid); + ODBC_PARAM_STRING(args, origtime); + ODBC_PARAM_STRING(args, duration); #ifdef EXTENDED_ODBC_STORAGE - SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(mailboxuser), 0, (void *)mailboxuser, 0, NULL); - SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(mailboxcontext), 0, (void *)mailboxcontext, 0, NULL); - if (!ast_strlen_zero(category)) - SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(category), 0, (void *)category, 0, NULL); -#else - if (!ast_strlen_zero(category)) - SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(category), 0, (void *)category, 0, NULL); + ODBC_PARAM_STRING(args, mailboxuser); + ODBC_PARAM_STRING(args, mailboxcontext); #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); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); + if (!ast_strlen_zero(category)) + ODBC_PARAM_STRING(args, category); + + stmt = odbc_prepare_and_execute(obj, prepare_with_args, &args); + if (stmt == SQL_NULL_HANDLE) { odbc_release_obj(obj); goto yuck; } @@ -1376,51 +1355,36 @@ static void rename_file(char *sdir, int smsg, char *mailboxuser, char *mailboxcontext, char *ddir, int dmsg) { - int res; SQLHSTMT stmt; char sql[256]; char msgnums[20]; char msgnumd[20]; struct odbc_obj *obj; + struct sql_args_obj args; delete_file(ddir, dmsg); obj = odbc_request_obj(odbc_database, 0); 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); - odbc_release_obj(obj); - goto yuck; - } - SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(ddir), 0, (void *)ddir, 0, NULL); - SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnumd), 0, (void *)msgnumd, 0, NULL); + + ODBC_PARAM_INIT(args, sql); + ODBC_PARAM_STRING(args, ddir); + ODBC_PARAM_STRING(args, msgnumd); #ifdef EXTENDED_ODBC_STORAGE - SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(mailboxuser), 0, (void *)mailboxuser, 0, NULL); - SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(mailboxcontext), 0, (void *)mailboxcontext, 0, NULL); - SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(sdir), 0, (void *)sdir, 0, NULL); - SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL); -#else - SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(sdir), 0, (void *)sdir, 0, NULL); - SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL); + ODBC_PARAM_STRING(args, mailboxuser); + ODBC_PARAM_STRING(args, mailboxcontext); #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); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); + ODBC_PARAM_STRING(args, sdir); + ODBC_PARAM_STRING(args, msgnums); + + stmt = odbc_prepare_and_execute(obj, prepare_with_args, &args); + if (stmt == SQL_NULL_HANDLE) { odbc_release_obj(obj); goto yuck; } @@ -2060,37 +2024,22 @@ 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_and_execute(obj, odbc_just_prepare, 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); - 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 +2047,22 @@ *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_and_execute(obj, odbc_just_prepare, 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); - 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 +2094,20 @@ 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_and_execute(obj, odbc_just_prepare, 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); - 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; }