/*************************************************************************
 *
 *	Function: sql_store_result
 *
 *	Purpose: database specific store_result function. Returns a result
 *	       set for the query. In case of multiple results, get the
 *	       first non-empty one.
 *
 *************************************************************************/
static sql_rcode_t sql_store_result(rlm_sql_handle_t * handle, UNUSED rlm_sql_config_t *config)
{
	rlm_sql_mysql_conn_t *conn = handle->conn;
	int status;

	if (!conn->sock) {
		ERROR("rlm_sql_mysql: Socket not connected");
		return RLM_SQL_RECONNECT;
	}
retry_store_result:
	if (!(conn->result = mysql_store_result(conn->sock))) {
		status = sql_check_error(mysql_errno(conn->sock));
		if (status != 0) {
			ERROR("rlm_sql_mysql: Cannot store result");
			ERROR("rlm_sql_mysql: MySQL error '%s'",
			       mysql_error(conn->sock));
			return status;
		}
#if (MYSQL_VERSION_ID >= 40100)
		status = mysql_next_result(conn->sock);
		if (status == 0) {
			/* there are more results */
			goto retry_store_result;
		} else if (status > 0) {
			ERROR("rlm_sql_mysql: Cannot get next result");
			ERROR("rlm_sql_mysql: MySQL error '%s'",
			       mysql_error(conn->sock));
			return sql_check_error(status);
		}
#endif
	}
	return 0;
}
Пример #2
0
/*************************************************************************
 *
 *	Function: sql_store_result
 *
 *	Purpose: database specific store_result function. Returns a result
 *               set for the query. In case of multiple results, get the
 *               first non-empty one.
 *
 *************************************************************************/
static int sql_store_result(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
{
	rlm_sql_mysql_sock *mysql_sock = sqlsocket->conn;
	int status;

	if (mysql_sock->sock == NULL) {
		radlog(L_ERR, "rlm_sql_mysql: Socket not connected");
		return SQL_DOWN;
	}
retry_store_result:
	if (!(mysql_sock->result = mysql_store_result(mysql_sock->sock))) {
		status = sql_check_error(mysql_errno(mysql_sock->sock));
		if (status != 0) {
			radlog(L_ERR, "rlm_sql_mysql: Cannot store result");
			radlog(L_ERR, "rlm_sql_mysql: MySQL error '%s'",
			       mysql_error(mysql_sock->sock));
			return status;
		}
#if (MYSQL_VERSION_ID >= 40100)
		status = mysql_next_result(mysql_sock->sock);
		if (status == 0) {
			/* there are more results */
			goto retry_store_result;
		} else if (status > 0) {
			radlog(L_ERR, "rlm_sql_mysql: Cannot get next result");
			radlog(L_ERR, "rlm_sql_mysql: MySQL error '%s'",
			       mysql_error(mysql_sock->sock));
			return sql_check_error(status);
		}
#endif
	}
	return 0;
}
Пример #3
0
static sql_rcode_t sql_socket_init(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
{
	rlm_sql_unixodbc_conn_t *conn;
	long err_handle;

	MEM(conn = handle->conn = talloc_zero(handle, rlm_sql_unixodbc_conn_t));
	talloc_set_destructor(conn, _sql_socket_destructor);

	/* 1. Allocate environment handle and register version */
	err_handle = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &conn->env);
	if (sql_check_error(err_handle, handle, config)) {
		ERROR("rlm_sql_unixodbc: Can't allocate environment handle");
		return RLM_SQL_ERROR;
	}

	err_handle = SQLSetEnvAttr(conn->env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
	if (sql_check_error(err_handle, handle, config)) {
		ERROR("rlm_sql_unixodbc: Can't register ODBC version");
		return RLM_SQL_ERROR;
	}

	/* 2. Allocate connection handle */
	err_handle = SQLAllocHandle(SQL_HANDLE_DBC, conn->env, &conn->dbc);
	if (sql_check_error(err_handle, handle, config)) {
		ERROR("rlm_sql_unixodbc: Can't allocate connection handle");
		return RLM_SQL_ERROR;
	}

	/* 3. Connect to the datasource */
	{
		SQLCHAR *odbc_server, *odbc_login, *odbc_password;

		memcpy(&odbc_server, &config->sql_server, sizeof(odbc_server));
		memcpy(&odbc_login, &config->sql_login, sizeof(odbc_login));
		memcpy(&odbc_password, &config->sql_password, sizeof(odbc_password));
		err_handle = SQLConnect(conn->dbc,
					odbc_server, strlen(config->sql_server),
					odbc_login, strlen(config->sql_login),
					odbc_password, strlen(config->sql_password));
	}

	if (sql_check_error(err_handle, handle, config)) {
		ERROR("rlm_sql_unixodbc: Connection failed");
		return RLM_SQL_ERROR;
	}

	/* 4. Allocate the stmt */
	err_handle = SQLAllocHandle(SQL_HANDLE_STMT, conn->dbc, &conn->stmt);
	if (sql_check_error(err_handle, handle, config)) {
		ERROR("rlm_sql_unixodbc: Can't allocate the stmt");
		return RLM_SQL_ERROR;
	}

    return RLM_SQL_OK;
}
Пример #4
0
/*************************************************************************
 *
 *	Function: sql_fetch_row
 *
 *	Purpose: database specific fetch_row. Returns a rlm_sql_row_t struct
 *               with all the data for the query in 'handle->row'. Returns
 *		 0 on success, -1 on failure, SQL_DOWN if database is down.
 *
 *************************************************************************/
static int sql_fetch_row(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {

	int	x;
	rlm_sql_oracle_conn_t *conn = handle->conn;

	if (conn->ctx == NULL) {
		radlog(L_ERR, "rlm_sql_oracle: Socket not connected");
		return SQL_DOWN;
	}

	handle->row = NULL;

	x=OCIStmtFetch(conn->queryHandle,
			conn->errHandle,
			1,
			OCI_FETCH_NEXT,
			OCI_DEFAULT);

	if (x == OCI_SUCCESS) {
		handle->row = conn->results;
		return 0;
	}

	if (x == OCI_ERROR) {
		radlog(L_ERR,"rlm_sql_oracle: fetch failed in sql_fetch_row: %s",
				sql_error(handle, config));
		return sql_check_error(handle, config);
	}
	else {
		return -1;
	}
}
Пример #5
0
/*************************************************************************
 *
 *	Function: sql_finish_query
 *
 *	Purpose: As a single SQL statement may return multiple results
 *	sets, (for example stored procedures) it is necessary to check
 *	whether more results exist and process them in turn if so.
 *
 *************************************************************************/
static int sql_finish_query(rlm_sql_handle_t * handle, UNUSED rlm_sql_config_t *config)
{
#if (MYSQL_VERSION_ID >= 40100)
	rlm_sql_mysql_conn_t *conn = handle->conn;
	int status;

skip_next_result:
	status = sql_store_result(handle, config);
	if (status != 0) {
		return status;
	} else if (conn->result != NULL) {
		radlog(L_DBG, "rlm_sql_mysql: SQL statement returned unexpected result");
		sql_free_result(handle, config);
	}
	status = mysql_next_result(conn->sock);
	if (status == 0) {
		/* there are more results */
		goto skip_next_result;
	}  else if (status > 0) {
		radlog(L_ERR, "rlm_sql_mysql: Cannot get next result");
		radlog(L_ERR, "rlm_sql_mysql: MySQL error '%s'",
		       mysql_error(conn->sock));
		return sql_check_error(status);
	}
#endif
	return 0;
}
Пример #6
0
/*************************************************************************
 *
 *	Function: sql_finish_query
 *
 *	Purpose: As a single SQL statement may return multiple results
 *	sets, (for example stored procedures) it is necessary to check
 *	whether more results exist and process them in turn if so.
 *
 *************************************************************************/
static int sql_finish_query(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
{
#if (MYSQL_VERSION_ID >= 40100)
	rlm_sql_mysql_sock *mysql_sock = sqlsocket->conn;
	int status;

skip_next_result:
	status = sql_store_result(sqlsocket, config);
	if (status != 0) {
		return status;
	} else if (mysql_sock->result != NULL) {
		radlog(L_DBG, "rlm_sql_mysql: SQL statement returned unexpected result");
		sql_free_result(sqlsocket, config);
	}
	status = mysql_next_result(mysql_sock->sock);
	if (status == 0) {
		/* there are more results */
		goto skip_next_result;
	}  else if (status > 0) {
		radlog(L_ERR, "rlm_sql_mysql: Cannot get next result");
		radlog(L_ERR, "rlm_sql_mysql: MySQL error '%s'",
		       mysql_error(mysql_sock->sock));
		return sql_check_error(status);
	}
#endif
	return 0;
}
Пример #7
0
/*************************************************************************
 *
 *	Function: sql_fetch_row
 *
 *	Purpose: database specific fetch_row. Returns a SQL_ROW struct
 *               with all the data for the query in 'sqlsocket->row'. Returns
 *		 0 on success, -1 on failure, SQL_DOWN if database is down.
 *
 *************************************************************************/
static int sql_fetch_row(SQLSOCK *sqlsocket, SQL_CONFIG *config) {

	int	x;
	rlm_sql_oracle_sock *oracle_sock = sqlsocket->conn;

	if (oracle_sock->conn == NULL) {
		radlog(L_ERR, "rlm_sql_oracle: Socket not connected");
		return SQL_DOWN;
	}

	sqlsocket->row = NULL;

	x=OCIStmtFetch(oracle_sock->queryHandle,
			oracle_sock->errHandle,
			1,
			OCI_FETCH_NEXT,
			OCI_DEFAULT);

	if (x == OCI_SUCCESS) {
		sqlsocket->row = oracle_sock->results;
		return 0;
	}

	if (x == OCI_ERROR) {
		radlog(L_ERR,"rlm_sql_oracle: fetch failed in sql_fetch_row: %s",
				sql_error(sqlsocket, config));
		return sql_check_error(sqlsocket, config);
	}
	else {
		return -1;
	}
}
Пример #8
0
static int sql_num_fields(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
{
	rlm_sql_unixodbc_conn_t *conn = handle->conn;
	long err_handle;
	SQLSMALLINT num_fields = 0;

	err_handle = SQLNumResultCols(conn->stmt,&num_fields);
	if (sql_check_error(err_handle, handle, config)) return -1;

	return num_fields;
}
Пример #9
0
/*************************************************************************
 *
 *	Function: sql_affected_rows
 *
 *	Purpose: Return the number of rows affected by the query (update,
 *	       or insert)
 *
 *************************************************************************/
static int sql_affected_rows(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
{
	rlm_sql_unixodbc_conn_t *conn = handle->conn;
	long error_handle;
	SQLLEN affected_rows;

	error_handle = SQLRowCount(conn->stmt, &affected_rows);
	if (sql_check_error(error_handle, handle, config)) return -1;

	return affected_rows;
}
Пример #10
0
/*************************************************************************
 *
 *	Function: sql_fetch_row
 *
 *	Purpose: database specific fetch_row. Returns a rlm_sql_row_t struct
 *               with all the data for the query in 'handle->row'. Returns
 *		 0 on success, -1 on failure, SQL_DOWN if database is down.
 *
 *************************************************************************/
static int sql_fetch_row(rlm_sql_handle_t * handle, UNUSED rlm_sql_config_t *config)
{
	rlm_sql_mysql_conn_t *conn = handle->conn;
	int status;

	/*
	 *  Check pointer before de-referencing it.
	 */
	if (!conn->result) {
		return SQL_DOWN;
	}

retry_fetch_row:
	handle->row = mysql_fetch_row(conn->result);

	if (handle->row == NULL) {
		status = sql_check_error(mysql_errno(conn->sock));
		if (status != 0) {
			radlog(L_ERR, "rlm_sql_mysql: Cannot fetch row");
			radlog(L_ERR, "rlm_sql_mysql: MySQL error '%s'",
			       mysql_error(conn->sock));
			return status;
		}
#if (MYSQL_VERSION_ID >= 40100)
		sql_free_result(handle, config);
		status = mysql_next_result(conn->sock);
		if (status == 0) {
			/* there are more results */
			if ((sql_store_result(handle, config) == 0)
			 && (conn->result != NULL))
				goto retry_fetch_row;
		} else if (status > 0) {
			radlog(L_ERR, "rlm_sql_mysql: Cannot get next result");
			radlog(L_ERR, "rlm_sql_mysql: MySQL error '%s'",
			       mysql_error(conn->sock));
			return sql_check_error(status);
		}
#endif
	}
	return 0;
}
Пример #11
0
/*************************************************************************
 *
 *	Function: sql_fetch_row
 *
 *	Purpose: database specific fetch_row. Returns a SQL_ROW struct
 *               with all the data for the query in 'sqlsocket->row'. Returns
 *		 0 on success, -1 on failure, SQL_DOWN if database is down.
 *
 *************************************************************************/
static int sql_fetch_row(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
{
	rlm_sql_mysql_sock *mysql_sock = sqlsocket->conn;
	int status;

	/*
	 *  Check pointer before de-referencing it.
	 */
	if (!mysql_sock->result) {
		return SQL_DOWN;
	}

retry_fetch_row:
	sqlsocket->row = mysql_fetch_row(mysql_sock->result);

	if (sqlsocket->row == NULL) {
		status = sql_check_error(mysql_errno(mysql_sock->sock));
		if (status != 0) {
			radlog(L_ERR, "rlm_sql_mysql: Cannot fetch row");
			radlog(L_ERR, "rlm_sql_mysql: MySQL error '%s'",
			       mysql_error(mysql_sock->sock));
			return status;
		}
#if (MYSQL_VERSION_ID >= 40100)
		sql_free_result(sqlsocket, config);
		status = mysql_next_result(mysql_sock->sock);
		if (status == 0) {
			/* there are more results */
			if ((sql_store_result(sqlsocket, config) == 0)
			 && (mysql_sock->result != NULL))
				goto retry_fetch_row;
		} else if (status > 0) {
			radlog(L_ERR, "rlm_sql_mysql: Cannot get next result");
			radlog(L_ERR, "rlm_sql_mysql: MySQL error '%s'",
			       mysql_error(mysql_sock->sock));
			return sql_check_error(status);
		}
#endif
	}
	return 0;
}
Пример #12
0
/*************************************************************************
 *
 *	Function: sql_query
 *
 *	Purpose: Issue a query to the database
 *
 *************************************************************************/
static sql_rcode_t sql_query(rlm_sql_handle_t * handle, UNUSED rlm_sql_config_t *config, char const *query)
{
	rlm_sql_mysql_conn_t *conn = handle->conn;

	if (!conn->sock) {
		ERROR("rlm_sql_mysql: Socket not connected");
		return RLM_SQL_RECONNECT;
	}

	mysql_query(conn->sock, query);
	return sql_check_error(mysql_errno(conn->sock));
}
Пример #13
0
/*************************************************************************
 *
 *	Function: sql_query
 *
 *	Purpose: Issue a query to the database
 *
 *************************************************************************/
static int sql_query(rlm_sql_handle_t * handle, UNUSED rlm_sql_config_t *config,
		     char *querystr)
{
	rlm_sql_mysql_conn_t *conn = handle->conn;

	if (conn->sock == NULL) {
		radlog(L_ERR, "rlm_sql_mysql: Socket not connected");
		return SQL_DOWN;
	}

	mysql_query(conn->sock, querystr);
	return sql_check_error(mysql_errno(conn->sock));
}
Пример #14
0
/*************************************************************************
 *
 *	Function: sql_query
 *
 *	Purpose: Issue a query to the database
 *
 *************************************************************************/
static int sql_query(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config,
		     char *querystr)
{
	rlm_sql_mysql_sock *mysql_sock = sqlsocket->conn;

	if (mysql_sock->sock == NULL) {
		radlog(L_ERR, "rlm_sql_mysql: Socket not connected");
		return SQL_DOWN;
	}

	mysql_query(mysql_sock->sock, querystr);
	return sql_check_error(mysql_errno(mysql_sock->sock));
}
Пример #15
0
/*************************************************************************
 *
 *	Function: sql_query
 *
 *	Purpose: Issue a query to the database
 *
 *************************************************************************/
static int sql_query(SQLSOCK * sqlsocket, SQL_CONFIG *config, char *querystr) {

	rlm_sql_postgres_sock *pg_sock = sqlsocket->conn;

	if (config->sqltrace)
		radlog(L_DBG,"rlm_sql_postgresql: query:\n%s", querystr);

	if (pg_sock->conn == NULL) {
		radlog(L_ERR, "rlm_sql_postgresql: Socket not connected");
		return SQL_DOWN;
	}

	pg_sock->result = PQexec(pg_sock->conn, querystr);
		/* Returns a result pointer or possibly a NULL pointer.
		 * A non-NULL pointer will generally be returned except in
		 * out-of-memory conditions or serious errors such as inability
		 * to send the command to the backend. If a NULL is returned,
		 *  it should be treated like a PGRES_FATAL_ERROR result.
		 * Use PQerrorMessage to get more information about the error.
		 */
	if (!pg_sock->result)
	{
		radlog(L_ERR, "rlm_sql_postgresql: PostgreSQL Query failed Error: %s",
				PQerrorMessage(pg_sock->conn));
		return  SQL_DOWN;
	} else {
		ExecStatusType status = PQresultStatus(pg_sock->result);

		radlog(L_DBG, "rlm_sql_postgresql: Status: %s", PQresStatus(status));

		radlog(L_DBG, "rlm_sql_postgresql: affected rows = %s",
				PQcmdTuples(pg_sock->result));

		if (!status_is_ok(status))
			return sql_check_error(status);

		if (strncasecmp("select", querystr, 6) != 0) {
			/* store the number of affected rows because the sql module
			 * calls finish_query before it retrieves the number of affected
			 * rows from the driver */
			pg_sock->affected_rows = affected_rows(pg_sock->result);
			return 0;
		} else {
			if ((sql_store_result(sqlsocket, config) == 0)
					&& (sql_num_fields(sqlsocket, config) >= 0))
				return 0;
			else
				return -1;
		}
	}
}
Пример #16
0
static sql_rcode_t sql_fetch_row(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
{
	rlm_sql_unixodbc_conn_t *conn = handle->conn;
	long err_handle;
	int state;

	handle->row = NULL;

	err_handle = SQLFetch(conn->stmt);
	if (err_handle == SQL_NO_DATA_FOUND) return RLM_SQL_NO_MORE_ROWS;

	if ((state = sql_check_error(err_handle, handle, config))) return state;

	handle->row = conn->row;
	return RLM_SQL_OK;
}
Пример #17
0
/*************************************************************************
 *
 *	Function: sql_query
 *
 *	Purpose: Issue a non-SELECT query (ie: update/delete/insert) to
 *               the database.
 *
 *************************************************************************/
static int sql_query(SQLSOCK *sqlsocket, SQL_CONFIG *config, char *querystr) {

	int	x;
	rlm_sql_oracle_sock *oracle_sock = sqlsocket->conn;

	if (config->sqltrace)
		DEBUG(querystr);
	if (oracle_sock->conn == NULL) {
		radlog(L_ERR, "rlm_sql_oracle: Socket not connected");
		return SQL_DOWN;
	}

	if (OCIStmtPrepare (oracle_sock->queryHandle, oracle_sock->errHandle,
				querystr, strlen(querystr),
				OCI_NTV_SYNTAX, OCI_DEFAULT))  {
		radlog(L_ERR,"rlm_sql_oracle: prepare failed in sql_query: %s",sql_error(sqlsocket, config));
		return -1;
	}

	x = OCIStmtExecute(oracle_sock->conn,
				oracle_sock->queryHandle,
				oracle_sock->errHandle,
				(ub4) 1,
				(ub4) 0,
				(OCISnapshot *) NULL,
				(OCISnapshot *) NULL,
				(ub4) OCI_COMMIT_ON_SUCCESS);

	if (x == OCI_SUCCESS) {
		return 0;
	}

	if (x == OCI_ERROR) {
		radlog(L_ERR,"rlm_sql_oracle: execute query failed in sql_query: %s",
				sql_error(sqlsocket, config));
		return sql_check_error(sqlsocket, config);
	}
	else {
		return -1;
	}
}
Пример #18
0
static sql_rcode_t sql_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config, char const *query)
{
	rlm_sql_unixodbc_conn_t *conn = handle->conn;
	long err_handle;
	int state;

	/* Executing query */
	{
		SQLCHAR *odbc_query;

		memcpy(&odbc_query, &query, sizeof(odbc_query));
		err_handle = SQLExecDirect(conn->stmt, odbc_query, strlen(query));
	}
	if ((state = sql_check_error(err_handle, handle, config))) {
		if(state == RLM_SQL_RECONNECT) {
			DEBUG("rlm_sql_unixodbc: rlm_sql will attempt to reconnect");
		}
		return state;
	}
	return 0;
}
Пример #19
0
/*************************************************************************
 *
 *	Function: sql_finish_select_query
 *
 *	Purpose: End the select query, such as freeing memory or result
 *
 *************************************************************************/
static int sql_finish_select_query(SQLSOCK * sqlsocket, SQL_CONFIG *config)
{
#if (MYSQL_VERSION_ID >= 40100)
	int status;
	rlm_sql_mysql_sock *mysql_sock = sqlsocket->conn;
#endif
	sql_free_result(sqlsocket, config);
#if (MYSQL_VERSION_ID >= 40100)
	status = mysql_next_result(mysql_sock->sock);
	if (status == 0) {
		/* there are more results */
		sql_finish_query(sqlsocket, config);
	}  else if (status > 0) {
		radlog(L_ERR, "rlm_sql_mysql: Cannot get next result");
		radlog(L_ERR, "rlm_sql_mysql: MySQL error '%s'",
		       mysql_error(mysql_sock->sock));
		return sql_check_error(status);
	}
#endif
	return 0;
}
Пример #20
0
/*************************************************************************
 *
 *	Function: sql_finish_select_query
 *
 *	Purpose: End the select query, such as freeing memory or result
 *
 *************************************************************************/
static int sql_finish_select_query(rlm_sql_handle_t * handle, rlm_sql_config_t *config)
{
#if (MYSQL_VERSION_ID >= 40100)
	int status;
	rlm_sql_mysql_conn_t *conn = handle->conn;
#endif
	sql_free_result(handle, config);
#if (MYSQL_VERSION_ID >= 40100)
	status = mysql_next_result(conn->sock);
	if (status == 0) {
		/* there are more results */
		sql_finish_query(handle, config);
	}  else if (status > 0) {
		radlog(L_ERR, "rlm_sql_mysql: Cannot get next result");
		radlog(L_ERR, "rlm_sql_mysql: MySQL error '%s'",
		       mysql_error(conn->sock));
		return sql_check_error(status);
	}
#endif
	return 0;
}
Пример #21
0
/*************************************************************************
 *
 *	Function: sql_query
 *
 *	Purpose: Issue a non-SELECT query (ie: update/delete/insert) to
 *               the database.
 *
 *************************************************************************/
static int sql_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config, char *querystr) {

	int	x;
	rlm_sql_oracle_conn_t *conn = handle->conn;

	if (conn->ctx == NULL) {
		radlog(L_ERR, "rlm_sql_oracle: Socket not connected");
		return SQL_DOWN;
	}

	if (OCIStmtPrepare (conn->queryHandle, conn->errHandle,
				querystr, strlen(querystr),
				OCI_NTV_SYNTAX, OCI_DEFAULT))  {
		radlog(L_ERR,"rlm_sql_oracle: prepare failed in sql_query: %s",sql_error(handle, config));
		return -1;
	}

	x = OCIStmtExecute(conn->ctx,
				conn->queryHandle,
				conn->errHandle,
				(ub4) 1,
				(ub4) 0,
				(OCISnapshot *) NULL,
				(OCISnapshot *) NULL,
				(ub4) OCI_COMMIT_ON_SUCCESS);

	if (x == OCI_SUCCESS) {
		return 0;
	}

	if (x == OCI_ERROR) {
		radlog(L_ERR,"rlm_sql_oracle: execute query failed in sql_query: %s",
				sql_error(handle, config));
		return sql_check_error(handle, config);
	}
	else {
		return -1;
	}
}
Пример #22
0
/*************************************************************************
 *
 *	Function: sql_select_query
 *
 *	Purpose: Issue a select query to the database
 *
 *************************************************************************/
static int sql_select_query(SQLSOCK *sqlsocket, SQL_CONFIG *config, char *querystr) {

	int		x;
	int		y;
	int		colcount;
	OCIParam	*param;
	OCIDefine	*define;
	ub2		dtype;
	ub2		dsize;
	char		**rowdata=NULL;
	sb2		*indicators;
	rlm_sql_oracle_sock *oracle_sock = sqlsocket->conn;

	if (config->sqltrace)
		DEBUG(querystr);
	if (oracle_sock->conn == NULL) {
		radlog(L_ERR, "rlm_sql_oracle: Socket not connected");
		return SQL_DOWN;
	}

	if (OCIStmtPrepare (oracle_sock->queryHandle, oracle_sock->errHandle,
				querystr, strlen(querystr),
				OCI_NTV_SYNTAX, OCI_DEFAULT))  {
		radlog(L_ERR,"rlm_sql_oracle: prepare failed in sql_select_query: %s",sql_error(sqlsocket, config));
		return -1;
	}

	/* Query only one row by default (for now) */
	x = OCIStmtExecute(oracle_sock->conn,
				oracle_sock->queryHandle,
				oracle_sock->errHandle,
				(ub4) 0,
				(ub4) 0,
				(OCISnapshot *) NULL,
				(OCISnapshot *) NULL,
				(ub4) OCI_DEFAULT);

	if (x == OCI_NO_DATA) {
		/* Nothing to fetch */
		return 0;
	}

	if (x != OCI_SUCCESS) {
		radlog(L_ERR,"rlm_sql_oracle: query failed in sql_select_query: %s",
				sql_error(sqlsocket, config));
		return sql_check_error(sqlsocket, config);
	}

	/*
	 * Define where the output from fetch calls will go
	 *
	 * This is a gross hack, but it works - we convert
	 * all data to strings for ease of use.  Fortunately, most
	 * of the data we deal with is already in string format.
	 */
	colcount = sql_num_fields(sqlsocket, config);

	/* DEBUG2("sql_select_query(): colcount=%d",colcount); */

	/*
	 *	FIXME: These malloc's can probably go, as the schema
	 *	is fixed...
	 */
	rowdata=(char **)rad_malloc(sizeof(char *) * (colcount+1) );
	memset(rowdata, 0, (sizeof(char *) * (colcount+1) ));
	indicators = (sb2 *) rad_malloc(sizeof(sb2) * (colcount+1) );
	memset(indicators, 0, sizeof(sb2) * (colcount+1));

	for (y=1; y <= colcount; y++) {
		x=OCIParamGet(oracle_sock->queryHandle, OCI_HTYPE_STMT,
				oracle_sock->errHandle,
				(dvoid **)&param,
				(ub4) y);
		if (x != OCI_SUCCESS) {
			radlog(L_ERR,"rlm_sql_oracle: OCIParamGet() failed in sql_select_query: %s",
				sql_error(sqlsocket, config));
			return -1;
		}

		x=OCIAttrGet((dvoid*)param, OCI_DTYPE_PARAM,
			   (dvoid*)&dtype, (ub4*)0, OCI_ATTR_DATA_TYPE,
			   oracle_sock->errHandle);
		if (x != OCI_SUCCESS) {
			radlog(L_ERR,"rlm_sql_oracle: OCIAttrGet() failed in sql_select_query: %s",
				sql_error(sqlsocket, config));
			return -1;
		}

		dsize=MAX_DATASTR_LEN;

		/*
		 * Use the retrieved length of dname to allocate an output
		 * buffer, and then define the output variable (but only
		 * for char/string type columns).
		 */
		switch(dtype) {
#ifdef SQLT_AFC
		case SQLT_AFC:	/* ansii fixed char */
#endif
#ifdef SQLT_AFV
		case SQLT_AFV:	/* ansii var char */
#endif
		case SQLT_VCS:	/* var char */
		case SQLT_CHR:	/* char */
		case SQLT_STR:	/* string */
			x=OCIAttrGet((dvoid*)param, (ub4) OCI_DTYPE_PARAM,
				   (dvoid*) &dsize, (ub4 *)0, (ub4) OCI_ATTR_DATA_SIZE,
				   oracle_sock->errHandle);
			if (x != OCI_SUCCESS) {
				radlog(L_ERR,"rlm_sql_oracle: OCIAttrGet() failed in sql_select_query: %s",
					sql_error(sqlsocket, config));
				return -1;
			}
			rowdata[y-1]=rad_malloc(dsize+1);
			memset(rowdata[y-1], 0, dsize+1);
			break;
		case SQLT_DAT:
		case SQLT_INT:
		case SQLT_UIN:
		case SQLT_FLT:
		case SQLT_PDN:
		case SQLT_BIN:
		case SQLT_NUM:
			rowdata[y-1]=rad_malloc(dsize+1);
			memset(rowdata[y-1], 0, dsize+1);
			break;
		default:
			dsize=0;
			rowdata[y-1]=NULL;
			break;
		}

		indicators[y-1] = 0;
		x=OCIDefineByPos(oracle_sock->queryHandle,
				&define,
				oracle_sock->errHandle,
				y,
				(ub1 *) rowdata[y-1],
				dsize+1,
				SQLT_STR,
				&indicators[y-1],
				(dvoid *) 0,
				(dvoid *) 0,
				OCI_DEFAULT);

		/*
		 *	FIXME: memory leaks of indicators & rowdata?
		 */
		if (x != OCI_SUCCESS) {
			radlog(L_ERR,"rlm_sql_oracle: OCIDefineByPos() failed in sql_select_query: %s",
				sql_error(sqlsocket, config));
			return -1;
		}
	}

	oracle_sock->results=rowdata;
	oracle_sock->indicators=indicators;

	return 0;
}