Database.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. //
  2. // Created by Иван_Архипов on 17.11.2017.
  3. //
  4. #define UNICODE
  5. #define _UNICODE
  6. #include "Database.h"
  7. #include "DatException.h"
  8. #include "BinaryData.h"
  9. #include "CommonFunctions.h"
  10. #include "SubfileData.h"
  11. #include <cstring>
  12. #include <sstream>
  13. namespace LOTRO_DAT {
  14. Database::Database() {
  15. db_ = nullptr;
  16. }
  17. void Database::CloseDatabase() {
  18. if (db_ != nullptr) {
  19. ExecSql("COMMIT TRANSACTION");
  20. sqlite3_finalize(insert_request_);
  21. sqlite3_finalize(fetch_one_request_);
  22. sqlite3_finalize(get_rows_number_request_);
  23. if (sqlite3_close_v2(db_) != SQLITE_OK)
  24. fprintf(stderr, "ERROR: Bad Database::CloseDatabase() - Error when closing: %s\n", sqlite3_errmsg(db_));
  25. db_ = nullptr;
  26. }
  27. }
  28. Database::~Database() {
  29. CloseDatabase();
  30. }
  31. void Database::InitDatabase(const std::string &filename) {
  32. CloseDatabase();
  33. if (sqlite3_open(filename.c_str(), &db_) != SQLITE_OK) {
  34. sqlite3_close(db_);
  35. throw DatException("Bad Database::InitDatabase() - sqlite3_open returned an error..."
  36. , DATABASE_EXCEPTION);
  37. }
  38. ExecSql("PRAGMA synchronous = OFF");
  39. ExecSql("PRAGMA count_changes = OFF");
  40. ExecSql("PRAGMA journal_mode = MEMORY");
  41. ExecSql("PRAGMA temp_store = MEMORY");
  42. ExecSql("PRAGMA encoding = \"UTF-8\";");
  43. ExecSql(CreateTableCommand_);
  44. sqlite3_prepare_v2(db_, InsertFileCommand_.c_str(), InsertFileCommand_.length(), &insert_request_, nullptr);
  45. sqlite3_prepare_v2(db_, FetchOneCommand.c_str(), FetchOneCommand.length(), &fetch_one_request_, nullptr);
  46. sqlite3_prepare_v2(db_, GetRowsNumberCommand_.c_str(), GetRowsNumberCommand_.length(), &get_rows_number_request_, nullptr);
  47. ExecSql("BEGIN TRANSACTION");
  48. }
  49. void Database::ExecSql(const std::string &sql) {
  50. if (db_ == nullptr)
  51. throw DatException("Bad Database::ExecSql() - database hasn't been opened!", DATABASE_EXCEPTION);
  52. char *error;
  53. if (sqlite3_exec(db_, sql.c_str(), nullptr, nullptr, &error) != SQLITE_OK) {
  54. fprintf(stderr, "SQLite3 error: %s\n", sqlite3_errmsg(db_));
  55. throw DatException((std::string("Bad Database::ExecSql() - unable to perform request")
  56. + std::string(sql)).c_str(), DATABASE_EXCEPTION);
  57. }
  58. }
  59. void Database::PushFile(const SubfileData &data) {
  60. if (db_ == nullptr)
  61. throw DatException("Bad Database::PushFile() - database hasn't been opened!", DATABASE_EXCEPTION);
  62. std::stringstream options_;
  63. options_ << data.options;
  64. sqlite3_bind_blob(insert_request_, 1, data.binary_data.data(), data.binary_data.size(), SQLITE_TRANSIENT);
  65. sqlite3_bind_text16(insert_request_, 2, data.text_data.c_str(), -1, SQLITE_TRANSIENT);
  66. sqlite3_bind_text(insert_request_, 3, options_.str().c_str(), -1, SQLITE_TRANSIENT);
  67. if (sqlite3_step(insert_request_) != SQLITE_DONE) {
  68. fprintf(stderr, "SQLite3 error: %s\n", sqlite3_errmsg(db_));
  69. throw DatException((std::string("Bad Database::PushTextFile() - unable to perform push operation")).c_str(),
  70. DATABASE_EXCEPTION);
  71. }
  72. sqlite3_reset(insert_request_);
  73. }
  74. SubfileData Database::GetNextFile() {
  75. SubfileData data;
  76. if (db_ == nullptr)
  77. throw DatException("Bad Database::GetNexFile() - database hasn't been opened!", DATABASE_EXCEPTION);
  78. int result = sqlite3_step(fetch_one_request_);
  79. if (result == SQLITE_ROW) {
  80. data.binary_data = BinaryData((char *) sqlite3_column_blob(fetch_one_request_, 0),
  81. unsigned(sqlite3_column_bytes(fetch_one_request_, 0)));
  82. data.text_data = std::u16string((char16_t *)sqlite3_column_text16(fetch_one_request_, 1));
  83. std::string _options = std::string((char *)sqlite3_column_text(fetch_one_request_, 2),
  84. unsigned(sqlite3_column_bytes(fetch_one_request_, 2)));
  85. data.options = YAML::Load(_options);
  86. return data;
  87. }
  88. if (result == SQLITE_DONE) {
  89. return data;
  90. }
  91. fprintf(stderr, "SQLite3 fetch_one request returned %d code. SQLite message is: %s", result, sqlite3_errmsg(db_));
  92. throw DatException("Bad Database::GetNextFile() - sqlite3 - error", DATABASE_EXCEPTION);
  93. }
  94. void Database::RemoveDatabase() {
  95. if (db_ == nullptr)
  96. throw DatException("Bad Database::RemoveDatabase() - database hasn't been opened!", DATABASE_EXCEPTION);
  97. throw DatException("Database::RemoveDatabase() haven't been implemented yet...", DATABASE_EXCEPTION);
  98. // TODO: Implement function
  99. }
  100. void Database::ClearDatabase() {
  101. if (db_ == nullptr)
  102. throw DatException("Bad Database::ClearDatabase() - database hasn't been opened!", DATABASE_EXCEPTION);
  103. ExecSql(ClearTableCommand_);
  104. }
  105. size_t Database::CountRows() {
  106. int result = sqlite3_step(get_rows_number_request_);
  107. if (result == SQLITE_ERROR) {
  108. fprintf(stderr, "ERROR: Bad Database::CountRows() - Error when counting rows %s\n", sqlite3_errmsg(db_));
  109. return 0;
  110. }
  111. long long res = sqlite3_column_int64(get_rows_number_request_, 0);
  112. sqlite3_reset(get_rows_number_request_);
  113. return size_t(res);
  114. }
  115. }