forked from qt-creator/qt-creator
Clang: Fix reset for write and execute in the sqlite statement
We were not reset a statement if we got an exception. There are now test for it. Change-Id: Ife7b4437fece9369767605ba7387bd0564c1bb8d Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
@@ -54,8 +54,7 @@ BaseStatement::BaseStatement(Utils::SmallStringView sqlStatement, Database &data
|
|||||||
|
|
||||||
void BaseStatement::deleteCompiledStatement(sqlite3_stmt *compiledStatement)
|
void BaseStatement::deleteCompiledStatement(sqlite3_stmt *compiledStatement)
|
||||||
{
|
{
|
||||||
if (compiledStatement)
|
sqlite3_finalize(compiledStatement);
|
||||||
sqlite3_finalize(compiledStatement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class UnlockNotification
|
class UnlockNotification
|
||||||
@@ -145,12 +144,6 @@ void BaseStatement::step() const
|
|||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::execute() const
|
|
||||||
{
|
|
||||||
next();
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
int BaseStatement::columnCount() const
|
int BaseStatement::columnCount() const
|
||||||
{
|
{
|
||||||
return m_columnCount;
|
return m_columnCount;
|
||||||
|
@@ -60,7 +60,6 @@ public:
|
|||||||
|
|
||||||
bool next() const;
|
bool next() const;
|
||||||
void step() const;
|
void step() const;
|
||||||
void execute() const;
|
|
||||||
void reset() const;
|
void reset() const;
|
||||||
|
|
||||||
int fetchIntValue(int column) const;
|
int fetchIntValue(int column) const;
|
||||||
@@ -159,6 +158,13 @@ class StatementImplementation : public BaseStatement
|
|||||||
public:
|
public:
|
||||||
using BaseStatement::BaseStatement;
|
using BaseStatement::BaseStatement;
|
||||||
|
|
||||||
|
void execute()
|
||||||
|
{
|
||||||
|
Resetter resetter{*this};
|
||||||
|
BaseStatement::next();
|
||||||
|
resetter.reset();
|
||||||
|
}
|
||||||
|
|
||||||
void bindValues()
|
void bindValues()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -172,8 +178,10 @@ public:
|
|||||||
template<typename... ValueType>
|
template<typename... ValueType>
|
||||||
void write(const ValueType&... values)
|
void write(const ValueType&... values)
|
||||||
{
|
{
|
||||||
|
Resetter resetter{*this};
|
||||||
bindValuesByIndex(1, values...);
|
bindValuesByIndex(1, values...);
|
||||||
BaseStatement::execute();
|
BaseStatement::next();
|
||||||
|
resetter.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... ValueType>
|
template<typename... ValueType>
|
||||||
@@ -185,8 +193,10 @@ public:
|
|||||||
template<typename... ValueType>
|
template<typename... ValueType>
|
||||||
void writeNamed(const ValueType&... values)
|
void writeNamed(const ValueType&... values)
|
||||||
{
|
{
|
||||||
|
Resetter resetter{*this};
|
||||||
bindValuesByName(values...);
|
bindValuesByName(values...);
|
||||||
BaseStatement::execute();
|
BaseStatement::next();
|
||||||
|
resetter.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ResultType,
|
template <typename ResultType,
|
||||||
|
@@ -178,7 +178,7 @@ void DatabaseBackend::setLastInsertedRowId(int64_t rowId)
|
|||||||
void DatabaseBackend::execute(Utils::SmallStringView sqlStatement)
|
void DatabaseBackend::execute(Utils::SmallStringView sqlStatement)
|
||||||
{
|
{
|
||||||
ReadWriteStatement statement(sqlStatement, m_database);
|
ReadWriteStatement statement(sqlStatement, m_database);
|
||||||
statement.step();
|
statement.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::close()
|
void DatabaseBackend::close()
|
||||||
|
@@ -64,6 +64,7 @@ public:
|
|||||||
{
|
{
|
||||||
m_interface.commit();
|
m_interface.commit();
|
||||||
m_isAlreadyCommited = true;
|
m_isAlreadyCommited = true;
|
||||||
|
m_locker.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -76,7 +77,7 @@ protected:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
TransactionInterface &m_interface;
|
TransactionInterface &m_interface;
|
||||||
std::lock_guard<TransactionInterface> m_locker{m_interface};
|
std::unique_lock<TransactionInterface> m_locker{m_interface};
|
||||||
bool m_isAlreadyCommited = false;
|
bool m_isAlreadyCommited = false;
|
||||||
bool m_rollback = false;
|
bool m_rollback = false;
|
||||||
};
|
};
|
||||||
|
@@ -35,7 +35,6 @@ class BaseMockSqliteStatement
|
|||||||
public:
|
public:
|
||||||
MOCK_METHOD0(next, bool ());
|
MOCK_METHOD0(next, bool ());
|
||||||
MOCK_METHOD0(step, void ());
|
MOCK_METHOD0(step, void ());
|
||||||
MOCK_METHOD0(execute, void ());
|
|
||||||
MOCK_METHOD0(reset, void ());
|
MOCK_METHOD0(reset, void ());
|
||||||
|
|
||||||
MOCK_CONST_METHOD1(fetchIntValue, int (int));
|
MOCK_CONST_METHOD1(fetchIntValue, int (int));
|
||||||
@@ -53,6 +52,7 @@ public:
|
|||||||
MOCK_METHOD2(bind, void (int, double));
|
MOCK_METHOD2(bind, void (int, double));
|
||||||
MOCK_METHOD2(bind, void (int, Utils::SmallStringView));
|
MOCK_METHOD2(bind, void (int, Utils::SmallStringView));
|
||||||
MOCK_METHOD2(bind, void (int, long));
|
MOCK_METHOD2(bind, void (int, long));
|
||||||
|
MOCK_CONST_METHOD1(bindingIndexForName, int (Utils::SmallStringView name));
|
||||||
|
|
||||||
MOCK_METHOD1(prepare, void (Utils::SmallStringView sqlStatement));
|
MOCK_METHOD1(prepare, void (Utils::SmallStringView sqlStatement));
|
||||||
};
|
};
|
||||||
|
@@ -639,6 +639,40 @@ TEST_F(SqliteStatement, ThrowExceptionOnlyInReset)
|
|||||||
Sqlite::StatementHasError);
|
Sqlite::StatementHasError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SqliteStatement, ResetIfWriteIsThrowingException)
|
||||||
|
{
|
||||||
|
MockSqliteStatement mockStatement;
|
||||||
|
|
||||||
|
EXPECT_CALL(mockStatement, bind(1, TypedEq<Utils::SmallStringView>("bar")))
|
||||||
|
.WillOnce(Throw(Sqlite::StatementIsBusy("")));
|
||||||
|
EXPECT_CALL(mockStatement, reset());
|
||||||
|
|
||||||
|
ASSERT_ANY_THROW(mockStatement.write("bar"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SqliteStatement, ResetIfWriteNamedIsThrowingException)
|
||||||
|
{
|
||||||
|
MockSqliteStatement mockStatement;
|
||||||
|
|
||||||
|
EXPECT_CALL(mockStatement, bindingIndexForName(TypedEq<Utils::SmallStringView>("@foo")))
|
||||||
|
.WillOnce(Return(1));
|
||||||
|
EXPECT_CALL(mockStatement, bind(1, TypedEq<Utils::SmallStringView>("bar")))
|
||||||
|
.WillOnce(Throw(Sqlite::StatementIsBusy("")));
|
||||||
|
EXPECT_CALL(mockStatement, reset());
|
||||||
|
|
||||||
|
ASSERT_ANY_THROW(mockStatement.writeNamed("@foo", "bar"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SqliteStatement, ResetIfExecuteThrowsException)
|
||||||
|
{
|
||||||
|
MockSqliteStatement mockStatement;
|
||||||
|
|
||||||
|
EXPECT_CALL(mockStatement, next()).WillOnce(Throw(Sqlite::StatementIsBusy("")));
|
||||||
|
EXPECT_CALL(mockStatement, reset());
|
||||||
|
|
||||||
|
ASSERT_ANY_THROW(mockStatement.execute());
|
||||||
|
}
|
||||||
|
|
||||||
void SqliteStatement::SetUp()
|
void SqliteStatement::SetUp()
|
||||||
{
|
{
|
||||||
database.execute("CREATE TABLE test(name TEXT UNIQUE, number NUMERIC, value NUMERIC)");
|
database.execute("CREATE TABLE test(name TEXT UNIQUE, number NUMERIC, value NUMERIC)");
|
||||||
|
Reference in New Issue
Block a user