From 0c43747065559f030fac204b4c93f2448369793c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Rombauts?= Date: Thu, 30 Jun 2016 08:33:19 +0200 Subject: [PATCH] Add unit tests for statement bindings + removed an assert() for ~Transaction() --- src/Database.cpp | 3 +- src/Statement.cpp | 6 +-- src/Transaction.cpp | 6 +-- tests/Statement_test.cpp | 95 +++++++++++++++++++++++++++++++++++++- tests/Transaction_test.cpp | 2 +- 5 files changed, 99 insertions(+), 13 deletions(-) diff --git a/src/Database.cpp b/src/Database.cpp index f19dee9..c0c7d34 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -130,8 +130,7 @@ bool Database::tableExists(const char* apTableName) Statement query(*this, "SELECT count(*) FROM sqlite_master WHERE type='table' AND name=?"); query.bind(1, apTableName); (void)query.executeStep(); // Cannot return false, as the above query always return a result - const int Nb = query.getColumn(0); - return (1 == Nb); + return (1 == query.getColumn(0).getInt()); } // Attach a custom function to your sqlite database. Assumes UTF8 text representation. diff --git a/src/Statement.cpp b/src/Statement.cpp index eec9a92..64488e4 100644 --- a/src/Statement.cpp +++ b/src/Statement.cpp @@ -49,7 +49,7 @@ Statement::~Statement() noexcept // nothrow // the finalization will be done by the destructor of the last shared pointer } -// Reset the statement to make it ready for a new execution +// Reset the statement to make it ready for a new execution (see also #clearBindings() bellow) void Statement::reset() { mbOk = false; @@ -58,11 +58,9 @@ void Statement::reset() check(ret); } -// Clears away all the bindings of a prepared statement. +// Clears away all the bindings of a prepared statement (can be associated with #reset() above). void Statement::clearBindings() { - mbOk = false; - mbDone = false; const int ret = sqlite3_clear_bindings(mStmtPtr); check(ret); } diff --git a/src/Transaction.cpp b/src/Transaction.cpp index 1b60aa5..677e82c 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -35,11 +35,9 @@ Transaction::~Transaction() noexcept // nothrow { mDatabase.exec("ROLLBACK"); } - catch (SQLite::Exception& e) + catch (SQLite::Exception&) { - // Never throw an exception in a destructor - (void)e; // warning proof - SQLITECPP_ASSERT(false, e.what()); // See SQLITECPP_ENABLE_ASSERT_HANDLER + // Never throw an exception in a destructor: error if already rollbacked, but no harm is caused by this. } } } diff --git a/tests/Statement_test.cpp b/tests/Statement_test.cpp index 0d70b35..ad2f3ff 100644 --- a/tests/Statement_test.cpp +++ b/tests/Statement_test.cpp @@ -86,8 +86,6 @@ TEST(Statement, invalid) { EXPECT_THROW(query.exec(), SQLite::Exception); // exec() shall throw as it does not expect a result } -// TODO: test every kind of binding + clearBindings() - TEST(Statement, executeStep) { // Create a new database SQLite::Database db(":memory:", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); @@ -128,6 +126,99 @@ TEST(Statement, executeStep) { EXPECT_THROW(query.executeStep(), SQLite::Exception); } +TEST(Statement, bindings) { + // Create a new database + SQLite::Database db(":memory:", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); + EXPECT_EQ(SQLITE_OK, db.getErrorCode()); + + // Create a new table + EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT, int INTEGER, double REAL)")); + EXPECT_EQ(SQLITE_OK, db.getErrorCode()); + + // Insertion with binded values + SQLite::Statement insert(db, "INSERT INTO test VALUES (NULL, ?, ?, ?)"); + + // First row with text/int/double + insert.bind(1, "first"); + insert.bind(2, 123); + insert.bind(3, 0.123); + EXPECT_EQ(1, insert.exec()); + EXPECT_EQ(SQLITE_DONE, db.getErrorCode()); + + // Compile a SQL query to check the result + SQLite::Statement query(db, "SELECT * FROM test"); + EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str()); + EXPECT_EQ(4, query.getColumnCount()); + + // Check the first row + query.executeStep(); + EXPECT_TRUE (query.isOk()); + EXPECT_FALSE(query.isDone()); + EXPECT_EQ (1, query.getColumn(0).getInt64()); + EXPECT_STREQ("first", query.getColumn(1).getText()); + EXPECT_EQ (123, query.getColumn(2).getInt()); + EXPECT_EQ (0.123, query.getColumn(3).getDouble()); + + // reset() without clearbindings() + insert.reset(); + + // Second row with the same exact values because clearbindings() was not called + EXPECT_EQ(1, insert.exec()); + EXPECT_EQ(SQLITE_DONE, db.getErrorCode()); + + // Check the second row + query.executeStep(); + EXPECT_TRUE (query.isOk()); + EXPECT_FALSE(query.isDone()); + EXPECT_EQ (2, query.getColumn(0).getInt64()); + EXPECT_STREQ("first", query.getColumn(1).getText()); + EXPECT_EQ (123, query.getColumn(2).getInt()); + EXPECT_EQ (0.123, query.getColumn(3).getDouble()); + + // reset() with clearbindings() and no more bindings + insert.reset(); + insert.clearBindings(); + + // Third row with the all null values because clearbindings() was called + EXPECT_EQ(1, insert.exec()); + EXPECT_EQ(SQLITE_DONE, db.getErrorCode()); + + // Check the third row + query.executeStep(); + EXPECT_TRUE (query.isOk()); + EXPECT_FALSE(query.isDone()); + EXPECT_EQ (3, query.getColumn(0).getInt64()); + EXPECT_TRUE (query.isColumnNull(1)); + EXPECT_STREQ("", query.getColumn(1).getText()); + EXPECT_TRUE (query.isColumnNull(2)); + EXPECT_EQ (0, query.getColumn(2).getInt()); + EXPECT_TRUE (query.isColumnNull(3)); + EXPECT_EQ (0.0, query.getColumn(3).getDouble()); + + // reset() with clearbindings() and new bindings + insert.reset(); + insert.clearBindings(); + + // Fourth row with string/int64/float + const std::string second("second"); + const sqlite_int64 int64 = 12345678900000LL; + const float fl32 = 0.123f; + insert.bind(1, second); + insert.bind(2, int64); + insert.bind(3, fl32); + EXPECT_EQ(1, insert.exec()); + EXPECT_EQ(SQLITE_DONE, db.getErrorCode()); + + // Check the fourth row + query.executeStep(); + EXPECT_TRUE (query.isOk()); + EXPECT_FALSE(query.isDone()); + EXPECT_EQ(4, query.getColumn(0).getInt64()); + EXPECT_EQ(second, query.getColumn(1).getText()); + EXPECT_EQ(12345678900000LL, query.getColumn(2).getInt64()); + EXPECT_EQ(0.123f, query.getColumn(3).getDouble()); +} + TEST(Statement, isColumnNull) { // Create a new database SQLite::Database db(":memory:", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); diff --git a/tests/Transaction_test.cpp b/tests/Transaction_test.cpp index ecf9ef4..9ed39a1 100644 --- a/tests/Transaction_test.cpp +++ b/tests/Transaction_test.cpp @@ -52,7 +52,7 @@ TEST(Transaction, commitRollback) { EXPECT_EQ(2, db.getLastInsertRowid()); // Execute with an error to rollback - db.exec("Obvious syntax error to raise an exception"); + db.exec("DesiredSyntaxError to raise an exception to rollback the transaction"); GTEST_FATAL_FAILURE_("we should never get there"); // Commit transaction