Any and DynamicAny binding/extraction

This commit is contained in:
Aleksandar Fabijanic 2007-10-31 01:29:21 +00:00
parent 76221cc707
commit e7ac6e383c
28 changed files with 773 additions and 159 deletions

View File

@ -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.
@ -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);

View File

@ -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 <map>
#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<T>(&_rPreparation[pos]);
return true;
}
@ -193,6 +203,63 @@ private:
return true;
}
template <typename T>
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,

View File

@ -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 <vector>
@ -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 <typename T>
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<long>(pos, SQL_C_SLONG);
}
#endif
inline void Preparation::prepare(std::size_t pos, bool)
{
preparePOD<bool>(pos, SQL_C_BIT);

View File

@ -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);
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 extractImpl(pos, val);
}
return false;
bool Extractor::extract(std::size_t pos, Poco::DynamicAny& val)
{
return extractImpl(pos, val);
}

View File

@ -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<float>(pos, SQL_C_FLOAT);
case MetaColumn::FDT_DOUBLE:
return preparePOD<float>(pos, SQL_C_DOUBLE);
return preparePOD<double>(pos, SQL_C_DOUBLE);
case MetaColumn::FDT_STRING:
return prepareRaw<char>(pos, SQL_C_CHAR, maxDataSize(pos));

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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();

View File

@ -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;
}

View File

@ -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();

View File

@ -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;
}

View File

@ -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);

View File

@ -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<int>(i) == 42);
assert (AnyCast<double>(f) == 42.5);
assert (AnyCast<std::string>(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);
}

View File

@ -136,6 +136,9 @@ public:
void asynchronous(int rowCount = 500);
void any();
void dynamicAny();
private:
Poco::Data::Session* _pSession;
};

View File

@ -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<long>(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);

View File

@ -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 <vector>
#include <utility>
@ -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 <typename T>
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;
};

View File

@ -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;
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 extractImpl(pos, val);
}
return ret;
bool Extractor::extract(std::size_t pos, Poco::DynamicAny& val)
{
return extractImpl(pos, val);
}

View File

@ -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<Int64>(i) == 42);
assert (AnyCast<double>(f) == 42.5);
assert (AnyCast<std::string>(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;
}

View File

@ -113,6 +113,9 @@ public:
void testRowIterator();
void testAsync();
void testAny();
void testDynamicAny();
void setUp();
void tearDown();

View File

@ -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;

View File

@ -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.

View File

@ -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.
};

View File

@ -367,6 +367,11 @@ public:
return new DynamicAnyHolderImpl(_val);
}
const Data::BLOB& value() const
{
return _val;
}
private:
Data::BLOB _val;
};

View File

@ -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<Int32>(val), dir);
else if(val.type() == typeid(std::string))
bind(pos, RefAnyCast<std::string>(val), dir);
else if (val.type() == typeid(bool))
bind(pos, RefAnyCast<bool>(val), dir);
else if(val.type() == typeid(char))
bind(pos, RefAnyCast<char>(val), dir);
else if(val.type() == typeid(Int8))
bind(pos, RefAnyCast<Int8>(val), dir);
else if(val.type() == typeid(UInt8))
bind(pos, RefAnyCast<UInt8>(val), dir);
else if(val.type() == typeid(Int16))
bind(pos, RefAnyCast<Int16>(val), dir);
else if(val.type() == typeid(UInt16))
bind(pos, RefAnyCast<UInt16>(val), dir);
else if(val.type() == typeid(UInt32))
bind(pos, RefAnyCast<UInt32>(val), dir);
else if(val.type() == typeid(Int64))
bind(pos, RefAnyCast<Int64>(val), dir);
else if(val.type() == typeid(UInt64))
bind(pos, RefAnyCast<UInt64>(val), dir);
else if(val.type() == typeid(float))
bind(pos, RefAnyCast<float>(val), dir);
else if(val.type() == typeid(double))
bind(pos, RefAnyCast<double>(val), dir);
else if(val.type() == typeid(DateTime))
bind(pos, RefAnyCast<DateTime>(val), dir);
else if(val.type() == typeid(BLOB))
bind(pos, RefAnyCast<BLOB>(val), dir);
#ifndef POCO_LONG_IS_64_BIT
else if(val.type() == typeid(long))
bind(pos, RefAnyCast<long>(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<Int32>(), dir);
else if(val.type() == typeid(std::string))
bind(pos, val.extract<std::string>(), dir);
else if (val.type() == typeid(bool))
bind(pos, val.extract<bool>(), dir);
else if(val.type() == typeid(char))
bind(pos, val.extract<char>(), dir);
else if(val.type() == typeid(Int8))
bind(pos, val.extract<Int8>(), dir);
else if(val.type() == typeid(UInt8))
bind(pos, val.extract<UInt8>(), dir);
else if(val.type() == typeid(Int16))
bind(pos, val.extract<Int16>(), dir);
else if(val.type() == typeid(UInt16))
bind(pos, val.extract<UInt16>(), dir);
else if(val.type() == typeid(UInt32))
bind(pos, val.extract<UInt32>(), dir);
else if(val.type() == typeid(Int64))
bind(pos, val.extract<Int64>(), dir);
else if(val.type() == typeid(UInt64))
bind(pos, val.extract<UInt64>(), dir);
else if(val.type() == typeid(float))
bind(pos, val.extract<float>(), dir);
else if(val.type() == typeid(double))
bind(pos, val.extract<double>(), dir);
else if(val.type() == typeid(DateTime))
bind(pos, val.extract<DateTime>(), dir);
else if(val.type() == typeid(BLOB))
bind(pos, val.extract<BLOB>(), dir);
#ifndef POCO_LONG_IS_64_BIT
else if(val.type() == typeid(long))
bind(pos, val.extract<long>(), dir);
#endif
else
throw UnknownTypeException(std::string(val.type().name()));
}
} } // namespace Poco::Data

View File

@ -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<BLOB>(col, row);
case MetaColumn::FDT_TIMESTAMP: return value<DateTime>(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<BLOB>(name, row);
case MetaColumn::FDT_TIMESTAMP: return value<DateTime>(name, row);
default:
throw Poco::InvalidArgumentException("Data type not supported.");
throw UnknownTypeException("Data type not supported.");
}
}