Add Statement::getColumnName(aIndex)

- enable getting names befor gettings rows of result
This commit is contained in:
Sébastien Rombauts 2015-05-03 17:21:04 +02:00
parent 078365febc
commit 8797f16d12
4 changed files with 236 additions and 190 deletions

View File

@ -140,28 +140,22 @@ int main ()
query.reset(); query.reset();
std::cout << "SQLite statement '" << query.getQuery().c_str() << "' reseted (" << query.getColumnCount() << " columns in the result)\n"; std::cout << "SQLite statement '" << query.getQuery().c_str() << "' reseted (" << query.getColumnCount() << " columns in the result)\n";
// Execute the first step of the query, to get the fist row of results, and name of columns
if (query.executeStep())
{
// Show how to get the aliased names of the result columns. // Show how to get the aliased names of the result columns.
const std::string name0 = query.getColumn(0).getName(); const std::string name0 = query.getColumnName(0);
const std::string name1 = query.getColumn(1).getName(); const std::string name1 = query.getColumnName(1);
const std::string name2 = query.getColumn(2).getName(); const std::string name2 = query.getColumnName(2);
std::cout << "aliased result [\"" << name0.c_str() << "\", \"" << name1.c_str() << "\", \"" << name2.c_str() << "\"]\n"; std::cout << "aliased result [\"" << name0.c_str() << "\", \"" << name1.c_str() << "\", \"" << name2.c_str() << "\"]\n";
#ifdef SQLITE_ENABLE_COLUMN_METADATA #ifdef SQLITE_ENABLE_COLUMN_METADATA
// Show how to get origin names of the table columns from which theses result columns come from. // 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 // Requires the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro to be
// also defined at compile times of the SQLite library itself. // also defined at compile times of the SQLite library itself.
const std::string oname0 = query.getColumn(0).getOriginName(); const std::string oname0 = query.getColumnOriginName(0);
const std::string oname1 = query.getColumn(1).getOriginName(); const std::string oname1 = query.getColumnOriginName(1);
const std::string oname2 = query.getColumn(2).getOriginName(); const std::string oname2 = query.getColumnOriginName(2);
std::cout << "origin table 'test' [\"" << oname0.c_str() << "\", \"" << oname1.c_str() << "\", \"" << oname2.c_str() << "\"]\n"; std::cout << "origin table 'test' [\"" << oname0.c_str() << "\", \"" << oname1.c_str() << "\", \"" << oname2.c_str() << "\"]\n";
#endif #endif
// Demonstrates that inserting column value in a std:ostream is natural // Loop to execute the query step by step, to get one a row of results at a time
std::cout << "row (" << query.getColumn(0) << ", \"" << query.getColumn(1) << "\", " << query.getColumn(2) << ")\n";
}
// Loop to execute the rest of the query step by step, to get one a row of results at a time
while (query.executeStep()) while (query.executeStep())
{ {
// Demonstrates that inserting column value in a std:ostream is natural // Demonstrates that inserting column value in a std:ostream is natural

View File

@ -297,7 +297,7 @@ public:
Column getColumn(const int aIndex); Column getColumn(const int aIndex);
/** /**
* @brief Return a copy of the column data specified by its column name * @brief Return a copy of the column data specified by its column name (less efficient than using an index)
* *
* Can be used to access the data of the current row of result when applicable, * Can be used to access the data of the current row of result when applicable,
* while the executeStep() method returns true. * while the executeStep() method returns true.
@ -308,9 +308,11 @@ public:
* - after the last executeStep() returned false * - after the last executeStep() returned false
* - after a reset() call * - after a reset() call
* *
* Throw an exception if the specified index is out of the [0, getColumnCount()) range. * Throw an exception if the specified name is not an on of the aliased name of the columns in the result.
* *
* @param[in] apName Name of the column, starting at index 0 * @param[in] apName Aliased name of the column, that is, the named specified in the query (not the original name)
*
* @note Uses a map of column names to indexes, build on first call.
* *
* @note This method is not const, reflecting the fact that the returned Column object will * @note This method is not const, reflecting the fact that the returned Column object will
* share the ownership of the underlying sqlite3_stmt. * share the ownership of the underlying sqlite3_stmt.
@ -329,9 +331,33 @@ public:
* @param[in] aIndex Index of the column, starting at 0 * @param[in] aIndex Index of the column, starting at 0
* *
* @return true if the column value is NULL * @return true if the column value is NULL
*
* Throw an exception if the specified index is out of the [0, getColumnCount()) range.
*/ */
bool isColumnNull(const int aIndex) const; bool isColumnNull(const int aIndex) const;
/**
* @brief Return a pointer to the named assigned to the specified result column (potentially aliased)
*
* @see getColumnOriginName() to get original column name (not aliased)
*
* Throw an exception if the specified index is out of the [0, getColumnCount()) range.
*/
const char* getColumnName(const int aIndex) const;
#ifdef SQLITE_ENABLE_COLUMN_METADATA
/**
* @brief Return a pointer to the table column name that is the origin of the specified result column
*
* Require definition of the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro :
* - when building the SQLite library itself (which is the case for the Debian libsqlite3 binary for instance),
* - and also when compiling this wrapper.
*
* Throw an exception if the specified index is out of the [0, getColumnCount()) range.
*/
const char* getColumnOriginName(const int aIndex) const;
#endif
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
/// @brief Return the UTF-8 SQL Query. /// @brief Return the UTF-8 SQL Query.
@ -423,7 +449,35 @@ private:
* *
* @param[in] SQLite return code to test against the SQLITE_OK expected value * @param[in] SQLite return code to test against the SQLITE_OK expected value
*/ */
void check(const int aRet); inline void Statement::check(const int aRet) const
{
if (SQLITE_OK != aRet)
{
throw SQLite::Exception(sqlite3_errmsg(mStmtPtr));
}
}
/**
* @brief Check if there is a row of result returnes by executeStep(), else throw a SQLite::Exception.
*/
inline void Statement::checkRow() const
{
if (false == mbOk)
{
throw SQLite::Exception("No row to get a column from. executeStep() was not called or did not returned true.");
}
}
/**
* @brief Check if there is a Column index is in the range of columns in the result.
*/
inline void Statement::checkIndex(const int aIndex) const
{
if ((aIndex < 0) || (aIndex >= mColumnCount))
{
throw SQLite::Exception("Column index out of range.");
}
}
private: private:
typedef std::map<std::string, int> TColumnNames; typedef std::map<std::string, int> TColumnNames;

View File

@ -54,7 +54,7 @@ void Statement::reset()
{ {
mbOk = false; mbOk = false;
mbDone = false; mbDone = false;
int ret = sqlite3_reset(mStmtPtr); const int ret = sqlite3_reset(mStmtPtr);
check(ret); check(ret);
} }
@ -65,56 +65,56 @@ void Statement::clearBindings(void)
{ {
mbOk = false; mbOk = false;
mbDone = false; mbDone = false;
int ret = sqlite3_clear_bindings(mStmtPtr); const int ret = sqlite3_clear_bindings(mStmtPtr);
check(ret); check(ret);
} }
// Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const int& aValue) void Statement::bind(const int aIndex, const int& aValue)
{ {
int ret = sqlite3_bind_int(mStmtPtr, aIndex, aValue); const int ret = sqlite3_bind_int(mStmtPtr, aIndex, aValue);
check(ret); check(ret);
} }
// Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const sqlite3_int64& aValue) void Statement::bind(const int aIndex, const sqlite3_int64& aValue)
{ {
int ret = sqlite3_bind_int64(mStmtPtr, aIndex, aValue); const int ret = sqlite3_bind_int64(mStmtPtr, aIndex, aValue);
check(ret); check(ret);
} }
// Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const double& aValue) void Statement::bind(const int aIndex, const double& aValue)
{ {
int ret = sqlite3_bind_double(mStmtPtr, aIndex, aValue); const int ret = sqlite3_bind_double(mStmtPtr, aIndex, aValue);
check(ret); check(ret);
} }
// Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const std::string& aValue) void Statement::bind(const int aIndex, const std::string& aValue)
{ {
int ret = sqlite3_bind_text(mStmtPtr, aIndex, aValue.c_str(), static_cast<int>(aValue.size()), SQLITE_TRANSIENT); const int ret = sqlite3_bind_text(mStmtPtr, aIndex, aValue.c_str(), static_cast<int>(aValue.size()), SQLITE_TRANSIENT);
check(ret); check(ret);
} }
// Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const char* apValue) void Statement::bind(const int aIndex, const char* apValue)
{ {
int ret = sqlite3_bind_text(mStmtPtr, aIndex, apValue, -1, SQLITE_TRANSIENT); const int ret = sqlite3_bind_text(mStmtPtr, aIndex, apValue, -1, SQLITE_TRANSIENT);
check(ret); check(ret);
} }
// Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const void* apValue, const int aSize) void Statement::bind(const int aIndex, const void* apValue, const int aSize)
{ {
int ret = sqlite3_bind_blob(mStmtPtr, aIndex, apValue, aSize, SQLITE_TRANSIENT); const int ret = sqlite3_bind_blob(mStmtPtr, aIndex, apValue, aSize, SQLITE_TRANSIENT);
check(ret); check(ret);
} }
// Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex) void Statement::bind(const int aIndex)
{ {
int ret = sqlite3_bind_null(mStmtPtr, aIndex); const int ret = sqlite3_bind_null(mStmtPtr, aIndex);
check(ret); check(ret);
} }
@ -122,56 +122,56 @@ void Statement::bind(const int aIndex)
// Bind an int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind an int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const int& aValue) void Statement::bind(const char* apName, const int& aValue)
{ {
int index = sqlite3_bind_parameter_index(mStmtPtr, apName); const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
int ret = sqlite3_bind_int(mStmtPtr, index, aValue); const int ret = sqlite3_bind_int(mStmtPtr, index, aValue);
check(ret); check(ret);
} }
// Bind a 64bits int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a 64bits int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const sqlite3_int64& aValue) void Statement::bind(const char* apName, const sqlite3_int64& aValue)
{ {
int index = sqlite3_bind_parameter_index(mStmtPtr, apName); const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
int ret = sqlite3_bind_int64(mStmtPtr, index, aValue); const int ret = sqlite3_bind_int64(mStmtPtr, index, aValue);
check(ret); check(ret);
} }
// Bind a double (64bits float) value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a double (64bits float) value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const double& aValue) void Statement::bind(const char* apName, const double& aValue)
{ {
int index = sqlite3_bind_parameter_index(mStmtPtr, apName); const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
int ret = sqlite3_bind_double(mStmtPtr, index, aValue); const int ret = sqlite3_bind_double(mStmtPtr, index, aValue);
check(ret); check(ret);
} }
// Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const std::string& aValue) void Statement::bind(const char* apName, const std::string& aValue)
{ {
int index = sqlite3_bind_parameter_index(mStmtPtr, apName); const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
int ret = sqlite3_bind_text(mStmtPtr, index, aValue.c_str(), static_cast<int>(aValue.size()), SQLITE_TRANSIENT); const int ret = sqlite3_bind_text(mStmtPtr, index, aValue.c_str(), static_cast<int>(aValue.size()), SQLITE_TRANSIENT);
check(ret); check(ret);
} }
// Bind a text value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a text value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const char* apValue) void Statement::bind(const char* apName, const char* apValue)
{ {
int index = sqlite3_bind_parameter_index(mStmtPtr, apName); const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
int ret = sqlite3_bind_text(mStmtPtr, index, apValue, -1, SQLITE_TRANSIENT); const int ret = sqlite3_bind_text(mStmtPtr, index, apValue, -1, SQLITE_TRANSIENT);
check(ret); check(ret);
} }
// Bind a binary blob value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a binary blob value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const void* apValue, const int aSize) void Statement::bind(const char* apName, const void* apValue, const int aSize)
{ {
int index = sqlite3_bind_parameter_index(mStmtPtr, apName); const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
int ret = sqlite3_bind_blob(mStmtPtr, index, apValue, aSize, SQLITE_TRANSIENT); const int ret = sqlite3_bind_blob(mStmtPtr, index, apValue, aSize, SQLITE_TRANSIENT);
check(ret); check(ret);
} }
// Bind a NULL value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a NULL value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName) void Statement::bind(const char* apName)
{ {
int index = sqlite3_bind_parameter_index(mStmtPtr, apName); const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
int ret = sqlite3_bind_null(mStmtPtr, index); const int ret = sqlite3_bind_null(mStmtPtr, index);
check(ret); check(ret);
} }
@ -181,7 +181,7 @@ bool Statement::executeStep()
{ {
if (false == mbDone) if (false == mbDone)
{ {
int ret = sqlite3_step(mStmtPtr); const int ret = sqlite3_step(mStmtPtr);
if (SQLITE_ROW == ret) // one row is ready : call getColumn(N) to access it if (SQLITE_ROW == ret) // one row is ready : call getColumn(N) to access it
{ {
mbOk = true; mbOk = true;
@ -200,7 +200,7 @@ bool Statement::executeStep()
} }
else else
{ {
throw SQLite::Exception("Statement needs to be reset"); throw SQLite::Exception("Statement needs to be reseted.");
} }
return mbOk; // true only if one row is accessible by getColumn(N) return mbOk; // true only if one row is accessible by getColumn(N)
@ -211,7 +211,7 @@ int Statement::exec()
{ {
if (false == mbDone) if (false == mbDone)
{ {
int ret = sqlite3_step(mStmtPtr); const int ret = sqlite3_step(mStmtPtr);
if (SQLITE_DONE == ret) // the statement has finished executing successfully if (SQLITE_DONE == ret) // the statement has finished executing successfully
{ {
mbOk = false; mbOk = false;
@ -221,7 +221,7 @@ int Statement::exec()
{ {
mbOk = false; mbOk = false;
mbDone = false; mbDone = false;
throw SQLite::Exception("exec() does not expect results"); throw SQLite::Exception("exec() does not expect results. Use executeStep.");
} }
else else
{ {
@ -232,7 +232,7 @@ int Statement::exec()
} }
else else
{ {
throw SQLite::Exception("Statement need to be reseted"); throw SQLite::Exception("Statement need to be reseted.");
} }
// 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)
@ -243,14 +243,8 @@ int Statement::exec()
// (use the Column copy-constructor) // (use the Column copy-constructor)
Column Statement::getColumn(const int aIndex) Column Statement::getColumn(const int aIndex)
{ {
if (false == mbOk) checkRow();
{ checkIndex(aIndex);
throw SQLite::Exception("No row to get a column from");
}
else if ((aIndex < 0) || (aIndex >= mColumnCount))
{
throw SQLite::Exception("Column index out of range");
}
// Share the Statement Object handle with the new Column created // Share the Statement Object handle with the new Column created
return Column(mStmtPtr, aIndex); return Column(mStmtPtr, aIndex);
@ -260,14 +254,8 @@ Column Statement::getColumn(const int aIndex)
// (use the Column copy-constructor) // (use the Column copy-constructor)
Column Statement::getColumn(const char* apName) Column Statement::getColumn(const char* apName)
{ {
int Index = -1; checkRow();
if (false == mbOk)
{
throw SQLite::Exception("No row to get a column from");
}
else
{
if (mColumnNames.empty()) if (mColumnNames.empty())
{ {
for (int i = 0; i < mColumnCount; ++i) for (int i = 0; i < mColumnCount; ++i)
@ -278,44 +266,38 @@ Column Statement::getColumn(const char* apName)
} }
const TColumnNames::const_iterator iIndex = mColumnNames.find(apName); const TColumnNames::const_iterator iIndex = mColumnNames.find(apName);
if (iIndex != mColumnNames.end()) if (iIndex == mColumnNames.end())
{ {
Index = (*iIndex).second; throw SQLite::Exception("Unknown column name.");
}
else
{
throw SQLite::Exception("Column index out of range");
}
} }
// Share the Statement Object handle with the new Column created // Share the Statement Object handle with the new Column created
return Column(mStmtPtr, Index); return Column(mStmtPtr, (*iIndex).second);
} }
// Test if the column is NULL // Test if the column is NULL
bool Statement::isColumnNull(const int aIndex) const bool Statement::isColumnNull(const int aIndex) const
{ {
if (false == mbOk) checkRow();
{ checkIndex(aIndex);
throw SQLite::Exception("No row to get a column from");
}
else if ((aIndex < 0) || (aIndex >= mColumnCount))
{
throw SQLite::Exception("Column index out of range");
}
return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, aIndex)); return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, aIndex));
} }
// Check if aRet equal SQLITE_OK, else throw a SQLite::Exception with the SQLite error message // Return the named assigned to the specified result column (potentially aliased)
void Statement::check(const int aRet) const char* Statement::getColumnName(const int aIndex) const
{ {
if (SQLITE_OK != aRet) checkIndex(aIndex);
{ return sqlite3_column_name(mStmtPtr, aIndex);
throw SQLite::Exception(sqlite3_errmsg(mStmtPtr));
}
} }
#ifdef SQLITE_ENABLE_COLUMN_METADATA
// Return the named assigned to the specified result column (potentially aliased)
const char* Statement::getColumnOriginName(const int aIndex) const
{
checkIndex(aIndex);
return sqlite3_column_origin_name(mStmtPtr, aIndex);
}
#endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Internal class : shared pointer to the sqlite3_stmt SQLite Statement Object // Internal class : shared pointer to the sqlite3_stmt SQLite Statement Object
@ -332,7 +314,7 @@ Statement::Ptr::Ptr(sqlite3* apSQLite, std::string& aQuery) :
mpStmt(NULL), mpStmt(NULL),
mpRefCount(NULL) mpRefCount(NULL)
{ {
int ret = sqlite3_prepare_v2(apSQLite, aQuery.c_str(), static_cast<int>(aQuery.size()), &mpStmt, NULL); const int ret = sqlite3_prepare_v2(apSQLite, aQuery.c_str(), static_cast<int>(aQuery.size()), &mpStmt, NULL);
if (SQLITE_OK != ret) if (SQLITE_OK != ret)
{ {
throw SQLite::Exception(sqlite3_errmsg(mpSQLite)); throw SQLite::Exception(sqlite3_errmsg(mpSQLite));

View File

@ -18,10 +18,8 @@
TEST(Statement, invalid) { TEST(Statement, invalid) {
remove("test.db3");
{
// Create a new database // Create a new database
SQLite::Database db("test.db3", SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); SQLite::Database db(":memory:", SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
EXPECT_EQ(SQLITE_OK, db.getErrorCode()); EXPECT_EQ(SQLITE_OK, db.getErrorCode());
EXPECT_EQ(SQLITE_OK, db.getExtendedErrorCode()); EXPECT_EQ(SQLITE_OK, db.getExtendedErrorCode());
@ -84,17 +82,13 @@ TEST(Statement, invalid) {
EXPECT_FALSE(query.isDone()); EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.exec(), SQLite::Exception); // exec() shall throw as it does not expect a result EXPECT_THROW(query.exec(), SQLite::Exception); // exec() shall throw as it does not expect a result
} // Close DB test.db3
remove("test.db3");
} }
// TODO: test every kind of binding
TEST(Statement, getColumnByName) { TEST(Statement, getColumnByName) {
remove("test.db3");
{
// Create a new database // Create a new database
SQLite::Database db("test.db3", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); SQLite::Database db(":memory:", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
EXPECT_EQ(SQLITE_OK, db.getErrorCode()); EXPECT_EQ(SQLITE_OK, db.getErrorCode());
EXPECT_EQ(SQLITE_OK, db.getExtendedErrorCode()); EXPECT_EQ(SQLITE_OK, db.getExtendedErrorCode());
@ -126,7 +120,29 @@ TEST(Statement, getColumnByName) {
EXPECT_EQ("first", msg); EXPECT_EQ("first", msg);
EXPECT_EQ(123, integer); EXPECT_EQ(123, integer);
EXPECT_EQ(0.123, real); EXPECT_EQ(0.123, real);
}
} // Close DB test.db3
remove("test.db3"); 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
} }