diff options
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h')
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h | 69 |
1 files changed, 49 insertions, 20 deletions
diff --git a/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h b/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h index 7419f8c..51465f9 100644 --- a/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h +++ b/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h @@ -12,6 +12,8 @@ #include <QThread> #include <QPointer> #include <QDebug> +#include <QMutexLocker> +#include <QMutex> /** * @brief Complete implementation of SQLite 2 driver for SQLiteStudio. @@ -42,9 +44,11 @@ class AbstractDb2 : public AbstractDb * All values from this constructor are just passed to AbstractDb constructor. */ AbstractDb2(const QString& name, const QString& path, const QHash<QString, QVariant>& connOptions); - ~AbstractDb2(); + bool loadExtension(const QString& filePath, const QString& initFunc = QString()); + bool isComplete(const QString& sql) const; + protected: bool isOpenInternal(); void interruptExecution(); @@ -131,6 +135,7 @@ class AbstractDb2 : public AbstractDb int dbErrorCode = SQLITE_OK; QList<FunctionUserData*> userDataList; QList<Query*> queries; + QMutex* dbOperMutex = nullptr; }; //------------------------------------------------------------------------------------ @@ -141,16 +146,32 @@ template <class T> AbstractDb2<T>::AbstractDb2(const QString& name, const QString& path, const QHash<QString, QVariant>& connOptions) : AbstractDb(name, path, connOptions) { + dbOperMutex = new QMutex(QMutex::Recursive); } template <class T> AbstractDb2<T>::~AbstractDb2() { + safe_delete(dbOperMutex); if (isOpenInternal()) closeInternal(); } template <class T> +bool AbstractDb2<T>::loadExtension(const QString& filePath, const QString& initFunc) +{ + UNUSED(filePath); + UNUSED(initFunc); + return false; +} + +template<class T> +bool AbstractDb2<T>::isComplete(const QString& sql) const +{ + return sqlite_complete(sql.toUtf8().constData()); +} + +template <class T> bool AbstractDb2<T>::isOpenInternal() { return dbHandle != nullptr; @@ -168,6 +189,7 @@ void AbstractDb2<T>::interruptExecution() if (!isOpenInternal()) return; + QMutexLocker mutexLocker(dbOperMutex); sqlite_interrupt(dbHandle); } @@ -189,6 +211,7 @@ bool AbstractDb2<T>::openInternal() resetError(); sqlite* handle = nullptr; char* errMsg = nullptr; + QMutexLocker mutexLocker(dbOperMutex); handle = sqlite_open(path.toUtf8().constData(), 0, &errMsg); if (!handle) { @@ -214,6 +237,7 @@ bool AbstractDb2<T>::closeInternal() cleanUp(); + QMutexLocker mutexLocker(dbOperMutex); sqlite_close(dbHandle); dbHandle = nullptr; return true; @@ -243,6 +267,7 @@ bool AbstractDb2<T>::deregisterFunction(const QString& name, int argCount) if (!dbHandle) return false; + QMutexLocker mutexLocker(dbOperMutex); sqlite_create_function(dbHandle, name.toLatin1().data(), argCount, nullptr, nullptr); sqlite_create_aggregate(dbHandle, name.toLatin1().data(), argCount, nullptr, nullptr, nullptr); @@ -273,6 +298,7 @@ bool AbstractDb2<T>::registerScalarFunction(const QString& name, int argCount) userData->argCount = argCount; userDataList << userData; + QMutexLocker mutexLocker(dbOperMutex); int res = sqlite_create_function(dbHandle, name.toUtf8().constData(), argCount, &AbstractDb2<T>::evaluateScalar, userData); @@ -291,6 +317,7 @@ bool AbstractDb2<T>::registerAggregateFunction(const QString& name, int argCount userData->argCount = argCount; userDataList << userData; + QMutexLocker mutexLocker(dbOperMutex); int res = sqlite_create_aggregate(dbHandle, name.toUtf8().constData(), argCount, &AbstractDb2<T>::evaluateAggregateStep, &AbstractDb2<T>::evaluateAggregateFinal, @@ -527,6 +554,7 @@ int AbstractDb2<T>::Query::prepareStmt(const QString& processedQuery) char* errMsg = nullptr; const char* tail; QByteArray queryBytes = processedQuery.toUtf8(); + QMutexLocker mutexLocker(db->dbOperMutex); int res = sqlite_compile(db->dbHandle, queryBytes.constData(), &tail, &stmt, &errMsg); if (res != SQLITE_OK) { @@ -556,6 +584,7 @@ int AbstractDb2<T>::Query::resetStmt() nextRowValues.clear(); char* errMsg = nullptr; + QMutexLocker mutexLocker(db->dbOperMutex); int res = sqlite_reset(stmt, &errMsg); if (res != SQLITE_OK) { @@ -576,23 +605,27 @@ bool AbstractDb2<T>::Query::execInternal(const QList<QVariant>& args) if (!checkDbState()) return false; - ReadWriteLocker locker(&(db->dbOperLock), query, Dialect::Sqlite2, flags.testFlag(Db::Flag::NO_LOCK)); + QMutexLocker mutexLocker(db->dbOperMutex); logSql(db.data(), query, args, flags); - QueryWithParamCount queryWithParams = getQueryWithParamCount(query, Dialect::Sqlite2); - QString singleStr = replaceNamedParams(queryWithParams.first); - int res; if (stmt) res = resetStmt(); else - res = prepareStmt(singleStr); + res = prepareStmt(query); if (res != SQLITE_OK) return false; - for (int paramIdx = 1; paramIdx <= queryWithParams.second; paramIdx++) + int maxParamIdx = args.size(); + if (!flags.testFlag(Db::Flag::SKIP_PARAM_COUNTING)) + { + QueryWithParamCount queryWithParams = getQueryWithParamCount(query, Dialect::Sqlite2); + maxParamIdx = qMin(maxParamIdx, queryWithParams.second); + } + + for (int paramIdx = 1; paramIdx <= maxParamIdx; paramIdx++) { res = bindParam(paramIdx, args[paramIdx-1]); if (res != SQLITE_OK) @@ -612,7 +645,7 @@ bool AbstractDb2<T>::Query::execInternal(const QHash<QString, QVariant>& args) if (!checkDbState()) return false; - ReadWriteLocker locker(&(db->dbOperLock), query, Dialect::Sqlite2, flags.testFlag(Db::Flag::NO_LOCK)); + QMutexLocker mutexLocker(db->dbOperMutex); logSql(db.data(), query, args, flags); @@ -629,7 +662,7 @@ bool AbstractDb2<T>::Query::execInternal(const QHash<QString, QVariant>& args) return false; int paramIdx = 1; - foreach (const QString& paramName, queryWithParams.second) + for (const QString& paramName : queryWithParams.second) { if (!args.contains(paramName)) { @@ -665,9 +698,7 @@ template <class T> int AbstractDb2<T>::Query::bindParam(int paramIdx, const QVariant& value) { if (value.isNull()) - { return sqlite_bind(stmt, paramIdx, nullptr, 0, 0); - } switch (value.type()) { @@ -686,6 +717,7 @@ int AbstractDb2<T>::Query::bindParam(int paramIdx, const QVariant& value) } } + qWarning() << "sqlite_bind() MISUSE"; return SQLITE_MISUSE; // not going to happen } template <class T> @@ -747,19 +779,14 @@ bool AbstractDb2<T>::Query::hasNextInternal() template <class T> int AbstractDb2<T>::Query::fetchFirst() { + QMutexLocker mutexLocker(db->dbOperMutex); rowAvailable = true; int res = fetchNext(); + affected = 0; if (res == SQLITE_OK) { - if (colCount == 0) - { - affected = 0; - } - else - { - affected = sqlite_changes(db->dbHandle); - insertRowId["ROWID"] = sqlite_last_insert_rowid(db->dbHandle); - } + affected = sqlite_changes(db->dbHandle); + insertRowId["ROWID"] = sqlite_last_insert_rowid(db->dbHandle); } return res; } @@ -783,6 +810,7 @@ QString AbstractDb2<T>::Query::finalize() if (stmt) { char* errMsg = nullptr; + QMutexLocker mutexLocker(db->dbOperMutex); sqlite_finalize(stmt, &errMsg); stmt = nullptr; if (errMsg) @@ -814,6 +842,7 @@ int AbstractDb2<T>::Query::fetchNext() int res; int secondsSpent = 0; + QMutexLocker mutexLocker(db->dbOperMutex); while ((res = sqlite_step(stmt, &columnsCount, &values, &columns)) == SQLITE_BUSY && secondsSpent < db->getTimeout()) { QThread::sleep(1); |
