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 "sqlitetable.h"
|
||||||
#include "sqlitetransaction.h"
|
#include "sqlitetransaction.h"
|
||||||
|
#include "sqlitereadwritestatement.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
@@ -54,11 +55,14 @@ Database::Database(Utils::PathString &&databaseFilePath,
|
|||||||
open(std::move(databaseFilePath));
|
open(std::move(databaseFilePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Database::~Database() = default;
|
||||||
|
|
||||||
void Database::open()
|
void Database::open()
|
||||||
{
|
{
|
||||||
m_databaseBackend.open(m_databaseFilePath, m_openMode);
|
m_databaseBackend.open(m_databaseFilePath, m_openMode);
|
||||||
m_databaseBackend.setJournalMode(m_journalMode);
|
m_databaseBackend.setJournalMode(m_journalMode);
|
||||||
m_databaseBackend.setBusyTimeout(m_busyTimeout);
|
m_databaseBackend.setBusyTimeout(m_busyTimeout);
|
||||||
|
registerTransactionStatements();
|
||||||
initializeTables();
|
initializeTables();
|
||||||
m_isOpen = true;
|
m_isOpen = true;
|
||||||
}
|
}
|
||||||
@@ -129,12 +133,55 @@ void Database::execute(Utils::SmallStringView sqlStatement)
|
|||||||
|
|
||||||
void Database::initializeTables()
|
void Database::initializeTables()
|
||||||
{
|
{
|
||||||
ImmediateTransaction transaction(*this);
|
try {
|
||||||
|
ImmediateTransaction transaction(*this);
|
||||||
|
|
||||||
for (Table &table : m_sqliteTables)
|
for (Table &table : m_sqliteTables)
|
||||||
table.initialize(*this);
|
table.initialize(*this);
|
||||||
|
|
||||||
transaction.commit();
|
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()
|
DatabaseBackend &Database::backend()
|
||||||
|
@@ -40,6 +40,7 @@ namespace Sqlite {
|
|||||||
|
|
||||||
class ReadStatement;
|
class ReadStatement;
|
||||||
class WriteStatement;
|
class WriteStatement;
|
||||||
|
class ReadWriteStatement;
|
||||||
|
|
||||||
class SQLITE_EXPORT Database final : public TransactionInterface
|
class SQLITE_EXPORT Database final : public TransactionInterface
|
||||||
{
|
{
|
||||||
@@ -54,10 +55,11 @@ public:
|
|||||||
|
|
||||||
Database();
|
Database();
|
||||||
Database(Utils::PathString &&databaseFilePath,
|
Database(Utils::PathString &&databaseFilePath,
|
||||||
JournalMode journalMode=JournalMode::Wal);
|
JournalMode journalMode=JournalMode::Delete);
|
||||||
Database(Utils::PathString &&databaseFilePath,
|
Database(Utils::PathString &&databaseFilePath,
|
||||||
std::chrono::milliseconds busyTimeout = {},
|
std::chrono::milliseconds busyTimeout = {},
|
||||||
JournalMode journalMode=JournalMode::Wal);
|
JournalMode journalMode=JournalMode::Delete);
|
||||||
|
~Database();
|
||||||
|
|
||||||
Database(const Database &) = delete;
|
Database(const Database &) = delete;
|
||||||
Database &operator=(const Database &) = delete;
|
Database &operator=(const Database &) = delete;
|
||||||
@@ -104,44 +106,26 @@ public:
|
|||||||
return m_databaseBackend.totalChangesCount();
|
return m_databaseBackend.totalChangesCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
void deferredBegin()
|
void deferredBegin();
|
||||||
{
|
void immediateBegin();
|
||||||
m_databaseMutex.lock();
|
void exclusiveBegin();
|
||||||
execute("BEGIN");
|
void commit();
|
||||||
}
|
void rollback();
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initializeTables();
|
void initializeTables();
|
||||||
|
void registerTransactionStatements();
|
||||||
std::mutex &databaseMutex() { return m_databaseMutex; }
|
std::mutex &databaseMutex() { return m_databaseMutex; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Utils::PathString m_databaseFilePath;
|
Utils::PathString m_databaseFilePath;
|
||||||
DatabaseBackend m_databaseBackend;
|
DatabaseBackend m_databaseBackend;
|
||||||
std::vector<Table> m_sqliteTables;
|
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::mutex m_databaseMutex;
|
||||||
std::chrono::milliseconds m_busyTimeout;
|
std::chrono::milliseconds m_busyTimeout;
|
||||||
JournalMode m_journalMode = JournalMode::Wal;
|
JournalMode m_journalMode = JournalMode::Wal;
|
||||||
|
@@ -140,6 +140,41 @@ TEST_F(SqliteDatabase, LastRowId)
|
|||||||
ASSERT_THAT(database.lastInsertedRowId(), 42);
|
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()
|
void SqliteDatabase::SetUp()
|
||||||
{
|
{
|
||||||
database.setJournalMode(JournalMode::Memory);
|
database.setJournalMode(JournalMode::Memory);
|
||||||
|
Reference in New Issue
Block a user