adatabase.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. *openPilotLog - A FOSS Pilot Logbook Application
  3. *Copyright (C) 2020-2021 Felix Turowsky
  4. *
  5. *This program is free software: you can redistribute it and/or modify
  6. *it under the terms of the GNU General Public License as published by
  7. *the Free Software Foundation, either version 3 of the License, or
  8. *(at your option) any later version.
  9. *
  10. *This program is distributed in the hope that it will be useful,
  11. *but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. *GNU General Public License for more details.
  14. *
  15. *You should have received a copy of the GNU General Public License
  16. *along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. #ifndef ADATABASE_H
  19. #define ADATABASE_H
  20. #include <QPair>
  21. #include <QMap>
  22. #include <QString>
  23. #include <QDir>
  24. #include <QSqlDatabase>
  25. #include <QSqlDriver>
  26. #include <QSqlQuery>
  27. #include <QSqlError>
  28. #include <QSqlTableModel>
  29. #include <QSqlQuery>
  30. #include <QSqlRecord>
  31. #include <QSqlField>
  32. #include "src/database/adatabasetypes.h"
  33. #include "src/classes/aentry.h"
  34. #include "src/classes/apilotentry.h"
  35. #include "src/classes/atailentry.h"
  36. #include "src/classes/aaircraftentry.h"
  37. #include "src/classes/aflightentry.h"
  38. #include "src/classes/astandardpaths.h"
  39. #include "src/classes/acurrencyentry.h"
  40. #define SQLITE_DRIVER QStringLiteral("QSQLITE")
  41. /*!
  42. * \brief Convinience macro that returns instance of DataBase.
  43. * Instead of this:
  44. * DataBase::getInstance().commit(...)
  45. * Write this:
  46. * aDB->commit(...)
  47. */
  48. #define aDB ADatabase::instance()
  49. /*!
  50. * \brief The DBTarget enum lists database items that are
  51. * used by completers, for content matching or need to be accessed programatically.
  52. */
  53. enum class ADatabaseTarget
  54. {
  55. aircraft,
  56. airport_identifier_icao,
  57. airport_identifier_iata,
  58. airport_identifier_all,
  59. airport_names,
  60. pilots,
  61. registrations,
  62. companies,
  63. tails
  64. };
  65. // [G]: This is how we should handle custom "events" in the program.
  66. // In this case a custom error doesnt need to be built from scratch.
  67. // Find the type of error you want and extend it with a few tweaks.
  68. /*!
  69. * \brief Custom Database Error derived from QSqlError.
  70. * Extends text() adding "Database Error: " before the text.
  71. */
  72. class ADatabaseError : public QSqlError {
  73. public:
  74. ADatabaseError() = default;
  75. ADatabaseError(QString msg);
  76. QString text() const;
  77. };
  78. /*!
  79. * \brief The DB class encapsulates the SQL database by providing fast access
  80. * to hot database data.
  81. */
  82. class ADatabase : public QObject {
  83. Q_OBJECT
  84. private:
  85. static ADatabase* self;
  86. TableNames_T tableNames;
  87. TableColumns_T tableColumns;
  88. int databaseVersion;
  89. ADatabase();
  90. int checkDbVersion() const;
  91. public:
  92. ADatabaseError lastError;
  93. //const QDir databaseDir;
  94. const QFileInfo databaseFile;
  95. // Ensure DB is not copiable or assignable
  96. ADatabase(const ADatabase&) = delete;
  97. void operator=(const ADatabase&) = delete;
  98. static ADatabase* instance();
  99. int dbVersion() const;
  100. /*!
  101. * \brief Return the names of all tables in the database
  102. */
  103. TableNames_T getTableNames() const;
  104. /*!
  105. * \brief Return the names of a given table in the database.
  106. */
  107. ColumnNames_T getTableColumns(TableName_T table_name) const;
  108. /*!
  109. * \brief Updates the member variables tableNames and tableColumns with up-to-date layout information
  110. * if the database has been altered. This function is normally only required during database setup or maintenance.
  111. */
  112. void updateLayout();
  113. /*!
  114. * \brief ADatabase::sqliteVersion returns database sqlite version.
  115. * \return sqlite version string
  116. */
  117. const QString sqliteVersion() const;
  118. /*!
  119. * \brief Connect to the database and populate database information.
  120. */
  121. bool connect();
  122. /*!
  123. * \brief closes the database connection.
  124. */
  125. void disconnect();
  126. /*!
  127. * \brief Can be used to access the database connection.
  128. * \return The QSqlDatabase object pertaining to the connection.
  129. */
  130. static QSqlDatabase database();
  131. /*!
  132. * \brief Can be used to send a complex query to the database.
  133. * \param query - the full sql query statement
  134. * \param returnValues - the number of return values
  135. */
  136. QVector<QVariant> customQuery(QString statement, int return_values);
  137. /*!
  138. * \brief Checks if an entry exists in the database, based on position data
  139. */
  140. bool exists(AEntry entry);
  141. bool exists(DataPosition data_position);
  142. /*!
  143. * \brief commits an entry to the database, calls either insert or update,
  144. * based on position data
  145. */
  146. bool commit(AEntry entry);
  147. /*!
  148. * \brief Create new entry in the databse based on UserInput
  149. */
  150. bool insert(AEntry new_entry);
  151. /*!
  152. * \brief Updates entry in database from existing entry tweaked by the user.
  153. */
  154. bool update(AEntry updated_entry);
  155. /*!
  156. * \brief deletes an entry from the database.
  157. */
  158. bool remove(AEntry entry);
  159. /*!
  160. * \brief deletes a list of entries from the database. Optimised for speed when
  161. * deleting many entries.
  162. */
  163. bool removeMany(QList<DataPosition>);
  164. /*!
  165. * \brief retreive entry data from the database to create an entry object
  166. */
  167. RowData_T getEntryData(DataPosition data_position);
  168. /*!
  169. * \brief retreive an Entry from the database.
  170. */
  171. AEntry getEntry(DataPosition data_position);
  172. /*!
  173. * \brief retreives a PilotEntry from the database.
  174. *
  175. * This function is a wrapper for DataBase::getEntry(DataPosition),
  176. * where the table is already set and which returns a PilotEntry
  177. * instead of an Entry. It allows for easy access to a pilot entry
  178. * with only the RowId required as input.
  179. */
  180. APilotEntry getPilotEntry(RowId_T row_id);
  181. /*!
  182. * \brief retreives a TailEntry from the database.
  183. *
  184. * This function is a wrapper for DataBase::getEntry(DataPosition),
  185. * where the table is already set and which returns a TailEntry
  186. * instead of an Entry. It allows for easy access to a tail entry
  187. * with only the RowId required as input.
  188. */
  189. ATailEntry getTailEntry(RowId_T row_id);
  190. /*!
  191. * \brief retreives a TailEntry from the database.
  192. *
  193. * This function is a wrapper for DataBase::getEntry(DataPosition),
  194. * where the table is already set and which returns an AAircraftEntry
  195. * instead of an AEntry. It allows for easy access to an aircraft entry
  196. * with only the RowId required as input.
  197. */
  198. AAircraftEntry getAircraftEntry(RowId_T row_id);
  199. /*!
  200. * \brief retreives a flight entry from the database.
  201. *
  202. * This function is a wrapper for DataBase::getEntry(DataPosition),
  203. * where the table is already set and which returns an AFlightEntry
  204. * instead of an AEntry. It allows for easy access to a flight entry
  205. * with only the RowId required as input.
  206. */
  207. AFlightEntry getFlightEntry(RowId_T row_id);
  208. /*!
  209. * \brief Retreives a currency entry from the database.
  210. */
  211. ACurrencyEntry getCurrencyEntry(ACurrencyEntry::CurrencyName currency_name);
  212. /*!
  213. * \brief getCompletionList returns a QStringList of values for a
  214. * QCompleter based on database values
  215. */
  216. const QStringList getCompletionList(ADatabaseTarget target);
  217. /*!
  218. * \brief returns a QMap<QString, RowId_t> of a human-readable database value and
  219. * its row id. Used in the Dialogs to map user input to unique database entries.
  220. * \todo What is this QString semantically? As i understand its a "QueryResult" QVariant cast to QString
  221. */
  222. const QMap<QString, RowId_T> getIdMap(ADatabaseTarget target);
  223. /*!
  224. * \brief returns the ROWID for the newest entry in the respective database.
  225. */
  226. int getLastEntry(ADatabaseTarget target);
  227. /*!
  228. * \brief returns a list of ROWID's in the flights table for which foreign key constraints
  229. * exist.
  230. */
  231. QList<RowId_T> getForeignKeyConstraints(RowId_T foreign_row_id, ADatabaseTarget target);
  232. /*!
  233. * \brief Resolves the foreign key in a flight entry
  234. * \return The Pilot Entry referencted by the foreign key.
  235. */
  236. APilotEntry resolveForeignPilot(RowId_T foreign_key);
  237. /*!
  238. * \brief Resolves the foreign key in a flight entry
  239. * \return The Tail Entry referencted by the foreign key.
  240. */
  241. ATailEntry resolveForeignTail(RowId_T foreign_key);
  242. /*!
  243. * \brief Return the summary of the DB_PATH as a stringlist
  244. * \todo Contemplate whether it should be a more generic function
  245. * that may be used for different elements to summarize.
  246. * and ADD DOCUMENTATION, theres some specific sql stuff going on.
  247. * \return
  248. */
  249. QMap<QString, QString> databaseSummary(const QString& db_path);
  250. signals:
  251. /*!
  252. * \brief updated is emitted whenever the database contents have been updated.
  253. * This can be either a commit, update or remove. This signal should be used to
  254. * trigger an update to the models of the views displaying database contents in
  255. * the user interface so that a user is always presented with up-to-date information.
  256. */
  257. void dataBaseUpdated();
  258. };
  259. #endif // ADATABASE_H