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()
{
dropTable("Strings");
try { *_pSession << "CREATE TABLE Strings (str INTEGER)", now; }
dropTable("Ints");
try { *_pSession << "CREATE TABLE Ints (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.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,
ParameterBinding dataBinding,
TypeInfo* pDataTypes,
ODBCMetaColumn::NumericConversion numericConversion,
bool insertOnly);
/// Creates the Binder.
@ -1043,7 +1042,6 @@ private:
std::size_t _maxCharColLength;
std::size_t _maxWCharColLength;
std::size_t _maxVarBinColSize;
ODBCMetaColumn::NumericConversion _numericConversion;
NullCbMap _nullCbMap;
bool _insertOnly;
};

View File

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

View File

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

View File

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

View File

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

View File

@ -45,7 +45,6 @@ class ODBC_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl>
{
public:
static const std::size_t ODBC_MAX_FIELD_SIZE = 1024u;
static const char* const NUMERIC_CONVERSION_PROPERTY;
enum TransactionCapability
{
@ -168,22 +167,10 @@ public:
Poco::Any dataTypeInfo(const std::string& rName="");
/// 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:
void setDataTypeInfo(const std::string& rName, const Poco::Any& rValue);
/// No-op. Throws InvalidAccessException.
void setNumericConversion(const std::string&, const Poco::Any& rValue);
Poco::Any numericConversion(const std::string& nm);
void init();
static const int FUNCTIONS = SQL_API_ODBC3_ALL_FUNCTIONS_SIZE;
@ -199,7 +186,6 @@ private:
Poco::Any _maxFieldSize;
bool _autoBind;
bool _autoExtract;
ODBCMetaColumn::NumericConversion _numericConversion;
TypeInfo _dataTypes;
char _canTransact;
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

View File

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

View File

@ -23,10 +23,9 @@ namespace Data {
namespace ODBC {
ODBCMetaColumn::ODBCMetaColumn(const StatementHandle& rStmt, std::size_t position, NumericConversion numericConversion) :
ODBCMetaColumn::ODBCMetaColumn(const StatementHandle& rStmt, std::size_t position) :
MetaColumn(position),
_rStmt(rStmt),
_numericConversion(numericConversion)
_rStmt(rStmt)
{
init();
}
@ -117,44 +116,17 @@ void ODBCMetaColumn::init()
case SQL_NUMERIC:
case SQL_DECIMAL:
{
bool toString = false;
switch (_numericConversion)
{
case NC_BEST_FIT:
case NC_BEST_FIT_DBL_LIMIT:
if (0 == _columnDesc.decimalDigits)
{
if (_columnDesc.size <= 9)
setType(MetaColumn::FDT_INT32);
else if (_columnDesc.size <= 18)
#ifdef POCO_64_BIT
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
setType(MetaColumn::FDT_STRING);
setType(MetaColumn::FDT_INT32);
#endif
}
else
{
setType(MetaColumn::FDT_DOUBLE);
}
break;

View File

@ -47,7 +47,6 @@ ODBCStatementImpl::ODBCStatementImpl(SessionImpl& rSession):
_prepared(false),
_affectedRowCount(0),
_canCompile(true),
_numericConversion(rSession.numericConversion()),
_isPostgres(false),
_insertHint(false)
{
@ -111,9 +110,8 @@ void ODBCStatementImpl::compileImpl()
}
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();
doPrepare();
@ -156,7 +154,7 @@ bool ODBCStatementImpl::addPreparator(bool addAlways)
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
prep = new Preparator(*_preparations[0]);
@ -340,19 +338,23 @@ bool ODBCStatementImpl::hasNext()
if (!nextRowReady())
{
// have a loop here, as there could be one or more empty results
do {
if (hasMoreDataSets()) {
do
{
if (hasMoreDataSets())
{
activateNextDataSet();
if (!nextResultSet())
return false;
addPreparator();
}
else {
if (nextResultSet()) {
else
{
if (nextResultSet())
{
if (!addPreparator(false)) // skip the result set if it has no columns
continue;
fillColumns(currentDataSet() + 1);
makeExtractors(_preparations.back()->columns(), static_cast<Position::PositionType>(currentDataSet() + 1));
makeExtractors(_preparations.back()->columns(), static_cast<Position::Type>(currentDataSet() + 1));
activateNextDataSet();
}
else return false;
@ -469,7 +471,7 @@ void ODBCStatementImpl::fillColumns(size_t dataSetPos)
_columnPtrs.resize(dataSetPos + 1);
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,
std::size_t maxFieldSize,
DataExtraction dataExtraction,
ODBCMetaColumn::NumericConversion numericConversion,
bool isPostgres) :
_rStmt(rStmt),
_maxFieldSize(maxFieldSize),
_dataExtraction(dataExtraction),
_numericConversion(numericConversion)
_dataExtraction(dataExtraction)
{
SQLCHAR* pStr = (SQLCHAR*) statement.c_str();
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):
_rStmt(other._rStmt),
_maxFieldSize(other._maxFieldSize),
_dataExtraction(other._dataExtraction),
_numericConversion(other._numericConversion)
_dataExtraction(other._dataExtraction)
{
resize();
}
@ -169,7 +166,7 @@ std::size_t Preparator::maxDataSize(std::size_t pos) const
try
{
ODBCMetaColumn mc(_rStmt, pos, _numericConversion);
ODBCMetaColumn mc(_rStmt, pos);
sz = mc.length();
// accommodate for terminating zero (non-bulk only!)

View File

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

View File

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

View File

@ -578,17 +578,6 @@ void ODBCDB2Test::recreateNullableTable()
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()
{
@ -637,8 +626,8 @@ void ODBCDB2Test::recreatePersonDateTimeTable()
void ODBCDB2Test::recreateIntsTable()
{
dropObject("TABLE", ExecUtil::strings());
try { session() << "CREATE TABLE " << ExecUtil::strings() << " (str INTEGER)", now; }
dropObject("TABLE", ExecUtil::ints());
try { session() << "CREATE TABLE " << ExecUtil::ints() << " (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.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, testNullable);
CppUnit_addTest(pSuite, ODBCDB2Test, testReconnect);
CppUnit_addTest(pSuite, ODBCDB2Test, testNumeric);
CppUnit_addTest(pSuite, ODBCDB2Test, testXMLColumn);
CppUnit_addTest(pSuite, ODBCDB2Test, testInsertStatReuse);

View File

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

View File

@ -304,8 +304,8 @@ void ODBCMySQLTest::recreatePersonDateTimeTable()
void ODBCMySQLTest::recreateIntsTable()
{
dropObject("TABLE", ExecUtil::strings());
try { *_pSession << "CREATE TABLE " << ExecUtil::strings() << " (str INTEGER)", now; }
dropObject("TABLE", ExecUtil::ints());
try { *_pSession << "CREATE TABLE " << ExecUtil::ints() << " (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.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;
#define ORACLE_ODBC_DRIVER "Oracle in XE"
#define ORACLE_ODBC_DRIVER "Oracle in OraClient12Home1_32bit"//XE"
#define ORACLE_DSN "PocoDataOracleTest"
#define ORACLE_SERVER POCO_ODBC_TEST_DATABASE_SERVER
#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()
{
const std::size_t maxFldSize = 1000000;
@ -598,18 +617,18 @@ void ODBCOracleTest::testAutoTransaction()
recreateIntsTable();
session().setFeature("autoCommit", true);
session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (1)", now;
localSession << "SELECT count(*) FROM " << ExecUtil::person() , into(count), now;
session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (1)", now;
localSession << "SELECT count(*) FROM " << ExecUtil::ints() , into(count), now;
assert (1 == count);
session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (2)", now;
localSession << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now;
session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (2)", now;
localSession << "SELECT count(*) FROM " << ExecUtil::ints(), into(count), now;
assert (2 == count);
session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (3)", now;
localSession << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now;
session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (3)", now;
localSession << "SELECT count(*) FROM " << ExecUtil::ints(), into(count), now;
assert (3 == count);
session() << "DELETE FROM " << ExecUtil::strings(), now;
localSession << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now;
session() << "DELETE FROM " << ExecUtil::ints(), now;
localSession << "SELECT count(*) FROM " << ExecUtil::ints(), into(count), now;
assert (0 == count);
session().setFeature("autoCommit", false);
@ -617,26 +636,26 @@ void ODBCOracleTest::testAutoTransaction()
try
{
AutoTransaction at(session());
session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (1)", now;
session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (2)", now;
session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (1)", now;
session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (2)", now;
session() << "BAD QUERY", now;
} catch (Poco::Exception&) {}
session() << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now;
session() << "SELECT count(*) FROM " << ExecUtil::ints(), into(count), now;
assert (0 == count);
AutoTransaction at(session());
session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (1)", now;
session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (2)", now;
session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (3)", now;
session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (1)", now;
session() << "INSERT INTO " << ExecUtil::ints() << " VALUES (2)", 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);
at.commit();
localSession << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now;
localSession << "SELECT count(*) FROM " << ExecUtil::ints(), into(count), now;
assert (3 == count);
session().setFeature("autoCommit", ac);
@ -726,8 +745,8 @@ void ODBCOracleTest::recreatePersonDateTable()
void ODBCOracleTest::recreateIntsTable()
{
dropObject("TABLE", ExecUtil::strings());
try { *_pSession << "CREATE TABLE " << ExecUtil::strings() <<" (str INTEGER)", now; }
dropObject("TABLE", ExecUtil::ints());
try { *_pSession << "CREATE TABLE " << ExecUtil::ints() <<" (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.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 testInternalExtraction();
void testBLOB();
void testMultipleResults();

View File

@ -482,8 +482,8 @@ void ODBCPostgreSQLTest::recreatePersonTimeTable()
void ODBCPostgreSQLTest::recreateIntsTable()
{
dropObject("TABLE", ExecUtil::strings());
try { session() << "CREATE TABLE " << ExecUtil::strings() <<" (str INTEGER)", now; }
dropObject("TABLE", ExecUtil::ints());
try { session() << "CREATE TABLE " << ExecUtil::ints() <<" (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.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()
{
dropObject("TABLE", ExecUtil::strings());
try { session() << "CREATE TABLE " << ExecUtil::strings() <<" (str INTEGER)", now; }
dropObject("TABLE", ExecUtil::ints());
try { session() << "CREATE TABLE " << ExecUtil::ints() <<" (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.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()
{
dropObject("TABLE", ExecUtil::strings());
try { session() << "CREATE TABLE " << ExecUtil::strings() <<" (str INTEGER)", now; }
dropObject("TABLE", ExecUtil::ints());
try { session() << "CREATE TABLE " << ExecUtil::ints() <<" (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.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()
{
doPersonTable();
@ -216,8 +205,8 @@ void SybaseODBC::recreatePersonDateTimeTable()
void SybaseODBC::recreateIntsTable()
{
dropObject("TABLE", ExecUtil::strings());
try { session() << "CREATE TABLE " << ExecUtil::strings() << " (str INTEGER)", now; }
dropObject("TABLE", ExecUtil::ints());
try { session() << "CREATE TABLE " << ExecUtil::ints() << " (str INTEGER)", now; }
catch (ConnectionException& ce){ std::cout << ce.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, testNullable);
CppUnit_addTest(pSuite, SybaseODBC, testReconnect);
CppUnit_addTest(pSuite, SybaseODBC, testNumeric);
CppUnit_addTest(pSuite, SybaseODBC, testInsertStatReuse);
_pExecutor = 0;

View File

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

View File

@ -960,7 +960,7 @@ void ODBCTest::testInternalExtraction()
recreateVectorsTable();
_pSession->setFeature("autoBind", bindValue(i));
_pSession->setFeature("autoExtract", bindValue(i+1));
_pExecutor->internalExtraction();
_pExecutor->internalExtraction(0);
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()
{
@ -1413,7 +1386,7 @@ ODBCTest::SessionPtr ODBCTest::init(const std::string& driver,
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);
}catch (ConnectionFailedException& ex)
{

View File

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

View File

@ -32,7 +32,6 @@
#include "Poco/Data/Time.h"
#include "Poco/Data/LOB.h"
#include "Poco/Data/StatementImpl.h"
#include "Poco/Data/RecordSet.h"
#include "Poco/Data/RowIterator.h"
#include "Poco/Data/RowFilter.h"
#include "Poco/Data/BulkExtraction.h"
@ -1518,7 +1517,7 @@ void SQLExecutor::insertSingleBulk()
{
std::string funct = "insertSingleBulk()";
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)
{
@ -1526,12 +1525,12 @@ void SQLExecutor::insertSingleBulk()
assert (1 == i);
}
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(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
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(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assert (count == ((0+99)*100/2));
@ -1592,16 +1591,16 @@ void SQLExecutor::insertSingleBulkVec()
for (int x = 0; x < 100; ++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();
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(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
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(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assert (count == ((0+99)*100/2));
@ -1617,12 +1616,12 @@ void SQLExecutor::limits()
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(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
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(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assert (retData.size() == 50);
@ -1642,12 +1641,12 @@ void SQLExecutor::limitZero()
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(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
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(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assert (retData.size() == 0);
@ -1663,12 +1662,12 @@ void SQLExecutor::limitOnce()
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(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
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 (retData.size() == 50);
stmt.execute();
@ -1696,14 +1695,14 @@ void SQLExecutor::limitPrepare()
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());
}
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
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 (!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
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(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
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)
{
@ -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)
{
std::string funct = "filter()";
@ -3455,12 +3265,12 @@ void SQLExecutor::asynchronous(int rowCount)
if (!_connInitSql.empty()) tmp << _connInitSql, now;
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();
assert (!stmt.isAsync());
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.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());
stmt.wait();
assert (stmt.execute() == 0);
@ -3502,7 +3312,7 @@ void SQLExecutor::asynchronous(int rowCount)
assert (!stmt.isAsync());
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.wait() == 0);
assert (stmt.execute() == rowCount);
@ -3514,7 +3324,7 @@ void SQLExecutor::asynchronous(int rowCount)
assert (0 == rowCount % 10);
int step = (int) (rowCount/10);
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 (!stmt2.done());
std::size_t rows = 0;
@ -3529,7 +3339,7 @@ void SQLExecutor::asynchronous(int rowCount)
assert (stmt2.done());
assert (rowCount == data.size());
stmt2 = tmp << "SELECT * FROM " << ExecUtil::strings(), reset;
stmt2 = tmp << "SELECT * FROM " << ExecUtil::ints(), reset;
assert (!stmt2.isAsync());
assert ("deque" == stmt2.getStorage());
assert (stmt2.execute() == rowCount);

View File

@ -22,6 +22,7 @@
#include "Poco/Data/Session.h"
#include "Poco/Data/BulkExtraction.h"
#include "Poco/Data/BulkBinding.h"
#include "Poco/Data/RecordSet.h"
#include "Poco/NumberFormatter.h"
#include "Poco/String.h"
#include "Poco/Exception.h"
@ -87,6 +88,11 @@ struct ExecUtil
return mangleTable("Strings");
}
static std::string ints()
{
return mangleTable("Ints");
}
static std::string tuples()
{
return mangleTable("Tuples");
@ -141,11 +147,6 @@ struct ExecUtil
{
return mangleTable("Test");
}
static std::string numeric_tbl()
{
return mangleTable("numer_t");
}
};
@ -222,7 +223,6 @@ public:
void limitPrepare();
void limitZero();
void prepare();
void numericTypes(const std::vector<std::string>& vals);
void insertStatReuse();
template <typename C1, typename C2, typename C3, typename C4, typename C5, typename C6>
@ -562,13 +562,153 @@ public:
void tuples();
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 =
"SELECT * FROM " + ExecUtil::vectors() + " ORDER BY i0 ASC",
const std::string& intFldName = "i0");
"SELECT * FROM " + ExecUtil::vectors() + " ORDER BY int0 ASC",
const std::string& intFldName = "int0");
void internalBulkExtraction();
void internalBulkExtractionUTF16();
void internalStorageType();
void nulls(bool emptyStrIsSpace = false);
void notNulls(const std::string& sqlState = "23502");

View File

@ -952,8 +952,8 @@ void PostgreSQLTest::recreatePersonTimeTable()
void PostgreSQLTest::recreateIntsTable()
{
dropTable("Strings");
try { *_pSession << "CREATE TABLE Strings (str INTEGER)", now; }
dropTable("Ints");
try { *_pSession << "CREATE TABLE " << ExecUtil::ints() << " (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.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<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);
/// Creates the AbstractExtraction. A limit value equal to EXTRACT_UNLIMITED (0xffffffffu)
/// means that we extract as much data as possible during one execute.
@ -153,6 +153,11 @@ public:
/// - string is empty
/// - getEmptyStringIsNull() returns true
const std::string& type() const
{
return _type;
}
private:
template <typename S>
bool isStringNull(const S& str, bool deflt)
@ -165,6 +170,7 @@ private:
return deflt;
}
std::string _type;
ExtractorPtr _pExtractor;
Poco::UInt32 _limit;
Poco::UInt32 _position;
@ -176,11 +182,6 @@ private:
typedef std::vector<AbstractExtraction::Ptr> AbstractExtractionVec;
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

View File

@ -47,7 +47,7 @@ public:
typedef SharedPtr<Type> Ptr;
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),
_default()
{
@ -56,7 +56,7 @@ public:
}
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),
_default(def)
{

View File

@ -87,7 +87,7 @@ public:
typedef SharedPtr<Type> Ptr;
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),
_default(),
_extracted(false),
@ -98,7 +98,7 @@ public:
}
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),
_default(def),
_extracted(false),
@ -179,7 +179,7 @@ public:
typedef SharedPtr<Type> Ptr;
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),
_default()
{
@ -187,7 +187,7 @@ public:
}
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),
_default(def)
{
@ -269,7 +269,7 @@ public:
typedef SharedPtr<Type> Ptr;
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),
_default()
{
@ -277,7 +277,7 @@ public:
}
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),
_default(def)
{
@ -361,7 +361,7 @@ public:
typedef SharedPtr<Type> Ptr;
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),
_default()
{
@ -369,7 +369,7 @@ public:
}
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),
_default(def)
{
@ -451,7 +451,7 @@ public:
typedef SharedPtr<Type> Ptr;
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),
_default()
{
@ -459,7 +459,7 @@ public:
}
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),
_default(def)
{
@ -611,7 +611,7 @@ public:
typedef typename ValType::iterator Iterator;
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),
_default()
{
@ -619,7 +619,7 @@ public:
}
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),
_default(def)
{
@ -675,7 +675,7 @@ public:
typedef SharedPtr<Type> Ptr;
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),
_default()
{
@ -683,7 +683,7 @@ public:
}
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),
_default(def)
{
@ -739,7 +739,7 @@ public:
typedef SharedPtr<Type> Ptr;
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),
_default()
{
@ -747,7 +747,7 @@ public:
}
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),
_default(def)
{
@ -803,7 +803,7 @@ public:
typedef SharedPtr<Type> Ptr;
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),
_default()
{
@ -811,7 +811,7 @@ public:
}
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),
_default(def)
{

View File

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

View File

@ -438,7 +438,8 @@ private:
if (typeFound)
throw NotFoundException(Poco::format("Column name: %s", name));
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>
@ -469,9 +470,13 @@ private:
}
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,
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();
/// Destroys the RowFilter.
void addFilter(const Ptr& pFilter, LogicOperator comparison);
void addFilter(Ptr pFilter, LogicOperator comparison);
/// Appends another filter to this one.
void removeFilter(const Ptr& pFilter);
void removeFilter(Ptr pFilter);
/// Removes filter from this filter.
bool has(Ptr pFilter) const;
/// Returns true if this filter is parent of pFilter;
template <typename T>
void add(const std::string& name, Comparison comparison, const T& value, LogicOperator op = OP_OR)
/// 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
{
return _comparisonMap.size() == 0;

View File

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

View File

@ -29,6 +29,7 @@ RowFilter::RowFilter(RecordSet* pRecordSet): _pRecordSet(pRecordSet), _not(false
{
poco_check_ptr(pRecordSet);
init();
duplicate();
_pRecordSet->filter(this);
}
@ -39,6 +40,7 @@ RowFilter::RowFilter(Ptr pParent, LogicOperator op): _pRecordSet(0),
{
poco_check_ptr(_pParent.get());
init();
duplicate();
_pParent->addFilter(this, op);
}
@ -62,7 +64,9 @@ RowFilter::~RowFilter()
try
{
if (_pRecordSet) _pRecordSet->filter(0);
if (_pParent.get()) _pParent->removeFilter(this);
if (_pParent && _pParent->has(this))
_pParent->removeFilter(this);
release();
}
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);
@ -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);
pFilter->_pRecordSet = 0;
_pRecordSet->moveFirst();
_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)
{
// 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)

View File

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