Added comments and test arround Database::exec() method

This commit is contained in:
Sébastien Rombauts 2014-03-13 21:44:07 +01:00
parent 8d87e80b75
commit 3af95da230
4 changed files with 55 additions and 11 deletions

View File

@ -195,8 +195,8 @@ int main (void)
SQLite::Database db("test.db3", SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); SQLite::Database db("test.db3", SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
std::cout << "SQLite database file '" << db.getFilename().c_str() << "' opened successfully\n"; std::cout << "SQLite database file '" << db.getFilename().c_str() << "' opened successfully\n";
// Create a new table with an explicit "id" column aliasing the underlying rowid
db.exec("DROP TABLE IF EXISTS test"); db.exec("DROP TABLE IF EXISTS test");
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"); db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
// first row // first row

View File

@ -93,8 +93,8 @@ public:
* @brief Shortcut to execute one or multiple statements without results. * @brief Shortcut to execute one or multiple statements without results.
* *
* This is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" : * This is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" :
* - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP"
* - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE" * - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE"
* - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP"
* - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK" * - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK"
* *
* @see Statement::exec() to handle precompiled statements (for better performances) without results * @see Statement::exec() to handle precompiled statements (for better performances) without results
@ -102,7 +102,8 @@ public:
* *
* @param[in] apQueries one or multiple UTF-8 encoded, semicolon-separate SQL statements * @param[in] apQueries one or multiple UTF-8 encoded, semicolon-separate SQL statements
* *
* @return number of rows modified by those SQL statements (INSERT, UPDATE or DELETE) * @return number of rows modified by the *last* INSERT, UPDATE or DELETE statement (beware of multiple statements)
* @warning undefined for CREATE or DROP table: returns the value of a previous INSERT, UPDATE or DELETE statement.
* *
* @throw SQLite::Exception in case of error * @throw SQLite::Exception in case of error
*/ */
@ -112,8 +113,8 @@ public:
* @brief Shortcut to execute one or multiple statements without results. * @brief Shortcut to execute one or multiple statements without results.
* *
* This is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" : * This is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" :
* - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP"
* - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE" * - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE"
* - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP"
* - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK" * - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK"
* *
* @see Statement::exec() to handle precompiled statements (for better performances) without results * @see Statement::exec() to handle precompiled statements (for better performances) without results
@ -121,7 +122,8 @@ public:
* *
* @param[in] aQueries one or multiple UTF-8 encoded, semicolon-separate SQL statements * @param[in] aQueries one or multiple UTF-8 encoded, semicolon-separate SQL statements
* *
* @return number of rows modified by those SQL statements (INSERT, UPDATE or DELETE) * @return number of rows modified by the *last* INSERT, UPDATE or DELETE statement (beware of multiple statements)
* @warning undefined for CREATE or DROP table: returns the value of a previous INSERT, UPDATE or DELETE statement.
* *
* @throw SQLite::Exception in case of error * @throw SQLite::Exception in case of error
*/ */
@ -217,6 +219,9 @@ public:
/** /**
* @brief Get the rowid of the most recent successful INSERT into the database from the current connection. * @brief Get the rowid of the most recent successful INSERT into the database from the current connection.
* *
* Each entry in an SQLite table always has a unique 64-bit signed integer key called the rowid.
* If the table has a column of type INTEGER PRIMARY KEY, then it is an alias for the rowid.
*
* @return Rowid of the most recent successful INSERT into the database, or 0 if there was none. * @return Rowid of the most recent successful INSERT into the database, or 0 if there was none.
*/ */
inline sqlite3_int64 getLastInsertRowid(void) const noexcept // nothrow inline sqlite3_int64 getLastInsertRowid(void) const noexcept // nothrow

View File

@ -61,13 +61,13 @@ Database::~Database(void) noexcept // nothrow
SQLITECPP_ASSERT(SQLITE_OK == ret, sqlite3_errmsg(mpSQLite)); // See SQLITECPP_ENABLE_ASSERT_HANDLER SQLITECPP_ASSERT(SQLITE_OK == ret, sqlite3_errmsg(mpSQLite)); // See SQLITECPP_ENABLE_ASSERT_HANDLER
} }
// Shortcut to execute one or multiple SQL statements without results (UPDATE, INSERT, ALTER, COMMIT...). // Shortcut to execute one or multiple SQL statements without results (UPDATE, INSERT, ALTER, COMMIT, CREATE...).
int Database::exec(const char* apQueries) int Database::exec(const char* apQueries)
{ {
int ret = sqlite3_exec(mpSQLite, apQueries, NULL, NULL, NULL); int ret = sqlite3_exec(mpSQLite, apQueries, NULL, NULL, NULL);
check(ret); check(ret);
// Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE) // Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE only)
return sqlite3_changes(mpSQLite); return sqlite3_changes(mpSQLite);
} }

View File

@ -32,8 +32,10 @@ void assertion_failed(const char* apFile, const long apLine, const char* apFunc,
TEST(Database, ctorExecCreateDropExist) { TEST(Database, ctorExecCreateDropExist) {
remove("test.db3"); remove("test.db3");
{ {
EXPECT_THROW(SQLite::Database absent("test.db3"), SQLite::Exception); // Try to open an unexisting database
EXPECT_THROW(SQLite::Database not_found("test.db3"), SQLite::Exception);
// Create a new database
SQLite::Database db("test.db3", SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); SQLite::Database db("test.db3", SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
EXPECT_STREQ("test.db3", db.getFilename().c_str()); EXPECT_STREQ("test.db3", db.getFilename().c_str());
EXPECT_FALSE(db.tableExists("test")); EXPECT_FALSE(db.tableExists("test"));
@ -58,15 +60,52 @@ TEST(Database, ctorExecCreateDropExist) {
TEST(Database, ctorExecAndGet) { TEST(Database, ctorExecAndGet) {
remove("test.db3"); remove("test.db3");
{ {
// Create a new database
SQLite::Database db("test.db3", SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); SQLite::Database db("test.db3", SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)")); // Create a new table with an explicit "id" column aliasing the underlying rowid
// NOTE: here exec() returns 0 only because it is the first statements since database connexion,
// but its return is an undefined value for "CREATE TABLE" statements.
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
EXPECT_EQ(0, db.getLastInsertRowid()); EXPECT_EQ(0, db.getLastInsertRowid());
// first row // first row : insert the "first" text value into new row of id 1
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"test\")")); EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\")"));
EXPECT_EQ(1, db.getLastInsertRowid()); EXPECT_EQ(1, db.getLastInsertRowid());
// second row : insert the "second" text value into new row of id 2
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"second\")"));
EXPECT_EQ(2, db.getLastInsertRowid());
// third row : insert the "third" text value into new row of id 3
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"third\")"));
EXPECT_EQ(3, db.getLastInsertRowid());
// update the second row : update text value to "second_updated"
EXPECT_EQ(1, db.exec("UPDATE test SET value=\"second-updated\" WHERE id='2'"));
EXPECT_EQ(3, db.getLastInsertRowid()); // last inserted row ID is still 3
// delete the third row
EXPECT_EQ(1, db.exec("DELETE FROM test WHERE id='3'"));
EXPECT_EQ(3, db.getLastInsertRowid());
// drop the whole table, ie the two remaining columns
// NOTE: here exec() returns 1, like the last time, as it is an undefined value for "DROP TABLE" statements
db.exec("DROP TABLE IF EXISTS test");
EXPECT_FALSE(db.tableExists("test"));
// Re-Create the same table
// NOTE: here exec() returns 1, like the last time, as it is an undefined value for "CREATE TABLE" statements
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
// insert two rows with two *different* statements => returns only 1, ie. for the second INSERT statement
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\");INSERT INTO test VALUES (NULL, \"second\");"));
EXPECT_EQ(2, db.getLastInsertRowid());
// insert two rows with only one statement => returns 2
EXPECT_EQ(2, db.exec("INSERT INTO test VALUES (NULL, \"third\"), (NULL, \"fourth\");"));
EXPECT_EQ(4, db.getLastInsertRowid());
} // Close DB test.db3 } // Close DB test.db3
remove("test.db3"); remove("test.db3");
} }