From e7ac6e383c1a75021023a0e590d0a8b6308969b7 Mon Sep 17 00:00:00 2001 From: Aleksandar Fabijanic Date: Wed, 31 Oct 2007 01:29:21 +0000 Subject: [PATCH] Any and DynamicAny binding/extraction --- Data/ODBC/include/Poco/Data/ODBC/Binder.h | 27 +++- Data/ODBC/include/Poco/Data/ODBC/Extractor.h | 67 +++++++++ .../ODBC/include/Poco/Data/ODBC/Preparation.h | 20 +++ Data/ODBC/src/Extractor.cpp | 65 +++------ Data/ODBC/src/Preparation.cpp | 14 +- Data/ODBC/testsuite/src/ODBCDB2Test.cpp | 43 ++++++ Data/ODBC/testsuite/src/ODBCDB2Test.h | 4 + Data/ODBC/testsuite/src/ODBCOracleTest.cpp | 43 ++++++ Data/ODBC/testsuite/src/ODBCOracleTest.h | 4 + .../ODBC/testsuite/src/ODBCPostgreSQLTest.cpp | 43 ++++++ Data/ODBC/testsuite/src/ODBCPostgreSQLTest.h | 4 + Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp | 43 ++++++ Data/ODBC/testsuite/src/ODBCSQLServerTest.h | 4 + Data/ODBC/testsuite/src/ODBCSQLiteTest.cpp | 43 ++++++ Data/ODBC/testsuite/src/ODBCSQLiteTest.h | 4 + Data/ODBC/testsuite/src/SQLExecutor.cpp | 48 +++++++ Data/ODBC/testsuite/src/SQLExecutor.h | 3 + Data/SQLite/include/Poco/Data/SQLite/Binder.h | 15 +++ .../include/Poco/Data/SQLite/Extractor.h | 127 ++++++++++++++++++ Data/SQLite/src/Extractor.cpp | 116 +++------------- Data/SQLite/testsuite/src/SQLiteTest.cpp | 55 ++++++++ Data/SQLite/testsuite/src/SQLiteTest.h | 3 + Data/include/Poco/Data/AbstractBinder.h | 13 ++ Data/include/Poco/Data/AbstractExtractor.h | 13 ++ Data/include/Poco/Data/AbstractPreparation.h | 9 ++ Data/include/Poco/Data/BLOB.h | 5 + Data/src/AbstractBinder.cpp | 92 +++++++++++++ Data/src/RecordSet.cpp | 5 +- 28 files changed, 773 insertions(+), 159 deletions(-) diff --git a/Data/ODBC/include/Poco/Data/ODBC/Binder.h b/Data/ODBC/include/Poco/Data/ODBC/Binder.h index d678cae1f..f16b33c9b 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/Binder.h +++ b/Data/ODBC/include/Poco/Data/ODBC/Binder.h @@ -110,6 +110,11 @@ public: void bind(std::size_t pos, const Poco::UInt64& val, Direction dir = PD_IN); /// Binds an UInt64. +#ifndef POCO_LONG_IS_64_BIT + void bind(std::size_t pos, const long& val, Direction dir = PD_IN); + /// Binds a long. +#endif + void bind(std::size_t pos, const bool& val, Direction dir = PD_IN); /// Binds a boolean. @@ -205,13 +210,13 @@ private: /// For in-bound purposes only. const StatementHandle& _rStmt; - LengthVec _lengthIndicator; - ParamMap _inParams; - ParamMap _outParams; - ParameterBinding _paramBinding; - TimestampMap _timestamps; - StringMap _strings; - const TypeInfo* _pTypeInfo; + LengthVec _lengthIndicator; + ParamMap _inParams; + ParamMap _outParams; + ParameterBinding _paramBinding; + TimestampMap _timestamps; + StringMap _strings; + const TypeInfo* _pTypeInfo; }; @@ -266,6 +271,14 @@ inline void Binder::bind(std::size_t pos, const Poco::UInt64& val, Direction dir } +#ifndef POCO_LONG_IS_64_BIT +inline void Binder::bind(std::size_t pos, const long& val, Direction dir) +{ + bindImpl(pos, val, SQL_C_SLONG, dir); +} +#endif + + inline void Binder::bind(std::size_t pos, const float& val, Direction dir) { bindImpl(pos, val, SQL_C_FLOAT, dir); diff --git a/Data/ODBC/include/Poco/Data/ODBC/Extractor.h b/Data/ODBC/include/Poco/Data/ODBC/Extractor.h index 78f932848..807fe49d2 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/Extractor.h +++ b/Data/ODBC/include/Poco/Data/ODBC/Extractor.h @@ -48,6 +48,7 @@ #include "Poco/Data/ODBC/Utility.h" #include "Poco/DateTime.h" #include "Poco/Any.h" +#include "Poco/DynamicAny.h" #include "Poco/Exception.h" #include #ifdef POCO_OS_FAMILY_WINDOWS @@ -97,6 +98,11 @@ public: bool extract(std::size_t pos, Poco::UInt64& val); /// Extracts an UInt64. +#ifndef POCO_LONG_IS_64_BIT + bool extract(std::size_t pos, long& val); + /// Extracts a long. +#endif + bool extract(std::size_t pos, bool& val); /// Extracts a boolean. @@ -121,6 +127,9 @@ public: bool extract(std::size_t pos, Poco::Any& val); /// Extracts an Any. + bool extract(std::size_t pos, Poco::DynamicAny& val); + /// Extracts a DynamicAny. + void setDataExtraction(Preparation::DataExtraction ext); /// Set data extraction mode. @@ -158,6 +167,7 @@ private: if (isNull(pos)) return false; poco_assert (typeid(T) == _rPreparation[pos].type()); + val = *AnyCast(&_rPreparation[pos]); return true; } @@ -193,6 +203,63 @@ private: return true; } + template + bool extractImpl(std::size_t pos, T& val) + /// Utility function for extraction of Any and DynamicAny. + { + ODBCColumn column(_rStmt, pos); + + switch (column.type()) + { + case MetaColumn::FDT_INT8: + { Poco::Int8 i = 0; extract(pos, i); val = i; return true; } + + case MetaColumn::FDT_UINT8: + { Poco::UInt8 i = 0; extract(pos, i); val = i; return true; } + + case MetaColumn::FDT_INT16: + { Poco::Int16 i = 0; extract(pos, i); val = i; return true; } + + case MetaColumn::FDT_UINT16: + { Poco::UInt16 i = 0; extract(pos, i); val = i; return true; } + + case MetaColumn::FDT_INT32: + { Poco::Int32 i = 0; extract(pos, i); val = i; return true; } + + case MetaColumn::FDT_UINT32: + { Poco::UInt32 i = 0; extract(pos, i); val = i; return true; } + + case MetaColumn::FDT_INT64: + { Poco::Int64 i = 0; extract(pos, i); val = i; return true; } + + case MetaColumn::FDT_UINT64: + { Poco::UInt64 i = 0; extract(pos, i); val = i; return true; } + + case MetaColumn::FDT_BOOL: + { bool b; extract(pos, b); val = b; return true; } + + case MetaColumn::FDT_FLOAT: + { float f; extract(pos, f); val = f; return true; } + + case MetaColumn::FDT_DOUBLE: + { double d; extract(pos, d); val = d; return true; } + + case MetaColumn::FDT_STRING: + { std::string s; extract(pos, s); val = s; return true; } + + case MetaColumn::FDT_BLOB: + { Poco::Data::BLOB b; extract(pos, b); val = b; return true; } + + case MetaColumn::FDT_TIMESTAMP: + { Poco::DateTime b; extract(pos, b); val = b; return true; } + + default: + throw DataFormatException("Unsupported data type."); + } + + return false; + } + bool isNullLengthIndicator(SQLLEN val) const; /// The reason for this utility wrapper are platforms where /// SQLLEN macro (a.k.a. SQLINTEGER) yields 64-bit value, diff --git a/Data/ODBC/include/Poco/Data/ODBC/Preparation.h b/Data/ODBC/include/Poco/Data/ODBC/Preparation.h index 07fa4e5f3..c35f872d9 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/Preparation.h +++ b/Data/ODBC/include/Poco/Data/ODBC/Preparation.h @@ -47,6 +47,7 @@ #include "Poco/Data/AbstractPreparation.h" #include "Poco/Data/BLOB.h" #include "Poco/Any.h" +#include "Poco/DynamicAny.h" #include "Poco/DateTime.h" #include "Poco/SharedPtr.h" #include @@ -126,6 +127,11 @@ public: void prepare(std::size_t pos, Poco::UInt64); /// Prepares an UInt64. +#ifndef POCO_LONG_IS_64_BIT + void prepare(std::size_t pos, long); + /// Prepares a long. +#endif + void prepare(std::size_t pos, bool); /// Prepares a boolean. @@ -150,6 +156,9 @@ public: void prepare(std::size_t pos, const Poco::Any&); /// Prepares an Any. + void prepare(std::size_t pos, const Poco::DynamicAny&); + /// Prepares a DynamicAny. + std::size_t columns() const; /// Returns the number of columns. /// Resizes the internal storage iff the size is zero. @@ -181,6 +190,9 @@ public: /// Returns data extraction mode. private: + void prepareImpl(std::size_t pos); + /// Utility function to prepare Any and DynamicAny + template void preparePOD(std::size_t pos, SQLSMALLINT valueType) { @@ -293,6 +305,14 @@ inline void Preparation::prepare(std::size_t pos, Poco::UInt64) } +#ifndef POCO_LONG_IS_64_BIT +inline void Preparation::prepare(std::size_t pos, long) +{ + preparePOD(pos, SQL_C_SLONG); +} +#endif + + inline void Preparation::prepare(std::size_t pos, bool) { preparePOD(pos, SQL_C_BIT); diff --git a/Data/ODBC/src/Extractor.cpp b/Data/ODBC/src/Extractor.cpp index d8f02507f..76c8ca4a0 100644 --- a/Data/ODBC/src/Extractor.cpp +++ b/Data/ODBC/src/Extractor.cpp @@ -265,6 +265,17 @@ bool Extractor::extract(std::size_t pos, Poco::Int64& val) } +#ifndef POCO_LONG_IS_64_BIT +bool Extractor::extract(std::size_t pos, long& val) +{ + if (Preparation::DE_MANUAL == _dataExtraction) + return extractManualImpl(pos, val, SQL_C_SLONG); + else + return extractBoundImpl(pos, val); +} +#endif + + bool Extractor::extract(std::size_t pos, double& val) { if (Preparation::DE_MANUAL == _dataExtraction) @@ -384,57 +395,13 @@ bool Extractor::extract(std::size_t pos, char& val) bool Extractor::extract(std::size_t pos, Poco::Any& val) { - ODBCColumn column(_rStmt, pos); + return extractImpl(pos, val); +} - switch (column.type()) - { - case MetaColumn::FDT_INT8: - { Poco::Int8 i = 0; extract(pos, i); val = i; return true; } - case MetaColumn::FDT_UINT8: - { Poco::UInt8 i = 0; extract(pos, i); val = i; return true; } - - case MetaColumn::FDT_INT16: - { Poco::Int16 i = 0; extract(pos, i); val = i; return true; } - - case MetaColumn::FDT_UINT16: - { Poco::UInt16 i = 0; extract(pos, i); val = i; return true; } - - case MetaColumn::FDT_INT32: - { Poco::Int32 i = 0; extract(pos, i); val = i; return true; } - - case MetaColumn::FDT_UINT32: - { Poco::UInt32 i = 0; extract(pos, i); val = i; return true; } - - case MetaColumn::FDT_INT64: - { Poco::Int64 i = 0; extract(pos, i); val = i; return true; } - - case MetaColumn::FDT_UINT64: - { Poco::UInt64 i = 0; extract(pos, i); val = i; return true; } - - case MetaColumn::FDT_BOOL: - { bool b; extract(pos, b); val = b; return true; } - - case MetaColumn::FDT_FLOAT: - { float f; extract(pos, f); val = f; return true; } - - case MetaColumn::FDT_DOUBLE: - { double d; extract(pos, d); val = d; return true; } - - case MetaColumn::FDT_STRING: - { std::string s; extract(pos, s); val = s; return true; } - - case MetaColumn::FDT_BLOB: - { Poco::Data::BLOB b; extract(pos, b); val = b; return true; } - - case MetaColumn::FDT_TIMESTAMP: - { Poco::DateTime b; extract(pos, b); val = b; return true; } - - default: - throw DataFormatException("Unsupported data type."); - } - - return false; +bool Extractor::extract(std::size_t pos, Poco::DynamicAny& val) +{ + return extractImpl(pos, val); } diff --git a/Data/ODBC/src/Preparation.cpp b/Data/ODBC/src/Preparation.cpp index ccfa1a19b..876a90b1b 100644 --- a/Data/ODBC/src/Preparation.cpp +++ b/Data/ODBC/src/Preparation.cpp @@ -95,6 +95,18 @@ Poco::Any& Preparation::operator [] (std::size_t pos) void Preparation::prepare(std::size_t pos, const Poco::Any&) +{ + prepareImpl(pos); +} + + +void Preparation::prepare(std::size_t pos, const Poco::DynamicAny&) +{ + prepareImpl(pos); +} + + +void Preparation::prepareImpl(std::size_t pos) { ODBCColumn col(_rStmt, pos); @@ -131,7 +143,7 @@ void Preparation::prepare(std::size_t pos, const Poco::Any&) return preparePOD(pos, SQL_C_FLOAT); case MetaColumn::FDT_DOUBLE: - return preparePOD(pos, SQL_C_DOUBLE); + return preparePOD(pos, SQL_C_DOUBLE); case MetaColumn::FDT_STRING: return prepareRaw(pos, SQL_C_CHAR, maxDataSize(pos)); diff --git a/Data/ODBC/testsuite/src/ODBCDB2Test.cpp b/Data/ODBC/testsuite/src/ODBCDB2Test.cpp index f9009230b..97870a272 100644 --- a/Data/ODBC/testsuite/src/ODBCDB2Test.cpp +++ b/Data/ODBC/testsuite/src/ODBCDB2Test.cpp @@ -1082,6 +1082,38 @@ void ODBCDB2Test::testAsync() } +void ODBCDB2Test::testAny() +{ + if (!_pSession) fail ("Test not available."); + + for (int i = 0; i < 8;) + { + recreateAnysTable(); + _pSession->setFeature("autoBind", bindValues[i]); + _pSession->setFeature("autoExtract", bindValues[i+1]); + _pExecutor->any(); + + i += 2; + } +} + + +void ODBCDB2Test::testDynamicAny() +{ + if (!_pSession) fail ("Test not available."); + + for (int i = 0; i < 8;) + { + recreateAnysTable(); + _pSession->setFeature("autoBind", bindValues[i]); + _pSession->setFeature("autoExtract", bindValues[i+1]); + _pExecutor->dynamicAny(); + + i += 2; + } +} + + void ODBCDB2Test::dropObject(const std::string& type, const std::string& name) { try @@ -1182,6 +1214,15 @@ void ODBCDB2Test::recreateVectorsTable() } +void ODBCDB2Test::recreateAnysTable() +{ + dropObject("TABLE", "Anys"); + try { *_pSession << "CREATE TABLE Anys (i0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; } + catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); } + catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); } +} + + void ODBCDB2Test::recreateNullsTable(const std::string& notNull) { dropObject("TABLE", "NullTest"); @@ -1338,6 +1379,8 @@ CppUnit::Test* ODBCDB2Test::suite() CppUnit_addTest(pSuite, ODBCDB2Test, testNull); CppUnit_addTest(pSuite, ODBCDB2Test, testRowIterator); CppUnit_addTest(pSuite, ODBCDB2Test, testAsync); + CppUnit_addTest(pSuite, ODBCDB2Test, testAny); + CppUnit_addTest(pSuite, ODBCDB2Test, testDynamicAny); return pSuite; } diff --git a/Data/ODBC/testsuite/src/ODBCDB2Test.h b/Data/ODBC/testsuite/src/ODBCDB2Test.h index fed542333..24e6f9b03 100644 --- a/Data/ODBC/testsuite/src/ODBCDB2Test.h +++ b/Data/ODBC/testsuite/src/ODBCDB2Test.h @@ -127,6 +127,9 @@ public: void testAsync(); + void testAny(); + void testDynamicAny(); + void setUp(); void tearDown(); @@ -146,6 +149,7 @@ private: void recreateFloatsTable(); void recreateTuplesTable(); void recreateVectorsTable(); + void recreateAnysTable(); void recreateNullsTable(const std::string& notNull = ""); static bool init(const std::string& driver, const std::string& dsn); diff --git a/Data/ODBC/testsuite/src/ODBCOracleTest.cpp b/Data/ODBC/testsuite/src/ODBCOracleTest.cpp index 7c9e0ea69..ffee9bfec 100644 --- a/Data/ODBC/testsuite/src/ODBCOracleTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCOracleTest.cpp @@ -1175,6 +1175,38 @@ void ODBCOracleTest::testAsync() } +void ODBCOracleTest::testAny() +{ + if (!_pSession) fail ("Test not available."); + + for (int i = 0; i < 8;) + { + recreateAnysTable(); + _pSession->setFeature("autoBind", bindValues[i]); + _pSession->setFeature("autoExtract", bindValues[i+1]); + _pExecutor->any(); + + i += 2; + } +} + + +void ODBCOracleTest::testDynamicAny() +{ + if (!_pSession) fail ("Test not available."); + + for (int i = 0; i < 8;) + { + recreateAnysTable(); + _pSession->setFeature("autoBind", bindValues[i]); + _pSession->setFeature("autoExtract", bindValues[i+1]); + _pExecutor->dynamicAny(); + + i += 2; + } +} + + void ODBCOracleTest::dropObject(const std::string& type, const std::string& name) { try @@ -1276,6 +1308,15 @@ void ODBCOracleTest::recreateVectorsTable() } +void ODBCOracleTest::recreateAnysTable() +{ + dropObject("TABLE", "Anys"); + try { *_pSession << "CREATE TABLE Anys (int0 INTEGER, flt0 NUMBER, str0 VARCHAR(30))", now; } + catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); } + catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); } +} + + void ODBCOracleTest::recreateNullsTable(const std::string& notNull) { dropObject("TABLE", "NullTest"); @@ -1466,6 +1507,8 @@ CppUnit::Test* ODBCOracleTest::suite() CppUnit_addTest(pSuite, ODBCOracleTest, testNull); CppUnit_addTest(pSuite, ODBCOracleTest, testRowIterator); CppUnit_addTest(pSuite, ODBCOracleTest, testAsync); + CppUnit_addTest(pSuite, ODBCOracleTest, testAny); + CppUnit_addTest(pSuite, ODBCOracleTest, testDynamicAny); return pSuite; } diff --git a/Data/ODBC/testsuite/src/ODBCOracleTest.h b/Data/ODBC/testsuite/src/ODBCOracleTest.h index d98df5e98..19e03ec6c 100644 --- a/Data/ODBC/testsuite/src/ODBCOracleTest.h +++ b/Data/ODBC/testsuite/src/ODBCOracleTest.h @@ -127,6 +127,9 @@ public: void testAsync(); + void testAny(); + void testDynamicAny(); + void setUp(); void tearDown(); @@ -148,6 +151,7 @@ private: void recreateFloatsTable(); void recreateTuplesTable(); void recreateVectorsTable(); + void recreateAnysTable(); void recreateNullsTable(const std::string& notNull = ""); static bool init(const std::string& driver, const std::string& dsn); diff --git a/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp b/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp index 0f42ecee0..5f607ac1d 100644 --- a/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp @@ -1009,6 +1009,38 @@ void ODBCPostgreSQLTest::testAsync() } +void ODBCPostgreSQLTest::testAny() +{ + if (!_pSession) fail ("Test not available."); + + for (int i = 0; i < 8;) + { + recreateAnysTable(); + _pSession->setFeature("autoBind", bindValues[i]); + _pSession->setFeature("autoExtract", bindValues[i+1]); + _pExecutor->any(); + + i += 2; + } +} + + +void ODBCPostgreSQLTest::testDynamicAny() +{ + if (!_pSession) fail ("Test not available."); + + for (int i = 0; i < 8;) + { + recreateAnysTable(); + _pSession->setFeature("autoBind", bindValues[i]); + _pSession->setFeature("autoExtract", bindValues[i+1]); + _pExecutor->dynamicAny(); + + i += 2; + } +} + + void ODBCPostgreSQLTest::configurePLPgSQL() { if (!_pSession) fail ("Test not available."); @@ -1135,6 +1167,15 @@ void ODBCPostgreSQLTest::recreateVectorsTable() } +void ODBCPostgreSQLTest::recreateAnysTable() +{ + dropObject("TABLE", "Anys"); + try { *_pSession << "CREATE TABLE Anys (int0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; } + catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); } + catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); } +} + + void ODBCPostgreSQLTest::recreateNullsTable(const std::string& notNull) { dropObject("TABLE", "NullTest"); @@ -1333,6 +1374,8 @@ CppUnit::Test* ODBCPostgreSQLTest::suite() CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testRowIterator); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testStdVectorBool); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testAsync); + CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testAny); + CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testDynamicAny); return pSuite; } diff --git a/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.h b/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.h index b68fb984f..ae03ed6c7 100644 --- a/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.h +++ b/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.h @@ -135,6 +135,9 @@ public: void testAsync(); + void testAny(); + void testDynamicAny(); + void setUp(); void tearDown(); @@ -154,6 +157,7 @@ private: void recreateFloatsTable(); void recreateTuplesTable(); void recreateVectorsTable(); + void recreateAnysTable(); void recreateNullsTable(const std::string& notNull=""); void recreateBoolTable(); diff --git a/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp b/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp index ef2b27dc5..04b391591 100644 --- a/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp @@ -1100,6 +1100,38 @@ void ODBCSQLServerTest::testAsync() } +void ODBCSQLServerTest::testAny() +{ + if (!_pSession) fail ("Test not available."); + + for (int i = 0; i < 8;) + { + recreateAnysTable(); + _pSession->setFeature("autoBind", bindValues[i]); + _pSession->setFeature("autoExtract", bindValues[i+1]); + _pExecutor->any(); + + i += 2; + } +} + + +void ODBCSQLServerTest::testDynamicAny() +{ + if (!_pSession) fail ("Test not available."); + + for (int i = 0; i < 8;) + { + recreateAnysTable(); + _pSession->setFeature("autoBind", bindValues[i]); + _pSession->setFeature("autoExtract", bindValues[i+1]); + _pExecutor->dynamicAny(); + + i += 2; + } +} + + void ODBCSQLServerTest::dropObject(const std::string& type, const std::string& name) { try @@ -1209,6 +1241,15 @@ void ODBCSQLServerTest::recreateVectorsTable() } +void ODBCSQLServerTest::recreateAnysTable() +{ + dropObject("TABLE", "Anys"); + try { *_pSession << "CREATE TABLE Anys (int0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; } + catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); } + catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); } +} + + void ODBCSQLServerTest::recreateNullsTable(const std::string& notNull) { dropObject("TABLE", "NullTest"); @@ -1382,6 +1423,8 @@ CppUnit::Test* ODBCSQLServerTest::suite() CppUnit_addTest(pSuite, ODBCSQLServerTest, testRowIterator); CppUnit_addTest(pSuite, ODBCSQLServerTest, testStdVectorBool); CppUnit_addTest(pSuite, ODBCSQLServerTest, testAsync); + CppUnit_addTest(pSuite, ODBCSQLServerTest, testAny); + CppUnit_addTest(pSuite, ODBCSQLServerTest, testDynamicAny); return pSuite; } diff --git a/Data/ODBC/testsuite/src/ODBCSQLServerTest.h b/Data/ODBC/testsuite/src/ODBCSQLServerTest.h index cca98b008..9b8d69468 100644 --- a/Data/ODBC/testsuite/src/ODBCSQLServerTest.h +++ b/Data/ODBC/testsuite/src/ODBCSQLServerTest.h @@ -131,6 +131,9 @@ public: void testAsync(); + void testAny(); + void testDynamicAny(); + void setUp(); void tearDown(); @@ -151,6 +154,7 @@ private: void recreateTuplesTable(); void recreateVectorTable(); void recreateVectorsTable(); + void recreateAnysTable(); void recreateNullsTable(const std::string& notNull = ""); void recreateBoolTable(); diff --git a/Data/ODBC/testsuite/src/ODBCSQLiteTest.cpp b/Data/ODBC/testsuite/src/ODBCSQLiteTest.cpp index 5ea1637e4..e7b4692de 100644 --- a/Data/ODBC/testsuite/src/ODBCSQLiteTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCSQLiteTest.cpp @@ -921,6 +921,38 @@ void ODBCSQLiteTest::testAsync() } +void ODBCSQLiteTest::testAny() +{ + if (!_pSession) fail ("Test not available."); + + for (int i = 0; i < 8;) + { + recreateAnysTable(); + _pSession->setFeature("autoBind", bindValues[i]); + _pSession->setFeature("autoExtract", bindValues[i+1]); + _pExecutor->any(); + + i += 2; + } +} + + +void ODBCSQLiteTest::testDynamicAny() +{ + if (!_pSession) fail ("Test not available."); + + for (int i = 0; i < 8;) + { + recreateAnysTable(); + _pSession->setFeature("autoBind", bindValues[i]); + _pSession->setFeature("autoExtract", bindValues[i+1]); + _pExecutor->dynamicAny(); + + i += 2; + } +} + + void ODBCSQLiteTest::dropObject(const std::string& type, const std::string& name) { try @@ -1021,6 +1053,15 @@ void ODBCSQLiteTest::recreateVectorsTable() } +void ODBCSQLiteTest::recreateAnysTable() +{ + dropObject("TABLE", "Anys"); + try { *_pSession << "CREATE TABLE Anys (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now; } + catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); } + catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); } +} + + void ODBCSQLiteTest::recreateNullsTable(const std::string& notNull) { dropObject("TABLE", "NullTest"); @@ -1169,6 +1210,8 @@ CppUnit::Test* ODBCSQLiteTest::suite() CppUnit_addTest(pSuite, ODBCSQLiteTest, testNull); CppUnit_addTest(pSuite, ODBCSQLiteTest, testRowIterator); CppUnit_addTest(pSuite, ODBCSQLiteTest, testAsync); + CppUnit_addTest(pSuite, ODBCSQLiteTest, testAny); + CppUnit_addTest(pSuite, ODBCSQLiteTest, testDynamicAny); return pSuite; } diff --git a/Data/ODBC/testsuite/src/ODBCSQLiteTest.h b/Data/ODBC/testsuite/src/ODBCSQLiteTest.h index 5305a85fb..0caa0da34 100644 --- a/Data/ODBC/testsuite/src/ODBCSQLiteTest.h +++ b/Data/ODBC/testsuite/src/ODBCSQLiteTest.h @@ -124,6 +124,9 @@ public: void testAsync(); + void testAny(); + void testDynamicAny(); + void setUp(); void tearDown(); @@ -143,6 +146,7 @@ private: void recreateFloatsTable(); void recreateTuplesTable(); void recreateVectorsTable(); + void recreateAnysTable(); void recreateNullsTable(const std::string& notNull = ""); static bool init(const std::string& driver, const std::string& dsn); diff --git a/Data/ODBC/testsuite/src/SQLExecutor.cpp b/Data/ODBC/testsuite/src/SQLExecutor.cpp index f0ace3563..67a40070b 100644 --- a/Data/ODBC/testsuite/src/SQLExecutor.cpp +++ b/Data/ODBC/testsuite/src/SQLExecutor.cpp @@ -36,6 +36,7 @@ #include "Poco/Format.h" #include "Poco/Tuple.h" #include "Poco/Any.h" +#include "Poco/DynamicAny.h" #include "Poco/DateTime.h" #include "Poco/Exception.h" #include "Poco/Data/Common.h" @@ -66,6 +67,7 @@ using Poco::format; using Poco::Tuple; using Poco::Any; using Poco::AnyCast; +using Poco::DynamicAny; using Poco::DateTime; using Poco::NotFoundException; using Poco::InvalidAccessException; @@ -2325,3 +2327,49 @@ void SQLExecutor::asynchronous(int rowCount) assert ("deque" == stmt2.getStorage()); assert (stmt2.execute() == rowCount); } + +void SQLExecutor::any() +{ + Any i = 42; + Any f = 42.5; + Any s = std::string("42"); + + Session tmp = *_pSession; + + tmp << "INSERT INTO Anys VALUES (?, ?, ?)", use(i), use(f), use(s), now; + + int count = 0; + tmp << "SELECT COUNT(*) FROM Anys", into(count), now; + assert (1 == count); + + i = 0; + f = 0.0; + s = std::string(""); + tmp << "SELECT * FROM Anys", into(i), into(f), into(s), now; + assert (AnyCast(i) == 42); + assert (AnyCast(f) == 42.5); + assert (AnyCast(s) == "42"); +} + + +void SQLExecutor::dynamicAny() +{ + DynamicAny i = 42; + DynamicAny f = 42.5; + DynamicAny s = "42"; + + Session tmp = *_pSession; + tmp << "INSERT INTO Anys VALUES (?, ?, ?)", use(i), use(f), use(s), now; + + int count = 0; + tmp << "SELECT COUNT(*) FROM Anys", into(count), now; + assert (1 == count); + + i = 0; + f = 0.0; + s = std::string(""); + tmp << "SELECT * FROM Anys", into(i), into(f), into(s), now; + assert (42 == i); + assert (42.5 == f); + assert ("42" == s); +} diff --git a/Data/ODBC/testsuite/src/SQLExecutor.h b/Data/ODBC/testsuite/src/SQLExecutor.h index 9a12825bd..b09151735 100644 --- a/Data/ODBC/testsuite/src/SQLExecutor.h +++ b/Data/ODBC/testsuite/src/SQLExecutor.h @@ -135,6 +135,9 @@ public: void stdVectorBool(); void asynchronous(int rowCount = 500); + + void any(); + void dynamicAny(); private: Poco::Data::Session* _pSession; diff --git a/Data/SQLite/include/Poco/Data/SQLite/Binder.h b/Data/SQLite/include/Poco/Data/SQLite/Binder.h index 01ddb9968..ba4de30e0 100644 --- a/Data/SQLite/include/Poco/Data/SQLite/Binder.h +++ b/Data/SQLite/include/Poco/Data/SQLite/Binder.h @@ -43,6 +43,7 @@ #include "Poco/Data/SQLite/SQLite.h" #include "Poco/Data/AbstractBinder.h" #include "Poco/Any.h" +#include "Poco/DynamicAny.h" struct sqlite3_stmt; @@ -87,6 +88,11 @@ public: void bind(std::size_t pos, const Poco::UInt64 &val, Direction dir = PD_IN); /// Binds an UInt64. +#ifndef POCO_LONG_IS_64_BIT + void bind(std::size_t pos, const long &val, Direction dir = PD_IN); + /// Binds a long +#endif + void bind(std::size_t pos, const bool &val, Direction dir = PD_IN); /// Binds a boolean. @@ -168,6 +174,15 @@ inline void Binder::bind(std::size_t pos, const Poco::UInt64 &val, Direction dir } +#ifndef POCO_LONG_IS_64_BIT +inline void Binder::bind(std::size_t pos, const long &val, Direction dir) +{ + long tmp = static_cast(val); + bind(pos, tmp, dir); +} +#endif + + inline void Binder::bind(std::size_t pos, const bool &val, Direction dir) { Poco::Int32 tmp = (val ? 1 : 0); diff --git a/Data/SQLite/include/Poco/Data/SQLite/Extractor.h b/Data/SQLite/include/Poco/Data/SQLite/Extractor.h index 44b513798..cea7bfa61 100644 --- a/Data/SQLite/include/Poco/Data/SQLite/Extractor.h +++ b/Data/SQLite/include/Poco/Data/SQLite/Extractor.h @@ -41,8 +41,12 @@ #include "Poco/Data/SQLite/SQLite.h" +#include "Poco/Data/SQLite/Utility.h" #include "Poco/Data/AbstractExtractor.h" +#include "Poco/Data/MetaColumn.h" +#include "Poco/Data/DataException.h" #include "Poco/Any.h" +#include "Poco/DynamicAny.h" #include #include @@ -93,6 +97,11 @@ public: bool extract(std::size_t pos, Poco::UInt64& val); /// Extracts an UInt64. +#ifndef POCO_LONG_IS_64_BIT + bool extract(std::size_t pos, long& val); + /// Extracts a long. +#endif + bool extract(std::size_t pos, bool& val); /// Extracts a boolean. @@ -117,6 +126,9 @@ public: bool extract(std::size_t pos, Poco::Any& val); /// Extracts an Any. + bool extract(std::size_t pos, Poco::DynamicAny& val); + /// Extracts a DynamicAny. + bool isNull(std::size_t pos); /// Returns true if the current row value at pos column is null. /// Because of the loss of information about null-ness of the @@ -135,6 +147,121 @@ public: /// Clears the cached nulls indicator vector. private: + template + bool extractImpl(std::size_t pos, T& val) + /// Utility function for extraction of Any and DynamicAny. + { + if (isNull(pos)) return false; + + bool ret = false; + + switch (Utility::getColumnType(_pStmt, pos)) + { + case MetaColumn::FDT_BOOL: + { + bool i = false; + ret = extract(pos, i); + val = i; + break; + } + case MetaColumn::FDT_INT8: + { + Poco::Int8 i = 0; + ret = extract(pos, i); + val = i; + break; + } + case MetaColumn::FDT_UINT8: + { + Poco::UInt8 i = 0; + ret = extract(pos, i); + val = i; + break; + } + case MetaColumn::FDT_INT16: + { + Poco::Int16 i = 0; + ret = extract(pos, i); + val = i; + break; + } + case MetaColumn::FDT_UINT16: + { + Poco::UInt16 i = 0; + ret = extract(pos, i); + val = i; + break; + } + case MetaColumn::FDT_INT32: + { + Poco::Int32 i = 0; + ret = extract(pos, i); + val = i; + break; + } + case MetaColumn::FDT_UINT32: + { + Poco::UInt32 i = 0; + ret = extract(pos, i); + val = i; + break; + } + case MetaColumn::FDT_INT64: + { + Poco::Int64 i = 0; + ret = extract(pos, i); + val = i; + break; + } + case MetaColumn::FDT_UINT64: + { + Poco::UInt64 i = 0; + ret = extract(pos, i); + val = i; + break; + } + case MetaColumn::FDT_STRING: + { + std::string s; + ret = extract(pos, s); + val = s; + break; + } + case MetaColumn::FDT_DOUBLE: + { + double d(0.0); + ret = extract(pos, d); + val = d; + break; + } + case MetaColumn::FDT_FLOAT: + { + float f(0.0); + ret = extract(pos, f); + val = f; + break; + } + case MetaColumn::FDT_BLOB: + { + BLOB b; + ret = extract(pos, b); + val = b; + break; + } + case MetaColumn::FDT_TIMESTAMP: + { + DateTime dt; + ret = extract(pos, dt); + val = dt; + break; + } + default: + throw Poco::Data::UnknownTypeException("Unknown type during extraction"); + } + + return ret; + } + sqlite3_stmt* _pStmt; NullIndVec _nulls; }; diff --git a/Data/SQLite/src/Extractor.cpp b/Data/SQLite/src/Extractor.cpp index 9d59436a5..7dfc8d46e 100644 --- a/Data/SQLite/src/Extractor.cpp +++ b/Data/SQLite/src/Extractor.cpp @@ -81,6 +81,17 @@ bool Extractor::extract(std::size_t pos, Poco::Int64& val) } +#ifndef POCO_LONG_IS_64_BIT +bool Extractor::extract(std::size_t pos, long& val) +{ + if (isNull(pos)) + return false; + val = sqlite3_column_int(_pStmt, (int) pos); + return true; +} +#endif + + bool Extractor::extract(std::size_t pos, double& val) { if (isNull(pos)) @@ -206,108 +217,13 @@ bool Extractor::extract(std::size_t pos, DateTime& val) bool Extractor::extract(std::size_t pos, Poco::Any& val) { - if (isNull(pos)) return false; + return extractImpl(pos, val); +} - bool ret = false; - switch (Utility::getColumnType(_pStmt, pos)) - { - case MetaColumn::FDT_BOOL: - { - bool i = false; - ret = extract(pos, i); - val = i; - break; - } - case MetaColumn::FDT_INT8: - { - Poco::Int8 i = 0; - ret = extract(pos, i); - val = i; - break; - } - case MetaColumn::FDT_UINT8: - { - Poco::UInt8 i = 0; - ret = extract(pos, i); - val = i; - break; - } - case MetaColumn::FDT_INT16: - { - Poco::Int16 i = 0; - ret = extract(pos, i); - val = i; - break; - } - case MetaColumn::FDT_UINT16: - { - Poco::UInt16 i = 0; - ret = extract(pos, i); - val = i; - break; - } - case MetaColumn::FDT_INT32: - { - Poco::Int32 i = 0; - ret = extract(pos, i); - val = i; - break; - } - case MetaColumn::FDT_UINT32: - { - Poco::UInt32 i = 0; - ret = extract(pos, i); - val = i; - break; - } - case MetaColumn::FDT_INT64: - { - Poco::Int64 i = 0; - ret = extract(pos, i); - val = i; - break; - } - case MetaColumn::FDT_UINT64: - { - Poco::UInt64 i = 0; - ret = extract(pos, i); - val = i; - break; - } - case MetaColumn::FDT_STRING: - { - std::string s; - ret = extract(pos, s); - val = s; - break; - } - case MetaColumn::FDT_DOUBLE: - { - double d(0.0); - ret = extract(pos, d); - val = d; - break; - } - case MetaColumn::FDT_FLOAT: - { - float f(0.0); - ret = extract(pos, f); - val = f; - break; - } - case MetaColumn::FDT_BLOB: - { - BLOB b; - ret = extract(pos, b); - val = b; - break; - } - default: - throw Poco::Data::UnknownTypeException("Unknown type during extraction"); - } - - return ret; +bool Extractor::extract(std::size_t pos, Poco::DynamicAny& val) +{ + return extractImpl(pos, val); } diff --git a/Data/SQLite/testsuite/src/SQLiteTest.cpp b/Data/SQLite/testsuite/src/SQLiteTest.cpp index 33127cc89..5fdd67a5a 100644 --- a/Data/SQLite/testsuite/src/SQLiteTest.cpp +++ b/Data/SQLite/testsuite/src/SQLiteTest.cpp @@ -50,6 +50,7 @@ using namespace Poco::Data; using Poco::Tuple; using Poco::Any; using Poco::AnyCast; +using Poco::DynamicAny; using Poco::InvalidAccessException; using Poco::RangeException; using Poco::BadCastException; @@ -1779,6 +1780,58 @@ void SQLiteTest::testAsync() } +void SQLiteTest::testAny() +{ + Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db")); + tmp << "DROP TABLE IF EXISTS Anys", now; + tmp << "CREATE TABLE Anys (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now; + + Any i = Int64(42); + Any f = double(42.5); + Any s = std::string("42"); + + tmp << "INSERT INTO Anys VALUES (?, ?, ?)", use(i), use(f), use(s), now; + + int count = 0; + tmp << "SELECT COUNT(*) FROM Anys", into(count), now; + assert (1 == count); + + i = 0; + f = 0.0; + s = std::string(""); + tmp << "SELECT * FROM Anys", into(i), into(f), into(s), now; + assert (AnyCast(i) == 42); + assert (AnyCast(f) == 42.5); + assert (AnyCast(s) == "42"); +} + + +void SQLiteTest::testDynamicAny() +{ + Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db")); + tmp << "DROP TABLE IF EXISTS Anys", now; + tmp << "CREATE TABLE Anys (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now; + + DynamicAny i = Int64(42); + DynamicAny f = double(42.5); + DynamicAny s = std::string("42"); + + tmp << "INSERT INTO Anys VALUES (?, ?, ?)", use(i), use(f), use(s), now; + + int count = 0; + tmp << "SELECT COUNT(*) FROM Anys", into(count), now; + assert (1 == count); + + i = 0; + f = 0.0; + s = std::string(""); + tmp << "SELECT * FROM Anys", into(i), into(f), into(s), now; + assert (42 == i); + assert (42.5 == f); + assert ("42" == s); +} + + void SQLiteTest::setUp() { } @@ -1853,6 +1906,8 @@ CppUnit::Test* SQLiteTest::suite() CppUnit_addTest(pSuite, SQLiteTest, testNull); CppUnit_addTest(pSuite, SQLiteTest, testRowIterator); CppUnit_addTest(pSuite, SQLiteTest, testAsync); + CppUnit_addTest(pSuite, SQLiteTest, testAny); + CppUnit_addTest(pSuite, SQLiteTest, testDynamicAny); return pSuite; } diff --git a/Data/SQLite/testsuite/src/SQLiteTest.h b/Data/SQLite/testsuite/src/SQLiteTest.h index d1fde24ca..29356baa4 100644 --- a/Data/SQLite/testsuite/src/SQLiteTest.h +++ b/Data/SQLite/testsuite/src/SQLiteTest.h @@ -113,6 +113,9 @@ public: void testRowIterator(); void testAsync(); + void testAny(); + void testDynamicAny(); + void setUp(); void tearDown(); diff --git a/Data/include/Poco/Data/AbstractBinder.h b/Data/include/Poco/Data/AbstractBinder.h index 6e4cbc5b5..c3b13d0be 100644 --- a/Data/include/Poco/Data/AbstractBinder.h +++ b/Data/include/Poco/Data/AbstractBinder.h @@ -47,6 +47,8 @@ namespace Poco { class DateTime; +class Any; +class DynamicAny; namespace Data { @@ -118,6 +120,11 @@ public: virtual void bind(std::size_t pos, const Poco::UInt64& val, Direction dir) = 0; /// Binds an UInt64. +#ifndef POCO_LONG_IS_64_BIT + virtual void bind(std::size_t pos, const long& val, Direction dir) = 0; + /// Binds a long. +#endif + virtual void bind(std::size_t pos, const bool& val, Direction dir) = 0; /// Binds a boolean. @@ -145,6 +152,12 @@ public: virtual void bind(std::size_t pos, const NullData& val, Direction dir) = 0; /// Binds a null. + void bind(std::size_t pos, const Any& val, Direction dir = PD_IN); + /// Binds an Any. + + void bind(std::size_t pos, const DynamicAny& val, Direction dir = PD_IN); + /// Binds a DynamicAny. + static bool isOutBound(Direction dir); /// Returns true if direction is out bound; diff --git a/Data/include/Poco/Data/AbstractExtractor.h b/Data/include/Poco/Data/AbstractExtractor.h index 073c1d7b3..ac15d884e 100644 --- a/Data/include/Poco/Data/AbstractExtractor.h +++ b/Data/include/Poco/Data/AbstractExtractor.h @@ -48,6 +48,8 @@ namespace Poco { class DateTime; +class Any; +class DynamicAny; namespace Data { @@ -91,6 +93,11 @@ public: virtual bool extract(std::size_t pos, Poco::UInt64& val) = 0; /// Extracts an UInt64. Returns false if null was received. +#ifndef POCO_LONG_IS_64_BIT + virtual bool extract(std::size_t pos, long& val) = 0; + /// Extracts a long. Returns false if null was received. +#endif + virtual bool extract(std::size_t pos, bool& val) = 0; /// Extracts a boolean. Returns false if null was received. @@ -112,6 +119,12 @@ public: virtual bool extract(std::size_t pos, DateTime& val) = 0; /// Extracts a DateTime. Returns false if null was received. + virtual bool extract(std::size_t pos, Any& val) = 0; + /// Extracts a Any. Returns false if null was received. + + virtual bool extract(std::size_t pos, DynamicAny& val) = 0; + /// Extracts a DynamicAny. Returns false if null was received. + virtual bool isNull(std::size_t pos) = 0; /// Returns true if the current row value at pos column is null. diff --git a/Data/include/Poco/Data/AbstractPreparation.h b/Data/include/Poco/Data/AbstractPreparation.h index 93f7881c1..593d23e5b 100644 --- a/Data/include/Poco/Data/AbstractPreparation.h +++ b/Data/include/Poco/Data/AbstractPreparation.h @@ -50,6 +50,7 @@ namespace Poco { class DateTime; class Any; +class DynamicAny; namespace Data { @@ -95,6 +96,11 @@ public: virtual void prepare(std::size_t pos, Poco::UInt64) = 0; /// Prepares an UInt64. +#ifndef POCO_LONG_IS_64_BIT + virtual void prepare(std::size_t pos, long) = 0; + /// Prepares a long. +#endif + virtual void prepare(std::size_t pos, bool) = 0; /// Prepares a boolean. @@ -118,6 +124,9 @@ public: virtual void prepare(std::size_t pos, const Any&) = 0; /// Prepares an Any. + + virtual void prepare(std::size_t pos, const DynamicAny&) = 0; + /// Prepares a DynamicAny. }; diff --git a/Data/include/Poco/Data/BLOB.h b/Data/include/Poco/Data/BLOB.h index b2b4a484b..211ed93f1 100644 --- a/Data/include/Poco/Data/BLOB.h +++ b/Data/include/Poco/Data/BLOB.h @@ -367,6 +367,11 @@ public: return new DynamicAnyHolderImpl(_val); } + const Data::BLOB& value() const + { + return _val; + } + private: Data::BLOB _val; }; diff --git a/Data/src/AbstractBinder.cpp b/Data/src/AbstractBinder.cpp index a5ffcaea7..76db68451 100644 --- a/Data/src/AbstractBinder.cpp +++ b/Data/src/AbstractBinder.cpp @@ -35,6 +35,10 @@ #include "Poco/Data/AbstractBinder.h" +#include "Poco/Data/DataException.h" +#include "Poco/Any.h" +#include "Poco/DynamicAny.h" +#include "Poco/Data/BLOB.h" namespace Poco { @@ -51,4 +55,92 @@ AbstractBinder::~AbstractBinder() } +void AbstractBinder::bind(std::size_t pos, const Any& val, Direction dir) +{ + if (PD_IN != dir) + throw InvalidAccessException("Only IN direction is allowed."); + + if(val.type() == typeid(Int32)) + bind(pos, RefAnyCast(val), dir); + else if(val.type() == typeid(std::string)) + bind(pos, RefAnyCast(val), dir); + else if (val.type() == typeid(bool)) + bind(pos, RefAnyCast(val), dir); + else if(val.type() == typeid(char)) + bind(pos, RefAnyCast(val), dir); + else if(val.type() == typeid(Int8)) + bind(pos, RefAnyCast(val), dir); + else if(val.type() == typeid(UInt8)) + bind(pos, RefAnyCast(val), dir); + else if(val.type() == typeid(Int16)) + bind(pos, RefAnyCast(val), dir); + else if(val.type() == typeid(UInt16)) + bind(pos, RefAnyCast(val), dir); + else if(val.type() == typeid(UInt32)) + bind(pos, RefAnyCast(val), dir); + else if(val.type() == typeid(Int64)) + bind(pos, RefAnyCast(val), dir); + else if(val.type() == typeid(UInt64)) + bind(pos, RefAnyCast(val), dir); + else if(val.type() == typeid(float)) + bind(pos, RefAnyCast(val), dir); + else if(val.type() == typeid(double)) + bind(pos, RefAnyCast(val), dir); + else if(val.type() == typeid(DateTime)) + bind(pos, RefAnyCast(val), dir); + else if(val.type() == typeid(BLOB)) + bind(pos, RefAnyCast(val), dir); +#ifndef POCO_LONG_IS_64_BIT + else if(val.type() == typeid(long)) + bind(pos, RefAnyCast(val), dir); +#endif + else + throw UnknownTypeException(std::string(val.type().name())); +} + + +void AbstractBinder::bind(std::size_t pos, const DynamicAny& val, Direction dir) +{ + if (PD_IN != dir) + throw InvalidAccessException("Only IN direction is allowed."); + + if(val.type() == typeid(Int32)) + bind(pos, val.extract(), dir); + else if(val.type() == typeid(std::string)) + bind(pos, val.extract(), dir); + else if (val.type() == typeid(bool)) + bind(pos, val.extract(), dir); + else if(val.type() == typeid(char)) + bind(pos, val.extract(), dir); + else if(val.type() == typeid(Int8)) + bind(pos, val.extract(), dir); + else if(val.type() == typeid(UInt8)) + bind(pos, val.extract(), dir); + else if(val.type() == typeid(Int16)) + bind(pos, val.extract(), dir); + else if(val.type() == typeid(UInt16)) + bind(pos, val.extract(), dir); + else if(val.type() == typeid(UInt32)) + bind(pos, val.extract(), dir); + else if(val.type() == typeid(Int64)) + bind(pos, val.extract(), dir); + else if(val.type() == typeid(UInt64)) + bind(pos, val.extract(), dir); + else if(val.type() == typeid(float)) + bind(pos, val.extract(), dir); + else if(val.type() == typeid(double)) + bind(pos, val.extract(), dir); + else if(val.type() == typeid(DateTime)) + bind(pos, val.extract(), dir); + else if(val.type() == typeid(BLOB)) + bind(pos, val.extract(), dir); +#ifndef POCO_LONG_IS_64_BIT + else if(val.type() == typeid(long)) + bind(pos, val.extract(), dir); +#endif + else + throw UnknownTypeException(std::string(val.type().name())); +} + + } } // namespace Poco::Data diff --git a/Data/src/RecordSet.cpp b/Data/src/RecordSet.cpp index 7b96639b7..5b51f7082 100644 --- a/Data/src/RecordSet.cpp +++ b/Data/src/RecordSet.cpp @@ -36,6 +36,7 @@ #include "Poco/Data/RecordSet.h" #include "Poco/Data/Session.h" +#include "Poco/Data/DataException.h" #include "Poco/DateTime.h" @@ -95,7 +96,7 @@ DynamicAny RecordSet::value(std::size_t col, std::size_t row) const case MetaColumn::FDT_BLOB: return value(col, row); case MetaColumn::FDT_TIMESTAMP: return value(col, row); default: - throw Poco::InvalidArgumentException("Data type not supported."); + throw UnknownTypeException("Data type not supported."); } } @@ -119,7 +120,7 @@ DynamicAny RecordSet::value(const std::string& name, std::size_t row) const case MetaColumn::FDT_BLOB: return value(name, row); case MetaColumn::FDT_TIMESTAMP: return value(name, row); default: - throw Poco::InvalidArgumentException("Data type not supported."); + throw UnknownTypeException("Data type not supported."); } }