database.cpp 6.2 KB

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