File indexing completed on 2024-05-05 17:45:00

0001 /*
0002     SPDX-FileCopyrightText: 2007 Glenn Ergeerts <glenn.ergeerts@telenet.be>
0003     SPDX-FileCopyrightText: 2012 Marco Gulino <marco.gulino@xpeppers.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "fetchsqlite.h"
0009 #include "bookmarks_debug.h"
0010 #include "bookmarksrunner_defs.h"
0011 #include <QDebug>
0012 #include <QFile>
0013 #include <QMutexLocker>
0014 #include <QSqlError>
0015 #include <QSqlQuery>
0016 #include <QSqlRecord>
0017 #include <sstream>
0018 #include <thread>
0019 
0020 FetchSqlite::FetchSqlite(const QString &databaseFile, QObject *parent)
0021     : QObject(parent)
0022     , m_databaseFile(databaseFile)
0023 {
0024 }
0025 
0026 FetchSqlite::~FetchSqlite()
0027 {
0028 }
0029 
0030 void FetchSqlite::prepare()
0031 {
0032 }
0033 
0034 void FetchSqlite::teardown()
0035 {
0036     const QString connectionPrefix = m_databaseFile + "-";
0037     const auto connections = QSqlDatabase::connectionNames();
0038     for (const auto &c : connections) {
0039         if (c.startsWith(connectionPrefix)) {
0040             qCDebug(RUNNER_BOOKMARKS) << "Closing connection" << c;
0041             QSqlDatabase::removeDatabase(c);
0042         }
0043     }
0044 }
0045 
0046 static QSqlDatabase openDbConnection(const QString &databaseFile)
0047 {
0048     // create a thread unique connection name based on the DB filename and thread id
0049     auto connection = databaseFile + "-";
0050     std::stringstream s;
0051     s << std::this_thread::get_id();
0052     connection += QString::fromStdString(s.str());
0053 
0054     // Try to reuse the previous connection
0055     auto db = QSqlDatabase::database(connection);
0056     if (db.isValid()) {
0057         qCDebug(RUNNER_BOOKMARKS) << "Reusing connection" << connection;
0058         return db;
0059     }
0060 
0061     // Otherwise, create, configure and open a new one
0062     db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), connection);
0063     db.setHostName(QStringLiteral("localhost"));
0064     db.setDatabaseName(databaseFile);
0065     db.open();
0066     qCDebug(RUNNER_BOOKMARKS) << "Opened connection" << connection;
0067 
0068     return db;
0069 }
0070 
0071 QList<QVariantMap> FetchSqlite::query(const QString &sql, QMap<QString, QVariant> bindObjects)
0072 {
0073     QMutexLocker lock(&m_mutex);
0074 
0075     auto db = openDbConnection(m_databaseFile);
0076     if (!db.isValid()) {
0077         return QList<QVariantMap>();
0078     }
0079 
0080     // qDebug() << "query: " << sql;
0081     QSqlQuery query(db);
0082     query.prepare(sql);
0083     for (auto entry = bindObjects.constKeyValueBegin(); entry != bindObjects.constKeyValueEnd(); ++entry) {
0084         query.bindValue((*entry).first, (*entry).second);
0085         // qDebug() << "* Bound " << variableName << " to " << query.boundValue(variableName);
0086     }
0087 
0088     if (!query.exec()) {
0089         QSqlError error = db.lastError();
0090         // qDebug() << "query failed: " << error.text() << " (" << error.type() << ", " << error.number() << ")";
0091         // qDebug() << query.lastQuery();
0092     }
0093 
0094     QList<QVariantMap> result;
0095     while (query.next()) {
0096         QVariantMap recordValues;
0097         QSqlRecord record = query.record();
0098         for (int field = 0; field < record.count(); field++) {
0099             QVariant value = record.value(field);
0100             recordValues.insert(record.fieldName(field), value);
0101         }
0102         result << recordValues;
0103     }
0104 
0105     return result;
0106 }
0107 
0108 QStringList FetchSqlite::tables(QSql::TableType type)
0109 {
0110     QMutexLocker lock(&m_mutex);
0111 
0112     auto db = openDbConnection(m_databaseFile);
0113     return db.tables(type);
0114 }