forked from qt-creator/qt-creator
Sqlite: Use compiled statements for transactions
So we don't recompile them again and again. Change-Id: I54c95e9d81df86f4944b9e3d45a7277f93f37312 Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "sqlitetable.h"
|
||||
#include "sqlitetransaction.h"
|
||||
#include "sqlitereadwritestatement.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
@@ -54,11 +55,14 @@ Database::Database(Utils::PathString &&databaseFilePath,
|
||||
open(std::move(databaseFilePath));
|
||||
}
|
||||
|
||||
Database::~Database() = default;
|
||||
|
||||
void Database::open()
|
||||
{
|
||||
m_databaseBackend.open(m_databaseFilePath, m_openMode);
|
||||
m_databaseBackend.setJournalMode(m_journalMode);
|
||||
m_databaseBackend.setBusyTimeout(m_busyTimeout);
|
||||
registerTransactionStatements();
|
||||
initializeTables();
|
||||
m_isOpen = true;
|
||||
}
|
||||
@@ -129,12 +133,55 @@ void Database::execute(Utils::SmallStringView sqlStatement)
|
||||
|
||||
void Database::initializeTables()
|
||||
{
|
||||
try {
|
||||
ImmediateTransaction transaction(*this);
|
||||
|
||||
for (Table &table : m_sqliteTables)
|
||||
table.initialize(*this);
|
||||
|
||||
transaction.commit();
|
||||
} catch (const StatementIsBusy &) {
|
||||
initializeTables();
|
||||
}
|
||||
}
|
||||
|
||||
void Database::registerTransactionStatements()
|
||||
{
|
||||
m_deferredBeginStatement = std::make_unique<ReadWriteStatement>("BEGIN", *this);
|
||||
m_immediateBeginStatement = std::make_unique<ReadWriteStatement>("BEGIN IMMEDIATE", *this);
|
||||
m_exclusiveBeginStatement = std::make_unique<ReadWriteStatement>("BEGIN EXCLUSIVE", *this);
|
||||
m_commitBeginStatement = std::make_unique<ReadWriteStatement>("COMMIT", *this);
|
||||
m_rollbackBeginStatement = std::make_unique<ReadWriteStatement>("ROLLBACK", *this);
|
||||
}
|
||||
|
||||
void Database::deferredBegin()
|
||||
{
|
||||
m_databaseMutex.lock();
|
||||
m_deferredBeginStatement->execute();
|
||||
}
|
||||
|
||||
void Database::immediateBegin()
|
||||
{
|
||||
m_databaseMutex.lock();
|
||||
m_immediateBeginStatement->execute();
|
||||
}
|
||||
|
||||
void Database::exclusiveBegin()
|
||||
{
|
||||
m_databaseMutex.lock();
|
||||
m_exclusiveBeginStatement->execute();
|
||||
}
|
||||
|
||||
void Database::commit()
|
||||
{
|
||||
m_commitBeginStatement->execute();
|
||||
m_databaseMutex.unlock();
|
||||
}
|
||||
|
||||
void Database::rollback()
|
||||
{
|
||||
m_rollbackBeginStatement->execute();
|
||||
m_databaseMutex.unlock();
|
||||
}
|
||||
|
||||
DatabaseBackend &Database::backend()
|
||||
|
@@ -40,6 +40,7 @@ namespace Sqlite {
|
||||
|
||||
class ReadStatement;
|
||||
class WriteStatement;
|
||||
class ReadWriteStatement;
|
||||
|
||||
class SQLITE_EXPORT Database final : public TransactionInterface
|
||||
{
|
||||
@@ -54,10 +55,11 @@ public:
|
||||
|
||||
Database();
|
||||
Database(Utils::PathString &&databaseFilePath,
|
||||
JournalMode journalMode=JournalMode::Wal);
|
||||
JournalMode journalMode=JournalMode::Delete);
|
||||
Database(Utils::PathString &&databaseFilePath,
|
||||
std::chrono::milliseconds busyTimeout = {},
|
||||
JournalMode journalMode=JournalMode::Wal);
|
||||
JournalMode journalMode=JournalMode::Delete);
|
||||
~Database();
|
||||
|
||||
Database(const Database &) = delete;
|
||||
Database &operator=(const Database &) = delete;
|
||||
@@ -104,44 +106,26 @@ public:
|
||||
return m_databaseBackend.totalChangesCount();
|
||||
}
|
||||
|
||||
void deferredBegin()
|
||||
{
|
||||
m_databaseMutex.lock();
|
||||
execute("BEGIN");
|
||||
}
|
||||
|
||||
void immediateBegin()
|
||||
{
|
||||
m_databaseMutex.lock();
|
||||
execute("BEGIN IMMEDIATE");
|
||||
}
|
||||
|
||||
void exclusiveBegin()
|
||||
{
|
||||
m_databaseMutex.lock();
|
||||
execute("BEGIN EXCLUSIVE");
|
||||
}
|
||||
|
||||
void commit()
|
||||
{
|
||||
execute("COMMIT");
|
||||
m_databaseMutex.unlock();
|
||||
}
|
||||
|
||||
void rollback()
|
||||
{
|
||||
execute("ROLLBACK");
|
||||
m_databaseMutex.unlock();
|
||||
}
|
||||
void deferredBegin();
|
||||
void immediateBegin();
|
||||
void exclusiveBegin();
|
||||
void commit();
|
||||
void rollback();
|
||||
|
||||
private:
|
||||
void initializeTables();
|
||||
void registerTransactionStatements();
|
||||
std::mutex &databaseMutex() { return m_databaseMutex; }
|
||||
|
||||
private:
|
||||
Utils::PathString m_databaseFilePath;
|
||||
DatabaseBackend m_databaseBackend;
|
||||
std::vector<Table> m_sqliteTables;
|
||||
std::unique_ptr<ReadWriteStatement> m_deferredBeginStatement;
|
||||
std::unique_ptr<ReadWriteStatement> m_immediateBeginStatement;
|
||||
std::unique_ptr<ReadWriteStatement> m_exclusiveBeginStatement;
|
||||
std::unique_ptr<ReadWriteStatement> m_commitBeginStatement;
|
||||
std::unique_ptr<ReadWriteStatement> m_rollbackBeginStatement;
|
||||
std::mutex m_databaseMutex;
|
||||
std::chrono::milliseconds m_busyTimeout;
|
||||
JournalMode m_journalMode = JournalMode::Wal;
|
||||
|
@@ -140,6 +140,41 @@ TEST_F(SqliteDatabase, LastRowId)
|
||||
ASSERT_THAT(database.lastInsertedRowId(), 42);
|
||||
}
|
||||
|
||||
TEST_F(SqliteDatabase, DeferredBegin)
|
||||
{
|
||||
ASSERT_ANY_THROW(database.deferredBegin());
|
||||
|
||||
database.commit();
|
||||
}
|
||||
|
||||
TEST_F(SqliteDatabase, ImmediateBegin)
|
||||
{
|
||||
ASSERT_ANY_THROW(database.immediateBegin());
|
||||
|
||||
database.commit();
|
||||
}
|
||||
|
||||
TEST_F(SqliteDatabase, ExclusiveBegin)
|
||||
{
|
||||
ASSERT_ANY_THROW(database.exclusiveBegin());
|
||||
|
||||
database.commit();
|
||||
}
|
||||
|
||||
TEST_F(SqliteDatabase, Commit)
|
||||
{
|
||||
database.deferredBegin();
|
||||
|
||||
ASSERT_ANY_THROW(database.commit());
|
||||
}
|
||||
|
||||
TEST_F(SqliteDatabase, Rollback)
|
||||
{
|
||||
database.deferredBegin();
|
||||
|
||||
ASSERT_ANY_THROW(database.rollback());
|
||||
}
|
||||
|
||||
void SqliteDatabase::SetUp()
|
||||
{
|
||||
database.setJournalMode(JournalMode::Memory);
|
||||
|
Reference in New Issue
Block a user