Prepare statements at startup and finalize them

This commit is contained in:
ShadowNinja 2014-03-28 13:42:37 -04:00
parent 66813a36b8
commit 6e565e93d1
2 changed files with 50 additions and 38 deletions

View File

@ -2,73 +2,82 @@
#include <stdexcept> #include <stdexcept>
#include <unistd.h> // for usleep #include <unistd.h> // for usleep
DBSQLite3::DBSQLite3(const std::string &mapdir) { #define SQLRES(f, good) \
result = (sqlite3_##f);\
std::string db_name = mapdir + "map.sqlite"; if (result != good) {\
if (sqlite3_open_v2(db_name.c_str(), &m_db, SQLITE_OPEN_READONLY | SQLITE_OPEN_PRIVATECACHE, 0) != SQLITE_OK) { throw std::runtime_error(sqlite3_errmsg(m_db));\
throw std::runtime_error(std::string(sqlite3_errmsg(m_db)) + ", Database file: " + db_name);
} }
#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(), &m_db, SQLITE_OPEN_READONLY | SQLITE_OPEN_PRIVATECACHE, 0))
SQLOK(prepare_v2(m_db,
"SELECT pos, data FROM blocks WHERE (pos >= ? AND pos <= ?)",
-1, &stmt_get_blocks, NULL))
SQLOK(prepare_v2(m_db,
"SELECT pos FROM blocks",
-1, &stmt_get_block_pos, NULL))
} }
DBSQLite3::~DBSQLite3() { DBSQLite3::~DBSQLite3() {
sqlite3_close(m_db); int result;
SQLOK(finalize(stmt_get_blocks));
SQLOK(finalize(stmt_get_block_pos));
SQLOK(close(m_db));
} }
std::vector<int64_t> DBSQLite3::getBlockPos() { std::vector<int64_t> DBSQLite3::getBlockPos() {
std::vector<int64_t> vec; std::vector<int64_t> vec;
sqlite3_stmt *statement; int result = 0;
std::string sql = "SELECT pos FROM blocks"; while ((result = sqlite3_step(stmt_get_block_pos)) != SQLITE_DONE) {
if (sqlite3_prepare_v2(m_db, sql.c_str(), sql.length(), &statement, 0) == SQLITE_OK) { if (result == SQLITE_ROW) {
int result = 0; int64_t blockpos = sqlite3_column_int64(stmt_get_block_pos, 0);
while (true) { vec.push_back(blockpos);
result = sqlite3_step(statement); } else if (result == SQLITE_BUSY) { // Wait some time and try again
if(result == SQLITE_ROW) { usleep(10000);
sqlite3_int64 blocknum = sqlite3_column_int64(statement, 0); } else {
vec.push_back(blocknum); throw std::runtime_error(sqlite3_errmsg(m_db));
} else if (result == SQLITE_BUSY) // Wait some time and try again
usleep(10000);
else
break;
} }
} else {
throw std::runtime_error("Failed to get list of MapBlocks");
} }
return vec; return vec;
} }
DBBlockList DBSQLite3::getBlocksOnZ(int zPos) DBBlockList DBSQLite3::getBlocksOnZ(int zPos)
{ {
sqlite3_stmt *statement;
std::string sql = "SELECT pos, data FROM blocks WHERE (pos >= ? AND pos <= ?)";
if (sqlite3_prepare_v2(m_db, sql.c_str(), sql.length(), &statement, 0) != SQLITE_OK) {
throw std::runtime_error("Failed to prepare statement");
}
DBBlockList blocks; DBBlockList blocks;
sqlite3_int64 psMin; sqlite3_int64 psMin;
sqlite3_int64 psMax; sqlite3_int64 psMax;
psMin = (static_cast<sqlite3_int64>(zPos) * 16777216l) - 0x800000; psMin = (static_cast<sqlite3_int64>(zPos) * 16777216L) - 0x800000;
psMax = (static_cast<sqlite3_int64>(zPos) * 16777216l) + 0x7fffff; psMax = (static_cast<sqlite3_int64>(zPos) * 16777216L) + 0x7fffff;
sqlite3_bind_int64(statement, 1, psMin); sqlite3_bind_int64(stmt_get_blocks, 1, psMin);
sqlite3_bind_int64(statement, 2, psMax); sqlite3_bind_int64(stmt_get_blocks, 2, psMax);
int result = 0; int result = 0;
while (true) { while ((result = sqlite3_step(stmt_get_blocks)) != SQLITE_DONE) {
result = sqlite3_step(statement); if (result == SQLITE_ROW) {
if(result == SQLITE_ROW) { int64_t blocknum = sqlite3_column_int64(stmt_get_blocks, 0);
sqlite3_int64 blocknum = sqlite3_column_int64(statement, 0); const unsigned char *data = reinterpret_cast<const unsigned char *>(sqlite3_column_blob(stmt_get_blocks, 1));
const unsigned char *data = reinterpret_cast<const unsigned char *>(sqlite3_column_blob(statement, 1)); int size = sqlite3_column_bytes(stmt_get_blocks, 1);
int size = sqlite3_column_bytes(statement, 1);
blocks.push_back(DBBlock(blocknum, std::basic_string<unsigned char>(data, size))); blocks.push_back(DBBlock(blocknum, std::basic_string<unsigned char>(data, size)));
} else if (result == SQLITE_BUSY) { // Wait some time and try again } else if (result == SQLITE_BUSY) { // Wait some time and try again
usleep(10000); usleep(10000);
} else { } else {
break; throw std::runtime_error(sqlite3_errmsg(m_db));
} }
} }
sqlite3_reset(statement); SQLOK(reset(stmt_get_blocks));
return blocks; return blocks;
} }
#undef SQLRES
#undef SQLOK

View File

@ -12,6 +12,9 @@ public:
~DBSQLite3(); ~DBSQLite3();
private: private:
sqlite3 *m_db; sqlite3 *m_db;
sqlite3_stmt *stmt_get_block_pos;
sqlite3_stmt *stmt_get_blocks;
}; };
#endif // _DB_SQLITE3_H #endif // _DB_SQLITE3_H