mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-28 03:20:11 +01:00
bulk internal extraction fixes and tests; some renaming/refactoring
This commit is contained in:
@@ -17,7 +17,7 @@ $(error No ODBC library found. Please install unixODBC or iODBC and try again)
|
||||
endif
|
||||
|
||||
objects = Binder ConnectionHandle Connector EnvironmentHandle \
|
||||
Extractor ODBCColumn ODBCException ODBCStatementImpl \
|
||||
Extractor ODBCMetaColumn ODBCException ODBCStatementImpl \
|
||||
Parameter Preparation SessionImpl TypeInfo Unicode Utility
|
||||
|
||||
target = PocoODBC
|
||||
|
||||
@@ -176,7 +176,7 @@
|
||||
RelativePath=".\include\Poco\Data\Odbc\ODBC.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\ODBC\ODBCColumn.h">
|
||||
RelativePath=".\include\Poco\Data\ODBC\ODBCMetaColumn.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\Odbc\ODBCException.h">
|
||||
@@ -228,7 +228,7 @@
|
||||
RelativePath=".\src\Extractor.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\ODBCColumn.cpp">
|
||||
RelativePath=".\src\ODBCMetaColumn.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\ODBCException.cpp">
|
||||
|
||||
@@ -246,11 +246,11 @@
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\ODBC\ODBCColumn.h"
|
||||
RelativePath=".\include\Poco\Data\ODBC\ODBCException.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\ODBC\ODBCException.h"
|
||||
RelativePath=".\include\Poco\Data\ODBC\ODBCMetaColumn.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
@@ -314,11 +314,11 @@
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\ODBCColumn.cpp"
|
||||
RelativePath=".\src\ODBCException.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\ODBCException.cpp"
|
||||
RelativePath=".\src\ODBCMetaColumn.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
#include "Poco/Data/AbstractBinder.h"
|
||||
#include "Poco/Data/ODBC/Handle.h"
|
||||
#include "Poco/Data/ODBC/Parameter.h"
|
||||
#include "Poco/Data/ODBC/ODBCColumn.h"
|
||||
#include "Poco/Data/ODBC/ODBCMetaColumn.h"
|
||||
#include "Poco/Data/ODBC/Utility.h"
|
||||
#include "Poco/Data/ODBC/TypeInfo.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
#include "Poco/Data/ODBC/ODBC.h"
|
||||
#include "Poco/Data/AbstractExtractor.h"
|
||||
#include "Poco/Data/ODBC/Preparation.h"
|
||||
#include "Poco/Data/ODBC/ODBCColumn.h"
|
||||
#include "Poco/Data/ODBC/ODBCMetaColumn.h"
|
||||
#include "Poco/Data/ODBC/Error.h"
|
||||
#include "Poco/Data/ODBC/Utility.h"
|
||||
#include "Poco/DateTime.h"
|
||||
@@ -401,7 +401,7 @@ private:
|
||||
bool extractImpl(std::size_t pos, T& val)
|
||||
/// Utility function for extraction of Any and DynamicAny.
|
||||
{
|
||||
ODBCColumn column(_rStmt, pos);
|
||||
ODBCMetaColumn column(_rStmt, pos);
|
||||
|
||||
switch (column.type())
|
||||
{
|
||||
@@ -504,7 +504,7 @@ inline bool Extractor::isNullLengthIndicator(SQLLEN val) const
|
||||
|
||||
inline SQLINTEGER Extractor::columnSize(std::size_t pos) const
|
||||
{
|
||||
std::size_t size = ODBCColumn(_rStmt, pos).length();
|
||||
std::size_t size = ODBCMetaColumn(_rStmt, pos).length();
|
||||
std::size_t maxSize = _rPreparation.maxDataSize(pos);
|
||||
if (size > maxSize) size = maxSize;
|
||||
return (SQLINTEGER) size;
|
||||
|
||||
@@ -77,8 +77,13 @@ public:
|
||||
~Handle()
|
||||
/// Destroys the Handle.
|
||||
{
|
||||
SQLRETURN rc = SQLFreeHandle(handleType, _handle);
|
||||
poco_assert (!Utility::isError(rc));
|
||||
#if defined(_DEBUG)
|
||||
SQLRETURN rc =
|
||||
#endif
|
||||
SQLFreeHandle(handleType, _handle);
|
||||
// N.B. Destructors should not throw, but neither do we want to
|
||||
// leak resources. So, we throw here in debug mode if things go bad.
|
||||
poco_assert_dbg (!Utility::isError(rc));
|
||||
}
|
||||
|
||||
operator const H& () const
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
//
|
||||
// ODBCColumn.h
|
||||
// ODBCMetaColumn.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/ODBC/include/Poco/Data/ODBC/ODBCColumn.h#3 $
|
||||
// $Id: //poco/Main/Data/ODBC/include/Poco/Data/ODBC/ODBCMetaColumn.h#3 $
|
||||
//
|
||||
// Library: ODBC
|
||||
// Package: ODBC
|
||||
// Module: ODBCColumn
|
||||
// Module: ODBCMetaColumn
|
||||
//
|
||||
// Definition of ODBCColumn.
|
||||
// Definition of ODBCMetaColumn.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
@@ -56,14 +56,14 @@ namespace Data {
|
||||
namespace ODBC {
|
||||
|
||||
|
||||
class ODBC_API ODBCColumn: public MetaColumn
|
||||
class ODBC_API ODBCMetaColumn: public MetaColumn
|
||||
{
|
||||
public:
|
||||
explicit ODBCColumn(const StatementHandle& rStmt, std::size_t position);
|
||||
/// Creates the ODBCColumn.
|
||||
explicit ODBCMetaColumn(const StatementHandle& rStmt, std::size_t position);
|
||||
/// Creates the ODBCMetaColumn.
|
||||
|
||||
~ODBCColumn();
|
||||
/// Destroys the ODBCColumn.
|
||||
~ODBCMetaColumn();
|
||||
/// Destroys the ODBCMetaColumn.
|
||||
|
||||
std::size_t dataLength() const;
|
||||
/// A numeric value that is either the maximum or actual character length of a character
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
/// This information is returned from the SQL_DESC_LENGTH record field of the IRD.
|
||||
|
||||
private:
|
||||
ODBCColumn();
|
||||
ODBCMetaColumn();
|
||||
|
||||
static const int NAME_BUFFER_LENGTH = 2048;
|
||||
|
||||
@@ -99,7 +99,7 @@ private:
|
||||
///
|
||||
/// inlines
|
||||
///
|
||||
inline std::size_t ODBCColumn::dataLength() const
|
||||
inline std::size_t ODBCMetaColumn::dataLength() const
|
||||
{
|
||||
return _dataLength;
|
||||
}
|
||||
@@ -45,7 +45,7 @@
|
||||
#include "Poco/Data/ODBC/Binder.h"
|
||||
#include "Poco/Data/ODBC/Extractor.h"
|
||||
#include "Poco/Data/ODBC/Preparation.h"
|
||||
#include "Poco/Data/ODBC/ODBCColumn.h"
|
||||
#include "Poco/Data/ODBC/ODBCMetaColumn.h"
|
||||
#include "Poco/Data/StatementImpl.h"
|
||||
#include "Poco/Data/Column.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
@@ -66,7 +66,7 @@ class ODBC_API ODBCStatementImpl: public Poco::Data::StatementImpl
|
||||
/// Implements statement functionality needed for ODBC
|
||||
{
|
||||
public:
|
||||
typedef std::vector<ODBCColumn*> ColumnPtrVec;
|
||||
typedef std::vector<ODBCMetaColumn*> ColumnPtrVec;
|
||||
|
||||
ODBCStatementImpl(SessionImpl& rSession);
|
||||
/// Creates the ODBCStatementImpl.
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
#include "Poco/Data/ODBC/ODBC.h"
|
||||
#include "Poco/Data/ODBC/Handle.h"
|
||||
#include "Poco/Data/ODBC/ODBCColumn.h"
|
||||
#include "Poco/Data/ODBC/ODBCMetaColumn.h"
|
||||
#include "Poco/Data/ODBC/Utility.h"
|
||||
#include "Poco/Data/AbstractPreparation.h"
|
||||
#include "Poco/Data/BLOB.h"
|
||||
@@ -415,7 +415,7 @@ private:
|
||||
void prepareImpl(std::size_t pos, const C* pVal = 0)
|
||||
/// Utility function to prepare Any and DynamicAny.
|
||||
{
|
||||
ODBCColumn col(_rStmt, pos);
|
||||
ODBCMetaColumn col(_rStmt, pos);
|
||||
|
||||
switch (col.type())
|
||||
{
|
||||
|
||||
@@ -444,7 +444,7 @@ void Binder::getColSizeAndPrecision(std::size_t pos,
|
||||
|
||||
try
|
||||
{
|
||||
ODBCColumn c(_rStmt, pos);
|
||||
ODBCMetaColumn c(_rStmt, pos);
|
||||
colSize = (SQLINTEGER) c.length();
|
||||
decDigits = (SQLSMALLINT) c.precision();
|
||||
return;
|
||||
@@ -465,7 +465,7 @@ void Binder::getColumnOrParameterSize(std::size_t pos, SQLINTEGER& size)
|
||||
|
||||
try
|
||||
{
|
||||
ODBCColumn col(_rStmt, pos);
|
||||
ODBCMetaColumn col(_rStmt, pos);
|
||||
colSize = col.length();
|
||||
}
|
||||
catch (StatementException&) { }
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
|
||||
#include "Poco/Data/ODBC/Extractor.h"
|
||||
#include "Poco/Data/ODBC/ODBCColumn.h"
|
||||
#include "Poco/Data/ODBC/ODBCMetaColumn.h"
|
||||
#include "Poco/Data/ODBC/Utility.h"
|
||||
#include "Poco/Data/ODBC/ODBCException.h"
|
||||
#include "Poco/Data/BLOB.h"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
//
|
||||
// ODBCColumn.cpp
|
||||
// ODBCMetaColumn.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/ODBC/src/ODBCColumn.cpp#5 $
|
||||
// $Id: //poco/Main/Data/ODBC/src/ODBCMetaColumn.cpp#5 $
|
||||
//
|
||||
// Library: ODBC
|
||||
// Package: ODBC
|
||||
// Module: ODBCColumn
|
||||
// Module: ODBCMetaColumn
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
@@ -34,7 +34,7 @@
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/ODBC/ODBCColumn.h"
|
||||
#include "Poco/Data/ODBC/ODBCMetaColumn.h"
|
||||
#include "Poco/Data/ODBC/Utility.h"
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Data {
|
||||
namespace ODBC {
|
||||
|
||||
|
||||
ODBCColumn::ODBCColumn(const StatementHandle& rStmt, std::size_t position) :
|
||||
ODBCMetaColumn::ODBCMetaColumn(const StatementHandle& rStmt, std::size_t position) :
|
||||
MetaColumn(position),
|
||||
_rStmt(rStmt)
|
||||
{
|
||||
@@ -51,12 +51,12 @@ ODBCColumn::ODBCColumn(const StatementHandle& rStmt, std::size_t position) :
|
||||
}
|
||||
|
||||
|
||||
ODBCColumn::~ODBCColumn()
|
||||
ODBCMetaColumn::~ODBCMetaColumn()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ODBCColumn::getDescription()
|
||||
void ODBCMetaColumn::getDescription()
|
||||
{
|
||||
memset(_columnDesc.name, 0, NAME_BUFFER_LENGTH);
|
||||
_columnDesc.nameBufferLength = 0;
|
||||
@@ -80,7 +80,7 @@ void ODBCColumn::getDescription()
|
||||
}
|
||||
|
||||
|
||||
void ODBCColumn::init()
|
||||
void ODBCMetaColumn::init()
|
||||
{
|
||||
getDescription();
|
||||
|
||||
@@ -414,7 +414,7 @@ void ODBCStatementImpl::fillColumns()
|
||||
Poco::UInt32 colCount = columnsReturned();
|
||||
|
||||
for (int i = 0; i < colCount; ++i)
|
||||
_columnPtrs.push_back(new ODBCColumn(_stmt, i));
|
||||
_columnPtrs.push_back(new ODBCMetaColumn(_stmt, i));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
|
||||
#include "Poco/Data/ODBC/Preparation.h"
|
||||
#include "Poco/Data/ODBC/ODBCColumn.h"
|
||||
#include "Poco/Data/ODBC/ODBCMetaColumn.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -154,7 +154,7 @@ std::size_t Preparation::maxDataSize(std::size_t pos) const
|
||||
|
||||
try
|
||||
{
|
||||
sz = ODBCColumn(_rStmt, pos).length();
|
||||
sz = ODBCMetaColumn(_rStmt, pos).length();
|
||||
}
|
||||
catch (StatementException&) { }
|
||||
|
||||
|
||||
@@ -588,6 +588,7 @@ CppUnit::Test* ODBCDB2Test::suite()
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testLimitZero);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testPrepare);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testBulk);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testBulkPerformance);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testSetSimple);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testSetComplex);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testSetComplexUnique);
|
||||
@@ -618,6 +619,7 @@ CppUnit::Test* ODBCDB2Test::suite()
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testTuple);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testTupleVector);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testInternalExtraction);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testInternalBulkExtraction);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testInternalStorageType);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testStoredProcedure);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testStoredProcedureAny);
|
||||
|
||||
@@ -406,6 +406,7 @@ CppUnit::Test* ODBCMySQLTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testLimitZero);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testPrepare);
|
||||
//CppUnit_addTest(pSuite, ODBCMySQLTest, testBulk);
|
||||
//CppUnit_addTest(pSuite, ODBCMySQLTest, testBulkPerformance);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testSetSimple);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testSetComplex);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testSetComplexUnique);
|
||||
@@ -438,6 +439,7 @@ CppUnit::Test* ODBCMySQLTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testStoredProcedure);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testStoredFunction);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testInternalExtraction);
|
||||
//CppUnit_addTest(pSuite, ODBCOracleTest, testInternalBulkExtraction);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testInternalStorageType);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testNull);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testRowIterator);
|
||||
|
||||
@@ -788,6 +788,7 @@ CppUnit::Test* ODBCOracleTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testLimitZero);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testPrepare);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testBulk);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testBulkPerformance);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testSetSimple);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testSetComplex);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testSetComplexUnique);
|
||||
@@ -823,6 +824,7 @@ CppUnit::Test* ODBCOracleTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testStoredFunction);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testCursorStoredFunction);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testInternalExtraction);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testInternalBulkExtraction);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testInternalStorageType);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testNull);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testRowIterator);
|
||||
|
||||
@@ -522,7 +522,6 @@ void ODBCPostgreSQLTest::recreateMiscTable()
|
||||
dropObject("TABLE", "MiscTest");
|
||||
try
|
||||
{
|
||||
// pgSQL fails with BLOB bulk operations
|
||||
// Mammoth does not bind columns properly
|
||||
session() << "CREATE TABLE MiscTest "
|
||||
"(First VARCHAR(30),"
|
||||
@@ -567,7 +566,12 @@ CppUnit::Test* ODBCPostgreSQLTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testLimitPrepare);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testLimitZero);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testPrepare);
|
||||
//On Linux, PostgreSQL driver returns SQL_NEED_DATA on SQLExecute (see ODBCStatementImpl::bindImpl() )
|
||||
//this behavior is not expected and not handled for automatic binding
|
||||
#ifdef POCO_OS_FAMILY_WINDOWS
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testBulk);
|
||||
#endif
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testBulkPerformance);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSetSimple);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSetComplex);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSetComplexUnique);
|
||||
@@ -598,6 +602,11 @@ CppUnit::Test* ODBCPostgreSQLTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTuple);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTupleVector);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testInternalExtraction);
|
||||
//On Linux, PostgreSQL driver returns SQL_NEED_DATA on SQLExecute (see ODBCStatementImpl::bindImpl() )
|
||||
//this behavior is not expected and not handled for automatic binding
|
||||
#ifdef POCO_OS_FAMILY_WINDOWS
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testInternalBulkExtraction);
|
||||
#endif
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testInternalStorageType);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testStoredFunction);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testStoredFunctionAny);
|
||||
|
||||
@@ -218,9 +218,6 @@ void ODBCSQLServerTest::testBulk()
|
||||
std::list<double>,
|
||||
std::list<DateTime>,
|
||||
std::list<bool> >(100);
|
||||
|
||||
recreateMiscTable();
|
||||
_pExecutor->doBulkPerformance(1000);
|
||||
}
|
||||
|
||||
|
||||
@@ -696,6 +693,7 @@ CppUnit::Test* ODBCSQLServerTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testLimitZero);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testPrepare);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testBulk);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testBulkPerformance);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSetSimple);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSetComplex);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSetComplexUnique);
|
||||
@@ -729,6 +727,7 @@ CppUnit::Test* ODBCSQLServerTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testStoredProcedureDynamicAny);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testStoredFunction);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testInternalExtraction);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testInternalBulkExtraction);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testInternalStorageType);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testNull);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testRowIterator);
|
||||
|
||||
@@ -435,6 +435,15 @@ void ODBCTest::testBulk()
|
||||
std::list<BLOB>,
|
||||
std::list<double>,
|
||||
std::list<DateTime> >(100);
|
||||
}
|
||||
|
||||
|
||||
void ODBCTest::testBulkPerformance()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
_pSession->setFeature("autoBind", true);
|
||||
_pSession->setFeature("autoExtract", true);
|
||||
|
||||
recreateMiscTable();
|
||||
_pExecutor->doBulkPerformance(1000);
|
||||
@@ -894,6 +903,17 @@ void ODBCTest::testInternalExtraction()
|
||||
}
|
||||
|
||||
|
||||
void ODBCTest::testInternalBulkExtraction()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
recreatePersonTable();
|
||||
_pSession->setFeature("autoBind", true);
|
||||
_pSession->setFeature("autoExtract", true);
|
||||
_pExecutor->internalBulkExtraction();
|
||||
}
|
||||
|
||||
|
||||
void ODBCTest::testInternalStorageType()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
@@ -92,6 +92,7 @@ public:
|
||||
virtual void testLimitZero();
|
||||
virtual void testPrepare();
|
||||
virtual void testBulk();
|
||||
virtual void testBulkPerformance();
|
||||
|
||||
virtual void testSetSimple();
|
||||
virtual void testSetComplex();
|
||||
@@ -128,6 +129,7 @@ public:
|
||||
virtual void testTupleVector();
|
||||
|
||||
virtual void testInternalExtraction();
|
||||
virtual void testInternalBulkExtraction();
|
||||
virtual void testInternalStorageType();
|
||||
|
||||
virtual void testStoredProcedure() { /* no-op */ };
|
||||
|
||||
@@ -2422,9 +2422,9 @@ void SQLExecutor::internalExtraction()
|
||||
i = rset.value("str0", 2);
|
||||
assert (5 == i);
|
||||
|
||||
const Column<int>& col = rset.column<int, std::deque<int> >(0);
|
||||
Column<int>::Iterator it = col.begin();
|
||||
Column<int>::Iterator end = col.end();
|
||||
const Column<std::deque<int> >& col = rset.column<std::deque<int>, InternalExtraction<std::deque<int> > >(0);
|
||||
Column<std::deque<int> >::Iterator it = col.begin();
|
||||
Column<std::deque<int> >::Iterator end = col.end();
|
||||
for (int i = 1; it != end; ++it, ++i)
|
||||
assert (*it == i);
|
||||
|
||||
@@ -2456,7 +2456,7 @@ void SQLExecutor::internalExtraction()
|
||||
s = rset.value("cnt", 0).convert<std::string>();
|
||||
assert ("4" == s);
|
||||
|
||||
try { rset.column<int, std::vector<int> >(100); fail ("must fail"); }
|
||||
try { rset.column<std::deque<int>, InternalExtraction<std::deque<int> > >(100); fail ("must fail"); }
|
||||
catch (RangeException&) { }
|
||||
|
||||
try { rset.value<std::string>(0,0); fail ("must fail"); }
|
||||
@@ -2465,7 +2465,7 @@ void SQLExecutor::internalExtraction()
|
||||
stmt = (session() << "DELETE FROM Vectors", now);
|
||||
rset = stmt;
|
||||
|
||||
try { rset.column<int, std::vector<int> >(0); fail ("must fail"); }
|
||||
try { rset.column<std::deque<int>, InternalExtraction<std::deque<int> > >(0); fail ("must fail"); }
|
||||
catch (RangeException&) { }
|
||||
}
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
@@ -2473,6 +2473,65 @@ void SQLExecutor::internalExtraction()
|
||||
}
|
||||
|
||||
|
||||
void SQLExecutor::internalBulkExtraction()
|
||||
{
|
||||
std::string funct = "internalBulkExtraction()";
|
||||
int size = 100;
|
||||
std::vector<std::string> lastName(size);
|
||||
std::vector<std::string> firstName(size);
|
||||
std::vector<std::string> address(size);
|
||||
std::vector<int> age(size);
|
||||
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
lastName[i] = "LN" + NumberFormatter::format(i);
|
||||
firstName[i] = "FN" + NumberFormatter::format(i);
|
||||
address[i] = "Addr" + NumberFormatter::format(i);
|
||||
age[i] = i;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
session() << "INSERT INTO Person VALUES (?,?,?,?)",
|
||||
use(lastName, bulk),
|
||||
use(firstName, bulk),
|
||||
use(address, bulk),
|
||||
use(age, bulk),
|
||||
now;
|
||||
}
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
|
||||
try
|
||||
{
|
||||
Statement stmt = (session() << "SELECT * FROM Person", bulk(size), now);
|
||||
RecordSet rset(stmt);
|
||||
assert (size == rset.rowCount());
|
||||
assert ("LN0" == rset["LastName"]);
|
||||
assert (0 == rset["Age"]);
|
||||
rset.moveLast();
|
||||
assert (std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]);
|
||||
assert (size - 1 == rset["Age"]);
|
||||
}
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
|
||||
try
|
||||
{
|
||||
Statement stmt = (session() << "SELECT * FROM Person", limit(size), bulk, now);
|
||||
RecordSet rset(stmt);
|
||||
assert (size == rset.rowCount());
|
||||
assert ("LN0" == rset["LastName"]);
|
||||
assert (0 == rset["Age"]);
|
||||
rset.moveLast();
|
||||
assert (std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]);
|
||||
assert (size - 1 == rset["Age"]);
|
||||
}
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
}
|
||||
|
||||
|
||||
void SQLExecutor::internalStorageType()
|
||||
{
|
||||
std::string funct = "internalStorageType()";
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "Poco/Data/ODBC/ODBC.h"
|
||||
#include "Poco/Data/ODBC/Utility.h"
|
||||
#include "Poco/Data/ODBC/ODBCException.h"
|
||||
#include "Poco/Data/Session.h"
|
||||
#include "Poco/Data/BulkExtraction.h"
|
||||
#include "Poco/Data/BulkBinding.h"
|
||||
@@ -51,7 +52,7 @@
|
||||
Poco::Data::ODBC::EnvironmentException ee(h); \
|
||||
std::cout << ee.toString() << std::endl; \
|
||||
} \
|
||||
assert (SQL_SUCCEEDED(r));
|
||||
assert (SQL_SUCCEEDED(r))
|
||||
|
||||
|
||||
#define poco_odbc_check_dbc(r, h) \
|
||||
@@ -60,7 +61,7 @@
|
||||
Poco::Data::ODBC::ConnectionException ce(h); \
|
||||
std::cout << ce.toString() << std::endl; \
|
||||
} \
|
||||
assert (SQL_SUCCEEDED(r));
|
||||
assert (SQL_SUCCEEDED(r))
|
||||
|
||||
|
||||
#define poco_odbc_check_stmt(r, h) \
|
||||
@@ -69,7 +70,7 @@
|
||||
Poco::Data::ODBC::StatementException se(h); \
|
||||
std::cout << se.toString() << std::endl; \
|
||||
} \
|
||||
assert (SQL_SUCCEEDED(r));
|
||||
assert (SQL_SUCCEEDED(r))
|
||||
|
||||
|
||||
#define poco_odbc_check_desc(r, h) \
|
||||
@@ -78,7 +79,17 @@
|
||||
Poco::Data::ODBC::DescriptorException de(h); \
|
||||
std::cout << de.toString() << std::endl; \
|
||||
} \
|
||||
assert (SQL_SUCCEEDED(r));
|
||||
assert (SQL_SUCCEEDED(r))
|
||||
|
||||
|
||||
#define poco_data_using_statements using Poco::Data::now; \
|
||||
using Poco::Data::into; \
|
||||
using Poco::Data::use; \
|
||||
using Poco::Data::bulk; \
|
||||
using Poco::Data::limit; \
|
||||
using Poco::Data::BLOB; \
|
||||
using Poco::Data::ODBC::ConnectionException; \
|
||||
using Poco::Data::ODBC::StatementException
|
||||
|
||||
|
||||
class SQLExecutor: public CppUnit::TestCase
|
||||
@@ -148,6 +159,8 @@ public:
|
||||
template <typename C1, typename C2, typename C3, typename C4, typename C5, typename C6>
|
||||
void doBulkWithBool(Poco::UInt32 size)
|
||||
{
|
||||
poco_data_using_statements;
|
||||
|
||||
std::string funct = "doBulkWithBool()";
|
||||
C1 ints;
|
||||
C2 strings;
|
||||
@@ -287,6 +300,8 @@ public:
|
||||
template <typename C1, typename C2, typename C3, typename C4, typename C5>
|
||||
void doBulk(Poco::UInt32 size)
|
||||
{
|
||||
poco_data_using_statements;
|
||||
|
||||
std::string funct = "doBulk()";
|
||||
C1 ints;
|
||||
C2 strings;
|
||||
@@ -431,6 +446,8 @@ public:
|
||||
template <typename C1, typename C2>
|
||||
void blobContainer(int size)
|
||||
{
|
||||
poco_data_using_statements;
|
||||
|
||||
std::string funct = "blobContainer()";
|
||||
C1 lastName(size, "lastname");
|
||||
C1 firstName(size, "firstname");
|
||||
@@ -464,6 +481,7 @@ public:
|
||||
void tupleVector();
|
||||
|
||||
void internalExtraction();
|
||||
void internalBulkExtraction();
|
||||
void internalStorageType();
|
||||
void nulls();
|
||||
void notNulls(const std::string& sqlState = "23502");
|
||||
|
||||
@@ -96,14 +96,14 @@ inline Bulk bulk(const T& limit)
|
||||
}
|
||||
|
||||
|
||||
inline void bulk()
|
||||
inline void bulk(char)
|
||||
/// Dummy bulk function. Used for bulk binding creation
|
||||
/// (see BulkBinding.h).
|
||||
/// (see BulkBinding) and bulk extraction signalling to Statement.
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
typedef void (*BulkFnType)();
|
||||
typedef void (*BulkFnType)(char);
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
||||
|
||||
@@ -59,16 +59,18 @@ class BulkExtraction: public AbstractExtraction
|
||||
/// - std::list
|
||||
{
|
||||
public:
|
||||
typedef typename C::value_type T;
|
||||
|
||||
BulkExtraction(C& result, Poco::UInt32 limit):
|
||||
AbstractExtraction(limit, 0, true),
|
||||
_rResult(result),
|
||||
_default(1)
|
||||
_default()
|
||||
{
|
||||
if (static_cast<Poco::UInt32>(result.size()) != limit)
|
||||
result.resize(limit);
|
||||
}
|
||||
|
||||
BulkExtraction(C& result, const C& def, Poco::UInt32 limit):
|
||||
BulkExtraction(C& result, const T& def, Poco::UInt32 limit):
|
||||
AbstractExtraction(limit, 0, true),
|
||||
_rResult(result),
|
||||
_default(def)
|
||||
@@ -139,7 +141,7 @@ protected:
|
||||
|
||||
private:
|
||||
C& _rResult;
|
||||
C _default;
|
||||
T _default;
|
||||
std::deque<bool> _nulls;
|
||||
};
|
||||
|
||||
@@ -152,15 +154,15 @@ class InternalBulkExtraction: public BulkExtraction<C>
|
||||
/// to automaticaly create internal BulkExtraction in cases when statement returns data and no external storage
|
||||
/// was supplied. It is later used by RecordSet to retrieve the fetched data after statement execution.
|
||||
/// It takes ownership of the Column pointer supplied as constructor argument. Column object, in turn
|
||||
/// owns the data vector pointer.
|
||||
/// owns the data container pointer.
|
||||
///
|
||||
/// InternalBulkExtraction objects can not be copied or assigned.
|
||||
{
|
||||
public:
|
||||
typedef typename C::value_type T;
|
||||
|
||||
explicit InternalBulkExtraction(C& result, Column<T,C>* pColumn, Poco::UInt32 limit):
|
||||
BulkExtraction<C>(result, _default, limit),
|
||||
explicit InternalBulkExtraction(C& result, Column<C>* pColumn, Poco::UInt32 limit):
|
||||
BulkExtraction<C>(result, T(), limit),
|
||||
_pColumn(pColumn)
|
||||
/// Creates InternalBulkExtraction.
|
||||
{
|
||||
@@ -194,7 +196,7 @@ public:
|
||||
return BulkExtraction<C>::isNull(row);
|
||||
}
|
||||
|
||||
const Column<T,C>& column() const
|
||||
const Column<C>& column() const
|
||||
{
|
||||
return *_pColumn;
|
||||
}
|
||||
@@ -204,8 +206,7 @@ private:
|
||||
InternalBulkExtraction(const InternalBulkExtraction&);
|
||||
InternalBulkExtraction& operator = (const InternalBulkExtraction&);
|
||||
|
||||
Column<T,C>* _pColumn;
|
||||
C _default;
|
||||
Column<C>* _pColumn;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
|
||||
template <class T, class C = std::deque<T> >
|
||||
template <class C>
|
||||
class Column
|
||||
/// Column class is column data container.
|
||||
/// Data (a pointer to container) is assigned to the class
|
||||
@@ -65,8 +65,9 @@ public:
|
||||
typedef typename Container::const_iterator Iterator;
|
||||
typedef typename Container::const_reverse_iterator RIterator;
|
||||
typedef typename Container::size_type Size;
|
||||
typedef typename Container::value_type Type;
|
||||
|
||||
Column(const MetaColumn& metaColumn, C* pData): _metaColumn(metaColumn), _pData(pData)
|
||||
Column(const MetaColumn& metaColumn, Container* pData): _metaColumn(metaColumn), _pData(pData)
|
||||
/// Creates the Column.
|
||||
{
|
||||
poco_check_ptr (_pData);
|
||||
@@ -104,7 +105,7 @@ public:
|
||||
return *_pData;
|
||||
}
|
||||
|
||||
const T& value(std::size_t row) const
|
||||
const Type& value(std::size_t row) const
|
||||
/// Returns the field value in specified row.
|
||||
{
|
||||
try
|
||||
@@ -117,7 +118,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
const T& operator [] (std::size_t row) const
|
||||
const Type& operator [] (std::size_t row) const
|
||||
/// Returns the field value in specified row.
|
||||
{
|
||||
return value(row);
|
||||
@@ -132,7 +133,7 @@ public:
|
||||
void reset()
|
||||
/// Clears and shrinks the storage.
|
||||
{
|
||||
C().swap(*_pData);
|
||||
Container().swap(*_pData);
|
||||
}
|
||||
|
||||
const std::string& name() const
|
||||
@@ -187,7 +188,7 @@ private:
|
||||
|
||||
|
||||
template <>
|
||||
class Column<bool, std::vector<bool> >
|
||||
class Column<std::vector<bool> >
|
||||
/// The std::vector<bool> specialization for the Column class.
|
||||
///
|
||||
/// This specialization is necessary due to the nature of std::vector<bool>.
|
||||
@@ -339,7 +340,7 @@ private:
|
||||
|
||||
|
||||
template <class T>
|
||||
class Column<T, std::list<T> >
|
||||
class Column<std::list<T> >
|
||||
/// Column specialization for std::list
|
||||
{
|
||||
public:
|
||||
@@ -485,8 +486,8 @@ private:
|
||||
};
|
||||
|
||||
|
||||
template <typename T, typename C>
|
||||
inline void swap(Column<T,C>& c1, Column<T,C>& c2)
|
||||
template <typename C>
|
||||
inline void swap(Column<C>& c1, Column<C>& c2)
|
||||
{
|
||||
c1.swap(c2);
|
||||
}
|
||||
|
||||
@@ -480,14 +480,14 @@ class InternalExtraction: public Extraction<C>
|
||||
/// to automaticaly create internal Extraction in cases when statement returns data and no external storage
|
||||
/// was supplied. It is later used by RecordSet to retrieve the fetched data after statement execution.
|
||||
/// It takes ownership of the Column pointer supplied as constructor argument. Column object, in turn
|
||||
/// owns the data vector pointer.
|
||||
/// owns the data container pointer.
|
||||
///
|
||||
/// InternalExtraction objects can not be copied or assigned.
|
||||
{
|
||||
public:
|
||||
typedef typename C::value_type T;
|
||||
|
||||
explicit InternalExtraction(C& result, Column<T,C>* pColumn, const Position& pos = Position(0)):
|
||||
explicit InternalExtraction(C& result, Column<C>* pColumn, const Position& pos = Position(0)):
|
||||
Extraction<C>(result, T(), pos),
|
||||
_pColumn(pColumn)
|
||||
/// Creates InternalExtraction.
|
||||
@@ -522,7 +522,7 @@ public:
|
||||
return Extraction<C>::isNull(row);
|
||||
}
|
||||
|
||||
const Column<T,C>& column() const
|
||||
const Column<C>& column() const
|
||||
{
|
||||
return *_pColumn;
|
||||
}
|
||||
@@ -532,7 +532,7 @@ private:
|
||||
InternalExtraction(const InternalExtraction&);
|
||||
InternalExtraction& operator = (const InternalExtraction&);
|
||||
|
||||
Column<T,C>* _pColumn;
|
||||
Column<C>* _pColumn;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
#include "Poco/Data/Data.h"
|
||||
#include "Poco/Data/Extraction.h"
|
||||
#include "Poco/Data/BulkExtraction.h"
|
||||
#include "Poco/Data/Statement.h"
|
||||
#include "Poco/Data/RowIterator.h"
|
||||
#include "Poco/Data/BLOB.h"
|
||||
@@ -100,18 +101,19 @@ public:
|
||||
std::size_t columnCount() const;
|
||||
/// Returns the number of rows in the recordset.
|
||||
|
||||
template <class T, class C>
|
||||
const Column<T,C>& column(const std::string& name) const
|
||||
template <class C, class E>
|
||||
const Column<C>& column(const std::string& name) const
|
||||
/// Returns the reference to the first Column with the specified name.
|
||||
{
|
||||
return column<T,C>(columnPosition<T,C>(name));
|
||||
return column<C,E>(columnPosition<C,E>(name));
|
||||
}
|
||||
|
||||
template <class T, class C>
|
||||
const Column<T,C>& column(std::size_t pos) const
|
||||
template <class C, class E>
|
||||
const Column<C>& column(std::size_t pos) const
|
||||
/// Returns the reference to column at specified location.
|
||||
{
|
||||
typedef const InternalExtraction<C>* ExtractionVecPtr;
|
||||
typedef typename C::value_type T;
|
||||
typedef const E* ExtractionVecPtr;
|
||||
|
||||
const AbstractExtractionVec& rExtractions = extractions();
|
||||
|
||||
@@ -144,12 +146,30 @@ public:
|
||||
switch (storage())
|
||||
{
|
||||
case STORAGE_VECTOR:
|
||||
return column<T, std::vector<T> >(col).value(row);
|
||||
{
|
||||
typedef std::vector<T> C;
|
||||
if (isBulkExtraction())
|
||||
return column<C, InternalBulkExtraction<C> >(col).value(row);
|
||||
else
|
||||
return column<C, InternalExtraction<C> >(col).value(row);
|
||||
}
|
||||
case STORAGE_LIST:
|
||||
return column<T, std::list<T> >(col).value(row);
|
||||
{
|
||||
typedef std::list<T> C;
|
||||
if (isBulkExtraction())
|
||||
return column<C, InternalBulkExtraction<C> >(col).value(row);
|
||||
else
|
||||
return column<C, InternalExtraction<C> >(col).value(row);
|
||||
}
|
||||
case STORAGE_DEQUE:
|
||||
case STORAGE_UNKNOWN:
|
||||
return column<T, std::deque<T> >(col).value(row);
|
||||
{
|
||||
typedef std::deque<T> C;
|
||||
if (isBulkExtraction())
|
||||
return column<C, InternalBulkExtraction<C> >(col).value(row);
|
||||
else
|
||||
return column<C, InternalExtraction<C> >(col).value(row);
|
||||
}
|
||||
default:
|
||||
throw IllegalStateException("Invalid storage setting.");
|
||||
}
|
||||
@@ -162,12 +182,30 @@ public:
|
||||
switch (storage())
|
||||
{
|
||||
case STORAGE_VECTOR:
|
||||
return column<T, std::vector<T> >(name).value(row);
|
||||
{
|
||||
typedef std::vector<T> C;
|
||||
if (isBulkExtraction())
|
||||
return column<C, InternalBulkExtraction<C> >(name).value(row);
|
||||
else
|
||||
return column<C, InternalExtraction<C> >(name).value(row);
|
||||
}
|
||||
case STORAGE_LIST:
|
||||
return column<T, std::list<T> >(name).value(row);
|
||||
{
|
||||
typedef std::list<T> C;
|
||||
if (isBulkExtraction())
|
||||
return column<C, InternalBulkExtraction<C> >(name).value(row);
|
||||
else
|
||||
return column<C, InternalExtraction<C> >(name).value(row);
|
||||
}
|
||||
case STORAGE_DEQUE:
|
||||
case STORAGE_UNKNOWN:
|
||||
return column<T, std::deque<T> >(name).value(row);
|
||||
{
|
||||
typedef std::deque<T> C;
|
||||
if (isBulkExtraction())
|
||||
return column<C, InternalBulkExtraction<C> >(name).value(row);
|
||||
else
|
||||
return column<C, InternalExtraction<C> >(name).value(row);
|
||||
}
|
||||
default:
|
||||
throw IllegalStateException("Invalid storage setting.");
|
||||
}
|
||||
@@ -259,11 +297,12 @@ public:
|
||||
private:
|
||||
RecordSet();
|
||||
|
||||
template<class T, class C>
|
||||
template<class C, class E>
|
||||
std::size_t columnPosition(const std::string& name) const
|
||||
/// Returns the position of the column with specified name.
|
||||
{
|
||||
typedef const InternalExtraction<C>* ExtractionVecPtr;
|
||||
typedef typename C::value_type T;
|
||||
typedef const E* ExtractionVecPtr;
|
||||
|
||||
bool typeFound = false;
|
||||
|
||||
@@ -278,7 +317,7 @@ private:
|
||||
if (pExtraction)
|
||||
{
|
||||
typeFound = true;
|
||||
const Column<T,C>& col = pExtraction->column();
|
||||
const Column<C>& col = pExtraction->column();
|
||||
if (0 == Poco::icompare(name, col.name()))
|
||||
return col.position();
|
||||
}
|
||||
|
||||
@@ -181,14 +181,19 @@ public:
|
||||
|
||||
Statement& operator , (const Bulk& bulk);
|
||||
/// Sets the bulk execution mode (both binding and extraction) for this
|
||||
/// statement.Statement must not have any extracors or binders set at the
|
||||
/// statement.Statement must not have any extractors or binders set at the
|
||||
/// time when this operator is applied.
|
||||
/// Failure to adhere to the above constraint shall result in
|
||||
/// InvalidAccessException.
|
||||
/// Additionally, any binding buffers passed to the statement later
|
||||
/// through use() or in() must be of the same size (determined by size
|
||||
/// of the bulk passed to this function). Since they are resized automatically
|
||||
/// by the framework, the extraction buffers do not have to adhere to this.
|
||||
|
||||
Statement& operator , (BulkFnType);
|
||||
/// Sets the bulk execution mode (both binding and extraction) for this
|
||||
/// statement.Statement must not have any extractors or binders set at the
|
||||
/// time when this operator is applied.
|
||||
/// Additionally, this function requires limit to be set in order to
|
||||
/// determine the bulk size.
|
||||
/// Failure to adhere to the above constraints shall result in
|
||||
/// InvalidAccessException.
|
||||
|
||||
Statement& operator , (const Limit& extrLimit);
|
||||
/// Sets a limit on the maximum number of rows a select is allowed to return.
|
||||
@@ -277,6 +282,9 @@ protected:
|
||||
bool isNull(std::size_t col, std::size_t row) const;
|
||||
/// Returns true if the current row value at column pos is null.
|
||||
|
||||
bool isBulkExtraction() const;
|
||||
/// Returns true if this statement extracts data in bulk.
|
||||
|
||||
private:
|
||||
typedef Poco::SharedPtr<StatementImpl> StatementImplPtr;
|
||||
|
||||
@@ -443,6 +451,12 @@ inline bool Statement::isNull(std::size_t col, std::size_t row) const
|
||||
}
|
||||
|
||||
|
||||
inline bool Statement::isBulkExtraction() const
|
||||
{
|
||||
return _pImpl->isBulkExtraction();
|
||||
}
|
||||
|
||||
|
||||
inline bool Statement::isAsync() const
|
||||
{
|
||||
return _async;
|
||||
|
||||
@@ -295,18 +295,16 @@ private:
|
||||
template <class C>
|
||||
InternalExtraction<C>* createExtract(const MetaColumn& mc)
|
||||
{
|
||||
typedef typename C::value_type T;
|
||||
C* pData = new C;
|
||||
Column<T,C>* pCol = new Column<T,C>(mc, pData);
|
||||
Column<C>* pCol = new Column<C>(mc, pData);
|
||||
return new InternalExtraction<C>(*pData, pCol);
|
||||
}
|
||||
|
||||
template <class C>
|
||||
InternalBulkExtraction<C>* createBulkExtract(const MetaColumn& mc)
|
||||
{
|
||||
typedef typename C::value_type T;
|
||||
C* pData = new C;
|
||||
Column<T,C>* pCol = new Column<T,C>(mc, pData);
|
||||
Column<C>* pCol = new Column<C>(mc, pData);
|
||||
return new InternalBulkExtraction<C>(*pData, pCol, getExtractionLimit());
|
||||
}
|
||||
|
||||
|
||||
@@ -160,13 +160,12 @@ private:
|
||||
};
|
||||
|
||||
|
||||
template <class C>
|
||||
class TypeHandler<std::deque<C> >: public AbstractTypeHandler
|
||||
template <class T>
|
||||
class TypeHandler<std::deque<T> >: public AbstractTypeHandler
|
||||
/// Specialization of type handler for std::deque.
|
||||
/// Used by bulk extraction.
|
||||
{
|
||||
public:
|
||||
static void bind(std::size_t pos, const std::deque<C>& obj, AbstractBinder* pBinder, AbstractBinder::Direction dir)
|
||||
static void bind(std::size_t pos, const std::deque<T>& obj, AbstractBinder* pBinder, AbstractBinder::Direction dir)
|
||||
{
|
||||
poco_assert_dbg (pBinder != 0);
|
||||
pBinder->bind(pos, obj, dir);
|
||||
@@ -177,21 +176,14 @@ public:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void extract(std::size_t pos, std::deque<C>& obj, const std::deque<C>& defVal, AbstractExtractor* pExt)
|
||||
static void extract(std::size_t pos, std::deque<T>& obj, const T& defVal, AbstractExtractor* pExt)
|
||||
{
|
||||
poco_assert_dbg (pExt != 0);
|
||||
if (!pExt->extract(pos, obj))
|
||||
{
|
||||
if (defVal.size() == 1)
|
||||
obj.assign(obj.size(), defVal.front());
|
||||
else if (defVal.size() > 1)
|
||||
obj.assign(defVal.begin(), defVal.end());
|
||||
else
|
||||
throw InvalidArgumentException("Size of default value container must not be zero.");
|
||||
}
|
||||
obj.assign(obj.size(), defVal);
|
||||
}
|
||||
|
||||
static void prepare(std::size_t pos, std::deque<C>& obj, AbstractPreparation* pPrepare)
|
||||
static void prepare(std::size_t pos, std::deque<T>& obj, AbstractPreparation* pPrepare)
|
||||
{
|
||||
poco_assert_dbg (pPrepare != 0);
|
||||
pPrepare->prepare(pos, obj);
|
||||
@@ -203,15 +195,12 @@ private:
|
||||
};
|
||||
|
||||
|
||||
template <class C>
|
||||
class TypeHandler<std::vector<C> >: public AbstractTypeHandler
|
||||
template <class T>
|
||||
class TypeHandler<std::vector<T> >: public AbstractTypeHandler
|
||||
/// Specialization of type handler for std::vector.
|
||||
/// Used by bulk extraction.
|
||||
{
|
||||
public:
|
||||
typedef typename std::vector<C>::value_type T;
|
||||
|
||||
static void bind(std::size_t pos, const std::vector<C>& obj, AbstractBinder* pBinder, AbstractBinder::Direction dir)
|
||||
static void bind(std::size_t pos, const std::vector<T>& obj, AbstractBinder* pBinder, AbstractBinder::Direction dir)
|
||||
{
|
||||
poco_assert_dbg (pBinder != 0);
|
||||
pBinder->bind(pos, obj, dir);
|
||||
@@ -222,21 +211,14 @@ public:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void extract(std::size_t pos, std::vector<C>& obj, const std::vector<C>& defVal, AbstractExtractor* pExt)
|
||||
static void extract(std::size_t pos, std::vector<T>& obj, const T& defVal, AbstractExtractor* pExt)
|
||||
{
|
||||
poco_assert_dbg (pExt != 0);
|
||||
if (!pExt->extract(pos, obj))
|
||||
{
|
||||
if (defVal.size() == 1)
|
||||
obj.assign(obj.size(), defVal.front());
|
||||
else if (defVal.size() > 1)
|
||||
obj.assign(defVal.begin(), defVal.end());
|
||||
else
|
||||
throw InvalidArgumentException("Size of default value container must not be zero.");
|
||||
}
|
||||
obj.assign(obj.size(), defVal);
|
||||
}
|
||||
|
||||
static void prepare(std::size_t pos, std::vector<C>& obj, AbstractPreparation* pPrepare)
|
||||
static void prepare(std::size_t pos, std::vector<T>& obj, AbstractPreparation* pPrepare)
|
||||
{
|
||||
poco_assert_dbg (pPrepare != 0);
|
||||
pPrepare->prepare(pos, obj);
|
||||
@@ -248,13 +230,12 @@ private:
|
||||
};
|
||||
|
||||
|
||||
template <class C>
|
||||
class TypeHandler<std::list<C> >: public AbstractTypeHandler
|
||||
template <class T>
|
||||
class TypeHandler<std::list<T> >: public AbstractTypeHandler
|
||||
/// Specialization of type handler for std::list.
|
||||
/// Used by bulk extraction.
|
||||
{
|
||||
public:
|
||||
static void bind(std::size_t pos, const std::list<C>& obj, AbstractBinder* pBinder, AbstractBinder::Direction dir)
|
||||
static void bind(std::size_t pos, const std::list<T>& obj, AbstractBinder* pBinder, AbstractBinder::Direction dir)
|
||||
{
|
||||
poco_assert_dbg (pBinder != 0);
|
||||
pBinder->bind(pos, obj, dir);
|
||||
@@ -265,21 +246,14 @@ public:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void extract(std::size_t pos, std::list<C>& obj, const std::list<C>& defVal, AbstractExtractor* pExt)
|
||||
static void extract(std::size_t pos, std::list<T>& obj, const T& defVal, AbstractExtractor* pExt)
|
||||
{
|
||||
poco_assert_dbg (pExt != 0);
|
||||
if (!pExt->extract(pos, obj))
|
||||
{
|
||||
if (defVal.size() == 1)
|
||||
obj.assign(obj.size(), defVal.front());
|
||||
else if (defVal.size() > 1)
|
||||
obj.assign(defVal.begin(), defVal.end());
|
||||
else
|
||||
throw InvalidArgumentException("Size of default value container must not be zero.");
|
||||
}
|
||||
obj.assign(obj.size(), defVal);
|
||||
}
|
||||
|
||||
static void prepare(std::size_t pos, std::list<C>& obj, AbstractPreparation* pPrepare)
|
||||
static void prepare(std::size_t pos, std::list<T>& obj, AbstractPreparation* pPrepare)
|
||||
{
|
||||
poco_assert_dbg (pPrepare != 0);
|
||||
pPrepare->prepare(pos, obj);
|
||||
|
||||
@@ -269,7 +269,6 @@ Statement& Statement::operator , (const Bulk& bulk)
|
||||
_pImpl->bulkExtractionAllowed() &&
|
||||
_pImpl->bulkBindingAllowed())
|
||||
{
|
||||
Limit l(_pImpl->getExtractionLimit(), false, false);
|
||||
_pImpl->setBulkExtraction(bulk);
|
||||
_pImpl->setBulkBinding();
|
||||
}
|
||||
@@ -280,4 +279,23 @@ Statement& Statement::operator , (const Bulk& bulk)
|
||||
}
|
||||
|
||||
|
||||
Statement& Statement::operator , (BulkFnType)
|
||||
{
|
||||
const Limit& limit(_pImpl->extractionLimit());
|
||||
if (limit.isHardLimit() ||
|
||||
limit.isLowerLimit() ||
|
||||
Limit::LIMIT_UNLIMITED == limit.value())
|
||||
{
|
||||
throw InvalidAccessException("Bulk is only allowed with limited extraction,"
|
||||
"non-hard and zero-based limits.");
|
||||
}
|
||||
|
||||
Bulk bulk(limit);
|
||||
_pImpl->setBulkExtraction(bulk);
|
||||
_pImpl->setBulkBinding();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
||||
|
||||
@@ -380,7 +380,7 @@ void DataTest::testColumnVector()
|
||||
pData->push_back(4);
|
||||
pData->push_back(5);
|
||||
|
||||
Column<int, std::vector<int> > c(mc, pData);
|
||||
Column<std::vector<int> > c(mc, pData);
|
||||
|
||||
assert (c.rowCount() == 5);
|
||||
assert (c[0] == 1);
|
||||
@@ -401,7 +401,7 @@ void DataTest::testColumnVector()
|
||||
}
|
||||
catch (RangeException&) { }
|
||||
|
||||
Column<int, std::vector<int> > c1 = c;
|
||||
Column<std::vector<int> > c1 = c;
|
||||
|
||||
assert (c1.rowCount() == 5);
|
||||
assert (c1[0] == 1);
|
||||
@@ -410,7 +410,7 @@ void DataTest::testColumnVector()
|
||||
assert (c1[3] == 4);
|
||||
assert (c1[4] == 5);
|
||||
|
||||
Column<int, std::vector<int> > c2(c1);
|
||||
Column<std::vector<int> > c2(c1);
|
||||
|
||||
assert (c2.rowCount() == 5);
|
||||
assert (c2[0] == 1);
|
||||
@@ -445,8 +445,8 @@ void DataTest::testColumnVector()
|
||||
pV2->push_back(3);
|
||||
pV2->push_back(2);
|
||||
pV2->push_back(1);
|
||||
Column<int, std::vector<int> > c3(mc, pV1);
|
||||
Column<int, std::vector<int> > c4(mc, pV2);
|
||||
Column<std::vector<int> > c3(mc, pV1);
|
||||
Column<std::vector<int> > c4(mc, pV2);
|
||||
|
||||
Poco::Data::swap(c3, c4);
|
||||
assert (c3[0] == 5);
|
||||
@@ -487,7 +487,7 @@ void DataTest::testColumnVectorBool()
|
||||
pData->push_back(false);
|
||||
pData->push_back(true);
|
||||
|
||||
Column<bool, std::vector<bool> > c(mc, pData);
|
||||
Column<std::vector<bool> > c(mc, pData);
|
||||
|
||||
assert (c.rowCount() == 5);
|
||||
assert (c[0] == true);
|
||||
@@ -504,7 +504,7 @@ void DataTest::testColumnVectorBool()
|
||||
}
|
||||
catch (RangeException&) { }
|
||||
|
||||
Column<bool, std::vector<bool> > c1 = c;
|
||||
Column<std::vector<bool> > c1 = c;
|
||||
|
||||
assert (c1.rowCount() == 5);
|
||||
assert (c1[0] == true);
|
||||
@@ -513,7 +513,7 @@ void DataTest::testColumnVectorBool()
|
||||
assert (c1[3] == false);
|
||||
assert (c1[4] == true);
|
||||
|
||||
Column<bool, std::vector<bool> > c2(c1);
|
||||
Column<std::vector<bool> > c2(c1);
|
||||
|
||||
assert (c2.rowCount() == 5);
|
||||
assert (c2[0] == true);
|
||||
@@ -541,7 +541,7 @@ void DataTest::testColumnVectorBool()
|
||||
void DataTest::testColumnDeque()
|
||||
{
|
||||
typedef std::deque<int> ContainerType;
|
||||
typedef Column<int> ColumnType;
|
||||
typedef Column<ContainerType> ColumnType;
|
||||
|
||||
MetaColumn mc(0, "mc", MetaColumn::FDT_DOUBLE, 2, 3, true);
|
||||
|
||||
@@ -624,8 +624,8 @@ void DataTest::testColumnDeque()
|
||||
pV2->push_back(3);
|
||||
pV2->push_back(2);
|
||||
pV2->push_back(1);
|
||||
Column<int> c3(mc, pV1);
|
||||
Column<int> c4(mc, pV2);
|
||||
Column<ContainerType> c3(mc, pV1);
|
||||
Column<ContainerType> c4(mc, pV2);
|
||||
|
||||
Poco::Data::swap(c3, c4);
|
||||
assert (c3[0] == 5);
|
||||
@@ -658,7 +658,7 @@ void DataTest::testColumnDeque()
|
||||
void DataTest::testColumnList()
|
||||
{
|
||||
typedef std::list<int> ContainerType;
|
||||
typedef Column<int, ContainerType> ColumnType;
|
||||
typedef Column<ContainerType> ColumnType;
|
||||
|
||||
MetaColumn mc(0, "mc", MetaColumn::FDT_DOUBLE, 2, 3, true);
|
||||
|
||||
@@ -739,8 +739,8 @@ void DataTest::testColumnList()
|
||||
pV2->push_back(3);
|
||||
pV2->push_back(2);
|
||||
pV2->push_back(1);
|
||||
Column<int, ContainerType> c3(mc, pV1);
|
||||
Column<int, ContainerType> c4(mc, pV2);
|
||||
Column<ContainerType> c3(mc, pV1);
|
||||
Column<ContainerType> c4(mc, pV2);
|
||||
|
||||
Poco::Data::swap(c3, c4);
|
||||
assert (c3[0] == 5);
|
||||
|
||||
Reference in New Issue
Block a user