Advertisement
Guest User

hi ron

a guest
Mar 19th, 2019
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.71 KB | None | 0 0
  1. #include "DatabaseAccess.h"
  2.  
  3. int tempNum = 0; // Functions will save things such as ID numbers to communicate with other functions
  4. std::list<Album> m_albums;
  5. std::list<User> m_users;
  6. std::list<Picture> m_pictures;
  7. std::list<int> m_tags;
  8.  
  9. // --------------------- MY FUNCTIONS ---------------------
  10.  
  11. /*
  12. Function will get an SQL statement as well as a callback function, and executes the statement.
  13. Returns whether the execution was sucessful.
  14. */
  15. bool DatabaseAccess::executeSQL(const std::string sqlStatement, int(*func)(void *, int, char **, char **))
  16. {
  17. char *errMessage = nullptr;
  18. int res = sqlite3_exec(db, sqlStatement.c_str(), func, nullptr, &errMessage);
  19. if (res != SQLITE_OK) {
  20. std::cout << errMessage << std::endl;
  21. return false;
  22. }
  23. return true;
  24. }
  25.  
  26. /*
  27. Callback funcion that gets an ID number from its caller and saves it to a global variable.
  28. Note: If it gets more than one value, or no values, the function will save ERROR_NUM (-1) to the global variable.
  29. */
  30. int saveToGlobal(void *data, int argc, char **argv, char **azColName)
  31. {
  32. if (argc != 1)
  33. tempNum = ERROR_NUM;
  34. else tempNum = atoi(argv[0]);
  35. return 0;
  36. }
  37.  
  38. /*
  39. Callback function that gets a table of users and prints it.
  40. */
  41. int callbackUsersPrinter(void *data, int argc, char **argv, char **azColName)
  42. {
  43. if (argc < 2)
  44. return 1;
  45. for (int i = 0; i < argc; i += 2)
  46. std::cout << " - @" << argv[i] << " - " << argv[i + 1] << std::endl;
  47. return 0;
  48. }
  49.  
  50. /*
  51. Callback function that gets a table of albums and prints it.
  52. */
  53. int callbackAlbumsPrinter(void *data, int argc, char **argv, char **azColName)
  54. {
  55. if (argc < 3)
  56. return 1;
  57. std::cout << " - @" << argv[0] << " - " << argv[1] << std::endl;
  58. return 0;
  59. }
  60.  
  61. /*
  62. Callback funcion that gets a user from its caller and saves it to a global (list) variable, and returns true.
  63. Note: If it gets no values, the function will save ERROR_NUM (-1) to the global variable and return false.
  64. */
  65. int saveUser(void *data, int argc, char **argv, char **azColName)
  66. {
  67. if (argc < 2)
  68. {
  69. tempNum = ERROR_NUM;
  70. return 1;
  71. }
  72. tempNum = 0;
  73. m_users.push_back(User(atoi(argv[0]), argv[1]));
  74. return 0;
  75. }
  76.  
  77. /*
  78. Callback funcion that gets a tag from its caller and saves it to a global (list) variable, and returns true.
  79. Note: If it gets no values, the function will save ERROR_NUM (-1) to the global variable and return false.
  80. */
  81. int saveTag(void *data, int argc, char **argv, char **azColName)
  82. {
  83. if (argc < 1)
  84. {
  85. tempNum = ERROR_NUM;
  86. return 1;
  87. }
  88. tempNum = 0;
  89. m_tags.push_back(atoi(argv[0]));
  90. return 0;
  91. }
  92.  
  93. /*
  94. Callback funcion that gets a picture from its caller and saves it to a global (list) variable, and returns true.
  95. Note: If it gets no values, the function will save ERROR_NUM (-1) to the global variable and return false.
  96. */
  97. int savePicture(void *data, int argc, char **argv, char **azColName)
  98. {
  99. if (argc < 4)
  100. {
  101. tempNum = ERROR_NUM;
  102. return 1;
  103. }
  104. tempNum = 0;
  105. Picture p = Picture(atoi(argv[0]), argv[1], argv[2], argv[3]);
  106. m_pictures.push_back(p);
  107. return 0;
  108. }
  109.  
  110. /*
  111. Callback funcion that gets an album from its caller and saves it to a global (vector) variable, and returns true.
  112. Note: If it gets no values, the function will save ERROR_NUM (-1) to the global variable and return false.
  113. */
  114. int saveAlbum(void *data, int argc, char **argv, char **azColName)
  115. {
  116. if (argc < 3)
  117. {
  118. tempNum = ERROR_NUM;
  119. return 1;
  120. }
  121. tempNum = 0;
  122. Album temp = Album(atoi(argv[2]), argv[0], argv[1]);
  123. m_albums.push_back(temp);
  124. return 0;
  125. }
  126.  
  127. /*
  128. Function gets an album name and returns its ID number.
  129. */
  130. int DatabaseAccess::getUserIdByName(const std::string & userName)
  131. {
  132. std::string sql = "select id from users where name='" + userName + "';";
  133. executeSQL(sql, saveToGlobal);
  134. if (tempNum == ERROR_NUM)
  135. throw "No user with name \"" + userName + "\" found.";
  136. return tempNum;
  137. }
  138.  
  139. /*
  140. Function gets an album name and returns its ID number.
  141. */
  142. int DatabaseAccess::getAlbumIdByName(const std::string & albumName)
  143. {
  144. std::string sql = "select id from albums where name='" + albumName + "';";
  145. executeSQL(sql, saveToGlobal);
  146. if (tempNum == ERROR_NUM)
  147. throw "No album with name \"" + albumName + "\" found.";
  148. return tempNum;
  149. }
  150.  
  151. /*
  152. Function gets a picture name and the ID of the picture's album, and returns its ID number.
  153. */
  154. int DatabaseAccess::getPictureIdByName(const std::string & pictureName, int albumId)
  155. {
  156. std::string sql = "select id from pictures where name='" + pictureName + "' and album_id=" + std::to_string(albumId) + ";";
  157. executeSQL(sql, saveToGlobal);
  158. if (tempNum == ERROR_NUM)
  159. throw "No picture with name \"" + pictureName + "\" and album ID " + std::to_string(albumId) + " found.";
  160. return tempNum;
  161. }
  162.  
  163. // ------------------------ QUERIES ------------------------
  164.  
  165. /*
  166. Function opens a database from and existing .sqlite file with path DB_FILE_NAME.
  167. Returns whether database was opened successfully.
  168. */
  169. bool DatabaseAccess::open()
  170. {
  171. int file_exist = _access(DB_FILE_NAME, 0);
  172. int res = sqlite3_open(DB_FILE_NAME, &db);
  173. if (res != SQLITE_OK) {
  174. db = nullptr;
  175. std::cout << "Failed to open Database" << std::endl;
  176. return -1;
  177. }
  178. if (file_exist != 0) {
  179. std::cout << "Database does not exist" << std::endl;
  180. return false;
  181. }
  182. return true;
  183. }
  184.  
  185. /*
  186. Function closes the database.
  187. */
  188. void DatabaseAccess::close()
  189. {
  190. sqlite3_close(db);
  191. db = nullptr;
  192. }
  193.  
  194. /*
  195. Function clears the memory of all objects created by this class.
  196. */
  197. void DatabaseAccess::clear()
  198. {
  199. m_users.clear();
  200. m_albums.clear();
  201. m_pictures.clear();
  202. m_tags.clear();
  203. }
  204.  
  205. /*
  206. Function returns the user which has been tagged the most.
  207. */
  208. User DatabaseAccess::getTopTaggedUser()
  209. {
  210. std::string sql = "select user_id from tags group by user_id order by count(*) desc limit 1;";
  211. executeSQL(sql, saveToGlobal);
  212. return getUser(tempNum);
  213. }
  214.  
  215. /*
  216. Function returns the picture which has been tagged the most.
  217. */
  218. Picture DatabaseAccess::getTopTaggedPicture()
  219. {
  220. std::string sql = "select picture_id from tags group by picture_id order by count(*) desc limit 1;";
  221. executeSQL(sql, saveToGlobal);
  222. return getPicture(tempNum);
  223. }
  224.  
  225. /*
  226. Function gets a user and returns a list of all pictures tagged to the user.
  227. */
  228. std::list<Picture> DatabaseAccess::getTaggedPicturesOfUser(const User & user)
  229. {
  230. std::string sql = "select id, name, location, creation_date from pictures inner join tags on tags.picture_id=pictures.id where user_id=" + std::to_string(user.getId()) + ';';
  231. m_pictures.clear();
  232. executeSQL(sql, savePicture);
  233. for (Picture& p : m_pictures)
  234. fillPicture(p);
  235. return m_pictures;
  236. }
  237.  
  238. /*
  239. Function gets a picture ID and returns a list of all the user IDs tagged in the picture.
  240. */
  241. std::list<int> DatabaseAccess::getTagsInPicture(int pictureId)
  242. {
  243. std::string sql = "select user_id from tags where picture_id=" + std::to_string(pictureId) + ';';
  244. m_tags.clear();
  245. executeSQL(sql, saveTag);
  246. return m_tags;
  247. }
  248.  
  249. // --------------------- ALBUM RELATED ---------------------
  250.  
  251. /*
  252. This function does nothing, and is just here to fulfil the requirements of the IDataAccess interface.
  253. */
  254. void DatabaseAccess::closeAlbum(Album & pAlbum) { }
  255.  
  256. /*
  257. Function prints a list of all albums currently in the database.
  258. */
  259. void DatabaseAccess::printAlbums()
  260. {
  261. std::cout << "Album list:" << std::endl << "-----------" << std::endl;
  262. for (const Album& album : getAlbums())
  263. std::cout << std::setw(5) << "* " << album;
  264. }
  265.  
  266. /*
  267. Function returns a list of all albums currently in the database.
  268. */
  269. const std::list<Album> DatabaseAccess::getAlbums()
  270. {
  271. std::string sql = "select name, creation_date, user_id from albums;";
  272. m_albums.clear();
  273. executeSQL(sql, saveAlbum);
  274. for (Album a : m_albums)
  275. fillAlbum(a);
  276. return m_albums;
  277. }
  278.  
  279. /*
  280. Function gets a user and returns all albums which are owned by that user.
  281. */
  282. const std::list<Album> DatabaseAccess::getAlbumsOfUser(const User & user)
  283. {
  284. std::string sql = "select name, creation_date, user_id from albums where user_id='" + std::to_string(user.getId()) + "';";
  285. m_albums.clear();
  286. executeSQL(sql, saveAlbum);
  287. for (Album a : m_albums)
  288. fillAlbum(a);
  289. return m_albums;
  290. //return std::list<Album>(m_albums.begin(), m_albums.end());
  291. }
  292.  
  293. /*
  294. Function gets an album and adds it to the database.
  295. */
  296. void DatabaseAccess::createAlbum(const Album & album)
  297. {
  298. std::string sql = "insert into albums (name, creation_date, user_id) values ('" + album.getName() + "','" + album.getCreationDate() + "'," + std::to_string(album.getOwnerId()) + ");";
  299. executeSQL(sql, nullptr);
  300. }
  301.  
  302. /*
  303. Function deletes an album by its name and its owner's user ID.
  304. */
  305. void DatabaseAccess::deleteAlbum(const std::string & albumName, int userId)
  306. {
  307. for (Picture p : openAlbum(albumName).getPictures())
  308. removePictureFromAlbumByName(albumName, p.getName());
  309. std::string sql = "delete from albums where user_id=" + std::to_string(userId) + " and name='" + albumName + "';";
  310. executeSQL(sql, nullptr);
  311. }
  312.  
  313. /*
  314. Function gets an album name and a user ID, and returns whether an album with those parameters exists in the database.
  315. */
  316. bool DatabaseAccess::doesAlbumExists(const std::string & albumName, int userId)
  317. {
  318. std::string sql = "select count (*) from albums where name='" + albumName + "' and user_id=" + std::to_string(userId) + ';';
  319. executeSQL(sql, saveToGlobal);
  320. return tempNum != 0;
  321. }
  322.  
  323. /*
  324. Function gets an album name and returns an object representing the corresponding album.
  325. */
  326. Album DatabaseAccess::openAlbum(const std::string & albumName)
  327. {
  328. std::string sql = "select name, creation_date, user_id from albums where name='" + albumName + "';";
  329. m_albums.clear();
  330. executeSQL(sql, saveAlbum);
  331. Album a = m_albums.back();
  332. fillAlbum(a);
  333. return a;
  334. }
  335.  
  336. /*
  337. Function gets a reference to an Album object and fills it with the pictures it should have according to the database.
  338. */
  339. void DatabaseAccess::fillAlbum(Album& a)
  340. {
  341. std::string sql = "select * from pictures where album_id=" + std::to_string(getAlbumIdByName(a.getName())) + ";";
  342. m_pictures.clear();
  343. executeSQL(sql, savePicture);
  344. for (Picture p : m_pictures)
  345. {
  346. fillPicture(p);
  347. a.addPicture(p);
  348. }
  349. }
  350.  
  351. // -------------------- PICTURE RELATED --------------------
  352.  
  353. /*
  354. Function gets an album name and a picture, and adds said picture to the album.
  355. */
  356. void DatabaseAccess::addPictureToAlbumByName(const std::string & albumName, const Picture & picture)
  357. {
  358. int albumId = getAlbumIdByName(albumName);
  359. std::string sql = "insert into pictures (name, location, creation_date, album_id) values ('" + picture.getName() + "','" + picture.getPath() + "','" + picture.getCreationDate() + "'," + std::to_string(albumId) + ");";
  360. executeSQL(sql, nullptr);
  361. }
  362.  
  363. /*
  364. Function gets an album name and a picture name, and deletes said pictures.
  365. */
  366. void DatabaseAccess::removePictureFromAlbumByName(const std::string & albumName, const std::string & pictureName)
  367. {
  368. int albumId = getAlbumIdByName(albumName);
  369. for (int i : getTagsInPicture(getPictureIdByName(pictureName, albumId)))
  370. untagUserInPicture(albumName, pictureName, i);
  371. std::string sql = "delete from pictures where album_id='" + std::to_string(albumId) + "' and name='" + pictureName + "';";
  372. executeSQL(sql, nullptr);
  373. }
  374.  
  375. /*
  376. Function creates a new tag based on the album's name, the picture's name, and the user's ID.
  377. */
  378. void DatabaseAccess::tagUserInPicture(const std::string & albumName, const std::string & pictureName, int userId)
  379. {
  380. int albumId = getAlbumIdByName(albumName);
  381. int pictureId = getPictureIdByName(pictureName, albumId);
  382. std::string sql = "insert into tags (picture_id, user_id) values (" + std::to_string(pictureId) + ',' + std::to_string(userId) + ");";
  383. executeSQL(sql, nullptr);
  384. }
  385.  
  386. /*
  387. Function deletes a tag based on the album's name, the picture's name, and the user's ID.
  388. */
  389. void DatabaseAccess::untagUserInPicture(const std::string & albumName, const std::string & pictureName, int userId)
  390. {
  391. int albumId = getAlbumIdByName(albumName);
  392. int pictureId = getPictureIdByName(pictureName, albumId);
  393. std::string sql = "delete from tags where picture_id=" + std::to_string(pictureId) + " and user_id=" + std::to_string(userId) + ";";
  394. executeSQL(sql, nullptr);
  395. }
  396.  
  397. /*
  398. Function gets a picture ID and returns an object representing the corresponding picture.
  399. */
  400. Picture DatabaseAccess::getPicture(int pictureId)
  401. {
  402. std::string sql = "select * from pictures where id=" + std::to_string(pictureId) + ';';
  403. m_pictures.clear();
  404. executeSQL(sql, savePicture);
  405. Picture p = m_pictures.back();
  406. fillPicture(p);
  407. return p;
  408. }
  409.  
  410. /*
  411. Function gets a reference to a Picture object and fills it with the tags it should have according to the database.
  412. */
  413. void DatabaseAccess::fillPicture(Picture& p)
  414. {
  415. for (int i : getTagsInPicture(p.getId()))
  416. p.tagUser(i);
  417. }
  418.  
  419. // --------------------- USER RELATED ---------------------
  420.  
  421. /*
  422. Function prints all users in the database.
  423. */
  424. void DatabaseAccess::printUsers()
  425. {
  426. std::string sql = "select * from users;";
  427. executeSQL(sql, callbackUsersPrinter);
  428. }
  429.  
  430. /*
  431. Function gets a user ID and returns an object representing the corresponding user.
  432. */
  433. User DatabaseAccess::getUser(int userId)
  434. {
  435. std::string sql = "select * from users where id=" + std::to_string(userId) + ';';
  436. executeSQL(sql, saveUser);
  437. return m_users.back();
  438. }
  439.  
  440. /*
  441. Function gets a user and adds it to the database.
  442. Note: Only the name is kept, the id of the user may change.
  443. */
  444. void DatabaseAccess::createUser(User & user)
  445. {
  446. std::string sql = "insert into users (name) values ('" + user.getName() + "');";
  447. executeSQL(sql, nullptr);
  448. user.setId(getUserIdByName(user.getName()));
  449. }
  450.  
  451. /*
  452. Function gets a user and deletes it from the database.
  453. Note: Deletion is based on ID alone.
  454. */
  455. void DatabaseAccess::deleteUser(const User & user)
  456. {
  457. for (Album a : getAlbumsOfUser(user))
  458. deleteAlbum(a.getName(), user.getId());
  459. std::string sql = "delete from users where id=" + std::to_string(user.getId()) + ";";
  460. executeSQL(sql, nullptr);
  461. }
  462.  
  463. /*
  464. Function gets a user ID and returns whether there exists a user with that ID in the database.
  465. */
  466. bool DatabaseAccess::doesUserExists(int userId)
  467. {
  468. std::string sql = "select count (*) from users where id=" + std::to_string(userId) + ';';
  469. executeSQL(sql, saveToGlobal);
  470. return tempNum != 0;
  471. }
  472.  
  473. // -------------------- USER STATISTICS --------------------
  474.  
  475. /*
  476. Function gets a user and returns the number of albums which are owned by the user.
  477. */
  478. int DatabaseAccess::countAlbumsOwnedOfUser(const User & user)
  479. {
  480. std::string sql = "select count (*) from albums where user_id=" + std::to_string(user.getId()) + ';';
  481. executeSQL(sql, saveToGlobal);
  482. return tempNum;
  483. }
  484.  
  485. /*
  486. Function gets a user and returns the number of albums which are tagged to the user.
  487. */
  488. int DatabaseAccess::countAlbumsTaggedOfUser(const User & user)
  489. {
  490. std::string sql = "select count(distinct pictures.album_id) from tags inner join pictures on tags.picture_id = pictures.id where user_id=" + std::to_string(user.getId()) + ';';;
  491. executeSQL(sql, saveToGlobal);
  492. return tempNum;
  493. }
  494.  
  495. /*
  496. Function gets a user and returns the number of tags which are tagged to the user.
  497. */
  498. int DatabaseAccess::countTagsOfUser(const User & user)
  499. {
  500. std::string sql = "select count (*) from tags where user_id=" + std::to_string(user.getId()) + ';';
  501. executeSQL(sql, saveToGlobal);
  502. return tempNum;
  503. }
  504.  
  505. /*
  506. Function gets a user, and returns the average number of tags that user has per album.
  507. */
  508. float DatabaseAccess::averageTagsPerAlbumOfUser(const User & user)
  509. {
  510. std::string sql = "select count(*) from tags where user_id=" + std::to_string(user.getId()) + ';';
  511. executeSQL(sql, saveToGlobal);
  512. float numTags = tempNum;
  513. sql = "select count(*) from albums";
  514. executeSQL(sql, saveToGlobal);
  515. float numAlbums = tempNum;
  516. return numTags / numAlbums;
  517. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement