#include "db-sqlite3.h" #include #include // for usleep #define SQLRES(f, good) \ result = (sqlite3_##f);\ if (result != good) {\ throw std::runtime_error(sqlite3_errmsg(db));\ } #define SQLOK(f) SQLRES(f, SQLITE_OK) DBSQLite3::DBSQLite3(const std::string &mapdir) { int result; std::string db_name = mapdir + "map.sqlite"; SQLOK(open_v2(db_name.c_str(), &db, SQLITE_OPEN_READONLY | SQLITE_OPEN_PRIVATECACHE, 0)) SQLOK(prepare_v2(db, "SELECT pos, data FROM blocks WHERE (pos >= ? AND pos <= ?)", -1, &stmt_get_blocks, NULL)) SQLOK(prepare_v2(db, "SELECT pos FROM blocks", -1, &stmt_get_block_pos, NULL)) } DBSQLite3::~DBSQLite3() { int result; SQLOK(finalize(stmt_get_blocks)); SQLOK(finalize(stmt_get_block_pos)); SQLOK(close(db)); } std::vector DBSQLite3::getBlockPos() { std::vector vec; int result; while ((result = sqlite3_step(stmt_get_block_pos)) != SQLITE_DONE) { if (result == SQLITE_ROW) { int64_t blockpos = sqlite3_column_int64(stmt_get_block_pos, 0); vec.push_back(blockpos); } else if (result == SQLITE_BUSY) { // Wait some time and try again usleep(10000); } else { throw std::runtime_error(sqlite3_errmsg(db)); } } SQLOK(reset(stmt_get_block_pos)); return vec; } DBBlockList DBSQLite3::getBlocksOnZ(int zPos) { DBBlockList blocks; int64_t psMin = (static_cast(zPos) * 16777216L) - 0x800000; int64_t psMax = (static_cast(zPos) * 16777216L) + 0x7fffff; sqlite3_bind_int64(stmt_get_blocks, 1, psMin); sqlite3_bind_int64(stmt_get_blocks, 2, psMax); int result; while ((result = sqlite3_step(stmt_get_blocks)) != SQLITE_DONE) { if (result == SQLITE_ROW) { int64_t blocknum = sqlite3_column_int64(stmt_get_blocks, 0); const unsigned char *data = reinterpret_cast(sqlite3_column_blob(stmt_get_blocks, 1)); int size = sqlite3_column_bytes(stmt_get_blocks, 1); blocks.push_back(DBBlock(blocknum, std::basic_string(data, size))); } else if (result == SQLITE_BUSY) { // Wait some time and try again usleep(10000); } else { throw std::runtime_error(sqlite3_errmsg(db)); } } SQLOK(reset(stmt_get_blocks)); return blocks; } #undef SQLRES #undef SQLOK