Merge pull request #1778 from pocoproject/internal-ext-fix

ODBC RecordSet (internal extraction) broken #1775
This commit is contained in:
Aleksandar Fabijanic 2017-06-30 16:53:50 +02:00 committed by GitHub
commit a33057d8fe
39 changed files with 423 additions and 577 deletions

View File

@ -793,8 +793,8 @@ void MySQLTest::recreatePersonTimeTable()
void MySQLTest::recreateIntsTable() void MySQLTest::recreateIntsTable()
{ {
dropTable("Strings"); dropTable("Ints");
try { *_pSession << "CREATE TABLE Strings (str INTEGER)", now; } try { *_pSession << "CREATE TABLE Ints (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateIntsTable()"); } catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateIntsTable()"); }
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateIntsTable()"); }
} }

View File

@ -90,7 +90,6 @@ public:
std::size_t maxFieldSize, std::size_t maxFieldSize,
ParameterBinding dataBinding, ParameterBinding dataBinding,
TypeInfo* pDataTypes, TypeInfo* pDataTypes,
ODBCMetaColumn::NumericConversion numericConversion,
bool insertOnly); bool insertOnly);
/// Creates the Binder. /// Creates the Binder.
@ -1043,7 +1042,6 @@ private:
std::size_t _maxCharColLength; std::size_t _maxCharColLength;
std::size_t _maxWCharColLength; std::size_t _maxWCharColLength;
std::size_t _maxVarBinColSize; std::size_t _maxVarBinColSize;
ODBCMetaColumn::NumericConversion _numericConversion;
NullCbMap _nullCbMap; NullCbMap _nullCbMap;
bool _insertOnly; bool _insertOnly;
}; };

View File

@ -514,7 +514,7 @@ private:
bool extractImpl(std::size_t pos, T& val) bool extractImpl(std::size_t pos, T& val)
/// Utility function for extraction of Any and DynamicAny. /// Utility function for extraction of Any and DynamicAny.
{ {
ODBCMetaColumn column(_rStmt, pos, _pPreparator->numericConversion()); ODBCMetaColumn column(_rStmt, pos);
switch (column.type()) switch (column.type())
{ {
@ -720,7 +720,7 @@ inline bool Extractor::isNullLengthIndicator(SQLLEN val) const
inline SQLINTEGER Extractor::columnSize(std::size_t pos) const inline SQLINTEGER Extractor::columnSize(std::size_t pos) const
{ {
std::size_t size = ODBCMetaColumn(_rStmt, pos, _pPreparator->numericConversion()).length(); std::size_t size = ODBCMetaColumn(_rStmt, pos).length();
std::size_t maxSize = _pPreparator->maxDataSize(pos); std::size_t maxSize = _pPreparator->maxDataSize(pos);
if (size > maxSize) size = maxSize; if (size > maxSize) size = maxSize;
return (SQLINTEGER) size; return (SQLINTEGER) size;

View File

@ -40,14 +40,7 @@ class ODBC_API ODBCMetaColumn: public MetaColumn
{ {
public: public:
enum NumericConversion ODBCMetaColumn(const StatementHandle& rStmt, std::size_t position);
{
NC_BEST_FIT = 0,
NC_FORCE_STRING = 1,
NC_BEST_FIT_DBL_LIMIT = 2
};
ODBCMetaColumn(const StatementHandle& rStmt, std::size_t position, NumericConversion numericConversion);
/// Creates the ODBCMetaColumn. /// Creates the ODBCMetaColumn.
~ODBCMetaColumn(); ~ODBCMetaColumn();
@ -81,7 +74,6 @@ private:
SQLLEN _dataLength; SQLLEN _dataLength;
const StatementHandle& _rStmt; const StatementHandle& _rStmt;
ColumnDescription _columnDesc; ColumnDescription _columnDesc;
NumericConversion _numericConversion;
}; };

View File

@ -160,7 +160,6 @@ private:
bool _prepared; bool _prepared;
mutable std::size_t _affectedRowCount; mutable std::size_t _affectedRowCount;
bool _canCompile; bool _canCompile;
ODBCMetaColumn::NumericConversion _numericConversion;
bool _isPostgres; bool _isPostgres;
bool _insertHint; bool _insertHint;
}; };

View File

@ -102,7 +102,6 @@ public:
const std::string& statement, const std::string& statement,
std::size_t maxFieldSize, std::size_t maxFieldSize,
DataExtraction dataExtraction, DataExtraction dataExtraction,
ODBCMetaColumn::NumericConversion numericConversion ,
bool isPostgres bool isPostgres
); );
/// Creates the Preparator. /// Creates the Preparator.
@ -419,9 +418,6 @@ public:
DataExtraction getDataExtraction() const; DataExtraction getDataExtraction() const;
/// Returns data extraction mode. /// Returns data extraction mode.
ODBCMetaColumn::NumericConversion numericConversion() const;
/// Tells if numeric values are always converted to string
private: private:
typedef std::vector<Poco::Any> ValueVec; typedef std::vector<Poco::Any> ValueVec;
typedef std::vector<SQLLEN> LengthVec; typedef std::vector<SQLLEN> LengthVec;
@ -435,7 +431,7 @@ private:
void prepareImpl(std::size_t pos, const C* pVal = 0) void prepareImpl(std::size_t pos, const C* pVal = 0)
/// Utility function to prepare Any and DynamicAny. /// Utility function to prepare Any and DynamicAny.
{ {
ODBCMetaColumn col(_rStmt, pos, _numericConversion); ODBCMetaColumn col(_rStmt, pos);
switch (col.type()) switch (col.type())
{ {
@ -687,7 +683,6 @@ private:
mutable IndexMap _varLengthArrays; mutable IndexMap _varLengthArrays;
std::size_t _maxFieldSize; std::size_t _maxFieldSize;
DataExtraction _dataExtraction; DataExtraction _dataExtraction;
ODBCMetaColumn::NumericConversion _numericConversion;
}; };
@ -1274,12 +1269,6 @@ inline Poco::Any& Preparator::at(std::size_t pos)
} }
inline ODBCMetaColumn::NumericConversion Preparator::numericConversion() const
{
return _numericConversion;
}
} } } // namespace Poco::Data::ODBC } } } // namespace Poco::Data::ODBC

View File

@ -45,7 +45,6 @@ class ODBC_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl>
{ {
public: public:
static const std::size_t ODBC_MAX_FIELD_SIZE = 1024u; static const std::size_t ODBC_MAX_FIELD_SIZE = 1024u;
static const char* const NUMERIC_CONVERSION_PROPERTY;
enum TransactionCapability enum TransactionCapability
{ {
@ -168,22 +167,10 @@ public:
Poco::Any dataTypeInfo(const std::string& rName=""); Poco::Any dataTypeInfo(const std::string& rName="");
/// Returns the data types information. /// Returns the data types information.
ODBCMetaColumn::NumericConversion numericConversion() const;
/// Tells if NUMERIC values to be always
/// converted to string
void setNumericConversion(ODBCMetaColumn::NumericConversion value);
/// Sets flag to tell if NUMERIC values are always returned as
/// string
private: private:
void setDataTypeInfo(const std::string& rName, const Poco::Any& rValue); void setDataTypeInfo(const std::string& rName, const Poco::Any& rValue);
/// No-op. Throws InvalidAccessException. /// No-op. Throws InvalidAccessException.
void setNumericConversion(const std::string&, const Poco::Any& rValue);
Poco::Any numericConversion(const std::string& nm);
void init(); void init();
static const int FUNCTIONS = SQL_API_ODBC3_ALL_FUNCTIONS_SIZE; static const int FUNCTIONS = SQL_API_ODBC3_ALL_FUNCTIONS_SIZE;
@ -199,7 +186,6 @@ private:
Poco::Any _maxFieldSize; Poco::Any _maxFieldSize;
bool _autoBind; bool _autoBind;
bool _autoExtract; bool _autoExtract;
ODBCMetaColumn::NumericConversion _numericConversion;
TypeInfo _dataTypes; TypeInfo _dataTypes;
char _canTransact; char _canTransact;
bool _inTransaction; bool _inTransaction;
@ -302,30 +288,6 @@ inline int SessionImpl::queryTimeout() const
} }
inline ODBCMetaColumn::NumericConversion SessionImpl::numericConversion() const
{
return _numericConversion;
}
inline Poco::Any SessionImpl::numericConversion(const std::string&)
{
return numericConversion();
}
inline void SessionImpl::setNumericConversion(ODBCMetaColumn::NumericConversion value)
{
_numericConversion = value;
}
inline void SessionImpl::setNumericConversion(const std::string&, const Poco::Any& rValue)
{
setNumericConversion( Poco::AnyCast<ODBCMetaColumn::NumericConversion>(rValue) );
}
} } } // namespace Poco::Data::ODBC } } } // namespace Poco::Data::ODBC

View File

@ -44,7 +44,6 @@ Binder::Binder(const StatementHandle& rStmt,
std::size_t maxFieldSize, std::size_t maxFieldSize,
Binder::ParameterBinding dataBinding, Binder::ParameterBinding dataBinding,
TypeInfo* pDataTypes, TypeInfo* pDataTypes,
ODBCMetaColumn::NumericConversion numericConversion,
bool insertOnly) : bool insertOnly) :
_rStmt(rStmt), _rStmt(rStmt),
_paramBinding(dataBinding), _paramBinding(dataBinding),
@ -54,7 +53,6 @@ Binder::Binder(const StatementHandle& rStmt,
_maxCharColLength(1024), _maxCharColLength(1024),
_maxWCharColLength(1024), _maxWCharColLength(1024),
_maxVarBinColSize(1024), _maxVarBinColSize(1024),
_numericConversion(numericConversion),
_insertOnly(insertOnly) _insertOnly(insertOnly)
{ {
getProp(*_pTypeInfo, SQL_WVARCHAR, _maxWCharColLength); getProp(*_pTypeInfo, SQL_WVARCHAR, _maxWCharColLength);
@ -566,7 +564,7 @@ void Binder::getColSizeAndPrecision(std::size_t pos,
{ {
try try
{ {
ODBCMetaColumn c(_rStmt, pos, _numericConversion); ODBCMetaColumn c(_rStmt, pos);
_parameters[pos] = ParamDescriptor(static_cast<SQLINTEGER>(c.length()), cDataType, static_cast<SQLSMALLINT>(c.precision())); _parameters[pos] = ParamDescriptor(static_cast<SQLINTEGER>(c.length()), cDataType, static_cast<SQLSMALLINT>(c.precision()));
} }
catch (StatementException&) {} catch (StatementException&) {}
@ -587,7 +585,7 @@ void Binder::getColumnOrParameterSize(std::size_t pos, SQLINTEGER& size)
try try
{ {
ODBCMetaColumn col(_rStmt, pos, _numericConversion); ODBCMetaColumn col(_rStmt, pos);
colSize = col.length(); colSize = col.length();
} }
catch (StatementException&) { } catch (StatementException&) { }

View File

@ -23,10 +23,9 @@ namespace Data {
namespace ODBC { namespace ODBC {
ODBCMetaColumn::ODBCMetaColumn(const StatementHandle& rStmt, std::size_t position, NumericConversion numericConversion) : ODBCMetaColumn::ODBCMetaColumn(const StatementHandle& rStmt, std::size_t position) :
MetaColumn(position), MetaColumn(position),
_rStmt(rStmt), _rStmt(rStmt)
_numericConversion(numericConversion)
{ {
init(); init();
} }
@ -117,44 +116,17 @@ void ODBCMetaColumn::init()
case SQL_NUMERIC: case SQL_NUMERIC:
case SQL_DECIMAL: case SQL_DECIMAL:
{
bool toString = false;
switch (_numericConversion)
{
case NC_BEST_FIT:
case NC_BEST_FIT_DBL_LIMIT:
if (0 == _columnDesc.decimalDigits) if (0 == _columnDesc.decimalDigits)
{ {
if (_columnDesc.size <= 9) #ifdef POCO_64_BIT
setType(MetaColumn::FDT_INT32);
else if (_columnDesc.size <= 18)
setType(MetaColumn::FDT_INT64); setType(MetaColumn::FDT_INT64);
else if (_numericConversion != NC_BEST_FIT_DBL_LIMIT)
toString = true;
else
setType(MetaColumn::FDT_DOUBLE);
}
else
{
// we can't have more than 16 digits in double, but we may be asked to
if (_columnDesc.size > 16 && _numericConversion != NC_BEST_FIT_DBL_LIMIT)
toString = true;
else
setType(MetaColumn::FDT_DOUBLE);
}
break;
case NC_FORCE_STRING:
toString = true;
}
if (toString)
{
setLength(_columnDesc.size + 4);
#if defined(UNICODE)
setType(MetaColumn::FDT_WSTRING);
#else #else
setType(MetaColumn::FDT_STRING); setType(MetaColumn::FDT_INT32);
#endif #endif
} }
else
{
setType(MetaColumn::FDT_DOUBLE);
} }
break; break;

View File

@ -47,7 +47,6 @@ ODBCStatementImpl::ODBCStatementImpl(SessionImpl& rSession):
_prepared(false), _prepared(false),
_affectedRowCount(0), _affectedRowCount(0),
_canCompile(true), _canCompile(true),
_numericConversion(rSession.numericConversion()),
_isPostgres(false), _isPostgres(false),
_insertHint(false) _insertHint(false)
{ {
@ -111,9 +110,8 @@ void ODBCStatementImpl::compileImpl()
} }
const std::size_t maxFieldSize = AnyCast<std::size_t>(session().getProperty("maxFieldSize")); const std::size_t maxFieldSize = AnyCast<std::size_t>(session().getProperty("maxFieldSize"));
const ODBCMetaColumn::NumericConversion numericConversion = dynamic_cast<SessionImpl&>(session()).numericConversion();
_pBinder = new Binder(_stmt, maxFieldSize, bind, pDT, numericConversion, _insertHint); _pBinder = new Binder(_stmt, maxFieldSize, bind, pDT, _insertHint);
makeInternalExtractors(); makeInternalExtractors();
doPrepare(); doPrepare();
@ -156,7 +154,7 @@ bool ODBCStatementImpl::addPreparator(bool addAlways)
std::size_t maxFieldSize = AnyCast<std::size_t>(session().getProperty("maxFieldSize")); std::size_t maxFieldSize = AnyCast<std::size_t>(session().getProperty("maxFieldSize"));
prep = new Preparator(_stmt, statement, maxFieldSize, ext, _numericConversion, _isPostgres); prep = new Preparator(_stmt, statement, maxFieldSize, ext, _isPostgres);
} }
else else
prep = new Preparator(*_preparations[0]); prep = new Preparator(*_preparations[0]);
@ -340,19 +338,23 @@ bool ODBCStatementImpl::hasNext()
if (!nextRowReady()) if (!nextRowReady())
{ {
// have a loop here, as there could be one or more empty results // have a loop here, as there could be one or more empty results
do { do
if (hasMoreDataSets()) { {
if (hasMoreDataSets())
{
activateNextDataSet(); activateNextDataSet();
if (!nextResultSet()) if (!nextResultSet())
return false; return false;
addPreparator(); addPreparator();
} }
else { else
if (nextResultSet()) { {
if (nextResultSet())
{
if (!addPreparator(false)) // skip the result set if it has no columns if (!addPreparator(false)) // skip the result set if it has no columns
continue; continue;
fillColumns(currentDataSet() + 1); fillColumns(currentDataSet() + 1);
makeExtractors(_preparations.back()->columns(), static_cast<Position::PositionType>(currentDataSet() + 1)); makeExtractors(_preparations.back()->columns(), static_cast<Position::Type>(currentDataSet() + 1));
activateNextDataSet(); activateNextDataSet();
} }
else return false; else return false;
@ -469,7 +471,7 @@ void ODBCStatementImpl::fillColumns(size_t dataSetPos)
_columnPtrs.resize(dataSetPos + 1); _columnPtrs.resize(dataSetPos + 1);
for (int i = 0; i < colCount; ++i) for (int i = 0; i < colCount; ++i)
_columnPtrs[dataSetPos].push_back(new ODBCMetaColumn(_stmt, i, _numericConversion)); _columnPtrs[dataSetPos].push_back(new ODBCMetaColumn(_stmt, i));
} }

View File

@ -31,12 +31,10 @@ Preparator::Preparator(const StatementHandle& rStmt,
const std::string& statement, const std::string& statement,
std::size_t maxFieldSize, std::size_t maxFieldSize,
DataExtraction dataExtraction, DataExtraction dataExtraction,
ODBCMetaColumn::NumericConversion numericConversion,
bool isPostgres) : bool isPostgres) :
_rStmt(rStmt), _rStmt(rStmt),
_maxFieldSize(maxFieldSize), _maxFieldSize(maxFieldSize),
_dataExtraction(dataExtraction), _dataExtraction(dataExtraction)
_numericConversion(numericConversion)
{ {
SQLCHAR* pStr = (SQLCHAR*) statement.c_str(); SQLCHAR* pStr = (SQLCHAR*) statement.c_str();
if (Utility::isError(Poco::Data::ODBC::SQLPrepare(_rStmt, pStr, (SQLINTEGER) statement.length()))) if (Utility::isError(Poco::Data::ODBC::SQLPrepare(_rStmt, pStr, (SQLINTEGER) statement.length())))
@ -57,8 +55,7 @@ Preparator::Preparator(const StatementHandle& rStmt,
Preparator::Preparator(const Preparator& other): Preparator::Preparator(const Preparator& other):
_rStmt(other._rStmt), _rStmt(other._rStmt),
_maxFieldSize(other._maxFieldSize), _maxFieldSize(other._maxFieldSize),
_dataExtraction(other._dataExtraction), _dataExtraction(other._dataExtraction)
_numericConversion(other._numericConversion)
{ {
resize(); resize();
} }
@ -169,7 +166,7 @@ std::size_t Preparator::maxDataSize(std::size_t pos) const
try try
{ {
ODBCMetaColumn mc(_rStmt, pos, _numericConversion); ODBCMetaColumn mc(_rStmt, pos);
sz = mc.length(); sz = mc.length();
// accommodate for terminating zero (non-bulk only!) // accommodate for terminating zero (non-bulk only!)

View File

@ -29,8 +29,6 @@ namespace Data {
namespace ODBC { namespace ODBC {
const char* const SessionImpl::NUMERIC_CONVERSION_PROPERTY= "numericConversion";
SessionImpl::SessionImpl(const std::string& connect, SessionImpl::SessionImpl(const std::string& connect,
std::size_t loginTimeout, std::size_t loginTimeout,
std::size_t maxFieldSize, std::size_t maxFieldSize,
@ -41,7 +39,6 @@ SessionImpl::SessionImpl(const std::string& connect,
_maxFieldSize(maxFieldSize), _maxFieldSize(maxFieldSize),
_autoBind(autoBind), _autoBind(autoBind),
_autoExtract(autoExtract), _autoExtract(autoExtract),
_numericConversion(ODBCMetaColumn::NC_BEST_FIT),
_canTransact(ODBC_TXN_CAPABILITY_UNKNOWN), _canTransact(ODBC_TXN_CAPABILITY_UNKNOWN),
_inTransaction(false), _inTransaction(false),
_queryTimeout(-1) _queryTimeout(-1)
@ -69,9 +66,6 @@ SessionImpl::SessionImpl(const std::string& connect,
void SessionImpl::init() void SessionImpl::init()
{ {
addProperty(NUMERIC_CONVERSION_PROPERTY,
&SessionImpl::setNumericConversion,
&SessionImpl::numericConversion);
setFeature("bulk", true); setFeature("bulk", true);
open(); open();
setProperty("handle", _db.handle()); setProperty("handle", _db.handle());

View File

@ -58,7 +58,7 @@
<Filter>_Suite\Header Files</Filter> <Filter>_Suite\Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\ODBCSybaseTest.h"> <ClInclude Include="src\ODBCSybaseTest.h">
<Filter>ODBC</Filter> <Filter>ODBC\Header Files</Filter>
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -96,7 +96,7 @@
<Filter>_Driver\Source Files</Filter> <Filter>_Driver\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\ODBCSybaseTest.cpp"> <ClCompile Include="src\ODBCSybaseTest.cpp">
<Filter>ODBC</Filter> <Filter>ODBC\Source Files</Filter>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -578,17 +578,6 @@ void ODBCDB2Test::recreateNullableTable()
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); }
} }
void ODBCDB2Test::recreateNumericTable()
{
dropObject("TABLE", ExecUtil::numeric_tbl());
try {
session() << "CREATE TABLE " << ExecUtil::numeric_tbl() <<
" (id integer, num8 NUMERIC(8), num16_3 NUMERIC(16,3), num18 NUMERIC(18), num18_8 NUMERIC(18,8), num22 NUMERIC(22))", now;
}
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail("recreateNumericTable()"); }
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail("recreateNumericTable()"); }
}
void ODBCDB2Test::recreatePersonTable() void ODBCDB2Test::recreatePersonTable()
{ {
@ -637,8 +626,8 @@ void ODBCDB2Test::recreatePersonDateTimeTable()
void ODBCDB2Test::recreateIntsTable() void ODBCDB2Test::recreateIntsTable()
{ {
dropObject("TABLE", ExecUtil::strings()); dropObject("TABLE", ExecUtil::ints());
try { session() << "CREATE TABLE " << ExecUtil::strings() << " (str INTEGER)", now; } try { session() << "CREATE TABLE " << ExecUtil::ints() << " (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); }
} }
@ -835,7 +824,6 @@ CppUnit::Test* ODBCDB2Test::suite()
CppUnit_addTest(pSuite, ODBCDB2Test, testTransactor); CppUnit_addTest(pSuite, ODBCDB2Test, testTransactor);
CppUnit_addTest(pSuite, ODBCDB2Test, testNullable); CppUnit_addTest(pSuite, ODBCDB2Test, testNullable);
CppUnit_addTest(pSuite, ODBCDB2Test, testReconnect); CppUnit_addTest(pSuite, ODBCDB2Test, testReconnect);
CppUnit_addTest(pSuite, ODBCDB2Test, testNumeric);
CppUnit_addTest(pSuite, ODBCDB2Test, testXMLColumn); CppUnit_addTest(pSuite, ODBCDB2Test, testXMLColumn);
CppUnit_addTest(pSuite, ODBCDB2Test, testInsertStatReuse); CppUnit_addTest(pSuite, ODBCDB2Test, testInsertStatReuse);

View File

@ -62,7 +62,6 @@ private:
void recreateNullsTable(const std::string& notNull = ""); void recreateNullsTable(const std::string& notNull = "");
void recreateMiscTable(); void recreateMiscTable();
void recreateLogTable(); void recreateLogTable();
void recreateNumericTable();
static ODBCTest::SessionPtr _pSession; static ODBCTest::SessionPtr _pSession;
static ODBCTest::ExecPtr _pExecutor; static ODBCTest::ExecPtr _pExecutor;

View File

@ -304,8 +304,8 @@ void ODBCMySQLTest::recreatePersonDateTimeTable()
void ODBCMySQLTest::recreateIntsTable() void ODBCMySQLTest::recreateIntsTable()
{ {
dropObject("TABLE", ExecUtil::strings()); dropObject("TABLE", ExecUtil::ints());
try { *_pSession << "CREATE TABLE " << ExecUtil::strings() << " (str INTEGER)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::ints() << " (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); }
} }

View File

@ -43,7 +43,7 @@ using Poco::DynamicAny;
using Poco::DateTime; using Poco::DateTime;
#define ORACLE_ODBC_DRIVER "Oracle in XE" #define ORACLE_ODBC_DRIVER "Oracle in OraClient12Home1_32bit"//XE"
#define ORACLE_DSN "PocoDataOracleTest" #define ORACLE_DSN "PocoDataOracleTest"
#define ORACLE_SERVER POCO_ODBC_TEST_DATABASE_SERVER #define ORACLE_SERVER POCO_ODBC_TEST_DATABASE_SERVER
#define ORACLE_PORT "1521" #define ORACLE_PORT "1521"
@ -169,6 +169,25 @@ void ODBCOracleTest::testBarebone()
} }
void ODBCOracleTest::testInternalExtraction()
{
if (!_pSession) fail ("Test not available.");
for (int i = 0; i < 8;)
{
recreateVectorsTable();
_pSession->setFeature("autoBind", bindValue(i));
_pSession->setFeature("autoExtract", bindValue(i+1));
#ifdef POCO_64_BIT
_pExecutor->internalExtraction<double>(0.);
#else
_pExecutor->internalExtraction(0);
#endif
i += 2;
}
}
void ODBCOracleTest::testBLOB() void ODBCOracleTest::testBLOB()
{ {
const std::size_t maxFldSize = 1000000; const std::size_t maxFldSize = 1000000;
@ -598,18 +617,18 @@ void ODBCOracleTest::testAutoTransaction()
recreateIntsTable(); recreateIntsTable();
session().setFeature("autoCommit", true); session().setFeature("autoCommit", true);
session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (1)", now; session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (1)", now;
localSession << "SELECT count(*) FROM " << ExecUtil::person() , into(count), now; localSession << "SELECT count(*) FROM " << ExecUtil::ints() , into(count), now;
assert (1 == count); assert (1 == count);
session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (2)", now; session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (2)", now;
localSession << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now; localSession << "SELECT count(*) FROM " << ExecUtil::ints(), into(count), now;
assert (2 == count); assert (2 == count);
session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (3)", now; session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (3)", now;
localSession << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now; localSession << "SELECT count(*) FROM " << ExecUtil::ints(), into(count), now;
assert (3 == count); assert (3 == count);
session() << "DELETE FROM " << ExecUtil::strings(), now; session() << "DELETE FROM " << ExecUtil::ints(), now;
localSession << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now; localSession << "SELECT count(*) FROM " << ExecUtil::ints(), into(count), now;
assert (0 == count); assert (0 == count);
session().setFeature("autoCommit", false); session().setFeature("autoCommit", false);
@ -617,26 +636,26 @@ void ODBCOracleTest::testAutoTransaction()
try try
{ {
AutoTransaction at(session()); AutoTransaction at(session());
session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (1)", now; session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (1)", now;
session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (2)", now; session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (2)", now;
session() << "BAD QUERY", now; session() << "BAD QUERY", now;
} catch (Poco::Exception&) {} } catch (Poco::Exception&) {}
session() << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now; session() << "SELECT count(*) FROM " << ExecUtil::ints(), into(count), now;
assert (0 == count); assert (0 == count);
AutoTransaction at(session()); AutoTransaction at(session());
session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (1)", now; session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (1)", now;
session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (2)", now; session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (2)", now;
session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (3)", now; session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (3)", now;
localSession << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now; localSession << "SELECT count(*) FROM " << ExecUtil::ints(), into(count), now;
assert (0 == count); assert (0 == count);
at.commit(); at.commit();
localSession << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now; localSession << "SELECT count(*) FROM " << ExecUtil::ints(), into(count), now;
assert (3 == count); assert (3 == count);
session().setFeature("autoCommit", ac); session().setFeature("autoCommit", ac);
@ -726,8 +745,8 @@ void ODBCOracleTest::recreatePersonDateTable()
void ODBCOracleTest::recreateIntsTable() void ODBCOracleTest::recreateIntsTable()
{ {
dropObject("TABLE", ExecUtil::strings()); dropObject("TABLE", ExecUtil::ints());
try { *_pSession << "CREATE TABLE " << ExecUtil::strings() <<" (str INTEGER)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::ints() <<" (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); }
} }

View File

@ -36,6 +36,8 @@ public:
void testBareboneODBC(); void testBareboneODBC();
void testInternalExtraction();
void testBLOB(); void testBLOB();
void testMultipleResults(); void testMultipleResults();

View File

@ -482,8 +482,8 @@ void ODBCPostgreSQLTest::recreatePersonTimeTable()
void ODBCPostgreSQLTest::recreateIntsTable() void ODBCPostgreSQLTest::recreateIntsTable()
{ {
dropObject("TABLE", ExecUtil::strings()); dropObject("TABLE", ExecUtil::ints());
try { session() << "CREATE TABLE " << ExecUtil::strings() <<" (str INTEGER)", now; } try { session() << "CREATE TABLE " << ExecUtil::ints() <<" (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); }
} }

View File

@ -589,8 +589,8 @@ void ODBCSQLServerTest::recreatePersonDateTimeTable()
void ODBCSQLServerTest::recreateIntsTable() void ODBCSQLServerTest::recreateIntsTable()
{ {
dropObject("TABLE", ExecUtil::strings()); dropObject("TABLE", ExecUtil::ints());
try { session() << "CREATE TABLE " << ExecUtil::strings() <<" (str INTEGER)", now; } try { session() << "CREATE TABLE " << ExecUtil::ints() <<" (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); }
} }

View File

@ -205,8 +205,8 @@ void ODBCSQLiteTest::recreatePersonDateTimeTable()
void ODBCSQLiteTest::recreateIntsTable() void ODBCSQLiteTest::recreateIntsTable()
{ {
dropObject("TABLE", ExecUtil::strings()); dropObject("TABLE", ExecUtil::ints());
try { session() << "CREATE TABLE " << ExecUtil::strings() <<" (str INTEGER)", now; } try { session() << "CREATE TABLE " << ExecUtil::ints() <<" (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); }
} }

View File

@ -153,17 +153,6 @@ void SybaseODBC::recreateNullableTable()
} }
void SybaseODBC::recreateNumericTable()
{
dropObject("TABLE", ExecUtil::numeric_tbl());
try {
session() << "CREATE TABLE " << ExecUtil::numeric_tbl() <<
" (id integer, num8 NUMERIC(8), num16_3 NUMERIC(16,3), num18 NUMERIC(18), num18_8 NUMERIC(18,8), num22 NUMERIC(22))", now;
}
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail("recreateNumericTable()"); }
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail("recreateNumericTable()"); }
}
void SybaseODBC::recreatePersonTable() void SybaseODBC::recreatePersonTable()
{ {
doPersonTable(); doPersonTable();
@ -216,8 +205,8 @@ void SybaseODBC::recreatePersonDateTimeTable()
void SybaseODBC::recreateIntsTable() void SybaseODBC::recreateIntsTable()
{ {
dropObject("TABLE", ExecUtil::strings()); dropObject("TABLE", ExecUtil::ints());
try { session() << "CREATE TABLE " << ExecUtil::strings() << " (str INTEGER)", now; } try { session() << "CREATE TABLE " << ExecUtil::ints() << " (str INTEGER)", now; }
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail("recreateIntsTable()"); } catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail("recreateIntsTable()"); }
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail("recreateIntsTable()"); } catch (StatementException& se){ std::cout << se.toString() << std::endl; fail("recreateIntsTable()"); }
} }
@ -665,7 +654,6 @@ CppUnit::Test* SybaseODBC::suite()
CppUnit_addTest(pSuite, SybaseODBC, testTransactor); CppUnit_addTest(pSuite, SybaseODBC, testTransactor);
CppUnit_addTest(pSuite, SybaseODBC, testNullable); CppUnit_addTest(pSuite, SybaseODBC, testNullable);
CppUnit_addTest(pSuite, SybaseODBC, testReconnect); CppUnit_addTest(pSuite, SybaseODBC, testReconnect);
CppUnit_addTest(pSuite, SybaseODBC, testNumeric);
CppUnit_addTest(pSuite, SybaseODBC, testInsertStatReuse); CppUnit_addTest(pSuite, SybaseODBC, testInsertStatReuse);
_pExecutor = 0; _pExecutor = 0;

View File

@ -56,7 +56,6 @@ private:
void recreateNullsTable(const std::string& notNull = ""); void recreateNullsTable(const std::string& notNull = "");
void recreateMiscTable(); void recreateMiscTable();
void recreateLogTable(); void recreateLogTable();
void recreateNumericTable();
void testStoredProcedure(); void testStoredProcedure();
void testStoredProcedureDynamicAny(); void testStoredProcedureDynamicAny();
void testStoredProcedureAny(); void testStoredProcedureAny();

View File

@ -960,7 +960,7 @@ void ODBCTest::testInternalExtraction()
recreateVectorsTable(); recreateVectorsTable();
_pSession->setFeature("autoBind", bindValue(i)); _pSession->setFeature("autoBind", bindValue(i));
_pSession->setFeature("autoExtract", bindValue(i+1)); _pSession->setFeature("autoExtract", bindValue(i+1));
_pExecutor->internalExtraction(); _pExecutor->internalExtraction(0);
i += 2; i += 2;
} }
} }
@ -1235,33 +1235,6 @@ void ODBCTest::testNullable()
} }
} }
void ODBCTest::testNumeric()
{
if (!_pSession) fail("Test not available.");
recreateNumericTable();
std::vector<std::string> vals;
vals.push_back("12345678");
vals.push_back("123456789012.123");
vals.push_back("123456789012345678");
vals.push_back("1234567890.12345678");
vals.push_back("1234567890123456789012");
const std::string sqlStr = std::string("INSERT INTO ") + ExecUtil::numeric_tbl() +
"(id, num8, num16_3, num18, num18_8, num22) VALUES (1, " + str2NumExpr(vals[0],8,0) + " , " + str2NumExpr(vals[1],16,3) + ", " + str2NumExpr(vals[2], 18,0)
+ " , " + str2NumExpr(vals[3], 18, 8) + " , " + str2NumExpr(vals[4], 22, 0) + ")";
session() << sqlStr, now;
for (int i = 0; i < 8;)
{
_pSession->setFeature("autoBind", bindValue(i));
_pSession->setFeature("autoExtract", bindValue(i + 1));
_pExecutor->numericTypes(vals);
i += 2;
}
}
void ODBCTest::testInsertStatReuse() void ODBCTest::testInsertStatReuse()
{ {
@ -1413,7 +1386,7 @@ ODBCTest::SessionPtr ODBCTest::init(const std::string& driver,
try try
{ {
std::cout << "Conecting to [" << dbConnString << ']' << std::endl; std::cout << "Connecting to [" << dbConnString << ']' << std::endl;
return new Session(Poco::Data::ODBC::Connector::KEY, dbConnString, 5); return new Session(Poco::Data::ODBC::Connector::KEY, dbConnString, 5);
}catch (ConnectionFailedException& ex) }catch (ConnectionFailedException& ex)
{ {

View File

@ -154,7 +154,6 @@ public:
virtual void testUnicode(); virtual void testUnicode();
virtual void testReconnect(); virtual void testReconnect();
virtual void testNumeric();
virtual void testSyntaxError(); virtual void testSyntaxError();
virtual void testInsertStatReuse(); virtual void testInsertStatReuse();

View File

@ -32,7 +32,6 @@
#include "Poco/Data/Time.h" #include "Poco/Data/Time.h"
#include "Poco/Data/LOB.h" #include "Poco/Data/LOB.h"
#include "Poco/Data/StatementImpl.h" #include "Poco/Data/StatementImpl.h"
#include "Poco/Data/RecordSet.h"
#include "Poco/Data/RowIterator.h" #include "Poco/Data/RowIterator.h"
#include "Poco/Data/RowFilter.h" #include "Poco/Data/RowFilter.h"
#include "Poco/Data/BulkExtraction.h" #include "Poco/Data/BulkExtraction.h"
@ -1518,7 +1517,7 @@ void SQLExecutor::insertSingleBulk()
{ {
std::string funct = "insertSingleBulk()"; std::string funct = "insertSingleBulk()";
int x = 0; int x = 0;
Statement stmt((session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (?)", use(x))); Statement stmt((session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (?)", use(x)));
for (x = 0; x < 100; ++x) for (x = 0; x < 100; ++x)
{ {
@ -1526,12 +1525,12 @@ void SQLExecutor::insertSingleBulk()
assert (1 == i); assert (1 == i);
} }
int count = 0; int count = 0;
try { session() << "SELECT COUNT(*) FROM " << ExecUtil::strings(), into(count), now; } try { session() << "SELECT COUNT(*) FROM " << ExecUtil::ints(), into(count), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assert (count == 100); assert (count == 100);
try { session() << "SELECT SUM(str) FROM " << ExecUtil::strings(), into(count), now; } try { session() << "SELECT SUM(str) FROM " << ExecUtil::ints(), into(count), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assert (count == ((0+99)*100/2)); assert (count == ((0+99)*100/2));
@ -1592,16 +1591,16 @@ void SQLExecutor::insertSingleBulkVec()
for (int x = 0; x < 100; ++x) for (int x = 0; x < 100; ++x)
data.push_back(x); data.push_back(x);
Statement stmt((session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (?)", use(data))); Statement stmt((session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (?)", use(data)));
stmt.execute(); stmt.execute();
int count = 0; int count = 0;
try { session() << "SELECT COUNT(*) FROM " << ExecUtil::strings(), into(count), now; } try { session() << "SELECT COUNT(*) FROM " << ExecUtil::ints(), into(count), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assert (count == 100); assert (count == 100);
try { session() << "SELECT SUM(str) FROM " << ExecUtil::strings(), into(count), now; } try { session() << "SELECT SUM(str) FROM " << ExecUtil::ints(), into(count), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assert (count == ((0+99)*100/2)); assert (count == ((0+99)*100/2));
@ -1617,12 +1616,12 @@ void SQLExecutor::limits()
data.push_back(x); data.push_back(x);
} }
try { session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (?)", use(data), now; } try { session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (?)", use(data), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
std::vector<int> retData; std::vector<int> retData;
try { session() << "SELECT * FROM " << ExecUtil::strings(), into(retData), limit(50), now; } try { session() << "SELECT * FROM " << ExecUtil::ints(), into(retData), limit(50), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assert (retData.size() == 50); assert (retData.size() == 50);
@ -1642,12 +1641,12 @@ void SQLExecutor::limitZero()
data.push_back(x); data.push_back(x);
} }
try { session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (?)", use(data), now; } try { session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (?)", use(data), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
std::vector<int> retData; std::vector<int> retData;
try { session() << "SELECT * FROM " << ExecUtil::strings(), into(retData), limit(0), now; }// stupid test, but at least we shouldn't crash try { session() << "SELECT * FROM " << ExecUtil::ints(), into(retData), limit(0), now; }// stupid test, but at least we shouldn't crash
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assert (retData.size() == 0); assert (retData.size() == 0);
@ -1663,12 +1662,12 @@ void SQLExecutor::limitOnce()
data.push_back(x); data.push_back(x);
} }
try { session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (?)", use(data), now; } try { session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (?)", use(data), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
std::vector<int> retData; std::vector<int> retData;
Statement stmt = (session() << "SELECT * FROM " << ExecUtil::strings(), into(retData), limit(50), now); Statement stmt = (session() << "SELECT * FROM " << ExecUtil::ints(), into(retData), limit(50), now);
assert (!stmt.done()); assert (!stmt.done());
assert (retData.size() == 50); assert (retData.size() == 50);
stmt.execute(); stmt.execute();
@ -1696,14 +1695,14 @@ void SQLExecutor::limitPrepare()
try try
{ {
Statement stmt = (session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (?)", use(data)); Statement stmt = (session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (?)", use(data));
assert (100 == stmt.execute()); assert (100 == stmt.execute());
} }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
std::vector<int> retData; std::vector<int> retData;
Statement stmt = (session() << "SELECT * FROM " << ExecUtil::strings(), into(retData), limit(50)); Statement stmt = (session() << "SELECT * FROM " << ExecUtil::ints(), into(retData), limit(50));
assert (retData.size() == 0); assert (retData.size() == 0);
assert (!stmt.done()); assert (!stmt.done());
@ -1739,84 +1738,17 @@ void SQLExecutor::prepare()
} }
{ {
Statement stmt((session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (?)", use(data))); Statement stmt((session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (?)", use(data)));
} }
// stmt should not have been executed when destroyed // stmt should not have been executed when destroyed
int count = 100; int count = 100;
try { session() << "SELECT COUNT(*) FROM " << ExecUtil::strings(), into(count), now; } try { session() << "SELECT COUNT(*) FROM " << ExecUtil::ints(), into(count), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assert (count == 0); assert (count == 0);
} }
void SQLExecutor::numericTypes(const std::vector<std::string>& vals)
{
std::string funct = "numericTypes()";
try {
session().setProperty(Poco::Data::ODBC::SessionImpl::NUMERIC_CONVERSION_PROPERTY, Poco::Data::ODBC::ODBCMetaColumn::NC_BEST_FIT);
{
Statement stat(session());
stat << "SELECT * FROM " << ExecUtil::numeric_tbl(), now;
RecordSet rs(stat);
assert(vals.size() + 1 == rs.columnCount());
assert(Poco::Data::ODBC::ODBCMetaColumn::FDT_INT32 == rs.columnType(0));
assert(Poco::Data::ODBC::ODBCMetaColumn::FDT_INT32 == rs.columnType(1));
assert(Poco::Data::ODBC::ODBCMetaColumn::FDT_DOUBLE == rs.columnType(2));
assert(Poco::Data::ODBC::ODBCMetaColumn::FDT_INT64 == rs.columnType(3));
assert(Poco::Data::ODBC::ODBCMetaColumn::FDT_STRING == rs.columnType(4));
assert(Poco::Data::ODBC::ODBCMetaColumn::FDT_STRING == rs.columnType(5));
for (size_t i = 0; i < vals.size(); ++i)
{
std::string v = rs.value(i + 1).convert<std::string>();
assert(vals[i] == v);
}
}
session().setProperty(Poco::Data::ODBC::SessionImpl::NUMERIC_CONVERSION_PROPERTY, Poco::Data::ODBC::ODBCMetaColumn::NC_FORCE_STRING);
{
Statement stat(session());
stat << "SELECT * FROM " << ExecUtil::numeric_tbl(), now;
RecordSet rs(stat);
assert(vals.size() + 1 == rs.columnCount());
assert(Poco::Data::ODBC::ODBCMetaColumn::FDT_INT32 == rs.columnType(0));
for (size_t i = 0; i < vals.size(); ++i)
{
assert(Poco::Data::ODBC::ODBCMetaColumn::FDT_STRING == rs.columnType(i + 1));
std::string v = rs.value<std::string>(i + 1);
assert(vals[i] == v);
}
}
session().setProperty(Poco::Data::ODBC::SessionImpl::NUMERIC_CONVERSION_PROPERTY, Poco::Data::ODBC::ODBCMetaColumn::NC_BEST_FIT_DBL_LIMIT);
{
Statement stat(session());
stat << "SELECT * FROM " << ExecUtil::numeric_tbl(), now;
RecordSet rs(stat);
assert(vals.size() + 1 == rs.columnCount());
assert(Poco::Data::ODBC::ODBCMetaColumn::FDT_INT32 == rs.columnType(0));
assert(Poco::Data::ODBC::ODBCMetaColumn::FDT_INT32 == rs.columnType(1));
assert(Poco::Data::ODBC::ODBCMetaColumn::FDT_DOUBLE == rs.columnType(2));
assert(Poco::Data::ODBC::ODBCMetaColumn::FDT_INT64 == rs.columnType(3));
assert(Poco::Data::ODBC::ODBCMetaColumn::FDT_DOUBLE == rs.columnType(4)); //conversion would be done with precision loss
assert(Poco::Data::ODBC::ODBCMetaColumn::FDT_DOUBLE == rs.columnType(5)); //conversion would be done with precision loss
for (size_t i = 0; i < vals.size(); ++i)
{
std::string v = rs.value(i + 1).convert<std::string>();
if (i < 3) // we've lost precision, so can't compare values
assert(vals[i] == v);
}
}
}
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); }
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); }
}
void SQLExecutor::doBulkPerformance(Poco::UInt32 size) void SQLExecutor::doBulkPerformance(Poco::UInt32 size)
{ {
@ -2800,128 +2732,6 @@ void SQLExecutor::tupleVector()
} }
void SQLExecutor::internalExtraction()
{
std::string funct = "internalExtraction()";
std::vector<Tuple<int, double, std::string> > v;
v.push_back(Tuple<int, double, std::string>(1, 1.5f, "3"));
v.push_back(Tuple<int, double, std::string>(2, 2.5f, "4"));
v.push_back(Tuple<int, double, std::string>(3, 3.5f, "5"));
v.push_back(Tuple<int, double, std::string>(4, 4.5f, "6"));
try { session() << "INSERT INTO " << ExecUtil::vectors() << " VALUES (?,?,?)", use(v), 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 " << ExecUtil::vectors() , now);
RecordSet rset(stmt);
assert (3 == rset.columnCount());
assert (4 == rset.rowCount());
int curVal = 3;
do
{
assert (rset["str0"] == curVal);
++curVal;
} while (rset.moveNext());
rset.moveFirst();
assert (rset["str0"] == "3");
rset.moveLast();
assert(rset["str0"] == "6");
RecordSet rset2(rset);
assert (3 == rset2.columnCount());
assert (4 == rset2.rowCount());
int i = rset.value<int>(0,0);
assert (1 == i);
std::string s = rset.value(0,0).convert<std::string>();
assert ("1" == s);
int a = rset.value<int>(0,2);
assert (3 == a);
try
{
double d = rset.value<double>(1,1);
assert (2.5 == d);
}
catch (BadCastException&)
{
float f = rset.value<float>(1,1);
assert (2.5 == f);
}
try
{
s = rset.value<std::string>(2, 2);
}
catch (BadCastException&)
{
UTF16String us = rset.value<Poco::UTF16String>(2, 2);
Poco::UnicodeConverter::convert(us, s);
}
assert("5" == s);
i = rset.value("str0", 2);
assert (5 == i);
const Column<std::deque<int> >& col = rset.column<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);
rset = (session() << "SELECT COUNT(*) AS cnt FROM " << ExecUtil::vectors(), now);
//various results for COUNT(*) are received from different drivers
try
{
//this is what most drivers will return
int i = rset.value<int>(0,0);
assert (4 == i);
}
catch(BadCastException&)
{
try
{
//this is for Oracle
double i = rset.value<double>(0,0);
assert (4 == int(i));
}
catch(BadCastException&)
{
//this is for PostgreSQL
Poco::Int64 big = rset.value<Poco::Int64>(0,0);
assert (4 == big);
}
}
s = rset.value("cnt", 0).convert<std::string>();
assert ("4" == s);
try { rset.column<std::deque<int> >(100); fail ("must fail"); }
catch (RangeException&) { }
try { rset.value<std::string>(0,0); fail ("must fail"); }
catch (BadCastException&) { }
stmt = (session() << "DELETE FROM " << ExecUtil::vectors(), now);
rset = stmt;
try { rset.column<std::deque<int> >(0); fail ("must fail"); }
catch (RangeException&) { }
}
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
}
void SQLExecutor::filter(const std::string& query, const std::string& intFldName) void SQLExecutor::filter(const std::string& query, const std::string& intFldName)
{ {
std::string funct = "filter()"; std::string funct = "filter()";
@ -3455,12 +3265,12 @@ void SQLExecutor::asynchronous(int rowCount)
if (!_connInitSql.empty()) tmp << _connInitSql, now; if (!_connInitSql.empty()) tmp << _connInitSql, now;
std::vector<int> data(rowCount); std::vector<int> data(rowCount);
Statement stmt = (tmp << "INSERT INTO " << ExecUtil::strings() << " VALUES(?)", use(data)); Statement stmt = (tmp << "INSERT INTO " << ExecUtil::ints() << " VALUES(?)", use(data));
Statement::Result result = stmt.executeAsync(); Statement::Result result = stmt.executeAsync();
assert (!stmt.isAsync()); assert (!stmt.isAsync());
result.wait(); result.wait();
Statement stmt1 = (tmp << "SELECT * FROM " << ExecUtil::strings(), into(data), async, now); Statement stmt1 = (tmp << "SELECT * FROM " << ExecUtil::ints(), into(data), async, now);
assert (stmt1.isAsync()); assert (stmt1.isAsync());
assert (stmt1.wait() == rowCount); assert (stmt1.wait() == rowCount);
@ -3478,7 +3288,7 @@ void SQLExecutor::asynchronous(int rowCount)
} }
// --- // ---
stmt = tmp << "SELECT * FROM " << ExecUtil::strings(), into(data), async, now; stmt = tmp << "SELECT * FROM " << ExecUtil::ints(), into(data), async, now;
assert (stmt.isAsync()); assert (stmt.isAsync());
stmt.wait(); stmt.wait();
assert (stmt.execute() == 0); assert (stmt.execute() == 0);
@ -3502,7 +3312,7 @@ void SQLExecutor::asynchronous(int rowCount)
assert (!stmt.isAsync()); assert (!stmt.isAsync());
assert (stmt.execute() == rowCount); assert (stmt.execute() == rowCount);
stmt = tmp << "SELECT * FROM " << ExecUtil::strings(), into(data), sync, now; stmt = tmp << "SELECT * FROM " << ExecUtil::ints(), into(data), sync, now;
assert (!stmt.isAsync()); assert (!stmt.isAsync());
assert (stmt.wait() == 0); assert (stmt.wait() == 0);
assert (stmt.execute() == rowCount); assert (stmt.execute() == rowCount);
@ -3514,7 +3324,7 @@ void SQLExecutor::asynchronous(int rowCount)
assert (0 == rowCount % 10); assert (0 == rowCount % 10);
int step = (int) (rowCount/10); int step = (int) (rowCount/10);
data.clear(); data.clear();
Statement stmt2 = (tmp << "SELECT * FROM " << ExecUtil::strings(), into(data), async, limit(step)); Statement stmt2 = (tmp << "SELECT * FROM " << ExecUtil::ints(), into(data), async, limit(step));
assert (data.size() == 0); assert (data.size() == 0);
assert (!stmt2.done()); assert (!stmt2.done());
std::size_t rows = 0; std::size_t rows = 0;
@ -3529,7 +3339,7 @@ void SQLExecutor::asynchronous(int rowCount)
assert (stmt2.done()); assert (stmt2.done());
assert (rowCount == data.size()); assert (rowCount == data.size());
stmt2 = tmp << "SELECT * FROM " << ExecUtil::strings(), reset; stmt2 = tmp << "SELECT * FROM " << ExecUtil::ints(), reset;
assert (!stmt2.isAsync()); assert (!stmt2.isAsync());
assert ("deque" == stmt2.getStorage()); assert ("deque" == stmt2.getStorage());
assert (stmt2.execute() == rowCount); assert (stmt2.execute() == rowCount);

View File

@ -22,6 +22,7 @@
#include "Poco/Data/Session.h" #include "Poco/Data/Session.h"
#include "Poco/Data/BulkExtraction.h" #include "Poco/Data/BulkExtraction.h"
#include "Poco/Data/BulkBinding.h" #include "Poco/Data/BulkBinding.h"
#include "Poco/Data/RecordSet.h"
#include "Poco/NumberFormatter.h" #include "Poco/NumberFormatter.h"
#include "Poco/String.h" #include "Poco/String.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
@ -87,6 +88,11 @@ struct ExecUtil
return mangleTable("Strings"); return mangleTable("Strings");
} }
static std::string ints()
{
return mangleTable("Ints");
}
static std::string tuples() static std::string tuples()
{ {
return mangleTable("Tuples"); return mangleTable("Tuples");
@ -141,11 +147,6 @@ struct ExecUtil
{ {
return mangleTable("Test"); return mangleTable("Test");
} }
static std::string numeric_tbl()
{
return mangleTable("numer_t");
}
}; };
@ -222,7 +223,6 @@ public:
void limitPrepare(); void limitPrepare();
void limitZero(); void limitZero();
void prepare(); void prepare();
void numericTypes(const std::vector<std::string>& vals);
void insertStatReuse(); void insertStatReuse();
template <typename C1, typename C2, typename C3, typename C4, typename C5, typename C6> template <typename C1, typename C2, typename C3, typename C4, typename C5, typename C6>
@ -562,13 +562,153 @@ public:
void tuples(); void tuples();
void tupleVector(); void tupleVector();
void internalExtraction(); template <typename IntType =
#ifdef POCO_64_BIT
Poco::Int64 IntType
#else
Poco::Int32 IntType
#endif
>
void internalExtraction(IntType)
{
using Poco::Data::RecordSet;
using Poco::Data::Column;
using Poco::UTF16String;
using Poco::BadCastException;
using Poco::RangeException;
std::string funct = "internalExtraction()";
std::vector<Tuple<int, double, std::string> > v;
v.push_back(Tuple<int, double, std::string>(1, 1.5, "3"));
v.push_back(Tuple<int, double, std::string>(2, 2.5, "4"));
v.push_back(Tuple<int, double, std::string>(3, 3.5, "5"));
v.push_back(Tuple<int, double, std::string>(4, 4.5, "6"));
try { session() << "INSERT INTO " << ExecUtil::vectors() << " VALUES (?,?,?)", use(v), 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 " << ExecUtil::vectors() , now);
RecordSet rset(stmt);
assert (3 == rset.columnCount());
assert (4 == rset.rowCount());
int curVal = 3;
do
{
assert (rset["str0"] == curVal);
++curVal;
} while (rset.moveNext());
rset.moveFirst();
assert (rset["str0"] == "3");
rset.moveLast();
assert(rset["str0"] == "6");
RecordSet rset2(rset);
assert (3 == rset2.columnCount());
assert (4 == rset2.rowCount());
IntType i;
try {
i = rset.value<IntType>(0, 0);
assert(1 == i);
}
catch (Poco::BadCastException& ex)
{
std::cout << ex.displayText() << std::endl;
}
std::string s = rset.value(0,0).convert<std::string>();
assert ("1" == s);
IntType a = rset.value<IntType>(0,2);
assert (3 == a);
try
{
double d = rset.value<double>(1,1);
assert (2.5 == d);
}
catch (BadCastException&)
{
float f = rset.value<float>(1,1);
assert (2.5 == f);
}
try
{
s = rset.value<std::string>(2, 2);
}
catch (BadCastException&)
{
UTF16String us = rset.value<Poco::UTF16String>(2, 2);
Poco::UnicodeConverter::convert(us, s);
}
assert("5" == s);
i = rset.value("str0", 2);
assert (5 == i);
const Column<std::deque<IntType> >& col = rset.column<std::deque<IntType> >(0);
Column<std::deque<IntType> >::Iterator it = col.begin();
Column<std::deque<IntType> >::Iterator end = col.end();
for (int i = 1; it != end; ++it, ++i)
assert (*it == i);
rset = (session() << "SELECT COUNT(*) AS cnt FROM " << ExecUtil::vectors(), now);
//various results for COUNT(*) are received from different drivers
try
{
//this is what most drivers will return
int i = rset.value<int>(0,0);
assert (4 == i);
}
catch(BadCastException&)
{
try
{
//this is for Oracle
double i = rset.value<double>(0,0);
assert (4 == int(i));
}
catch(BadCastException&)
{
//this is for PostgreSQL
Poco::Int64 big = rset.value<Poco::Int64>(0,0);
assert (4 == big);
}
}
s = rset.value("cnt", 0).convert<std::string>();
assert ("4" == s);
try { rset.column<std::deque<IntType> >(100); fail ("must fail"); }
catch (RangeException&) { }
try { rset.value<std::string>(0,0); fail ("must fail"); }
catch (BadCastException&) { }
stmt = (session() << "DELETE FROM " << ExecUtil::vectors(), now);
rset = stmt;
try { rset.column<std::deque<IntType> >(0); fail ("must fail"); }
catch (RangeException&) { }
}
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
}
void filter(const std::string& query = void filter(const std::string& query =
"SELECT * FROM " + ExecUtil::vectors() + " ORDER BY i0 ASC", "SELECT * FROM " + ExecUtil::vectors() + " ORDER BY int0 ASC",
const std::string& intFldName = "i0"); const std::string& intFldName = "int0");
void internalBulkExtraction(); void internalBulkExtraction();
void internalBulkExtractionUTF16(); void internalBulkExtractionUTF16();
void internalStorageType(); void internalStorageType();
void nulls(bool emptyStrIsSpace = false); void nulls(bool emptyStrIsSpace = false);
void notNulls(const std::string& sqlState = "23502"); void notNulls(const std::string& sqlState = "23502");

View File

@ -952,8 +952,8 @@ void PostgreSQLTest::recreatePersonTimeTable()
void PostgreSQLTest::recreateIntsTable() void PostgreSQLTest::recreateIntsTable()
{ {
dropTable("Strings"); dropTable("Ints");
try { *_pSession << "CREATE TABLE Strings (str INTEGER)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::ints() << " (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateIntsTable()"); } catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateIntsTable()"); }
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateIntsTable()"); }
} }

View File

@ -49,7 +49,7 @@ public:
typedef SharedPtr<AbstractExtractor> ExtractorPtr; typedef SharedPtr<AbstractExtractor> ExtractorPtr;
typedef SharedPtr<AbstractPreparator> PreparatorPtr; typedef SharedPtr<AbstractPreparator> PreparatorPtr;
AbstractExtraction(Poco::UInt32 limit = Limit::LIMIT_UNLIMITED, AbstractExtraction(const std::string& type, Poco::UInt32 limit = Limit::LIMIT_UNLIMITED,
Poco::UInt32 position = 0, bool bulk = false); Poco::UInt32 position = 0, bool bulk = false);
/// Creates the AbstractExtraction. A limit value equal to EXTRACT_UNLIMITED (0xffffffffu) /// Creates the AbstractExtraction. A limit value equal to EXTRACT_UNLIMITED (0xffffffffu)
/// means that we extract as much data as possible during one execute. /// means that we extract as much data as possible during one execute.
@ -153,6 +153,11 @@ public:
/// - string is empty /// - string is empty
/// - getEmptyStringIsNull() returns true /// - getEmptyStringIsNull() returns true
const std::string& type() const
{
return _type;
}
private: private:
template <typename S> template <typename S>
bool isStringNull(const S& str, bool deflt) bool isStringNull(const S& str, bool deflt)
@ -165,6 +170,7 @@ private:
return deflt; return deflt;
} }
std::string _type;
ExtractorPtr _pExtractor; ExtractorPtr _pExtractor;
Poco::UInt32 _limit; Poco::UInt32 _limit;
Poco::UInt32 _position; Poco::UInt32 _position;
@ -176,11 +182,6 @@ private:
typedef std::vector<AbstractExtraction::Ptr> AbstractExtractionVec; typedef std::vector<AbstractExtraction::Ptr> AbstractExtractionVec;
typedef std::vector<AbstractExtractionVec> AbstractExtractionVecVec; typedef std::vector<AbstractExtractionVec> AbstractExtractionVecVec;
typedef std::deque<AbstractExtraction::Ptr> AbstractExtractionDeq;
typedef std::vector<AbstractExtractionDeq> AbstractExtractionDeqVec;
typedef std::list<AbstractExtraction::Ptr> AbstractExtractionLst;
typedef std::vector<AbstractExtractionLst> AbstractExtractionLstVec;
// //
// inlines // inlines

View File

@ -47,7 +47,7 @@ public:
typedef SharedPtr<Type> Ptr; typedef SharedPtr<Type> Ptr;
BulkExtraction(C& rResult, Poco::UInt32 limit, const Position& pos = Position(0)): BulkExtraction(C& rResult, Poco::UInt32 limit, const Position& pos = Position(0)):
AbstractExtraction(limit, pos.value(), true), AbstractExtraction(typeid(C).name(), limit, pos.value(), true),
_rResult(rResult), _rResult(rResult),
_default() _default()
{ {
@ -56,7 +56,7 @@ public:
} }
BulkExtraction(C& rResult, const CValType& def, Poco::UInt32 limit, const Position& pos = Position(0)): BulkExtraction(C& rResult, const CValType& def, Poco::UInt32 limit, const Position& pos = Position(0)):
AbstractExtraction(limit, pos.value(), true), AbstractExtraction(typeid(C).name(), limit, pos.value(), true),
_rResult(rResult), _rResult(rResult),
_default(def) _default(def)
{ {

View File

@ -87,7 +87,7 @@ public:
typedef SharedPtr<Type> Ptr; typedef SharedPtr<Type> Ptr;
Extraction(T& rResult, const Position& pos = Position(0)): Extraction(T& rResult, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(T).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default(), _default(),
_extracted(false), _extracted(false),
@ -98,7 +98,7 @@ public:
} }
Extraction(T& rResult, const T& def, const Position& pos = Position(0)): Extraction(T& rResult, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(T).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default(def), _default(def),
_extracted(false), _extracted(false),
@ -179,7 +179,7 @@ public:
typedef SharedPtr<Type> Ptr; typedef SharedPtr<Type> Ptr;
Extraction(std::vector<T>& rResult, const Position& pos = Position(0)): Extraction(std::vector<T>& rResult, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(std::vector<T>).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default() _default()
{ {
@ -187,7 +187,7 @@ public:
} }
Extraction(std::vector<T>& rResult, const T& def, const Position& pos = Position(0)): Extraction(std::vector<T>& rResult, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(std::vector<T>).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default(def) _default(def)
{ {
@ -269,7 +269,7 @@ public:
typedef SharedPtr<Type> Ptr; typedef SharedPtr<Type> Ptr;
Extraction(std::vector<bool>& rResult, const Position& pos = Position(0)): Extraction(std::vector<bool>& rResult, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(std::vector<bool>).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default() _default()
{ {
@ -277,7 +277,7 @@ public:
} }
Extraction(std::vector<bool>& rResult, const bool& def, const Position& pos = Position(0)): Extraction(std::vector<bool>& rResult, const bool& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(std::vector<bool>).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default(def) _default(def)
{ {
@ -361,7 +361,7 @@ public:
typedef SharedPtr<Type> Ptr; typedef SharedPtr<Type> Ptr;
Extraction(std::list<T>& rResult, const Position& pos = Position(0)): Extraction(std::list<T>& rResult, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(std::list<T>).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default() _default()
{ {
@ -369,7 +369,7 @@ public:
} }
Extraction(std::list<T>& rResult, const T& def, const Position& pos = Position(0)): Extraction(std::list<T>& rResult, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(std::list<T>).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default(def) _default(def)
{ {
@ -451,7 +451,7 @@ public:
typedef SharedPtr<Type> Ptr; typedef SharedPtr<Type> Ptr;
Extraction(std::deque<T>& rResult, const Position& pos = Position(0)): Extraction(std::deque<T>& rResult, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(std::deque<T>).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default() _default()
{ {
@ -459,7 +459,7 @@ public:
} }
Extraction(std::deque<T>& rResult, const T& def, const Position& pos = Position(0)): Extraction(std::deque<T>& rResult, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(std::deque<T>).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default(def) _default(def)
{ {
@ -611,7 +611,7 @@ public:
typedef typename ValType::iterator Iterator; typedef typename ValType::iterator Iterator;
Extraction(std::set<T>& rResult, const Position& pos = Position(0)): Extraction(std::set<T>& rResult, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(std::set<T>).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default() _default()
{ {
@ -619,7 +619,7 @@ public:
} }
Extraction(std::set<T>& rResult, const T& def, const Position& pos = Position(0)): Extraction(std::set<T>& rResult, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(std::set<T>).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default(def) _default(def)
{ {
@ -675,7 +675,7 @@ public:
typedef SharedPtr<Type> Ptr; typedef SharedPtr<Type> Ptr;
Extraction(std::multiset<T>& rResult, const Position& pos = Position(0)): Extraction(std::multiset<T>& rResult, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(std::multiset<T>).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default() _default()
{ {
@ -683,7 +683,7 @@ public:
} }
Extraction(std::multiset<T>& rResult, const T& def, const Position& pos = Position(0)): Extraction(std::multiset<T>& rResult, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(std::multiset<T>).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default(def) _default(def)
{ {
@ -739,7 +739,7 @@ public:
typedef SharedPtr<Type> Ptr; typedef SharedPtr<Type> Ptr;
Extraction(std::map<K, V>& rResult, const Position& pos = Position(0)): Extraction(std::map<K, V>& rResult, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(std::map<K, V>).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default() _default()
{ {
@ -747,7 +747,7 @@ public:
} }
Extraction(std::map<K, V>& rResult, const V& def, const Position& pos = Position(0)): Extraction(std::map<K, V>& rResult, const V& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(std::map<K, V>).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default(def) _default(def)
{ {
@ -803,7 +803,7 @@ public:
typedef SharedPtr<Type> Ptr; typedef SharedPtr<Type> Ptr;
Extraction(std::multimap<K, V>& rResult, const Position& pos = Position(0)): Extraction(std::multimap<K, V>& rResult, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(std::multimap<K, V>).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default() _default()
{ {
@ -811,7 +811,7 @@ public:
} }
Extraction(std::multimap<K, V>& rResult, const V& def, const Position& pos = Position(0)): Extraction(std::multimap<K, V>& rResult, const V& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()), AbstractExtraction(typeid(std::multimap<K, V>).name(), Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(rResult), _rResult(rResult),
_default(def) _default(def)
{ {

View File

@ -32,28 +32,28 @@ class Data_API Position
/// indicate the recordset position in batch SQL statements. /// indicate the recordset position in batch SQL statements.
{ {
public: public:
typedef Poco::UInt32 PositionType; typedef Poco::UInt32 Type;
Position(PositionType value); Position(Type value);
/// Creates the Position. /// Creates the Position.
~Position(); ~Position();
/// Destroys the Position. /// Destroys the Position.
PositionType value() const; Type value() const;
/// Returns the position value. /// Returns the position value.
private: private:
Position(); Position();
PositionType _value; Type _value;
}; };
/// ///
/// inlines /// inlines
/// ///
inline Position::PositionType Position::value() const inline Position::Type Position::value() const
{ {
return _value; return _value;
} }

View File

@ -438,7 +438,8 @@ private:
if (typeFound) if (typeFound)
throw NotFoundException(Poco::format("Column name: %s", name)); throw NotFoundException(Poco::format("Column name: %s", name));
else else
throw NotFoundException(Poco::format("Column type: %s, name: %s", std::string(typeid(T).name()), name)); throw NotFoundException(Poco::format("Column type: %s, Container type: %s, name: %s",
std::string(typeid(T).name()), std::string(typeid(ExtractionVecPtr).name()), name));
} }
template <class C, class E> template <class C, class E>
@ -469,9 +470,13 @@ private:
} }
else else
{ {
throw Poco::BadCastException(Poco::format("Type cast failed!\nColumn: %z\nTarget type:\t%s", throw Poco::BadCastException(Poco::format("RecordSet::columnImpl(%z) type cast failed!\nTarget type:\t%s"
"\nTarget container type:\t%s\nSource container type:\t%s\nSource abstraction type:\t%s",
pos, pos,
std::string(typeid(T).name()))); std::string(typeid(T).name()),
std::string(typeid(ExtractionVecPtr).name()),
rExtractions[pos]->type(),
std::string(typeid(rExtractions[pos].get()).name())));
} }
} }

View File

@ -85,12 +85,15 @@ public:
~RowFilter(); ~RowFilter();
/// Destroys the RowFilter. /// Destroys the RowFilter.
void addFilter(const Ptr& pFilter, LogicOperator comparison); void addFilter(Ptr pFilter, LogicOperator comparison);
/// Appends another filter to this one. /// Appends another filter to this one.
void removeFilter(const Ptr& pFilter); void removeFilter(Ptr pFilter);
/// Removes filter from this filter. /// Removes filter from this filter.
bool has(Ptr pFilter) const;
/// Returns true if this filter is parent of pFilter;
template <typename T> template <typename T>
void add(const std::string& name, Comparison comparison, const T& value, LogicOperator op = OP_OR) void add(const std::string& name, Comparison comparison, const T& value, LogicOperator op = OP_OR)
/// Adds value to the filter. /// Adds value to the filter.
@ -185,6 +188,12 @@ private:
/// ///
inline bool RowFilter::has(Ptr pFilter) const
{
return _filterMap.find(pFilter) != _filterMap.end();
}
inline bool RowFilter::isEmpty() const inline bool RowFilter::isEmpty() const
{ {
return _comparisonMap.size() == 0; return _comparisonMap.size() == 0;

View File

@ -21,9 +21,10 @@ namespace Poco {
namespace Data { namespace Data {
AbstractExtraction::AbstractExtraction(Poco::UInt32 limit, AbstractExtraction::AbstractExtraction(const std::string& type, Poco::UInt32 limit,
Poco::UInt32 extractionPosition, Poco::UInt32 extractionPosition,
bool bulk): bool bulk):
_type(type),
_pExtractor(0), _pExtractor(0),
_limit(limit), _limit(limit),
_position(extractionPosition), _position(extractionPosition),

View File

@ -29,6 +29,7 @@ RowFilter::RowFilter(RecordSet* pRecordSet): _pRecordSet(pRecordSet), _not(false
{ {
poco_check_ptr(pRecordSet); poco_check_ptr(pRecordSet);
init(); init();
duplicate();
_pRecordSet->filter(this); _pRecordSet->filter(this);
} }
@ -39,6 +40,7 @@ RowFilter::RowFilter(Ptr pParent, LogicOperator op): _pRecordSet(0),
{ {
poco_check_ptr(_pParent.get()); poco_check_ptr(_pParent.get());
init(); init();
duplicate();
_pParent->addFilter(this, op); _pParent->addFilter(this, op);
} }
@ -62,7 +64,9 @@ RowFilter::~RowFilter()
try try
{ {
if (_pRecordSet) _pRecordSet->filter(0); if (_pRecordSet) _pRecordSet->filter(0);
if (_pParent.get()) _pParent->removeFilter(this); if (_pParent && _pParent->has(this))
_pParent->removeFilter(this);
release();
} }
catch (...) catch (...)
{ {
@ -162,7 +166,7 @@ RowFilter::Comparison RowFilter::getComparison(const std::string& comp) const
} }
void RowFilter::addFilter(const Ptr& pFilter, LogicOperator comparison) void RowFilter::addFilter(Ptr pFilter, LogicOperator comparison)
{ {
poco_check_ptr (_pRecordSet); poco_check_ptr (_pRecordSet);
@ -172,13 +176,14 @@ void RowFilter::addFilter(const Ptr& pFilter, LogicOperator comparison)
} }
void RowFilter::removeFilter(const Ptr& pFilter) void RowFilter::removeFilter(Ptr pFilter)
{ {
poco_check_ptr (_pRecordSet); poco_check_ptr (_pRecordSet);
pFilter->_pRecordSet = 0;
_pRecordSet->moveFirst(); _pRecordSet->moveFirst();
_filterMap.erase(pFilter); _filterMap.erase(pFilter);
pFilter->_pRecordSet = 0;
pFilter->_pParent = 0;
} }

View File

@ -319,7 +319,7 @@ void StatementImpl::setStorage(const std::string& storage)
void StatementImpl::makeExtractors(std::size_t count) void StatementImpl::makeExtractors(std::size_t count)
{ {
// type cast is needed when size_t is 64 bit // type cast is needed when size_t is 64 bit
makeExtractors(count, static_cast<Position::PositionType>(currentDataSet())); makeExtractors(count, static_cast<Position::Type>(currentDataSet()));
} }
void StatementImpl::makeExtractors(std::size_t count, const Position& position) void StatementImpl::makeExtractors(std::size_t count, const Position& position)

View File

@ -208,6 +208,11 @@ namespace Poco {
#endif #endif
#if defined(POCO_PTR_IS_64_BIT) && (POCO_PTR_IS_64_BIT == 1)
#define POCO_64_BIT
#endif
} // namespace Poco } // namespace Poco