Sqlite: Remove static database handle

Change-Id: Ic31f61a477ad681652eeccdaa39f82970c57eb5a
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2017-07-26 18:43:07 +02:00
parent e562cc3f68
commit 400da9def8
17 changed files with 271 additions and 190 deletions

View File

@@ -41,16 +41,22 @@ SqliteDatabase::~SqliteDatabase()
void SqliteDatabase::open() void SqliteDatabase::open()
{ {
m_sqliteDatabaseBackEnd.open(m_databaseFilePath); m_databaseBackend.open(m_databaseFilePath);
m_sqliteDatabaseBackEnd.setJournalMode(journalMode()); m_databaseBackend.setJournalMode(journalMode());
initializeTables(); initializeTables();
m_isOpen = true; m_isOpen = true;
} }
void SqliteDatabase::open(const QString &databaseFilePath)
{
setDatabaseFilePath(databaseFilePath);
open();
}
void SqliteDatabase::close() void SqliteDatabase::close()
{ {
m_isOpen = false; m_isOpen = false;
m_sqliteDatabaseBackEnd.close(); m_databaseBackend.close();
} }
bool SqliteDatabase::isOpen() const bool SqliteDatabase::isOpen() const
@@ -89,10 +95,25 @@ JournalMode SqliteDatabase::journalMode() const
return m_journalMode; return m_journalMode;
} }
int SqliteDatabase::changesCount()
{
return m_databaseBackend.changesCount();
}
int SqliteDatabase::totalChangesCount()
{
return m_databaseBackend.totalChangesCount();
}
void SqliteDatabase::initializeTables() void SqliteDatabase::initializeTables()
{ {
for (SqliteTable *table: tables()) for (SqliteTable *table: tables())
table->initialize(); table->initialize();
} }
SqliteDatabaseBackend &SqliteDatabase::backend()
{
return m_databaseBackend;
}
} // namespace Sqlite } // namespace Sqlite

View File

@@ -34,14 +34,19 @@
namespace Sqlite { namespace Sqlite {
class SqliteTable; class SqliteTable;
class SqliteDatabaseBackend;
class SQLITE_EXPORT SqliteDatabase class SQLITE_EXPORT SqliteDatabase
{ {
friend class SqliteAbstractTransaction;
friend class SqliteStatement;
public: public:
SqliteDatabase(); SqliteDatabase();
~SqliteDatabase(); ~SqliteDatabase();
void open(); void open();
void open(const QString &databaseFilePath);
void close(); void close();
bool isOpen() const; bool isOpen() const;
@@ -55,12 +60,16 @@ public:
void setJournalMode(JournalMode journalMode); void setJournalMode(JournalMode journalMode);
JournalMode journalMode() const; JournalMode journalMode() const;
int changesCount();
int totalChangesCount();
private: private:
void initializeTables(); void initializeTables();
SqliteDatabaseBackend &backend();
private: private:
SqliteDatabaseBackend m_sqliteDatabaseBackEnd; SqliteDatabaseBackend m_databaseBackend;
QVector<SqliteTable*> m_sqliteTables; QVector<SqliteTable*> m_sqliteTables;
QString m_databaseFilePath; QString m_databaseFilePath;
JournalMode m_journalMode; JournalMode m_journalMode;

View File

@@ -48,19 +48,15 @@
namespace Sqlite { namespace Sqlite {
QTC_THREAD_LOCAL SqliteDatabaseBackend *sqliteDatabaseBackend = nullptr;
SqliteDatabaseBackend::SqliteDatabaseBackend() SqliteDatabaseBackend::SqliteDatabaseBackend()
: m_databaseHandle(nullptr), : m_databaseHandle(nullptr),
m_cachedTextEncoding(Utf8) m_cachedTextEncoding(Utf8)
{ {
sqliteDatabaseBackend = this;
} }
SqliteDatabaseBackend::~SqliteDatabaseBackend() SqliteDatabaseBackend::~SqliteDatabaseBackend()
{ {
closeWithoutException(); closeWithoutException();
sqliteDatabaseBackend = nullptr;
} }
void SqliteDatabaseBackend::setMmapSize(qint64 defaultSize, qint64 maximumSize) void SqliteDatabaseBackend::setMmapSize(qint64 defaultSize, qint64 maximumSize)
@@ -123,22 +119,22 @@ void SqliteDatabaseBackend::open(const QString &databaseFilePath)
sqlite3 *SqliteDatabaseBackend::sqliteDatabaseHandle() sqlite3 *SqliteDatabaseBackend::sqliteDatabaseHandle()
{ {
checkDatabaseBackendIsNotNull();
checkDatabaseHandleIsNotNull(); checkDatabaseHandleIsNotNull();
return threadLocalInstance()->m_databaseHandle; return m_databaseHandle;
} }
void SqliteDatabaseBackend::setPragmaValue(const Utf8String &pragmaKey, const Utf8String &newPragmaValue) void SqliteDatabaseBackend::setPragmaValue(const Utf8String &pragmaKey, const Utf8String &newPragmaValue)
{ {
SqliteReadWriteStatement::execute(Utf8StringLiteral("PRAGMA ") + pragmaKey + Utf8StringLiteral("='") + newPragmaValue + Utf8StringLiteral("'")); SqliteReadWriteStatement statement(Utf8StringLiteral("PRAGMA ") + pragmaKey + Utf8StringLiteral("='") + newPragmaValue + Utf8StringLiteral("'"), *this);
Utf8String pragmeValueInDatabase = SqliteReadWriteStatement::toValue<Utf8String>(Utf8StringLiteral("PRAGMA ") + pragmaKey); statement.step();
Utf8String pragmeValueInDatabase = toValue<Utf8String>(Utf8StringLiteral("PRAGMA ") + pragmaKey);
checkPragmaValue(pragmeValueInDatabase, newPragmaValue); checkPragmaValue(pragmeValueInDatabase, newPragmaValue);
} }
Utf8String SqliteDatabaseBackend::pragmaValue(const Utf8String &pragma) const Utf8String SqliteDatabaseBackend::pragmaValue(const Utf8String &pragma)
{ {
return SqliteReadWriteStatement::toValue<Utf8String>(Utf8StringLiteral("PRAGMA ") + pragma); return toValue<Utf8String>(Utf8StringLiteral("PRAGMA ") + pragma);
} }
void SqliteDatabaseBackend::setJournalMode(JournalMode journalMode) void SqliteDatabaseBackend::setJournalMode(JournalMode journalMode)
@@ -146,7 +142,7 @@ void SqliteDatabaseBackend::setJournalMode(JournalMode journalMode)
setPragmaValue(Utf8StringLiteral("journal_mode"), journalModeToPragma(journalMode)); setPragmaValue(Utf8StringLiteral("journal_mode"), journalModeToPragma(journalMode));
} }
JournalMode SqliteDatabaseBackend::journalMode() const JournalMode SqliteDatabaseBackend::journalMode()
{ {
return pragmaToJournalMode(pragmaValue(Utf8StringLiteral("journal_mode"))); return pragmaToJournalMode(pragmaValue(Utf8StringLiteral("journal_mode")));
} }
@@ -165,7 +161,7 @@ TextEncoding SqliteDatabaseBackend::textEncoding()
Utf8StringVector SqliteDatabaseBackend::columnNames(const Utf8String &tableName) Utf8StringVector SqliteDatabaseBackend::columnNames(const Utf8String &tableName)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT * FROM ") + tableName); SqliteReadWriteStatement statement(Utf8StringLiteral("SELECT * FROM ") + tableName, *this);
return statement.columnNames(); return statement.columnNames();
} }
@@ -179,6 +175,12 @@ int SqliteDatabaseBackend::totalChangesCount()
return sqlite3_total_changes(sqliteDatabaseHandle()); return sqlite3_total_changes(sqliteDatabaseHandle());
} }
void SqliteDatabaseBackend::execute(const Utf8String &sqlStatementUtf8)
{
SqliteReadWriteStatement statement(sqlStatementUtf8, *this);
statement.step();
}
void SqliteDatabaseBackend::close() void SqliteDatabaseBackend::close()
{ {
checkForOpenDatabaseWhichCanBeClosed(); checkForOpenDatabaseWhichCanBeClosed();
@@ -191,12 +193,6 @@ void SqliteDatabaseBackend::close()
} }
SqliteDatabaseBackend *SqliteDatabaseBackend::threadLocalInstance()
{
checkDatabaseBackendIsNotNull();
return sqliteDatabaseBackend;
}
bool SqliteDatabaseBackend::databaseIsOpen() const bool SqliteDatabaseBackend::databaseIsOpen() const
{ {
return m_databaseHandle != nullptr; return m_databaseHandle != nullptr;
@@ -282,16 +278,10 @@ void SqliteDatabaseBackend::checkPragmaValue(const Utf8String &databaseValue, co
void SqliteDatabaseBackend::checkDatabaseHandleIsNotNull() void SqliteDatabaseBackend::checkDatabaseHandleIsNotNull()
{ {
if (sqliteDatabaseBackend->m_databaseHandle == nullptr) if (m_databaseHandle == nullptr)
throwException("SqliteDatabaseBackend: database is not open!"); throwException("SqliteDatabaseBackend: database is not open!");
} }
void SqliteDatabaseBackend::checkDatabaseBackendIsNotNull()
{
if (sqliteDatabaseBackend == nullptr)
throwException("SqliteDatabaseBackend: database backend is not initialized!");
}
void SqliteDatabaseBackend::checkIfMultithreadingIsActivated(int resultCode) void SqliteDatabaseBackend::checkIfMultithreadingIsActivated(int resultCode)
{ {
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
@@ -357,7 +347,7 @@ JournalMode SqliteDatabaseBackend::pragmaToJournalMode(const Utf8String &pragma)
int index = indexOfPragma(pragma, journalModeStrings, SIZE_OF_BYTEARRAY_ARRAY(journalModeStrings)); int index = indexOfPragma(pragma, journalModeStrings, SIZE_OF_BYTEARRAY_ARRAY(journalModeStrings));
if (index < 0) if (index < 0)
throwException("SqliteDatabaseBackend::pragmaToJournalMode: pragma can't be transformed in a journal mode enumeration!"); throwExceptionStatic("SqliteDatabaseBackend::pragmaToJournalMode: pragma can't be transformed in a journal mode enumeration!");
return static_cast<JournalMode>(index); return static_cast<JournalMode>(index);
} }
@@ -378,17 +368,32 @@ TextEncoding SqliteDatabaseBackend::pragmaToTextEncoding(const Utf8String &pragm
int index = indexOfPragma(pragma, textEncodingStrings, SIZE_OF_BYTEARRAY_ARRAY(textEncodingStrings)); int index = indexOfPragma(pragma, textEncodingStrings, SIZE_OF_BYTEARRAY_ARRAY(textEncodingStrings));
if (index < 0) if (index < 0)
throwException("SqliteDatabaseBackend::pragmaToTextEncoding: pragma can't be transformed in a text encoding enumeration!"); throwExceptionStatic("SqliteDatabaseBackend::pragmaToTextEncoding: pragma can't be transformed in a text encoding enumeration!");
return static_cast<TextEncoding>(index); return static_cast<TextEncoding>(index);
} }
void SqliteDatabaseBackend::throwException(const char *whatHasHappens) void SqliteDatabaseBackend::throwExceptionStatic(const char *whatHasHappens)
{ {
if (sqliteDatabaseBackend && sqliteDatabaseBackend->m_databaseHandle) throw SqliteException(whatHasHappens);
throw SqliteException(whatHasHappens, sqlite3_errmsg(sqliteDatabaseBackend->m_databaseHandle)); }
void SqliteDatabaseBackend::throwException(const char *whatHasHappens) const
{
if (m_databaseHandle)
throw SqliteException(whatHasHappens, sqlite3_errmsg(m_databaseHandle));
else else
throw SqliteException(whatHasHappens); throw SqliteException(whatHasHappens);
} }
template <typename Type>
Type SqliteDatabaseBackend::toValue(const Utf8String &sqlStatementUtf8)
{
SqliteReadWriteStatement statement(sqlStatementUtf8, *this);
statement.next();
return statement.value<Type>(0);
}
} // namespace Sqlite } // namespace Sqlite

View File

@@ -42,38 +42,42 @@ public:
SqliteDatabaseBackend(); SqliteDatabaseBackend();
~SqliteDatabaseBackend(); ~SqliteDatabaseBackend();
static void setMmapSize(qint64 defaultSize, qint64 maximumSize); void setMmapSize(qint64 defaultSize, qint64 maximumSize);
static void activateMultiThreading(); void activateMultiThreading();
static void activateLogging(); void activateLogging();
static void initializeSqliteLibrary(); void initializeSqliteLibrary();
static void shutdownSqliteLibrary(); void shutdownSqliteLibrary();
static void checkpointFullWalLog(); void checkpointFullWalLog();
void open(const QString &databaseFilePath); void open(const QString &databaseFilePath);
void close(); void close();
void closeWithoutException(); void closeWithoutException();
static SqliteDatabaseBackend *threadLocalInstance(); sqlite3* sqliteDatabaseHandle();
static sqlite3* sqliteDatabaseHandle();
void setJournalMode(JournalMode journalMode); void setJournalMode(JournalMode journalMode);
JournalMode journalMode() const; JournalMode journalMode();
void setTextEncoding(TextEncoding textEncoding); void setTextEncoding(TextEncoding textEncoding);
TextEncoding textEncoding(); TextEncoding textEncoding();
static Utf8StringVector columnNames(const Utf8String &tableName); Utf8StringVector columnNames(const Utf8String &tableName);
static int changesCount(); int changesCount();
static int totalChangesCount(); int totalChangesCount();
void execute(const Utf8String &sqlStatementUtf8);
template <typename Type>
Type toValue(const Utf8String &sqlStatementUtf8);
protected: protected:
bool databaseIsOpen() const; bool databaseIsOpen() const;
void setPragmaValue(const Utf8String &pragma, const Utf8String &value); void setPragmaValue(const Utf8String &pragma, const Utf8String &value);
Utf8String pragmaValue(const Utf8String &pragma) const; Utf8String pragmaValue(const Utf8String &pragma);
void registerBusyHandler(); void registerBusyHandler();
void registerRankingFunction(); void registerRankingFunction();
@@ -86,22 +90,22 @@ protected:
void checkCanOpenDatabase(const QString &databaseFilePath); void checkCanOpenDatabase(const QString &databaseFilePath);
void checkDatabaseCouldBeOpened(int resultCode); void checkDatabaseCouldBeOpened(int resultCode);
void checkPragmaValue(const Utf8String &databaseValue, const Utf8String &expectedValue); void checkPragmaValue(const Utf8String &databaseValue, const Utf8String &expectedValue);
static void checkDatabaseHandleIsNotNull(); void checkDatabaseHandleIsNotNull();
static void checkDatabaseBackendIsNotNull(); void checkIfMultithreadingIsActivated(int resultCode);
static void checkIfMultithreadingIsActivated(int resultCode); void checkIfLoogingIsActivated(int resultCode);
static void checkIfLoogingIsActivated(int resultCode); void checkMmapSizeIsSet(int resultCode);
static void checkMmapSizeIsSet(int resultCode); void checkInitializeSqliteLibraryWasSuccesful(int resultCode);
static void checkInitializeSqliteLibraryWasSuccesful(int resultCode); void checkShutdownSqliteLibraryWasSuccesful(int resultCode);
static void checkShutdownSqliteLibraryWasSuccesful(int resultCode); void checkIfLogCouldBeCheckpointed(int resultCode);
static void checkIfLogCouldBeCheckpointed(int resultCode);
static int indexOfPragma(const Utf8String pragma, const Utf8String pragmas[], size_t pragmaCount); static int indexOfPragma(const Utf8String pragma, const Utf8String pragmas[], size_t pragmaCount);
static const Utf8String &journalModeToPragma(JournalMode journalMode); static const Utf8String &journalModeToPragma(JournalMode journalMode);
static JournalMode pragmaToJournalMode(const Utf8String &pragma); static JournalMode pragmaToJournalMode(const Utf8String &pragma);
static const Utf8String &textEncodingToPragma(TextEncoding textEncoding); const Utf8String &textEncodingToPragma(TextEncoding textEncoding);
static TextEncoding pragmaToTextEncoding(const Utf8String &pragma); static TextEncoding pragmaToTextEncoding(const Utf8String &pragma);
Q_NORETURN static void throwException(const char *whatHasHappens); Q_NORETURN static void throwExceptionStatic(const char *whatHasHappens);
Q_NORETURN void throwException(const char *whatHasHappens) const;
private: private:
sqlite3 *m_databaseHandle; sqlite3 *m_databaseHandle;

View File

@@ -29,8 +29,9 @@
namespace Sqlite { namespace Sqlite {
SqliteReadStatement::SqliteReadStatement(const Utf8String &sqlStatementUtf8) SqliteReadStatement::SqliteReadStatement(const Utf8String &sqlStatementUtf8,
: SqliteStatement(sqlStatementUtf8) SqliteDatabase &database)
: SqliteStatement(sqlStatementUtf8, database)
{ {
checkIsReadOnlyStatement(); checkIsReadOnlyStatement();
} }

View File

@@ -32,7 +32,7 @@ namespace Sqlite {
class SQLITE_EXPORT SqliteReadStatement final : private SqliteStatement class SQLITE_EXPORT SqliteReadStatement final : private SqliteStatement
{ {
public: public:
explicit SqliteReadStatement(const Utf8String &sqlStatementUtf8); explicit SqliteReadStatement(const Utf8String &sqlStatementUtf8, SqliteDatabase &database);
using SqliteStatement::next; using SqliteStatement::next;
using SqliteStatement::reset; using SqliteStatement::reset;

View File

@@ -27,8 +27,15 @@
namespace Sqlite { namespace Sqlite {
SqliteReadWriteStatement::SqliteReadWriteStatement(const Utf8String &sqlStatementUft8) SqliteReadWriteStatement::SqliteReadWriteStatement(const Utf8String &sqlStatementUft8,
: SqliteStatement(sqlStatementUft8) SqliteDatabase &database)
: SqliteStatement(sqlStatementUft8, database)
{
}
SqliteReadWriteStatement::SqliteReadWriteStatement(const Utf8String &sqlStatementUft8,
SqliteDatabaseBackend &backend)
: SqliteStatement(sqlStatementUft8, backend)
{ {
} }

View File

@@ -31,8 +31,10 @@ namespace Sqlite {
class SQLITE_EXPORT SqliteReadWriteStatement final : private SqliteStatement class SQLITE_EXPORT SqliteReadWriteStatement final : private SqliteStatement
{ {
friend class SqliteDatabaseBackend;
public: public:
explicit SqliteReadWriteStatement(const Utf8String &sqlStatementUft8); explicit SqliteReadWriteStatement(const Utf8String &sqlStatementUft8, SqliteDatabase &database);
using SqliteStatement::next; using SqliteStatement::next;
using SqliteStatement::step; using SqliteStatement::step;
@@ -48,7 +50,10 @@ public:
using SqliteStatement::columnCount; using SqliteStatement::columnCount;
using SqliteStatement::columnNames; using SqliteStatement::columnNames;
using SqliteStatement::toValue; using SqliteStatement::toValue;
using SqliteStatement::execute;
private:
explicit SqliteReadWriteStatement(const Utf8String &sqlStatementUft8,
SqliteDatabaseBackend &backend);
}; };
} // namespace Sqlite } // namespace Sqlite

View File

@@ -25,6 +25,7 @@
#include "sqlitestatement.h" #include "sqlitestatement.h"
#include "sqlitedatabase.h"
#include "sqlitedatabasebackend.h" #include "sqlitedatabasebackend.h"
#include "sqliteexception.h" #include "sqliteexception.h"
@@ -41,8 +42,15 @@
namespace Sqlite { namespace Sqlite {
SqliteStatement::SqliteStatement(const Utf8String &sqlStatementUtf8) SqliteStatement::SqliteStatement(const Utf8String &sqlStatementUtf8, SqliteDatabase &database)
: SqliteStatement(sqlStatementUtf8, database.backend())
{
}
SqliteStatement::SqliteStatement(const Utf8String &sqlStatementUtf8, SqliteDatabaseBackend &databaseBackend)
: m_compiledStatement(nullptr, deleteCompiledStatement), : m_compiledStatement(nullptr, deleteCompiledStatement),
m_databaseBackend(databaseBackend),
m_bindingParameterCount(0), m_bindingParameterCount(0),
m_columnCount(0), m_columnCount(0),
m_isReadyToFetchValues(false) m_isReadyToFetchValues(false)
@@ -295,12 +303,6 @@ const Utf8StringVector &SqliteStatement::bindingColumnNames() const
return m_bindingColumnNames; return m_bindingColumnNames;
} }
void SqliteStatement::execute(const Utf8String &sqlStatementUtf8)
{
SqliteStatement statement(sqlStatementUtf8);
statement.step();
}
void SqliteStatement::prepare(const Utf8String &sqlStatementUtf8) void SqliteStatement::prepare(const Utf8String &sqlStatementUtf8)
{ {
int resultCode; int resultCode;
@@ -318,19 +320,14 @@ void SqliteStatement::prepare(const Utf8String &sqlStatementUtf8)
checkForPrepareError(resultCode); checkForPrepareError(resultCode);
} }
sqlite3 *SqliteStatement::sqliteDatabaseHandle() sqlite3 *SqliteStatement::sqliteDatabaseHandle() const
{ {
return SqliteDatabaseBackend::sqliteDatabaseHandle(); return m_databaseBackend.sqliteDatabaseHandle();
} }
TextEncoding SqliteStatement::databaseTextEncoding() TextEncoding SqliteStatement::databaseTextEncoding()
{ {
if (SqliteDatabaseBackend::threadLocalInstance()) return m_databaseBackend.textEncoding();
return SqliteDatabaseBackend::threadLocalInstance()->textEncoding();
throwException("SqliteStatement::databaseTextEncoding: database backend instance is null!");
Q_UNREACHABLE();
} }
bool SqliteStatement::checkForStepError(int resultCode) const bool SqliteStatement::checkForStepError(int resultCode) const
@@ -445,7 +442,7 @@ bool SqliteStatement::isReadOnlyStatement() const
return sqlite3_stmt_readonly(m_compiledStatement.get()); return sqlite3_stmt_readonly(m_compiledStatement.get());
} }
void SqliteStatement::throwException(const char *whatHasHappened) void SqliteStatement::throwException(const char *whatHasHappened) const
{ {
throw SqliteException(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); throw SqliteException(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
} }
@@ -654,21 +651,21 @@ template SQLITE_EXPORT Utf8StringVector SqliteStatement::values<Utf8StringVector
template SQLITE_EXPORT QVector<QString> SqliteStatement::values<QVector<QString>>(int column) const; template SQLITE_EXPORT QVector<QString> SqliteStatement::values<QVector<QString>>(int column) const;
template <typename Type> template <typename Type>
Type SqliteStatement::toValue(const Utf8String &sqlStatementUtf8) Type SqliteStatement::toValue(const Utf8String &sqlStatementUtf8, SqliteDatabase &database)
{ {
SqliteStatement statement(sqlStatementUtf8); SqliteStatement statement(sqlStatementUtf8, database);
statement.next(); statement.next();
return statement.value<Type>(0); return statement.value<Type>(0);
} }
template SQLITE_EXPORT int SqliteStatement::toValue<int>(const Utf8String &sqlStatementUtf8); template SQLITE_EXPORT int SqliteStatement::toValue<int>(const Utf8String &sqlStatementUtf8, SqliteDatabase &database);
template SQLITE_EXPORT qint64 SqliteStatement::toValue<qint64>(const Utf8String &sqlStatementUtf8); template SQLITE_EXPORT qint64 SqliteStatement::toValue<qint64>(const Utf8String &sqlStatementUtf8, SqliteDatabase &database);
template SQLITE_EXPORT double SqliteStatement::toValue<double>(const Utf8String &sqlStatementUtf8); template SQLITE_EXPORT double SqliteStatement::toValue<double>(const Utf8String &sqlStatementUtf8, SqliteDatabase &database);
template SQLITE_EXPORT QString SqliteStatement::toValue<QString>(const Utf8String &sqlStatementUtf8); template SQLITE_EXPORT QString SqliteStatement::toValue<QString>(const Utf8String &sqlStatementUtf8, SqliteDatabase &database);
template SQLITE_EXPORT QByteArray SqliteStatement::toValue<QByteArray>(const Utf8String &sqlStatementUtf8); template SQLITE_EXPORT QByteArray SqliteStatement::toValue<QByteArray>(const Utf8String &sqlStatementUtf8, SqliteDatabase &database);
template SQLITE_EXPORT Utf8String SqliteStatement::toValue<Utf8String>(const Utf8String &sqlStatementUtf8); template SQLITE_EXPORT Utf8String SqliteStatement::toValue<Utf8String>(const Utf8String &sqlStatementUtf8, SqliteDatabase &database);
template SQLITE_EXPORT QVariant SqliteStatement::toValue<QVariant>(const Utf8String &sqlStatementUtf8); template SQLITE_EXPORT QVariant SqliteStatement::toValue<QVariant>(const Utf8String &sqlStatementUtf8, SqliteDatabase &database);
} // namespace Sqlite } // namespace Sqlite

View File

@@ -42,10 +42,13 @@ struct sqlite3;
namespace Sqlite { namespace Sqlite {
class SqliteDatabase;
class SqliteDatabaseBackend;
class SQLITE_EXPORT SqliteStatement class SQLITE_EXPORT SqliteStatement
{ {
protected: protected:
explicit SqliteStatement(const Utf8String &sqlStatementUtf8); explicit SqliteStatement(const Utf8String &sqlStatementUtf8, SqliteDatabase &database);
static void deleteCompiledStatement(sqlite3_stmt *m_compiledStatement); static void deleteCompiledStatement(sqlite3_stmt *m_compiledStatement);
@@ -85,10 +88,8 @@ protected:
QMap<QString, QVariant> rowColumnValueMap() const; QMap<QString, QVariant> rowColumnValueMap() const;
QMap<QString, QVariant> twoColumnValueMap() const; QMap<QString, QVariant> twoColumnValueMap() const;
static void execute(const Utf8String &sqlStatementUtf8);
template <typename Type> template <typename Type>
static Type toValue(const Utf8String &sqlStatementUtf8); static Type toValue(const Utf8String &sqlStatementUtf8, SqliteDatabase &database);
void prepare(const Utf8String &sqlStatementUtf8); void prepare(const Utf8String &sqlStatementUtf8);
void waitForUnlockNotify() const; void waitForUnlockNotify() const;
@@ -96,8 +97,8 @@ protected:
void write(const RowDictionary &rowDictionary); void write(const RowDictionary &rowDictionary);
void writeUnchecked(const RowDictionary &rowDictionary); void writeUnchecked(const RowDictionary &rowDictionary);
static sqlite3 *sqliteDatabaseHandle(); sqlite3 *sqliteDatabaseHandle() const;
static TextEncoding databaseTextEncoding(); TextEncoding databaseTextEncoding();
bool checkForStepError(int resultCode) const; bool checkForStepError(int resultCode) const;
@@ -114,16 +115,21 @@ protected:
void setColumnCount(); void setColumnCount();
void checkBindingValueMapIsEmpty(const RowDictionary &rowDictionary) const; void checkBindingValueMapIsEmpty(const RowDictionary &rowDictionary) const;
bool isReadOnlyStatement() const; bool isReadOnlyStatement() const;
Q_NORETURN static void throwException(const char *whatHasHappened); Q_NORETURN void throwException(const char *whatHasHappened) const;
template <typename ContainerType> template <typename ContainerType>
ContainerType columnValues(const QVector<int> &columnIndices) const; ContainerType columnValues(const QVector<int> &columnIndices) const;
QString columnName(int column) const; QString columnName(int column) const;
protected:
explicit SqliteStatement(const Utf8String &sqlStatementUtf8,
SqliteDatabaseBackend &databaseBackend);
private: private:
std::unique_ptr<sqlite3_stmt, void (*)(sqlite3_stmt*)> m_compiledStatement; std::unique_ptr<sqlite3_stmt, void (*)(sqlite3_stmt*)> m_compiledStatement;
Utf8StringVector m_bindingColumnNames; Utf8StringVector m_bindingColumnNames;
SqliteDatabaseBackend &m_databaseBackend;
int m_bindingParameterCount; int m_bindingParameterCount;
int m_columnCount; int m_columnCount;
mutable bool m_isReadyToFetchValues; mutable bool m_isReadyToFetchValues;

View File

@@ -88,8 +88,8 @@ void SqliteTable::initialize()
createTableSqlStatementBuilder.setUseWithoutRowId(m_withoutRowId); createTableSqlStatementBuilder.setUseWithoutRowId(m_withoutRowId);
createTableSqlStatementBuilder.setColumnDefinitions(createColumnDefintions()); createTableSqlStatementBuilder.setColumnDefinitions(createColumnDefintions());
SqliteImmediateTransaction transaction; SqliteImmediateTransaction transaction(*m_sqliteDatabase);
SqliteWriteStatement::execute(createTableSqlStatementBuilder.sqlStatement()); SqliteWriteStatement(createTableSqlStatementBuilder.sqlStatement(), *m_sqliteDatabase).step();
transaction.commit(); transaction.commit();
m_isReady = true; m_isReady = true;

View File

@@ -25,6 +25,8 @@
#include "sqlitetransaction.h" #include "sqlitetransaction.h"
#include "sqlitedatabase.h"
#include "sqlitedatabasebackend.h"
#include "sqlitewritestatement.h" #include "sqlitewritestatement.h"
namespace Sqlite { namespace Sqlite {
@@ -32,28 +34,41 @@ namespace Sqlite {
SqliteAbstractTransaction::~SqliteAbstractTransaction() SqliteAbstractTransaction::~SqliteAbstractTransaction()
{ {
if (!m_isAlreadyCommited) if (!m_isAlreadyCommited)
SqliteWriteStatement::execute(Utf8StringLiteral("ROLLBACK")); m_databaseBackend.execute(Utf8StringLiteral("ROLLBACK"));
} }
void SqliteAbstractTransaction::commit() void SqliteAbstractTransaction::commit()
{ {
SqliteWriteStatement::execute(Utf8StringLiteral("COMMIT")); m_databaseBackend.execute(Utf8StringLiteral("COMMIT"));
m_isAlreadyCommited = true; m_isAlreadyCommited = true;
} }
SqliteTransaction::SqliteTransaction() SqliteAbstractTransaction::SqliteAbstractTransaction(SqliteDatabaseBackend &backend)
: m_databaseBackend(backend)
{ {
SqliteWriteStatement::execute(Utf8StringLiteral("BEGIN"));
} }
SqliteImmediateTransaction::SqliteImmediateTransaction() SqliteAbstractTransaction::SqliteAbstractTransaction(SqliteDatabase &database)
: SqliteAbstractTransaction(database.backend())
{ {
SqliteWriteStatement::execute(Utf8StringLiteral("BEGIN IMMEDIATE"));
} }
SqliteExclusiveTransaction::SqliteExclusiveTransaction() SqliteTransaction::SqliteTransaction(SqliteDatabase &database)
: SqliteAbstractTransaction(database)
{ {
SqliteWriteStatement::execute(Utf8StringLiteral("BEGIN EXCLUSIVE")); m_databaseBackend.execute(Utf8StringLiteral("BEGIN"));
}
SqliteImmediateTransaction::SqliteImmediateTransaction(SqliteDatabase &database)
: SqliteAbstractTransaction(database)
{
m_databaseBackend.execute(Utf8StringLiteral("BEGIN IMMEDIATE"));
}
SqliteExclusiveTransaction::SqliteExclusiveTransaction(SqliteDatabase &database)
: SqliteAbstractTransaction(database)
{
m_databaseBackend.execute(Utf8StringLiteral("BEGIN EXCLUSIVE"));
} }
} // namespace Sqlite } // namespace Sqlite

View File

@@ -29,6 +29,9 @@
namespace Sqlite { namespace Sqlite {
class SqliteDatabaseBackend;
class SqliteDatabase;
class SQLITE_EXPORT SqliteAbstractTransaction class SQLITE_EXPORT SqliteAbstractTransaction
{ {
public: public:
@@ -36,6 +39,13 @@ public:
void commit(); void commit();
protected:
SqliteAbstractTransaction(SqliteDatabaseBackend &backend);
SqliteAbstractTransaction(SqliteDatabase &database);
protected:
SqliteDatabaseBackend &m_databaseBackend;
private: private:
bool m_isAlreadyCommited = false; bool m_isAlreadyCommited = false;
}; };
@@ -44,21 +54,21 @@ private:
class SQLITE_EXPORT SqliteTransaction final : public SqliteAbstractTransaction class SQLITE_EXPORT SqliteTransaction final : public SqliteAbstractTransaction
{ {
public: public:
SqliteTransaction(); SqliteTransaction(SqliteDatabase &database);
}; };
class SQLITE_EXPORT SqliteImmediateTransaction final : public SqliteAbstractTransaction class SQLITE_EXPORT SqliteImmediateTransaction final : public SqliteAbstractTransaction
{ {
public: public:
SqliteImmediateTransaction(); SqliteImmediateTransaction(SqliteDatabase &database);
}; };
class SQLITE_EXPORT SqliteExclusiveTransaction final : public SqliteAbstractTransaction class SQLITE_EXPORT SqliteExclusiveTransaction final : public SqliteAbstractTransaction
{ {
public: public:
SqliteExclusiveTransaction(); SqliteExclusiveTransaction(SqliteDatabase &database);
}; };

View File

@@ -27,8 +27,9 @@
namespace Sqlite { namespace Sqlite {
SqliteWriteStatement::SqliteWriteStatement(const Utf8String &sqlStatementUtf8) SqliteWriteStatement::SqliteWriteStatement(const Utf8String &sqlStatementUtf8,
: SqliteStatement(sqlStatementUtf8) SqliteDatabase &database)
: SqliteStatement(sqlStatementUtf8, database)
{ {
checkIsWritableStatement(); checkIsWritableStatement();
} }

View File

@@ -32,7 +32,7 @@ namespace Sqlite {
class SQLITE_EXPORT SqliteWriteStatement : private SqliteStatement class SQLITE_EXPORT SqliteWriteStatement : private SqliteStatement
{ {
public: public:
explicit SqliteWriteStatement(const Utf8String &sqlStatementUtf8); explicit SqliteWriteStatement(const Utf8String &sqlStatementUtf8, SqliteDatabase &database);
using SqliteStatement::step; using SqliteStatement::step;
using SqliteStatement::reset; using SqliteStatement::reset;
@@ -43,7 +43,6 @@ public:
using SqliteStatement::bindingColumnNames; using SqliteStatement::bindingColumnNames;
using SqliteStatement::write; using SqliteStatement::write;
using SqliteStatement::writeUnchecked; using SqliteStatement::writeUnchecked;
using SqliteStatement::execute;
protected: protected:
void checkIsWritableStatement(); void checkIsWritableStatement();

View File

@@ -135,7 +135,7 @@ TEST_F(SqliteDatabaseBackend, TextEncodingCannotBeChangedAfterTouchingDatabase)
{ {
databaseBackend.setJournalMode(JournalMode::Memory); databaseBackend.setJournalMode(JournalMode::Memory);
SqliteWriteStatement::execute(Utf8StringLiteral("CREATE TABLE text(name, number)")); databaseBackend.execute(Utf8StringLiteral("CREATE TABLE text(name, number)"));
ASSERT_THROW(databaseBackend.setTextEncoding(Utf16), SqliteException); ASSERT_THROW(databaseBackend.setTextEncoding(Utf16), SqliteException);
} }

View File

@@ -25,7 +25,7 @@
#include "googletest.h" #include "googletest.h"
#include <sqlitedatabasebackend.h> #include <sqlitedatabase.h>
#include <sqlitereadstatement.h> #include <sqlitereadstatement.h>
#include <sqlitereadwritestatement.h> #include <sqlitereadwritestatement.h>
#include <sqlitewritestatement.h> #include <sqlitewritestatement.h>
@@ -41,7 +41,7 @@
namespace { namespace {
using Sqlite::SqliteException; using Sqlite::SqliteException;
using Sqlite::SqliteDatabaseBackend; using Sqlite::SqliteDatabase;
using Sqlite::SqliteReadStatement; using Sqlite::SqliteReadStatement;
using Sqlite::SqliteReadWriteStatement; using Sqlite::SqliteReadWriteStatement;
using Sqlite::SqliteWriteStatement; using Sqlite::SqliteWriteStatement;
@@ -52,32 +52,32 @@ protected:
void SetUp() override; void SetUp() override;
void TearDown() override; void TearDown() override;
SqliteDatabaseBackend databaseBackend; SqliteDatabase database;
}; };
TEST_F(SqliteStatement, PrepareFailure) TEST_F(SqliteStatement, PrepareFailure)
{ {
ASSERT_THROW(SqliteReadStatement(Utf8StringLiteral("blah blah blah")), SqliteException); ASSERT_THROW(SqliteReadStatement(Utf8StringLiteral("blah blah blah"), database), SqliteException);
ASSERT_THROW(SqliteWriteStatement(Utf8StringLiteral("blah blah blah")), SqliteException); ASSERT_THROW(SqliteWriteStatement(Utf8StringLiteral("blah blah blah"), database), SqliteException);
ASSERT_THROW(SqliteReadStatement(Utf8StringLiteral("INSERT INTO test(name, number) VALUES (?, ?)")), SqliteException); ASSERT_THROW(SqliteReadStatement(Utf8StringLiteral("INSERT INTO test(name, number) VALUES (?, ?)"), database), SqliteException);
ASSERT_THROW(SqliteWriteStatement(Utf8StringLiteral("SELECT name, number FROM test '")), SqliteException); ASSERT_THROW(SqliteWriteStatement(Utf8StringLiteral("SELECT name, number FROM test '"), database), SqliteException);
} }
TEST_F(SqliteStatement, CountRows) TEST_F(SqliteStatement, CountRows)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT * FROM test")); SqliteReadStatement statement(Utf8StringLiteral("SELECT * FROM test"), database);
int nextCount = 0; int nextCount = 0;
while (statement.next()) while (statement.next())
++nextCount; ++nextCount;
int sqlCount = SqliteReadStatement::toValue<int>(Utf8StringLiteral("SELECT count(*) FROM test")); int sqlCount = SqliteReadStatement::toValue<int>(Utf8StringLiteral("SELECT count(*) FROM test"), database);
ASSERT_THAT(nextCount, sqlCount); ASSERT_THAT(nextCount, sqlCount);
} }
TEST_F(SqliteStatement, Value) TEST_F(SqliteStatement, Value)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test ORDER BY name")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test ORDER BY name"), database);
statement.next(); statement.next();
@@ -108,7 +108,7 @@ TEST_F(SqliteStatement, Value)
TEST_F(SqliteStatement, ValueFailure) TEST_F(SqliteStatement, ValueFailure)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test"), database);
ASSERT_THROW(statement.value<int>(0), SqliteException); ASSERT_THROW(statement.value<int>(0), SqliteException);
statement.reset(); statement.reset();
@@ -125,42 +125,42 @@ TEST_F(SqliteStatement, ValueFailure)
TEST_F(SqliteStatement, ToIntergerValue) TEST_F(SqliteStatement, ToIntergerValue)
{ {
ASSERT_THAT(SqliteReadStatement::toValue<int>(Utf8StringLiteral("SELECT number FROM test WHERE name='foo'")), 23); ASSERT_THAT(SqliteReadStatement::toValue<int>(Utf8StringLiteral("SELECT number FROM test WHERE name='foo'"), database), 23);
} }
TEST_F(SqliteStatement, ToLongIntergerValue) TEST_F(SqliteStatement, ToLongIntergerValue)
{ {
ASSERT_THAT(SqliteReadStatement::toValue<qint64>(Utf8StringLiteral("SELECT number FROM test WHERE name='foo'")), 23LL); ASSERT_THAT(SqliteReadStatement::toValue<qint64>(Utf8StringLiteral("SELECT number FROM test WHERE name='foo'"), database), 23LL);
} }
TEST_F(SqliteStatement, ToDoubleValue) TEST_F(SqliteStatement, ToDoubleValue)
{ {
ASSERT_THAT(SqliteReadStatement::toValue<double>(Utf8StringLiteral("SELECT number FROM test WHERE name='foo'")), 23.3); ASSERT_THAT(SqliteReadStatement::toValue<double>(Utf8StringLiteral("SELECT number FROM test WHERE name='foo'"), database), 23.3);
} }
TEST_F(SqliteStatement, ToQStringValue) TEST_F(SqliteStatement, ToQStringValue)
{ {
ASSERT_THAT(SqliteReadStatement::toValue<QString>(Utf8StringLiteral("SELECT name FROM test WHERE name='foo'")), QStringLiteral("foo")); ASSERT_THAT(SqliteReadStatement::toValue<QString>(Utf8StringLiteral("SELECT name FROM test WHERE name='foo'"), database), QStringLiteral("foo"));
} }
TEST_F(SqliteStatement, ToUtf8StringValue) TEST_F(SqliteStatement, ToUtf8StringValue)
{ {
ASSERT_THAT(SqliteReadStatement::toValue<Utf8String>(Utf8StringLiteral("SELECT name FROM test WHERE name='foo'")), Utf8StringLiteral("foo")); ASSERT_THAT(SqliteReadStatement::toValue<Utf8String>(Utf8StringLiteral("SELECT name FROM test WHERE name='foo'"), database), Utf8StringLiteral("foo"));
} }
TEST_F(SqliteStatement, ToQByteArrayValueIsNull) TEST_F(SqliteStatement, ToQByteArrayValueIsNull)
{ {
ASSERT_TRUE(SqliteReadStatement::toValue<QByteArray>(Utf8StringLiteral("SELECT name FROM test WHERE name='foo'")).isNull()); ASSERT_TRUE(SqliteReadStatement::toValue<QByteArray>(Utf8StringLiteral("SELECT name FROM test WHERE name='foo'"), database).isNull());
} }
TEST_F(SqliteStatement, ToQVariantValue) TEST_F(SqliteStatement, ToQVariantValue)
{ {
ASSERT_THAT(SqliteReadStatement::toValue<QVariant>(Utf8StringLiteral("SELECT name FROM test WHERE name='foo'")), QVariant::fromValue(QStringLiteral("foo"))); ASSERT_THAT(SqliteReadStatement::toValue<QVariant>(Utf8StringLiteral("SELECT name FROM test WHERE name='foo'"), database), QVariant::fromValue(QStringLiteral("foo")));
} }
TEST_F(SqliteStatement, Utf8Values) TEST_F(SqliteStatement, Utf8Values)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test ORDER by name")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test ORDER by name"), database);
Utf8StringVector values = statement.values<Utf8StringVector>(); Utf8StringVector values = statement.values<Utf8StringVector>();
ASSERT_THAT(values.count(), 3); ASSERT_THAT(values.count(), 3);
@@ -170,7 +170,7 @@ TEST_F(SqliteStatement, Utf8Values)
} }
TEST_F(SqliteStatement, DoubleValues) TEST_F(SqliteStatement, DoubleValues)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test ORDER by name")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test ORDER by name"), database);
QVector<double> values = statement.values<QVector<double>>(1); QVector<double> values = statement.values<QVector<double>>(1);
@@ -182,7 +182,7 @@ TEST_F(SqliteStatement, DoubleValues)
TEST_F(SqliteStatement, QVariantValues) TEST_F(SqliteStatement, QVariantValues)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test ORDER by name")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test ORDER by name"), database);
QVector<QVariant> values = statement.values<QVector<QVariant>>(QVector<int>() << 0 << 1); QVector<QVariant> values = statement.values<QVector<QVariant>>(QVector<int>() << 0 << 1);
@@ -197,7 +197,7 @@ TEST_F(SqliteStatement, QVariantValues)
TEST_F(SqliteStatement, RowColumnValueMapCountForValidRow) TEST_F(SqliteStatement, RowColumnValueMapCountForValidRow)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE rowid=1")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE rowid=1"), database);
QMap<QString, QVariant> values = statement.rowColumnValueMap(); QMap<QString, QVariant> values = statement.rowColumnValueMap();
@@ -206,7 +206,7 @@ TEST_F(SqliteStatement, RowColumnValueMapCountForValidRow)
TEST_F(SqliteStatement, RowColumnValueMapCountForInvalidRow) TEST_F(SqliteStatement, RowColumnValueMapCountForInvalidRow)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE rowid=100")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE rowid=100"), database);
QMap<QString, QVariant> values = statement.rowColumnValueMap(); QMap<QString, QVariant> values = statement.rowColumnValueMap();
@@ -215,7 +215,7 @@ TEST_F(SqliteStatement, RowColumnValueMapCountForInvalidRow)
TEST_F(SqliteStatement, RowColumnValueMapValues) TEST_F(SqliteStatement, RowColumnValueMapValues)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE rowid=2")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE rowid=2"), database);
QMap<QString, QVariant> values = statement.rowColumnValueMap(); QMap<QString, QVariant> values = statement.rowColumnValueMap();
@@ -225,7 +225,7 @@ TEST_F(SqliteStatement, RowColumnValueMapValues)
TEST_F(SqliteStatement, TwoColumnValueMapCount) TEST_F(SqliteStatement, TwoColumnValueMapCount)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test"), database);
QMap<QString, QVariant> values = statement.twoColumnValueMap(); QMap<QString, QVariant> values = statement.twoColumnValueMap();
@@ -234,7 +234,7 @@ TEST_F(SqliteStatement, TwoColumnValueMapCount)
TEST_F(SqliteStatement, TwoColumnValueMapValues) TEST_F(SqliteStatement, TwoColumnValueMapValues)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test"), database);
QMap<QString, QVariant> values = statement.twoColumnValueMap(); QMap<QString, QVariant> values = statement.twoColumnValueMap();
@@ -243,7 +243,7 @@ TEST_F(SqliteStatement, TwoColumnValueMapValues)
TEST_F(SqliteStatement, ValuesFailure) TEST_F(SqliteStatement, ValuesFailure)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test"), database);
ASSERT_THROW(statement.values<QVector<QVariant>>(QVector<int>() << 1 << 2);, SqliteException); ASSERT_THROW(statement.values<QVector<QVariant>>(QVector<int>() << 1 << 2);, SqliteException);
ASSERT_THROW(statement.values<QVector<QVariant>>(QVector<int>() << -1 << 1);, SqliteException); ASSERT_THROW(statement.values<QVector<QVariant>>(QVector<int>() << -1 << 1);, SqliteException);
@@ -251,7 +251,7 @@ TEST_F(SqliteStatement, ValuesFailure)
TEST_F(SqliteStatement, ColumnNames) TEST_F(SqliteStatement, ColumnNames)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test"), database);
Utf8StringVector columnNames = statement.columnNames(); Utf8StringVector columnNames = statement.columnNames();
@@ -264,7 +264,7 @@ TEST_F(SqliteStatement, ColumnNames)
TEST_F(SqliteStatement, BindQString) TEST_F(SqliteStatement, BindQString)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE name=?")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE name=?"), database);
statement.bind(1, QStringLiteral("foo")); statement.bind(1, QStringLiteral("foo"));
@@ -276,7 +276,7 @@ TEST_F(SqliteStatement, BindQString)
TEST_F(SqliteStatement, BindInteger) TEST_F(SqliteStatement, BindInteger)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?"), database);
statement.bind(1, 40); statement.bind(1, 40);
statement.next(); statement.next();
@@ -286,7 +286,7 @@ TEST_F(SqliteStatement, BindInteger)
TEST_F(SqliteStatement, BindLongInteger) TEST_F(SqliteStatement, BindLongInteger)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?"), database);
statement.bind(1, qint64(40)); statement.bind(1, qint64(40));
statement.next(); statement.next();
@@ -296,7 +296,7 @@ TEST_F(SqliteStatement, BindLongInteger)
TEST_F(SqliteStatement, BindByteArray) TEST_F(SqliteStatement, BindByteArray)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?"), database);
statement.bind(1, QByteArray::fromHex("0500")); statement.bind(1, QByteArray::fromHex("0500"));
statement.next(); statement.next();
@@ -306,7 +306,7 @@ TEST_F(SqliteStatement, BindByteArray)
TEST_F(SqliteStatement, BindDouble) TEST_F(SqliteStatement, BindDouble)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?"), database);
statement.bind(1, 23.3); statement.bind(1, 23.3);
statement.next(); statement.next();
@@ -316,7 +316,7 @@ TEST_F(SqliteStatement, BindDouble)
TEST_F(SqliteStatement, BindIntergerQVariant) TEST_F(SqliteStatement, BindIntergerQVariant)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?"), database);
statement.bind(1, QVariant::fromValue(40)); statement.bind(1, QVariant::fromValue(40));
statement.next(); statement.next();
@@ -326,7 +326,7 @@ TEST_F(SqliteStatement, BindIntergerQVariant)
TEST_F(SqliteStatement, BindLongIntergerQVariant) TEST_F(SqliteStatement, BindLongIntergerQVariant)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?"), database);
statement.bind(1, QVariant::fromValue(qint64(40))); statement.bind(1, QVariant::fromValue(qint64(40)));
statement.next(); statement.next();
@@ -335,7 +335,7 @@ TEST_F(SqliteStatement, BindLongIntergerQVariant)
TEST_F(SqliteStatement, BindDoubleQVariant) TEST_F(SqliteStatement, BindDoubleQVariant)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?"), database);
statement.bind(1, QVariant::fromValue(23.3)); statement.bind(1, QVariant::fromValue(23.3));
statement.next(); statement.next();
@@ -345,7 +345,7 @@ TEST_F(SqliteStatement, BindDoubleQVariant)
TEST_F(SqliteStatement, BindByteArrayQVariant) TEST_F(SqliteStatement, BindByteArrayQVariant)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=?"), database);
statement.bind(1, QVariant::fromValue(QByteArray::fromHex("0500"))); statement.bind(1, QVariant::fromValue(QByteArray::fromHex("0500")));
statement.next(); statement.next();
@@ -355,7 +355,7 @@ TEST_F(SqliteStatement, BindByteArrayQVariant)
TEST_F(SqliteStatement, BindIntegerByParameter) TEST_F(SqliteStatement, BindIntegerByParameter)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number"), database);
statement.bind(Utf8StringLiteral("@number"), 40); statement.bind(Utf8StringLiteral("@number"), 40);
statement.next(); statement.next();
@@ -365,7 +365,7 @@ TEST_F(SqliteStatement, BindIntegerByParameter)
TEST_F(SqliteStatement, BindLongIntegerByParameter) TEST_F(SqliteStatement, BindLongIntegerByParameter)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number"), database);
statement.bind(Utf8StringLiteral("@number"), qint64(40)); statement.bind(Utf8StringLiteral("@number"), qint64(40));
statement.next(); statement.next();
@@ -375,7 +375,7 @@ TEST_F(SqliteStatement, BindLongIntegerByParameter)
TEST_F(SqliteStatement, BindByteArrayByParameter) TEST_F(SqliteStatement, BindByteArrayByParameter)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number"), database);
statement.bind(Utf8StringLiteral("@number"), QByteArray::fromHex("0500")); statement.bind(Utf8StringLiteral("@number"), QByteArray::fromHex("0500"));
statement.next(); statement.next();
@@ -385,7 +385,7 @@ TEST_F(SqliteStatement, BindByteArrayByParameter)
TEST_F(SqliteStatement, BindDoubleByIndex) TEST_F(SqliteStatement, BindDoubleByIndex)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number"), database);
statement.bind(statement.bindingIndexForName(Utf8StringLiteral("@number")), 23.3); statement.bind(statement.bindingIndexForName(Utf8StringLiteral("@number")), 23.3);
statement.next(); statement.next();
@@ -395,7 +395,7 @@ TEST_F(SqliteStatement, BindDoubleByIndex)
TEST_F(SqliteStatement, BindQVariantByIndex) TEST_F(SqliteStatement, BindQVariantByIndex)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number"), database);
statement.bind(statement.bindingIndexForName(Utf8StringLiteral("@number")), QVariant::fromValue((40))); statement.bind(statement.bindingIndexForName(Utf8StringLiteral("@number")), QVariant::fromValue((40)));
statement.next(); statement.next();
@@ -406,7 +406,7 @@ TEST_F(SqliteStatement, BindQVariantByIndex)
TEST_F(SqliteStatement, BindFailure) TEST_F(SqliteStatement, BindFailure)
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE number=@number"), database);
ASSERT_THROW(statement.bind(0, 40), SqliteException); ASSERT_THROW(statement.bind(0, 40), SqliteException);
ASSERT_THROW(statement.bind(2, 40), SqliteException); ASSERT_THROW(statement.bind(2, 40), SqliteException);
@@ -417,7 +417,7 @@ TEST_F(SqliteStatement, RequestBindingNamesFromStatement)
{ {
Utf8StringVector expectedValues({Utf8StringLiteral("name"), Utf8StringLiteral("number"), Utf8StringLiteral("id")}); Utf8StringVector expectedValues({Utf8StringLiteral("name"), Utf8StringLiteral("number"), Utf8StringLiteral("id")});
SqliteWriteStatement statement(Utf8StringLiteral("UPDATE test SET name=@name, number=@number WHERE rowid=@id")); SqliteWriteStatement statement(Utf8StringLiteral("UPDATE test SET name=@name, number=@number WHERE rowid=@id"), database);
ASSERT_THAT(statement.bindingColumnNames(), expectedValues); ASSERT_THAT(statement.bindingColumnNames(), expectedValues);
} }
@@ -425,7 +425,7 @@ TEST_F(SqliteStatement, RequestBindingNamesFromStatement)
TEST_F(SqliteStatement, WriteUpdateWidthUnamedParameter) TEST_F(SqliteStatement, WriteUpdateWidthUnamedParameter)
{ {
{ {
int startTotalCount = databaseBackend.totalChangesCount(); int startTotalCount = database.totalChangesCount();
RowDictionary firstValueMap; RowDictionary firstValueMap;
firstValueMap.insert(Utf8StringLiteral("name"), QStringLiteral("foo")); firstValueMap.insert(Utf8StringLiteral("name"), QStringLiteral("foo"));
firstValueMap.insert(Utf8StringLiteral("number"), 66.6); firstValueMap.insert(Utf8StringLiteral("number"), 66.6);
@@ -434,24 +434,24 @@ TEST_F(SqliteStatement, WriteUpdateWidthUnamedParameter)
secondValueMap.insert(Utf8StringLiteral("name"), QStringLiteral("bar")); secondValueMap.insert(Utf8StringLiteral("name"), QStringLiteral("bar"));
secondValueMap.insert(Utf8StringLiteral("number"), 77.7); secondValueMap.insert(Utf8StringLiteral("number"), 77.7);
SqliteWriteStatement statement(Utf8StringLiteral("UPDATE test SET number=? WHERE name=?")); SqliteWriteStatement statement(Utf8StringLiteral("UPDATE test SET number=? WHERE name=?"), database);
statement.setBindingColumnNames(Utf8StringVector() << Utf8StringLiteral("number") << Utf8StringLiteral("name")); statement.setBindingColumnNames(Utf8StringVector() << Utf8StringLiteral("number") << Utf8StringLiteral("name"));
statement.write(firstValueMap); statement.write(firstValueMap);
ASSERT_THAT(databaseBackend.totalChangesCount(), startTotalCount + 1); ASSERT_THAT(database.totalChangesCount(), startTotalCount + 1);
statement.write(firstValueMap); statement.write(firstValueMap);
ASSERT_THAT(databaseBackend.totalChangesCount(), startTotalCount + 2); ASSERT_THAT(database.totalChangesCount(), startTotalCount + 2);
statement.write(secondValueMap); statement.write(secondValueMap);
ASSERT_THAT(databaseBackend.totalChangesCount(), startTotalCount + 3); ASSERT_THAT(database.totalChangesCount(), startTotalCount + 3);
} }
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE name='foo'")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE name='foo'"), database);
statement.next(); statement.next();
@@ -462,18 +462,18 @@ TEST_F(SqliteStatement, WriteUpdateWidthUnamedParameter)
TEST_F(SqliteStatement, WriteUpdateWidthNamedParameter) TEST_F(SqliteStatement, WriteUpdateWidthNamedParameter)
{ {
{ {
int startTotalCount = databaseBackend.totalChangesCount(); int startTotalCount = database.totalChangesCount();
RowDictionary firstValueMap; RowDictionary firstValueMap;
firstValueMap.insert(Utf8StringLiteral("name"), QStringLiteral("foo")); firstValueMap.insert(Utf8StringLiteral("name"), QStringLiteral("foo"));
firstValueMap.insert(Utf8StringLiteral("number"), 99.9); firstValueMap.insert(Utf8StringLiteral("number"), 99.9);
SqliteWriteStatement statement(Utf8StringLiteral("UPDATE test SET number=@number WHERE name=@name")); SqliteWriteStatement statement(Utf8StringLiteral("UPDATE test SET number=@number WHERE name=@name"), database);
statement.write(firstValueMap); statement.write(firstValueMap);
ASSERT_THAT(databaseBackend.totalChangesCount(), startTotalCount + 1); ASSERT_THAT(database.totalChangesCount(), startTotalCount + 1);
} }
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE name='foo'")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE name='foo'"), database);
statement.next(); statement.next();
ASSERT_THAT(statement.value<double>(1), 99.9); ASSERT_THAT(statement.value<double>(1), 99.9);
} }
@@ -482,17 +482,17 @@ TEST_F(SqliteStatement, WriteUpdateWidthNamedParameter)
TEST_F(SqliteStatement, WriteUpdateWidthNamedParameterAndBindNotAllParameter) TEST_F(SqliteStatement, WriteUpdateWidthNamedParameterAndBindNotAllParameter)
{ {
{ {
int startTotalCount = databaseBackend.totalChangesCount(); int startTotalCount = database.totalChangesCount();
RowDictionary firstValueMap; RowDictionary firstValueMap;
firstValueMap.insert(Utf8StringLiteral("name"), QStringLiteral("foo")); firstValueMap.insert(Utf8StringLiteral("name"), QStringLiteral("foo"));
SqliteWriteStatement statement(Utf8StringLiteral("UPDATE test SET number=@number WHERE name=@name")); SqliteWriteStatement statement(Utf8StringLiteral("UPDATE test SET number=@number WHERE name=@name"), database);
statement.writeUnchecked(firstValueMap); statement.writeUnchecked(firstValueMap);
ASSERT_THAT(databaseBackend.totalChangesCount(), startTotalCount + 1); ASSERT_THAT(database.totalChangesCount(), startTotalCount + 1);
} }
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE name='foo'")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE name='foo'"), database);
statement.next(); statement.next();
ASSERT_THAT(statement.value<double>(1), 0.0); ASSERT_THAT(statement.value<double>(1), 0.0);
} }
@@ -501,22 +501,22 @@ TEST_F(SqliteStatement, WriteUpdateWidthNamedParameterAndBindNotAllParameter)
TEST_F(SqliteStatement, WriteInsert) TEST_F(SqliteStatement, WriteInsert)
{ {
{ {
int startTotalCount = databaseBackend.totalChangesCount(); int startTotalCount = database.totalChangesCount();
RowDictionary valueMap; RowDictionary valueMap;
valueMap.insert(Utf8StringLiteral("name"), QStringLiteral("jane")); valueMap.insert(Utf8StringLiteral("name"), QStringLiteral("jane"));
valueMap.insert(Utf8StringLiteral("number"), 232.3); valueMap.insert(Utf8StringLiteral("number"), 232.3);
SqliteWriteStatement statement(Utf8StringLiteral("INSERT OR IGNORE INTO test(name, number) VALUES (?, ?)")); SqliteWriteStatement statement(Utf8StringLiteral("INSERT OR IGNORE INTO test(name, number) VALUES (?, ?)"), database);
statement.setBindingColumnNames(Utf8StringVector() << Utf8StringLiteral("name") << Utf8StringLiteral("number")); statement.setBindingColumnNames(Utf8StringVector() << Utf8StringLiteral("name") << Utf8StringLiteral("number"));
statement.write(valueMap); statement.write(valueMap);
ASSERT_THAT(databaseBackend.totalChangesCount(), startTotalCount + 1); ASSERT_THAT(database.totalChangesCount(), startTotalCount + 1);
statement.write(valueMap); statement.write(valueMap);
ASSERT_THAT(databaseBackend.totalChangesCount(), startTotalCount + 1); ASSERT_THAT(database.totalChangesCount(), startTotalCount + 1);
} }
{ {
SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE name='jane'")); SqliteReadStatement statement(Utf8StringLiteral("SELECT name, number FROM test WHERE name='jane'"), database);
statement.next(); statement.next();
ASSERT_THAT(statement.value<double>(1), 232.3); ASSERT_THAT(statement.value<double>(1), 232.3);
} }
@@ -529,7 +529,7 @@ TEST_F(SqliteStatement, WriteFailure)
valueMap.insert(Utf8StringLiteral("name"), QStringLiteral("foo")); valueMap.insert(Utf8StringLiteral("name"), QStringLiteral("foo"));
valueMap.insert(Utf8StringLiteral("number"), 323.3); valueMap.insert(Utf8StringLiteral("number"), 323.3);
SqliteWriteStatement statement(Utf8StringLiteral("INSERT INTO test(name, number) VALUES (?, ?)")); SqliteWriteStatement statement(Utf8StringLiteral("INSERT INTO test(name, number) VALUES (?, ?)"), database);
statement.setBindingColumnNames(Utf8StringVector() << Utf8StringLiteral("name") << Utf8StringLiteral("number")); statement.setBindingColumnNames(Utf8StringVector() << Utf8StringLiteral("name") << Utf8StringLiteral("number"));
ASSERT_THROW(statement.write(valueMap), SqliteException); ASSERT_THROW(statement.write(valueMap), SqliteException);
} }
@@ -538,7 +538,7 @@ TEST_F(SqliteStatement, WriteFailure)
RowDictionary valueMap; RowDictionary valueMap;
valueMap.insert(Utf8StringLiteral("name"), QStringLiteral("bar")); valueMap.insert(Utf8StringLiteral("name"), QStringLiteral("bar"));
SqliteWriteStatement statement(Utf8StringLiteral("INSERT OR IGNORE INTO test(name, number) VALUES (?, ?)")); SqliteWriteStatement statement(Utf8StringLiteral("INSERT OR IGNORE INTO test(name, number) VALUES (?, ?)"), database);
statement.setBindingColumnNames(Utf8StringVector() << Utf8StringLiteral("name") << Utf8StringLiteral("number")); statement.setBindingColumnNames(Utf8StringVector() << Utf8StringLiteral("name") << Utf8StringLiteral("number"));
ASSERT_THROW(statement.write(valueMap), SqliteException); ASSERT_THROW(statement.write(valueMap), SqliteException);
} }
@@ -546,25 +546,26 @@ TEST_F(SqliteStatement, WriteFailure)
TEST_F(SqliteStatement, ClosedDatabase) TEST_F(SqliteStatement, ClosedDatabase)
{ {
databaseBackend.close(); database.close();
ASSERT_THROW(SqliteWriteStatement(Utf8StringLiteral("INSERT INTO test(name, number) VALUES (?, ?)")), SqliteException); ASSERT_THROW(SqliteWriteStatement(Utf8StringLiteral("INSERT INTO test(name, number) VALUES (?, ?)"), database), SqliteException);
ASSERT_THROW(SqliteReadStatement(Utf8StringLiteral("SELECT * FROM test")), SqliteException); ASSERT_THROW(SqliteReadStatement(Utf8StringLiteral("SELECT * FROM test"), database), SqliteException);
ASSERT_THROW(SqliteReadWriteStatement(Utf8StringLiteral("INSERT INTO test(name, number) VALUES (?, ?)")), SqliteException); ASSERT_THROW(SqliteReadWriteStatement(Utf8StringLiteral("INSERT INTO test(name, number) VALUES (?, ?)"), database), SqliteException);
databaseBackend.open(QDir::tempPath() + QStringLiteral("/SqliteStatementTest.db")); database.open(QDir::tempPath() + QStringLiteral("/SqliteStatementTest.db"));
} }
void SqliteStatement::SetUp() void SqliteStatement::SetUp()
{ {
databaseBackend.open(QStringLiteral(":memory:")); database.setJournalMode(JournalMode::Memory);
SqliteWriteStatement::execute(Utf8StringLiteral("CREATE TABLE test(name TEXT UNIQUE, number NUMERIC)")); database.open(QStringLiteral(":memory:"));
SqliteWriteStatement::execute(Utf8StringLiteral("INSERT INTO test VALUES ('bar', x'0500')")); SqliteWriteStatement(Utf8StringLiteral("CREATE TABLE test(name TEXT UNIQUE, number NUMERIC)"), database).step();
SqliteWriteStatement::execute(Utf8StringLiteral("INSERT INTO test VALUES ('foo', 23.3)")); SqliteWriteStatement(Utf8StringLiteral("INSERT INTO test VALUES ('bar', x'0500')"), database).step();
SqliteWriteStatement::execute(Utf8StringLiteral("INSERT INTO test VALUES ('poo', 40)")); SqliteWriteStatement(Utf8StringLiteral("INSERT INTO test VALUES ('foo', 23.3)"), database).step();
SqliteWriteStatement(Utf8StringLiteral("INSERT INTO test VALUES ('poo', 40)"), database).step();
} }
void SqliteStatement::TearDown() void SqliteStatement::TearDown()
{ {
databaseBackend.close(); database.close();
} }
} }