diff --git a/Data/SQLite/include/Poco/Data/SQLite/Utility.h b/Data/SQLite/include/Poco/Data/SQLite/Utility.h index 0c349f14b..4758e2f13 100644 --- a/Data/SQLite/include/Poco/Data/SQLite/Utility.h +++ b/Data/SQLite/include/Poco/Data/SQLite/Utility.h @@ -42,6 +42,8 @@ #include "Poco/Data/SQLite/SQLite.h" #include "Poco/Data/MetaColumn.h" +#include "Poco/Mutex.h" +#include struct sqlite3; @@ -59,6 +61,15 @@ class SQLite_API Utility public: static const std::string SQLITE_DATE_FORMAT; static const std::string SQLITE_TIME_FORMAT; + typedef std::map TypeMap; + + Utility(); + /// Maps SQLite column declared types to Poco::Data types through + /// static TypeMap member. + /// Note: SQLite is type-agnostic and it is the end-user responsibility + /// to ensure that column declared data type corresponds to the type of + /// data actually held in the database. + /// Column types are case-insensitive. static std::string lastError(sqlite3* pDb); /// Retreives the last error code from sqlite and converts it to a string @@ -68,6 +79,10 @@ public: static MetaColumn::ColumnDataType getColumnType(sqlite3_stmt* pStmt, std::size_t pos); /// Returns column data type. + +private: + static TypeMap _types; + Poco::FastMutex _mutex; }; diff --git a/Data/SQLite/src/Utility.cpp b/Data/SQLite/src/Utility.cpp index 7b3813182..90bd5bf47 100644 --- a/Data/SQLite/src/Utility.cpp +++ b/Data/SQLite/src/Utility.cpp @@ -51,6 +51,66 @@ namespace SQLite { const std::string Utility::SQLITE_DATE_FORMAT = "%Y-%m-%d"; const std::string Utility::SQLITE_TIME_FORMAT = "%H:%M:%S"; +Utility::TypeMap Utility::_types; + + +Utility::Utility() +{ + Poco::FastMutex::ScopedLock l(_mutex); + + if (_types.empty()) + { + _types.insert(TypeMap::value_type("", MetaColumn::FDT_STRING)); + _types.insert(TypeMap::value_type("BOOL", MetaColumn::FDT_BOOL)); + _types.insert(TypeMap::value_type("BOOLEAN", MetaColumn::FDT_BOOL)); + _types.insert(TypeMap::value_type("BIT", MetaColumn::FDT_BOOL)); + _types.insert(TypeMap::value_type("UINT8", MetaColumn::FDT_UINT8)); + _types.insert(TypeMap::value_type("UTINY", MetaColumn::FDT_UINT8)); + _types.insert(TypeMap::value_type("UINTEGER8", MetaColumn::FDT_UINT8)); + _types.insert(TypeMap::value_type("INT8", MetaColumn::FDT_INT8)); + _types.insert(TypeMap::value_type("TINY", MetaColumn::FDT_INT8)); + _types.insert(TypeMap::value_type("INTEGER8", MetaColumn::FDT_INT8)); + _types.insert(TypeMap::value_type("UINT16", MetaColumn::FDT_UINT16)); + _types.insert(TypeMap::value_type("USHORT", MetaColumn::FDT_UINT16)); + _types.insert(TypeMap::value_type("UINTEGER16", MetaColumn::FDT_UINT16)); + _types.insert(TypeMap::value_type("INT16", MetaColumn::FDT_INT16)); + _types.insert(TypeMap::value_type("SHORT", MetaColumn::FDT_INT16)); + _types.insert(TypeMap::value_type("INTEGER16", MetaColumn::FDT_INT16)); + _types.insert(TypeMap::value_type("UINT", MetaColumn::FDT_UINT32)); + _types.insert(TypeMap::value_type("UINT32", MetaColumn::FDT_UINT32)); + _types.insert(TypeMap::value_type("UINTEGER32", MetaColumn::FDT_UINT32)); + _types.insert(TypeMap::value_type("INT", MetaColumn::FDT_INT32)); + _types.insert(TypeMap::value_type("INT32", MetaColumn::FDT_INT32)); + _types.insert(TypeMap::value_type("INTEGER", MetaColumn::FDT_INT32)); + _types.insert(TypeMap::value_type("INTEGER32", MetaColumn::FDT_INT32)); + _types.insert(TypeMap::value_type("UINT64", MetaColumn::FDT_UINT64)); + _types.insert(TypeMap::value_type("ULONG", MetaColumn::FDT_INT64)); + _types.insert(TypeMap::value_type("UINTEGER64", MetaColumn::FDT_UINT64)); + _types.insert(TypeMap::value_type("INT64", MetaColumn::FDT_INT64)); + _types.insert(TypeMap::value_type("LONG", MetaColumn::FDT_INT64)); + _types.insert(TypeMap::value_type("INTEGER64", MetaColumn::FDT_INT64)); + _types.insert(TypeMap::value_type("COUNTER", MetaColumn::FDT_UINT64)); + _types.insert(TypeMap::value_type("AUTOINCREMENT", MetaColumn::FDT_UINT64)); + _types.insert(TypeMap::value_type("REAL", MetaColumn::FDT_DOUBLE)); + _types.insert(TypeMap::value_type("FLOA", MetaColumn::FDT_DOUBLE)); + _types.insert(TypeMap::value_type("FLOAT", MetaColumn::FDT_DOUBLE)); + _types.insert(TypeMap::value_type("DOUB", MetaColumn::FDT_DOUBLE)); + _types.insert(TypeMap::value_type("DOUBLE", MetaColumn::FDT_DOUBLE)); + _types.insert(TypeMap::value_type("CHAR", MetaColumn::FDT_STRING)); + _types.insert(TypeMap::value_type("CLOB", MetaColumn::FDT_STRING)); + _types.insert(TypeMap::value_type("TEXT", MetaColumn::FDT_STRING)); + _types.insert(TypeMap::value_type("VARCHAR", MetaColumn::FDT_STRING)); + _types.insert(TypeMap::value_type("NCHAR", MetaColumn::FDT_STRING)); + _types.insert(TypeMap::value_type("NCLOB", MetaColumn::FDT_STRING)); + _types.insert(TypeMap::value_type("NTEXT", MetaColumn::FDT_STRING)); + _types.insert(TypeMap::value_type("NVARCHAR", MetaColumn::FDT_STRING)); + _types.insert(TypeMap::value_type("BLOB", MetaColumn::FDT_BLOB)); + _types.insert(TypeMap::value_type("DATE", MetaColumn::FDT_DATE)); + _types.insert(TypeMap::value_type("TIME", MetaColumn::FDT_TIME)); + _types.insert(TypeMap::value_type("DATETIME", MetaColumn::FDT_TIMESTAMP)); + _types.insert(TypeMap::value_type("TIMESTAMP", MetaColumn::FDT_TIMESTAMP)); + } +} std::string Utility::lastError(sqlite3 *pDB) @@ -63,27 +123,17 @@ MetaColumn::ColumnDataType Utility::getColumnType(sqlite3_stmt* pStmt, std::size { poco_assert_dbg (pStmt); + static Utility u; + const char* pc = sqlite3_column_decltype(pStmt, (int) pos); std::string sqliteType = pc ? pc : ""; Poco::toUpperInPlace(sqliteType); - - if (sqliteType.npos != sqliteType.find("INT")) - return MetaColumn::FDT_INT64; - else if (sqliteType.empty() || - sqliteType.npos != sqliteType.find("CHAR") || - sqliteType.npos != sqliteType.find("CLOB") || - sqliteType.npos != sqliteType.find("TEXT")) - return MetaColumn::FDT_STRING; - else if (sqliteType.npos != sqliteType.find("REAL") || - sqliteType.npos != sqliteType.find("FLOA") || - sqliteType.npos != sqliteType.find("DOUB")) - return MetaColumn::FDT_DOUBLE; - else if (sqliteType.npos != sqliteType.find("BLOB")) - return MetaColumn::FDT_BLOB; - else if (sqliteType.npos != sqliteType.find("DATE")) - return MetaColumn::FDT_TIMESTAMP; + sqliteType = sqliteType.substr(0, sqliteType.find_first_of(" (")); - throw Poco::NotFoundException(); + TypeMap::const_iterator it = _types.find(Poco::trimInPlace(sqliteType)); + if (_types.end() == it) throw Poco::NotFoundException(); + + return it->second; } diff --git a/Data/SQLite/testsuite/src/SQLiteTest.cpp b/Data/SQLite/testsuite/src/SQLiteTest.cpp index be6736738..d489e74b2 100644 --- a/Data/SQLite/testsuite/src/SQLiteTest.cpp +++ b/Data/SQLite/testsuite/src/SQLiteTest.cpp @@ -89,7 +89,7 @@ using Poco::NotFoundException; using Poco::NullPointerException; using Poco::Data::SQLite::ConstraintViolationException; using Poco::Data::SQLite::ParameterCountMismatchException; -using Poco::Int64; +using Poco::Int32; struct Person @@ -1759,13 +1759,13 @@ void SQLiteTest::testInternalExtraction() assert (3 == rset2.columnCount()); assert (4 == rset2.rowCount()); - Int64 a = rset.value(0,2); + Int32 a = rset.value(0,2); assert (3 == a); int c = rset2.value(0); assert (1 == c); - Int64 b = rset2.value("InT0",2); + Int32 b = rset2.value("InT0",2); assert (3 == b); double d = rset.value(1,0); @@ -1774,7 +1774,7 @@ void SQLiteTest::testInternalExtraction() std::string s = rset.value(2,1); assert ("4" == s); - typedef std::deque IntDeq; + typedef std::deque IntDeq; const Column& col = rset.column(0); assert (col[0] == 1); @@ -2024,7 +2024,7 @@ void SQLiteTest::testAny() tmp << "DROP TABLE IF EXISTS Anys", now; tmp << "CREATE TABLE Anys (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now; - Any i = Int64(42); + Any i = Int32(42); Any f = double(42.5); Any s = std::string("42"); @@ -2038,7 +2038,7 @@ void SQLiteTest::testAny() f = 0.0; s = std::string(""); tmp << "SELECT * FROM Anys", into(i), into(f), into(s), now; - assert (AnyCast(i) == 42); + assert (AnyCast(i) == 42); assert (AnyCast(f) == 42.5); assert (AnyCast(s) == "42"); } @@ -2050,7 +2050,7 @@ void SQLiteTest::testDynamicAny() tmp << "DROP TABLE IF EXISTS Anys", now; tmp << "CREATE TABLE Anys (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now; - DynamicAny i = Int64(42); + DynamicAny i = Int32(42); DynamicAny f = double(42.5); DynamicAny s = std::string("42");