Database.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. //
  2. // Created by Иван_Архипов on 17.11.2017.
  3. //
  4. #include "Database.h"
  5. #include "BinaryData.h"
  6. #include "SubfileData.h"
  7. #include "EasyLogging++/easylogging++.h"
  8. namespace LOTRO_DAT {
  9. Database::Database() {
  10. LOG(DEBUG) << "Initialising new Database instance.";
  11. db_ = nullptr;
  12. }
  13. bool Database::CloseDatabase() {
  14. LOG(DEBUG) << "Closing database.";
  15. if (db_ != nullptr) {
  16. ExecSql("COMMIT TRANSACTION");
  17. sqlite3_finalize(insert_request_);
  18. sqlite3_finalize(fetch_one_request_);
  19. sqlite3_finalize(get_rows_number_request_);
  20. if (sqlite3_close_v2(db_) != SQLITE_OK)
  21. LOG(ERROR) << "Database error when closing: " << sqlite3_errmsg(db_);
  22. db_ = nullptr;
  23. }
  24. LOG(DEBUG) << "Database successfully closed.";
  25. return true;
  26. }
  27. Database::~Database() {
  28. CloseDatabase();
  29. }
  30. bool Database::InitDatabase(const std::string &filename) {
  31. LOG(DEBUG) << "Initializing database " << filename;
  32. CloseDatabase();
  33. if (sqlite3_open(filename.c_str(), &db_) != SQLITE_OK) {
  34. sqlite3_close(db_);
  35. db_ = nullptr;
  36. LOG(ERROR) << "sqlite3_open returned an error. Unable to open file " << filename;
  37. return false;
  38. }
  39. ExecSql("PRAGMA synchronous = OFF");
  40. ExecSql("PRAGMA count_changes = OFF");
  41. ExecSql("PRAGMA journal_mode = MEMORY");
  42. ExecSql("PRAGMA temp_store = MEMORY");
  43. ExecSql("PRAGMA encoding = \"UTF-8\";");
  44. ExecSql(CreateTableCommand_);
  45. sqlite3_prepare_v2(db_, InsertFileCommand_.c_str(), InsertFileCommand_.length(), &insert_request_, nullptr);
  46. sqlite3_prepare_v2(db_, FetchOneCommand.c_str(), FetchOneCommand.length(), &fetch_one_request_, nullptr);
  47. sqlite3_prepare_v2(db_, GetRowsNumberCommand_.c_str(), GetRowsNumberCommand_.length(),
  48. &get_rows_number_request_, nullptr);
  49. ExecSql("BEGIN TRANSACTION");
  50. LOG(DEBUG) << "Database " << filename << " successfully initialized";
  51. return true;
  52. }
  53. void Database::ExecSql(const std::string &sql) {
  54. LOG(DEBUG) << "Executing SQL request: " << sql;
  55. if (db_ == nullptr) {
  56. LOG(WARNING) << "Trying to execute sql query to db, which hasn't been opened yet.";
  57. return;
  58. }
  59. char *error;
  60. if (sqlite3_exec(db_, sql.c_str(), nullptr, nullptr, &error) != SQLITE_OK) {
  61. LOG(ERROR) << "SQLite3 error: " << sqlite3_errmsg(db_);
  62. return;
  63. }
  64. LOG(DEBUG) << "SQL request " << sql << " executed successfully";
  65. }
  66. bool Database::PushFile(const SubfileData &data) {
  67. LOG(DEBUG) << "Pushing to database file with file_id " << data.options["fid"].as<long long>();
  68. if (db_ == nullptr) {
  69. LOG(WARNING) << "Trying to push file to db, which hasn't been opened yet.";
  70. return false;
  71. }
  72. std::stringstream options_;
  73. options_ << data.options;
  74. sqlite3_bind_blob(insert_request_, 1, data.binary_data.data(), data.binary_data.size(), SQLITE_TRANSIENT);
  75. sqlite3_bind_text16(insert_request_, 2, data.text_data.c_str(), -1, SQLITE_TRANSIENT);
  76. sqlite3_bind_text(insert_request_, 3, options_.str().c_str(), -1, SQLITE_TRANSIENT);
  77. if (sqlite3_step(insert_request_) != SQLITE_DONE) {
  78. LOG(ERROR) << "SQLite3 error: " << sqlite3_errmsg(db_);
  79. return false;
  80. }
  81. sqlite3_reset(insert_request_);
  82. LOG(DEBUG) << "File with file_id " << data.options["fid"].as<long long>() << " pushed to database successfully.";
  83. return true;
  84. }
  85. SubfileData Database::GetNextFile() {
  86. LOG(DEBUG) << "Getting next file from database..";
  87. if (db_ == nullptr) {
  88. LOG(WARNING) << "Trying to get next file from db, which hasn't been opened yet.";
  89. return SubfileData();
  90. }
  91. SubfileData data;
  92. int result = sqlite3_step(fetch_one_request_);
  93. if (result == SQLITE_ROW) {
  94. data.binary_data = BinaryData((char *) sqlite3_column_blob(fetch_one_request_, 0),
  95. unsigned(sqlite3_column_bytes(fetch_one_request_, 0)));
  96. data.text_data = std::u16string((char16_t *) sqlite3_column_text16(fetch_one_request_, 1));
  97. std::string _options = std::string((char *) sqlite3_column_text(fetch_one_request_, 2),
  98. unsigned(sqlite3_column_bytes(fetch_one_request_, 2)));
  99. data.options = YAML::Load(_options);
  100. return data;
  101. }
  102. if (result == SQLITE_DONE) {
  103. LOG(DEBUG) << "Next file fetched successfully.";
  104. return data;
  105. }
  106. LOG(ERROR) << "SQLite3 fetch_one request returned " << result << " code. SQLite message is: "<< sqlite3_errmsg(db_);
  107. return data;
  108. }
  109. size_t Database::CountRows() {
  110. LOG(INFO) << "Counting rows in database...";
  111. if (db_ == nullptr) {
  112. LOG(WARNING) << "Trying to execute sql query (Count rows) to db, which hasn't been opened yet.";
  113. return 0;
  114. }
  115. int result = sqlite3_step(get_rows_number_request_);
  116. if (result == SQLITE_ERROR) {
  117. LOG(ERROR) << "Error when counting rows " << sqlite3_errmsg(db_);
  118. return 0;
  119. }
  120. long long res = sqlite3_column_int64(get_rows_number_request_, 0);
  121. sqlite3_reset(get_rows_number_request_);
  122. LOG(INFO) << "Counted " << size_t(res) << " rows in database.";
  123. return size_t(res);
  124. }
  125. }