mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-13 18:45:10 +01:00
configurable internal storage
This commit is contained in:
parent
911d0c5b82
commit
c1ecb3ee05
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,7 @@ public:
|
|||||||
void testTupleVector();
|
void testTupleVector();
|
||||||
|
|
||||||
void testInternalExtraction();
|
void testInternalExtraction();
|
||||||
|
void testInternalStorageType();
|
||||||
|
|
||||||
void setUp();
|
void setUp();
|
||||||
void tearDown();
|
void tearDown();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,8 @@ public:
|
|||||||
void testTupleVector();
|
void testTupleVector();
|
||||||
|
|
||||||
void testInternalExtraction();
|
void testInternalExtraction();
|
||||||
|
void testInternalStorageType();
|
||||||
|
|
||||||
void testStoredProcedure();
|
void testStoredProcedure();
|
||||||
void testStoredFunction();
|
void testStoredFunction();
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -118,6 +118,7 @@ public:
|
|||||||
void testTupleVector();
|
void testTupleVector();
|
||||||
|
|
||||||
void testInternalExtraction();
|
void testInternalExtraction();
|
||||||
|
void testInternalStorageType();
|
||||||
|
|
||||||
void setUp();
|
void setUp();
|
||||||
void tearDown();
|
void tearDown();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,7 @@ public:
|
|||||||
void testTupleVector();
|
void testTupleVector();
|
||||||
|
|
||||||
void testInternalExtraction();
|
void testInternalExtraction();
|
||||||
|
void testInternalStorageType();
|
||||||
|
|
||||||
void setUp();
|
void setUp();
|
||||||
void tearDown();
|
void tearDown();
|
||||||
|
@ -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); }
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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.");
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -61,7 +61,7 @@ SessionImpl::~SessionImpl()
|
|||||||
|
|
||||||
Poco::Data::StatementImpl* SessionImpl::createStatementImpl()
|
Poco::Data::StatementImpl* SessionImpl::createStatementImpl()
|
||||||
{
|
{
|
||||||
return new TestStatementImpl;
|
return new TestStatementImpl(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user