adatabase.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. #include "adatabase.h"
  2. namespace experimental {
  3. ADataBase* ADataBase::instance = nullptr;
  4. ADataBase* ADataBase::getInstance()
  5. {
  6. if(!instance)
  7. instance = new ADataBase();
  8. return instance;
  9. }
  10. bool ADataBase::connect()
  11. {
  12. const QString driver("QSQLITE");
  13. if (!QSqlDatabase::isDriverAvailable(driver))
  14. return false;
  15. QDir directory("data");
  16. QString databaseLocation = directory.filePath("logbook.db");
  17. QSqlDatabase db = QSqlDatabase::addDatabase(driver);
  18. db.setDatabaseName(databaseLocation);
  19. if (!db.open())
  20. return false;
  21. DEB("Database connection established.");
  22. // Enable foreign key restrictions
  23. QSqlQuery query("PRAGMA foreign_keys = ON;");
  24. tableNames = db.tables();
  25. QStringList columnNames;
  26. for (const auto &table : tableNames) {
  27. columnNames.clear();
  28. QSqlRecord fields = db.record(table);
  29. for (int i = 0; i < fields.count(); i++) {
  30. columnNames.append(fields.field(i).name());
  31. tableColumns.insert(table, columnNames);
  32. }
  33. }
  34. DEB("Database Tables: " << tableNames);
  35. return true;
  36. }
  37. void ADataBase::disconnect()
  38. {
  39. auto db = ADataBase::database();
  40. db.close();
  41. db.removeDatabase(db.connectionName());
  42. DEB("Database connection closed.");
  43. }
  44. QSqlDatabase ADataBase::database()
  45. {
  46. return QSqlDatabase::database("qt_sql_default_connection");
  47. }
  48. bool ADataBase::commit(Entry entry)
  49. {
  50. if (exists(entry)) {
  51. return update(entry);
  52. } else {
  53. return insert(entry);
  54. }
  55. }
  56. bool ADataBase::remove(Entry entry)
  57. {
  58. if (!exists(entry)) {
  59. DEB("Error: Entry does not exist.");
  60. return false;
  61. }
  62. QString statement = "DELETE FROM " + entry.getPosition().tableName +
  63. " WHERE ROWID=" + QString::number(entry.getPosition().rowId);
  64. QSqlQuery q(statement);
  65. if (q.lastError().type() == QSqlError::NoError)
  66. {
  67. DEB("Entry " << entry.getPosition().tableName << entry.getPosition().rowId << " removed.");
  68. emit commitSuccessful();
  69. return true;
  70. } else {
  71. DEB("Unable to delete.");
  72. DEB("Query: " << statement);
  73. DEB("Query Error: " << q.lastError().text());
  74. emit sqlError(q.lastError(), statement);
  75. return false;
  76. }
  77. }
  78. bool ADataBase::exists(Entry entry)
  79. {
  80. if(entry.getPosition() == DEFAULT_PILOT_POSITION)
  81. return false;
  82. //Check database for row id
  83. QString statement = "SELECT COUNT(*) FROM " + entry.getPosition().tableName +
  84. " WHERE ROWID=" + QString::number(entry.getPosition().rowId);
  85. //this returns either 1 or 0 since row ids are unique
  86. QSqlQuery q(statement);
  87. q.next();
  88. int rowId = q.value(0).toInt();
  89. if (rowId) {
  90. DEB("Entry " << entry.getPosition() << " exists.");
  91. return true;
  92. } else {
  93. DEB("Entry does not exist.");
  94. return false;
  95. }
  96. }
  97. bool ADataBase::update(Entry updated_entry)
  98. {
  99. auto data = updated_entry.getData();
  100. QString statement = "UPDATE " + updated_entry.getPosition().tableName + " SET ";
  101. for (auto i = data.constBegin(); i != data.constEnd(); ++i) {
  102. if (i.key() != QString()) {
  103. statement += i.key() + QLatin1String("=\"") + i.value() + QLatin1String("\", ");
  104. } else {
  105. DEB(i.key() << "is empty key. skipping.");
  106. }
  107. }
  108. statement.chop(2); // Remove last comma
  109. statement.append(QLatin1String(" WHERE ROWID=") + QString::number(updated_entry.getPosition().rowId));
  110. DEB("UPDATE QUERY: " << statement);
  111. QSqlQuery q(statement);
  112. if (q.lastError().type() == QSqlError::NoError)
  113. {
  114. DEB("Entry successfully committed.");
  115. emit commitSuccessful();
  116. return true;
  117. } else {
  118. DEB("Unable to commit.");
  119. DEB("Query: " << statement);
  120. DEB("Query Error: " << q.lastError().text());
  121. emit sqlError(q.lastError(), statement);
  122. return false;
  123. }
  124. }
  125. bool ADataBase::insert(Entry new_entry)
  126. {
  127. auto data = new_entry.getData();
  128. DEB("Inserting...");
  129. QString statement = "INSERT INTO " + new_entry.getPosition().tableName + QLatin1String(" (");
  130. QMap<QString, QString>::iterator i;
  131. for (i = data.begin(); i != data.end(); ++i) {
  132. statement += i.key() + QLatin1String(", ");
  133. }
  134. statement.chop(2);
  135. statement += QLatin1String(") VALUES (");
  136. for (i = data.begin(); i != data.end(); ++i) {
  137. statement += QLatin1String("\"") + i.value() + QLatin1String("\", ");
  138. }
  139. statement.chop(2);
  140. statement += QLatin1String(")");
  141. QSqlQuery q(statement);
  142. //check result.
  143. if (q.lastError().type() == QSqlError::NoError)
  144. {
  145. DEB("Entry successfully committed.");
  146. emit commitSuccessful();
  147. return true;
  148. } else {
  149. DEB("Unable to commit.");
  150. DEB("Query: " << statement);
  151. DEB("Query Error: " << q.lastError().text());
  152. emit sqlError(q.lastError(), statement);
  153. return false;
  154. }
  155. }
  156. TableData ADataBase::getEntryData(DataPosition data_position)
  157. {
  158. // check table exists
  159. if (!tableNames.contains(data_position.first)) {
  160. DEB(data_position.first << " not a table in the database. Unable to retreive Entry data.");
  161. return TableData();
  162. }
  163. //Check Database for rowId
  164. QString statement = "SELECT COUNT(*) FROM " + data_position.first
  165. + " WHERE ROWID=" + QString::number(data_position.second);
  166. QSqlQuery check_query(statement);
  167. if (check_query.lastError().type() != QSqlError::NoError) {
  168. DEB("SQL error: " << check_query.lastError().text());
  169. DEB("Statement: " << statement);
  170. return TableData();
  171. }
  172. check_query.next();
  173. if (check_query.value(0).toInt() == 0) {
  174. DEB("No Entry found for row id: " << data_position.second );
  175. return TableData();
  176. }
  177. // Retreive TableData
  178. DEB("Retreiving data for row id: " << data_position.second);
  179. statement = "SELECT * FROM " + data_position.first
  180. + " WHERE ROWID=" + QString::number(data_position.second);
  181. QSqlQuery select_query(statement);
  182. if (select_query.lastError().type() != QSqlError::NoError) {
  183. DEB("SQL error: " << select_query.lastError().text());
  184. DEB("Statement: " << statement);
  185. return TableData();
  186. }
  187. select_query.next();
  188. TableData entry_data;
  189. for (const auto &column : tableColumns.value(data_position.first)) {
  190. entry_data.insert(column, select_query.value(column).toString());
  191. }
  192. return entry_data;
  193. }
  194. Entry ADataBase::getEntry(DataPosition data_position)
  195. {
  196. Entry entry(data_position);
  197. entry.setData(getEntryData(data_position));
  198. return entry;
  199. }
  200. PilotEntry ADataBase::getPilotEntry(RowId row_id)
  201. {
  202. PilotEntry pilotEntry(row_id);
  203. pilotEntry.setData(getEntryData(pilotEntry.getPosition()));
  204. return pilotEntry;
  205. }
  206. QStringList ADataBase::getCompletionList(ADataBase::CompleterTarget target)
  207. {
  208. QString statement;
  209. switch (target) {
  210. case pilots:
  211. statement.append("SELECT piclastname||\",\"||picfirstname FROM pilots");
  212. break;
  213. case aircraft:
  214. statement.append("SELECT make||\" \"||model FROM aircraft WHERE model IS NOT NULL "
  215. "UNION "
  216. "SELECT make||\" \"||model||\"-\"||variant FROM aircraft WHERE variant IS NOT NULL");
  217. break;
  218. case airports:
  219. statement.append("SELECT icao FROM airports UNION SELECT iata FROM airports");
  220. break;
  221. case registrations:
  222. statement.append("SELECT registration FROM tails");
  223. break;
  224. case companies:
  225. statement.append("SELECT company FROM pilots");
  226. break;
  227. }
  228. QSqlQuery query(statement);
  229. if(!query.first())
  230. emit sqlError(query.lastError(), statement);
  231. query.previous();
  232. QStringList completer_list;
  233. while (query.next())
  234. completer_list.append(query.value(0).toString());
  235. completer_list.sort();
  236. completer_list.removeAll(QString(""));
  237. completer_list.removeDuplicates();
  238. return completer_list;
  239. }
  240. ADataBase* aDB() { return ADataBase::getInstance(); }
  241. }