File indexing completed on 2024-05-12 04:58:28
0001 /* ============================================================ 0002 * Falkon - Qt web browser 0003 * Copyright (C) 2014-2018 David Rosca <nowrep@gmail.com> 0004 * 0005 * This program is free software: you can redistribute it and/or modify 0006 * it under the terms of the GNU General Public License as published by 0007 * the Free Software Foundation, either version 3 of the License, or 0008 * (at your option) any later version. 0009 * 0010 * This program is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 * GNU General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU General Public License 0016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0017 * ============================================================ */ 0018 #include "sqldatabase.h" 0019 0020 #include <QApplication> 0021 #include <QThreadStorage> 0022 #include <QFutureWatcher> 0023 #include <QtConcurrent/QtConcurrentRun> 0024 0025 QThreadStorage<QSqlDatabase> s_databases; 0026 0027 Q_GLOBAL_STATIC(SqlDatabase, qz_sql_database) 0028 0029 // SqlQueryJob 0030 SqlQueryJob::SqlQueryJob(QObject *parent) 0031 : QObject(parent) 0032 { 0033 } 0034 0035 SqlQueryJob::SqlQueryJob(const QString &query, QObject *parent) 0036 : QObject(parent) 0037 { 0038 setQuery(query); 0039 } 0040 0041 void SqlQueryJob::setQuery(const QString &query) 0042 { 0043 m_query = query; 0044 } 0045 0046 void SqlQueryJob::addBindValue(const QVariant &value) 0047 { 0048 m_boundValues.append(value); 0049 } 0050 0051 QSqlError SqlQueryJob::error() const 0052 { 0053 return m_error; 0054 } 0055 0056 QVariant SqlQueryJob::lastInsertId() const 0057 { 0058 return m_lastInsertId; 0059 } 0060 0061 QVector<QSqlRecord> SqlQueryJob::records() const 0062 { 0063 return m_records; 0064 } 0065 0066 void SqlQueryJob::start() 0067 { 0068 struct Result { 0069 QSqlError error; 0070 QVariant lastInsertId; 0071 QVector<QSqlRecord> records; 0072 }; 0073 0074 const QString query = m_query; 0075 m_query.clear(); 0076 const QVector<QVariant> boundValues = m_boundValues; 0077 m_boundValues.clear(); 0078 0079 auto watcher = new QFutureWatcher<Result>(this); 0080 connect(watcher, &QFutureWatcher<Result>::finished, this, [=]() { 0081 deleteLater(); 0082 const auto result = watcher->result(); 0083 m_error = result.error; 0084 m_lastInsertId = result.lastInsertId; 0085 m_records = result.records; 0086 Q_EMIT finished(this); 0087 }); 0088 0089 watcher->setFuture(QtConcurrent::run([=]() { 0090 QSqlQuery q(SqlDatabase::instance()->database()); 0091 q.prepare(query); 0092 for (const QVariant &value : boundValues) { 0093 q.addBindValue(value); 0094 } 0095 q.exec(); 0096 Result res; 0097 res.error = q.lastError(); 0098 res.lastInsertId = q.lastInsertId(); 0099 while (q.next()) { 0100 res.records.append(q.record()); 0101 } 0102 return res; 0103 })); 0104 } 0105 0106 // SqlDatabase 0107 SqlDatabase::SqlDatabase(QObject* parent) 0108 : QObject(parent) 0109 { 0110 } 0111 0112 SqlDatabase::~SqlDatabase() 0113 = default; 0114 0115 QSqlDatabase SqlDatabase::database() 0116 { 0117 if (QThread::currentThread() == qApp->thread()) { 0118 return QSqlDatabase::database(); 0119 } 0120 0121 if (!s_databases.hasLocalData()) { 0122 const QString threadStr = QStringLiteral("Falkon/%1").arg((quintptr) QThread::currentThread()); 0123 QSqlDatabase::removeDatabase(threadStr); 0124 QSqlDatabase db = QSqlDatabase::addDatabase(QSL("QSQLITE"), threadStr); 0125 db.setDatabaseName(m_databaseName); 0126 db.setConnectOptions(m_connectOptions); 0127 db.open(); 0128 s_databases.setLocalData(db); 0129 } 0130 0131 return s_databases.localData(); 0132 } 0133 0134 void SqlDatabase::setDatabase(const QSqlDatabase &database) 0135 { 0136 m_databaseName = database.databaseName(); 0137 m_connectOptions = database.connectOptions(); 0138 } 0139 0140 // instance 0141 SqlDatabase* SqlDatabase::instance() 0142 { 0143 return qz_sql_database(); 0144 }