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; }
static void select_rows(abts_case *tc, apr_dbd_t* handle, const apr_dbd_driver_t* driver, int count) { apr_status_t rv; apr_pool_t* pool = p; apr_pool_t* tpool; const char* sql = "SELECT * FROM apr_dbd_test ORDER BY col1"; apr_dbd_results_t *res = NULL; apr_dbd_row_t *row = NULL; int i; rv = apr_dbd_select(driver, pool, handle, &res, sql, 0); ABTS_ASSERT(tc, sql, rv == APR_SUCCESS); ABTS_PTR_NOTNULL(tc, res); apr_pool_create(&tpool, pool); i = count; while (i > 0) { row = NULL; rv = apr_dbd_get_row(driver, pool, res, &row, -1); ABTS_ASSERT(tc, sql, rv == APR_SUCCESS); ABTS_PTR_NOTNULL(tc, row); apr_pool_clear(tpool); i--; } ABTS_ASSERT(tc, "Missing Rows!", i == 0); res = NULL; i = count; rv = apr_dbd_select(driver, pool, handle, &res, sql, 1); ABTS_ASSERT(tc, sql, rv == APR_SUCCESS); ABTS_PTR_NOTNULL(tc, res); rv = apr_dbd_num_tuples(driver, res); ABTS_ASSERT(tc, "invalid row count", rv == count); while (i > 0) { row = NULL; rv = apr_dbd_get_row(driver, pool, res, &row, i); ABTS_ASSERT(tc, sql, rv == APR_SUCCESS); ABTS_PTR_NOTNULL(tc, row); apr_pool_clear(tpool); i--; } ABTS_ASSERT(tc, "Missing Rows!", i == 0); rv = apr_dbd_get_row(driver, pool, res, &row, count+100); ABTS_ASSERT(tc, "If we overseek, get_row should return -1", rv == -1); }
/* ============================================================================= 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); }
/* ============================================================================= 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; }