aboutsummaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h
diff options
context:
space:
mode:
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h')
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/db/abstractdb2.h69
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);