configurable internal storage

This commit is contained in:
Aleksandar Fabijanic 2007-05-30 23:20:47 +00:00
parent 911d0c5b82
commit c1ecb3ee05
30 changed files with 1137 additions and 199 deletions

View File

@ -128,7 +128,7 @@ private:
void fillColumns(); void fillColumns();
void checkError(SQLRETURN rc, const std::string& msg=""); void checkError(SQLRETURN rc, const std::string& msg="");
SessionImpl& _rSession; const SQLHDBC& _rConnection;
const StatementHandle _stmt; const StatementHandle _stmt;
Poco::SharedPtr<Preparation> _pPreparation; Poco::SharedPtr<Preparation> _pPreparation;
Poco::SharedPtr<Binder> _pBinder; Poco::SharedPtr<Binder> _pBinder;

View File

@ -35,7 +35,7 @@
#include "Poco/Data/ODBC/ODBCStatementImpl.h" #include "Poco/Data/ODBC/ODBCStatementImpl.h"
#include "Poco/Data/ODBC/Handle.h" #include "Poco/Data/ODBC/ConnectionHandle.h"
#include "Poco/Data/ODBC/Utility.h" #include "Poco/Data/ODBC/Utility.h"
#include "Poco/Data/ODBC/ODBCException.h" #include "Poco/Data/ODBC/ODBCException.h"
#include "Poco/Data/AbstractPrepare.h" #include "Poco/Data/AbstractPrepare.h"
@ -51,8 +51,9 @@ const std::string ODBCStatementImpl::INVALID_CURSOR_STATE = "24000";
ODBCStatementImpl::ODBCStatementImpl(SessionImpl& rSession): ODBCStatementImpl::ODBCStatementImpl(SessionImpl& rSession):
_rSession(rSession), Poco::Data::StatementImpl(rSession),
_stmt(_rSession.dbc()), _rConnection(rSession.dbc()),
_stmt(rSession.dbc()),
_stepCalled(false), _stepCalled(false),
_nextResponse(0) _nextResponse(0)
{ {
@ -62,7 +63,7 @@ ODBCStatementImpl::ODBCStatementImpl(SessionImpl& rSession):
0), 0),
"SQLSetStmtAttr(SQL_CURSOR_TYPE, SQL_CURSOR_FORWARD_ONLY)"); "SQLSetStmtAttr(SQL_CURSOR_TYPE, SQL_CURSOR_FORWARD_ONLY)");
if (_rSession.getFeature("autoBind")) if (session().getFeature("autoBind"))
{ {
SQLSetStmtAttr(_stmt, SQLSetStmtAttr(_stmt,
SQL_ATTR_PARAM_BIND_TYPE, SQL_ATTR_PARAM_BIND_TYPE,
@ -96,16 +97,16 @@ void ODBCStatementImpl::compileImpl()
if (statement.empty()) if (statement.empty())
throw ODBCException("Empty statements are illegal"); throw ODBCException("Empty statements are illegal");
Preparation::DataExtraction ext = _rSession.getFeature("autoExtract") ? Preparation::DataExtraction ext = session().getFeature("autoExtract") ?
Preparation::DE_BOUND : Preparation::DE_MANUAL; Preparation::DE_BOUND : Preparation::DE_MANUAL;
std::size_t maxFieldSize = AnyCast<std::size_t>(_rSession.getProperty("maxFieldSize")); std::size_t maxFieldSize = AnyCast<std::size_t>(session().getProperty("maxFieldSize"));
_pPreparation = new Preparation(_stmt, _pPreparation = new Preparation(_stmt,
statement, statement,
maxFieldSize, maxFieldSize,
ext); ext);
Binder::ParameterBinding bind = _rSession.getFeature("autoBind") ? Binder::ParameterBinding bind = session().getFeature("autoBind") ?
Binder::PB_IMMEDIATE : Binder::PB_AT_EXEC; Binder::PB_IMMEDIATE : Binder::PB_AT_EXEC;
_pBinder = new Binder(_stmt, bind); _pBinder = new Binder(_stmt, bind);
@ -274,7 +275,7 @@ std::string ODBCStatementImpl::nativeSQL()
pNative = new char[retlen]; pNative = new char[retlen];
memset(pNative, 0, retlen); memset(pNative, 0, retlen);
length = retlen; length = retlen;
if (Utility::isError(SQLNativeSql(_rSession.dbc(), if (Utility::isError(SQLNativeSql(_rConnection,
(POCO_SQLCHAR*) statement.c_str(), (POCO_SQLCHAR*) statement.c_str(),
(SQLINTEGER) statement.size(), (SQLINTEGER) statement.size(),
(POCO_SQLCHAR*) pNative, (POCO_SQLCHAR*) pNative,
@ -282,7 +283,7 @@ std::string ODBCStatementImpl::nativeSQL()
&retlen))) &retlen)))
{ {
delete [] pNative; delete [] pNative;
throw ConnectionException(_rSession.dbc(), "SQLNativeSql()"); throw ConnectionException(_rConnection, "SQLNativeSql()");
} }
++retlen;//accomodate for terminating '\0' ++retlen;//accomodate for terminating '\0'
}while (retlen > length); }while (retlen > length);

View File

@ -828,6 +828,21 @@ void ODBCDB2Test::testInternalExtraction()
} }
void ODBCDB2Test::testInternalStorageType()
{
if (!_pSession) fail ("Test not available.");
for (int i = 0; i < 8;)
{
recreateVectorsTable();
_pSession->setFeature("autoBind", bindValues[i]);
_pSession->setFeature("autoExtract", bindValues[i+1]);
_pExecutor->internalStorageType();
i += 2;
}
}
void ODBCDB2Test::dropTable(const std::string& tableName) void ODBCDB2Test::dropTable(const std::string& tableName)
{ {
try try
@ -1056,6 +1071,7 @@ CppUnit::Test* ODBCDB2Test::suite()
CppUnit_addTest(pSuite, ODBCDB2Test, testTuple); CppUnit_addTest(pSuite, ODBCDB2Test, testTuple);
CppUnit_addTest(pSuite, ODBCDB2Test, testTupleVector); CppUnit_addTest(pSuite, ODBCDB2Test, testTupleVector);
CppUnit_addTest(pSuite, ODBCDB2Test, testInternalExtraction); CppUnit_addTest(pSuite, ODBCDB2Test, testInternalExtraction);
CppUnit_addTest(pSuite, ODBCDB2Test, testInternalStorageType);
return pSuite; return pSuite;
} }

View File

@ -115,6 +115,7 @@ public:
void testTupleVector(); void testTupleVector();
void testInternalExtraction(); void testInternalExtraction();
void testInternalStorageType();
void setUp(); void setUp();
void tearDown(); void tearDown();

View File

@ -35,6 +35,7 @@
#include "CppUnit/TestSuite.h" #include "CppUnit/TestSuite.h"
#include "Poco/String.h" #include "Poco/String.h"
#include "Poco/Format.h" #include "Poco/Format.h"
#include "Poco/Tuple.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include "Poco/Data/Common.h" #include "Poco/Data/Common.h"
#include "Poco/Data/BLOB.h" #include "Poco/Data/BLOB.h"
@ -54,6 +55,7 @@ using Poco::Data::ODBC::ConnectionException;
using Poco::Data::ODBC::StatementException; using Poco::Data::ODBC::StatementException;
using Poco::Data::ODBC::StatementDiagnostics; using Poco::Data::ODBC::StatementDiagnostics;
using Poco::format; using Poco::format;
using Poco::Tuple;
using Poco::NotFoundException; using Poco::NotFoundException;
@ -817,34 +819,46 @@ void ODBCMySQLTest::testInternalExtraction()
} }
void ODBCMySQLTest::dropTable(const std::string& tableName) void ODBCMySQLTest::testInternalStorageType()
{ {
try if (!_pSession) fail ("Test not available.");
for (int i = 0; i < 8;)
{ {
*_pSession << format("DROP TABLE %s", tableName), now; recreateVectorsTable();
} _pSession->setFeature("autoBind", bindValues[i]);
catch (StatementException& ex) _pSession->setFeature("autoExtract", bindValues[i+1]);
{ _pExecutor->internalStorageType();
bool ignoreError = false; i += 2;
const StatementDiagnostics::FieldVec& flds = ex.diagnostics().fields();
StatementDiagnostics::Iterator it = flds.begin();
for (; it != flds.end(); ++it)
{
if (1051 == it->_nativeError)//(table does not exist)
{
ignoreError = true;
break;
} }
} }
if (!ignoreError) throw;
void ODBCMySQLTest::testStoredProcedure()
{
//MySQL is currently buggy in this area:
// http://bugs.mysql.com/bug.php?id=17898
// http://bugs.mysql.com/bug.php?id=27632
} }
void ODBCMySQLTest::testStoredFunction()
{
//MySQL is currently buggy in this area:
// http://bugs.mysql.com/bug.php?id=17898
// http://bugs.mysql.com/bug.php?id=27632
}
void ODBCMySQLTest::dropObject(const std::string& type, const std::string& name)
{
*_pSession << format("DROP %s IF EXISTS %s", type, name), now;
} }
void ODBCMySQLTest::recreatePersonTable() void ODBCMySQLTest::recreatePersonTable()
{ {
dropTable("Person"); dropObject("TABLE", "Person");
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; } try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); }
@ -853,7 +867,7 @@ void ODBCMySQLTest::recreatePersonTable()
void ODBCMySQLTest::recreatePersonBLOBTable() void ODBCMySQLTest::recreatePersonBLOBTable()
{ {
dropTable("Person"); dropObject("TABLE", "Person");
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BLOB)", now; } try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BLOB)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
@ -862,7 +876,7 @@ void ODBCMySQLTest::recreatePersonBLOBTable()
void ODBCMySQLTest::recreateIntsTable() void ODBCMySQLTest::recreateIntsTable()
{ {
dropTable("Strings"); dropObject("TABLE", "Strings");
try { *_pSession << "CREATE TABLE Strings (str INTEGER)", now; } try { *_pSession << "CREATE TABLE Strings (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()"); }
@ -871,7 +885,7 @@ void ODBCMySQLTest::recreateIntsTable()
void ODBCMySQLTest::recreateStringsTable() void ODBCMySQLTest::recreateStringsTable()
{ {
dropTable("Strings"); dropObject("TABLE", "Strings");
try { *_pSession << "CREATE TABLE Strings (str VARCHAR(30))", now; } try { *_pSession << "CREATE TABLE Strings (str VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); }
@ -880,7 +894,7 @@ void ODBCMySQLTest::recreateStringsTable()
void ODBCMySQLTest::recreateFloatsTable() void ODBCMySQLTest::recreateFloatsTable()
{ {
dropTable("Strings"); dropObject("TABLE", "Strings");
try { *_pSession << "CREATE TABLE Strings (str FLOAT)", now; } try { *_pSession << "CREATE TABLE Strings (str FLOAT)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); }
@ -889,7 +903,7 @@ void ODBCMySQLTest::recreateFloatsTable()
void ODBCMySQLTest::recreateTuplesTable() void ODBCMySQLTest::recreateTuplesTable()
{ {
dropTable("Tuples"); dropObject("TABLE", "Tuples");
try { *_pSession << "CREATE TABLE Tuples " try { *_pSession << "CREATE TABLE Tuples "
"(i0 INTEGER, i1 INTEGER, i2 INTEGER, i3 INTEGER, i4 INTEGER, i5 INTEGER, i6 INTEGER, " "(i0 INTEGER, i1 INTEGER, i2 INTEGER, i3 INTEGER, i4 INTEGER, i5 INTEGER, i6 INTEGER, "
"i7 INTEGER, i8 INTEGER, i9 INTEGER, i10 INTEGER, i11 INTEGER, i12 INTEGER, i13 INTEGER," "i7 INTEGER, i8 INTEGER, i9 INTEGER, i10 INTEGER, i11 INTEGER, i12 INTEGER, i13 INTEGER,"
@ -901,7 +915,7 @@ void ODBCMySQLTest::recreateTuplesTable()
void ODBCMySQLTest::recreateVectorsTable() void ODBCMySQLTest::recreateVectorsTable()
{ {
dropTable("Vectors"); dropObject("TABLE", "Vectors");
try { *_pSession << "CREATE TABLE Vectors (i0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; } try { *_pSession << "CREATE TABLE Vectors (i0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); }
@ -959,9 +973,9 @@ void ODBCMySQLTest::setUp()
void ODBCMySQLTest::tearDown() void ODBCMySQLTest::tearDown()
{ {
dropTable("Person"); dropObject("TABLE", "Person");
dropTable("Strings"); dropObject("TABLE", "Strings");
dropTable("Tuples"); dropObject("TABLE", "Tuples");
} }
@ -1046,7 +1060,10 @@ CppUnit::Test* ODBCMySQLTest::suite()
CppUnit_addTest(pSuite, ODBCMySQLTest, testDouble); CppUnit_addTest(pSuite, ODBCMySQLTest, testDouble);
CppUnit_addTest(pSuite, ODBCMySQLTest, testTuple); CppUnit_addTest(pSuite, ODBCMySQLTest, testTuple);
CppUnit_addTest(pSuite, ODBCMySQLTest, testTupleVector); CppUnit_addTest(pSuite, ODBCMySQLTest, testTupleVector);
CppUnit_addTest(pSuite, ODBCMySQLTest, testStoredProcedure);
CppUnit_addTest(pSuite, ODBCMySQLTest, testStoredFunction);
CppUnit_addTest(pSuite, ODBCMySQLTest, testInternalExtraction); CppUnit_addTest(pSuite, ODBCMySQLTest, testInternalExtraction);
CppUnit_addTest(pSuite, ODBCMySQLTest, testInternalStorageType);
return pSuite; return pSuite;
} }

View File

@ -118,6 +118,10 @@ public:
void testTupleVector(); void testTupleVector();
void testInternalExtraction(); void testInternalExtraction();
void testInternalStorageType();
void testStoredProcedure();
void testStoredFunction();
void setUp(); void setUp();
void tearDown(); void tearDown();
@ -125,7 +129,7 @@ public:
static CppUnit::Test* suite(); static CppUnit::Test* suite();
private: private:
void dropTable(const std::string& tableName); void dropObject(const std::string& type, const std::string& name);
void recreatePersonTable(); void recreatePersonTable();
void recreatePersonBLOBTable(); void recreatePersonBLOBTable();
void recreateStringsTable(); void recreateStringsTable();

View File

@ -827,8 +827,30 @@ void ODBCOracleTest::testInternalExtraction()
} }
void ODBCOracleTest::testInternalStorageType()
{
if (!_pSession) fail ("Test not available.");
for (int i = 0; i < 8;)
{
recreateVectorsTable();
_pSession->setFeature("autoBind", bindValues[i]);
_pSession->setFeature("autoExtract", bindValues[i+1]);
_pExecutor->internalStorageType();
i += 2;
}
}
void ODBCOracleTest::testStoredProcedure() void ODBCOracleTest::testStoredProcedure()
{ {
if (!_pSession) fail ("Test not available.");
for (int k = 0; k < 8;)
{
_pSession->setFeature("autoBind", bindValues[k]);
_pSession->setFeature("autoExtract", bindValues[k+1]);
*_pSession << "CREATE OR REPLACE " *_pSession << "CREATE OR REPLACE "
"PROCEDURE storedProcedure(outParam OUT NUMBER) IS " "PROCEDURE storedProcedure(outParam OUT NUMBER) IS "
" BEGIN outParam := -1; " " BEGIN outParam := -1; "
@ -859,10 +881,17 @@ void ODBCOracleTest::testStoredProcedure()
*_pSession << "{call storedProcedure(?)}", io(i), now; *_pSession << "{call storedProcedure(?)}", io(i), now;
assert(4 == i); assert(4 == i);
*_pSession << "DROP PROCEDURE storedProcedure;", now; *_pSession << "DROP PROCEDURE storedProcedure;", now;
k += 2;
}
} }
void ODBCOracleTest::testStoredFunction() void ODBCOracleTest::testStoredFunction()
{
if (!_pSession) fail ("Test not available.");
for (int k = 0; k < 8;)
{ {
*_pSession << "CREATE OR REPLACE " *_pSession << "CREATE OR REPLACE "
"FUNCTION storedFunction RETURN NUMBER IS " "FUNCTION storedFunction RETURN NUMBER IS "
@ -921,6 +950,9 @@ void ODBCOracleTest::testStoredFunction()
assert(2 == params.get<0>()); assert(2 == params.get<0>());
assert(3 == result); assert(3 == result);
*_pSession << "DROP FUNCTION storedFunction;", now; *_pSession << "DROP FUNCTION storedFunction;", now;
k = k + 2;
}
} }
@ -1176,6 +1208,7 @@ CppUnit::Test* ODBCOracleTest::suite()
CppUnit_addTest(pSuite, ODBCOracleTest, testStoredProcedure); CppUnit_addTest(pSuite, ODBCOracleTest, testStoredProcedure);
CppUnit_addTest(pSuite, ODBCOracleTest, testStoredFunction); CppUnit_addTest(pSuite, ODBCOracleTest, testStoredFunction);
CppUnit_addTest(pSuite, ODBCOracleTest, testInternalExtraction); CppUnit_addTest(pSuite, ODBCOracleTest, testInternalExtraction);
CppUnit_addTest(pSuite, ODBCOracleTest, testInternalStorageType);
return pSuite; return pSuite;
} }

View File

@ -116,6 +116,8 @@ public:
void testTupleVector(); void testTupleVector();
void testInternalExtraction(); void testInternalExtraction();
void testInternalStorageType();
void testStoredProcedure(); void testStoredProcedure();
void testStoredFunction(); void testStoredFunction();

View File

@ -35,6 +35,7 @@
#include "CppUnit/TestSuite.h" #include "CppUnit/TestSuite.h"
#include "Poco/String.h" #include "Poco/String.h"
#include "Poco/Format.h" #include "Poco/Format.h"
#include "Poco/Tuple.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include "Poco/Data/Common.h" #include "Poco/Data/Common.h"
#include "Poco/Data/BLOB.h" #include "Poco/Data/BLOB.h"
@ -54,6 +55,7 @@ using Poco::Data::ODBC::ConnectionException;
using Poco::Data::ODBC::StatementException; using Poco::Data::ODBC::StatementException;
using Poco::Data::ODBC::StatementDiagnostics; using Poco::Data::ODBC::StatementDiagnostics;
using Poco::format; using Poco::format;
using Poco::Tuple;
using Poco::NotFoundException; using Poco::NotFoundException;
@ -811,6 +813,21 @@ void ODBCPostgreSQLTest::testInternalExtraction()
} }
void ODBCPostgreSQLTest::testInternalStorageType()
{
if (!_pSession) fail ("Test not available.");
for (int i = 0; i < 8;)
{
recreateVectorsTable();
_pSession->setFeature("autoBind", bindValues[i]);
_pSession->setFeature("autoExtract", bindValues[i+1]);
_pExecutor->internalStorageType();
i += 2;
}
}
void ODBCPostgreSQLTest::dropTable(const std::string& tableName) void ODBCPostgreSQLTest::dropTable(const std::string& tableName)
{ {
try try
@ -1068,6 +1085,7 @@ CppUnit::Test* ODBCPostgreSQLTest::suite()
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTuple); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTuple);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTupleVector); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTupleVector);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testInternalExtraction); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testInternalExtraction);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testInternalStorageType);
return pSuite; return pSuite;
} }

View File

@ -118,6 +118,7 @@ public:
void testTupleVector(); void testTupleVector();
void testInternalExtraction(); void testInternalExtraction();
void testInternalStorageType();
void setUp(); void setUp();
void tearDown(); void tearDown();

View File

@ -35,6 +35,7 @@
#include "CppUnit/TestSuite.h" #include "CppUnit/TestSuite.h"
#include "Poco/String.h" #include "Poco/String.h"
#include "Poco/Format.h" #include "Poco/Format.h"
#include "Poco/Tuple.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include "Poco/Data/Common.h" #include "Poco/Data/Common.h"
#include "Poco/Data/BLOB.h" #include "Poco/Data/BLOB.h"
@ -54,6 +55,7 @@ using Poco::Data::ODBC::ConnectionException;
using Poco::Data::ODBC::StatementException; using Poco::Data::ODBC::StatementException;
using Poco::Data::ODBC::StatementDiagnostics; using Poco::Data::ODBC::StatementDiagnostics;
using Poco::format; using Poco::format;
using Poco::Tuple;
using Poco::NotFoundException; using Poco::NotFoundException;
@ -829,11 +831,147 @@ void ODBCSQLServerTest::testInternalExtraction()
} }
void ODBCSQLServerTest::dropTable(const std::string& tableName) void ODBCSQLServerTest::testInternalStorageType()
{
if (!_pSession) fail ("Test not available.");
for (int i = 0; i < 8;)
{
recreateVectorsTable();
_pSession->setFeature("autoBind", bindValues[i]);
_pSession->setFeature("autoExtract", bindValues[i+1]);
_pExecutor->internalStorageType();
i += 2;
}
}
void ODBCSQLServerTest::testStoredProcedure()
{
dropObject("PROCEDURE", "storedProcedure");
*_pSession << "CREATE PROCEDURE storedProcedure "
"@outParam int = 0 OUTPUT "
"AS "
"SET @outParam = -1 "
, now;
int i = 0;
*_pSession << "{call storedProcedure(?)}", out(i), now;
assert(-1 == i);
dropObject("PROCEDURE", "storedProcedure");
*_pSession << "CREATE PROCEDURE storedProcedure "
"@inParam int, "
"@outParam int = 0 OUTPUT "
"AS "
"SET @outParam = @inParam*@inParam "
, now;
i = 2;
int j = 0;
/*not working */
try{
*_pSession << "{call storedProcedure(2, ?)}", out(j), now;
}catch(StatementException& ex)
{
std::cout << ex.toString();
}
//assert(4 == j);
dropObject("PROCEDURE", "storedProcedure");
*_pSession << "CREATE PROCEDURE storedProcedure "
"@ioParam int "
"AS "
"SET @ioParam = @ioParam*@ioParam "
, now;
i = 2;
/*not working*/
try{
*_pSession << "{call storedProcedure(?)}", io(i), now;
}catch(StatementException& ex)
{
std::cout << ex.toString();
}
//assert(4 == i);
dropObject("PROCEDURE", "storedProcedure");
}
void ODBCSQLServerTest::testStoredFunction()
{
dropObject("PROCEDURE", "storedFunction");
*_pSession << "CREATE PROCEDURE storedFunction "
"AS "
"DECLARE @retVal int "
"SET @retVal = -1 "
"RETURN @retVal"
, now;
int i = 0;
*_pSession << "{? = call storedFunction}", out(i), now;
assert(-1 == i);
dropObject("PROCEDURE", "storedFunction");
/*TODO
*_pSession << "CREATE OR REPLACE "
"FUNCTION storedFunction(inParam IN NUMBER) RETURN NUMBER IS "
" BEGIN RETURN(inParam*inParam); "
" END storedFunction;" , now;
i = 2;
int result = 0;
*_pSession << "{? = call storedFunction(?)}", out(result), in(i), now;
assert(4 == result);
*_pSession << "DROP FUNCTION storedFunction;", now;
*_pSession << "CREATE OR REPLACE "
"FUNCTION storedFunction(inParam IN NUMBER, outParam OUT NUMBER) RETURN NUMBER IS "
" BEGIN outParam := inParam*inParam; RETURN(outParam); "
" END storedFunction;" , now;
i = 2;
int j = 0;
result = 0;
*_pSession << "{? = call storedFunction(?, ?)}", out(result), in(i), out(j), now;
assert(4 == j);
assert(j == result);
*_pSession << "DROP FUNCTION storedFunction;", now;
*_pSession << "CREATE OR REPLACE "
"FUNCTION storedFunction(param1 IN OUT NUMBER, param2 IN OUT NUMBER) RETURN NUMBER IS "
" temp NUMBER := param1; "
" BEGIN param1 := param2; param2 := temp; RETURN(param1+param2); "
" END storedFunction;" , now;
i = 1;
j = 2;
result = 0;
*_pSession << "{? = call storedFunction(?, ?)}", out(result), io(i), io(j), now;
assert(1 == j);
assert(2 == i);
assert(3 == result);
Tuple<int, int> params(1, 2);
assert(1 == params.get<0>());
assert(2 == params.get<1>());
result = 0;
*_pSession << "{? = call storedFunction(?, ?)}", out(result), io(params), now;
assert(1 == params.get<1>());
assert(2 == params.get<0>());
assert(3 == result);
*_pSession << "DROP FUNCTION storedFunction;", now;
*/
}
void ODBCSQLServerTest::dropObject(const std::string& type, const std::string& name)
{ {
try try
{ {
*_pSession << format("DROP TABLE %s", tableName), now; *_pSession << format("DROP %s %s", type, name), now;
} }
catch (StatementException& ex) catch (StatementException& ex)
{ {
@ -856,7 +994,7 @@ void ODBCSQLServerTest::dropTable(const std::string& tableName)
void ODBCSQLServerTest::recreatePersonTable() void ODBCSQLServerTest::recreatePersonTable()
{ {
dropTable("Person"); dropObject("TABLE", "Person");
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; } try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); }
@ -865,7 +1003,7 @@ void ODBCSQLServerTest::recreatePersonTable()
void ODBCSQLServerTest::recreatePersonBLOBTable() void ODBCSQLServerTest::recreatePersonBLOBTable()
{ {
dropTable("Person"); dropObject("TABLE", "Person");
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image VARBINARY(MAX))", now; } try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image VARBINARY(MAX))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
@ -874,7 +1012,7 @@ void ODBCSQLServerTest::recreatePersonBLOBTable()
void ODBCSQLServerTest::recreateIntsTable() void ODBCSQLServerTest::recreateIntsTable()
{ {
dropTable("Strings"); dropObject("TABLE", "Strings");
try { *_pSession << "CREATE TABLE Strings (str INTEGER)", now; } try { *_pSession << "CREATE TABLE Strings (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()"); }
@ -883,7 +1021,7 @@ void ODBCSQLServerTest::recreateIntsTable()
void ODBCSQLServerTest::recreateStringsTable() void ODBCSQLServerTest::recreateStringsTable()
{ {
dropTable("Strings"); dropObject("TABLE", "Strings");
try { *_pSession << "CREATE TABLE Strings (str VARCHAR(30))", now; } try { *_pSession << "CREATE TABLE Strings (str VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); }
@ -892,7 +1030,7 @@ void ODBCSQLServerTest::recreateStringsTable()
void ODBCSQLServerTest::recreateFloatsTable() void ODBCSQLServerTest::recreateFloatsTable()
{ {
dropTable("Strings"); dropObject("TABLE", "Strings");
try { *_pSession << "CREATE TABLE Strings (str FLOAT)", now; } try { *_pSession << "CREATE TABLE Strings (str FLOAT)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); }
@ -901,7 +1039,7 @@ void ODBCSQLServerTest::recreateFloatsTable()
void ODBCSQLServerTest::recreateTuplesTable() void ODBCSQLServerTest::recreateTuplesTable()
{ {
dropTable("Tuples"); dropObject("TABLE", "Tuples");
try { *_pSession << "CREATE TABLE Tuples " try { *_pSession << "CREATE TABLE Tuples "
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, " "(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
"int7 INTEGER, int8 INTEGER, int9 INTEGER, int10 INTEGER, int11 INTEGER, int12 INTEGER, int13 INTEGER," "int7 INTEGER, int8 INTEGER, int9 INTEGER, int10 INTEGER, int11 INTEGER, int12 INTEGER, int13 INTEGER,"
@ -913,7 +1051,7 @@ void ODBCSQLServerTest::recreateTuplesTable()
void ODBCSQLServerTest::recreateVectorTable() void ODBCSQLServerTest::recreateVectorTable()
{ {
dropTable("Vector"); dropObject("TABLE", "Vector");
try { *_pSession << "CREATE TABLE Vector (i0 INTEGER)", now; } try { *_pSession << "CREATE TABLE Vector (i0 INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorTable()"); }
@ -922,7 +1060,7 @@ void ODBCSQLServerTest::recreateVectorTable()
void ODBCSQLServerTest::recreateVectorsTable() void ODBCSQLServerTest::recreateVectorsTable()
{ {
dropTable("Vectors"); dropObject("TABLE", "Vectors");
try { *_pSession << "CREATE TABLE Vectors (int0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; } try { *_pSession << "CREATE TABLE Vectors (int0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); }
@ -981,9 +1119,9 @@ void ODBCSQLServerTest::setUp()
void ODBCSQLServerTest::tearDown() void ODBCSQLServerTest::tearDown()
{ {
dropTable("Person"); dropObject("TABLE", "Person");
dropTable("Strings"); dropObject("TABLE", "Strings");
dropTable("Tuples"); dropObject("TABLE", "Tuples");
} }
@ -1068,7 +1206,10 @@ CppUnit::Test* ODBCSQLServerTest::suite()
CppUnit_addTest(pSuite, ODBCSQLServerTest, testDouble); CppUnit_addTest(pSuite, ODBCSQLServerTest, testDouble);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTuple); CppUnit_addTest(pSuite, ODBCSQLServerTest, testTuple);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTupleVector); CppUnit_addTest(pSuite, ODBCSQLServerTest, testTupleVector);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testStoredProcedure);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testStoredFunction);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testInternalExtraction); CppUnit_addTest(pSuite, ODBCSQLServerTest, testInternalExtraction);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testInternalStorageType);
return pSuite; return pSuite;
} }

View File

@ -117,7 +117,11 @@ public:
void testTuple(); void testTuple();
void testTupleVector(); void testTupleVector();
void testStoredProcedure();
void testStoredFunction();
void testInternalExtraction(); void testInternalExtraction();
void testInternalStorageType();
void setUp(); void setUp();
void tearDown(); void tearDown();
@ -125,7 +129,7 @@ public:
static CppUnit::Test* suite(); static CppUnit::Test* suite();
private: private:
void dropTable(const std::string& tableName); void dropObject(const std::string& type, const std::string& name);
void recreatePersonTable(); void recreatePersonTable();
void recreatePersonBLOBTable(); void recreatePersonBLOBTable();
void recreateStringsTable(); void recreateStringsTable();

View File

@ -807,6 +807,21 @@ void ODBCSQLiteTest::testInternalExtraction()
} }
void ODBCSQLiteTest::testInternalStorageType()
{
if (!_pSession) fail ("Test not available.");
for (int i = 0; i < 8;)
{
recreateVectorsTable();
_pSession->setFeature("autoBind", bindValues[i]);
_pSession->setFeature("autoExtract", bindValues[i+1]);
_pExecutor->internalStorageType();
i += 2;
}
}
void ODBCSQLiteTest::dropTable(const std::string& tableName) void ODBCSQLiteTest::dropTable(const std::string& tableName)
{ {
try try
@ -1029,6 +1044,7 @@ CppUnit::Test* ODBCSQLiteTest::suite()
CppUnit_addTest(pSuite, ODBCSQLiteTest, testTuple); CppUnit_addTest(pSuite, ODBCSQLiteTest, testTuple);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testTupleVector); CppUnit_addTest(pSuite, ODBCSQLiteTest, testTupleVector);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testInternalExtraction); CppUnit_addTest(pSuite, ODBCSQLiteTest, testInternalExtraction);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testInternalStorageType);
return pSuite; return pSuite;
} }

View File

@ -115,6 +115,7 @@ public:
void testTupleVector(); void testTupleVector();
void testInternalExtraction(); void testInternalExtraction();
void testInternalStorageType();
void setUp(); void setUp();
void tearDown(); void tearDown();

View File

@ -1836,7 +1836,7 @@ void SQLExecutor::internalExtraction()
i = rset.value("str0", 2); i = rset.value("str0", 2);
assert (5 == i); assert (5 == i);
const Column<int>& col = rset.column<int>(0); const Column<int>& col = rset.column<int, std::vector<int> >(0);
Column<int>::Iterator it = col.begin(); Column<int>::Iterator it = col.begin();
Column<int>::Iterator end = col.end(); Column<int>::Iterator end = col.end();
for (int i = 1; it != end; ++it, ++i) for (int i = 1; it != end; ++it, ++i)
@ -1870,7 +1870,7 @@ void SQLExecutor::internalExtraction()
s = rset.value("cnt", 0).convert<std::string>(); s = rset.value("cnt", 0).convert<std::string>();
assert ("4" == s); assert ("4" == s);
try { rset.column<int>(100); fail ("must fail"); } try { rset.column<int, std::vector<int> >(100); fail ("must fail"); }
catch (RangeException&) { } catch (RangeException&) { }
try { rset.value<std::string>(0,0); fail ("must fail"); } try { rset.value<std::string>(0,0); fail ("must fail"); }
@ -1879,9 +1879,79 @@ void SQLExecutor::internalExtraction()
stmt = (*_pSession << "DELETE FROM Vectors", now); stmt = (*_pSession << "DELETE FROM Vectors", now);
rset = stmt; rset = stmt;
try { rset.column<int>(0); fail ("must fail"); } try { rset.column<int, std::vector<int> >(0); fail ("must fail"); }
catch (RangeException&) { } catch (RangeException&) { }
} }
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); }
} }
void SQLExecutor::internalStorageType()
{
std::string funct = "internalStorageType()";
std::vector<Statement::Manipulator> manips;
manips.push_back(list);
manips.push_back(deque);
manips.push_back(vector);
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 { *_pSession << "INSERT INTO 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
{
std::vector<Statement::Manipulator>::iterator it = manips.begin();
std::vector<Statement::Manipulator>::iterator end = manips.end();
for (; it != end; ++it)
{
Statement stmt = (*_pSession << "SELECT * FROM Vectors", *it, 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");
try
{
stmt = (*_pSession << "SELECT * FROM Vectors", now, *it);
fail ("must fail");
}
catch(InvalidAccessException&){}
try
{
stmt = (*_pSession << "SELECT * FROM Vectors", into(v), now, *it);
fail ("must fail");
}
catch(InvalidAccessException&){}
try
{
stmt = (*_pSession << "SELECT * FROM Vectors", into(v), *it, now);
fail ("must fail");
}
catch(InvalidAccessException&){}
}
}
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
}

View File

@ -126,6 +126,7 @@ public:
void tupleVector(); void tupleVector();
void internalExtraction(); void internalExtraction();
void internalStorageType();
private: private:
Poco::Data::Session* _pSession; Poco::Data::Session* _pSession;

View File

@ -74,7 +74,19 @@ public:
AbstractSessionImpl() AbstractSessionImpl()
/// Creates the AbstractSessionImpl. /// Creates the AbstractSessionImpl.
/// Adds "storage" property and sets the default internal storage container
/// type to std::vector.
/// The storage is created by statements automatically whenever a query
/// returning results is executed but external storage is provided by the user.
/// Storage type can be reconfigured at runtime both globally (for the
/// duration of the session) and locally (for a single statement execution only).
/// See StatementImpl for details on how this property is used at runtime.
{ {
addProperty("storage",
&AbstractSessionImpl<C>::setStorage,
&AbstractSessionImpl<C>::getStorage);
setProperty("storage", std::string("vector"));
} }
~AbstractSessionImpl() ~AbstractSessionImpl()
@ -142,6 +154,24 @@ public:
else throw NotSupportedException(name); else throw NotSupportedException(name);
} }
void setStorage(const std::string& value)
/// Sets the storage type.
{
_storage = value;
}
void setStorage(const std::string& name, const Poco::Any& value)
/// Sets the storage type.
{
_storage = Poco::RefAnyCast<std::string>(value);
}
Poco::Any getStorage(const std::string& name="")
/// Returns the storage type
{
return _storage;
}
protected: protected:
void addFeature(const std::string& name, FeatureSetter setter, FeatureGetter getter) void addFeature(const std::string& name, FeatureSetter setter, FeatureGetter getter)
/// Adds a feature to the map of supported features. /// Adds a feature to the map of supported features.
@ -185,6 +215,7 @@ private:
FeatureMap _features; FeatureMap _features;
PropertyMap _properties; PropertyMap _properties;
std::string _storage;
}; };

View File

@ -44,13 +44,14 @@
#include "Poco/Data/MetaColumn.h" #include "Poco/Data/MetaColumn.h"
#include "Poco/SharedPtr.h" #include "Poco/SharedPtr.h"
#include <vector> #include <vector>
#include <list>
namespace Poco { namespace Poco {
namespace Data { namespace Data {
template <class T> template <class T, class C = std::vector<T> >
class Column class Column
/// Column class is column data container. /// Column class is column data container.
/// Data (a pointer to vector of contained values) is assigned to the class /// Data (a pointer to vector of contained values) is assigned to the class
@ -59,11 +60,11 @@ class Column
/// This class owns the data assigned to it and deletes the storage on destruction. /// This class owns the data assigned to it and deletes the storage on destruction.
{ {
public: public:
typedef std::vector<T> DataVec; typedef C Container;
typedef typename DataVec::const_iterator Iterator; typedef typename Container::const_iterator Iterator;
typedef typename DataVec::size_type Size; typedef typename Container::size_type Size;
Column(const MetaColumn& metaColumn, std::vector<T>* pData): _metaColumn(metaColumn), _pData(pData) Column(const MetaColumn& metaColumn, C* pData): _metaColumn(metaColumn), _pData(pData)
/// Creates the Column. /// Creates the Column.
{ {
poco_check_ptr (_pData); poco_check_ptr (_pData);
@ -94,7 +95,7 @@ public:
std::swap(_pData, other._pData); std::swap(_pData, other._pData);
} }
DataVec& data() Container& data()
/// Returns reference to contained data. /// Returns reference to contained data.
{ {
return *_pData; return *_pData;
@ -128,7 +129,7 @@ public:
void reset() void reset()
/// Clears and shrinks the storage. /// Clears and shrinks the storage.
{ {
std::vector<T>().swap(*_pData); C().swap(*_pData);
} }
const std::string& name() const const std::string& name() const
@ -178,7 +179,133 @@ private:
Column(); Column();
MetaColumn _metaColumn; MetaColumn _metaColumn;
Poco::SharedPtr<DataVec> _pData; Poco::SharedPtr<Container> _pData;
};
template <class T>
class Column<T, std::list<T> >
/// Column specialization for std::list
{
public:
typedef std::list<T> List;
typedef typename List::const_iterator Iterator;
typedef typename List::size_type Size;
Column(const MetaColumn& metaColumn, std::list<T>* pData): _metaColumn(metaColumn), _pData(pData)
/// Creates the Column.
{
poco_check_ptr (_pData);
}
Column(const Column& col): _metaColumn(col._metaColumn), _pData(col._pData)
/// Creates the Column.
{
}
~Column()
/// Destroys the Column.
{
}
Column& operator = (const Column& col)
/// Assignment operator.
{
Column tmp(col);
swap(tmp);
return *this;
}
void swap(Column& other)
/// Swaps the column with another one.
{
std::swap(_metaColumn, other._metaColumn);
std::swap(_pData, other._pData);
}
List& data()
/// Returns reference to contained data.
{
return *_pData;
}
const T& value(std::size_t row) const
/// Returns the field value in specified row.
{
List::const_iterator it = _pData->begin();
List::const_iterator end = _pData->end();
for (int i = 0; it != end; ++it, ++i)
if (i == row) return *it;
throw RangeException("Invalid row number.");
}
const T& operator [] (std::size_t row) const
/// Returns the field value in specified row.
{
return value(row);
}
Size rowCount() const
/// Returns number of rows.
{
return _pData->size();
}
void reset()
/// Clears the storage.
{
_pData->clear();
}
const std::string& name() const
/// Returns column name.
{
return _metaColumn.name();
}
std::size_t length() const
/// Returns column maximum length.
{
return _metaColumn.length();
}
std::size_t precision() const
/// Returns column precision.
/// Valid for floating point fields only (zero for other data types).
{
return _metaColumn.precision();
}
std::size_t position() const
/// Returns column position.
{
return _metaColumn.position();
}
MetaColumn::ColumnDataType type() const
/// Returns column type.
{
return _metaColumn.type();
}
Iterator begin() const
/// Returns iterator pointing to the beginning of data storage vector.
{
return _pData->begin();
}
Iterator end() const
/// Returns iterator pointing to the end of data storage vector.
{
return _pData->end();
}
private:
Column();
MetaColumn _metaColumn;
Poco::SharedPtr<List> _pData;
}; };

View File

@ -310,7 +310,7 @@ class InternalExtraction: public Extraction<C>
/// InternalExtraction objects can not be copied or assigned. /// InternalExtraction objects can not be copied or assigned.
{ {
public: public:
explicit InternalExtraction(C& result, Column<T>* pColumn): explicit InternalExtraction(C& result, Column<T,C>* pColumn):
Extraction<C>(result), Extraction<C>(result),
_pColumn(pColumn) _pColumn(pColumn)
/// Creates InternalExtraction. /// Creates InternalExtraction.
@ -341,7 +341,7 @@ public:
} }
} }
const Column<T>& column() const const Column<T,C>& column() const
{ {
return *_pColumn; return *_pColumn;
} }
@ -351,7 +351,7 @@ private:
InternalExtraction(const InternalExtraction&); InternalExtraction(const InternalExtraction&);
InternalExtraction& operator = (const InternalExtraction&); InternalExtraction& operator = (const InternalExtraction&);
Column<T>* _pColumn; Column<T,C>* _pColumn;
}; };

View File

@ -88,18 +88,18 @@ public:
std::size_t columnCount() const; std::size_t columnCount() const;
/// Returns the number of rows in the recordset. /// Returns the number of rows in the recordset.
template<class T> template<class T, class C>
const Column<T>& column(const std::string& name) const const Column<T,C>& column(const std::string& name) const
/// Returns the reference to the first Column with the specified name. /// Returns the reference to the first Column with the specified name.
{ {
return column<T>(columnPosition<T>(name)); return column<T,C>(columnPosition<T,C>(name));
} }
template<class T> template<class T, class C>
const Column<T>& column(std::size_t pos) const const Column<T,C>& column(std::size_t pos) const
/// Returns the reference to column at specified location. /// Returns the reference to column at specified location.
{ {
typedef const InternalExtraction<T>* ExtractionVecPtr; typedef const InternalExtraction<T,C>* ExtractionVecPtr;
const AbstractExtractionVec& rExtractions = extractions(); const AbstractExtractionVec& rExtractions = extractions();
@ -125,14 +125,36 @@ public:
const T& value(std::size_t col, std::size_t row) const const T& value(std::size_t col, std::size_t row) const
/// Returns the reference to data value at [col, row] location. /// Returns the reference to data value at [col, row] location.
{ {
return column<T>(col).value(row); switch (storage())
{
case STORAGE_VECTOR:
case STORAGE_UNKNOWN:
return column<T, std::vector<T> >(col).value(row);
case STORAGE_LIST:
return column<T, std::list<T> >(col).value(row);
case STORAGE_DEQUE:
return column<T, std::deque<T> >(col).value(row);
default:
throw IllegalStateException("Invalid storage setting.");
}
} }
template<class T> template<class T>
const T& value(const std::string& name, std::size_t row) const const T& value(const std::string& name, std::size_t row) const
/// Returns the reference to data value at named column, row location. /// Returns the reference to data value at named column, row location.
{ {
return column<T>(name).value(row); switch (storage())
{
case STORAGE_VECTOR:
case STORAGE_UNKNOWN:
return column<T, std::vector<T> >(name).value(row);
case STORAGE_LIST:
return column<T, std::list<T> >(name).value(row);
case STORAGE_DEQUE:
return column<T, std::deque<T> >(name).value(row);
default:
throw IllegalStateException("Invalid storage setting.");
}
} }
DynamicAny value(std::size_t col, std::size_t row) const; DynamicAny value(std::size_t col, std::size_t row) const;
@ -204,11 +226,11 @@ public:
private: private:
RecordSet(); RecordSet();
template<class T> template<class T, class C>
std::size_t columnPosition(const std::string& name) const std::size_t columnPosition(const std::string& name) const
/// Returns the position of the column with specified name. /// Returns the position of the column with specified name.
{ {
typedef const InternalExtraction<T>* ExtractionVecPtr; typedef const InternalExtraction<T,C>* ExtractionVecPtr;
const AbstractExtractionVec& rExtractions = extractions(); const AbstractExtractionVec& rExtractions = extractions();
AbstractExtractionVec::const_iterator it = rExtractions.begin(); AbstractExtractionVec::const_iterator it = rExtractions.begin();
@ -220,7 +242,7 @@ private:
if (pExtraction) if (pExtraction)
{ {
const Column<T>& col = pExtraction->column(); const Column<T,C>& col = pExtraction->column();
if (0 == Poco::icompare(name, col.name())) if (0 == Poco::icompare(name, col.name()))
return col.position(); return col.position();
} }

View File

@ -64,6 +64,14 @@ class Data_API Statement
public: public:
typedef void (*Manipulator)(Statement&); typedef void (*Manipulator)(Statement&);
enum Storage
{
STORAGE_VECTOR = StatementImpl::STORAGE_VECTOR_IMPL,
STORAGE_LIST = StatementImpl::STORAGE_LIST_IMPL,
STORAGE_DEQUE = StatementImpl::STORAGE_DEQUE_IMPL,
STORAGE_UNKNOWN = StatementImpl::STORAGE_UNKNOWN_IMPL
};
Statement(StatementImpl* pImpl); Statement(StatementImpl* pImpl);
/// Creates the Statement. /// Creates the Statement.
@ -134,6 +142,22 @@ public:
Statement& reset(Session& session); Statement& reset(Session& session);
/// Resets the Statement so that it can be filled with a new SQL command. /// Resets the Statement so that it can be filled with a new SQL command.
bool canModifyStorage();
/// Returns true if statement is in a state that allows the internal storage to be modified.
Storage storage() const;
/// Returns the internal storage type for the stamement.
void setStorage(const std::string& storage);
/// Sets the internal storage type for the stamement.
const std::string& getStorage() const;
/// Returns the internal storage type for the stamement.
std::size_t extractionCount() const;
/// Returns the number of extraction storage buffers associated
/// with the statement.
protected: protected:
const AbstractExtractionVec& extractions() const; const AbstractExtractionVec& extractions() const;
/// Returns the extractions vector. /// Returns the extractions vector.
@ -157,6 +181,12 @@ private:
// //
void Data_API now(Statement& statement); void Data_API now(Statement& statement);
void Data_API vector(Statement& statement);
void Data_API list(Statement& statement);
void Data_API deque(Statement& statement);
// //
// inlines // inlines
@ -221,6 +251,24 @@ inline const MetaColumn& Statement::metaColumn(const std::string& name) const
} }
inline void Statement::setStorage(const std::string& storage)
{
_ptr->setStorage(storage);
}
inline std::size_t Statement::extractionCount() const
{
return _ptr->extractionCount();
}
inline Statement::Storage Statement::storage() const
{
return static_cast<Storage>(_ptr->getStorage());
}
} } // namespace Poco::Data } } // namespace Poco::Data

View File

@ -59,6 +59,9 @@ namespace Poco {
namespace Data { namespace Data {
class SessionImpl;
class Data_API StatementImpl: public Poco::RefCountedObject class Data_API StatementImpl: public Poco::RefCountedObject
/// StatementImpl interface that subclasses must implement to define database dependent query execution. /// StatementImpl interface that subclasses must implement to define database dependent query execution.
/// ///
@ -74,7 +77,20 @@ public:
ST_RESET ST_RESET
}; };
StatementImpl(); enum Storage
{
STORAGE_VECTOR_IMPL,
STORAGE_LIST_IMPL,
STORAGE_DEQUE_IMPL,
STORAGE_UNKNOWN_IMPL
};
static const std::string VECTOR;
static const std::string LIST;
static const std::string DEQUE;
static const std::string UNKNOWN;
StatementImpl(SessionImpl& rSession);
/// Creates the StatementImpl. /// Creates the StatementImpl.
virtual ~StatementImpl(); virtual ~StatementImpl();
@ -107,6 +123,19 @@ public:
State getState() const; State getState() const;
/// Returns the state of the Statement. /// Returns the state of the Statement.
void setStorage(Storage storage);
/// Sets the storage type for this statement;
void setStorage(const std::string& storage);
/// Sets the storage type for this statement;
Storage getStorage() const;
/// Returns the storage type for this statement.
std::size_t extractionCount() const;
/// Returns the number of extraction storage buffers associated
/// with the statement.
protected: protected:
virtual Poco::UInt32 columnsReturned() const = 0; virtual Poco::UInt32 columnsReturned() const = 0;
/// Returns number of columns returned by query. /// Returns number of columns returned by query.
@ -161,8 +190,29 @@ protected:
/// Returns the extractions vector. /// Returns the extractions vector.
void makeExtractors(Poco::UInt32 count); void makeExtractors(Poco::UInt32 count);
/// Creates extraction vector. Used in case when there is /// Determines the type of the internal extraction container and
/// data returned, but no extraction supplied externally. /// calls the extraction creation function (addInternalExtract)
/// with appropriate data type and container type arguments.
///
/// This function is only called in cases when there is data
/// returned by query, but no data storage supplied by user.
///
/// The type of the internal container is determined in the
/// following order:
/// 1. If statement has the container type set, the type is used.
/// 2. If statement does not have the container type set,
/// session is queried for container type setting. If the
/// session container type setting is found, it is used.
/// 3. If neither session nor statement have the internal
/// container type set, std::vector is used.
///
/// Supported internal extraction container types are:
/// - std::vector (default)
/// - std::deque
/// - std::list
SessionImpl& session();
/// Rteurns session associated with this statement.
private: private:
void compile(); void compile();
@ -193,9 +243,9 @@ private:
void addInternalExtract(const MetaColumn& mc) void addInternalExtract(const MetaColumn& mc)
/// Utility function to create and add an internal extraction. /// Utility function to create and add an internal extraction.
{ {
std::vector<T>* pData = new C; C* pData = new C;
Column<T>* pCol = new Column<T>(mc, pData); Column<T,C>* pCol = new Column<T,C>(mc, pData);
addExtract(new InternalExtraction<T>(*pData, pCol)); addExtract(new InternalExtraction<T,C>(*pData, pCol));
} }
StatementImpl(const StatementImpl& stmt); StatementImpl(const StatementImpl& stmt);
@ -208,6 +258,8 @@ private:
std::ostringstream _ostr; std::ostringstream _ostr;
AbstractBindingVec _bindings; AbstractBindingVec _bindings;
AbstractExtractionVec _extractors; AbstractExtractionVec _extractors;
SessionImpl& _rSession;
Storage _storage;
friend class Statement; friend class Statement;
}; };
@ -270,6 +322,30 @@ inline StatementImpl::State StatementImpl::getState() const
} }
inline SessionImpl& StatementImpl::session()
{
return _rSession;
}
inline void StatementImpl::setStorage(Storage storage)
{
_storage = storage;
}
inline StatementImpl::Storage StatementImpl::getStorage() const
{
return _storage;
}
inline std::size_t StatementImpl::extractionCount() const
{
return extractions().size();
}
} } // namespace Poco::Data } } // namespace Poco::Data

View File

@ -106,6 +106,14 @@ bool Statement::done()
} }
bool Statement::canModifyStorage()
{
return 0 == extractionCount() &&
(_ptr->getState() == StatementImpl::ST_INITIALIZED ||
_ptr->getState() == StatementImpl::ST_RESET);
}
Statement& Statement::reset(Session& session) Statement& Statement::reset(Session& session)
{ {
Statement stmt(session.createStatementImpl()); Statement stmt(session.createStatementImpl());
@ -114,10 +122,55 @@ Statement& Statement::reset(Session& session)
} }
const std::string& Statement::getStorage() const
{
switch (storage())
{
case STORAGE_VECTOR:
return StatementImpl::VECTOR;
case STORAGE_LIST:
return StatementImpl::LIST;
case STORAGE_DEQUE:
return StatementImpl::DEQUE;
case STORAGE_UNKNOWN:
return StatementImpl::UNKNOWN;
}
throw IllegalStateException("Invalid storage setting.");
}
void now(Statement& statement) void now(Statement& statement)
{ {
statement.execute(); statement.execute();
} }
void vector(Statement& statement)
{
if (!statement.canModifyStorage())
throw InvalidAccessException("Storage not modifiable.");
statement.setStorage("vector");
}
void list(Statement& statement)
{
if (!statement.canModifyStorage())
throw InvalidAccessException("Storage not modifiable.");
statement.setStorage("list");
}
void deque(Statement& statement)
{
if (!statement.canModifyStorage())
throw InvalidAccessException("Storage not modifiable.");
statement.setStorage("deque");
}
} } // namespace Poco::Data } } // namespace Poco::Data

View File

@ -35,6 +35,7 @@
#include "Poco/Data/StatementImpl.h" #include "Poco/Data/StatementImpl.h"
#include "Poco/Data/SessionImpl.h"
#include "Poco/Data/DataException.h" #include "Poco/Data/DataException.h"
#include "Poco/Data/AbstractBinder.h" #include "Poco/Data/AbstractBinder.h"
#include "Poco/Data/Extraction.h" #include "Poco/Data/Extraction.h"
@ -44,15 +45,26 @@
#include "Poco/Exception.h" #include "Poco/Exception.h"
using Poco::icompare;
namespace Poco { namespace Poco {
namespace Data { namespace Data {
StatementImpl::StatementImpl(): const std::string StatementImpl::VECTOR = "vector";
const std::string StatementImpl::LIST = "list";
const std::string StatementImpl::DEQUE = "deque";
const std::string StatementImpl::UNKNOWN = "unknown";
StatementImpl::StatementImpl(SessionImpl& rSession):
_state(ST_INITIALIZED), _state(ST_INITIALIZED),
_extrLimit(upperLimit((Poco::UInt32) Limit::LIMIT_UNLIMITED, false)), _extrLimit(upperLimit((Poco::UInt32) Limit::LIMIT_UNLIMITED, false)),
_lowerLimit(0), _lowerLimit(0),
_columnsExtracted(0), _columnsExtracted(0),
_rSession(rSession),
_storage(STORAGE_UNKNOWN_IMPL),
_ostr(), _ostr(),
_bindings() _bindings()
{ {
@ -254,8 +266,37 @@ void StatementImpl::resetExtraction()
} }
void StatementImpl::setStorage(const std::string& storage)
{
if (0 == icompare(VECTOR, storage))
_storage = STORAGE_VECTOR_IMPL;
else if (0 == icompare(LIST, storage))
_storage = STORAGE_LIST_IMPL;
else if (0 == icompare(DEQUE, storage))
_storage = STORAGE_DEQUE_IMPL;
else if (0 == icompare(UNKNOWN, storage))
_storage = STORAGE_UNKNOWN_IMPL;
else
throw NotFoundException();
}
void StatementImpl::makeExtractors(Poco::UInt32 count) void StatementImpl::makeExtractors(Poco::UInt32 count)
{ {
std::string storage;
switch (_storage)
{
case STORAGE_VECTOR_IMPL: storage = VECTOR; break;
case STORAGE_LIST_IMPL: storage = LIST; break;
case STORAGE_DEQUE_IMPL: storage = DEQUE; break;
case STORAGE_UNKNOWN_IMPL:
storage = AnyCast<std::string>(session().getProperty("storage"));
break;
}
if ("" == storage) storage = VECTOR;
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
{ {
const MetaColumn& mc = metaColumn(i); const MetaColumn& mc = metaColumn(i);
@ -263,40 +304,100 @@ void StatementImpl::makeExtractors(Poco::UInt32 count)
{ {
case MetaColumn::FDT_BOOL: case MetaColumn::FDT_BOOL:
case MetaColumn::FDT_INT8: case MetaColumn::FDT_INT8:
if (0 == icompare(VECTOR, storage))
addInternalExtract<Int8, std::vector<Int8> >(mc); addInternalExtract<Int8, std::vector<Int8> >(mc);
else if (0 == icompare(LIST, storage))
addInternalExtract<Int8, std::list<Int8> >(mc);
else if (0 == icompare(DEQUE, storage))
addInternalExtract<Int8, std::deque<Int8> >(mc);
break; break;
case MetaColumn::FDT_UINT8: case MetaColumn::FDT_UINT8:
if (0 == icompare(VECTOR, storage))
addInternalExtract<UInt8, std::vector<UInt8> >(mc); addInternalExtract<UInt8, std::vector<UInt8> >(mc);
else if (0 == icompare(LIST, storage))
addInternalExtract<UInt8, std::list<UInt8> >(mc);
else if (0 == icompare(DEQUE, storage))
addInternalExtract<UInt8, std::deque<UInt8> >(mc);
break; break;
case MetaColumn::FDT_INT16: case MetaColumn::FDT_INT16:
if (0 == icompare(VECTOR, storage))
addInternalExtract<Int16, std::vector<Int16> >(mc); addInternalExtract<Int16, std::vector<Int16> >(mc);
else if (0 == icompare(LIST, storage))
addInternalExtract<Int16, std::list<Int16> >(mc);
else if (0 == icompare(DEQUE, storage))
addInternalExtract<Int16, std::deque<Int16> >(mc);
break; break;
case MetaColumn::FDT_UINT16: case MetaColumn::FDT_UINT16:
if (0 == icompare(VECTOR, storage))
addInternalExtract<UInt16, std::vector<UInt16> >(mc); addInternalExtract<UInt16, std::vector<UInt16> >(mc);
else if (0 == icompare(LIST, storage))
addInternalExtract<UInt16, std::list<UInt16> >(mc);
else if (0 == icompare(DEQUE, storage))
addInternalExtract<UInt16, std::deque<UInt16> >(mc);
break; break;
case MetaColumn::FDT_INT32: case MetaColumn::FDT_INT32:
if (0 == icompare(VECTOR, storage))
addInternalExtract<Int32, std::vector<Int32> >(mc); addInternalExtract<Int32, std::vector<Int32> >(mc);
else if (0 == icompare(LIST, storage))
addInternalExtract<Int32, std::list<Int32> >(mc);
else if (0 == icompare(DEQUE, storage))
addInternalExtract<Int32, std::deque<Int32> >(mc);
break; break;
case MetaColumn::FDT_UINT32: case MetaColumn::FDT_UINT32:
if (0 == icompare(VECTOR, storage))
addInternalExtract<UInt32, std::vector<UInt32> >(mc); addInternalExtract<UInt32, std::vector<UInt32> >(mc);
else if (0 == icompare(LIST, storage))
addInternalExtract<UInt32, std::list<UInt32> >(mc);
else if (0 == icompare(DEQUE, storage))
addInternalExtract<UInt32, std::deque<UInt32> >(mc);
break; break;
case MetaColumn::FDT_INT64: case MetaColumn::FDT_INT64:
if (0 == icompare(VECTOR, storage))
addInternalExtract<Int64, std::vector<Int64> >(mc); addInternalExtract<Int64, std::vector<Int64> >(mc);
else if (0 == icompare(LIST, storage))
addInternalExtract<Int64, std::list<Int64> >(mc);
else if (0 == icompare(DEQUE, storage))
addInternalExtract<Int64, std::deque<Int64> >(mc);
break; break;
case MetaColumn::FDT_UINT64: case MetaColumn::FDT_UINT64:
if (0 == icompare(VECTOR, storage))
addInternalExtract<UInt64, std::vector<UInt64> >(mc); addInternalExtract<UInt64, std::vector<UInt64> >(mc);
else if (0 == icompare(LIST, storage))
addInternalExtract<UInt64, std::list<UInt64> >(mc);
else if (0 == icompare(DEQUE, storage))
addInternalExtract<UInt64, std::deque<UInt64> >(mc);
break; break;
case MetaColumn::FDT_FLOAT: case MetaColumn::FDT_FLOAT:
if (0 == icompare(VECTOR, storage))
addInternalExtract<float, std::vector<float> >(mc); addInternalExtract<float, std::vector<float> >(mc);
else if (0 == icompare(LIST, storage))
addInternalExtract<float, std::list<float> >(mc);
else if (0 == icompare(DEQUE, storage))
addInternalExtract<float, std::deque<float> >(mc);
break; break;
case MetaColumn::FDT_DOUBLE: case MetaColumn::FDT_DOUBLE:
if (0 == icompare(VECTOR, storage))
addInternalExtract<double, std::vector<double> >(mc); addInternalExtract<double, std::vector<double> >(mc);
else if (0 == icompare(LIST, storage))
addInternalExtract<double, std::list<double> >(mc);
else if (0 == icompare(DEQUE, storage))
addInternalExtract<double, std::deque<double> >(mc);
break; break;
case MetaColumn::FDT_STRING: case MetaColumn::FDT_STRING:
if (0 == icompare(VECTOR, storage))
addInternalExtract<std::string, std::vector<std::string> >(mc); addInternalExtract<std::string, std::vector<std::string> >(mc);
else if (0 == icompare(LIST, storage))
addInternalExtract<std::string, std::list<std::string> >(mc);
else if (0 == icompare(DEQUE, storage))
addInternalExtract<std::string, std::deque<std::string> >(mc);
break; break;
case MetaColumn::FDT_BLOB: case MetaColumn::FDT_BLOB:
if (0 == icompare(VECTOR, storage))
addInternalExtract<BLOB, std::vector<BLOB> >(mc); addInternalExtract<BLOB, std::vector<BLOB> >(mc);
else if (0 == icompare(LIST, storage))
addInternalExtract<BLOB, std::list<BLOB> >(mc);
else if (0 == icompare(DEQUE, storage))
addInternalExtract<BLOB, std::deque<BLOB> >(mc);
break; break;
default: default:
throw Poco::InvalidArgumentException("Data type not supported."); throw Poco::InvalidArgumentException("Data type not supported.");

View File

@ -347,7 +347,7 @@ void DataTest::readFromBLOB(BinaryReader& reader)
} }
void DataTest::testColumn() void DataTest::testColumnVector()
{ {
MetaColumn mc(0, "mc", MetaColumn::FDT_DOUBLE, 2, 3, true); MetaColumn mc(0, "mc", MetaColumn::FDT_DOUBLE, 2, 3, true);
@ -417,7 +417,156 @@ void DataTest::testColumn()
assert (c.rowCount() == 0); assert (c.rowCount() == 0);
assert (c1.rowCount() == 0); assert (c1.rowCount() == 0);
assert (c2.rowCount() == 0); assert (c2.rowCount() == 0);
}
void DataTest::testColumnDeque()
{
typedef std::deque<int> ContainerType;
typedef Column<int, ContainerType> ColumnType;
MetaColumn mc(0, "mc", MetaColumn::FDT_DOUBLE, 2, 3, true);
assert (mc.name() == "mc");
assert (mc.position() == 0);
assert (mc.length() == 2);
assert (mc.precision() == 3);
assert (mc.type() == MetaColumn::FDT_DOUBLE);
assert (mc.isNullable());
ContainerType* pData = new ContainerType;
pData->push_back(1);
pData->push_back(2);
pData->push_back(3);
pData->push_back(4);
pData->push_back(5);
ColumnType c(mc, pData);
assert (c.rowCount() == 5);
assert (c[0] == 1);
assert (c[1] == 2);
assert (c[2] == 3);
assert (c[3] == 4);
assert (c[4] == 5);
assert (c.name() == "mc");
assert (c.position() == 0);
assert (c.length() == 2);
assert (c.precision() == 3);
assert (c.type() == MetaColumn::FDT_DOUBLE);
try
{
int i = c[100];
fail ("must fail");
}
catch (RangeException&) { }
ColumnType c1 = c;
assert (c1.rowCount() == 5);
assert (c1[0] == 1);
assert (c1[1] == 2);
assert (c1[2] == 3);
assert (c1[3] == 4);
assert (c1[4] == 5);
ColumnType c2(c1);
assert (c2.rowCount() == 5);
assert (c2[0] == 1);
assert (c2[1] == 2);
assert (c2[2] == 3);
assert (c2[3] == 4);
assert (c2[4] == 5);
ContainerType vi;
vi.assign(c.begin(), c.end());
assert (vi.size() == 5);
assert (vi[0] == 1);
assert (vi[1] == 2);
assert (vi[2] == 3);
assert (vi[3] == 4);
assert (vi[4] == 5);
c.reset();
assert (c.rowCount() == 0);
assert (c1.rowCount() == 0);
assert (c2.rowCount() == 0);
}
void DataTest::testColumnList()
{
typedef std::list<int> ContainerType;
typedef Column<int, ContainerType> ColumnType;
MetaColumn mc(0, "mc", MetaColumn::FDT_DOUBLE, 2, 3, true);
assert (mc.name() == "mc");
assert (mc.position() == 0);
assert (mc.length() == 2);
assert (mc.precision() == 3);
assert (mc.type() == MetaColumn::FDT_DOUBLE);
assert (mc.isNullable());
ContainerType* pData = new ContainerType;
pData->push_back(1);
pData->push_back(2);
pData->push_back(3);
pData->push_back(4);
pData->push_back(5);
ColumnType c(mc, pData);
assert (c.rowCount() == 5);
assert (c[0] == 1);
assert (c[1] == 2);
assert (c[2] == 3);
assert (c[3] == 4);
assert (c[4] == 5);
assert (c.name() == "mc");
assert (c.position() == 0);
assert (c.length() == 2);
assert (c.precision() == 3);
assert (c.type() == MetaColumn::FDT_DOUBLE);
try
{
int i = c[100];
fail ("must fail");
}
catch (RangeException&) { }
ColumnType c1 = c;
assert (c1.rowCount() == 5);
assert (c1[0] == 1);
assert (c1[1] == 2);
assert (c1[2] == 3);
assert (c1[3] == 4);
assert (c1[4] == 5);
ColumnType c2(c1);
assert (c2.rowCount() == 5);
assert (c2[0] == 1);
assert (c2[1] == 2);
assert (c2[2] == 3);
assert (c2[3] == 4);
assert (c2[4] == 5);
ContainerType vi;
vi.assign(c.begin(), c.end());
assert (vi.size() == 5);
ContainerType::const_iterator it = vi.begin();
ContainerType::const_iterator end = vi.end();
for (int i = 1; it != end; ++it, ++i)
assert (*it == i);
c.reset();
assert (c.rowCount() == 0);
assert (c1.rowCount() == 0);
assert (c2.rowCount() == 0);
} }
@ -440,7 +589,9 @@ CppUnit::Test* DataTest::suite()
CppUnit_addTest(pSuite, DataTest, testProperties); CppUnit_addTest(pSuite, DataTest, testProperties);
CppUnit_addTest(pSuite, DataTest, testBLOB); CppUnit_addTest(pSuite, DataTest, testBLOB);
CppUnit_addTest(pSuite, DataTest, testBLOBStreams); CppUnit_addTest(pSuite, DataTest, testBLOBStreams);
CppUnit_addTest(pSuite, DataTest, testColumn); CppUnit_addTest(pSuite, DataTest, testColumnVector);
CppUnit_addTest(pSuite, DataTest, testColumnDeque);
CppUnit_addTest(pSuite, DataTest, testColumnList);
return pSuite; return pSuite;
} }

View File

@ -53,7 +53,9 @@ public:
void testProperties(); void testProperties();
void testBLOB(); void testBLOB();
void testBLOBStreams(); void testBLOBStreams();
void testColumn(); void testColumnVector();
void testColumnDeque();
void testColumnList();
void setUp(); void setUp();
void tearDown(); void tearDown();

View File

@ -61,7 +61,7 @@ SessionImpl::~SessionImpl()
Poco::Data::StatementImpl* SessionImpl::createStatementImpl() Poco::Data::StatementImpl* SessionImpl::createStatementImpl()
{ {
return new TestStatementImpl; return new TestStatementImpl(*this);
} }

View File

@ -31,6 +31,7 @@
#include "TestStatementImpl.h" #include "TestStatementImpl.h"
#include "SessionImpl.h"
namespace Poco { namespace Poco {
@ -38,7 +39,8 @@ namespace Data {
namespace Test { namespace Test {
TestStatementImpl::TestStatementImpl() TestStatementImpl::TestStatementImpl(SessionImpl& rSession):
Poco::Data::StatementImpl(rSession)
{ {
} }

View File

@ -44,20 +44,19 @@
#include "Preparation.h" #include "Preparation.h"
struct sqlite3;
struct sqlite3_stmt;
namespace Poco { namespace Poco {
namespace Data { namespace Data {
namespace Test { namespace Test {
class SessionImpl;
class TestStatementImpl: public Poco::Data::StatementImpl class TestStatementImpl: public Poco::Data::StatementImpl
/// A no-op implementation of TestStatementImpl for testing. /// A no-op implementation of TestStatementImpl for testing.
{ {
public: public:
TestStatementImpl(); TestStatementImpl(SessionImpl& rSession);
/// Creates the TestStatementImpl. /// Creates the TestStatementImpl.
~TestStatementImpl(); ~TestStatementImpl();