diff options
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/common/readwritelocker.cpp')
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/common/readwritelocker.cpp | 103 |
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; +} |
