From 98aff920810408e73c932718bf11ed36eda5a7d1 Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Mon, 16 Mar 2020 15:26:30 +0100 Subject: [PATCH 1/3] Implemented getDeclaredType with documentation. --- include/SQLiteCpp/Statement.h | 16 ++++++++++++++++ src/Statement.cpp | 14 ++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/include/SQLiteCpp/Statement.h b/include/SQLiteCpp/Statement.h index 5d6a73c..24bf06c 100644 --- a/include/SQLiteCpp/Statement.h +++ b/include/SQLiteCpp/Statement.h @@ -643,6 +643,22 @@ public: */ int getColumnIndex(const char* apName) const; + + /** + * @brief Return the declared type of the specified result column for a SELECT statement. + * + * This is the type given at creation of the column and not the actual data type. + * SQLite stores data types dynamically for each value and not per column. + * + * @param[in] aIndex Index of the column in the range [0, getColumnCount()). + * + * Throw an exception if the specified index is out of the [0, getColumnCount()) range + * or if the current statement is not a SELECT statement. + */ + const char * getDeclaredType(const int aIndex) const; + + + //////////////////////////////////////////////////////////////////////////// /// Return the UTF-8 SQL Query. diff --git a/src/Statement.cpp b/src/Statement.cpp index c981ccb..5b28324 100644 --- a/src/Statement.cpp +++ b/src/Statement.cpp @@ -296,6 +296,20 @@ int Statement::getColumnIndex(const char* apName) const return (*iIndex).second; } +const char * Statement::getDeclaredType(const int aIndex) const +{ + checkIndex(aIndex); + const char * result = sqlite3_column_decltype(mStmtPtr, aIndex); + if (!result) + { + throw SQLite::Exception("Could not determine declared column type."); + } + else + { + return result; + } +} + int Statement::getBindParameterCount() const noexcept { return sqlite3_bind_parameter_count(mStmtPtr); From 9dee407ff04bb3cf3da33e06b8831c7e0fcb2faa Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Wed, 25 Mar 2020 16:20:10 +0100 Subject: [PATCH 2/3] Added unit tests for new function on statements. --- tests/Statement_test.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/Statement_test.cpp b/tests/Statement_test.cpp index b80b35d..6391fe3 100644 --- a/tests/Statement_test.cpp +++ b/tests/Statement_test.cpp @@ -918,6 +918,29 @@ TEST(Statement, getName) #endif } +TEST(Statement, getDeclaredType) +{ + // 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, value DOUBLE)")); + + SQLite::Statement query(db, "SELECT * FROM test"); + + const std::string decltype0 = query.getDeclaredType(0); + const std::string decltype1 = query.getDeclaredType(1); + const std::string decltype2 = query.getDeclaredType(2); + EXPECT_EQ("INTEGER", decltype0); + EXPECT_EQ("TEXT", decltype1); + EXPECT_EQ("DOUBLE", decltype2); + + // Index out of bounds. + EXPECT_THROW(query.getDeclaredType(3), SQLite::Exception); + + // Not a SELECT statement. + SQLite::Statement insert(db, "INSERT INTO test VALUES (1, 'Hello', 3.1415)"); + EXPECT_THROW(insert.getDeclaredType(0), SQLite::Exception); +} + #if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900) TEST(Statement, getColumns) { From 0c9d4a3f3694e5f2be975dfe2057442ad3588c85 Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Thu, 26 Mar 2020 09:19:27 +0100 Subject: [PATCH 3/3] Improved name of new function, documentation and tests. --- include/SQLiteCpp/Statement.h | 8 +++++--- src/Statement.cpp | 2 +- tests/Statement_test.cpp | 27 +++++++++++++++------------ 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/include/SQLiteCpp/Statement.h b/include/SQLiteCpp/Statement.h index 24bf06c..a407417 100644 --- a/include/SQLiteCpp/Statement.h +++ b/include/SQLiteCpp/Statement.h @@ -652,10 +652,12 @@ public: * * @param[in] aIndex Index of the column in the range [0, getColumnCount()). * - * Throw an exception if the specified index is out of the [0, getColumnCount()) range - * or if the current statement is not a SELECT statement. + * Throw an exception if the type can't be determined because: + * - the specified index is out of the [0, getColumnCount()) range + * - the statement is not a SELECT query + * - the column at aIndex is not a table column but an expression or subquery */ - const char * getDeclaredType(const int aIndex) const; + const char * getColumnDeclaredType(const int aIndex) const; diff --git a/src/Statement.cpp b/src/Statement.cpp index 5b28324..8ab6862 100644 --- a/src/Statement.cpp +++ b/src/Statement.cpp @@ -296,7 +296,7 @@ int Statement::getColumnIndex(const char* apName) const return (*iIndex).second; } -const char * Statement::getDeclaredType(const int aIndex) const +const char * Statement::getColumnDeclaredType(const int aIndex) const { checkIndex(aIndex); const char * result = sqlite3_column_decltype(mStmtPtr, aIndex); diff --git a/tests/Statement_test.cpp b/tests/Statement_test.cpp index 6391fe3..fbaec4b 100644 --- a/tests/Statement_test.cpp +++ b/tests/Statement_test.cpp @@ -918,27 +918,30 @@ TEST(Statement, getName) #endif } -TEST(Statement, getDeclaredType) +TEST(Statement, getColumnDeclaredType) { // 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, value DOUBLE)")); - - SQLite::Statement query(db, "SELECT * FROM test"); - - const std::string decltype0 = query.getDeclaredType(0); - const std::string decltype1 = query.getDeclaredType(1); - const std::string decltype2 = query.getDeclaredType(2); + + SQLite::Statement query(db, "SELECT *, 1 FROM test"); + + const std::string decltype0 = query.getColumnDeclaredType(0); + const std::string decltype1 = query.getColumnDeclaredType(1); + const std::string decltype2 = query.getColumnDeclaredType(2); EXPECT_EQ("INTEGER", decltype0); EXPECT_EQ("TEXT", decltype1); EXPECT_EQ("DOUBLE", decltype2); - // Index out of bounds. - EXPECT_THROW(query.getDeclaredType(3), SQLite::Exception); + // The column at index 3 is not a table column. + EXPECT_THROW(query.getColumnDeclaredType(3), SQLite::Exception); - // Not a SELECT statement. - SQLite::Statement insert(db, "INSERT INTO test VALUES (1, 'Hello', 3.1415)"); - EXPECT_THROW(insert.getDeclaredType(0), SQLite::Exception); + // Index out of bounds. + EXPECT_THROW(query.getColumnDeclaredType(4), SQLite::Exception); + + // Not a select statement. + SQLite::Statement pragma(db,"PRAGMA compile_options"); + EXPECT_THROW(pragma.getColumnDeclaredType(0), SQLite::Exception); } #if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900)