#include "main.h"
#include "settings.h"
#include "log.h"
+#include "filesys.h"
Database_SQLite3::Database_SQLite3(ServerMap *map, std::string savedir)
{
m_database_read = NULL;
m_database_write = NULL;
m_database_list = NULL;
+ m_database_delete = NULL;
m_savedir = savedir;
srvmap = map;
}
errorstream<<"SQLite3 read statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
throw FileNotGoodException("Cannot prepare read statement");
}
-
- d = sqlite3_prepare(m_database, "REPLACE INTO `blocks` VALUES(?, ?)", -1, &m_database_write, NULL);
+#ifdef __ANDROID__
+ d = sqlite3_prepare(m_database, "INSERT INTO `blocks` VALUES(?, ?);", -1, &m_database_write, NULL);
+#else
+ d = sqlite3_prepare(m_database, "REPLACE INTO `blocks` VALUES(?, ?);", -1, &m_database_write, NULL);
+#endif
if(d != SQLITE_OK) {
errorstream<<"SQLite3 write statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
throw FileNotGoodException("Cannot prepare write statement");
}
+ d = sqlite3_prepare(m_database, "DELETE FROM `blocks` WHERE `pos`=?;", -1, &m_database_delete, NULL);
+ if(d != SQLITE_OK) {
+ infostream<<"WARNING: SQLite3 database delete statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
+ throw FileNotGoodException("Cannot prepare delete statement");
+ }
+
d = sqlite3_prepare(m_database, "SELECT `pos` FROM `blocks`", -1, &m_database_list, NULL);
if(d != SQLITE_OK) {
infostream<<"SQLite3 list statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
infostream<<"ServerMap: SQLite3 database opened"<<std::endl;
}
+bool Database_SQLite3::deleteBlock(v3s16 blockpos)
+{
+ verifyDatabase();
+
+ if (sqlite3_bind_int64(m_database_delete, 1,
+ getBlockAsInteger(blockpos)) != SQLITE_OK) {
+ errorstream << "WARNING: Could not bind block position for delete: "
+ << sqlite3_errmsg(m_database) << std::endl;
+ }
+
+ if (sqlite3_step(m_database_delete) != SQLITE_DONE) {
+ errorstream << "WARNING: deleteBlock: Block failed to delete "
+ << PP(blockpos) << ": " << sqlite3_errmsg(m_database) << std::endl;
+ sqlite3_reset(m_database_delete);
+ return false;
+ }
+
+ sqlite3_reset(m_database_delete);
+ return true;
+}
+
bool Database_SQLite3::saveBlock(v3s16 blockpos, std::string &data)
{
verifyDatabase();
- if (sqlite3_bind_int64(m_database_write, 1, getBlockAsInteger(blockpos)) != SQLITE_OK) {
+ s64 bkey = getBlockAsInteger(blockpos);
+
+#ifdef __ANDROID__
+ /**
+ * Note: For some unknown reason sqlite3 fails to REPLACE blocks on android,
+ * deleting them and inserting first works.
+ */
+ if (sqlite3_bind_int64(m_database_read, 1, bkey) != SQLITE_OK) {
+ infostream << "WARNING: Could not bind block position for load: "
+ << sqlite3_errmsg(m_database)<<std::endl;
+ }
+
+ int step_result = sqlite3_step(m_database_read);
+ sqlite3_reset(m_database_read);
+
+ if (step_result == SQLITE_ROW) {
+ if (sqlite3_bind_int64(m_database_delete, 1, bkey) != SQLITE_OK) {
+ infostream << "WARNING: Could not bind block position for delete: "
+ << sqlite3_errmsg(m_database)<<std::endl;
+ }
+
+ if (sqlite3_step(m_database_delete) != SQLITE_DONE) {
+ errorstream << "WARNING: saveBlock: Block failed to delete "
+ << PP(blockpos) << ": " << sqlite3_errmsg(m_database) << std::endl;
+ return false;
+ }
+ sqlite3_reset(m_database_delete);
+ }
+#endif
+
+ if (sqlite3_bind_int64(m_database_write, 1, bkey) != SQLITE_OK) {
errorstream << "WARNING: saveBlock: Block position failed to bind: "
<< PP(blockpos) << ": " << sqlite3_errmsg(m_database) << std::endl;
sqlite3_reset(m_database_write);
return false;
}
- if (sqlite3_bind_blob(m_database_write, 2, (void *) data.c_str(), data.size(), NULL) != SQLITE_OK) {
+ if (sqlite3_bind_blob(m_database_write, 2, (void *)data.c_str(),
+ data.size(), NULL) != SQLITE_OK) {
errorstream << "WARNING: saveBlock: Block data failed to bind: "
<< PP(blockpos) << ": " << sqlite3_errmsg(m_database) << std::endl;
sqlite3_reset(m_database_write);
}
sqlite3_reset(m_database_write);
+
return true;
}
"`data` BLOB"
");"
, NULL, NULL, NULL);
- if(e == SQLITE_ABORT)
+ if(e != SQLITE_OK)
throw FileNotGoodException("Could not create sqlite3 database structure");
else
infostream<<"ServerMap: SQLite3 database structure was created";
}
-void Database_SQLite3::listAllLoadableBlocks(std::list<v3s16> &dst)
+void Database_SQLite3::listAllLoadableBlocks(std::vector<v3s16> &dst)
{
verifyDatabase();
- while(sqlite3_step(m_database_list) == SQLITE_ROW)
- {
+ while(sqlite3_step(m_database_list) == SQLITE_ROW) {
sqlite3_int64 block_i = sqlite3_column_int64(m_database_list, 0);
v3s16 p = getIntegerAsBlock(block_i);
//dstream<<"block_i="<<block_i<<" p="<<PP(p)<<std::endl;
FINALIZE_STATEMENT(m_database_read)
FINALIZE_STATEMENT(m_database_write)
FINALIZE_STATEMENT(m_database_list)
+ FINALIZE_STATEMENT(m_database_delete)
if(m_database)
rc = sqlite3_close(m_database);