Changeset View
Changeset View
Standalone View
Standalone View
runners/bookmarks/fetchsqlite.cpp
Show All 15 Lines | |||||
16 | * License along with this program; if not, write to the | 16 | * License along with this program; if not, write to the | ||
17 | * Free Software Foundation, Inc., | 17 | * Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
19 | */ | 19 | */ | ||
20 | 20 | | |||
21 | #include "fetchsqlite.h" | 21 | #include "fetchsqlite.h" | ||
22 | #include <QFile> | 22 | #include <QFile> | ||
23 | #include <QDebug> | 23 | #include <QDebug> | ||
24 | #include "bookmarks_debug.h" | ||||
24 | #include "bookmarksrunner_defs.h" | 25 | #include "bookmarksrunner_defs.h" | ||
25 | #include <QSqlQuery> | 26 | #include <QSqlQuery> | ||
26 | #include <QSqlError> | 27 | #include <QSqlError> | ||
27 | #include <QSqlRecord> | 28 | #include <QSqlRecord> | ||
28 | #include <QMutexLocker> | 29 | #include <QMutexLocker> | ||
30 | #include <thread> | ||||
31 | #include <sstream> | ||||
29 | 32 | | |||
30 | FetchSqlite::FetchSqlite(const QString &originalFilePath, const QString ©To, QObject *parent) : | 33 | FetchSqlite::FetchSqlite(const QString &originalFilePath, const QString ©To, QObject *parent) : | ||
31 | QObject(parent), m_databaseFile(copyTo) | 34 | QObject(parent), m_databaseFile(copyTo) | ||
32 | { | 35 | { | ||
33 | m_db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), originalFilePath); | | |||
34 | m_db.setHostName(QStringLiteral("localhost")); | | |||
35 | | ||||
36 | QFile originalFile(originalFilePath); | 36 | QFile originalFile(originalFilePath); | ||
37 | QFile(copyTo).remove(); | 37 | QFile(copyTo).remove(); | ||
38 | bool couldCopy = originalFile.copy(copyTo); | 38 | bool couldCopy = originalFile.copy(copyTo); | ||
39 | if(!couldCopy) { | 39 | if(!couldCopy) { | ||
40 | //qDebug() << "error copying favicon database from " << originalFile.fileName() << " to " << copyTo; | 40 | //qDebug() << "error copying favicon database from " << originalFile.fileName() << " to " << copyTo; | ||
41 | //qDebug() << originalFile.errorString(); | 41 | //qDebug() << originalFile.errorString(); | ||
42 | } | 42 | } | ||
43 | } | 43 | } | ||
44 | 44 | | |||
45 | FetchSqlite::~FetchSqlite() | 45 | FetchSqlite::~FetchSqlite() | ||
46 | { | 46 | { | ||
47 | if(m_db.isOpen()) m_db.close(); | | |||
48 | QFile(m_databaseFile).remove(); | 47 | QFile(m_databaseFile).remove(); | ||
49 | } | 48 | } | ||
50 | 49 | | |||
51 | void FetchSqlite::prepare() | 50 | void FetchSqlite::prepare() | ||
52 | { | 51 | { | ||
53 | QMutexLocker lock(&m_mutex); | | |||
54 | m_db.setDatabaseName(m_databaseFile); | | |||
55 | bool ok = m_db.open(); | | |||
56 | //qDebug() << "Sqlite Database " << m_databaseFile << " was opened: " << ok; | | |||
57 | if(!ok) { | | |||
58 | //qDebug() << "Error: " << m_db.lastError().text(); | | |||
59 | } | | |||
60 | } | 52 | } | ||
61 | 53 | | |||
62 | void FetchSqlite::teardown() | 54 | void FetchSqlite::teardown() | ||
63 | { | 55 | { | ||
64 | QMutexLocker lock(&m_mutex); | 56 | QString connectionPrefix = m_databaseFile + "-"; | ||
65 | m_db.close(); | 57 | | ||
58 | const auto connections = QSqlDatabase::connectionNames(); | ||||
59 | for (auto c : connections) { | ||||
60 | if (c.startsWith(connectionPrefix)) { | ||||
61 | qCDebug(RUNNER_BOOKMARKS) << "Closing connection" << c; | ||||
62 | QSqlDatabase::removeDatabase(c); | ||||
63 | } | ||||
64 | } | ||||
65 | } | ||||
66 | | ||||
67 | static QSqlDatabase openDbConnection(const QString& databaseFile) { | ||||
68 | // create a thread unique connection name based on the DB filename and thread id | ||||
69 | auto connection = databaseFile + "-"; | ||||
70 | std::stringstream s; | ||||
71 | s << std::this_thread::get_id(); | ||||
72 | connection += QString::fromStdString(s.str()); | ||||
73 | | ||||
74 | // Try to reuse the previous connection | ||||
75 | auto db = QSqlDatabase::database(connection); | ||||
76 | if (db.isValid()) { | ||||
77 | qCDebug(RUNNER_BOOKMARKS) << "Reusing connection" << connection; | ||||
78 | return db; | ||||
79 | } | ||||
80 | | ||||
81 | // Otherwise, create, configure and open a new one | ||||
82 | db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), connection); | ||||
83 | db.setHostName(QStringLiteral("localhost")); | ||||
84 | db.setDatabaseName(databaseFile); | ||||
85 | db.open(); | ||||
86 | qCDebug(RUNNER_BOOKMARKS) << "Opened connection" << connection; | ||||
87 | | ||||
88 | return db; | ||||
66 | } | 89 | } | ||
67 | 90 | | |||
68 | QList<QVariantMap> FetchSqlite::query(const QString &sql, QMap<QString, QVariant> bindObjects) | 91 | QList<QVariantMap> FetchSqlite::query(const QString &sql, QMap<QString, QVariant> bindObjects) | ||
69 | { | 92 | { | ||
70 | QMutexLocker lock(&m_mutex); | 93 | QMutexLocker lock(&m_mutex); | ||
71 | 94 | | |||
95 | auto db = openDbConnection(m_databaseFile); | ||||
96 | | ||||
72 | //qDebug() << "query: " << sql; | 97 | //qDebug() << "query: " << sql; | ||
73 | QSqlQuery query(m_db); | 98 | QSqlQuery query(db); | ||
74 | query.prepare(sql); | 99 | query.prepare(sql); | ||
75 | foreach(const QString &variableName, bindObjects.keys()) { | 100 | foreach(const QString &variableName, bindObjects.keys()) { | ||
76 | query.bindValue(variableName, bindObjects.value(variableName)); | 101 | query.bindValue(variableName, bindObjects.value(variableName)); | ||
77 | //qDebug() << "* Bound " << variableName << " to " << query.boundValue(variableName); | 102 | //qDebug() << "* Bound " << variableName << " to " << query.boundValue(variableName); | ||
78 | } | 103 | } | ||
79 | 104 | | |||
80 | if(!query.exec()) { | 105 | if(!query.exec()) { | ||
81 | QSqlError error = m_db.lastError(); | 106 | QSqlError error = db.lastError(); | ||
82 | //qDebug() << "query failed: " << error.text() << " (" << error.type() << ", " << error.number() << ")"; | 107 | //qDebug() << "query failed: " << error.text() << " (" << error.type() << ", " << error.number() << ")"; | ||
83 | //qDebug() << query.lastQuery(); | 108 | //qDebug() << query.lastQuery(); | ||
84 | } | 109 | } | ||
85 | 110 | | |||
86 | QList<QVariantMap> result; | 111 | QList<QVariantMap> result; | ||
87 | while(query.next()) { | 112 | while(query.next()) { | ||
88 | QVariantMap recordValues; | 113 | QVariantMap recordValues; | ||
89 | QSqlRecord record = query.record(); | 114 | QSqlRecord record = query.record(); | ||
90 | for(int field=0; field<record.count(); field++) { | 115 | for(int field=0; field<record.count(); field++) { | ||
91 | QVariant value = record.value(field); | 116 | QVariant value = record.value(field); | ||
92 | recordValues.insert(record.fieldName(field), value ); | 117 | recordValues.insert(record.fieldName(field), value ); | ||
93 | } | 118 | } | ||
94 | result << recordValues; | 119 | result << recordValues; | ||
95 | } | 120 | } | ||
121 | | ||||
96 | return result; | 122 | return result; | ||
97 | } | 123 | } | ||
98 | 124 | | |||
99 | QStringList FetchSqlite::tables(QSql::TableType type) | 125 | QStringList FetchSqlite::tables(QSql::TableType type) | ||
100 | { | 126 | { | ||
101 | QMutexLocker lock(&m_mutex); | 127 | QMutexLocker lock(&m_mutex); | ||
102 | 128 | | |||
103 | return m_db.tables(type); | 129 | auto db = openDbConnection(m_databaseFile); | ||
130 | return db.tables(type); | ||||
104 | } | 131 | } |