mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-11-04 05:15:22 +00:00 
			
		
		
		
	res_config_odbc: Prevent Realtime fallback on record-not-found (SQL_NO_DATA)
This patch fixes an issue in the ODBC Realtime engine where Asterisk incorrectly falls back to the next configured backend when the current one returns SQL_NO_DATA (i.e., no record found). This is a logical error and performance risk in multi-backend configurations. Solution: Introduced CONFIG_RT_NOT_FOUND ((void *)-1) as a special return marker. ODBC Realtime backend now return CONFIG_RT_NOT_FOUND when no data is found. Core engine stops iterating on this marker, avoiding unnecessary fallback. Notes: Other Realtime backends (PostgreSQL, LDAP, etc.) can be updated similarly. This patch only covers ODBC. Fixes: #1305
This commit is contained in:
		
				
					committed by
					
						
						github-actions[bot]
					
				
			
			
				
	
			
			
			
						parent
						
							9820a62263
						
					
				
				
					commit
					3e178dcfd6
				
			@@ -126,6 +126,12 @@ typedef int realtime_require(const char *database, const char *table, va_list ap
 | 
			
		||||
 */
 | 
			
		||||
typedef int realtime_unload(const char *database, const char *table);
 | 
			
		||||
 | 
			
		||||
/*! Special return value indicating a successful query that returned no data.
 | 
			
		||||
 * Used by realtime backends to signal "not found" vs an actual backend failure.
 | 
			
		||||
 * This allows the core engine to differentiate and avoid unnecessary failover.
 | 
			
		||||
 */
 | 
			
		||||
#define CONFIG_RT_NOT_FOUND	(void *)-1
 | 
			
		||||
 | 
			
		||||
/*! \brief Configuration engine structure, used to define realtime drivers */
 | 
			
		||||
struct ast_config_engine {
 | 
			
		||||
	char *name;
 | 
			
		||||
 
 | 
			
		||||
@@ -3660,8 +3660,20 @@ struct ast_variable *ast_load_realtime_all_fields(const char *family, const stru
 | 
			
		||||
 | 
			
		||||
	for (i = 1; ; i++) {
 | 
			
		||||
		if ((eng = find_engine(family, i, db, sizeof(db), table, sizeof(table)))) {
 | 
			
		||||
			if (eng->realtime_func && (res = eng->realtime_func(db, table, fields))) {
 | 
			
		||||
				return res;
 | 
			
		||||
			if (eng->realtime_func) {
 | 
			
		||||
				res = eng->realtime_func(db, table, fields);
 | 
			
		||||
 | 
			
		||||
				/* If a backend returns CONFIG_RT_NOT_FOUND, stop iteration and return NULL,
 | 
			
		||||
				 * indicating that the requested record does not exist and no failover should occur.
 | 
			
		||||
				 * Only continue iteration if the result is NULL and not CONFIG_RT_NOT_FOUND,
 | 
			
		||||
				 * which signals a backend failure.
 | 
			
		||||
				 */
 | 
			
		||||
				if (res == CONFIG_RT_NOT_FOUND) {
 | 
			
		||||
					return NULL;
 | 
			
		||||
				}
 | 
			
		||||
				if (res) {
 | 
			
		||||
					return res;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			return NULL;
 | 
			
		||||
 
 | 
			
		||||
@@ -167,7 +167,8 @@ static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
 | 
			
		||||
 * Sub-in the values to the prepared statement and execute it. Return results
 | 
			
		||||
 * as a ast_variable list.
 | 
			
		||||
 *
 | 
			
		||||
 * \return var on success
 | 
			
		||||
 * \return var on success (data found)
 | 
			
		||||
 * \return CONFIG_RT_NOT_FOUND on success but no record
 | 
			
		||||
 * \retval NULL on failure
 | 
			
		||||
 */
 | 
			
		||||
static struct ast_variable *realtime_odbc(const char *database, const char *table, const struct ast_variable *fields)
 | 
			
		||||
@@ -237,9 +238,13 @@ static struct ast_variable *realtime_odbc(const char *database, const char *tabl
 | 
			
		||||
 | 
			
		||||
	res = SQLFetch(stmt);
 | 
			
		||||
	if (res == SQL_NO_DATA) {
 | 
			
		||||
		/* SQL_NO_DATA indicates that the query was valid but no record was found.
 | 
			
		||||
		 * Instead of returning NULL (which signals a backend error to the core),
 | 
			
		||||
		 * return CONFIG_RT_NOT_FOUND to prevent incorrect failover.
 | 
			
		||||
		 */
 | 
			
		||||
		SQLFreeHandle (SQL_HANDLE_STMT, stmt);
 | 
			
		||||
		ast_odbc_release_obj(obj);
 | 
			
		||||
		return NULL;
 | 
			
		||||
		return CONFIG_RT_NOT_FOUND;
 | 
			
		||||
	}
 | 
			
		||||
	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 | 
			
		||||
		ast_log(LOG_WARNING, "SQL Fetch error! [%s]\n", ast_str_buffer(sql));
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user