Check QSqlQuery errors when doing a query

This is more for me than the end user, because if there is an error with
a query, there is—almost aways—nothing a user can do, since it is
probably an error in the static SQL string or the database.  However, it
is better to show an error, than to do nothing at all when there is a
failure.

According to Qt’s documentation[0], QFuture relies on exceptions for the
error handling. At first i assumed that i had to attach an onFailed
handler to QFuture in order to receive that exception and skip the then
handler.

However, i can not attach the onFailure inside Database::query, before
returning the QFuture, because the subsequent then is only executed when
there _is_ an error, never in the normal, non-exceptional, case.  I
would have to add the onFailure after then.

Nonetheless, i found out that there is no need for onFailure: since i do
not call result(), i do not get the exception, and the actual work is
performed in the then handler when no exception is raised.

[0]: https://doc.qt.io/qt-6/qfuture.html
This commit is contained in:
jordi fita mas 2025-01-15 13:01:40 +01:00
parent c795effd3d
commit 0e371d71dd
3 changed files with 16 additions and 0 deletions

View File

@ -89,4 +89,15 @@ QFuture<void> Database::close()
});
}
void Database::checkError(const QSqlQuery &query)
{
QSqlError lastError = query.lastError();
if (!lastError.isValid()) {
return;
}
QString errorMessage = lastError.text();
emit getInstance().errorOcurred(errorMessage);
throw std::runtime_error(errorMessage.toStdString());
}
#include "moc_database.cpp"

View File

@ -7,6 +7,7 @@
#include <QThreadPool>
#include <QtConcurrent>
class QSqlQuery;
class Database : public QObject
{
Q_OBJECT
@ -27,6 +28,8 @@ public:
const QString &connectOptions);
Q_INVOKABLE QFuture<void> close();
static void checkError(const QSqlQuery &query);
template<class Function>
static auto query(Function &&f)
{

View File

@ -85,6 +85,7 @@ void TimelineListModel::fetch()
Results results;
{
QSqlQuery query("select campsite_id, label from campsite order by label, campsite_id");
Database::checkError(query);
while (query.next()) {
Lodging item{query.value(0).toInt(), query.value(1).toString()};
results.lodgings.append(item);
@ -104,6 +105,7 @@ void TimelineListModel::fetch()
" join booking using (booking_id) "
" order by lower(booking_campsite.stay), booking_id "
"");
Database::checkError(query);
while (query.next()) {
int lodgingId = query.value(0).toInt();
auto *item = new TimelineModel::Item{