示例#1
0
/** Call the driver's sql_fetch_row function
 *
 * Calls the driver's sql_fetch_row logging any errors. On success, will
 * write row data to ``(*handle)->row``.
 *
 * @param out Where to write row data.
 * @param inst Instance of #rlm_sql_t.
 * @param request The Current request, may be NULL.
 * @param handle Handle to retrieve errors for.
 * @return
 *	- #RLM_SQL_OK on success.
 *	- other #sql_rcode_t constants on error.
 */
sql_rcode_t rlm_sql_fetch_row(rlm_sql_row_t *out, rlm_sql_t const *inst, REQUEST *request, rlm_sql_handle_t **handle)
{
	sql_rcode_t ret;

	if (!*handle || !(*handle)->conn) return RLM_SQL_ERROR;

	/*
	 *	We can't implement reconnect logic here, because the caller
	 *	may require the original connection to free up queries or
	 *	result sets associated with that connection.
	 */
	ret = (inst->driver->sql_fetch_row)(out, *handle, inst->config);
	switch (ret) {
	case RLM_SQL_OK:
		rad_assert(*out != NULL);
		return ret;

	case RLM_SQL_NO_MORE_ROWS:
		rad_assert(*out == NULL);
		return ret;

	default:
		ROPTIONAL(RERROR, ERROR, "Error fetching row");
		rlm_sql_print_error(inst, request, *handle, false);
		return ret;
	}
}
示例#2
0
/** Call the driver's sql_select_query method, reconnecting if necessary.
 *
 * @note Caller must call ``(inst->module->sql_finish_select_query)(handle, inst->config);``
 *	after they're done with the result.
 *
 * @param inst #rlm_sql_t instance data.
 * @param request Current request.
 * @param handle to query the database with. *handle should not be NULL, as this indicates
 *	  previous reconnection attempt has failed.
 * @param query to execute. Should not be zero length.
 * @return
 *	- #RLM_SQL_OK on success.
 *	- #RLM_SQL_RECONNECT if a new handle is required (also sets *handle = NULL).
 *	- #RLM_SQL_QUERY_INVALID, #RLM_SQL_ERROR on invalid query or connection error.
 */
sql_rcode_t rlm_sql_select_query(rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t **handle,  char const *query)
{
	int ret = RLM_SQL_ERROR;
	int i, count;

	/* Caller should check they have a valid handle */
	rad_assert(*handle);

	/* There's no query to run, return an error */
	if (query[0] == '\0') {
		if (request) REDEBUG("Zero length query");

		return RLM_SQL_QUERY_INVALID;
	}

	/*
	 *  inst->pool may be NULL is this function is called by mod_conn_create.
	 */
	count = inst->pool ? fr_connection_get_num(inst->pool) : 0;

	/*
	 *  For sanity, for when no connections are viable, and we can't make a new one
	 */
	for (i = 0; i < (count + 1); i++) {
		ROPTIONAL(RDEBUG2, DEBUG2, "Executing select query: %s", query);

		ret = (inst->module->sql_select_query)(*handle, inst->config, query);
		switch (ret) {
		case RLM_SQL_OK:
			break;

		/*
		 *	Run through all available sockets until we exhaust all existing
		 *	sockets in the pool and fail to establish a *new* connection.
		 */
		case RLM_SQL_RECONNECT:
			*handle = fr_connection_reconnect(inst->pool, *handle);
			/* Reconnection failed */
			if (!*handle) return RLM_SQL_RECONNECT;
			/* Reconnection succeeded, try again with the new handle */
			continue;

		case RLM_SQL_QUERY_INVALID:
		case RLM_SQL_ERROR:
		default:
			rlm_sql_print_error(inst, request, *handle, false);
			(inst->module->sql_finish_select_query)(*handle, inst->config);
			break;
		}

		return ret;
	}

	ROPTIONAL(RERROR, ERROR, "Hit reconnection limit");

	return RLM_SQL_ERROR;
}
示例#3
0
/** Call the driver's sql_fetch_row function
 *
 * Calls the driver's sql_fetch_row logging any errors. On success, will
 * write row data to ``(*handle)->row``.
 *
 * @param out Where to write row data.
 * @param inst Instance of #rlm_sql_t.
 * @param request The Current request, may be NULL.
 * @param handle Handle to retrieve errors for.
 * @return
 *	- #RLM_SQL_OK on success.
 *	- other #sql_rcode_t constants on error.
 */
sql_rcode_t rlm_sql_fetch_row(rlm_sql_row_t *out, rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t **handle)
{
	sql_rcode_t ret;

	if (!*handle || !(*handle)->conn) return RLM_SQL_ERROR;

	/*
	 *	We can't implement reconnect logic here, because the caller
	 *	may require the original connection to free up queries or
	 *	result sets associated with that connection.
	 */
	ret = (inst->module->sql_fetch_row)(out, *handle, inst->config);
	if (ret < 0) {
		ROPTIONAL(RERROR, ERROR, "Error fetching row");

		rlm_sql_print_error(inst, request, *handle, false);
	}

	return ret;
}
示例#4
0
/** Call the driver's sql_query method, reconnecting if necessary.
 *
 * @note Caller must call ``(inst->module->sql_finish_query)(handle, inst->config);``
 *	after they're done with the result.
 *
 * @param handle to query the database with. *handle should not be NULL, as this indicates
 * 	previous reconnection attempt has failed.
 * @param request Current request.
 * @param inst #rlm_sql_t instance data.
 * @param query to execute. Should not be zero length.
 * @return
 *	- #RLM_SQL_OK on success.
 *	- #RLM_SQL_RECONNECT if a new handle is required (also sets *handle = NULL).
 *	- #RLM_SQL_QUERY_INVALID, #RLM_SQL_ERROR on invalid query or connection error.
 *	- #RLM_SQL_ALT_QUERY on constraints violation.
 */
sql_rcode_t rlm_sql_query(rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t **handle, char const *query)
{
	int ret = RLM_SQL_ERROR;
	int i, count;

	/* Caller should check they have a valid handle */
	rad_assert(*handle);

	/* There's no query to run, return an error */
	if (query[0] == '\0') {
		if (request) REDEBUG("Zero length query");
		return RLM_SQL_QUERY_INVALID;
	}

	/*
	 *  inst->pool may be NULL is this function is called by mod_conn_create.
	 */
	count = inst->pool ? fr_connection_get_num(inst->pool) : 0;

	/*
	 *  Here we try with each of the existing connections, then try to create
	 *  a new connection, then give up.
	 */
	for (i = 0; i < (count + 1); i++) {
		ROPTIONAL(RDEBUG2, DEBUG2, "Executing query: %s", query);

		ret = (inst->module->sql_query)(*handle, inst->config, query);
		switch (ret) {
		case RLM_SQL_OK:
			break;

		/*
		 *	Run through all available sockets until we exhaust all existing
		 *	sockets in the pool and fail to establish a *new* connection.
		 */
		case RLM_SQL_RECONNECT:
			*handle = fr_connection_reconnect(inst->pool, *handle);
			/* Reconnection failed */
			if (!*handle) return RLM_SQL_RECONNECT;
			/* Reconnection succeeded, try again with the new handle */
			continue;

		/*
		 *	These are bad and should make rlm_sql return invalid
		 */
		case RLM_SQL_QUERY_INVALID:
			rlm_sql_print_error(inst, request, *handle, false);
			(inst->module->sql_finish_query)(*handle, inst->config);
			break;

		/*
		 *	Server or client errors.
		 *
		 *	If the driver claims to be able to distinguish between
		 *	duplicate row errors and other errors, and we hit a
		 *	general error treat it as a failure.
		 *
		 *	Otherwise rewrite it to RLM_SQL_ALT_QUERY.
		 */
		case RLM_SQL_ERROR:
			if (inst->module->flags & RLM_SQL_RCODE_FLAGS_ALT_QUERY) {
				rlm_sql_print_error(inst, request, *handle, false);
				(inst->module->sql_finish_query)(*handle, inst->config);
				break;
			}
			ret = RLM_SQL_ALT_QUERY;
			/* FALL-THROUGH */

		/*
		 *	Driver suggested using an alternative query
		 */
		case RLM_SQL_ALT_QUERY:
			rlm_sql_print_error(inst, request, *handle, true);
			(inst->module->sql_finish_query)(*handle, inst->config);
			break;

		}

		return ret;
	}

	ROPTIONAL(RERROR, ERROR, "Hit reconnection limit");

	return RLM_SQL_ERROR;
}