database.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #include "database.hpp"
  2. #include <iostream>
  3. namespace db {
  4. // Объект работы с БД
  5. static sqlite3* DB;
  6. void databaseInit(std::string filename) {
  7. db_path = filename;
  8. }
  9. int databaseOpen() {
  10. return sqlite3_open(db_path.c_str(), &DB);
  11. }
  12. void databaseClose() {
  13. sqlite3_close(DB);
  14. }
  15. // Для каждого запроса на создание таблиц из массива quieries мы вызываем
  16. // sqlite3_exec. Если запрос провалится, выводим сообщение об ошибке
  17. void createTables() {
  18. char* message_error;
  19. int status;
  20. std::array<std::string, 3> queries = {
  21. "CREATE TABLE IF NOT EXISTS \"author\" (\
  22. \"id\" INTEGER,\
  23. \"yt_id\" TEXT,\
  24. \"name\" TEXT,\
  25. PRIMARY KEY(\"id\" AUTOINCREMENT)\
  26. )",
  27. "CREATE TABLE IF NOT EXISTS \"video\" (\
  28. \"id\" INTEGER,\
  29. \"yt_id\" TEXT,\
  30. \"title\" TEXT NOT NULL,\
  31. \"description\" TEXT NOT NULL,\
  32. \"author_id\" INTEGER NOT NULL,\
  33. \"published_at\" DATETIME NOT NULL,\
  34. \"dur_h\" INTEGER NOT NULL DEFAULT 0,\
  35. \"dur_m\" INTEGER NOT NULL DEFAULT 0,\
  36. \"dur_s\" INTEGER NOT NULL DEFAULT 0,\
  37. \"views_count\" INTEGER NOT NULL DEFAULT 0,\
  38. \"likes_count\" INTEGER NOT NULL DEFAULT 0,\
  39. \"rate_status\" INTEGER NOT NULL DEFAULT 0,\
  40. PRIMARY KEY(\"id\" AUTOINCREMENT)\
  41. )",
  42. "PRAGMA journal_mode=WAL"
  43. };
  44. databaseOpen();
  45. for (int i = 0; i < 3; i++) {
  46. status = sqlite3_exec(DB, queries[i].c_str(), NULL, 0, &message_error);
  47. if (status != SQLITE_OK) {
  48. std::cerr << "Error creating tables" << std::endl;
  49. sqlite3_free(message_error);
  50. databaseClose();
  51. return;
  52. }
  53. }
  54. databaseClose();
  55. }
  56. bool getVideoByYTID(std::string yt_id, video* output) {
  57. sqlite3_stmt* stmt;
  58. std::string query =
  59. "SELECT v.id, v.yt_id, v.title, v.description, a.id, a.yt_id, a.name,"
  60. " v.published_at, v.views_count, v.rate_status"
  61. " FROM video v LEFT JOIN author a ON v.author_id=a.id"
  62. " WHERE v.yt_id=?";
  63. databaseOpen();
  64. author video_author;
  65. // Подготовка
  66. sqlite3_prepare_v2(DB, query.c_str(), query.length(), &stmt, nullptr);
  67. // Привязка данных
  68. sqlite3_bind_text(stmt, 1, yt_id.c_str(), yt_id.length(), SQLITE_STATIC);
  69. // Выполнение
  70. int result = sqlite3_step(stmt);
  71. if (result == SQLITE_DONE) {
  72. // Видео не найдено
  73. databaseClose();
  74. return false;
  75. }
  76. // Заполнение данными
  77. // unsigned const char* конвертируется в std::string
  78. // https://stackoverflow.com/a/804131
  79. video_author.id = sqlite3_column_int(stmt, 4);
  80. video_author.yt_id = std::string(reinterpret_cast<const char*>(
  81. sqlite3_column_text(stmt, 5)
  82. ));
  83. video_author.name = Glib::ustring(reinterpret_cast<const char*>(
  84. sqlite3_column_text(stmt, 6)
  85. ));
  86. output->id = sqlite3_column_int(stmt, 0);
  87. output->yt_id = std::string(reinterpret_cast<const char*>(
  88. sqlite3_column_text(stmt, 1)
  89. ));
  90. output->title = Glib::ustring(reinterpret_cast<const char*>(
  91. sqlite3_column_text(stmt, 2)
  92. ));
  93. output->description = Glib::ustring(reinterpret_cast<const char*>(
  94. sqlite3_column_text(stmt, 3)
  95. ));
  96. output->published_at = std::string(reinterpret_cast<const char*>(
  97. sqlite3_column_text(stmt, 7)
  98. ));
  99. output->views_count = sqlite3_column_int(stmt, 8);
  100. output->rate_status = sqlite3_column_int(stmt, 9);
  101. output->author_obj = video_author;
  102. // Завершение
  103. sqlite3_finalize(stmt);
  104. databaseClose();
  105. return true;
  106. }
  107. bool getAuthorByYTID(std::string yt_id, author* output) {
  108. sqlite3_stmt* stmt;
  109. std::string query =
  110. "SELECT a.id, a.name"
  111. " FROM author a"
  112. " WHERE a.yt_id=?";
  113. databaseOpen();
  114. // Подготовка
  115. sqlite3_prepare_v2(DB, query.c_str(), query.length(), &stmt, nullptr);
  116. // Привязка данных
  117. sqlite3_bind_text(stmt, 1, yt_id.c_str(), yt_id.length(), SQLITE_STATIC);
  118. // Выполнение
  119. int result = sqlite3_step(stmt);
  120. if (result == SQLITE_DONE) {
  121. // Автор не найден
  122. databaseClose();
  123. return false;
  124. }
  125. // Заполнение данными
  126. output->id = sqlite3_column_int(stmt, 0);
  127. output->name = std::string(reinterpret_cast<const char*>(
  128. sqlite3_column_text(stmt, 1)
  129. ));
  130. // Завершение
  131. sqlite3_finalize(stmt);
  132. databaseClose();
  133. return true;
  134. }
  135. void addAuthor(author* a) {
  136. sqlite3_stmt* stmt;
  137. std::string query =
  138. "INSERT INTO author (yt_id, name) VALUES(?, ?)";
  139. databaseOpen();
  140. sqlite3_prepare_v2(DB, query.c_str(), query.length(), &stmt, nullptr);
  141. sqlite3_bind_text(stmt, 1, a->yt_id.c_str(), a->yt_id.length(), SQLITE_STATIC);
  142. sqlite3_bind_text(stmt, 2, a->name.c_str(), a->name.bytes(), SQLITE_STATIC);
  143. sqlite3_step(stmt);
  144. a->id = sqlite3_last_insert_rowid(DB);
  145. sqlite3_finalize(stmt);
  146. databaseClose();
  147. }
  148. void addVideo(video* v)
  149. {
  150. sqlite3_stmt* stmt;
  151. std::string query =
  152. "INSERT INTO video (yt_id, title, description, author_id, published_at,"
  153. " views_count, rate_status)"
  154. " VALUES(?, ?, ?, ?, ?, ?, ?)";
  155. databaseOpen();
  156. sqlite3_prepare_v2(DB, query.c_str(), query.length(), &stmt, nullptr);
  157. sqlite3_bind_text(stmt, 1, v->yt_id.c_str(), v->yt_id.length(), SQLITE_STATIC);
  158. sqlite3_bind_text(stmt, 2, v->title.c_str(), v->title.bytes(), SQLITE_STATIC);
  159. sqlite3_bind_text(stmt, 3, v->description.c_str(), v->description.bytes(), SQLITE_STATIC);
  160. sqlite3_bind_int(stmt, 4, v->author_obj.id);
  161. sqlite3_bind_text(stmt, 5, v->published_at.c_str(), v->published_at.length(), SQLITE_STATIC);
  162. sqlite3_bind_int(stmt, 6, v->views_count);
  163. sqlite3_bind_int(stmt, 7, static_cast<int>(v->rate_status));
  164. sqlite3_step(stmt);
  165. v->id = sqlite3_last_insert_rowid(DB);
  166. sqlite3_finalize(stmt);
  167. databaseClose();
  168. }
  169. void setVideoRating(std::string yt_id, int rating)
  170. {
  171. sqlite3_stmt* stmt;
  172. std::string query =
  173. "UPDATE video SET rate_status=? WHERE yt_id=?";
  174. databaseOpen();
  175. sqlite3_prepare_v2(DB, query.c_str(), query.length(), &stmt, nullptr);
  176. sqlite3_bind_int(stmt, 1, rating);
  177. sqlite3_bind_text(stmt, 2, yt_id.c_str(), yt_id.length(), SQLITE_STATIC);
  178. std::cout << sqlite3_step(stmt);
  179. sqlite3_finalize(stmt);
  180. databaseClose();
  181. }
  182. int getVideoRating(std::string yt_id)
  183. {
  184. sqlite3_stmt* stmt;
  185. std::string query =
  186. "SELECT v.rate_status"
  187. " FROM video v"
  188. " WHERE v.yt_id=?";
  189. databaseOpen();
  190. sqlite3_prepare_v2(DB, query.c_str(), query.length(), &stmt, nullptr);
  191. sqlite3_bind_text(stmt, 1, yt_id.c_str(), yt_id.length(), SQLITE_STATIC);
  192. // Выполнение
  193. int output;
  194. int result = sqlite3_step(stmt);
  195. if (result == SQLITE_DONE) {
  196. // Видео не найдено
  197. output = 3;
  198. }
  199. output = sqlite3_column_int(stmt, 0);
  200. databaseClose();
  201. return output;
  202. }
  203. }