KanoopDatabaseQt 1.1.1
Qt database abstraction library
Loading...
Searching...
No Matches
datasource.h
1/**
2 * DataSource
3 *
4 * An abstraction model for databases.
5 *
6 * Subclass this class to provide a Controller in the MVC programming paradigm.
7 *
8 * Stephen Punak, January 11 2025
9 */
10#ifndef DATASOURCE_H
11#define DATASOURCE_H
12
13#include <Kanoop/utility/loggingbaseclass.h>
14#include <Kanoop/database/databasecredentials.h>
15#include <QSqlDatabase>
16
17/** @brief Abstract database access layer providing connection management, query execution, and utility methods.
18 *
19 * Subclass this class to provide a Controller in the MVC programming paradigm.
20 */
21class DataSource : public QObject,
22 public LoggingBaseClass
23{
24 Q_OBJECT
25public:
26 /** @brief Construct a DataSource with default (empty) credentials. */
27 explicit DataSource() :
28 QObject(),
29 LoggingBaseClass("db") {}
30
31 /** @brief Construct a DataSource with the given database credentials.
32 * @param credentials The database connection credentials.
33 */
35 QObject(),
36 LoggingBaseClass("db"),
37 _credentials(credentials) {}
38
39 /** @brief Destructor. Closes the database connection if open. */
40 virtual ~DataSource();
41
42 /** @brief Open a database connection using the stored credentials.
43 * @return true if the connection was opened successfully.
44 */
45 virtual bool openConnection();
46
47 /** @brief Close the current database connection.
48 * @return true if the connection was closed successfully.
49 */
50 virtual bool closeConnection();
51
52 /** @brief Return true if the database connection is currently open.
53 * @return true if connected.
54 */
55 bool isOpen() { return _db.isOpen(); }
56
57 /** @brief Get the current database credentials.
58 * @return The stored DatabaseCredentials.
59 */
60 DatabaseCredentials credentials() const { return _credentials; }
61 /** @brief Set the database credentials.
62 * @param value The new credentials.
63 */
64 void setCredentials(const DatabaseCredentials& value) { _credentials = value; }
65
66 /** @brief Get the Qt connection name for this data source.
67 * @return The connection name string.
68 */
69 QString connectionName() const { return _connectionName; }
70 /** @brief Set the Qt connection name.
71 * @param value The connection name string.
72 */
73 void setConnectionName(const QString& value) { _connectionName = value; }
74
75 /** @brief Return true if the database should be created when opening fails.
76 * @return true if auto-creation on failure is enabled.
77 */
78 bool createOnOpenFailure() const { return _createOnOpenFailure; }
79 /** @brief Set whether to create the database when opening fails.
80 * @param value true to auto-create on failure.
81 */
82 void setCreateOnOpenFailure(bool value) { _createOnOpenFailure = value; }
83
84 /** @brief Get a human-readable string describing the last error.
85 * @return The error description string.
86 */
87 QString errorText() const;
88
89 /** @brief Check whether the given file is a valid SQLite database.
90 * @param filename The file path to check.
91 * @return true if the file is a SQLite database.
92 */
93 static bool isSqlite(const QString& filename);
94
95protected:
96 /** @brief Prepare a QSqlQuery from the given SQL string.
97 * @param sql The SQL statement to prepare.
98 * @param success Optional pointer set to true on success, false on failure.
99 * @return The prepared QSqlQuery.
100 */
101 QSqlQuery prepareQuery(const QString& sql, bool* success = nullptr);
102
103 /** @brief Execute a SQL string and return the resulting query.
104 * @param sql The SQL statement to execute.
105 * @param success Optional pointer set to true on success, false on failure.
106 * @return The executed QSqlQuery.
107 */
108 QSqlQuery executeQuery(const QString& sql, bool* success = nullptr);
109
110 /** @brief Execute an already-prepared QSqlQuery.
111 * @param query The query to execute.
112 * @return true if execution succeeded.
113 */
114 bool executeQuery(QSqlQuery& query);
115
116 /** @brief Check whether a query completed without error.
117 * @param query The query to check.
118 * @return true if the query was successful.
119 */
120 bool querySuccessful(const QSqlQuery& query);
121
122 /** @brief Execute multiple SQL statements in sequence.
123 * @param queries The list of SQL statements to execute.
124 * @return true if all statements executed successfully.
125 */
126 bool executeMultiple(const QStringList& queries);
127
128 /** @brief Return the SQL used to create the database schema. Override in subclasses.
129 * @return The SQL creation string, or an empty string by default.
130 */
131 virtual QString createSql() const { return QString(); }
132
133 /** @brief Perform any necessary database migrations. Override in subclasses.
134 * @return true on success.
135 */
136 virtual bool migrate() { return true; }
137
138 /** @brief Run an integrity check on the database. Override in subclasses.
139 * @return true if the database passes the integrity check.
140 */
141 virtual bool integrityCheck() { return true; }
142
143 /** @brief Log a SQL statement at the given log level.
144 * @param file The source file name (use __FILE__).
145 * @param line The source line number (use __LINE__).
146 * @param level The log level.
147 * @param sql The SQL statement to log.
148 */
149 void logSql(const char* file, int line, Log::LogLevel level, const QString& sql);
150
151 /** @brief Log details of a failed query.
152 * @param query The failed QSqlQuery.
153 */
154 void logFailure(const QSqlQuery& query) const;
155
156 /** @brief Set the data source error string.
157 * @param value The error description.
158 */
159 void setDataSourceError(const QString& value) { _dataSourceError = value; }
160
161 /** @brief Delete and recreate the SQLite database file from createSql().
162 * @return true on success.
163 */
165
166 /** @brief Execute any post-creation scripts after a new database is created. Override in subclasses.
167 * @return true on success.
168 */
169 virtual bool executePostCreateScripts() { return true; }
170
171 /** @brief Return true if the current credentials specify a SQLite engine.
172 * @return true if the engine is SQLite.
173 */
174 bool isSqlite() const { return _credentials.isSqlite(); }
175
176 /** @brief Convert a QVariant database value to a UTC QDateTime.
177 * @param value The QVariant containing the datetime value.
178 * @return The corresponding QDateTime in UTC.
179 */
180 static QDateTime utcTime(const QVariant& value);
181
182 /** @brief Get the current UTC timestamp as a formatted string suitable for SQL.
183 * @return The formatted timestamp string.
184 */
185 static QString currentTimestamp();
186
187 /** @brief The underlying QSqlDatabase connection object. */
188 QSqlDatabase _db;
189
190 /** @brief Build a comma-delimited string from a list of values.
191 * @param list The list of values to join.
192 * @return A comma-separated string representation.
193 */
194 template <typename T>
195 static QString commaDelimitedList(const QList<T> &list);
196
197 /** @brief Build a comma-delimited string from a list of integers.
198 * @param list The list of integers.
199 * @return A comma-separated string of integers.
200 */
201 static QString commaDelimitedIntList(const QList<int> &list);
202
203 /** @brief Build a comma-delimited string from a list of UUIDs.
204 * @param list The list of QUuid values.
205 * @return A comma-separated string of UUIDs.
206 */
207 static QString commaDelimitedUuidList(const QList<QUuid>& list);
208
209 /** @brief Build a comma-delimited string from a list of strings.
210 * @param list The string list.
211 * @return A comma-separated, quoted string.
212 */
213 static QString commaDelimitedStringList(const QStringList& list);
214
215 /** @brief Escape special characters in a string for safe inclusion in SQL.
216 * @param unescaped The raw string.
217 * @return The escaped string.
218 */
219 static QString escapedString(const QString& unescaped);
220
221
222private:
223 bool checkExecutingThread() const;
224 void recordQueryError(const QSqlQuery& query);
225 void createSqliteDatabase();
226 bool setSqliteForeignKeyChecking(bool value);
227
228 DatabaseCredentials _credentials;
229 QString _connectionName;
230
231 bool _createOnOpenFailure = true;
232
233 QString _dataSourceError;
234 QString _driverError;
235 QString _databaseError;
236 QString _nativeError;
237
238 int64_t _threadId = 0;
239};
240
241#endif // DATASOURCE_H
DataSource.
Definition datasource.h:23
static QString commaDelimitedStringList(const QStringList &list)
Build a comma-delimited string from a list of strings.
virtual bool closeConnection()
Close the current database connection.
virtual bool migrate()
Perform any necessary database migrations.
Definition datasource.h:136
bool executeMultiple(const QStringList &queries)
Execute multiple SQL statements in sequence.
DatabaseCredentials credentials() const
Get the current database credentials.
Definition datasource.h:60
QSqlQuery prepareQuery(const QString &sql, bool *success=nullptr)
Prepare a QSqlQuery from the given SQL string.
bool executeQuery(QSqlQuery &query)
Execute an already-prepared QSqlQuery.
static QString commaDelimitedList(const QList< T > &list)
Build a comma-delimited string from a list of values.
bool createOnOpenFailure() const
Return true if the database should be created when opening fails.
Definition datasource.h:78
bool isSqlite() const
Return true if the current credentials specify a SQLite engine.
Definition datasource.h:174
QSqlQuery executeQuery(const QString &sql, bool *success=nullptr)
Execute a SQL string and return the resulting query.
virtual QString createSql() const
Return the SQL used to create the database schema.
Definition datasource.h:131
static QString commaDelimitedUuidList(const QList< QUuid > &list)
Build a comma-delimited string from a list of UUIDs.
virtual bool executePostCreateScripts()
Execute any post-creation scripts after a new database is created.
Definition datasource.h:169
bool querySuccessful(const QSqlQuery &query)
Check whether a query completed without error.
void setDataSourceError(const QString &value)
Set the data source error string.
Definition datasource.h:159
void setCredentials(const DatabaseCredentials &value)
Set the database credentials.
Definition datasource.h:64
virtual bool openConnection()
Open a database connection using the stored credentials.
QString errorText() const
Get a human-readable string describing the last error.
void setConnectionName(const QString &value)
Set the Qt connection name.
Definition datasource.h:73
static bool isSqlite(const QString &filename)
Check whether the given file is a valid SQLite database.
static QString commaDelimitedIntList(const QList< int > &list)
Build a comma-delimited string from a list of integers.
static QString escapedString(const QString &unescaped)
Escape special characters in a string for safe inclusion in SQL.
static QDateTime utcTime(const QVariant &value)
Convert a QVariant database value to a UTC QDateTime.
virtual ~DataSource()
Destructor.
void logFailure(const QSqlQuery &query) const
Log details of a failed query.
DataSource(const DatabaseCredentials &credentials)
Construct a DataSource with the given database credentials.
Definition datasource.h:34
void logSql(const char *file, int line, Log::LogLevel level, const QString &sql)
Log a SQL statement at the given log level.
virtual bool integrityCheck()
Run an integrity check on the database.
Definition datasource.h:141
bool isOpen()
Return true if the database connection is currently open.
Definition datasource.h:55
static QString currentTimestamp()
Get the current UTC timestamp as a formatted string suitable for SQL.
bool recreateSqliteDatabase()
Delete and recreate the SQLite database file from createSql().
QSqlDatabase _db
The underlying QSqlDatabase connection object.
Definition datasource.h:188
QString connectionName() const
Get the Qt connection name for this data source.
Definition datasource.h:69
DataSource()
Construct a DataSource with default (empty) credentials.
Definition datasource.h:27
void setCreateOnOpenFailure(bool value)
Set whether to create the database when opening fails.
Definition datasource.h:82
DatabaseCredentials.
bool isSqlite() const
Return true if the engine is SQLite.