|  |  |  | @ -47,6 +47,9 @@ ASTERISK_REGISTER_FILE() | 
			
		
	
		
			
				
					|  |  |  |  | #include "asterisk/utils.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "asterisk/stringfields.h" | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /*! Initial SQL query buffer size to allocate. */ | 
			
		
	
		
			
				
					|  |  |  |  | #define SQL_BUF_SIZE	1024 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | AST_THREADSTORAGE(sql_buf); | 
			
		
	
		
			
				
					|  |  |  |  | AST_THREADSTORAGE(rowdata_buf); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -114,7 +117,7 @@ static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	res = SQLPrepare(stmt, (unsigned char *)cps->sql, SQL_NTS); | 
			
		
	
		
			
				
					|  |  |  |  | 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", cps->sql); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL Prepare failed! [%s]\n", cps->sql); | 
			
		
	
		
			
				
					|  |  |  |  | 		SQLFreeHandle (SQL_HANDLE_STMT, stmt); | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
	
		
			
				
					|  |  |  | @ -161,13 +164,13 @@ static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data) | 
			
		
	
		
			
				
					|  |  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  |  * \retval var on success | 
			
		
	
		
			
				
					|  |  |  |  |  * \retval NULL on failure | 
			
		
	
		
			
				
					|  |  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | static struct ast_variable *realtime_odbc(const char *database, const char *table, const struct ast_variable *fields) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct odbc_obj *obj; | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLHSTMT stmt; | 
			
		
	
		
			
				
					|  |  |  |  | 	char sql[1024]; | 
			
		
	
		
			
				
					|  |  |  |  | 	char coltitle[256]; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE); | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_str *rowdata = ast_str_thread_get(&rowdata_buf, 128); | 
			
		
	
		
			
				
					|  |  |  |  | 	char *op; | 
			
		
	
		
			
				
					|  |  |  |  | 	const struct ast_variable *field = fields; | 
			
		
	
	
		
			
				
					|  |  |  | @ -183,29 +186,30 @@ static struct ast_variable *realtime_odbc(const char *database, const char *tabl | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLSMALLINT decimaldigits; | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLSMALLINT nullable; | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLLEN indicator; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct custom_prepare_struct cps = { .sql = sql, .fields = fields, }; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct custom_prepare_struct cps = { .fields = fields, }; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!table || !field) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!table || !field || !sql || !rowdata) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	obj = ast_odbc_request_obj2(database, connected_flag); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!obj) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_ERROR, "No database handle available with the name of '%s' (check res_odbc.conf)\n", database); | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	op = !strchr(field->name, ' ') ? " =" : ""; | 
			
		
	
		
			
				
					|  |  |  |  | 	snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, field->name, op, | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s ?%s", table, field->name, op, | 
			
		
	
		
			
				
					|  |  |  |  | 		strcasestr(field->name, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\\\'" : ""); | 
			
		
	
		
			
				
					|  |  |  |  | 	while ((field = field->next)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		op = !strchr(field->name, ' ') ? " =" : ""; | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", field->name, op, | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_str_append(&sql, 0, " AND %s%s ?%s", field->name, op, | 
			
		
	
		
			
				
					|  |  |  |  | 			strcasestr(field->name, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\\\'" : ""); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	cps.sql = ast_str_buffer(sql); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (ast_string_field_init(&cps, 256)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_odbc_release_obj(obj); | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
	
		
			
				
					|  |  |  | @ -220,7 +224,7 @@ static struct ast_variable *realtime_odbc(const char *database, const char *tabl | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	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); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL Column Count error! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 		SQLFreeHandle (SQL_HANDLE_STMT, stmt); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_odbc_release_obj(obj); | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
	
		
			
				
					|  |  |  | @ -233,7 +237,7 @@ static struct ast_variable *realtime_odbc(const char *database, const char *tabl | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL Fetch error! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 		SQLFreeHandle (SQL_HANDLE_STMT, stmt); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_odbc_release_obj(obj); | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
	
		
			
				
					|  |  |  | @ -244,7 +248,7 @@ static struct ast_variable *realtime_odbc(const char *database, const char *tabl | 
			
		
	
		
			
				
					|  |  |  |  | 		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); | 
			
		
	
		
			
				
					|  |  |  |  | 			ast_log(LOG_WARNING, "SQL Describe Column error! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 			if (var) | 
			
		
	
		
			
				
					|  |  |  |  | 				ast_variables_destroy(var); | 
			
		
	
		
			
				
					|  |  |  |  | 			ast_odbc_release_obj(obj); | 
			
		
	
	
		
			
				
					|  |  |  | @ -273,7 +277,7 @@ static struct ast_variable *realtime_odbc(const char *database, const char *tabl | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { | 
			
		
	
		
			
				
					|  |  |  |  | 			ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); | 
			
		
	
		
			
				
					|  |  |  |  | 			ast_log(LOG_WARNING, "SQL Get Data error! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 			if (var) | 
			
		
	
		
			
				
					|  |  |  |  | 				ast_variables_destroy(var); | 
			
		
	
		
			
				
					|  |  |  |  | 			ast_odbc_release_obj(obj); | 
			
		
	
	
		
			
				
					|  |  |  | @ -317,13 +321,13 @@ static struct ast_variable *realtime_odbc(const char *database, const char *tabl | 
			
		
	
		
			
				
					|  |  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  |  * \retval var on success | 
			
		
	
		
			
				
					|  |  |  |  |  * \retval NULL on failure | 
			
		
	
		
			
				
					|  |  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | static struct ast_config *realtime_multi_odbc(const char *database, const char *table, const struct ast_variable *fields) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct odbc_obj *obj; | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLHSTMT stmt; | 
			
		
	
		
			
				
					|  |  |  |  | 	char sql[1024]; | 
			
		
	
		
			
				
					|  |  |  |  | 	char coltitle[256]; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE); | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_str *rowdata = ast_str_thread_get(&rowdata_buf, 128); | 
			
		
	
		
			
				
					|  |  |  |  | 	const char *initfield; | 
			
		
	
		
			
				
					|  |  |  |  | 	char *op; | 
			
		
	
	
		
			
				
					|  |  |  | @ -343,9 +347,9 @@ static struct ast_config *realtime_multi_odbc(const char *database, const char * | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLSMALLINT decimaldigits; | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLSMALLINT nullable; | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLLEN indicator; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct custom_prepare_struct cps = { .sql = sql, .fields = fields, }; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct custom_prepare_struct cps = { .fields = fields, }; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!table || !field) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!table || !field || !sql || !rowdata) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -360,15 +364,16 @@ static struct ast_config *realtime_multi_odbc(const char *database, const char * | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	op = !strchr(field->name, ' ') ? " =" : ""; | 
			
		
	
		
			
				
					|  |  |  |  | 	snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, field->name, op, | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s ?%s", table, field->name, op, | 
			
		
	
		
			
				
					|  |  |  |  | 		strcasestr(field->name, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\\\'" : ""); | 
			
		
	
		
			
				
					|  |  |  |  | 	while ((field = field->next)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		op = !strchr(field->name, ' ') ? " =" : ""; | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", field->name, op, | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_str_append(&sql, 0, " AND %s%s ?%s", field->name, op, | 
			
		
	
		
			
				
					|  |  |  |  | 			strcasestr(field->name, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\\\'" : ""); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_str_append(&sql, 0, " ORDER BY %s", initfield); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield); | 
			
		
	
		
			
				
					|  |  |  |  | 	cps.sql = ast_str_buffer(sql); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (ast_string_field_init(&cps, 256)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_odbc_release_obj(obj); | 
			
		
	
	
		
			
				
					|  |  |  | @ -384,7 +389,7 @@ static struct ast_config *realtime_multi_odbc(const char *database, const char * | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	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); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL Column Count error! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 		SQLFreeHandle(SQL_HANDLE_STMT, stmt); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_odbc_release_obj(obj); | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
	
		
			
				
					|  |  |  | @ -401,7 +406,7 @@ static struct ast_config *realtime_multi_odbc(const char *database, const char * | 
			
		
	
		
			
				
					|  |  |  |  | 	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); | 
			
		
	
		
			
				
					|  |  |  |  | 			ast_log(LOG_WARNING, "SQL Fetch error! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 			continue; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		cat = ast_category_new("","",99999); | 
			
		
	
	
		
			
				
					|  |  |  | @ -415,7 +420,7 @@ static struct ast_config *realtime_multi_odbc(const char *database, const char * | 
			
		
	
		
			
				
					|  |  |  |  | 			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); | 
			
		
	
		
			
				
					|  |  |  |  | 				ast_log(LOG_WARNING, "SQL Describe Column error! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 				ast_category_destroy(cat); | 
			
		
	
		
			
				
					|  |  |  |  | 				goto next_sql_fetch; | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
	
		
			
				
					|  |  |  | @ -440,7 +445,7 @@ static struct ast_config *realtime_multi_odbc(const char *database, const char * | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { | 
			
		
	
		
			
				
					|  |  |  |  | 				ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); | 
			
		
	
		
			
				
					|  |  |  |  | 				ast_log(LOG_WARNING, "SQL Get Data error! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 				ast_category_destroy(cat); | 
			
		
	
		
			
				
					|  |  |  |  | 				goto next_sql_fetch; | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
	
		
			
				
					|  |  |  | @ -482,21 +487,21 @@ next_sql_fetch:; | 
			
		
	
		
			
				
					|  |  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  |  * \retval number of rows affected | 
			
		
	
		
			
				
					|  |  |  |  |  * \retval -1 on failure | 
			
		
	
		
			
				
					|  |  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | static int update_odbc(const char *database, const char *table, const char *keyfield, const char *lookup, const struct ast_variable *fields) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct odbc_obj *obj; | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLHSTMT stmt; | 
			
		
	
		
			
				
					|  |  |  |  | 	char sql[256]; | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLLEN rowcount=0; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE); | 
			
		
	
		
			
				
					|  |  |  |  | 	const struct ast_variable *field = fields; | 
			
		
	
		
			
				
					|  |  |  |  | 	int res, count = 0, paramcount = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct custom_prepare_struct cps = { .sql = sql, .extra = lookup, .fields = fields, }; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct custom_prepare_struct cps = { .extra = lookup, .fields = fields, }; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct odbc_cache_tables *tableptr; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct odbc_cache_columns *column = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!table || !field || !keyfield) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!table || !field || !keyfield || !sql) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -510,19 +515,19 @@ static int update_odbc(const char *database, const char *table, const char *keyf | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "Key field '%s' does not exist in table '%s@%s'.  Update will fail\n", keyfield, table, database); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	snprintf(sql, sizeof(sql), "UPDATE %s SET ", table); | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_str_set(&sql, 0, "UPDATE %s SET ", table); | 
			
		
	
		
			
				
					|  |  |  |  | 	while (field) { | 
			
		
	
		
			
				
					|  |  |  |  | 		if ((tableptr && (column = ast_odbc_find_column(tableptr, field->name))) || count >= 64) { | 
			
		
	
		
			
				
					|  |  |  |  | 			if (paramcount++) { | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", "); | 
			
		
	
		
			
				
					|  |  |  |  | 				ast_str_append(&sql, 0, ", "); | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 			/* NULL test for non-text columns */ | 
			
		
	
		
			
				
					|  |  |  |  | 			if (count < 64 && ast_strlen_zero(field->value) && column->nullable && !is_text(column)) { | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=NULL", field->name); | 
			
		
	
		
			
				
					|  |  |  |  | 				ast_str_append(&sql, 0, "%s=NULL", field->name); | 
			
		
	
		
			
				
					|  |  |  |  | 				cps.skip |= (1LL << count); | 
			
		
	
		
			
				
					|  |  |  |  | 			} else { | 
			
		
	
		
			
				
					|  |  |  |  | 				/* Value is not an empty string, or column is of text type, or we couldn't fit any more into cps.skip (count >= 64 ?!). */ | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=?", field->name); | 
			
		
	
		
			
				
					|  |  |  |  | 				ast_str_append(&sql, 0, "%s=?", field->name); | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 		} else { /* the column does not exist in the table */ | 
			
		
	
		
			
				
					|  |  |  |  | 			cps.skip |= (1LL << count); | 
			
		
	
	
		
			
				
					|  |  |  | @ -530,9 +535,11 @@ static int update_odbc(const char *database, const char *table, const char *keyf | 
			
		
	
		
			
				
					|  |  |  |  | 		++count; | 
			
		
	
		
			
				
					|  |  |  |  | 		field = field->next; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s=?", keyfield); | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_str_append(&sql, 0, " WHERE %s=?", keyfield); | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_odbc_release_table(tableptr); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	cps.sql = ast_str_buffer(sql); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (ast_string_field_init(&cps, 256)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_odbc_release_obj(obj); | 
			
		
	
		
			
				
					|  |  |  |  | 		return -1; | 
			
		
	
	
		
			
				
					|  |  |  | @ -550,7 +557,7 @@ static int update_odbc(const char *database, const char *table, const char *keyf | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_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); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL Row Count error! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 		return -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -573,17 +580,15 @@ static SQLHSTMT update2_prepare(struct odbc_obj *obj, void *data) | 
			
		
	
		
			
				
					|  |  |  |  | 	int res, x = 1, first = 1; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct update2_prepare_struct *ups = data; | 
			
		
	
		
			
				
					|  |  |  |  | 	const struct ast_variable *field; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_str *sql = ast_str_thread_get(&sql_buf, 16); | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE); | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLHSTMT stmt; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct odbc_cache_tables *tableptr = ast_odbc_find_table(ups->database, ups->table); | 
			
		
	
		
			
				
					|  |  |  |  | 	struct odbc_cache_tables *tableptr; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!sql) { | 
			
		
	
		
			
				
					|  |  |  |  | 		if (tableptr) { | 
			
		
	
		
			
				
					|  |  |  |  | 			ast_odbc_release_table(tableptr); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	tableptr = ast_odbc_find_table(ups->database, ups->table); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!tableptr) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_ERROR, "Could not retrieve metadata for table '%s@%s'.  Update will fail!\n", ups->table, ups->database); | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
	
		
			
				
					|  |  |  | @ -628,7 +633,7 @@ static SQLHSTMT update2_prepare(struct odbc_obj *obj, void *data) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	res = SQLPrepare(stmt, (unsigned char *)ast_str_buffer(sql), SQL_NTS); | 
			
		
	
		
			
				
					|  |  |  |  | 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL Prepare failed! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 		SQLFreeHandle(SQL_HANDLE_STMT, stmt); | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
	
		
			
				
					|  |  |  | @ -674,8 +679,9 @@ static int update2_odbc(const char *database, const char *table, const struct as | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		/* Since only a single thread can access this memory, we can retrieve what would otherwise be lost. */ | 
			
		
	
		
			
				
					|  |  |  |  | 		sql = ast_str_thread_get(&sql_buf, 16); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 		sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_assert(sql != NULL); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL Row Count error! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 		return -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -698,36 +704,47 @@ static int update2_odbc(const char *database, const char *table, const struct as | 
			
		
	
		
			
				
					|  |  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  |  * \retval number of rows affected | 
			
		
	
		
			
				
					|  |  |  |  |  * \retval -1 on failure | 
			
		
	
		
			
				
					|  |  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | static int store_odbc(const char *database, const char *table, const struct ast_variable *fields) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct odbc_obj *obj; | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLHSTMT stmt; | 
			
		
	
		
			
				
					|  |  |  |  | 	char sql[256]; | 
			
		
	
		
			
				
					|  |  |  |  | 	char keys[256]; | 
			
		
	
		
			
				
					|  |  |  |  | 	char vals[256]; | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLLEN rowcount=0; | 
			
		
	
		
			
				
					|  |  |  |  | 	const struct ast_variable *field = fields; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_str *keys; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_str *vals; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE); | 
			
		
	
		
			
				
					|  |  |  |  | 	int res; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct custom_prepare_struct cps = { .sql = sql, .extra = NULL, .fields = fields, }; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct custom_prepare_struct cps = { .fields = fields, }; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!table || !field) { | 
			
		
	
		
			
				
					|  |  |  |  | 	keys = ast_str_create(SQL_BUF_SIZE / 2); | 
			
		
	
		
			
				
					|  |  |  |  | 	vals = ast_str_create(SQL_BUF_SIZE / 4); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!table || !field || !keys || !vals || !sql) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_free(vals); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_free(keys); | 
			
		
	
		
			
				
					|  |  |  |  | 		return -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	obj = ast_odbc_request_obj2(database, connected_flag); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!obj) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_free(vals); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_free(keys); | 
			
		
	
		
			
				
					|  |  |  |  | 		return -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	snprintf(keys, sizeof(keys), "%s", field->name); | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_copy_string(vals, "?", sizeof(vals)); | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_str_set(&keys, 0, "%s", field->name); | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_str_set(&vals, 0, "?"); | 
			
		
	
		
			
				
					|  |  |  |  | 	while ((field = field->next)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(keys + strlen(keys), sizeof(keys) - strlen(keys), ", %s", field->name); | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(vals + strlen(vals), sizeof(vals) - strlen(vals), ", ?"); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_str_append(&keys, 0, ", %s", field->name); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_str_append(&vals, 0, ", ?"); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	snprintf(sql, sizeof(sql), "INSERT INTO %s (%s) VALUES (%s)", table, keys, vals); | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_str_set(&sql, 0, "INSERT INTO %s (%s) VALUES (%s)", | 
			
		
	
		
			
				
					|  |  |  |  | 		table, ast_str_buffer(keys), ast_str_buffer(vals)); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_free(vals); | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_free(keys); | 
			
		
	
		
			
				
					|  |  |  |  | 	cps.sql = ast_str_buffer(sql); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (ast_string_field_init(&cps, 256)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_odbc_release_obj(obj); | 
			
		
	
	
		
			
				
					|  |  |  | @ -746,7 +763,7 @@ static int store_odbc(const char *database, const char *table, const struct ast_ | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_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); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL Row Count error! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 		return -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -770,19 +787,19 @@ static int store_odbc(const char *database, const char *table, const struct ast_ | 
			
		
	
		
			
				
					|  |  |  |  |  * | 
			
		
	
		
			
				
					|  |  |  |  |  * \retval number of rows affected | 
			
		
	
		
			
				
					|  |  |  |  |  * \retval -1 on failure | 
			
		
	
		
			
				
					|  |  |  |  | */ | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | static int destroy_odbc(const char *database, const char *table, const char *keyfield, const char *lookup, const struct ast_variable *fields) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	struct odbc_obj *obj; | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLHSTMT stmt; | 
			
		
	
		
			
				
					|  |  |  |  | 	char sql[256]; | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLLEN rowcount=0; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE); | 
			
		
	
		
			
				
					|  |  |  |  | 	const struct ast_variable *field; | 
			
		
	
		
			
				
					|  |  |  |  | 	int res; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct custom_prepare_struct cps = { .sql = sql, .extra = lookup, .fields = fields, }; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct custom_prepare_struct cps = { .extra = lookup, .fields = fields, }; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_flags connected_flag = { RES_ODBC_CONNECTED }; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!table) { | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!table || !sql) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -791,12 +808,13 @@ static int destroy_odbc(const char *database, const char *table, const char *key | 
			
		
	
		
			
				
					|  |  |  |  | 		return -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE ", table); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_str_set(&sql, 0, "DELETE FROM %s WHERE ", table); | 
			
		
	
		
			
				
					|  |  |  |  | 	for (field = fields; field; field = field->next) { | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=? AND ", field->name); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_str_append(&sql, 0, "%s=? AND ", field->name); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=?", keyfield); | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_str_append(&sql, 0, "%s=?", keyfield); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	cps.sql = ast_str_buffer(sql); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (ast_string_field_init(&cps, 256)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_odbc_release_obj(obj); | 
			
		
	
	
		
			
				
					|  |  |  | @ -815,7 +833,7 @@ static int destroy_odbc(const char *database, const char *table, const char *key | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_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); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL Row Count error! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 		return -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -893,9 +911,7 @@ static struct ast_config *config_odbc(const char *database, const char *table, c | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_category *cur_cat; | 
			
		
	
		
			
				
					|  |  |  |  | 	int res = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 	struct odbc_obj *obj; | 
			
		
	
		
			
				
					|  |  |  |  | 	char sqlbuf[1024] = ""; | 
			
		
	
		
			
				
					|  |  |  |  | 	char *sql = sqlbuf; | 
			
		
	
		
			
				
					|  |  |  |  | 	size_t sqlleft = sizeof(sqlbuf); | 
			
		
	
		
			
				
					|  |  |  |  | 	struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE); | 
			
		
	
		
			
				
					|  |  |  |  | 	unsigned int last_cat_metric = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLSMALLINT rowcount = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLHSTMT stmt; | 
			
		
	
	
		
			
				
					|  |  |  | @ -906,21 +922,21 @@ static struct ast_config *config_odbc(const char *database, const char *table, c | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	memset(&q, 0, sizeof(q)); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!file || !strcmp (file, "res_config_odbc.conf")) | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!file || !strcmp (file, "res_config_odbc.conf") || !sql) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL;		/* cant configure myself with myself ! */ | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	obj = ast_odbc_request_obj2(database, connected_flag); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!obj) | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	q.sql = sqlbuf; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_build_string(&sql, &sqlleft, "SELECT MAX(LENGTH(var_val)) FROM %s WHERE filename='%s'", table, file); | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_str_set(&sql, 0, "SELECT MAX(LENGTH(var_val)) FROM %s WHERE filename='%s'", | 
			
		
	
		
			
				
					|  |  |  |  | 		table, file); | 
			
		
	
		
			
				
					|  |  |  |  | 	q.sql = ast_str_buffer(sql); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	stmt = ast_odbc_prepare_and_execute(obj, length_determination_odbc_prepare, &q); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!stmt) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL select error!\n[%s]\n\n", sql); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL select error! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_odbc_release_obj(obj); | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
	
		
			
				
					|  |  |  | @ -928,7 +944,7 @@ static struct ast_config *config_odbc(const char *database, const char *table, c | 
			
		
	
		
			
				
					|  |  |  |  | 	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); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL NumResultCols error! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 		SQLFreeHandle(SQL_HANDLE_STMT, stmt); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_odbc_release_obj(obj); | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
	
		
			
				
					|  |  |  | @ -950,12 +966,11 @@ static struct ast_config *config_odbc(const char *database, const char *table, c | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	/* Reset stuff to a fresh state for the actual query which will retrieve all configuration */ | 
			
		
	
		
			
				
					|  |  |  |  | 	SQLFreeHandle(SQL_HANDLE_STMT, stmt); | 
			
		
	
		
			
				
					|  |  |  |  | 	sql = sqlbuf; | 
			
		
	
		
			
				
					|  |  |  |  | 	sqlleft = sizeof(sqlbuf); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_build_string(&sql, &sqlleft, "SELECT cat_metric, category, var_name, var_val FROM %s ", table); | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_build_string(&sql, &sqlleft, "WHERE filename='%s' AND commented=0 ", file); | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_build_string(&sql, &sqlleft, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name "); | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_str_set(&sql, 0, "SELECT cat_metric, category, var_name, var_val FROM %s ", table); | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_str_append(&sql, 0, "WHERE filename='%s' AND commented=0 ", file); | 
			
		
	
		
			
				
					|  |  |  |  | 	ast_str_append(&sql, 0, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name "); | 
			
		
	
		
			
				
					|  |  |  |  | 	q.sql = ast_str_buffer(sql); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	q.var_val_size += 1; | 
			
		
	
		
			
				
					|  |  |  |  | 	q.var_val = ast_malloc(q.var_val_size); | 
			
		
	
	
		
			
				
					|  |  |  | @ -966,9 +981,8 @@ static struct ast_config *config_odbc(const char *database, const char *table, c | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	stmt = ast_odbc_prepare_and_execute(obj, config_odbc_prepare, &q); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!stmt) { | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL select error!\n[%s]\n\n", sql); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL select error! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_odbc_release_obj(obj); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_free(q.var_val); | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
	
		
			
				
					|  |  |  | @ -977,7 +991,7 @@ static struct ast_config *config_odbc(const char *database, const char *table, c | 
			
		
	
		
			
				
					|  |  |  |  | 	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); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_log(LOG_WARNING, "SQL NumResultCols error! [%s]\n", ast_str_buffer(sql)); | 
			
		
	
		
			
				
					|  |  |  |  | 		SQLFreeHandle(SQL_HANDLE_STMT, stmt); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_odbc_release_obj(obj); | 
			
		
	
		
			
				
					|  |  |  |  | 		ast_free(q.var_val); | 
			
		
	
	
		
			
				
					|  |  |  | 
 |