mirror of
https://invent.kde.org/network/falkon.git
synced 2024-12-19 18:26:34 +01:00
Add SqlQueryJob to run queries on separate thread
This commit is contained in:
parent
0d2776a261
commit
8a5c69b8a1
@ -22,6 +22,7 @@ falkon_tests(
|
||||
locationbartest
|
||||
webviewtest
|
||||
webtabtest
|
||||
sqldatabasetest
|
||||
)
|
||||
|
||||
set(falkon_autotests_SRCS ${CMAKE_SOURCE_DIR}/tests/modeltest/modeltest.cpp)
|
||||
|
90
autotests/sqldatabasetest.cpp
Normal file
90
autotests/sqldatabasetest.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
/* ============================================================
|
||||
* Falkon - Qt web browser
|
||||
* Copyright (C) 2018 David Rosca <nowrep@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* ============================================================ */
|
||||
#include "sqldatabasetest.h"
|
||||
#include "sqldatabase.h"
|
||||
|
||||
#include <QtTest/QTest>
|
||||
#include <QtTest/QSignalSpy>
|
||||
#include <QSqlDatabase>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
void SqlDatabaseTest::initTestCase()
|
||||
{
|
||||
}
|
||||
|
||||
void SqlDatabaseTest::cleanupTestCase()
|
||||
{
|
||||
}
|
||||
|
||||
static bool waitForFinished(SqlQueryJob *job)
|
||||
{
|
||||
QSignalSpy spy(job, &SqlQueryJob::finished);
|
||||
return spy.wait();
|
||||
}
|
||||
|
||||
void SqlDatabaseTest::sqlQueryJobTest()
|
||||
{
|
||||
QTemporaryFile file;
|
||||
file.open();
|
||||
|
||||
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
|
||||
db.setDatabaseName(file.fileName());
|
||||
db.open();
|
||||
|
||||
SqlDatabase::instance()->setDatabase(db);
|
||||
|
||||
QCOMPARE(db.tables().count(), 0);
|
||||
|
||||
SqlQueryJob *job = new SqlQueryJob();
|
||||
job->setQuery("CREATE TABLE test1 (data TEXT, id INTEGER PRIMARY KEY)");
|
||||
job->start();
|
||||
QVERIFY(waitForFinished(job));
|
||||
QVERIFY(!job->error().isValid());
|
||||
|
||||
QCOMPARE(db.tables(), QStringList{"test1"});
|
||||
|
||||
job = new SqlQueryJob();
|
||||
job->setQuery("INSERT INTO test1 (data) VALUES (?)");
|
||||
job->addBindValue("test-value");
|
||||
job->start();
|
||||
QVERIFY(waitForFinished(job));
|
||||
QVERIFY(!job->error().isValid());
|
||||
|
||||
QCOMPARE(job->lastInsertId().toInt(), 1);
|
||||
QSqlQuery query("SELECT data FROM test1", db);
|
||||
query.next();
|
||||
QCOMPARE(query.value(0).toString(), QString("test-value"));
|
||||
QVERIFY(!query.next());
|
||||
|
||||
job = new SqlQueryJob();
|
||||
job->setQuery("SELECT data FROM test1");
|
||||
job->start();
|
||||
QVERIFY(waitForFinished(job));
|
||||
QVERIFY(!job->error().isValid());
|
||||
|
||||
QCOMPARE(job->records().size(), 1);
|
||||
QCOMPARE(job->records().at(0).value(0).toString(), QString("test-value"));
|
||||
|
||||
job = new SqlQueryJob();
|
||||
job->setQuery("SELECT invalid sql syntax; 1321sdsa from");
|
||||
job->start();
|
||||
QVERIFY(waitForFinished(job));
|
||||
QVERIFY(job->error().isValid());
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(SqlDatabaseTest)
|
31
autotests/sqldatabasetest.h
Normal file
31
autotests/sqldatabasetest.h
Normal file
@ -0,0 +1,31 @@
|
||||
/* ============================================================
|
||||
* Falkon - Qt web browser
|
||||
* Copyright (C) 2018 David Rosca <nowrep@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* ============================================================ */
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class SqlDatabaseTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void cleanupTestCase();
|
||||
|
||||
void sqlQueryJobTest();
|
||||
};
|
@ -19,13 +19,90 @@
|
||||
|
||||
#include <QApplication>
|
||||
#include <QThreadStorage>
|
||||
|
||||
#include <QFutureWatcher>
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
|
||||
QThreadStorage<QSqlDatabase> s_databases;
|
||||
|
||||
Q_GLOBAL_STATIC(SqlDatabase, qz_sql_database)
|
||||
|
||||
// SqlQueryJob
|
||||
SqlQueryJob::SqlQueryJob(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
SqlQueryJob::SqlQueryJob(const QString &query, QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
setQuery(query);
|
||||
}
|
||||
|
||||
void SqlQueryJob::setQuery(const QString &query)
|
||||
{
|
||||
m_query = query;
|
||||
}
|
||||
|
||||
void SqlQueryJob::addBindValue(const QVariant &value)
|
||||
{
|
||||
m_boundValues.append(value);
|
||||
}
|
||||
|
||||
QSqlError SqlQueryJob::error() const
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
|
||||
QVariant SqlQueryJob::lastInsertId() const
|
||||
{
|
||||
return m_lastInsertId;
|
||||
}
|
||||
|
||||
QVector<QSqlRecord> SqlQueryJob::records() const
|
||||
{
|
||||
return m_records;
|
||||
}
|
||||
|
||||
void SqlQueryJob::start()
|
||||
{
|
||||
struct Result {
|
||||
QSqlError error;
|
||||
QVariant lastInsertId;
|
||||
QVector<QSqlRecord> records;
|
||||
};
|
||||
|
||||
const QString query = m_query;
|
||||
m_query.clear();
|
||||
const QVector<QVariant> boundValues = m_boundValues;
|
||||
m_boundValues.clear();
|
||||
|
||||
auto watcher = new QFutureWatcher<Result>(this);
|
||||
connect(watcher, &QFutureWatcher<Result>::finished, this, [=]() {
|
||||
deleteLater();
|
||||
const auto result = watcher->result();
|
||||
m_error = result.error;
|
||||
m_lastInsertId = result.lastInsertId;
|
||||
m_records = result.records;
|
||||
emit finished(this);
|
||||
});
|
||||
|
||||
watcher->setFuture(QtConcurrent::run([=]() {
|
||||
QSqlQuery q(SqlDatabase::instance()->database());
|
||||
q.prepare(query);
|
||||
for (const QVariant &value : boundValues) {
|
||||
q.addBindValue(value);
|
||||
}
|
||||
q.exec();
|
||||
Result res;
|
||||
res.error = q.lastError();
|
||||
res.lastInsertId = q.lastInsertId();
|
||||
while (q.next()) {
|
||||
res.records.append(q.record());
|
||||
}
|
||||
return res;
|
||||
}));
|
||||
}
|
||||
|
||||
// SqlDatabase
|
||||
SqlDatabase::SqlDatabase(QObject* parent)
|
||||
: QObject(parent)
|
||||
|
@ -18,13 +18,40 @@
|
||||
#ifndef SQLDATABASE_H
|
||||
#define SQLDATABASE_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QMutex>
|
||||
#include <QFuture>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include <QSqlRecord>
|
||||
|
||||
#include "qzcommon.h"
|
||||
|
||||
class FALKON_EXPORT SqlQueryJob : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SqlQueryJob(QObject *parent = nullptr);
|
||||
explicit SqlQueryJob(const QString &query, QObject *parent = nullptr);
|
||||
|
||||
void setQuery(const QString &query);
|
||||
void addBindValue(const QVariant &value);
|
||||
|
||||
QSqlError error() const;
|
||||
QVariant lastInsertId() const;
|
||||
QVector<QSqlRecord> records() const;
|
||||
|
||||
void start();
|
||||
|
||||
Q_SIGNALS:
|
||||
void finished(SqlQueryJob *job);
|
||||
|
||||
private:
|
||||
QString m_query;
|
||||
QVector<QVariant> m_boundValues;
|
||||
QSqlError m_error;
|
||||
QVariant m_lastInsertId;
|
||||
QVector<QSqlRecord> m_records;
|
||||
};
|
||||
|
||||
class FALKON_EXPORT SqlDatabase : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -120,6 +120,7 @@ set(GENERATED_SOURCES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/delayedfilewatcher_wrapper.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/iconprovider_wrapper.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/qztools_wrapper.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/sqlqueryjob_wrapper.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/sqldatabase_wrapper.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/toolbutton_wrapper.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/wheelhelper_wrapper.cpp
|
||||
|
@ -222,6 +222,7 @@
|
||||
</inject-code>
|
||||
</modify-function>
|
||||
</object-type>
|
||||
<object-type name="SqlQueryJob"/>
|
||||
<object-type name="SqlDatabase"/>
|
||||
<object-type name="ToolButton"/>
|
||||
<value-type name="WheelHelper">
|
||||
|
Loading…
Reference in New Issue
Block a user