// // Created by Иван_Архипов on 17.11.2017. // #define UNICODE #define _UNICODE #include "Database.h" #include "Common/DatException.h" #include "BinaryData.h" #include "Common/CommonFunctions.h" #include "SubfileData.h" #include #include namespace LOTRO_DAT { Database::Database() { db_ = nullptr; } Database::Database(const std::string &filename) { InitDatabase(filename.c_str()); } Database::~Database() { if (db_ != nullptr) { ExecSql("COMMIT TRANSACTION"); sqlite3_finalize(insert_request_); sqlite3_close(db_); } } void Database::InitDatabase(const std::string &filename) { if (sqlite3_open(filename.c_str(), &db_) != SQLITE_OK) { sqlite3_close(db_); throw DatException("Bad Database::InitDatabase() - sqlite3_open returned an error..." , DATABASE_EXCEPTION); } ExecSql("PRAGMA synchronous = OFF"); ExecSql("PRAGMA count_changes = OFF"); ExecSql("PRAGMA journal_mode = MEMORY"); ExecSql("PRAGMA temp_store = MEMORY"); ExecSql("PRAGMA encoding = \"UTF-8\";"); ExecSql(CreateTableCommand_); sqlite3_prepare_v2(db_, InsertFileCommand_.c_str(), InsertFileCommand_.length(), &insert_request_, nullptr); sqlite3_prepare_v2(db_, FetchOneCommand.c_str(), FetchOneCommand.length(), &fetch_one_request_, nullptr); ExecSql("BEGIN TRANSACTION"); } void Database::ExecSql(const std::string &sql) { if (db_ == nullptr) throw DatException("Bad Database::ExecSql() - database hasn't been opened!", DATABASE_EXCEPTION); char *error; if (sqlite3_exec(db_, sql.c_str(), nullptr, nullptr, &error) != SQLITE_OK) { fprintf(stderr, "SQLite3 error: %s\n", sqlite3_errmsg(db_)); throw DatException((std::string("Bad Database::ExecSql() - unable to perform request") + std::string(sql)).c_str(), DATABASE_EXCEPTION); } } void Database::PushFile(const SubfileData &data) { if (db_ == nullptr) throw DatException("Bad Database::PushFile() - database hasn't been opened!", DATABASE_EXCEPTION); std::stringstream options_; options_ << data.options; sqlite3_bind_blob(insert_request_, 1, data.binary_data.data(), data.binary_data.size(), SQLITE_TRANSIENT); sqlite3_bind_text16(insert_request_, 2, data.text_data.c_str(), -1, SQLITE_TRANSIENT); sqlite3_bind_text(insert_request_, 3, options_.str().c_str(), -1, SQLITE_TRANSIENT); if (sqlite3_step(insert_request_) != SQLITE_DONE) { fprintf(stderr, "SQLite3 error: %s\n", sqlite3_errmsg(db_)); throw DatException((std::string("Bad Database::PushTextFile() - unable to perform push operation")).c_str(), DATABASE_EXCEPTION); } sqlite3_reset(insert_request_); } SubfileData Database::GetNextFile() { SubfileData data; if (db_ == nullptr) throw DatException("Bad Database::GetNexFile() - database hasn't been opened!", DATABASE_EXCEPTION); int result = sqlite3_step(fetch_one_request_); if (result == SQLITE_ROW) { data.binary_data = BinaryData((char *) sqlite3_column_blob(fetch_one_request_, 0), unsigned(sqlite3_column_bytes(fetch_one_request_, 0))); data.text_data = std::u16string((char16_t *)sqlite3_column_text16(fetch_one_request_, 1)); std::string _options = std::string((char *)sqlite3_column_text(fetch_one_request_, 2), unsigned(sqlite3_column_bytes(fetch_one_request_, 2))); data.options = YAML::Load(_options); return data; } if (result == SQLITE_DONE) { return data; } fprintf(stderr, "SQLite3 fetch_one request returned %d code. SQLite message is: %s", result, sqlite3_errmsg(db_)); throw DatException("Bad Database::GetNextFile() - sqlite3 - error", DATABASE_EXCEPTION); } void Database::RemoveDatabase() { if (db_ == nullptr) throw DatException("Bad Database::RemoveDatabase() - database hasn't been opened!", DATABASE_EXCEPTION); throw DatException("Database::RemoveDatabase() haven't been implemented yet...", DATABASE_EXCEPTION); // TODO: Implement function } void Database::ClearDatabase() { if (db_ == nullptr) throw DatException("Bad Database::ClearDatabase() - database hasn't been opened!", DATABASE_EXCEPTION); ExecSql(ClearTableCommand_); } }