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; }
/* ============================================================================= 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); }
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; }