Implement extraction of Dynamic::Var and Any in MySQL extractor (#1863) (#1872)

* Implement extraction of Dynamic::Var and Any in MySQL extractor (#1863)

* Remove probably unnecessary include <my_global.h> from SQLExecutor
This commit is contained in:
Erbengi
2017-09-04 17:59:13 +02:00
committed by Aleksandar Fabijanic
parent e59fba4ddd
commit fe7230a6d5
6 changed files with 265 additions and 7 deletions

View File

@@ -25,6 +25,8 @@
#include "Poco/Data/MySQL/ResultMetadata.h"
#include "Poco/Data/AbstractExtractor.h"
#include "Poco/Data/LOB.h"
#include "Poco/Data/Date.h"
#include "Poco/Data/Time.h"
namespace Poco {
@@ -324,6 +326,17 @@ private:
bool realExtractFixed(std::size_t pos, enum_field_types type, void* buffer, bool isUnsigned = false);
bool realExtractFixedBlob(std::size_t pos, enum_field_types type, void* buffer, size_t len);
template<typename T>
T extractAny(std::size_t pos, bool& success)
{
T value;
success = extract(pos, value);
return value;
}
template<typename T>
bool extractToDynamic(std::size_t pos, T& val);
// Prevent VC8 warning "operator= could not be generated"
Extractor& operator=(const Extractor&);
@@ -333,6 +346,97 @@ private:
ResultMetadata& _metadata;
};
template<typename T>
bool Extractor::extractToDynamic(std::size_t pos, T &val)
{
MetaColumn::ColumnDataType columnType = _metadata.metaColumn(static_cast<Poco::UInt32>(pos)).type();
T resultValue;
bool success = false;
switch (columnType)
{
case MetaColumn::FDT_BOOL:
resultValue = extractAny<bool>(pos, success);
break;
case MetaColumn::FDT_INT8:
resultValue = extractAny<Int8>(pos, success);
break;
case MetaColumn::FDT_UINT8:
resultValue = extractAny<UInt8>(pos, success);
break;
case MetaColumn::FDT_INT16:
resultValue = extractAny<Int16>(pos, success);
break;
case MetaColumn::FDT_UINT16:
resultValue = extractAny<UInt16>(pos, success);
break;
case MetaColumn::FDT_INT32:
resultValue = extractAny<Int32>(pos, success);
break;
case MetaColumn::FDT_UINT32:
resultValue = extractAny<UInt32>(pos, success);
break;
case MetaColumn::FDT_INT64:
resultValue = extractAny<Int64>(pos, success);
break;
case MetaColumn::FDT_UINT64:
resultValue = extractAny<UInt64>(pos, success);
break;
case MetaColumn::FDT_FLOAT:
resultValue = extractAny<float>(pos, success);
break;
case MetaColumn::FDT_DOUBLE:
resultValue = extractAny<double>(pos, success);
break;
case MetaColumn::FDT_STRING:
resultValue = extractAny<std::string>(pos, success);
break;
case MetaColumn::FDT_WSTRING:
return false;
case MetaColumn::FDT_BLOB:
resultValue = extractAny<std::string>(pos, success);
break;
case MetaColumn::FDT_CLOB:
resultValue = extractAny<CLOB>(pos, success);
break;
case MetaColumn::FDT_DATE:
resultValue = extractAny<Date>(pos, success);
break;
case MetaColumn::FDT_TIME:
resultValue = extractAny<Time>(pos, success);
break;
case MetaColumn::FDT_TIMESTAMP:
resultValue = extractAny<DateTime>(pos, success);
break;
case MetaColumn::FDT_UNKNOWN:
return false;
}
if(success)
val.swap(resultValue);
return success;
}
} } } // namespace Poco::Data::MySQL

View File

@@ -18,6 +18,7 @@
#include "Poco/Data/Date.h"
#include "Poco/Data/Time.h"
#include "Poco/Dynamic/Var.h"
namespace Poco {
namespace Data {
@@ -240,13 +241,13 @@ bool Extractor::extract(std::size_t pos, Time& val)
bool Extractor::extract(std::size_t pos, Any& val)
{
return false;
return extractToDynamic<Any>(pos, val);
}
bool Extractor::extract(std::size_t pos, Dynamic::Var& val)
{
return false;
return extractToDynamic<Dynamic::Var>(pos, val);
}

View File

@@ -531,6 +531,22 @@ void MySQLTest::testDouble()
_pExecutor->doubles();
}
void MySQLTest::testAny()
{
if (!_pSession) fail ("Test not available.");
recreateAnyTable();
_pExecutor->any();
}
void MySQLTest::testDynamicAny()
{
if (!_pSession) fail ("Test not available.");
recreateAnyTable();
_pExecutor->dynamicAny();
}
void MySQLTest::testTuple()
{
@@ -875,6 +891,17 @@ void MySQLTest::recreateNullableStringTable()
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateNullableStringTable()"); }
}
void MySQLTest::recreateAnyTable()
{
dropTable("Anys");
try {
*_pSession << "CREATE TABLE Anys (int_8 TINYINT, int_16 SMALLINT, int_32 MEDIUMINT, int_64 BIGINT, flt FLOAT, dbl DOUBLE, "
"str0 VARCHAR(255), str1 TEXT, date0 DATE, time0 TIME, date_time0 DATETIME, empty INTEGER)", now;
}
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateAnyTable()"); }
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateAnyTable()"); }
}
void MySQLTest::recreateVectorsTable()
{
@@ -977,6 +1004,8 @@ CppUnit::Test* MySQLTest::suite()
CppUnit_addTest(pSuite, MySQLTest, testUnsignedInts);
CppUnit_addTest(pSuite, MySQLTest, testFloat);
CppUnit_addTest(pSuite, MySQLTest, testDouble);
CppUnit_addTest(pSuite, MySQLTest, testAny);
CppUnit_addTest(pSuite, MySQLTest, testDynamicAny);
CppUnit_addTest(pSuite, MySQLTest, testTuple);
CppUnit_addTest(pSuite, MySQLTest, testTupleVector);
#if __cplusplus >= 201103L

View File

@@ -87,6 +87,9 @@ public:
void testFloat();
void testDouble();
void testAny();
void testDynamicAny();
void testTuple();
void testTupleVector();
@@ -134,6 +137,7 @@ private:
void recreateVectorsTable();
void recreateNullableIntTable();
void recreateNullableStringTable();
void recreateAnyTable();
static void dbInfo(Poco::Data::Session& session);

View File

@@ -45,13 +45,8 @@ typedef unsigned int uint; /* System V compatibility */
typedef unsigned long ulong; /* System V compatibility */
#endif
#include <my_global.h>
#include <mysql.h>
#ifdef max
#undef max
#endif
using namespace Poco::Data;
using namespace Poco::Data::Keywords;
using Poco::Data::MySQL::ConnectionException;
@@ -62,6 +57,7 @@ using Poco::DateTime;
using Poco::NumberParser;
using Poco::Any;
using Poco::AnyCast;
using Poco::DynamicAny;
using Poco::NotFoundException;
using Poco::InvalidAccessException;
using Poco::BadCastException;
@@ -562,6 +558,128 @@ void SQLExecutor::doubles()
poco_assert (ret == data);
}
void SQLExecutor::any()
{
std::string funct = "any()";
Any i8 = Poco::Int8(42);
Any i16 = Poco::Int16(420);
Any i32 = Poco::UInt32(42058);
Any i64 = Poco::Int64(2205861);
Any f = float(42.5);
Any d = double(4278.5);
Any s = std::string("42");
Any date = Date(DateTime());
Any t = Time(DateTime());
Any dateTime = DateTime(2017, 9, 2, 18, 49, 15);
Any e;
assert (e.empty());
try { *_pSession << "INSERT INTO Anys VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, null)",
use(i8), use(i16), use(i32), use(i64), use(f), use(d), use(s), use(s), use(date),
use(t), use(dateTime), now; }
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
int count = 0;
try { *_pSession << "SELECT COUNT(*) FROM Anys", into(count), now; }
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
poco_assert (count == 1);
i8 = Poco::Int8(0);
i16 = Poco::Int16(0);
i32 = Poco::Int32(0);
i64 = Poco::Int64(0);
f = 0.0f;
d = 0.0;
s = std::string("");
Any s2 = std::string("");
Any dateR = Date();
Any tR = Time();
Any dateTimeR = DateTime(2010, 5, 25);
e = 1;
assert (!e.empty());
try { *_pSession << "SELECT * FROM Anys", into(i8), into(i16), into(i32), into(i64),
into(f), into(d), into(s), into(s2), into(dateR), into(tR), into(dateTimeR), into(e), now; }
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
assert (42 == AnyCast<Poco::Int8>(i8));
assert (420 == AnyCast<Poco::Int16>(i16));
assert (42058 == AnyCast<Poco::Int32>(i32));
assert (2205861 == AnyCast<Poco::Int64>(i64));
assert (42.5f == AnyCast<float>(f));
assert (4278.5 == AnyCast<double>(d));
assert ("42" == AnyCast<std::string>(s));
assert ("42" == AnyCast<std::string>(s2));
assert (AnyCast<Date>(date) == AnyCast<Date>(dateR));
assert (AnyCast<Time>(t) == AnyCast<Time>(tR));
assert (AnyCast<DateTime>(dateTimeR) == AnyCast<DateTime>(dateTime));
assert (e.empty());
}
void SQLExecutor::dynamicAny()
{
std::string funct = "dynamicAny()";
DynamicAny i8 = Poco::Int8(42);
DynamicAny i16 = Poco::Int16(420);
DynamicAny i32 = Poco::UInt32(42058);
DynamicAny i64 = Poco::Int64(2205861);
DynamicAny f = float(42.5);
DynamicAny d = double(4278.5);
DynamicAny s = std::string("42");
DynamicAny date = Date(DateTime());
DynamicAny t = Time(DateTime());
DynamicAny dateTime = DateTime();
DynamicAny e;
assert (e.isEmpty());
try { *_pSession << "INSERT INTO Anys VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, null)",
use(i8), use(i16), use(i32), use(i64), use(f), use(d), use(s), use(s), use(date),
use(t), use(dateTime), now; }
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
int count = 0;
try { *_pSession << "SELECT COUNT(*) FROM Anys", into(count), now; }
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
poco_assert (count == 1);
i8 = Poco::Int8(0);
i16 = Poco::Int16(0);
i32 = Poco::Int32(0);
i64 = Poco::Int64(0);
f = 0.0f;
d = 0.0;
s = std::string("");
DynamicAny s2 = std::string("");
DynamicAny dateR = Date();
DynamicAny tR = Time();
DynamicAny dateTimeR = DateTime(2017, 9, 2);
e = 1;
assert (!e.isEmpty());
try { *_pSession << "SELECT * FROM Anys", into(i8), into(i16), into(i32), into(i64),
into(f), into(d), into(s), into(s2), into(dateR), into(tR), into(dateTimeR), into(e), now; }
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
assert (42 == i8);
assert (420 == i16);
assert (42058 == i32);
assert (2205861 == i64);
assert (42.5f == f);
assert (4278.5 == d);
assert ("42" == s);
assert ("42" == s2);
assert (date == dateR);
assert (t == tR);
assert (dateTimeR == dateTime);
assert (e.isEmpty());
}
void SQLExecutor::insertSingleBulkVec()
{

View File

@@ -89,6 +89,8 @@ public:
void unsignedInts();
void floats();
void doubles();
void any();
void dynamicAny();
void tuples();
void tupleVector();