Database.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. //
  2. // Created by Иван_Архипов on 17.11.2017.
  3. //
  4. #include "Database.h"
  5. #include "DatException.h"
  6. #include "BinaryData.h"
  7. #include "CommonFunctions.h"
  8. #include "SubfileData.h"
  9. namespace LOTRO_DAT {
  10. Database::Database() {
  11. db_ = nullptr;
  12. }
  13. bool Database::CloseDatabase() {
  14. try {
  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. fprintf(stderr, "ERROR: Bad Database::CloseDatabase() - Error when closing: %s\n",
  22. sqlite3_errmsg(db_));
  23. db_ = nullptr;
  24. }
  25. } catch (std::exception &e) {
  26. fprintf(stderr, "Bad Database::CloseDatabase() - caught exception %s\n", e.what());
  27. return false;
  28. }
  29. return true;
  30. }
  31. Database::~Database() {
  32. CloseDatabase();
  33. }
  34. bool Database::InitDatabase(const std::string &filename) {
  35. try {
  36. CloseDatabase();
  37. if (sqlite3_open(filename.c_str(), &db_) != SQLITE_OK) {
  38. sqlite3_close(db_);
  39. throw DatException("Bad Database::InitDatabase() - sqlite3_open returned an error...",
  40. DATABASE_EXCEPTION);
  41. }
  42. ExecSql("PRAGMA synchronous = OFF");
  43. ExecSql("PRAGMA count_changes = OFF");
  44. ExecSql("PRAGMA journal_mode = MEMORY");
  45. ExecSql("PRAGMA temp_store = MEMORY");
  46. ExecSql("PRAGMA encoding = \"UTF-8\";");
  47. ExecSql(CreateTableCommand_);
  48. sqlite3_prepare_v2(db_, InsertFileCommand_.c_str(), InsertFileCommand_.length(), &insert_request_, nullptr);
  49. sqlite3_prepare_v2(db_, FetchOneCommand.c_str(), FetchOneCommand.length(), &fetch_one_request_, nullptr);
  50. sqlite3_prepare_v2(db_, GetRowsNumberCommand_.c_str(), GetRowsNumberCommand_.length(),
  51. &get_rows_number_request_, nullptr);
  52. ExecSql("BEGIN TRANSACTION");
  53. } catch (std::exception &e) {
  54. fprintf(stderr, "Bad Database::InitDatabase() - caught exception %s\n", e.what());
  55. return false;
  56. }
  57. return true;
  58. }
  59. void Database::ExecSql(const std::string &sql) {
  60. if (db_ == nullptr)
  61. throw DatException("Bad Database::ExecSql() - database hasn't been opened!", DATABASE_EXCEPTION);
  62. char *error;
  63. if (sqlite3_exec(db_, sql.c_str(), nullptr, nullptr, &error) != SQLITE_OK) {
  64. fprintf(stderr, "SQLite3 error: %s\n", sqlite3_errmsg(db_));
  65. throw DatException((std::string("Bad Database::ExecSql() - unable to perform request")
  66. + std::string(sql)).c_str(), DATABASE_EXCEPTION);
  67. }
  68. }
  69. bool Database::PushFile(const SubfileData &data) {
  70. try {
  71. if (db_ == nullptr)
  72. throw DatException("Bad Database::PushFile() - database hasn't been opened!", DATABASE_EXCEPTION);
  73. std::stringstream options_;
  74. options_ << data.options;
  75. sqlite3_bind_blob(insert_request_, 1, data.binary_data.data(), data.binary_data.size(), SQLITE_TRANSIENT);
  76. sqlite3_bind_text16(insert_request_, 2, data.text_data.c_str(), -1, SQLITE_TRANSIENT);
  77. sqlite3_bind_text(insert_request_, 3, options_.str().c_str(), -1, SQLITE_TRANSIENT);
  78. if (sqlite3_step(insert_request_) != SQLITE_DONE) {
  79. fprintf(stderr, "SQLite3 error: %s\n", sqlite3_errmsg(db_));
  80. throw DatException(
  81. (std::string("Bad Database::PushTextFile() - unable to perform push operation")).c_str(),
  82. DATABASE_EXCEPTION);
  83. }
  84. sqlite3_reset(insert_request_);
  85. } catch (std::exception &e) {
  86. fprintf(stderr, "Bad Database::PushFile() - caught exception %s\n", e.what());
  87. return false;
  88. }
  89. return true;
  90. }
  91. SubfileData Database::GetNextFile() {
  92. try {
  93. SubfileData data;
  94. if (db_ == nullptr)
  95. throw DatException("Bad Database::GetNexFile() - database hasn't been opened!", DATABASE_EXCEPTION);
  96. int result = sqlite3_step(fetch_one_request_);
  97. if (result == SQLITE_ROW) {
  98. data.binary_data = BinaryData((char *) sqlite3_column_blob(fetch_one_request_, 0),
  99. unsigned(sqlite3_column_bytes(fetch_one_request_, 0)));
  100. data.text_data = std::u16string((char16_t *) sqlite3_column_text16(fetch_one_request_, 1));
  101. std::string _options = std::string((char *) sqlite3_column_text(fetch_one_request_, 2),
  102. unsigned(sqlite3_column_bytes(fetch_one_request_, 2)));
  103. data.options = YAML::Load(_options);
  104. return data;
  105. }
  106. if (result == SQLITE_DONE) {
  107. return data;
  108. }
  109. fprintf(stderr, "SQLite3 fetch_one request returned %d code. SQLite message is: %s", result,
  110. sqlite3_errmsg(db_));
  111. throw DatException("Bad Database::GetNextFile() - sqlite3 - error", DATABASE_EXCEPTION);
  112. } catch (std::exception &e) {
  113. fprintf(stderr, "Bad Database::GetNextFile() - caught exception %s\n", e.what());
  114. return SubfileData();
  115. }
  116. }
  117. bool Database::RemoveDatabase() {
  118. try {
  119. if (db_ == nullptr)
  120. throw DatException("Bad Database::RemoveDatabase() - database hasn't been opened!", DATABASE_EXCEPTION);
  121. throw DatException("Database::RemoveDatabase() haven't been implemented yet...", DATABASE_EXCEPTION);
  122. // TODO: Implement function
  123. } catch (std::exception &e) {
  124. fprintf(stderr, "Bad Database::RemoveDatabase() - caught exception %s\n", e.what());
  125. return false;
  126. }
  127. }
  128. bool Database::ClearDatabase() {
  129. try {
  130. if (db_ == nullptr)
  131. throw DatException("Bad Database::ClearDatabase() - database hasn't been opened!", DATABASE_EXCEPTION);
  132. ExecSql(ClearTableCommand_);
  133. return true;
  134. } catch (std::exception &e) {
  135. fprintf(stderr, "Bad Database::ClearDatabase() - caught exception %s\n", e.what());
  136. return false;
  137. }
  138. }
  139. size_t Database::CountRows() {
  140. try {
  141. int result = sqlite3_step(get_rows_number_request_);
  142. if (result == SQLITE_ERROR) {
  143. fprintf(stderr, "ERROR: Bad Database::CountRows() - Error when counting rows %s\n",
  144. sqlite3_errmsg(db_));
  145. return 0;
  146. }
  147. long long res = sqlite3_column_int64(get_rows_number_request_, 0);
  148. sqlite3_reset(get_rows_number_request_);
  149. return size_t(res);
  150. } catch (std::exception &e) {
  151. fprintf(stderr, "Bad Database::CountRows() - caught exception %s\n", e.what());
  152. return 0;
  153. }
  154. }
  155. }