From a8f124e2249db07b037035f6c4ea136e240645bb Mon Sep 17 00:00:00 2001 From: aland Date: Wed, 24 May 2006 16:31:43 +0000 Subject: [PATCH] Pull fix from the head --- .../drivers/rlm_sql_unixodbc/sql_unixodbc.c | 130 +++++++++++++++------ 1 file changed, 95 insertions(+), 35 deletions(-) diff --git a/src/modules/rlm_sql/drivers/rlm_sql_unixodbc/sql_unixodbc.c b/src/modules/rlm_sql/drivers/rlm_sql_unixodbc/sql_unixodbc.c index d8d1daf..3dd0636 100644 --- a/src/modules/rlm_sql/drivers/rlm_sql_unixodbc/sql_unixodbc.c +++ b/src/modules/rlm_sql/drivers/rlm_sql_unixodbc/sql_unixodbc.c @@ -40,6 +40,7 @@ typedef struct rlm_sql_unixodbc_sock { /* Forward declarations */ static char *sql_error(SQLSOCK *sqlsocket, SQL_CONFIG *config); +static int sql_state(long err_handle, SQLSOCK *sqlsocket, SQL_CONFIG *config); static int sql_free_result(SQLSOCK *sqlsocket, SQL_CONFIG *config); static int sql_affected_rows(SQLSOCK *sqlsocket, SQL_CONFIG *config); static int sql_num_fields(SQLSOCK *sqlsocket, SQL_CONFIG *config); @@ -67,23 +68,23 @@ static int sql_init_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config) { /* 1. Allocate environment handle and register version */ err_handle = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&unixodbc_sock->env_handle); - if (!SQL_SUCCEEDED(err_handle)) + if (sql_state(err_handle, sqlsocket, config)) { - radlog(L_ERR, "rlm_sql_unixodbc: Can't allocate environment handle %s\n", sql_error(sqlsocket, config)); + radlog(L_ERR, "rlm_sql_unixodbc: Can't allocate environment handle\n"); return -1; } err_handle = SQLSetEnvAttr(unixodbc_sock->env_handle, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); - if (!SQL_SUCCEEDED(err_handle)) + if (sql_state(err_handle, sqlsocket, config)) { - radlog(L_ERR, "rlm_sql_unixodbc: Can't register ODBC version %s\n", sql_error(sqlsocket, config)); + radlog(L_ERR, "rlm_sql_unixodbc: Can't register ODBC version\n"); SQLFreeHandle(SQL_HANDLE_ENV, unixodbc_sock->env_handle); return -1; } /* 2. Allocate connection handle */ err_handle = SQLAllocHandle(SQL_HANDLE_DBC, unixodbc_sock->env_handle, &unixodbc_sock->dbc_handle); - if (!SQL_SUCCEEDED(err_handle)) + if (sql_state(err_handle, sqlsocket, config)) { - radlog(L_ERR, "rlm_sql_unixodbc: Can't allocate connection handle %s\n", sql_error(sqlsocket, config)); + radlog(L_ERR, "rlm_sql_unixodbc: Can't allocate connection handle\n"); SQLFreeHandle(SQL_HANDLE_ENV, unixodbc_sock->env_handle); return -1; } @@ -93,9 +94,9 @@ static int sql_init_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config) { (SQLCHAR*) config->sql_server, strlen(config->sql_server), (SQLCHAR*) config->sql_login, strlen(config->sql_login), (SQLCHAR*) config->sql_password, strlen(config->sql_password)); - if (!SQL_SUCCEEDED(err_handle)) + if (sql_state(err_handle, sqlsocket, config)) { - radlog(L_ERR, "rlm_sql_unixodbc: Connection failed %s\n", sql_error(sqlsocket, config)); + radlog(L_ERR, "rlm_sql_unixodbc: Connection failed\n"); SQLFreeHandle(SQL_HANDLE_DBC, unixodbc_sock->dbc_handle); SQLFreeHandle(SQL_HANDLE_ENV, unixodbc_sock->env_handle); return -1; @@ -103,9 +104,9 @@ static int sql_init_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config) { /* 4. Allocate the statement */ err_handle = SQLAllocStmt(unixodbc_sock->dbc_handle, &unixodbc_sock->stmt_handle); - if (!SQL_SUCCEEDED(err_handle)) + if (sql_state(err_handle, sqlsocket, config)) { - radlog(L_ERR, "rlm_sql_unixodbc: Can't allocate the statement %s\n", sql_error(sqlsocket, config)); + radlog(L_ERR, "rlm_sql_unixodbc: Can't allocate the statement\n"); return -1; } @@ -139,16 +140,17 @@ static int sql_destroy_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config) static int sql_query(SQLSOCK *sqlsocket, SQL_CONFIG *config, char *querystr) { rlm_sql_unixodbc_sock *unixodbc_sock = sqlsocket->conn; long err_handle; + int state; if (config->sqltrace) radlog(L_DBG, "query: %s", querystr); /* Executing query */ err_handle = SQLExecDirect(unixodbc_sock->stmt_handle, (SQLCHAR *)querystr, strlen(querystr)); - if (!SQL_SUCCEEDED(err_handle)) - { - radlog(L_ERR, "rlm_sql_unixodbc: '%s'\n", sql_error(sqlsocket, config)); - return -1; + if ((state = sql_state(err_handle, sqlsocket, config))) { + if(state == SQL_DOWN) + radlog(L_INFO, "rlm_sql_unixodbc: rlm_sql will attempt to reconnect\n"); + return state; } return 0; } @@ -165,9 +167,11 @@ static int sql_select_query(SQLSOCK *sqlsocket, SQL_CONFIG *config, char *querys rlm_sql_unixodbc_sock *unixodbc_sock = sqlsocket->conn; SQLINTEGER column, len; int numfields; + int state; - if(sql_query(sqlsocket, config, querystr) < 0) - return -1; + /* Only state = 0 means success */ + if((state = sql_query(sqlsocket, config, querystr))) + return state; numfields=sql_num_fields(sqlsocket, config); if(numfields < 0) @@ -214,11 +218,9 @@ static int sql_num_fields(SQLSOCK *sqlsocket, SQL_CONFIG *config) { int num_fields = 0; err_handle = SQLNumResultCols(unixodbc_sock->stmt_handle,(SQLSMALLINT *)&num_fields); - if (!SQL_SUCCEEDED(err_handle)) - { - radlog(L_ERR, "rlm_sql_unixodbc: '%s'\n", sql_error(sqlsocket, config)); + if (sql_state(err_handle, sqlsocket, config)) return -1; - } + return num_fields; } @@ -247,14 +249,19 @@ static int sql_num_rows(SQLSOCK *sqlsocket, SQL_CONFIG *config) { *************************************************************************/ static int sql_fetch_row(SQLSOCK *sqlsocket, SQL_CONFIG *config) { rlm_sql_unixodbc_sock *unixodbc_sock = sqlsocket->conn; + long err_handle; + int state; sqlsocket->row = NULL; - if(SQLFetch(unixodbc_sock->stmt_handle) == SQL_NO_DATA_FOUND) - return 0; - - /* XXX Check if return suggests we should return error or SQL_DOWN */ - + err_handle = SQLFetch(unixodbc_sock->stmt_handle); + if(err_handle == SQL_NO_DATA_FOUND) + return 0; + if ((state = sql_state(err_handle, sqlsocket, config))) { + if(state == SQL_DOWN) + radlog(L_INFO, "rlm_sql_unixodbc: rlm_sql will attempt to reconnect\n"); + return state; + } sqlsocket->row = unixodbc_sock->row; return 0; } @@ -341,14 +348,53 @@ static int sql_close(SQLSOCK *sqlsocket, SQL_CONFIG *config) { * *************************************************************************/ static char *sql_error(SQLSOCK *sqlsocket, SQL_CONFIG *config) { - SQLCHAR state[256] = ""; - SQLCHAR error[256] = ""; + SQLCHAR state[256]; + SQLCHAR error[256]; + SQLINTEGER errornum = 0; + SQLSMALLINT length = 255; + static char result[1024]; /* NOT thread-safe! */ + + rlm_sql_unixodbc_sock *unixodbc_sock = sqlsocket->conn; + + error[0] = state[0] = '\0'; + + SQLError( + unixodbc_sock->env_handle, + unixodbc_sock->dbc_handle, + unixodbc_sock->stmt_handle, + state, + &errornum, + error, + 256, + &length); + + sprintf(result, "%s %s", state, error); + result[sizeof(result) - 1] = '\0'; /* catch idiot thread issues */ + return result; +} + +/************************************************************************* + * + * Function: sql_state + * + * Purpose: Returns 0 for success, SQL_DOWN if the error was + * connection related or -1 for other errors + * + *************************************************************************/ +static int sql_state(long err_handle, SQLSOCK *sqlsocket, SQL_CONFIG *config) { + SQLCHAR state[256]; + SQLCHAR error[256]; SQLINTEGER errornum = 0; SQLSMALLINT length = 255; - char *result; + int res = -1; rlm_sql_unixodbc_sock *unixodbc_sock = sqlsocket->conn; + if(SQL_SUCCEEDED(err_handle)) + return 0; /* on success, just return 0 */ + + error[0] = state[0] = '\0'; + SQLError( unixodbc_sock->env_handle, unixodbc_sock->dbc_handle, @@ -359,9 +405,25 @@ static char *sql_error(SQLSOCK *sqlsocket, SQL_CONFIG *config) { 256, &length); - result = (char*)rad_malloc(strlen(state)+1+strlen(error)); - sprintf(result, "%s %s", state, error); - return result; + if(state[0] == '0') { + switch(state[1]) { + case '1': /* SQLSTATE 01 class contains info and warning messages */ + radlog(L_INFO, "rlm_sql_unixodbc: %s %s\n", state, error); + case '0': /* SQLSTATE 00 class means success */ + res = 0; + break; + case '8': /* SQLSTATE 08 class describes various connection errors */ + radlog(L_ERR, "rlm_sql_unixodbc: SQL down %s %s\n", state, error); + res = SQL_DOWN; + break; + default: /* any other SQLSTATE means error */ + radlog(L_ERR, "rlm_sql_unixodbc: %s %s\n", state, error); + res = -1; + break; + } + } + + return res; } /************************************************************************* @@ -378,11 +440,9 @@ static int sql_affected_rows(SQLSOCK *sqlsocket, SQL_CONFIG *config) { int affected_rows; err_handle = SQLRowCount(unixodbc_sock->stmt_handle, (SQLINTEGER *)&affected_rows); - if (!SQL_SUCCEEDED(err_handle)) - { - radlog(L_ERR, "rlm_sql_unixodbc: '%s'\n", sql_error(sqlsocket, config)); + if (sql_state(err_handle, sqlsocket, config)) return -1; - } + return affected_rows; } -- 2.1.4