typedef struct rlm_sql_iodbc_conn {
HENV env_handle;
HDBC dbc_handle;
- HSTMT stmt_handle;
+ HSTMT stmt;
int id;
rlm_sql_row_t row;
{
DEBUG2("rlm_sql_iodbc: Socket destructor called, closing socket");
- if (conn->stmt_handle) {
- SQLFreeStmt(conn->stmt_handle, SQL_DROP);
- }
+ if (conn->stmt) SQLFreeStmt(conn->stmt, SQL_DROP);
if (conn->dbc_handle) {
SQLDisconnect(conn->dbc_handle);
SQLFreeConnect(conn->dbc_handle);
}
- if (conn->env_handle) {
- SQLFreeEnv(conn->env_handle);
- }
+ if (conn->env_handle) SQLFreeEnv(conn->env_handle);
return 0;
}
ERROR("rlm_sql_iodbc: SQLAllocEnv failed");
if (sql_error(NULL, &entry, 1, handle, config) > 0) ERROR("rlm_sql_iodbc: %s", entry.msg);
- return -1;
+ return RLM_SQL_ERROR;
}
rcode = SQLAllocConnect(conn->env_handle,
ERROR("rlm_sql_iodbc: SQLAllocConnect failed");
if (sql_error(NULL, &entry, 1, handle, config) > 0) ERROR("rlm_sql_iodbc: %s", entry.msg);
- return -1;
+ return RLM_SQL_ERROR;
}
/*
ERROR("rlm_sql_iodbc: SQLConnectfailed");
if (sql_error(NULL, &entry, 1, handle, config) > 0) ERROR("rlm_sql_iodbc: %s", entry.msg);
- return -1;
+ return RLM_SQL_ERROR;
}
return 0;
rlm_sql_iodbc_conn_t *conn = handle->conn;
SQLRETURN rcode;
- rcode = SQLAllocStmt(conn->dbc_handle, &conn->stmt_handle);
- if (!SQL_SUCCEEDED(rcode)) return -1;
+ rcode = SQLAllocStmt(conn->dbc_handle, &conn->stmt);
+ if (!SQL_SUCCEEDED(rcode)) return RLM_SQL_ERROR;
if (!conn->dbc_handle) {
ERROR("rlm_sql_iodbc: Socket not connected");
- return -1;
+ return RLM_SQL_ERROR;
}
{
SQLCHAR *statement;
memcpy(&statement, &query, sizeof(statement));
- rcode = SQLExecDirect(conn->stmt_handle, statement, SQL_NTS);
+ rcode = SQLExecDirect(conn->stmt, statement, SQL_NTS);
}
- if (!SQL_SUCCEEDED(rcode)) return -1;
+ if (!SQL_SUCCEEDED(rcode)) return RLM_SQL_ERROR;
return 0;
}
long len = 0;
rlm_sql_iodbc_conn_t *conn = handle->conn;
- if(sql_query(handle, config, query) < 0) {
- return -1;
- }
+ if (sql_query(handle, config, query) < 0) return RLM_SQL_ERROR;
numfields = sql_num_fields(handle, config);
row[numfields] = NULL;
for(i=1; i<=numfields; i++) {
- SQLColAttributes(conn->stmt_handle, ((SQLUSMALLINT) i), SQL_COLUMN_LENGTH, NULL, 0, NULL, &len);
+ SQLColAttributes(conn->stmt, ((SQLUSMALLINT) i), SQL_COLUMN_LENGTH, NULL, 0, NULL, &len);
len++;
/*
*
* http://msdn.microsoft.com/library/psdk/dasdk/odap4o4z.htm
*/
- SQLBindCol(conn->stmt_handle, i, SQL_C_CHAR, (SQLCHAR *)row[i-1], len, 0);
+ SQLBindCol(conn->stmt, i, SQL_C_CHAR, (SQLCHAR *)row[i-1], len, 0);
}
conn->row = row;
return 0;
}
-static sql_rcode_t sql_store_result(UNUSED rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
-{
- return 0;
-}
-
static int sql_num_fields(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
{
SQLSMALLINT count=0;
rlm_sql_iodbc_conn_t *conn = handle->conn;
- SQLNumResultCols(conn->stmt_handle, &count);
+ SQLNumResultCols(conn->stmt, &count);
return (int)count;
}
-static int sql_num_rows(UNUSED rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
+static sql_rcode_t sql_fields(char const **out[], rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
{
- /*
- * I presume this function is used to determine the number of
- * rows in a result set *before* fetching them. I don't think
- * this is possible in ODBC 2.x, but I'd be happy to be proven
- * wrong. If you know how to do this, email me at jeff@apex.net
- */
- return 0;
+ rlm_sql_iodbc_conn_t *conn = handle->conn;
+
+ SQLSMALLINT fields, len, i;
+
+ char const **names;
+ char field[128];
+
+ SQLNumResultCols(conn->stmt, &fields);
+ if (fields == 0) return RLM_SQL_ERROR;
+
+ MEM(names = talloc_array(handle, char const *, fields));
+
+ for (i = 0; i < fields; i++) {
+ char *p;
+
+ switch (SQLColAttribute(conn->stmt, i, SQL_DESC_BASE_COLUMN_NAME,
+ field, sizeof(field), &len, NULL)) {
+ case SQL_INVALID_HANDLE:
+ case SQL_ERROR:
+ ERROR("Failed retrieving field name at index %i", i);
+ talloc_free(names);
+ return RLM_SQL_ERROR;
+
+ default:
+ break;
+ }
+
+ MEM(p = talloc_array(names, char, (size_t)len + 1));
+ strlcpy(p, field, (size_t)len + 1);
+ names[i] = p;
+ }
+ *out = names;
+
+ return RLM_SQL_OK;
}
static sql_rcode_t sql_fetch_row(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
handle->row = NULL;
- if((rc = SQLFetch(conn->stmt_handle)) == SQL_NO_DATA_FOUND) {
- return 0;
- }
+ rc = SQLFetch(conn->stmt);
+ if (rc == SQL_NO_DATA_FOUND) return RLM_SQL_NO_MORE_ROWS;
+
/* XXX Check rc for database down, if so, return RLM_SQL_RECONNECT */
handle->row = conn->row;
free(conn->row);
conn->row = NULL;
- SQLFreeStmt(conn->stmt_handle, SQL_DROP);
+ SQLFreeStmt(conn->stmt, SQL_DROP);
return 0;
}
rad_assert(outlen > 0);
errbuff[0] = '\0';
- SQLError(conn->env_handle, conn->dbc_handle, conn->stmt_handle,
+ SQLError(conn->env_handle, conn->dbc_handle, conn->stmt,
state, &errornum, errbuff, IODBC_MAX_ERROR_LEN, &length);
if (errbuff[0] == '\0') return 0;
long count;
rlm_sql_iodbc_conn_t *conn = handle->conn;
- SQLRowCount(conn->stmt_handle, &count);
+ SQLRowCount(conn->stmt, &count);
return (int)count;
}
.sql_socket_init = sql_socket_init,
.sql_query = sql_query,
.sql_select_query = sql_select_query,
- .sql_store_result = sql_store_result,
.sql_num_fields = sql_num_fields,
- .sql_num_rows = sql_num_rows,
.sql_affected_rows = sql_affected_rows,
+ .sql_fields = sql_fields,
.sql_fetch_row = sql_fetch_row,
.sql_free_result = sql_free_result,
.sql_error = sql_error,