summaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/coreSQLiteStudio/common/readwritelocker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/common/readwritelocker.cpp')
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/readwritelocker.cpp103
1 files changed, 103 insertions, 0 deletions
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/readwritelocker.cpp b/SQLiteStudio3/coreSQLiteStudio/common/readwritelocker.cpp
new file mode 100644
index 0000000..0eaca75
--- /dev/null
+++ b/SQLiteStudio3/coreSQLiteStudio/common/readwritelocker.cpp
@@ -0,0 +1,103 @@
+#include "readwritelocker.h"
+#include "parser/lexer.h"
+#include <QReadWriteLock>
+#include <QReadLocker>
+#include <QWriteLocker>
+
+ReadWriteLocker::ReadWriteLocker(QReadWriteLock* lock, Mode mode)
+{
+ init(lock, mode);
+}
+
+ReadWriteLocker::ReadWriteLocker(QReadWriteLock* lock, const QString& query, Dialect dialect, bool noLock)
+{
+ init(lock, getMode(query, dialect, noLock));
+}
+
+ReadWriteLocker::~ReadWriteLocker()
+{
+ if (readLocker)
+ {
+ delete readLocker;
+ readLocker = nullptr;
+ }
+
+ if (writeLocker)
+ {
+ delete writeLocker;
+ writeLocker = nullptr;
+ }
+}
+
+void ReadWriteLocker::init(QReadWriteLock* lock, ReadWriteLocker::Mode mode)
+{
+ switch (mode)
+ {
+ case ReadWriteLocker::READ:
+ readLocker = new QReadLocker(lock);
+ break;
+ case ReadWriteLocker::WRITE:
+ writeLocker = new QWriteLocker(lock);
+ break;
+ case ReadWriteLocker::NONE:
+ // Nothing to lock.
+ break;
+ }
+}
+
+ReadWriteLocker::Mode ReadWriteLocker::getMode(const QString &query, Dialect dialect, bool noLock)
+{
+ static QStringList readOnlyCommands = {"ANALYZE", "EXPLAIN", "PRAGMA"};
+
+ if (noLock)
+ return ReadWriteLocker::NONE;
+
+ TokenList tokens = Lexer::tokenize(query, dialect);
+ int keywordIdx = tokens.indexOf(Token::KEYWORD);
+
+ if (keywordIdx > -1 && readOnlyCommands.contains(tokens[keywordIdx]->value.toUpper()))
+ return ReadWriteLocker::READ;
+
+ if (keywordIdx > -1 && tokens[keywordIdx]->value.toUpper() == "WITH")
+ {
+ bool matched = false;
+ bool isSelect = false;
+ int depth = 0;
+ for (TokenPtr token : tokens)
+ {
+ switch (token->type)
+ {
+ case Token::PAR_LEFT:
+ depth++;
+ break;
+ case Token::PAR_RIGHT:
+ depth--;
+ break;
+ case Token::KEYWORD:
+ if (depth == 0)
+ {
+ QString val = token->value.toUpper();
+ if (val == "SELECT")
+ {
+ matched = true;
+ isSelect = true;
+ }
+ else if (val == "DELETE" || val == "UPDATE" || val == "INSERT")
+ {
+ matched = true;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (matched)
+ break;
+ }
+ if (isSelect)
+ return ReadWriteLocker::READ;
+ }
+
+ return ReadWriteLocker::WRITE;
+}