コード例 #1
0
ファイル: metadatastorage.cpp プロジェクト: nickman/Akumuli
std::vector<MetadataStorage::UntypedTuple> MetadataStorage::select_query(const char* query) const {
    std::vector<UntypedTuple> tuples;
    apr_dbd_results_t *results = nullptr;
    int status = apr_dbd_select(driver_, pool_.get(), handle_.get(), &results, query, 0);
    if (status != 0) {
        (*logger_)(AKU_LOG_ERROR, "Error executing query");
        throw std::runtime_error(apr_dbd_error(driver_, handle_.get(), status));
    }
    // get rows
    int ntuples = apr_dbd_num_tuples(driver_, results);
    int ncolumns = apr_dbd_num_cols(driver_, results);
    for (int i = ntuples; i --> 0;) {
        apr_dbd_row_t *row = nullptr;
        status = apr_dbd_get_row(driver_, pool_.get(), results, &row, -1);
        if (status != 0) {
            (*logger_)(AKU_LOG_ERROR, "Error getting row from resultset");
            throw std::runtime_error(apr_dbd_error(driver_, handle_.get(), status));
        }
        UntypedTuple tup;
        for (int col = 0; col < ncolumns; col++) {
            const char* entry = apr_dbd_get_entry(driver_, row, col);
            if (entry) {
                tup.emplace_back(entry);
            } else {
                tup.emplace_back();
            }
        }
        tuples.push_back(std::move(tup));
    }
    return tuples;
}
コード例 #2
0
ファイル: mod_authz_dbd.c プロジェクト: pexip/os-apache2
static int authz_dbd_group_query(request_rec *r, authz_dbd_cfg *cfg,
                                 apr_array_header_t *groups)
{
    /* SELECT group FROM authz WHERE user = %s */
    int rv;
    const char *message;
    ap_dbd_t *dbd;
    apr_dbd_prepared_t *query;
    apr_dbd_results_t *res = NULL;
    apr_dbd_row_t *row = NULL;

    if (cfg->query == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01649)
                      "No query configured for dbd-group!");
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    
    dbd = dbd_handle(r);
    if (dbd == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02903)
                      "No db handle available for dbd-query! "
                      "Check your database access");
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    query = apr_hash_get(dbd->prepared, cfg->query, APR_HASH_KEY_STRING);
    if (query == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01650)
                      "Error retrieving query for dbd-group!");
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    rv = apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res,
                          query, 0, r->user, NULL);
    if (rv == 0) {
        for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1);
             rv != -1;
             rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) {
            if (rv == 0) {
                APR_ARRAY_PUSH(groups, const char *) =
                    apr_pstrdup(r->pool,
                                apr_dbd_get_entry(dbd->driver, row, 0));
            }
            else {
                message = apr_dbd_error(dbd->driver, dbd->handle, rv);
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01651)
                        "authz_dbd in get_row; group query for user=%s [%s]",
                        r->user, message?message:noerror);
                return HTTP_INTERNAL_SERVER_ERROR;
            }
        }
    }
    else {
        message = apr_dbd_error(dbd->driver, dbd->handle, rv);
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01652)
                      "authz_dbd, in groups query for %s [%s]",
                      r->user, message?message:noerror);
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    return OK;
}
コード例 #3
0
ファイル: dbd.c プロジェクト: Ga-vin/apache
static int test_pquery(apr_pool_t* pool, apr_dbd_t* handle,
                       const apr_dbd_driver_t* driver)
{
    int rv = 0;
    const char *query = "INSERT INTO apr_dbd_test VALUES (%s, %s, %d)";
    apr_dbd_prepared_t *statement = NULL;
    const char *label = "testpquery";
    int nrows;
    apr_dbd_transaction_t *trans =0;

    rv = apr_dbd_prepare(driver, pool, handle, query, label, &statement);
    /* rv = apr_dbd_prepare(driver, pool, handle, query, NULL, &statement); */
    if (rv) {
        printf("Prepare statement failed!\n%s\n",
               apr_dbd_error(driver, handle, rv));
        return rv;
    }
    apr_dbd_transaction_start(driver, pool, handle, &trans);
    rv = apr_dbd_pvquery(driver, pool, handle, &nrows, statement,
                         "prepared", "insert", "2", NULL);
    apr_dbd_transaction_end(driver, pool, trans);
    if (rv) {
        printf("Exec of prepared statement failed!\n%s\n",
               apr_dbd_error(driver, handle, rv));
        return rv;
    }
    printf("Showing table (should now contain row \"prepared insert 2\")\n");
    select_sequential(pool, handle, driver);
    return rv;
}
コード例 #4
0
ファイル: dbd.c プロジェクト: Ga-vin/apache
static int select_random(apr_pool_t* pool, apr_dbd_t* handle,
                         const apr_dbd_driver_t* driver)
{
    int rv = 0;
    int n;
    const char* entry;
    const char* statement = "SELECT * FROM apr_dbd_test ORDER BY col1, col2";
    apr_dbd_results_t *res = NULL;
    apr_dbd_row_t *row = NULL;
    rv = apr_dbd_select(driver,pool,handle,&res,statement,1);
    if (rv) {
        printf("Select failed: %s", apr_dbd_error(driver, handle, rv));
        return rv;
    }
    rv = apr_dbd_get_row(driver, pool, res, &row, 5) ;
    if (rv) {
        printf("get_row failed: %s", apr_dbd_error(driver, handle, rv));
        return rv;
    }
    printf("ROW 5:	");
    for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
        entry = apr_dbd_get_entry(driver, row, n);
        if (entry == NULL) {
            printf("(null)	") ;
        }
        else {
            printf("%s	", entry);
        }
    }
    fputs("\n", stdout);
    rv = apr_dbd_get_row(driver, pool, res, &row, 1) ;
    if (rv) {
        printf("get_row failed: %s", apr_dbd_error(driver, handle, rv));
        return rv;
    }
    printf("ROW 1:	");
    for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
        entry = apr_dbd_get_entry(driver, row, n);
        if (entry == NULL) {
            printf("(null)	") ;
        }
        else {
            printf("%s	", entry);
        }
    }
    fputs("\n", stdout);
    rv = apr_dbd_get_row(driver, pool, res, &row, 11) ;
    if (rv != -1) {
        printf("Oops!  get_row out of range but thinks it succeeded!\n%s\n",
                apr_dbd_error(driver, handle, rv));
        return -1;
    }
    rv = 0;

    return rv;
}
コード例 #5
0
ファイル: mod_session_dbd.c プロジェクト: Aimbot2/apache2
/**
 * Load the session by the key specified.
 */
static apr_status_t dbd_load(request_rec * r, const char *key, const char **val)
{

    apr_status_t rv;
    ap_dbd_t *dbd = NULL;
    apr_dbd_prepared_t *statement = NULL;
    apr_dbd_results_t *res = NULL;
    apr_dbd_row_t *row = NULL;
    apr_int64_t expiry = (apr_int64_t) apr_time_now();

    session_dbd_dir_conf *conf = ap_get_module_config(r->per_dir_config,
                                                      &session_dbd_module);

    if (conf->selectlabel == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01853)
                      "no SessionDBDselectlabel has been specified");
        return APR_EGENERAL;
    }

    rv = dbd_init(r, conf->selectlabel, &dbd, &statement);
    if (rv) {
        return rv;
    }
    rv = apr_dbd_pvbselect(dbd->driver, r->pool, dbd->handle, &res, statement,
                          0, key, &expiry, NULL);
    if (rv) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01854)
                      "query execution error saving session '%s' "
                      "in database using query '%s': %s", key, conf->selectlabel,
                      apr_dbd_error(dbd->driver, dbd->handle, rv));
        return APR_EGENERAL;
    }
    for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1);
         rv != -1;
         rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) {
        if (rv != 0) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01855)
                          "error retrieving results while saving '%s' "
                          "in database using query '%s': %s", key, conf->selectlabel,
                           apr_dbd_error(dbd->driver, dbd->handle, rv));
            return APR_EGENERAL;
        }
        if (*val == NULL) {
            *val = apr_dbd_get_entry(dbd->driver, row, 0);
        }
        /* we can't break out here or row won't get cleaned up */
    }

    return APR_SUCCESS;

}
コード例 #6
0
ファイル: lua_dbd.c プロジェクト: Aimbot2/apache2
/*
   =============================================================================
    db:query(statement): Executes the given database query and returns the 
    number of rows affected. If an error is encountered, returns nil as the 
    first parameter and the error message as the second.
   =============================================================================
 */
int lua_db_query(lua_State *L)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~*/
    lua_db_handle   *db = 0;
    apr_status_t     rc = 0;
    int              x = 0;
    const char      *statement;
    /*~~~~~~~~~~~~~~~~~~~~~~~*/
    luaL_checktype(L, 3, LUA_TSTRING);
    statement = lua_tostring(L, 3);
    db = lua_get_db_handle(L);
    if (db && db->alive)
        rc = apr_dbd_query(db->driver, db->handle, &x, statement);
    else {
        rc = 0;
        x = -1;
    }

    if (rc == APR_SUCCESS)
        lua_pushnumber(L, x);
    else {

        /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
        const char  *err = apr_dbd_error(db->driver, db->handle, rc);
        /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

        lua_pushnil(L);
        if (err) {
            lua_pushstring(L, err);
            return 2;
        }
    }

    return 1;
}
コード例 #7
0
ファイル: dbd.c プロジェクト: Ga-vin/apache
static int select_sequential(apr_pool_t* pool, apr_dbd_t* handle,
                             const apr_dbd_driver_t* driver)
{
    int rv = 0;
    int i = 0;
    int n;
    const char* entry;
    const char* statement = "SELECT * FROM apr_dbd_test ORDER BY col1, col2";
    apr_dbd_results_t *res = NULL;
    apr_dbd_row_t *row = NULL;
    rv = apr_dbd_select(driver,pool,handle,&res,statement,0);
    if (rv) {
        printf("Select failed: %s", apr_dbd_error(driver, handle, rv));
        return rv;
    }
    for (rv = apr_dbd_get_row(driver, pool, res, &row, -1);
         rv == 0;
         rv = apr_dbd_get_row(driver, pool, res, &row, -1)) {
        printf("ROW %d:	", ++i) ;
        for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
            entry = apr_dbd_get_entry(driver, row, n);
            if (entry == NULL) {
                printf("(null)	") ;
            }
            else {
                printf("%s	", entry);
            }
        }
	fputs("\n", stdout);
    }
    return (rv == -1) ? 0 : 1;
}
コード例 #8
0
ファイル: dbd.c プロジェクト: Ga-vin/apache
static int test_pselect(apr_pool_t* pool, apr_dbd_t* handle,
                        const apr_dbd_driver_t* driver)
{
    int rv = 0;
    int i, n;
    const char *query =
        "SELECT * FROM apr_dbd_test WHERE col3 <= %s or col1 = 'bar'" ;
    const char *label = "lowvalues";
    apr_dbd_prepared_t *statement = NULL;
    apr_dbd_results_t *res = NULL;
    apr_dbd_row_t *row = NULL;
    const char *entry = NULL;

    rv = apr_dbd_prepare(driver, pool, handle, query, label, &statement);
    if (rv) {
        printf("Prepare statement failed!\n%s\n",
               apr_dbd_error(driver, handle, rv));
        return rv;
    }
    rv = apr_dbd_pvselect(driver, pool, handle, &res, statement, 0, "3", NULL);
    if (rv) {
        printf("Exec of prepared statement failed!\n%s\n",
               apr_dbd_error(driver, handle, rv));
        return rv;
    }
    i = 0;
    printf("Selecting rows where col3 <= 3 and bar row where it's unset.\nShould show four rows.\n");
    for (rv = apr_dbd_get_row(driver, pool, res, &row, -1);
         rv == 0;
         rv = apr_dbd_get_row(driver, pool, res, &row, -1)) {
        printf("ROW %d:	", ++i) ;
        for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
            entry = apr_dbd_get_entry(driver, row, n);
            if (entry == NULL) {
                printf("(null)	") ;
            }
            else {
                printf("%s	", entry);
            }
        }
	fputs("\n", stdout);
    }
    return (rv == -1) ? 0 : 1;
}
コード例 #9
0
ファイル: metadatastorage.cpp プロジェクト: nickman/Akumuli
int MetadataStorage::execute_query(std::string query) {
    int nrows = -1;
    int status = apr_dbd_query(driver_, handle_.get(), &nrows, query.c_str());
    if (status != 0 && status != 21) {
        // generate error and throw
        (*logger_)(AKU_LOG_ERROR, "Error executing query");
        throw std::runtime_error(apr_dbd_error(driver_, handle_.get(), status));
    }
    return nrows;
}
コード例 #10
0
ファイル: views.c プロジェクト: takev/mod_okioki
int mod_okioki_view_execute(request_rec *http_request, mod_okioki_dir_config *cfg, view_t *view, apr_hash_t *arguments, const apr_dbd_driver_t **db_driver, apr_dbd_results_t **db_result, char **error)
{
    apr_pool_t         *pool = http_request->pool;
    ap_dbd_t           *db_conn;
    apr_dbd_prepared_t *db_statement;
    char               *arg;
    int                argc = view->nr_sql_params;
    char               *argv[argc + 1];
    off_t              i;
    int                ret;

    // Copy the pointers parameters in the right order for the SQL statement.
    for (i = 0; i < argc; i++) {
        ASSERT_NOT_NULL(
            arg = (char *)apr_hash_get(arguments, view->sql_params[i], view->sql_params_len[i]),
            HTTP_INTERNAL_SERVER_ERROR, "Could not find parameter '%s' in request.", view->sql_params[i]
        )

        argv[i] = arg;
    }
    argv[i] = NULL;

    // Retrieve a database connection from the resource pool.
    ASSERT_NOT_NULL(
        db_conn = ap_dbd_acquire(http_request),
        HTTP_INTERNAL_SERVER_ERROR, "Can not get database connection."
    )
    *db_driver = db_conn->driver;

    // Get the prepared statement.
    ASSERT_NOT_NULL(
        db_statement = apr_hash_get((db_conn)->prepared, view->sql, view->sql_len),
        HTTP_INTERNAL_SERVER_ERROR, "Can not find '%s'", view->sql
    )

    // Execute the statement.
    *db_result = NULL;

    // Execute a select statement. We allow random access here as it allows easier configuration because the number
    // of columns and the name of the columns are known when random access is enabled.
    // Also because we use buckets and brigades everything is done in memory already, so streaming data would not
    // have worked anyway.
    ASSERT_APR_SUCCESS(
        ret = apr_dbd_pselect(db_conn->driver, db_conn->pool, db_conn->handle, db_result, db_statement, 1, argc, (const char **)argv),
        HTTP_BAD_GATEWAY, "%s", apr_dbd_error(db_conn->driver, db_conn->handle, ret)
    )

    ASSERT_NOT_NULL(
        *db_result,
        HTTP_BAD_GATEWAY, "Result was not set by apr_dbd_pselect."
    )
    return HTTP_OK;
}
コード例 #11
0
ファイル: dbd.c プロジェクト: Ga-vin/apache
static int invalid_op(apr_pool_t* pool, apr_dbd_t* handle,
                      const apr_dbd_driver_t* driver)
{
    int rv = 0;
    int nrows;
    const char *statement = "INSERT into apr_dbd_test1 (col2) values ('foo')" ;
    rv = apr_dbd_query(driver, handle, &nrows, statement);
    printf("invalid op returned %d (should be nonzero).  Error msg follows\n", rv);
    printf("'%s'\n", apr_dbd_error(driver, handle, rv));
    statement = "INSERT into apr_dbd_test (col1, col2) values ('bar', 'foo')" ;
    rv = apr_dbd_query(driver, handle, &nrows, statement);
    printf("valid op returned %d (should be zero; error shouldn't affect subsequent ops)\n", rv);
    return rv;
}
コード例 #12
0
ファイル: metadatastorage.cpp プロジェクト: nickman/Akumuli
MetadataStorage::MetadataStorage(const char* db, aku_logger_cb_t logger)
    : pool_(nullptr, &delete_apr_pool)
    , driver_(nullptr)
    , handle_(nullptr, AprHandleDeleter(nullptr))
    , logger_(logger)
{
    apr_pool_t *pool = nullptr;
    auto status = apr_pool_create(&pool, NULL);
    if (status != APR_SUCCESS) {
        // report error (can't return error from c-tor)
        throw std::runtime_error("Can't create memory pool");
    }
    pool_.reset(pool);

    status = apr_dbd_get_driver(pool, "sqlite3", &driver_);
    if (status != APR_SUCCESS) {
        (*logger_)(AKU_LOG_ERROR, "Can't load driver, maybe libaprutil1-dbd-sqlite3 isn't installed");
        throw std::runtime_error("Can't load sqlite3 dirver");
    }

    apr_dbd_t *handle = nullptr;
    status = apr_dbd_open(driver_, pool, db, &handle);
    if (status != APR_SUCCESS) {
        (*logger_)(AKU_LOG_ERROR, "Can't open database, check file path");
        throw std::runtime_error("Can't open database");
    }
    handle_ = HandleT(handle, AprHandleDeleter(driver_));

    auto sqlite_handle = apr_dbd_native_handle(driver_, handle);
    sqlite3_trace((sqlite3*)sqlite_handle, callback_adapter, (void*)logger_);

    create_tables();

    // Create prepared statement
    const char* query = "INSERT INTO akumuli_series (series_id, keyslist, storage_id) VALUES (%s, %s, %d)";
    status = apr_dbd_prepare(driver_, pool_.get(), handle_.get(), query, "INSERT_SERIES_NAME", &insert_);
    if (status != 0) {
        (*logger_)(AKU_LOG_ERROR, "Error creating prepared statement");
        throw std::runtime_error(apr_dbd_error(driver_, handle_.get(), status));
    }
}
コード例 #13
0
ファイル: apr_dbd.c プロジェクト: cookrn/openamq
APU_DECLARE(apr_status_t) apr_dbd_open_ex(const apr_dbd_driver_t *driver,
                                          apr_pool_t *pool, const char *params,
                                          apr_dbd_t **handle,
                                          const char **error)
{
    apr_status_t rv;
    *handle = (driver->open)(pool, params, error);
    if (*handle == NULL) {
        return APR_EGENERAL;
    }
    rv = apr_dbd_check_conn(driver, pool, *handle);
    if ((rv != APR_SUCCESS) && (rv != APR_ENOTIMPL)) {
        /* XXX: rv is APR error code, but apr_dbd_error() takes int! */
        if (error) {
            *error = apr_dbd_error(driver, *handle, rv);
        }
        apr_dbd_close(driver, *handle);
        return APR_EGENERAL;
    }
    return APR_SUCCESS;
}
コード例 #14
0
/* Run an insert query and return a categorized error or success */
static logsql_query_ret log_sql_dbd_query(request_rec *r,logsql_dbconnection *db,
								const char *query)
{
	int ret;
	const char *err;
	int affected;
	// Acquire a DBD connection from mod_dbd
	ap_dbd_t *dbd = log_sql_dbd_getconnection(r);
	if (!dbd) return LOGSQL_QUERY_NOLINK;

	// Run the query
	ret = apr_dbd_query(dbd->driver, dbd->handle, &affected, query);
	if (ret == 0) {
		return LOGSQL_QUERY_SUCCESS;
	} else {
		// attempt to detect error message
		err = apr_dbd_error(dbd->driver, dbd->handle, ret);
		log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "DB Returned error: (%d) %s", ret, err);
		// Unable to check if "NO SUCH TABLE" due to apr_dbd not mapping error codes to a standard set.
		return LOGSQL_QUERY_FAIL;
	}
}
コード例 #15
0
ファイル: lua_dbd.c プロジェクト: Aimbot2/apache2
/*
   =============================================================================
    statement:query(var1, var2, var3...): Injects variables into a prepared 
    statement and returns the number of rows affected.
   =============================================================================
 */
int lua_db_prepared_query(lua_State *L)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    lua_db_prepared_statement  *st = 0;
    apr_status_t     rc = 0;
    const char       **vars;
    int              x, have;
    /*~~~~~~~~~~~~~~~~~~~~~~~*/
    
    /* Fetch the prepared statement and the vars passed */
    luaL_checktype(L, 1, LUA_TTABLE);
    lua_rawgeti(L, 1, 0);
    luaL_checktype(L, -1, LUA_TUSERDATA);
    st = (lua_db_prepared_statement*) lua_topointer(L, -1);
    
    /* Check if we got enough variables passed on to us.
     * This, of course, only works for prepped statements made through lua. */
    have = lua_gettop(L) - 2;
    if (st->variables != -1 && have < st->variables ) {
        lua_pushboolean(L, 0);
        lua_pushfstring(L, 
                "Error in executing prepared statement: Expected %d arguments, got %d.", 
                st->variables, have);
        return 2;
    }
    vars = apr_pcalloc(st->db->pool, have*sizeof(char *));
    for (x = 0; x < have; x++) {
        vars[x] = lua_tostring(L, x + 2);
    }

    /* Fire off the query */
    if (st->db && st->db->alive) {

        /*~~~~~~~~~~~~~~*/
        int affected = 0;
        /*~~~~~~~~~~~~~~*/

        rc = apr_dbd_pquery(st->db->driver, st->db->pool, st->db->handle,
                                &affected, st->statement, have, vars);
        if (rc == APR_SUCCESS) {
            lua_pushinteger(L, affected);
            return 1;
        }
        else {

            /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
            const char  *err = apr_dbd_error(st->db->driver, st->db->handle, rc);
            /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

            lua_pushnil(L);
            if (err) {
                lua_pushstring(L, err);
                return 2;
            }
            return 1;
        }
    }

    lua_pushboolean(L, 0);
    lua_pushliteral(L, 
            "Database connection seems to be closed, please reacquire it.");
    return (2);
}
コード例 #16
0
ファイル: lua_dbd.c プロジェクト: Aimbot2/apache2
/*
   =============================================================================
    statement:select(var1, var2, var3...): Injects variables into a prepared 
    statement and returns the number of rows matching the query.
   =============================================================================
 */
int lua_db_prepared_select(lua_State *L)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    lua_db_prepared_statement  *st = 0;
    apr_status_t     rc = 0;
    const char       **vars;
    int              x, have;
    /*~~~~~~~~~~~~~~~~~~~~~~~*/
    
    /* Fetch the prepared statement and the vars passed */
    luaL_checktype(L, 1, LUA_TTABLE);
    lua_rawgeti(L, 1, 0);
    luaL_checktype(L, -1, LUA_TUSERDATA);
    st = (lua_db_prepared_statement*) lua_topointer(L, -1);
    
    /* Check if we got enough variables passed on to us.
     * This, of course, only works for prepped statements made through lua. */
    have = lua_gettop(L) - 2;
    if (st->variables != -1 && have < st->variables ) {
        lua_pushboolean(L, 0);
        lua_pushfstring(L, 
                "Error in executing prepared statement: Expected %d arguments, got %d.", 
                st->variables, have);
        return 2;
    }
    vars = apr_pcalloc(st->db->pool, have*sizeof(char *));
    for (x = 0; x < have; x++) {
        vars[x] = lua_tostring(L, x + 2);
    }

    /* Fire off the query */
    if (st->db && st->db->alive) {

        /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
        int cols;
        apr_dbd_results_t   *results = 0;
        /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

        rc = apr_dbd_pselect(st->db->driver, st->db->pool, st->db->handle,
                                &results, st->statement, 0, have, vars);
        if (rc == APR_SUCCESS) {

            /*~~~~~~~~~~~~~~~~~~~~~*/
            lua_db_result_set *resultset;
            /*~~~~~~~~~~~~~~~~~~~~~*/

            cols = apr_dbd_num_cols(st->db->driver, results);
            lua_newtable(L);
            resultset = lua_newuserdata(L, sizeof(lua_db_result_set));
            resultset->cols = cols;
            resultset->driver = st->db->driver;
            resultset->pool = st->db->pool;
            resultset->rows = apr_dbd_num_tuples(st->db->driver, results);
            resultset->results = results;
            luaL_newmetatable(L, "lua_apr.dbselect");
            lua_pushliteral(L, "__call");
            lua_pushcfunction(L, lua_db_get_row);
            lua_rawset(L, -3);
            lua_setmetatable(L, -3);
            lua_rawseti(L, -2, 0);
            return 1;
            
        }
        else {

            /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
            const char  *err = apr_dbd_error(st->db->driver, st->db->handle, rc);
            /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

            lua_pushnil(L);
            if (err) {
                lua_pushstring(L, err);
                return 2;
            }
            return 1;
        }
    }

    lua_pushboolean(L, 0);
    lua_pushliteral(L, 
            "Database connection seems to be closed, please reacquire it.");
    return (2);
}
コード例 #17
0
ファイル: lua_dbd.c プロジェクト: Aimbot2/apache2
/*
   =============================================================================
    db:select(statement): Queries the database for the given statement and 
    returns the rows/columns found as a table. If an error is encountered, 
    returns nil as the first parameter and the error message as the second.
   =============================================================================
 */
int lua_db_select(lua_State *L)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~*/
    lua_db_handle   *db = 0;
    apr_status_t     rc = 0;
    const char      *statement;
    request_rec     *r;
    /*~~~~~~~~~~~~~~~~~~~~~~~*/
    r = ap_lua_check_request_rec(L, 2);
    if (r) {
        luaL_checktype(L, 3, LUA_TSTRING);
        statement = lua_tostring(L, 3);
        db = lua_get_db_handle(L);
        if (db && db->alive) {

            /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
            int cols;
            apr_dbd_results_t   *results = 0;
            lua_db_result_set* resultset = NULL;
            /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

            rc = apr_dbd_select(db->driver, db->pool, db->handle,
                                &results, statement, 0);
            if (rc == APR_SUCCESS) {
                
                cols = apr_dbd_num_cols(db->driver, results);
                
                if (cols > 0) {
                    lua_newtable(L);
                    resultset = lua_newuserdata(L, sizeof(lua_db_result_set));
                    resultset->cols = cols;
                    resultset->driver = db->driver;
                    resultset->pool = db->pool;
                    resultset->rows = apr_dbd_num_tuples(db->driver, results);
                    resultset->results = results;
                    luaL_newmetatable(L, "lua_apr.dbselect");
                    lua_pushliteral(L, "__call");
                    lua_pushcfunction(L, lua_db_get_row);
                    lua_rawset(L, -3);
                    lua_setmetatable(L, -3);
                    lua_rawseti(L, -2, 0);
                    return 1;
                }
                return 0;
            }
            else {

                /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
                const char  *err = apr_dbd_error(db->driver, db->handle, rc);
                /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

                lua_pushnil(L);
                if (err) {
                    lua_pushstring(L, err);
                    return 2;
                }
            }
        }

        lua_pushboolean(L, 0);
        return 1;
    }

    return 0;
}
コード例 #18
0
ファイル: mod_session_dbd.c プロジェクト: Aimbot2/apache2
/**
 * Save the session by the key specified.
 */
static apr_status_t dbd_save(request_rec * r, const char *key, const char *val,
                             apr_int64_t expiry)
{

    apr_status_t rv;
    ap_dbd_t *dbd = NULL;
    apr_dbd_prepared_t *statement;
    int rows = 0;

    session_dbd_dir_conf *conf = ap_get_module_config(r->per_dir_config,
                                                      &session_dbd_module);

    if (conf->updatelabel == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01856)
                      "no SessionDBDupdatelabel has been specified");
        return APR_EGENERAL;
    }

    rv = dbd_init(r, conf->updatelabel, &dbd, &statement);
    if (rv) {
        return rv;
    }
    rv = apr_dbd_pvbquery(dbd->driver, r->pool, dbd->handle, &rows, statement,
                          val, &expiry, key, NULL);
    if (rv) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01857)
                      "query execution error updating session '%s' "
                      "using database query '%s': %s", key, conf->updatelabel,
                      apr_dbd_error(dbd->driver, dbd->handle, rv));
        return APR_EGENERAL;
    }

    /*
     * if some rows were updated it means a session existed and was updated,
     * so we are done.
     */
    if (rows != 0) {
        return APR_SUCCESS;
    }

    if (conf->insertlabel == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01858)
                      "no SessionDBDinsertlabel has been specified");
        return APR_EGENERAL;
    }

    rv = dbd_init(r, conf->insertlabel, &dbd, &statement);
    if (rv) {
        return rv;
    }
    rv = apr_dbd_pvbquery(dbd->driver, r->pool, dbd->handle, &rows, statement,
                          val, &expiry, key, NULL);
    if (rv) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01859)
                      "query execution error inserting session '%s' "
                      "in database with '%s': %s", key, conf->insertlabel,
                      apr_dbd_error(dbd->driver, dbd->handle, rv));
        return APR_EGENERAL;
    }

    /*
     * if some rows were inserted it means a session was inserted, so we are
     * done.
     */
    if (rows != 0) {
        return APR_SUCCESS;
    }

    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01860)
                  "the session insert query did not cause any rows to be added "
                  "to the database for session '%s', session not inserted", key);

    return APR_EGENERAL;

}
コード例 #19
0
ファイル: mod_authz_dbd.c プロジェクト: pexip/os-apache2
static int authz_dbd_login(request_rec *r, authz_dbd_cfg *cfg,
                           const char *action)
{
    int rv;
    const char *newuri = NULL;
    int nrows;
    const char *message;
    ap_dbd_t *dbd;
    apr_dbd_prepared_t *query;
    apr_dbd_results_t *res = NULL;
    apr_dbd_row_t *row = NULL;

    if (cfg->query == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01642)
                      "No query configured for %s!", action);
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    
    dbd = dbd_handle(r);
    if (dbd == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02902)
                      "No db handle available for %s! "
                      "Check your database access",
                      action);
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    query = apr_hash_get(dbd->prepared, cfg->query, APR_HASH_KEY_STRING);
    if (query == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01643)
                      "Error retrieving Query for %s!", action);
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    rv = apr_dbd_pvquery(dbd->driver, r->pool, dbd->handle, &nrows,
                         query, r->user, NULL);
    if (rv == 0) {
        if (nrows != 1) {
            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01644)
                          "authz_dbd: %s of user %s updated %d rows",
                          action, r->user, nrows);
        }
    }
    else {
        message = apr_dbd_error(dbd->driver, dbd->handle, rv);
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01645)
                      "authz_dbd: query for %s failed; user %s [%s]",
                      action, r->user, message?message:noerror);
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    if (cfg->redirect == 1) {
        newuri = apr_table_get(r->headers_in, "Referer");
    }

    if (!newuri && cfg->redir_query) {
        query = apr_hash_get(dbd->prepared, cfg->redir_query,
                             APR_HASH_KEY_STRING);
        if (query == NULL) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01646)
                          "authz_dbd: no redirect query!");
            /* OK, this is non-critical; we can just not-redirect */
        }
        else if ((rv = apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle,
                                        &res, query, 0, r->user, NULL)) == 0) {
            for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1);
                 rv != -1;
                 rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) {
                if (rv != 0) {
                    message = apr_dbd_error(dbd->driver, dbd->handle, rv);
                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01647)
                          "authz_dbd in get_row; action=%s user=%s [%s]",
                          action, r->user, message?message:noerror);
                }
                else if (newuri == NULL) {
                    newuri =
                        apr_pstrdup(r->pool,
                                    apr_dbd_get_entry(dbd->driver, row, 0));
                }
                /* we can't break out here or row won't get cleaned up */
            }
        }
        else {
            message = apr_dbd_error(dbd->driver, dbd->handle, rv);
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01648)
                          "authz_dbd/redirect for %s of %s [%s]",
                          action, r->user, message?message:noerror);
        }
    }
    if (newuri != NULL) {
        r->status = HTTP_MOVED_TEMPORARILY;
        apr_table_set(r->err_headers_out, "Location", newuri);
    }
    authz_dbd_run_client_login(r, OK, action);
    return OK;
}
コード例 #20
0
static int authz_dbd_query(request_rec *r, authz_dbd_cfg *cfg,
			   const apr_array_header_t *query_parameters,
			   apr_array_header_t *query_result_rows)
{
    /* SELECT group FROM authz WHERE col = %s, col = %s, ... */
    int rv;
    const char *message;
    ap_dbd_t *dbd = dbd_handle(r);
    apr_dbd_prepared_t *query;
    apr_dbd_results_t *res = NULL;
    apr_dbd_row_t *row = NULL;
    const char **query_result_row;

    if (cfg->query == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO()
                      "No query configured for dbd-query!");
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    if (dbd == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO()
                      "No db handle available for dbd-query! Check your database access");
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    query = apr_hash_get(dbd->prepared, cfg->query, APR_HASH_KEY_STRING);
    if (query == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO()
                      "Error retrieving query for dbd-query!");
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    rv = apr_dbd_pselect(dbd->driver, r->pool, dbd->handle, &res,
			 query, 0, 
			 query_parameters->nelts,
			 (const char **)query_parameters->elts);

    if (rv == 0) {
        for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1);
             rv != -1;
             rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) {
            if (rv == 0) {
                query_result_row = apr_array_push(query_result_rows);
                *query_result_row = apr_dbd_get_entry(dbd->driver, row, 0);
            }
            else {
                message = apr_dbd_error(dbd->driver, dbd->handle, rv);
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO()
                              "authz_dbd dbd_query in get_row; query for user=%s [%s]",
                              r->user, message?message:noerror);
                return HTTP_INTERNAL_SERVER_ERROR;
            }
        }
    }
    else {
        message = apr_dbd_error(dbd->driver, dbd->handle, rv);
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO()
                      "authz_dbd, in dbd_query query for %s [%s]",
                      r->user, message?message:noerror);
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    return OK;
}
コード例 #21
0
ファイル: lua_dbd.c プロジェクト: Aimbot2/apache2
/*
   =============================================================================
    db:prepare(statement): Prepares a statement for later query/select.
    Returns a table with a :query and :select function, same as the db funcs.
   =============================================================================
 */
int lua_db_prepare(lua_State* L) 
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    lua_db_handle   *db = 0;
    apr_status_t     rc = 0;
    const char      *statement, *at;
    request_rec     *r;
    lua_db_prepared_statement* st;
    int need = 0;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    
    r = ap_lua_check_request_rec(L, 2);
    if (r) {
        apr_dbd_prepared_t *pstatement = NULL;
        luaL_checktype(L, 3, LUA_TSTRING);
        statement = lua_tostring(L, 3);
        
        /* Count number of variables in statement */
        at = ap_strchr_c(statement,'%');
        while (at != NULL) {
            if (at[1] == '%') {
                at++;
            }
            else {
                need++;
            }
            at = ap_strchr_c(at+1,'%');
        }
        
        
        db = lua_get_db_handle(L);
        rc = apr_dbd_prepare(db->driver, r->pool, db->handle, statement, 
                    NULL, &pstatement);
        if (rc != APR_SUCCESS) {
            /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
            const char  *err = apr_dbd_error(db->driver, db->handle, rc);
            /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

            lua_pushnil(L);
            if (err) {
                lua_pushstring(L, err);
                return 2;
            }
            return 1;
        }
        
        /* Push the prepared statement table */
        lua_newtable(L);
        st = lua_newuserdata(L, sizeof(lua_db_prepared_statement));
        st->statement = pstatement;
        st->variables = need;
        st->db = db;
        
        lua_pushliteral(L, "select");
        lua_pushcfunction(L, lua_db_prepared_select);
        lua_rawset(L, -4);
        lua_pushliteral(L, "query");
        lua_pushcfunction(L, lua_db_prepared_query);
        lua_rawset(L, -4);
        lua_rawseti(L, -2, 0);
        return 1;
    }
    return 0;
}
コード例 #22
0
ファイル: dbd.c プロジェクト: Ga-vin/apache
static int test_transactions(apr_pool_t* pool, apr_dbd_t* handle,
                             const apr_dbd_driver_t* driver)
{
    int rv = 0;
    int nrows;
    apr_dbd_transaction_t *trans = NULL;
    const char* statement;

    /* trans 1 - error out early */
    printf("Transaction 1\n");
    rv = apr_dbd_transaction_start(driver, pool, handle, &trans);
    if (rv) {
        printf("Start transaction failed!\n%s\n",
               apr_dbd_error(driver, handle, rv));
        return rv;
    }
    statement = "UPDATE apr_dbd_test SET col2 = 'failed'";
    rv = apr_dbd_query(driver, handle, &nrows, statement);
    if (rv) {
        printf("Update failed: '%s'\n", apr_dbd_error(driver, handle, rv));
        apr_dbd_transaction_end(driver, pool, trans);
        return rv;
    }
    printf("%d rows updated\n", nrows);

    statement = "INSERT INTO apr_dbd_test1 (col3) values (3)";
    rv = apr_dbd_query(driver, handle, &nrows, statement);
    if (!rv) {
        printf("Oops, invalid op succeeded but shouldn't!\n");
    }
    statement = "INSERT INTO apr_dbd_test values ('zzz', 'aaa', 3)";
    rv = apr_dbd_query(driver, handle, &nrows, statement);
    printf("Valid insert returned %d.  Should be nonzero (fail) because transaction is bad\n", rv) ;

    rv = apr_dbd_transaction_end(driver, pool, trans);
    if (rv) {
        printf("End transaction failed!\n%s\n",
               apr_dbd_error(driver, handle, rv));
        return rv;
    }
    printf("Transaction ended (should be rollback) - viewing table\n"
           "A column of \"failed\" indicates transaction failed (no rollback)\n");
    select_sequential(pool, handle, driver);

    /* trans 2 - complete successfully */
    printf("Transaction 2\n");
    rv = apr_dbd_transaction_start(driver, pool, handle, &trans);
    if (rv) {
        printf("Start transaction failed!\n%s\n",
               apr_dbd_error(driver, handle, rv));
        return rv;
    }
    statement = "UPDATE apr_dbd_test SET col2 = 'success'";
    rv = apr_dbd_query(driver, handle, &nrows, statement);
    if (rv) {
        printf("Update failed: '%s'\n", apr_dbd_error(driver, handle, rv));
        apr_dbd_transaction_end(driver, pool, trans);
        return rv;
    }
    printf("%d rows updated\n", nrows);
    statement = "INSERT INTO apr_dbd_test values ('aaa', 'zzz', 3)";
    rv = apr_dbd_query(driver, handle, &nrows, statement);
    printf("Valid insert returned %d.  Should be zero (OK)\n", rv) ;
    rv = apr_dbd_transaction_end(driver, pool, trans);
    if (rv) {
        printf("End transaction failed!\n%s\n",
               apr_dbd_error(driver, handle, rv));
        return rv;
    }
    printf("Transaction ended (should be commit) - viewing table\n");
    select_sequential(pool, handle, driver);
    return rv;
}
コード例 #23
0
ファイル: dir_sync.c プロジェクト: soda0289/mod_MP
void * APR_THREAD_FUNC sync_dir(apr_thread_t* thread, void* ptr){
	int files_synced = 0;
	int status;
	apr_status_t rv;
	const char* dbd_error;
	List* file_list;

	music_file* song;

	dir_sync_thread_t* dir_sync = (dir_sync_thread_t*) ptr;
	apr_pool_t* pool;
	
	db_config_t* db_config = dir_sync->db_config;
	char error_message[256];

	//Create sub pool used for sync
	rv = apr_pool_create_ex(&pool, dir_sync->pool, NULL, NULL);
	if(rv != APR_SUCCESS){
		error_messages_add(dir_sync->error_messages, ERROR ,"Memory Pool Error", apr_strerror(rv, error_message, sizeof(error_message)));
		return 0;
	}

	file_list = apr_pcalloc(pool, sizeof(List));
	dir_sync->dir->stats->num_files = apr_pcalloc(pool, sizeof(int));

	if(db_config->connected != 1){
		error_messages_add(dir_sync->error_messages, ERROR, "Database not connected","ERROR ERROR");
		return 0;
	}

	count_table_rows();


	read_dir(pool, file_list, dir_sync->dir->path, dir_sync->dir->stats->num_files,  dir_sync->error_messages);

	if ((file_list == NULL || dir_sync->dir->stats->num_files == NULL )&& (*dir_sync->dir->stats->num_files ) > 0 ){
		error_messages_add(dir_sync->error_messages, ERROR, "Killing Sync Thread", "");
		return 0;
	}

	status = apr_dbd_transaction_start(db_config->dbd_driver, pool, db_config->dbd_handle,&(db_config->transaction));
	if(status != 0){
		dbd_error = apr_dbd_error(db_config->dbd_driver, db_config->dbd_handle, status);
		error_messages_add(dir_sync->error_messages,ERROR, "Database error start transaction", dbd_error);
		return 0;
	}
	while(file_list->file.path){
		  song = apr_pcalloc(pool, sizeof(music_file));
		  song->file = &(file_list->file);
		  switch(song->file->type){
#ifdef WITH_FLAC
		  	  case FLAC:{
		  		status = read_flac_level1(pool, song);
		  		if (status == 0){
		  			song->file->type_string = "flac";
		  		}
		  		break;
		  	  }
#endif
#ifdef WITH_OGG
		  	  case OGG:{
		  		status = read_ogg(pool, song);
		  		if (status == 0){
		  			song->file->type_string = "ogg";
		  		}
		  		break;
		  	  }
#endif
#ifdef WITH_MP3
		  	  case MP3:{
		  		  status = read_id3(pool,song);
			  	if (status == 0){
			  		song->file->type_string = "mp3";
			  	}
			  	break;
		  	  }
#endif
		  	 default:{
		  		  status = -1;
		  		  break;
		  	  }
		  }



		  if (status == 0 && song){
			  //We have song get musicbrainz ids
			  //status = get_musicbrainz_release_id(pool, song, dir_sync->error_messages);
			  //Update or Insert song
			  if (db_config->connected == 1){
				  status = sync_song(pool, db_config, song);
				  if (status != 0){
					error_messages_add(dir_sync->error_messages, ERROR, apr_psprintf(pool,"Failed to sync song:"),  apr_psprintf(pool, "(%d) Song title: %s Song artist: %s song album:%s song file path: %s",status, song->title, song->artist, song->album, song->file->path));
				  }
			  }else{
				  //Lost connection kill thread
				  error_messages_add(dir_sync->error_messages, ERROR, "Failed to sync song:",  "Lost connection to database");
				  return 0;
			  }
		  }
		  //Calculate the percent of files synchronized
		  dir_sync->dir->stats->sync_progress =(float) files_synced*100 / (*(dir_sync->dir->stats->num_files) - 1);
		  dir_sync->dir->stats->files_scanned = files_synced;
		  files_synced++;
		  file_list = file_list->next;
	}
	status = apr_dbd_transaction_end(db_config->dbd_driver, pool, db_config->transaction);
	if(status != 0){
		dbd_error = apr_dbd_error(db_config->dbd_driver, db_config->dbd_handle, status);
		error_messages_add(dir_sync->error_messages, ERROR, "Database error couldn't end transaction",dbd_error);
		return 0;
	}

	apr_pool_clear(pool);
	return 0;
}
コード例 #24
0
static authn_status authn_dbd_realm(request_rec *r, const char *user,
                                    const char *realm, char **rethash)
{
    apr_status_t rv;
    const char *dbd_hash = NULL;
    apr_dbd_prepared_t *statement;
    apr_dbd_results_t *res = NULL;
    apr_dbd_row_t *row = NULL;
    int ret;

    authn_dbd_conf *conf = ap_get_module_config(r->per_dir_config,
                                                &authn_dbd_module);
    ap_dbd_t *dbd = authn_dbd_acquire_fn(r);
    if (dbd == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01658)
                      "Failed to acquire database connection to look up "
                      "user '%s:%s'", user, realm);
        return AUTH_GENERAL_ERROR;
    }
    if (conf->realm == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01659)
                      "No AuthDBDUserRealmQuery has been specified");
        return AUTH_GENERAL_ERROR;
    }
    statement = apr_hash_get(dbd->prepared, conf->realm, APR_HASH_KEY_STRING);
    if (statement == NULL) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01660)
                      "A prepared statement could not be found for "
                      "AuthDBDUserRealmQuery with the key '%s'", conf->realm);
        return AUTH_GENERAL_ERROR;
    }
    if ((ret = apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res,
                                statement, 0, user, realm, NULL) != 0)) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01661)
                      "Query execution error looking up '%s:%s' "
                      "in database [%s]",
                      user, realm,
                      apr_dbd_error(dbd->driver, dbd->handle, ret));
        return AUTH_GENERAL_ERROR;
    }
    for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1);
         rv != -1;
         rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) {
        if (rv != 0) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01662)
                          "Error retrieving results while looking up '%s:%s' "
                          "in database", user, realm);
            return AUTH_GENERAL_ERROR;
        }
        if (dbd_hash == NULL) {
#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 3)
            /* add the rest of the columns to the environment */
            int i = 1;
            const char *name;
            for (name = apr_dbd_get_name(dbd->driver, res, i);
                 name != NULL;
                 name = apr_dbd_get_name(dbd->driver, res, i)) {

                char *str = apr_pstrcat(r->pool, AUTHN_PREFIX,
                                        name,
                                        NULL);
                int j = sizeof(AUTHN_PREFIX)-1; /* string length of "AUTHENTICATE_", excluding the trailing NIL */
                while (str[j]) {
                    if (!apr_isalnum(str[j])) {
                        str[j] = '_';
                    }
                    else {
                        str[j] = apr_toupper(str[j]);
                    }
                    j++;
                }
                apr_table_set(r->subprocess_env, str,
                              apr_dbd_get_entry(dbd->driver, row, i));
                i++;
            }
#endif
            dbd_hash = apr_dbd_get_entry(dbd->driver, row, 0);
        }
        /* we can't break out here or row won't get cleaned up */
    }

    if (!dbd_hash) {
        return AUTH_USER_NOT_FOUND;
    }
    AUTHN_CACHE_STORE(r, user, realm, dbd_hash);

    *rethash = apr_pstrdup(r->pool, dbd_hash);
    return AUTH_USER_FOUND;
}