aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libs/sqlite/sqlitebasestatement.cpp61
-rw-r--r--src/libs/sqlite/sqlitebasestatement.h19
-rw-r--r--src/libs/sqlite/sqliteexception.h7
-rw-r--r--tests/unit/unittest/mocksqlitestatement.h4
-rw-r--r--tests/unit/unittest/sqlitestatement-test.cpp78
5 files changed, 73 insertions, 96 deletions
diff --git a/src/libs/sqlite/sqlitebasestatement.cpp b/src/libs/sqlite/sqlitebasestatement.cpp
index 890c663997..f8dadeb425 100644
--- a/src/libs/sqlite/sqlitebasestatement.cpp
+++ b/src/libs/sqlite/sqlitebasestatement.cpp
@@ -41,11 +41,10 @@
namespace Sqlite {
BaseStatement::BaseStatement(Utils::SmallStringView sqlStatement, Database &database)
- : m_compiledStatement(nullptr, deleteCompiledStatement),
- m_database(database),
- m_bindingParameterCount(0),
- m_columnCount(0),
- m_isReadyToFetchValues(false)
+ : m_compiledStatement(nullptr, deleteCompiledStatement)
+ , m_database(database)
+ , m_bindingParameterCount(0)
+ , m_columnCount(0)
{
prepare(sqlStatement);
setBindingParameterCount();
@@ -107,11 +106,8 @@ void BaseStatement::reset() const
{
int resultCode = sqlite3_reset(m_compiledStatement.get());
- if (resultCode != SQLITE_OK) {
+ if (resultCode != SQLITE_OK)
checkForResetError(resultCode);
-
- m_isReadyToFetchValues = false;
- }
}
bool BaseStatement::next() const
@@ -127,8 +123,6 @@ bool BaseStatement::next() const
} while (resultCode == SQLITE_LOCKED);
- setIfIsReadyToFetchValues(resultCode);
-
if (resultCode == SQLITE_ROW)
return true;
else if (resultCode == SQLITE_DONE)
@@ -299,33 +293,10 @@ void BaseStatement::checkForBindingError(int resultCode) const
throwUnknowError("SqliteStatement::bind: unknown error has happened");
}
-void BaseStatement::setIfIsReadyToFetchValues(int resultCode) const
+void BaseStatement::checkColumnCount(int columnCount) const
{
- if (resultCode == SQLITE_ROW)
- m_isReadyToFetchValues = true;
- else
- m_isReadyToFetchValues = false;
-
-}
-
-void BaseStatement::checkIfIsReadyToFetchValues() const
-{
- if (!m_isReadyToFetchValues)
- throwNoValuesToFetch("SqliteStatement::value: there are no values to fetch!");
-}
-
-void BaseStatement::checkColumnsAreValid(const std::vector<int> &columns) const
-{
- for (int column : columns) {
- if (column < 0 || column >= m_columnCount)
- throwInvalidColumnFetched("SqliteStatement::values: column index out of bound!");
- }
-}
-
-void BaseStatement::checkColumnIsValid(int column) const
-{
- if (column < 0 || column >= m_columnCount)
- throwInvalidColumnFetched("SqliteStatement::values: column index out of bound!");
+ if (columnCount != m_columnCount)
+ throw ColumnCountDoesNotMatch("SqliteStatement::values: column count does not match!");
}
void BaseStatement::checkBindingName(int index) const
@@ -387,11 +358,6 @@ void BaseStatement::throwNoValuesToFetch(const char *whatHasHappened) const
throw NoValuesToFetch(whatHasHappened);
}
-void BaseStatement::throwInvalidColumnFetched(const char *whatHasHappened) const
-{
- throw InvalidColumnFetched(whatHasHappened);
-}
-
void BaseStatement::throwBindingIndexIsOutOfRange(const char *whatHasHappened) const
{
throw BindingIndexIsOutOfRange(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
@@ -472,8 +438,6 @@ StringType convertToTextForColumn(sqlite3_stmt *sqlStatment, int column)
int BaseStatement::fetchIntValue(int column) const
{
- checkIfIsReadyToFetchValues();
- checkColumnIsValid(column);
return sqlite3_column_int(m_compiledStatement.get(), column);
}
@@ -496,8 +460,6 @@ long BaseStatement::fetchValue<long>(int column) const
long long BaseStatement::fetchLongLongValue(int column) const
{
- checkIfIsReadyToFetchValues();
- checkColumnIsValid(column);
return sqlite3_column_int64(m_compiledStatement.get(), column);
}
@@ -509,16 +471,11 @@ long long BaseStatement::fetchValue<long long>(int column) const
double BaseStatement::fetchDoubleValue(int column) const
{
- checkIfIsReadyToFetchValues();
- checkColumnIsValid(column);
return sqlite3_column_double(m_compiledStatement.get(), column);
}
Utils::span<const byte> BaseStatement::fetchBlobValue(int column) const
{
- checkIfIsReadyToFetchValues();
- checkColumnIsValid(column);
-
return convertToBlobForColumn(m_compiledStatement.get(), column);
}
@@ -531,8 +488,6 @@ double BaseStatement::fetchValue<double>(int column) const
template<typename StringType>
StringType BaseStatement::fetchValue(int column) const
{
- checkIfIsReadyToFetchValues();
- checkColumnIsValid(column);
return convertToTextForColumn<StringType>(m_compiledStatement.get(), column);
}
diff --git a/src/libs/sqlite/sqlitebasestatement.h b/src/libs/sqlite/sqlitebasestatement.h
index 48076c37da..2480a4674a 100644
--- a/src/libs/sqlite/sqlitebasestatement.h
+++ b/src/libs/sqlite/sqlitebasestatement.h
@@ -101,9 +101,7 @@ public:
[[noreturn]] void checkForPrepareError(int resultCode) const;
[[noreturn]] void checkForBindingError(int resultCode) const;
void setIfIsReadyToFetchValues(int resultCode) const;
- void checkIfIsReadyToFetchValues() const;
- void checkColumnsAreValid(const std::vector<int> &columns) const;
- void checkColumnIsValid(int column) const;
+ void checkColumnCount(int columnCount) const;
void checkBindingName(int index) const;
void setBindingParameterCount();
void setColumnCount();
@@ -128,11 +126,10 @@ protected:
~BaseStatement() = default;
private:
- std::unique_ptr<sqlite3_stmt, void (*)(sqlite3_stmt*)> m_compiledStatement;
+ std::unique_ptr<sqlite3_stmt, void (*)(sqlite3_stmt *)> m_compiledStatement;
Database &m_database;
int m_bindingParameterCount;
int m_columnCount;
- mutable bool m_isReadyToFetchValues;
};
template <> SQLITE_EXPORT int BaseStatement::fetchValue<int>(int column) const;
@@ -180,6 +177,8 @@ public:
int ResultTypeCount = 1>
std::vector<ResultType> values(std::size_t reserveSize)
{
+ BaseStatement::checkColumnCount(ResultTypeCount);
+
Resetter resetter{*this};
std::vector<ResultType> resultValues;
resultValues.reserve(std::max(reserveSize, m_maximumResultCount));
@@ -199,6 +198,8 @@ public:
typename... QueryTypes>
std::vector<ResultType> values(std::size_t reserveSize, const QueryTypes&... queryValues)
{
+ BaseStatement::checkColumnCount(ResultTypeCount);
+
Resetter resetter{*this};
std::vector<ResultType> resultValues;
resultValues.reserve(std::max(reserveSize, m_maximumResultCount));
@@ -221,6 +222,8 @@ public:
std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<QueryElementType> &queryValues)
{
+ BaseStatement::checkColumnCount(ResultTypeCount);
+
std::vector<ResultType> resultValues;
resultValues.reserve(std::max(reserveSize, m_maximumResultCount));
@@ -245,6 +248,8 @@ public:
std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<std::tuple<QueryElementTypes...>> &queryTuples)
{
+ BaseStatement::checkColumnCount(ResultTypeCount);
+
using Container = std::vector<ResultType>;
Container resultValues;
resultValues.reserve(std::max(reserveSize, m_maximumResultCount));
@@ -269,6 +274,8 @@ public:
typename... QueryTypes>
Utils::optional<ResultType> value(const QueryTypes&... queryValues)
{
+ BaseStatement::checkColumnCount(ResultTypeCount);
+
Resetter resetter{*this};
Utils::optional<ResultType> resultValue;
@@ -287,6 +294,8 @@ public:
{
StatementImplementation statement(sqlStatement, database);
+ statement.checkColumnCount(1);
+
statement.next();
return statement.template fetchValue<Type>(0);
diff --git a/src/libs/sqlite/sqliteexception.h b/src/libs/sqlite/sqliteexception.h
index dcbbfcd1be..7f8f60ca42 100644
--- a/src/libs/sqlite/sqliteexception.h
+++ b/src/libs/sqlite/sqliteexception.h
@@ -119,13 +119,12 @@ public:
}
};
-class InvalidColumnFetched : public Exception
+class ColumnCountDoesNotMatch : public Exception
{
public:
- InvalidColumnFetched(const char *whatErrorHasHappen)
+ ColumnCountDoesNotMatch(const char *whatErrorHasHappen)
: Exception(whatErrorHasHappen)
- {
- }
+ {}
};
class BindingIndexIsOutOfRange : public Exception
diff --git a/tests/unit/unittest/mocksqlitestatement.h b/tests/unit/unittest/mocksqlitestatement.h
index 351c6708a5..7be7f3f05e 100644
--- a/tests/unit/unittest/mocksqlitestatement.h
+++ b/tests/unit/unittest/mocksqlitestatement.h
@@ -53,7 +53,9 @@ public:
MOCK_METHOD2(bind, void (int, Utils::SmallStringView));
MOCK_METHOD2(bind, void (int, long));
- MOCK_METHOD1(prepare, void (Utils::SmallStringView sqlStatement));
+ MOCK_METHOD1(prepare, void(Utils::SmallStringView sqlStatement));
+
+ MOCK_METHOD1(checkColumnCount, void(int));
};
template<>
diff --git a/tests/unit/unittest/sqlitestatement-test.cpp b/tests/unit/unittest/sqlitestatement-test.cpp
index 2b8942dbf1..4b59d52af2 100644
--- a/tests/unit/unittest/sqlitestatement-test.cpp
+++ b/tests/unit/unittest/sqlitestatement-test.cpp
@@ -178,37 +178,6 @@ TEST_F(SqliteStatement, Value)
ASSERT_THAT(statement.fetchValueView(2), Eq(2));
}
-TEST_F(SqliteStatement, ThrowNoValuesToFetchForNotSteppedStatement)
-{
- SqliteTestStatement statement("SELECT name, number FROM test", database);
-
- ASSERT_THROW(statement.fetchValue<int>(0), Sqlite::NoValuesToFetch);
-}
-
-TEST_F(SqliteStatement, ThrowNoValuesToFetchForDoneStatement)
-{
- SqliteTestStatement statement("SELECT name, number FROM test", database);
- while (statement.next()) {}
-
- ASSERT_THROW(statement.fetchValue<int>(0), Sqlite::NoValuesToFetch);
-}
-
-TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNegativeColumn)
-{
- SqliteTestStatement statement("SELECT name, number FROM test", database);
- statement.next();
-
- ASSERT_THROW(statement.fetchValue<int>(-1), Sqlite::InvalidColumnFetched);
-}
-
-TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNotExistingColumn)
-{
- SqliteTestStatement statement("SELECT name, number FROM test", database);
- statement.next();
-
- ASSERT_THROW(statement.fetchValue<int>(2), Sqlite::InvalidColumnFetched);
-}
-
TEST_F(SqliteStatement, ToIntegerValue)
{
auto value = ReadStatement::toValue<int>("SELECT number FROM test WHERE name='foo'", database);
@@ -567,7 +536,7 @@ TEST_F(SqliteStatement, GetValuesForMultipleOutputValuesAndContainerQueryValues)
TEST_F(SqliteStatement, GetValuesForSingleOutputValuesAndContainerQueryValues)
{
std::vector<double> queryValues = {40, 23.3};
- ReadStatement statement("SELECT name, number FROM test WHERE number=?", database);
+ ReadStatement statement("SELECT name FROM test WHERE number=?", database);
std::vector<Utils::SmallString> values = statement.values<Utils::SmallString>(3, queryValues);
@@ -591,7 +560,7 @@ TEST_F(SqliteStatement, GetValuesForSingleOutputValuesAndContainerQueryTupleValu
{
using Tuple = std::tuple<Utils::SmallString, Utils::SmallString>;
std::vector<Tuple> queryValues = {{"poo", "40"}, {"bar", "blah"}};
- ReadStatement statement("SELECT name, number FROM test WHERE name= ? AND number=?", database);
+ ReadStatement statement("SELECT name FROM test WHERE name= ? AND number=?", database);
std::vector<Utils::SmallString> values = statement.values<Utils::SmallString>(3, queryValues);
@@ -855,4 +824,47 @@ TEST_F(SqliteStatement, ResetIfExecuteThrowsException)
ASSERT_ANY_THROW(mockStatement.execute());
}
+
+TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForToManyArgumentsForValue)
+{
+ SqliteTestStatement statement("SELECT name, number FROM test", database);
+
+ ASSERT_THROW(statement.value<int>(), Sqlite::ColumnCountDoesNotMatch);
+}
+
+TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForToManyArgumentsForValues)
+{
+ SqliteTestStatement statement("SELECT name, number FROM test", database);
+
+ ASSERT_THROW(statement.values<int>(1), Sqlite::ColumnCountDoesNotMatch);
+}
+
+TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForToManyArgumentsForValuesWithArguments)
+{
+ SqliteTestStatement statement("SELECT name, number FROM test WHERE name=?", database);
+
+ ASSERT_THROW(statement.values<int>(1, 2), Sqlite::ColumnCountDoesNotMatch);
+}
+
+TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForToManyArgumentsForValuesWithVectorArguments)
+{
+ SqliteTestStatement statement("SELECT name, number FROM test", database);
+
+ ASSERT_THROW(statement.values<int>(1, std::vector<int>{}), Sqlite::ColumnCountDoesNotMatch);
+}
+
+TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForToManyArgumentsForValuesWithTupleArguments)
+{
+ SqliteTestStatement statement("SELECT name, number FROM test", database);
+
+ ASSERT_THROW(statement.values<int>(1, std::vector<std::tuple<int>>{}),
+ Sqlite::ColumnCountDoesNotMatch);
+}
+
+TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForToManyArgumentsForToValues)
+{
+ ASSERT_THROW(SqliteTestStatement::toValue<int>("SELECT name, number FROM test", database),
+ Sqlite::ColumnCountDoesNotMatch);
+}
+
} // namespace