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