working test

This commit is contained in:
MassiveAtoms
2019-06-26 13:11:16 -03:00
parent 20c5e25619
commit 964b27420b
50 changed files with 248999 additions and 37 deletions

View File

@ -0,0 +1,119 @@
/**
* @file Backup_test.cpp
* @ingroup tests
* @brief Test of a SQLite Backup.
*
* Copyright (c) 2015 Shibao HONG (shibaohong@outlook.com)
* Copyright (c) 2015-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Backup.h>
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/Exception.h>
#include <sqlite3.h> // for SQLITE_ERROR, SQLITE_RANGE and SQLITE_DONE
#include <gtest/gtest.h>
#include <cstdio>
TEST(Backup, initException)
{
remove("backup_test.db3");
SQLite::Database srcDB("backup_test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
srcDB.exec("CREATE TABLE backup_test (id INTEGER PRIMARY KEY, value TEXT)");
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (1, \"first\")"));
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (2, \"second\")"));
EXPECT_THROW(SQLite::Backup backup(srcDB, srcDB), SQLite::Exception);
EXPECT_THROW(SQLite::Backup backup(srcDB, "main", srcDB, "main"), SQLite::Exception);
const std::string name("main");
EXPECT_THROW(SQLite::Backup backup(srcDB, name, srcDB, name), SQLite::Exception);
remove("backup_test.db3");
}
TEST(Backup, executeStepOne)
{
remove("backup_test.db3");
remove("backup_test.db3.backup");
SQLite::Database srcDB("backup_test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
srcDB.exec("CREATE TABLE backup_test (id INTEGER PRIMARY KEY, value TEXT)");
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (1, \"first\")"));
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (2, \"second\")"));
SQLite::Database destDB("backup_test.db3.backup", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
SQLite::Backup backup(destDB, "main", srcDB, "main");
int res = backup.executeStep(1); // backup only one page at a time
ASSERT_EQ(SQLite::OK, res);
const int total = backup.getTotalPageCount();
ASSERT_EQ(2, total);
int remaining = backup.getRemainingPageCount();
ASSERT_EQ(1, remaining);
res = backup.executeStep(1); // backup the second and last page
ASSERT_EQ(SQLITE_DONE, res);
remaining = backup.getRemainingPageCount();
ASSERT_EQ(0, remaining);
SQLite::Statement query(destDB, "SELECT * FROM backup_test ORDER BY id ASC");
ASSERT_TRUE(query.executeStep());
EXPECT_EQ(1, query.getColumn(0).getInt());
EXPECT_STREQ("first", query.getColumn(1));
ASSERT_TRUE(query.executeStep());
EXPECT_EQ(2, query.getColumn(0).getInt());
EXPECT_STREQ("second", query.getColumn(1));
remove("backup_test.db3");
remove("backup_test.db3.backup");
}
TEST(Backup, executeStepAll)
{
remove("backup_test.db3");
remove("backup_test.db3.backup");
SQLite::Database srcDB("backup_test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
srcDB.exec("CREATE TABLE backup_test (id INTEGER PRIMARY KEY, value TEXT)");
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (1, \"first\")"));
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (2, \"second\")"));
SQLite::Database destDB("backup_test.db3.backup", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
SQLite::Backup backup(destDB, srcDB);
const int res = backup.executeStep(); // uses default argument "-1" => execute all steps at once
ASSERT_EQ(res, SQLITE_DONE);
const int total = backup.getTotalPageCount();
ASSERT_EQ(2, total);
const int remaining = backup.getRemainingPageCount();
ASSERT_EQ(0, remaining);
SQLite::Statement query(destDB, "SELECT * FROM backup_test ORDER BY id ASC");
ASSERT_TRUE(query.executeStep());
EXPECT_EQ(1, query.getColumn(0).getInt());
EXPECT_STREQ("first", query.getColumn(1));
ASSERT_TRUE(query.executeStep());
EXPECT_EQ(2, query.getColumn(0).getInt());
EXPECT_STREQ("second", query.getColumn(1));
remove("backup_test.db3");
remove("backup_test.db3.backup");
}
TEST(Backup, executeStepException)
{
remove("backup_test.db3");
remove("backup_test.db3.backup");
SQLite::Database srcDB("backup_test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
srcDB.exec("CREATE TABLE backup_test (id INTEGER PRIMARY KEY, value TEXT)");
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (1, \"first\")"));
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (2, \"second\")"));
{
SQLite::Database destDB("backup_test.db3.backup", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
(void)destDB;
}
{
SQLite::Database destDB("backup_test.db3.backup", SQLite::OPEN_READONLY);
SQLite::Backup backup(destDB, srcDB);
EXPECT_THROW(backup.executeStep(), SQLite::Exception);
}
remove("backup_test.db3");
remove("backup_test.db3.backup");
}

View File

@ -0,0 +1,241 @@
/**
* @file Column_test.cpp
* @ingroup tests
* @brief Test of a SQLiteCpp Column.
*
* Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/Column.h>
#include <sqlite3.h> // for sqlite3_int64
#include <gtest/gtest.h>
#include <cstdio>
#include <stdint.h>
TEST(Column, basis)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
// Create a new table
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT, int INTEGER, double REAL, binary BLOB, empty TEXT)"));
EXPECT_TRUE(db.tableExists("test"));
EXPECT_TRUE(db.tableExists(std::string("test")));
EXPECT_EQ(0, db.getLastInsertRowid());
// Create a first row (autoid: 1) with all kind of data and a null value
SQLite::Statement insert(db, "INSERT INTO test VALUES (NULL, \"first\", -123, 0.123, ?, NULL)");
// Bind the blob value to the first parameter of the SQL query
const char buffer[] = {'b', 'l', '\0', 'b'}; // "bl\0b" : 4 char, with a null byte inside
const int size = sizeof(buffer); // size = 4
const void* blob = &buffer;
insert.bind(1, blob, size);
// Execute the one-step query to insert the row
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(1, db.getLastInsertRowid());
EXPECT_EQ(1, db.getTotalChanges());
EXPECT_THROW(insert.exec(), SQLite::Exception); // exec() shall throw as it needs to be reseted
// Compile a SQL query
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(6, query.getColumnCount ());
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
// validates every variant of cast operators, and conversions of types
{
const sqlite3_int64 id1 = query.getColumn(0); // operator long long()
const int64_t id2 = query.getColumn(0); // operator long long()
const long long id3 = query.getColumn(0); // operator long long()
const long id4 = query.getColumn(0); // operator long long() or long() depending on compiler/architecture
const char id5 = query.getColumn(0); // operator char()
const short id6 = query.getColumn(0); // operator short()
const unsigned int uint1 = query.getColumn(0); // operator unsigned int()
const uint32_t uint2 = query.getColumn(0); // operator unsigned int()
const unsigned char uint3 = query.getColumn(0); // operator unsigned char()
const unsigned short uint4 = query.getColumn(0); // operator unsigned short()
const char* ptxt = query.getColumn(1); // operator const char*()
const std::string msg = query.getColumn(1); // operator std::string() (or const char* with MSVC)
const int integer = query.getColumn(2); // operator int()
const double real = query.getColumn(3); // operator double()
const void* pblob = query.getColumn(4); // operator void*()
#if !defined(_MSC_VER) || _MSC_VER >= 1900
// This implicit cast should use operator std::string()
// but would fallback to const char* with MSVC 2010-2013 (witch does not work with the NULL char in the middle)
const std::string sblob = query.getColumn(4); // operator std::string()
#endif
const void* pempty = query.getColumn(5); // operator void*()
EXPECT_EQ(1, id1);
EXPECT_EQ(1, id2);
EXPECT_EQ(1, id3);
EXPECT_EQ(1, id4);
EXPECT_EQ(1, id5);
EXPECT_EQ(1, id6);
EXPECT_EQ(1U, uint1);
EXPECT_EQ(1U, uint2);
EXPECT_EQ(1U, uint3);
EXPECT_EQ(1U, uint4);
EXPECT_STREQ("first", ptxt);
EXPECT_EQ("first", msg);
EXPECT_EQ(-123, integer);
EXPECT_EQ(0.123, real);
EXPECT_EQ(0, memcmp("bl\0b", pblob, size));
#if !defined(_MSC_VER) || _MSC_VER >= 1900
EXPECT_EQ((size_t)size, sblob.size());
EXPECT_EQ(0, memcmp("bl\0b", &sblob[0], size));
#endif
EXPECT_EQ(NULL, pempty);
}
// validates every variant of explicit getters
{
int64_t id = query.getColumn(0).getInt64();
const unsigned int uint1 = query.getColumn(0).getUInt();
const uint32_t uint2 = query.getColumn(0).getUInt();
const char* ptxt = query.getColumn(1).getText();
const std::string msg1 = query.getColumn(1).getText();
const std::string msg2 = query.getColumn(1).getString();
const int integer = query.getColumn(2).getInt();
const double real = query.getColumn(3).getDouble();
const void* pblob = query.getColumn(4).getBlob();
const std::string sblob = query.getColumn(4).getString();
EXPECT_EQ(1, id);
EXPECT_EQ(1U, uint1);
EXPECT_EQ(1U, uint2);
EXPECT_STREQ("first", ptxt);
EXPECT_EQ("first", msg1);
EXPECT_EQ("first", msg2);
EXPECT_EQ(-123, integer);
EXPECT_EQ(0.123, real);
EXPECT_EQ(0, memcmp("bl\0b", pblob, 4));
EXPECT_EQ(0, memcmp("bl\0b", &sblob[0], 4));
}
// Validate getBytes(), getType(), isInteger(), isNull()...
EXPECT_EQ(SQLite::INTEGER, query.getColumn(0).getType());
EXPECT_EQ(true, query.getColumn(0).isInteger());
EXPECT_EQ(false, query.getColumn(0).isFloat());
EXPECT_EQ(false, query.getColumn(0).isText());
EXPECT_EQ(false, query.getColumn(0).isBlob());
EXPECT_EQ(false, query.getColumn(0).isNull());
EXPECT_STREQ("1", query.getColumn(0).getText()); // convert to string
EXPECT_EQ(1, query.getColumn(0).getBytes()); // size of the string "1" without the null terminator
EXPECT_EQ(SQLite::TEXT, query.getColumn(1).getType());
EXPECT_EQ(false, query.getColumn(1).isInteger());
EXPECT_EQ(false, query.getColumn(1).isFloat());
EXPECT_EQ(true, query.getColumn(1).isText());
EXPECT_EQ(false, query.getColumn(1).isBlob());
EXPECT_EQ(false, query.getColumn(1).isNull());
EXPECT_STREQ("first", query.getColumn(1).getText()); // convert to string
EXPECT_EQ(5, query.getColumn(1).getBytes()); // size of the string "first"
EXPECT_EQ(SQLite::INTEGER, query.getColumn(2).getType());
EXPECT_EQ(true, query.getColumn(2).isInteger());
EXPECT_EQ(false, query.getColumn(2).isFloat());
EXPECT_EQ(false, query.getColumn(2).isText());
EXPECT_EQ(false, query.getColumn(2).isBlob());
EXPECT_EQ(false, query.getColumn(2).isNull());
EXPECT_STREQ("-123", query.getColumn(2).getText()); // convert to string
EXPECT_EQ(4, query.getColumn(2).getBytes()); // size of the string "-123"
EXPECT_EQ(SQLite::FLOAT, query.getColumn(3).getType());
EXPECT_EQ(false, query.getColumn(3).isInteger());
EXPECT_EQ(true, query.getColumn(3).isFloat());
EXPECT_EQ(false, query.getColumn(3).isText());
EXPECT_EQ(false, query.getColumn(3).isBlob());
EXPECT_EQ(false, query.getColumn(3).isNull());
EXPECT_STREQ("0.123", query.getColumn(3).getText()); // convert to string
EXPECT_EQ(5, query.getColumn(3).getBytes()); // size of the string "0.123"
EXPECT_EQ(SQLite::BLOB, query.getColumn(4).getType());
EXPECT_EQ(false, query.getColumn(4).isInteger());
EXPECT_EQ(false, query.getColumn(4).isFloat());
EXPECT_EQ(false, query.getColumn(4).isText());
EXPECT_EQ(true, query.getColumn(4).isBlob());
EXPECT_EQ(false, query.getColumn(4).isNull());
EXPECT_STREQ("bl\0b", query.getColumn(4).getText()); // convert to string
EXPECT_EQ(4, query.getColumn(4).getBytes()); // size of the blob "bl\0b" with the null char
EXPECT_EQ(SQLite::Null, query.getColumn(5).getType());
EXPECT_EQ(false, query.getColumn(5).isInteger());
EXPECT_EQ(false, query.getColumn(5).isFloat());
EXPECT_EQ(false, query.getColumn(5).isText());
EXPECT_EQ(false, query.getColumn(5).isBlob());
EXPECT_EQ(true, query.getColumn(5).isNull());
EXPECT_STREQ("", query.getColumn(5).getText()); // convert to string
EXPECT_EQ(0, query.getColumn(5).getBytes()); // size of the string "" without the null terminator
// Use intermediate Column objects (this is not the recommended way to use the API)
{
const SQLite::Column id = query.getColumn(0);
EXPECT_EQ(1, id.getInt64());
const SQLite::Column msg = query.getColumn(1);
EXPECT_EQ("first", msg.getString());
const SQLite::Column integer = query.getColumn(2);
EXPECT_EQ(-123, integer.getInt());
const SQLite::Column dbl = query.getColumn(3);
EXPECT_EQ(0.123, dbl.getDouble());
}
}
TEST(Column, getName)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT)"));
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\")"));
// Compile a SQL query, using the "id" column name as-is, but aliasing the "msg" column with new name "value"
SQLite::Statement query(db, "SELECT id, msg as value FROM test");
query.executeStep();
// Show how to get the aliased names of the result columns.
const std::string name0 = query.getColumn(0).getName();
const std::string name1 = query.getColumn(1).getName();
EXPECT_EQ("id", name0);
EXPECT_EQ("value", name1);
#ifdef SQLITE_ENABLE_COLUMN_METADATA
// Show how to get origin names of the table columns from which theses result columns come from.
// Requires the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro to be
// also defined at compile times of the SQLite library itself.
const std::string oname0 = query.getColumn(0).getOriginName();
const std::string oname1 = query.getColumn(1).getOriginName();
EXPECT_EQ("id", oname0);
EXPECT_EQ("msg", oname1);
#endif
}
TEST(Column, stream)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(0, db.exec("CREATE TABLE test (msg TEXT)"));
SQLite::Statement insert(db, "INSERT INTO test VALUES (?)");
// content to test
const char str_[] = "stringwith\0embedded";
std::string str(str_, sizeof(str_)-1);
insert.bind(1, str);
// Execute the one-step query to insert the row
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(1, db.getTotalChanges());
SQLite::Statement query(db, "SELECT * FROM test");
query.executeStep();
std::stringstream ss;
ss << query.getColumn(0);
std::string content = ss.str();
EXPECT_EQ(content, str);
}

View File

@ -0,0 +1,364 @@
/**
* @file Database_test.cpp
* @ingroup tests
* @brief Test of a SQLiteCpp Database.
*
* Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Database.h>
#include <sqlite3.h> // for SQLITE_ERROR and SQLITE_VERSION_NUMBER
#include <gtest/gtest.h>
#include <cstdio>
#ifdef SQLITECPP_ENABLE_ASSERT_HANDLER
namespace SQLite
{
/// definition of the assertion handler enabled when SQLITECPP_ENABLE_ASSERT_HANDLER is defined in the project (CMakeList.txt)
void assertion_failed(const char* apFile, const long apLine, const char* apFunc, const char* apExpr, const char* apMsg)
{
// TODO: unit test that this assertion callback get called (already tested manually)
std::cout << "assertion_failed(" << apFile << ", " << apLine << ", " << apFunc << ", " << apExpr << ", " << apMsg << ")\n";
}
}
#endif
TEST(SQLiteCpp, version)
{
EXPECT_STREQ(SQLITE_VERSION, SQLite::VERSION);
EXPECT_EQ (SQLITE_VERSION_NUMBER, SQLite::VERSION_NUMBER);
EXPECT_STREQ(SQLITE_VERSION, SQLite::getLibVersion());
EXPECT_EQ (SQLITE_VERSION_NUMBER, SQLite::getLibVersionNumber());
}
TEST(Database, ctorExecCreateDropExist)
{
remove("test.db3");
{
// Try to open a non-existing database
std::string filename = "test.db3";
EXPECT_THROW(SQLite::Database not_found(filename), SQLite::Exception);
// Create a new database
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_STREQ("test.db3", db.getFilename().c_str());
EXPECT_FALSE(db.tableExists("test"));
EXPECT_FALSE(db.tableExists(std::string("test")));
EXPECT_EQ(0, db.getLastInsertRowid());
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"));
EXPECT_TRUE(db.tableExists("test"));
EXPECT_TRUE(db.tableExists(std::string("test")));
EXPECT_EQ(0, db.getLastInsertRowid());
EXPECT_EQ(0, db.exec("DROP TABLE IF EXISTS test"));
EXPECT_FALSE(db.tableExists("test"));
EXPECT_FALSE(db.tableExists(std::string("test")));
EXPECT_EQ(0, db.getLastInsertRowid());
} // Close DB test.db3
remove("test.db3");
}
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
SQLite::Database DatabaseBuilder(const char* apName)
{
return SQLite::Database(apName, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
}
TEST(Database, moveConstructor)
{
remove("test.db3");
{
// Create a new database, using the move constructor
SQLite::Database db = DatabaseBuilder("test.db3");
EXPECT_FALSE(db.tableExists("test"));
EXPECT_TRUE(db.getHandle() != NULL);
SQLite::Database moved = std::move(db);
EXPECT_TRUE(db.getHandle() == NULL);
EXPECT_TRUE(moved.getHandle() != NULL);
EXPECT_FALSE(moved.tableExists("test"));
} // Close DB test.db3
remove("test.db3");
}
#endif
TEST(Database, createCloseReopen)
{
remove("test.db3");
{
// Try to open the non-existing 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);
EXPECT_FALSE(db.tableExists("test"));
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
EXPECT_TRUE(db.tableExists("test"));
} // Close DB test.db3
{
// Reopen the database file
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_TRUE(db.tableExists("test"));
} // Close DB test.db3
remove("test.db3");
}
TEST(Database, inMemory)
{
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
EXPECT_FALSE(db.tableExists("test"));
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
EXPECT_TRUE(db.tableExists("test"));
// Create a new database: not shared with the above db
SQLite::Database db2(":memory:");
EXPECT_FALSE(db2.tableExists("test"));
} // Close an destroy DBs
{
// Create a new database: no more "test" table
SQLite::Database db(":memory:");
EXPECT_FALSE(db.tableExists("test"));
} // Close an destroy DB
}
#if SQLITE_VERSION_NUMBER >= 3007015 // SQLite v3.7.15 is first version with PRAGMA busy_timeout
TEST(Database, busyTimeout)
{
{
// Create a new database with default timeout of 0ms
SQLite::Database db(":memory:");
// Busy timeout default to 0ms: any contention between threads or process leads to SQLITE_BUSY error
EXPECT_EQ(0, db.execAndGet("PRAGMA busy_timeout").getInt());
// Set a non null busy timeout: any contention between threads will leads to as much retry as possible during the time
db.setBusyTimeout(5000);
EXPECT_EQ(5000, db.execAndGet("PRAGMA busy_timeout").getInt());
// Reset timeout to 0
db.setBusyTimeout(0);
EXPECT_EQ(0, db.execAndGet("PRAGMA busy_timeout").getInt());
}
{
// Create a new database with a non null busy timeout
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE, 5000);
EXPECT_EQ(5000, db.execAndGet("PRAGMA busy_timeout").getInt());
// Reset timeout to null
db.setBusyTimeout(0);
EXPECT_EQ(0, db.execAndGet("PRAGMA busy_timeout").getInt());
}
{
// Create a new database with a non null busy timeout
const std::string memory = ":memory:";
SQLite::Database db(memory, SQLite::OPEN_READWRITE, 5000);
EXPECT_EQ(5000, db.execAndGet("PRAGMA busy_timeout").getInt());
// Reset timeout to null
db.setBusyTimeout(0);
EXPECT_EQ(0, db.execAndGet("PRAGMA busy_timeout").getInt());
}
}
#endif // SQLITE_VERSION_NUMBER >= 3007015
TEST(Database, exec)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
// 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.getTotalChanges());
// first row : insert the "first" text value into new row of id 1
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\")"));
EXPECT_EQ(1, db.getLastInsertRowid());
EXPECT_EQ(1, db.getTotalChanges());
// 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());
EXPECT_EQ(2, db.getTotalChanges());
// third row : insert the "third" text value into new row of id 3
const std::string insert("INSERT INTO test VALUES (NULL, \"third\")");
EXPECT_EQ(1, db.exec(insert));
EXPECT_EQ(3, db.getLastInsertRowid());
EXPECT_EQ(3, db.getTotalChanges());
// 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
EXPECT_EQ(4, db.getTotalChanges());
// delete the third row
EXPECT_EQ(1, db.exec("DELETE FROM test WHERE id='3'"));
EXPECT_EQ(3, db.getLastInsertRowid());
EXPECT_EQ(5, db.getTotalChanges());
// 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"));
EXPECT_EQ(5, db.getTotalChanges());
// 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)");
EXPECT_EQ(5, db.getTotalChanges());
// 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());
EXPECT_EQ(7, db.getTotalChanges());
#if (SQLITE_VERSION_NUMBER >= 3007011)
// insert two rows with only one statement (starting with SQLite 3.7.11) => returns 2
EXPECT_EQ(2, db.exec("INSERT INTO test VALUES (NULL, \"third\"), (NULL, \"fourth\");"));
EXPECT_EQ(4, db.getLastInsertRowid());
EXPECT_EQ(9, db.getTotalChanges());
#endif
}
TEST(Database, execAndGet)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
// Create a new table with an explicit "id" column aliasing the underlying rowid
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT, weight INTEGER)");
// insert a few rows
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\", 3)"));
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"second\", 5)"));
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"third\", 7)"));
// Get a single value result with an easy to use shortcut
EXPECT_STREQ("second", db.execAndGet("SELECT value FROM test WHERE id=2"));
EXPECT_STREQ("third", db.execAndGet("SELECT value FROM test WHERE weight=7"));
EXPECT_EQ(3, db.execAndGet("SELECT weight FROM test WHERE value=\"first\"").getInt());
}
TEST(Database, execException)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
// exception with SQL error: "no such table"
EXPECT_THROW(db.exec("INSERT INTO test VALUES (NULL, \"first\", 3)"), SQLite::Exception);
EXPECT_EQ(SQLITE_ERROR, db.getErrorCode());
EXPECT_EQ(SQLITE_ERROR, db.getExtendedErrorCode());
EXPECT_STREQ("no such table: test", db.getErrorMsg());
// Create a new table
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT, weight INTEGER)");
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
EXPECT_STREQ("not an error", db.getErrorMsg());
// exception with SQL error: "table test has 3 columns but 2 values were supplied"
EXPECT_THROW(db.exec("INSERT INTO test VALUES (NULL, 3)"), SQLite::Exception);
EXPECT_EQ(SQLITE_ERROR, db.getErrorCode());
EXPECT_EQ(SQLITE_ERROR, db.getExtendedErrorCode());
EXPECT_STREQ("table test has 3 columns but 2 values were supplied", db.getErrorMsg());
// exception with SQL error: "No row to get a column from"
EXPECT_THROW(db.execAndGet("SELECT weight FROM test WHERE value=\"first\""), SQLite::Exception);
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\", 3)"));
// exception with SQL error: "No row to get a column from"
EXPECT_THROW(db.execAndGet("SELECT weight FROM test WHERE value=\"second\""), SQLite::Exception);
// Add a row with more values than columns in the table: "table test has 3 columns but 4 values were supplied"
EXPECT_THROW(db.exec("INSERT INTO test VALUES (NULL, \"first\", 123, 0.123)"), SQLite::Exception);
EXPECT_EQ(SQLITE_ERROR, db.getErrorCode());
EXPECT_EQ(SQLITE_ERROR, db.getExtendedErrorCode());
EXPECT_STREQ("table test has 3 columns but 4 values were supplied", db.getErrorMsg());
}
// TODO: test Database::createFunction()
// TODO: test Database::loadExtension()
#ifdef SQLITE_HAS_CODEC
TEST(Database, encryptAndDecrypt)
{
remove("test.db3");
{
// Try to open the non-existing 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);
EXPECT_FALSE(db.tableExists("test"));
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
EXPECT_TRUE(db.tableExists("test"));
} // Close DB test.db3
{
// Reopen the database file and encrypt it
EXPECT_TRUE(SQLite::Database::isUnencrypted("test.db3"));
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE);
// Encrypt the database
db.rekey("123secret");
} // Close DB test.db3
{
// Reopen the database file and try to use it
EXPECT_FALSE(SQLite::Database::isUnencrypted("test.db3"));
SQLite::Database db("test.db3", SQLite::OPEN_READONLY);
EXPECT_THROW(db.tableExists("test"), SQLite::Exception);
db.key("123secret");
EXPECT_TRUE(db.tableExists("test"));
} // Close DB test.db3
{
// Reopen the database file and decrypt it
EXPECT_FALSE(SQLite::Database::isUnencrypted("test.db3"));
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE);
// Decrypt the database
db.key("123secret");
db.rekey("");
} // Close DB test.db3
{
// Reopen the database file and use it
EXPECT_TRUE(SQLite::Database::isUnencrypted("test.db3"));
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE);
EXPECT_TRUE(db.tableExists("test"));
} // Close DB test.db3
remove("test.db3");
}
#else // SQLITE_HAS_CODEC
TEST(Database, encryptAndDecrypt)
{
remove("test.db3");
{
// Try to open the non-existing 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);
EXPECT_FALSE(db.tableExists("test"));
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
EXPECT_TRUE(db.tableExists("test"));
} // Close DB test.db3
{
// Reopen the database file and encrypt it
EXPECT_TRUE(SQLite::Database::isUnencrypted("test.db3"));
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE);
// Encrypt the database
EXPECT_THROW(db.key("123secret"), SQLite::Exception);
EXPECT_THROW(db.rekey("123secret"), SQLite::Exception);
} // Close DB test.db3
remove("test.db3");
}
#endif // SQLITE_HAS_CODEC

View File

@ -0,0 +1,73 @@
/**
* @file Transaction_test.cpp
* @ingroup tests
* @brief Test of a SQLite Transaction.
*
* Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Exception.h>
#include <gtest/gtest.h>
#include <string>
TEST(Exception, copy)
{
const SQLite::Exception ex1("some error", 2);
const SQLite::Exception ex2 = ex1;
EXPECT_STREQ(ex1.what(), ex2.what());
EXPECT_EQ(ex1.getErrorCode(), ex2.getErrorCode());
EXPECT_EQ(ex1.getExtendedErrorCode(), ex2.getExtendedErrorCode());
}
// see http://eel.is/c++draft/exception#2 or http://www.cplusplus.com/reference/exception/exception/operator=/
// an assignment operator is expected to be avaiable
TEST(Exception, assignment)
{
const SQLite::Exception ex1("some error", 2);
SQLite::Exception ex2("some error2", 3);
ex2 = ex1;
EXPECT_STREQ(ex1.what(), ex2.what());
EXPECT_EQ(ex1.getErrorCode(), ex2.getErrorCode());
EXPECT_EQ(ex1.getExtendedErrorCode(), ex2.getExtendedErrorCode());
}
TEST(Exception, throw_catch)
{
const char message[] = "some error";
try
{
throw SQLite::Exception(message);
}
catch (const std::runtime_error& ex)
{
EXPECT_STREQ(ex.what(), message);
}
}
TEST(Exception, constructor)
{
const char msg1[] = "error msg";
std::string msg2 = msg1;
{
const SQLite::Exception ex1(msg1);
const SQLite::Exception ex2(msg2);
EXPECT_STREQ(ex1.what(), ex2.what());
EXPECT_EQ(ex1.getErrorCode(), ex2.getErrorCode());
EXPECT_EQ(ex1.getExtendedErrorCode(), ex2.getExtendedErrorCode());
}
{
const SQLite::Exception ex1(msg1, 1);
const SQLite::Exception ex2(msg2, 1);
EXPECT_STREQ(ex1.what(), ex2.what());
EXPECT_EQ(ex1.getErrorCode(), ex2.getErrorCode());
EXPECT_EQ(ex1.getExtendedErrorCode(), ex2.getExtendedErrorCode());
}
}

View File

@ -0,0 +1,54 @@
/**
* @file VariadicBind_test.cpp
* @ingroup tests
* @brief Test of variadic bind
*
* Copyright (c) 2019 Maximilian Bachmann (github@maxbachmann)
* Copyright (c) 2019 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/ExecuteMany.h>
#include <gtest/gtest.h>
#include <cstdio>
#if (__cplusplus >= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) ) // c++14: Visual Studio 2015
TEST(ExecuteMany, invalid)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(0, db.exec("DROP TABLE IF EXISTS test"));
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT DEFAULT 'default')"));
EXPECT_TRUE(db.tableExists("test"));
{
execute_many(db, "INSERT INTO test VALUES (?, ?)",
std::make_tuple(1),
std::make_tuple(2, "two"),
std::make_tuple(3, "three")
);
}
// make sure the content is as expected
{
SQLite::Statement query(db, std::string{"SELECT id, value FROM test ORDER BY id"});
std::vector<std::pair<int, std::string> > results;
while (query.executeStep())
{
const int id = query.getColumn(0);
std::string value = query.getColumn(1);
results.emplace_back( id, std::move(value) );
}
EXPECT_EQ(std::size_t(3), results.size());
EXPECT_EQ(std::make_pair(1,std::string{""}), results.at(0));
EXPECT_EQ(std::make_pair(2,std::string{"two"}), results.at(1));
EXPECT_EQ(std::make_pair(3,std::string{"three"}), results.at(2));
}
}
#endif // c++14

View File

@ -0,0 +1,864 @@
/**
* @file Statement_test.cpp
* @ingroup tests
* @brief Test of a SQLiteCpp Statement.
*
* Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Statement.h>
#include <sqlite3.h> // for SQLITE_DONE
#include <gtest/gtest.h>
#include <cstdio>
#include <stdint.h>
#include <climits> // For INT_MAX
TEST(Statement, invalid)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
// Compile a SQL query, but without any table in the database
EXPECT_THROW(SQLite::Statement query(db, "SELECT * FROM test"), SQLite::Exception);
EXPECT_EQ(SQLITE_ERROR, db.getErrorCode());
EXPECT_EQ(SQLITE_ERROR, db.getExtendedErrorCode());
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
// Compile a SQL query with no parameter
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(2, query.getColumnCount ());
EXPECT_FALSE(query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(SQLite::OK, query.getErrorCode());
EXPECT_EQ(SQLite::OK, query.getExtendedErrorCode());
EXPECT_THROW(query.isColumnNull(-1), SQLite::Exception);
EXPECT_THROW(query.isColumnNull(0), SQLite::Exception);
EXPECT_THROW(query.isColumnNull(1), SQLite::Exception);
EXPECT_THROW(query.isColumnNull(2), SQLite::Exception);
EXPECT_THROW(query.getColumn(-1), SQLite::Exception);
EXPECT_THROW(query.getColumn(0), SQLite::Exception);
EXPECT_THROW(query.getColumn(1), SQLite::Exception);
EXPECT_THROW(query.getColumn(2), SQLite::Exception);
query.reset();
EXPECT_FALSE(query.hasRow());
EXPECT_FALSE(query.isDone());
query.executeStep();
EXPECT_FALSE(query.hasRow());
EXPECT_TRUE( query.isDone());
query.reset();
EXPECT_FALSE(query.hasRow());
EXPECT_FALSE(query.isDone());
query.reset();
EXPECT_THROW(query.bind(-1, 123), SQLite::Exception);
EXPECT_THROW(query.bind(0, 123), SQLite::Exception);
EXPECT_THROW(query.bind(1, 123), SQLite::Exception);
EXPECT_THROW(query.bind(2, 123), SQLite::Exception);
EXPECT_THROW(query.bind(0, "abc"), SQLite::Exception);
EXPECT_THROW(query.bind(0), SQLite::Exception);
EXPECT_EQ(SQLITE_RANGE, db.getErrorCode());
EXPECT_EQ(SQLITE_RANGE, db.getExtendedErrorCode());
EXPECT_STREQ("column index out of range", db.getErrorMsg());
EXPECT_EQ(SQLITE_RANGE, query.getErrorCode());
EXPECT_EQ(SQLITE_RANGE, query.getExtendedErrorCode());
EXPECT_STREQ("column index out of range", query.getErrorMsg());
query.exec(); // exec() instead of executeStep() as there is no result
EXPECT_THROW(query.isColumnNull(0), SQLite::Exception);
EXPECT_THROW(query.getColumn(0), SQLite::Exception);
EXPECT_THROW(query.exec(), SQLite::Exception); // exec() shall throw as it needs to be reseted
// Add a first row
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\")"));
EXPECT_EQ(1, db.getLastInsertRowid());
EXPECT_EQ(1, db.getTotalChanges());
query.reset();
EXPECT_FALSE(query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.exec(), SQLite::Exception); // exec() shall throw as it does not expect a result
}
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
SQLite::Statement StatementBuilder(SQLite::Database& aDb, const char* apQuery)
{
return SQLite::Statement(aDb, apQuery);
}
TEST(Statement, moveConstructor)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"));
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\")"));
EXPECT_EQ(1, db.getLastInsertRowid());
SQLite::Statement query = StatementBuilder(db, "SELECT * FROM test");
EXPECT_FALSE(query.getQuery().empty());
EXPECT_FALSE(query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(2, query.getColumnCount());
SQLite::Statement moved = std::move(query);
EXPECT_TRUE(query.getQuery().empty());
EXPECT_EQ(0, query.getColumnCount());
EXPECT_FALSE(moved.getQuery().empty());
EXPECT_EQ(2, moved.getColumnCount());
// Execute
moved.executeStep();
EXPECT_TRUE(moved.hasRow());
EXPECT_FALSE(moved.isDone());
EXPECT_FALSE(query.hasRow());
EXPECT_FALSE(query.isDone());
}
#endif
TEST(Statement, executeStep)
{
// 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());
// Create a first row
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\", 123, 0.123)"));
EXPECT_EQ(1, db.getLastInsertRowid());
// Compile a SQL query
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(4, query.getColumnCount());
// Get the first row
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
const int64_t id = query.getColumn(0);
const std::string msg = query.getColumn(1);
const int integer = query.getColumn(2);
const long integer2= query.getColumn(2);
const double real = query.getColumn(3);
EXPECT_EQ(1, id);
EXPECT_EQ("first", msg);
EXPECT_EQ(123, integer);
EXPECT_EQ(123, integer2);
EXPECT_EQ(0.123, real);
// Step one more time to discover there is nothing more
query.executeStep();
EXPECT_FALSE(query.hasRow());
EXPECT_TRUE (query.isDone()); // "done" is "the end"
// Step after "the end" throw an exception
EXPECT_THROW(query.executeStep(), SQLite::Exception);
// Try to insert a new row with the same PRIMARY KEY: "UNIQUE constraint failed: test.id"
SQLite::Statement insert(db, "INSERT INTO test VALUES (1, \"impossible\", 456, 0.456)");
EXPECT_THROW(insert.executeStep(), SQLite::Exception);
// in this case, reset() do throw again the same error
EXPECT_THROW(insert.reset(), SQLite::Exception);
// Try again to insert a new row with the same PRIMARY KEY (with an alternative method): "UNIQUE constraint failed: test.id"
SQLite::Statement insert2(db, "INSERT INTO test VALUES (1, \"impossible\", 456, 0.456)");
EXPECT_THROW(insert2.exec(), SQLite::Exception);
}
TEST(Statement, tryExecuteStep)
{
// 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());
// Create a first row
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\", 123, 0.123)"));
EXPECT_EQ(1, db.getLastInsertRowid());
// Compile a SQL query
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(4, query.getColumnCount());
// Get the first row
EXPECT_EQ(query.tryExecuteStep(), SQLITE_ROW);
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
const int64_t id = query.getColumn(0);
const std::string msg = query.getColumn(1);
const int integer = query.getColumn(2);
const long integer2= query.getColumn(2);
const double real = query.getColumn(3);
EXPECT_EQ(1, id);
EXPECT_EQ("first", msg);
EXPECT_EQ(123, integer);
EXPECT_EQ(123, integer2);
EXPECT_EQ(0.123, real);
// Step one more time to discover there is nothing more
EXPECT_EQ(query.tryExecuteStep(), SQLITE_DONE);
EXPECT_FALSE(query.hasRow());
EXPECT_TRUE (query.isDone()); // "done" is "the end"
// Try to insert a new row with the same PRIMARY KEY: "UNIQUE constraint failed: test.id"
SQLite::Statement insert(db, "INSERT INTO test VALUES (1, \"impossible\", 456, 0.456)");
EXPECT_EQ(insert.tryExecuteStep(), SQLITE_CONSTRAINT);
// in this case, reset() do throw again the same error
EXPECT_EQ(insert.tryReset(), SQLITE_CONSTRAINT);
}
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 bindable parameters
SQLite::Statement insert(db, "INSERT INTO test VALUES (NULL, ?, ?, ?)");
// Compile a SQL query to check the results
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(4, query.getColumnCount());
// First row with text/int/double
{
const char* text = "first";
const int integer = -123;
const double dbl = 0.123;
insert.bind(1, text);
insert.bind(2, integer);
insert.bind(3, dbl);
EXPECT_EQ(insert.getExpandedSQL(), "INSERT INTO test VALUES (NULL, 'first', -123, 0.123)");
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE (query.hasRow());
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 result
query.executeStep();
EXPECT_TRUE (query.hasRow());
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 resultw
query.executeStep();
EXPECT_TRUE (query.hasRow());
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 fourth("fourth");
const long long int64 = 12345678900000LL;
const float float32 = 0.234f;
insert.bind(1, fourth);
insert.bind(2, int64);
insert.bind(3, float32);
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(4, query.getColumn(0).getInt64());
EXPECT_EQ(fourth, query.getColumn(1).getText());
EXPECT_EQ(12345678900000LL, query.getColumn(2).getInt64());
EXPECT_EQ(0.234f, query.getColumn(3).getDouble());
}
// reset() without clearbindings()
insert.reset();
// Fifth row with binary buffer and a null parameter
{
const char buffer[] = "binary";
insert.bind(1, buffer, sizeof(buffer));
insert.bind(2);
EXPECT_EQ(1, insert.exec());
// Check the result
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(5, query.getColumn(0).getInt64());
EXPECT_STREQ(buffer, query.getColumn(1).getText());
EXPECT_TRUE (query.isColumnNull(2));
EXPECT_EQ(0, query.getColumn(2).getInt());
EXPECT_EQ(0.234f, query.getColumn(3).getDouble());
}
// reset() without clearbindings()
insert.reset();
// Sixth row with uint32_t unsigned value and a long value (which is either a 32b int or a 64b long long)
{
const uint32_t uint32 = 4294967295U;
const long integer = -123;
insert.bind(2, uint32);
insert.bind(3, integer);
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE(query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(6, query.getColumn(0).getInt64());
EXPECT_EQ(4294967295U, query.getColumn(2).getUInt());
EXPECT_EQ(-123, query.getColumn(3).getInt());
}
// reset() without clearbindings()
insert.reset();
// Seventh row using another variant of int64 type
{
const int64_t int64 = 12345678900000LL;
insert.bind(2, int64);
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE(query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(7, query.getColumn(0).getInt64());
EXPECT_EQ(12345678900000LL, query.getColumn(2).getInt64());
}
}
TEST(Statement, bindNoCopy)
{
// 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, txt1 TEXT, txt2 TEXT, binary BLOB)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Insertion with bindable parameters
SQLite::Statement insert(db, "INSERT INTO test VALUES (NULL, ?, ?, ?)");
// Compile a SQL query to check the results
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(4, query.getColumnCount());
// Insert one row with all variants of bindNoCopy()
{
const char* txt1 = "first";
const std::string txt2 = "sec\0nd";
const char blob[] = {'b','l','\0','b'};
insert.bindNoCopy(1, txt1);
insert.bindNoCopy(2, txt2);
insert.bindNoCopy(3, blob, sizeof(blob));
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE(query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(1, query.getColumn(0).getInt64());
EXPECT_STREQ(txt1, query.getColumn(1).getText());
EXPECT_EQ(0, memcmp(&txt2[0], &query.getColumn(2).getString()[0], txt2.size()));
EXPECT_EQ(0, memcmp(blob, &query.getColumn(3).getString()[0], sizeof(blob)));
}
}
TEST(Statement, bindByName)
{
// 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, long INTEGER)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Insertion with bindable parameters
SQLite::Statement insert(db, "INSERT INTO test VALUES (NULL, @msg, @int, @double, @long)");
// First row with text/int/double
insert.bind("@msg", "first");
insert.bind("@int", 123);
insert.bind("@long", -123);
insert.bind("@double", 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(5, query.getColumnCount());
// Check the result
query.executeStep();
EXPECT_TRUE (query.hasRow());
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());
EXPECT_EQ (-123, query.getColumn(4).getInt());
// reset() with clearbindings() and new bindings
insert.reset();
insert.clearBindings();
// Second row with string/int64/float
{
const std::string second("second");
const long long int64 = 12345678900000LL;
const long integer = -123;
const float float32 = 0.234f;
insert.bind("@msg", second);
insert.bind("@int", int64);
insert.bind("@double", float32);
insert.bind("@long", integer);
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(2, query.getColumn(0).getInt64());
EXPECT_EQ(second, query.getColumn(1).getText());
EXPECT_EQ(12345678900000LL, query.getColumn(2).getInt64());
EXPECT_EQ(0.234f, query.getColumn(3).getDouble());
EXPECT_EQ(-123, query.getColumn(4).getInt());
}
// reset() without clearbindings()
insert.reset();
// Third row with binary buffer and a null parameter
{
const char buffer[] = "binary";
insert.bind("@msg", buffer, sizeof(buffer));
insert.bind("@int");
EXPECT_EQ(1, insert.exec());
// Check the result
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(3, query.getColumn(0).getInt64());
EXPECT_STREQ(buffer, query.getColumn(1).getText());
EXPECT_TRUE (query.isColumnNull(2));
EXPECT_EQ(0, query.getColumn(2).getInt());
EXPECT_EQ(0.234f, query.getColumn(3).getDouble());
}
// reset() without clearbindings()
insert.reset();
// Fourth row with uint32_t unsigned value and int64_t 64bits value
{
const uint32_t uint32 = 4294967295U;
const int64_t int64 = 12345678900000LL;
insert.bind("@int", uint32);
insert.bind("@long", int64);
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE(query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(4, query.getColumn(0).getInt64());
EXPECT_EQ(4294967295U, query.getColumn(2).getUInt());
EXPECT_EQ(12345678900000LL, query.getColumn(4).getInt64());
}
}
TEST(Statement, bindNoCopyByName)
{
// 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, txt1 TEXT, txt2 TEXT, binary BLOB)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Insertion with bindable parameters
SQLite::Statement insert(db, "INSERT INTO test VALUES (NULL, @txt1, @txt2, @blob)");
// Compile a SQL query to check the results
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(4, query.getColumnCount());
// Insert one row with all variants of bindNoCopy()
{
const char* txt1 = "first";
const std::string txt2 = "sec\0nd";
const char blob[] = { 'b','l','\0','b' };
insert.bindNoCopy("@txt1", txt1);
insert.bindNoCopy("@txt2", txt2);
insert.bindNoCopy("@blob", blob, sizeof(blob));
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE(query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(1, query.getColumn(0).getInt64());
EXPECT_STREQ(txt1, query.getColumn(1).getText());
EXPECT_EQ(0, memcmp(&txt2[0], &query.getColumn(2).getString()[0], txt2.size()));
EXPECT_EQ(0, memcmp(blob, &query.getColumn(3).getString()[0], sizeof(blob)));
}
}
TEST(Statement, isColumnNull)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
ASSERT_EQ(SQLite::OK, db.getErrorCode());
// Create a new table
EXPECT_EQ(0, db.exec("CREATE TABLE test (msg TEXT, int INTEGER, double REAL)"));
ASSERT_EQ(SQLite::OK, db.getErrorCode());
// Create a first row with no null values, then other rows with each time a NULL value
ASSERT_EQ(1, db.exec("INSERT INTO test VALUES (\"first\", 123, 0.123)"));
ASSERT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, 123, 0.123)"));
ASSERT_EQ(1, db.exec("INSERT INTO test VALUES (\"first\", NULL, 0.123)"));
ASSERT_EQ(1, db.exec("INSERT INTO test VALUES (\"first\", 123, NULL)"));
// Compile a SQL query
const std::string select("SELECT * FROM test");
SQLite::Statement query(db, select);
EXPECT_EQ(select, query.getQuery());
EXPECT_EQ(3, query.getColumnCount());
// Get the first non-null row
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.isColumnNull(-1), SQLite::Exception);
EXPECT_EQ(false, query.isColumnNull(0));
EXPECT_EQ(false, query.isColumnNull(1));
EXPECT_EQ(false, query.isColumnNull(2));
EXPECT_THROW(query.isColumnNull(3), SQLite::Exception);
// Get the second row with null text
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.isColumnNull(-1), SQLite::Exception);
EXPECT_EQ(true, query.isColumnNull(0));
EXPECT_EQ(false, query.isColumnNull(1));
EXPECT_EQ(false, query.isColumnNull(2));
EXPECT_THROW(query.isColumnNull(3), SQLite::Exception);
// Get the second row with null integer
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.isColumnNull(-1), SQLite::Exception);
EXPECT_EQ(false, query.isColumnNull(0));
EXPECT_EQ(true, query.isColumnNull(1));
EXPECT_EQ(false, query.isColumnNull(2));
EXPECT_THROW(query.isColumnNull(3), SQLite::Exception);
// Get the third row with null float
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.isColumnNull(-1), SQLite::Exception);
EXPECT_EQ(false, query.isColumnNull(0));
EXPECT_EQ(false, query.isColumnNull(1));
EXPECT_EQ(true, query.isColumnNull(2));
EXPECT_THROW(query.isColumnNull(3), SQLite::Exception);
}
TEST(Statement, isColumnNullByName)
{
// Create a new database
SQLite::Database db(":memory:", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
ASSERT_EQ(SQLITE_OK, db.getErrorCode());
// Create a new table
EXPECT_EQ(0, db.exec("CREATE TABLE test (msg TEXT, int INTEGER, double REAL)"));
ASSERT_EQ(SQLITE_OK, db.getErrorCode());
// Create a first row with no null values, then other rows with each time a NULL value
ASSERT_EQ(1, db.exec("INSERT INTO test VALUES (\"first\", 123, 0.123)"));
ASSERT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, 123, 0.123)"));
ASSERT_EQ(1, db.exec("INSERT INTO test VALUES (\"first\", NULL, 0.123)"));
ASSERT_EQ(1, db.exec("INSERT INTO test VALUES (\"first\", 123, NULL)"));
// Compile a SQL query
const std::string select("SELECT * FROM test");
SQLite::Statement query(db, select);
EXPECT_EQ(select, query.getQuery());
EXPECT_EQ(3, query.getColumnCount());
// Get the first non-null row
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.isColumnNull(""), SQLite::Exception);
EXPECT_EQ(false, query.isColumnNull("msg"));
EXPECT_EQ(false, query.isColumnNull("int"));
EXPECT_EQ(false, query.isColumnNull("double"));
EXPECT_THROW(query.isColumnNull(3), SQLite::Exception);
// Get the second row with null text
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.isColumnNull(""), SQLite::Exception);
EXPECT_EQ(true, query.isColumnNull("msg"));
EXPECT_EQ(false, query.isColumnNull(1));
EXPECT_EQ(false, query.isColumnNull("double"));
EXPECT_THROW(query.isColumnNull(3), SQLite::Exception);
// Get the second row with null integer
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.isColumnNull(""), SQLite::Exception);
EXPECT_EQ(false, query.isColumnNull("msg"));
EXPECT_EQ(true, query.isColumnNull("int"));
EXPECT_EQ(false, query.isColumnNull("double"));
EXPECT_THROW(query.isColumnNull(3), SQLite::Exception);
// Get the third row with null float
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.isColumnNull(""), SQLite::Exception);
EXPECT_EQ(false, query.isColumnNull("msg"));
EXPECT_EQ(false, query.isColumnNull("int"));
EXPECT_EQ(true, query.isColumnNull("double"));
EXPECT_THROW(query.isColumnNull(3), SQLite::Exception);
}
TEST(Statement, getColumnByName)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
// 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());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
// Create a first row
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\", 123, 0.123)"));
EXPECT_EQ(1, db.getLastInsertRowid());
EXPECT_EQ(1, db.getTotalChanges());
// Compile a SQL query
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(4, query.getColumnCount());
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
// Look for non-existing columns
EXPECT_THROW(query.getColumn("unknown"), SQLite::Exception);
EXPECT_THROW(query.getColumn(""), SQLite::Exception);
const std::string msg = query.getColumn("msg");
const int integer = query.getColumn("int");
const double real = query.getColumn("double");
EXPECT_EQ("first", msg);
EXPECT_EQ(123, integer);
EXPECT_EQ(0.123, real);
}
TEST(Statement, getName)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT)"));
// Compile a SQL query, using the "id" column name as-is, but aliasing the "msg" column with new name "value"
SQLite::Statement query(db, "SELECT id, msg as value FROM test");
query.executeStep();
const std::string name0 = query.getColumnName(0);
const std::string name1 = query.getColumnName(1);
EXPECT_EQ("id", name0);
EXPECT_EQ("value", name1);
#ifdef SQLITE_ENABLE_COLUMN_METADATA
// Show how to get origin names of the table columns from which theses result columns come from.
// Requires the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro to be
// also defined at compile times of the SQLite library itself.
const std::string oname0 = query.getColumnOriginName(0);
const std::string oname1 = query.getColumnOriginName(1);
EXPECT_EQ("id", oname0);
EXPECT_EQ("msg", oname1);
#endif
}
#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900)
TEST(Statement, getColumns)
{
struct GetRowTestStruct
{
int id;
std::string msg;
int integer;
double real;
GetRowTestStruct(int _id, std::string _msg, int _integer, double _real)
: id(_id), msg(_msg), integer(_integer), real(_real)
{}
GetRowTestStruct(int _id, const std::string& _msg)
: id(_id), msg(_msg), integer(-1), real(0.0)
{}
};
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
// 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());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
// Create a first row
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\", 123, 0.123)"));
EXPECT_EQ(1, db.getLastInsertRowid());
EXPECT_EQ(1, db.getTotalChanges());
// Compile a SQL query
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(4, query.getColumnCount());
query.executeStep();
EXPECT_TRUE(query.hasRow());
EXPECT_FALSE(query.isDone());
// Get all columns
auto testStruct = query.getColumns<GetRowTestStruct, 4>();
EXPECT_EQ(1, testStruct.id);
EXPECT_EQ("first", testStruct.msg);
EXPECT_EQ(123, testStruct.integer);
EXPECT_EQ(0.123, testStruct.real);
// Get only the first 2 columns
auto testStruct2 = query.getColumns<GetRowTestStruct, 2>();
EXPECT_EQ(1, testStruct2.id);
EXPECT_EQ("first", testStruct2.msg);
EXPECT_EQ(-1, testStruct2.integer);
EXPECT_EQ(0.0, testStruct2.real);
}
#endif
#if (LONG_MAX > INT_MAX) // sizeof(long)==8 means the data model of the system is LP64 (64bits Linux)
TEST(Statement, bind64bitsLong)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
SQLite::Statement query(db, "SELECT ?");
query.bind(1, 4294967297L);
query.executeStep();
EXPECT_EQ(4294967297L, query.getColumn(0).getInt64());
}
#endif
TEST(Statement, getBindParameterCount)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT)"));
SQLite::Statement query(db, "SELECT id, msg FROM test where id = ?");
EXPECT_EQ(1, query.getBindParameterCount());
SQLite::Statement query2(db, "SELECT id, msg FROM test where id = ? and msg = ?");
EXPECT_EQ(2, query2.getBindParameterCount());
SQLite::Statement query3(db, "SELECT id, msg FROM test");
EXPECT_EQ(0, query3.getBindParameterCount());
}

View File

@ -0,0 +1,104 @@
/**
* @file Transaction_test.cpp
* @ingroup tests
* @brief Test of a SQLite Transaction.
*
* Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Transaction.h>
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/Exception.h>
#include <gtest/gtest.h>
#include <cstdio>
TEST(Transaction, commitRollback)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
{
// Begin transaction
SQLite::Transaction transaction(db);
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Insert a first value
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\")"));
EXPECT_EQ(1, db.getLastInsertRowid());
// Commit transaction
transaction.commit();
// Commit again throw an exception
EXPECT_THROW(transaction.commit(), SQLite::Exception);
}
// Auto rollback if no commit() before the end of scope
{
// Begin transaction
SQLite::Transaction transaction(db);
// Insert a second value (that will be rollbacked)
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"third\")"));
EXPECT_EQ(2, db.getLastInsertRowid());
// end of scope: automatic rollback
}
// Auto rollback of a transaction on error/exception
try
{
// Begin transaction
SQLite::Transaction transaction(db);
// Insert a second value (that will be rollbacked)
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"second\")"));
EXPECT_EQ(2, db.getLastInsertRowid());
// Execute with an error => exception with auto-rollback
db.exec("DesiredSyntaxError to raise an exception to rollback the transaction");
GTEST_FATAL_FAILURE_("we should never get there");
transaction.commit(); // We should never get there
}
catch (std::exception& e)
{
std::cout << "SQLite exception: " << e.what() << std::endl;
// expected error, see above
}
// Double rollback with a manual command before the end of scope
{
// Begin transaction
SQLite::Transaction transaction(db);
// Insert a second value (that will be rollbacked)
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"third\")"));
EXPECT_EQ(2, db.getLastInsertRowid());
// Execute a manual rollback (no real use case I can think of, so no rollback() method)
db.exec("ROLLBACK");
// end of scope: the automatic rollback should not raise an error because it is harmless
}
// Check the results (expect only one row of result, as all other one have been rollbacked)
SQLite::Statement query(db, "SELECT * FROM test");
int nbRows = 0;
while (query.executeStep())
{
nbRows++;
EXPECT_EQ(1, query.getColumn(0).getInt());
EXPECT_STREQ("first", query.getColumn(1).getText());
}
EXPECT_EQ(1, nbRows);
}

View File

@ -0,0 +1,109 @@
/**
* @file VariadicBind_test.cpp
* @ingroup tests
* @brief Test of variadic bind
*
* Copyright (c) 2016 Paul Dreik (github@pauldreik.se)
* Copyright (c) 2016-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com)
* Copyright (c) 2019 Maximilian Bachmann (github@maxbachmann)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/VariadicBind.h>
#include <gtest/gtest.h>
#include <cstdio>
#if (__cplusplus >= 201103L) || ( defined(_MSC_VER) && (_MSC_VER >= 1800) ) // c++11: Visual Studio 2013
TEST(VariadicBind, invalid)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(0, db.exec("DROP TABLE IF EXISTS test"));
EXPECT_EQ(0,
db.exec(
"CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT DEFAULT 'default') "));
EXPECT_EQ(0,
db.exec(
"CREATE TABLE test2 (id INTEGER PRIMARY KEY, value TEXT DEFAULT 'default') "));
EXPECT_TRUE(db.tableExists("test"));
EXPECT_TRUE(db.tableExists("test2"));
{
SQLite::Statement query(db, "INSERT INTO test VALUES (?, ?)");
// bind one argument less than expected - should be fine.
// the unspecified argument should be set to null, not the default.
SQLite::bind(query, 1);
EXPECT_EQ(1, query.exec());
query.reset();
// bind all arguments - should work just fine
SQLite::bind(query, 2, "two");
EXPECT_EQ(1, query.exec());
query.reset();
// bind too many arguments - should throw.
EXPECT_THROW(SQLite::bind(query, 3, "three", 0), SQLite::Exception);
EXPECT_EQ(1, query.exec());
}
// make sure the content is as expected
{
SQLite::Statement query(db, std::string{"SELECT id, value FROM test ORDER BY id"});
std::vector<std::pair<int, std::string> > results;
while (query.executeStep())
{
const int id = query.getColumn(0);
std::string value = query.getColumn(1);
results.emplace_back( id, std::move(value) );
}
EXPECT_EQ(std::size_t(3), results.size());
EXPECT_EQ(std::make_pair(1,std::string{""}), results.at(0));
EXPECT_EQ(std::make_pair(2,std::string{"two"}), results.at(1));
EXPECT_EQ(std::make_pair(3,std::string{"three"}), results.at(2));
}
#if (__cplusplus >= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) ) // c++14: Visual Studio 2015
{
SQLite::Statement query(db, "INSERT INTO test2 VALUES (?, ?)");
// bind one argument less than expected - should be fine.
// the unspecified argument should be set to null, not the default.
SQLite::bind(query, std::make_tuple(1));
EXPECT_EQ(1, query.exec());
query.reset();
// bind all arguments - should work just fine
SQLite::bind(query, std::make_tuple(2, "two"));
EXPECT_EQ(1, query.exec());
query.reset();
// bind too many arguments - should throw.
EXPECT_THROW(SQLite::bind(query, std::make_tuple(3, "three", 0)), SQLite::Exception);
EXPECT_EQ(1, query.exec());
}
// make sure the content is as expected
{
SQLite::Statement query(db, std::string{"SELECT id, value FROM test2 ORDER BY id"});
std::vector<std::pair<int, std::string> > results;
while (query.executeStep())
{
const int id = query.getColumn(0);
std::string value = query.getColumn(1);
results.emplace_back( id, std::move(value) );
}
EXPECT_EQ(std::size_t(3), results.size());
EXPECT_EQ(std::make_pair(1,std::string{""}), results.at(0));
EXPECT_EQ(std::make_pair(2,std::string{"two"}), results.at(1));
EXPECT_EQ(std::make_pair(3,std::string{"three"}), results.at(2));
}
#endif // c++14
}
#endif // c++11