mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-13 10:32:57 +01:00
configurable internal storage
This commit is contained in:
parent
911d0c5b82
commit
c1ecb3ee05
@ -128,7 +128,7 @@ private:
|
||||
void fillColumns();
|
||||
void checkError(SQLRETURN rc, const std::string& msg="");
|
||||
|
||||
SessionImpl& _rSession;
|
||||
const SQLHDBC& _rConnection;
|
||||
const StatementHandle _stmt;
|
||||
Poco::SharedPtr<Preparation> _pPreparation;
|
||||
Poco::SharedPtr<Binder> _pBinder;
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
|
||||
#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/ODBCException.h"
|
||||
#include "Poco/Data/AbstractPrepare.h"
|
||||
@ -51,8 +51,9 @@ const std::string ODBCStatementImpl::INVALID_CURSOR_STATE = "24000";
|
||||
|
||||
|
||||
ODBCStatementImpl::ODBCStatementImpl(SessionImpl& rSession):
|
||||
_rSession(rSession),
|
||||
_stmt(_rSession.dbc()),
|
||||
Poco::Data::StatementImpl(rSession),
|
||||
_rConnection(rSession.dbc()),
|
||||
_stmt(rSession.dbc()),
|
||||
_stepCalled(false),
|
||||
_nextResponse(0)
|
||||
{
|
||||
@ -62,7 +63,7 @@ ODBCStatementImpl::ODBCStatementImpl(SessionImpl& rSession):
|
||||
0),
|
||||
"SQLSetStmtAttr(SQL_CURSOR_TYPE, SQL_CURSOR_FORWARD_ONLY)");
|
||||
|
||||
if (_rSession.getFeature("autoBind"))
|
||||
if (session().getFeature("autoBind"))
|
||||
{
|
||||
SQLSetStmtAttr(_stmt,
|
||||
SQL_ATTR_PARAM_BIND_TYPE,
|
||||
@ -96,16 +97,16 @@ void ODBCStatementImpl::compileImpl()
|
||||
if (statement.empty())
|
||||
throw ODBCException("Empty statements are illegal");
|
||||
|
||||
Preparation::DataExtraction ext = _rSession.getFeature("autoExtract") ?
|
||||
Preparation::DataExtraction ext = session().getFeature("autoExtract") ?
|
||||
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,
|
||||
statement,
|
||||
maxFieldSize,
|
||||
ext);
|
||||
|
||||
Binder::ParameterBinding bind = _rSession.getFeature("autoBind") ?
|
||||
Binder::ParameterBinding bind = session().getFeature("autoBind") ?
|
||||
Binder::PB_IMMEDIATE : Binder::PB_AT_EXEC;
|
||||
|
||||
_pBinder = new Binder(_stmt, bind);
|
||||
@ -274,7 +275,7 @@ std::string ODBCStatementImpl::nativeSQL()
|
||||
pNative = new char[retlen];
|
||||
memset(pNative, 0, retlen);
|
||||
length = retlen;
|
||||
if (Utility::isError(SQLNativeSql(_rSession.dbc(),
|
||||
if (Utility::isError(SQLNativeSql(_rConnection,
|
||||
(POCO_SQLCHAR*) statement.c_str(),
|
||||
(SQLINTEGER) statement.size(),
|
||||
(POCO_SQLCHAR*) pNative,
|
||||
@ -282,7 +283,7 @@ std::string ODBCStatementImpl::nativeSQL()
|
||||
&retlen)))
|
||||
{
|
||||
delete [] pNative;
|
||||
throw ConnectionException(_rSession.dbc(), "SQLNativeSql()");
|
||||
throw ConnectionException(_rConnection, "SQLNativeSql()");
|
||||
}
|
||||
++retlen;//accomodate for terminating '\0'
|
||||
}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)
|
||||
{
|
||||
try
|
||||
@ -1056,6 +1071,7 @@ CppUnit::Test* ODBCDB2Test::suite()
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testTuple);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testTupleVector);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testInternalExtraction);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testInternalStorageType);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -115,6 +115,7 @@ public:
|
||||
void testTupleVector();
|
||||
|
||||
void testInternalExtraction();
|
||||
void testInternalStorageType();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "CppUnit/TestSuite.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Format.h"
|
||||
#include "Poco/Tuple.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Data/Common.h"
|
||||
#include "Poco/Data/BLOB.h"
|
||||
@ -54,6 +55,7 @@ using Poco::Data::ODBC::ConnectionException;
|
||||
using Poco::Data::ODBC::StatementException;
|
||||
using Poco::Data::ODBC::StatementDiagnostics;
|
||||
using Poco::format;
|
||||
using Poco::Tuple;
|
||||
using Poco::NotFoundException;
|
||||
|
||||
|
||||
@ -817,34 +819,46 @@ void ODBCMySQLTest::testInternalExtraction()
|
||||
}
|
||||
|
||||
|
||||
void ODBCMySQLTest::dropTable(const std::string& tableName)
|
||||
void ODBCMySQLTest::testInternalStorageType()
|
||||
{
|
||||
try
|
||||
{
|
||||
*_pSession << format("DROP TABLE %s", tableName), now;
|
||||
}
|
||||
catch (StatementException& ex)
|
||||
{
|
||||
bool ignoreError = false;
|
||||
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 (!_pSession) fail ("Test not available.");
|
||||
|
||||
if (!ignoreError) throw;
|
||||
for (int i = 0; i < 8;)
|
||||
{
|
||||
recreateVectorsTable();
|
||||
_pSession->setFeature("autoBind", bindValues[i]);
|
||||
_pSession->setFeature("autoExtract", bindValues[i+1]);
|
||||
_pExecutor->internalStorageType();
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
dropTable("Person");
|
||||
dropObject("TABLE", "Person");
|
||||
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(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); }
|
||||
@ -853,7 +867,7 @@ void ODBCMySQLTest::recreatePersonTable()
|
||||
|
||||
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; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.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()
|
||||
{
|
||||
dropTable("Strings");
|
||||
dropObject("TABLE", "Strings");
|
||||
try { *_pSession << "CREATE TABLE Strings (str INTEGER)", now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); }
|
||||
@ -871,7 +885,7 @@ void ODBCMySQLTest::recreateIntsTable()
|
||||
|
||||
void ODBCMySQLTest::recreateStringsTable()
|
||||
{
|
||||
dropTable("Strings");
|
||||
dropObject("TABLE", "Strings");
|
||||
try { *_pSession << "CREATE TABLE Strings (str VARCHAR(30))", now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.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()
|
||||
{
|
||||
dropTable("Strings");
|
||||
dropObject("TABLE", "Strings");
|
||||
try { *_pSession << "CREATE TABLE Strings (str FLOAT)", now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.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()
|
||||
{
|
||||
dropTable("Tuples");
|
||||
dropObject("TABLE", "Tuples");
|
||||
try { *_pSession << "CREATE TABLE Tuples "
|
||||
"(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,"
|
||||
@ -901,7 +915,7 @@ void ODBCMySQLTest::recreateTuplesTable()
|
||||
|
||||
void ODBCMySQLTest::recreateVectorsTable()
|
||||
{
|
||||
dropTable("Vectors");
|
||||
dropObject("TABLE", "Vectors");
|
||||
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(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); }
|
||||
@ -959,9 +973,9 @@ void ODBCMySQLTest::setUp()
|
||||
|
||||
void ODBCMySQLTest::tearDown()
|
||||
{
|
||||
dropTable("Person");
|
||||
dropTable("Strings");
|
||||
dropTable("Tuples");
|
||||
dropObject("TABLE", "Person");
|
||||
dropObject("TABLE", "Strings");
|
||||
dropObject("TABLE", "Tuples");
|
||||
}
|
||||
|
||||
|
||||
@ -1046,7 +1060,10 @@ CppUnit::Test* ODBCMySQLTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testDouble);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testTuple);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testTupleVector);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testStoredProcedure);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testStoredFunction);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testInternalExtraction);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testInternalStorageType);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -118,6 +118,10 @@ public:
|
||||
void testTupleVector();
|
||||
|
||||
void testInternalExtraction();
|
||||
void testInternalStorageType();
|
||||
|
||||
void testStoredProcedure();
|
||||
void testStoredFunction();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
@ -125,7 +129,7 @@ public:
|
||||
static CppUnit::Test* suite();
|
||||
|
||||
private:
|
||||
void dropTable(const std::string& tableName);
|
||||
void dropObject(const std::string& type, const std::string& name);
|
||||
void recreatePersonTable();
|
||||
void recreatePersonBLOBTable();
|
||||
void recreateStringsTable();
|
||||
|
@ -827,100 +827,132 @@ 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()
|
||||
{
|
||||
*_pSession << "CREATE OR REPLACE "
|
||||
"PROCEDURE storedProcedure(outParam OUT NUMBER) IS "
|
||||
" BEGIN outParam := -1; "
|
||||
"END storedProcedure;" , now;
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
int i = 0;
|
||||
*_pSession << "{call storedProcedure(?)}", out(i), now;
|
||||
assert(-1 == i);
|
||||
*_pSession << "DROP PROCEDURE storedProcedure;", now;
|
||||
for (int k = 0; k < 8;)
|
||||
{
|
||||
_pSession->setFeature("autoBind", bindValues[k]);
|
||||
_pSession->setFeature("autoExtract", bindValues[k+1]);
|
||||
|
||||
*_pSession << "CREATE OR REPLACE "
|
||||
"PROCEDURE storedProcedure(inParam IN NUMBER, outParam OUT NUMBER) IS "
|
||||
" BEGIN outParam := inParam*inParam; "
|
||||
"END storedProcedure;" , now;
|
||||
*_pSession << "CREATE OR REPLACE "
|
||||
"PROCEDURE storedProcedure(outParam OUT NUMBER) IS "
|
||||
" BEGIN outParam := -1; "
|
||||
"END storedProcedure;" , now;
|
||||
|
||||
i = 2;
|
||||
int j = 0;
|
||||
*_pSession << "{call storedProcedure(?, ?)}", in(i), out(j), now;
|
||||
assert(4 == j);
|
||||
*_pSession << "DROP PROCEDURE storedProcedure;", now;
|
||||
int i = 0;
|
||||
*_pSession << "{call storedProcedure(?)}", out(i), now;
|
||||
assert(-1 == i);
|
||||
*_pSession << "DROP PROCEDURE storedProcedure;", now;
|
||||
|
||||
*_pSession << "CREATE OR REPLACE "
|
||||
"PROCEDURE storedProcedure(ioParam IN OUT NUMBER) IS "
|
||||
" BEGIN ioParam := ioParam*ioParam; "
|
||||
" END storedProcedure;" , now;
|
||||
*_pSession << "CREATE OR REPLACE "
|
||||
"PROCEDURE storedProcedure(inParam IN NUMBER, outParam OUT NUMBER) IS "
|
||||
" BEGIN outParam := inParam*inParam; "
|
||||
"END storedProcedure;" , now;
|
||||
|
||||
i = 2;
|
||||
*_pSession << "{call storedProcedure(?)}", io(i), now;
|
||||
assert(4 == i);
|
||||
*_pSession << "DROP PROCEDURE storedProcedure;", now;
|
||||
i = 2;
|
||||
int j = 0;
|
||||
*_pSession << "{call storedProcedure(?, ?)}", in(i), out(j), now;
|
||||
assert(4 == j);
|
||||
*_pSession << "DROP PROCEDURE storedProcedure;", now;
|
||||
|
||||
*_pSession << "CREATE OR REPLACE "
|
||||
"PROCEDURE storedProcedure(ioParam IN OUT NUMBER) IS "
|
||||
" BEGIN ioParam := ioParam*ioParam; "
|
||||
" END storedProcedure;" , now;
|
||||
|
||||
i = 2;
|
||||
*_pSession << "{call storedProcedure(?)}", io(i), now;
|
||||
assert(4 == i);
|
||||
*_pSession << "DROP PROCEDURE storedProcedure;", now;
|
||||
|
||||
k += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODBCOracleTest::testStoredFunction()
|
||||
{
|
||||
*_pSession << "CREATE OR REPLACE "
|
||||
"FUNCTION storedFunction RETURN NUMBER IS "
|
||||
" BEGIN return(-1); "
|
||||
" END storedFunction;" , now;
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
int i = 0;
|
||||
*_pSession << "{? = call storedFunction()}", out(i), now;
|
||||
assert(-1 == i);
|
||||
*_pSession << "DROP FUNCTION storedFunction;", now;
|
||||
for (int k = 0; k < 8;)
|
||||
{
|
||||
*_pSession << "CREATE OR REPLACE "
|
||||
"FUNCTION storedFunction RETURN NUMBER IS "
|
||||
" BEGIN return(-1); "
|
||||
" END storedFunction;" , now;
|
||||
|
||||
*_pSession << "CREATE OR REPLACE "
|
||||
"FUNCTION storedFunction(inParam IN NUMBER) RETURN NUMBER IS "
|
||||
" BEGIN RETURN(inParam*inParam); "
|
||||
" END storedFunction;" , now;
|
||||
int i = 0;
|
||||
*_pSession << "{? = call storedFunction()}", out(i), now;
|
||||
assert(-1 == i);
|
||||
*_pSession << "DROP FUNCTION 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) RETURN NUMBER IS "
|
||||
" BEGIN RETURN(inParam*inParam); "
|
||||
" END 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 result = 0;
|
||||
*_pSession << "{? = call storedFunction(?)}", out(result), in(i), now;
|
||||
assert(4 == result);
|
||||
*_pSession << "DROP FUNCTION 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(inParam IN NUMBER, outParam OUT NUMBER) RETURN NUMBER IS "
|
||||
" BEGIN outParam := inParam*inParam; RETURN(outParam); "
|
||||
" END 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 = 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;
|
||||
|
||||
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;
|
||||
*_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;
|
||||
|
||||
k = k + 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1176,6 +1208,7 @@ CppUnit::Test* ODBCOracleTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testStoredProcedure);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testStoredFunction);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testInternalExtraction);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testInternalStorageType);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -116,6 +116,8 @@ public:
|
||||
void testTupleVector();
|
||||
|
||||
void testInternalExtraction();
|
||||
void testInternalStorageType();
|
||||
|
||||
void testStoredProcedure();
|
||||
void testStoredFunction();
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "CppUnit/TestSuite.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Format.h"
|
||||
#include "Poco/Tuple.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Data/Common.h"
|
||||
#include "Poco/Data/BLOB.h"
|
||||
@ -54,6 +55,7 @@ using Poco::Data::ODBC::ConnectionException;
|
||||
using Poco::Data::ODBC::StatementException;
|
||||
using Poco::Data::ODBC::StatementDiagnostics;
|
||||
using Poco::format;
|
||||
using Poco::Tuple;
|
||||
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)
|
||||
{
|
||||
try
|
||||
@ -1068,6 +1085,7 @@ CppUnit::Test* ODBCPostgreSQLTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTuple);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTupleVector);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testInternalExtraction);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testInternalStorageType);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -118,6 +118,7 @@ public:
|
||||
void testTupleVector();
|
||||
|
||||
void testInternalExtraction();
|
||||
void testInternalStorageType();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "CppUnit/TestSuite.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Format.h"
|
||||
#include "Poco/Tuple.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Data/Common.h"
|
||||
#include "Poco/Data/BLOB.h"
|
||||
@ -54,6 +55,7 @@ using Poco::Data::ODBC::ConnectionException;
|
||||
using Poco::Data::ODBC::StatementException;
|
||||
using Poco::Data::ODBC::StatementDiagnostics;
|
||||
using Poco::format;
|
||||
using Poco::Tuple;
|
||||
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
|
||||
{
|
||||
*_pSession << format("DROP TABLE %s", tableName), now;
|
||||
*_pSession << format("DROP %s %s", type, name), now;
|
||||
}
|
||||
catch (StatementException& ex)
|
||||
{
|
||||
@ -856,7 +994,7 @@ void ODBCSQLServerTest::dropTable(const std::string& tableName)
|
||||
|
||||
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; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.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()
|
||||
{
|
||||
dropTable("Person");
|
||||
dropObject("TABLE", "Person");
|
||||
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(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
|
||||
@ -874,7 +1012,7 @@ void ODBCSQLServerTest::recreatePersonBLOBTable()
|
||||
|
||||
void ODBCSQLServerTest::recreateIntsTable()
|
||||
{
|
||||
dropTable("Strings");
|
||||
dropObject("TABLE", "Strings");
|
||||
try { *_pSession << "CREATE TABLE Strings (str INTEGER)", now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); }
|
||||
@ -883,7 +1021,7 @@ void ODBCSQLServerTest::recreateIntsTable()
|
||||
|
||||
void ODBCSQLServerTest::recreateStringsTable()
|
||||
{
|
||||
dropTable("Strings");
|
||||
dropObject("TABLE", "Strings");
|
||||
try { *_pSession << "CREATE TABLE Strings (str VARCHAR(30))", now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.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()
|
||||
{
|
||||
dropTable("Strings");
|
||||
dropObject("TABLE", "Strings");
|
||||
try { *_pSession << "CREATE TABLE Strings (str FLOAT)", now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.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()
|
||||
{
|
||||
dropTable("Tuples");
|
||||
dropObject("TABLE", "Tuples");
|
||||
try { *_pSession << "CREATE TABLE Tuples "
|
||||
"(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,"
|
||||
@ -913,7 +1051,7 @@ void ODBCSQLServerTest::recreateTuplesTable()
|
||||
|
||||
void ODBCSQLServerTest::recreateVectorTable()
|
||||
{
|
||||
dropTable("Vector");
|
||||
dropObject("TABLE", "Vector");
|
||||
try { *_pSession << "CREATE TABLE Vector (i0 INTEGER)", now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.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()
|
||||
{
|
||||
dropTable("Vectors");
|
||||
dropObject("TABLE", "Vectors");
|
||||
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(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); }
|
||||
@ -981,9 +1119,9 @@ void ODBCSQLServerTest::setUp()
|
||||
|
||||
void ODBCSQLServerTest::tearDown()
|
||||
{
|
||||
dropTable("Person");
|
||||
dropTable("Strings");
|
||||
dropTable("Tuples");
|
||||
dropObject("TABLE", "Person");
|
||||
dropObject("TABLE", "Strings");
|
||||
dropObject("TABLE", "Tuples");
|
||||
}
|
||||
|
||||
|
||||
@ -1068,7 +1206,10 @@ CppUnit::Test* ODBCSQLServerTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testDouble);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTuple);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTupleVector);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testStoredProcedure);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testStoredFunction);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testInternalExtraction);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testInternalStorageType);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -117,7 +117,11 @@ public:
|
||||
void testTuple();
|
||||
void testTupleVector();
|
||||
|
||||
void testStoredProcedure();
|
||||
void testStoredFunction();
|
||||
|
||||
void testInternalExtraction();
|
||||
void testInternalStorageType();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
@ -125,7 +129,7 @@ public:
|
||||
static CppUnit::Test* suite();
|
||||
|
||||
private:
|
||||
void dropTable(const std::string& tableName);
|
||||
void dropObject(const std::string& type, const std::string& name);
|
||||
void recreatePersonTable();
|
||||
void recreatePersonBLOBTable();
|
||||
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)
|
||||
{
|
||||
try
|
||||
@ -1029,6 +1044,7 @@ CppUnit::Test* ODBCSQLiteTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testTuple);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testTupleVector);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testInternalExtraction);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testInternalStorageType);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -115,6 +115,7 @@ public:
|
||||
void testTupleVector();
|
||||
|
||||
void testInternalExtraction();
|
||||
void testInternalStorageType();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
@ -1836,7 +1836,7 @@ void SQLExecutor::internalExtraction()
|
||||
i = rset.value("str0", 2);
|
||||
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 end = col.end();
|
||||
for (int i = 1; it != end; ++it, ++i)
|
||||
@ -1870,7 +1870,7 @@ void SQLExecutor::internalExtraction()
|
||||
s = rset.value("cnt", 0).convert<std::string>();
|
||||
assert ("4" == s);
|
||||
|
||||
try { rset.column<int>(100); fail ("must fail"); }
|
||||
try { rset.column<int, std::vector<int> >(100); fail ("must fail"); }
|
||||
catch (RangeException&) { }
|
||||
|
||||
try { rset.value<std::string>(0,0); fail ("must fail"); }
|
||||
@ -1879,9 +1879,79 @@ void SQLExecutor::internalExtraction()
|
||||
stmt = (*_pSession << "DELETE FROM Vectors", now);
|
||||
rset = stmt;
|
||||
|
||||
try { rset.column<int>(0); fail ("must fail"); }
|
||||
try { rset.column<int, std::vector<int> >(0); fail ("must fail"); }
|
||||
catch (RangeException&) { }
|
||||
}
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
||||
}
|
||||
|
||||
|
||||
void SQLExecutor::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 internalExtraction();
|
||||
void internalStorageType();
|
||||
|
||||
private:
|
||||
Poco::Data::Session* _pSession;
|
||||
|
@ -74,7 +74,19 @@ public:
|
||||
|
||||
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()
|
||||
@ -142,6 +154,24 @@ public:
|
||||
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:
|
||||
void addFeature(const std::string& name, FeatureSetter setter, FeatureGetter getter)
|
||||
/// Adds a feature to the map of supported features.
|
||||
@ -185,6 +215,7 @@ private:
|
||||
|
||||
FeatureMap _features;
|
||||
PropertyMap _properties;
|
||||
std::string _storage;
|
||||
};
|
||||
|
||||
|
||||
|
@ -44,13 +44,14 @@
|
||||
#include "Poco/Data/MetaColumn.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
|
||||
template <class T>
|
||||
template <class T, class C = std::vector<T> >
|
||||
class Column
|
||||
/// Column class is column data container.
|
||||
/// 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.
|
||||
{
|
||||
public:
|
||||
typedef std::vector<T> DataVec;
|
||||
typedef typename DataVec::const_iterator Iterator;
|
||||
typedef typename DataVec::size_type Size;
|
||||
typedef C Container;
|
||||
typedef typename Container::const_iterator Iterator;
|
||||
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.
|
||||
{
|
||||
poco_check_ptr (_pData);
|
||||
@ -94,7 +95,7 @@ public:
|
||||
std::swap(_pData, other._pData);
|
||||
}
|
||||
|
||||
DataVec& data()
|
||||
Container& data()
|
||||
/// Returns reference to contained data.
|
||||
{
|
||||
return *_pData;
|
||||
@ -128,7 +129,7 @@ public:
|
||||
void reset()
|
||||
/// Clears and shrinks the storage.
|
||||
{
|
||||
std::vector<T>().swap(*_pData);
|
||||
C().swap(*_pData);
|
||||
}
|
||||
|
||||
const std::string& name() const
|
||||
@ -177,8 +178,134 @@ public:
|
||||
private:
|
||||
Column();
|
||||
|
||||
MetaColumn _metaColumn;
|
||||
Poco::SharedPtr<DataVec> _pData;
|
||||
MetaColumn _metaColumn;
|
||||
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.
|
||||
{
|
||||
public:
|
||||
explicit InternalExtraction(C& result, Column<T>* pColumn):
|
||||
explicit InternalExtraction(C& result, Column<T,C>* pColumn):
|
||||
Extraction<C>(result),
|
||||
_pColumn(pColumn)
|
||||
/// Creates InternalExtraction.
|
||||
@ -341,7 +341,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
const Column<T>& column() const
|
||||
const Column<T,C>& column() const
|
||||
{
|
||||
return *_pColumn;
|
||||
}
|
||||
@ -351,7 +351,7 @@ private:
|
||||
InternalExtraction(const InternalExtraction&);
|
||||
InternalExtraction& operator = (const InternalExtraction&);
|
||||
|
||||
Column<T>* _pColumn;
|
||||
Column<T,C>* _pColumn;
|
||||
};
|
||||
|
||||
|
||||
|
@ -88,18 +88,18 @@ public:
|
||||
std::size_t columnCount() const;
|
||||
/// Returns the number of rows in the recordset.
|
||||
|
||||
template<class T>
|
||||
const Column<T>& column(const std::string& name) const
|
||||
template<class T, class C>
|
||||
const Column<T,C>& column(const std::string& name) const
|
||||
/// 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>
|
||||
const Column<T>& column(std::size_t pos) const
|
||||
template<class T, class C>
|
||||
const Column<T,C>& column(std::size_t pos) const
|
||||
/// Returns the reference to column at specified location.
|
||||
{
|
||||
typedef const InternalExtraction<T>* ExtractionVecPtr;
|
||||
typedef const InternalExtraction<T,C>* ExtractionVecPtr;
|
||||
|
||||
const AbstractExtractionVec& rExtractions = extractions();
|
||||
|
||||
@ -125,14 +125,36 @@ public:
|
||||
const T& value(std::size_t col, std::size_t row) const
|
||||
/// 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>
|
||||
const T& value(const std::string& name, std::size_t row) const
|
||||
/// 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;
|
||||
@ -204,11 +226,11 @@ public:
|
||||
private:
|
||||
RecordSet();
|
||||
|
||||
template<class T>
|
||||
template<class T, class C>
|
||||
std::size_t columnPosition(const std::string& name) const
|
||||
/// Returns the position of the column with specified name.
|
||||
{
|
||||
typedef const InternalExtraction<T>* ExtractionVecPtr;
|
||||
typedef const InternalExtraction<T,C>* ExtractionVecPtr;
|
||||
|
||||
const AbstractExtractionVec& rExtractions = extractions();
|
||||
AbstractExtractionVec::const_iterator it = rExtractions.begin();
|
||||
@ -220,7 +242,7 @@ private:
|
||||
|
||||
if (pExtraction)
|
||||
{
|
||||
const Column<T>& col = pExtraction->column();
|
||||
const Column<T,C>& col = pExtraction->column();
|
||||
if (0 == Poco::icompare(name, col.name()))
|
||||
return col.position();
|
||||
}
|
||||
|
@ -63,7 +63,15 @@ class Data_API Statement
|
||||
{
|
||||
public:
|
||||
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);
|
||||
/// Creates the Statement.
|
||||
|
||||
@ -134,6 +142,22 @@ public:
|
||||
Statement& reset(Session& session);
|
||||
/// 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:
|
||||
const AbstractExtractionVec& extractions() const;
|
||||
/// Returns the extractions vector.
|
||||
@ -157,6 +181,12 @@ private:
|
||||
//
|
||||
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
|
||||
@ -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
|
||||
|
||||
|
||||
|
@ -59,6 +59,9 @@ namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
|
||||
class SessionImpl;
|
||||
|
||||
|
||||
class Data_API StatementImpl: public Poco::RefCountedObject
|
||||
/// StatementImpl interface that subclasses must implement to define database dependent query execution.
|
||||
///
|
||||
@ -74,7 +77,20 @@ public:
|
||||
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.
|
||||
|
||||
virtual ~StatementImpl();
|
||||
@ -107,6 +123,19 @@ public:
|
||||
State getState() const;
|
||||
/// 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:
|
||||
virtual Poco::UInt32 columnsReturned() const = 0;
|
||||
/// Returns number of columns returned by query.
|
||||
@ -161,8 +190,29 @@ protected:
|
||||
/// Returns the extractions vector.
|
||||
|
||||
void makeExtractors(Poco::UInt32 count);
|
||||
/// Creates extraction vector. Used in case when there is
|
||||
/// data returned, but no extraction supplied externally.
|
||||
/// Determines the type of the internal extraction container and
|
||||
/// 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:
|
||||
void compile();
|
||||
@ -193,9 +243,9 @@ private:
|
||||
void addInternalExtract(const MetaColumn& mc)
|
||||
/// Utility function to create and add an internal extraction.
|
||||
{
|
||||
std::vector<T>* pData = new C;
|
||||
Column<T>* pCol = new Column<T>(mc, pData);
|
||||
addExtract(new InternalExtraction<T>(*pData, pCol));
|
||||
C* pData = new C;
|
||||
Column<T,C>* pCol = new Column<T,C>(mc, pData);
|
||||
addExtract(new InternalExtraction<T,C>(*pData, pCol));
|
||||
}
|
||||
|
||||
StatementImpl(const StatementImpl& stmt);
|
||||
@ -208,6 +258,8 @@ private:
|
||||
std::ostringstream _ostr;
|
||||
AbstractBindingVec _bindings;
|
||||
AbstractExtractionVec _extractors;
|
||||
SessionImpl& _rSession;
|
||||
Storage _storage;
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
@ -62,7 +62,7 @@ DynamicAny RecordSet::value(std::size_t col, std::size_t row) const
|
||||
case MetaColumn::FDT_UINT8: return value<UInt8>(col, row);
|
||||
case MetaColumn::FDT_INT16: return value<Int16>(col, row);
|
||||
case MetaColumn::FDT_UINT16: return value<UInt16>(col, row);
|
||||
case MetaColumn::FDT_INT32: return value<Int32>(col, row);
|
||||
case MetaColumn::FDT_INT32: return value<Int32>(col, row);
|
||||
case MetaColumn::FDT_UINT32: return value<UInt32>(col, row);
|
||||
case MetaColumn::FDT_INT64: return value<Int64>(col, row);
|
||||
case MetaColumn::FDT_UINT64: return value<UInt64>(col, row);
|
||||
@ -81,18 +81,18 @@ DynamicAny RecordSet::value(const std::string& name, std::size_t row) const
|
||||
switch (columnType(name))
|
||||
{
|
||||
case MetaColumn::FDT_BOOL:
|
||||
case MetaColumn::FDT_INT8: return value<Int8>(name, row);
|
||||
case MetaColumn::FDT_UINT8: return value<UInt8>(name, row);
|
||||
case MetaColumn::FDT_INT16: return value<Int16>(name, row);
|
||||
case MetaColumn::FDT_UINT16: return value<UInt16>(name, row);
|
||||
case MetaColumn::FDT_INT32: return value<Int32>(name, row);
|
||||
case MetaColumn::FDT_UINT32: return value<UInt32>(name, row);
|
||||
case MetaColumn::FDT_INT64: return value<Int64>(name, row);
|
||||
case MetaColumn::FDT_UINT64: return value<UInt64>(name, row);
|
||||
case MetaColumn::FDT_FLOAT: return value<float>(name, row);
|
||||
case MetaColumn::FDT_DOUBLE: return value<double>(name, row);
|
||||
case MetaColumn::FDT_STRING: return value<std::string>(name, row);
|
||||
case MetaColumn::FDT_BLOB: return value<BLOB>(name, row);
|
||||
case MetaColumn::FDT_INT8: return value<Int8>(name, row);
|
||||
case MetaColumn::FDT_UINT8: return value<UInt8>(name, row);
|
||||
case MetaColumn::FDT_INT16: return value<Int16>(name, row);
|
||||
case MetaColumn::FDT_UINT16: return value<UInt16>(name, row);
|
||||
case MetaColumn::FDT_INT32: return value<Int32>(name, row);
|
||||
case MetaColumn::FDT_UINT32: return value<UInt32>(name, row);
|
||||
case MetaColumn::FDT_INT64: return value<Int64>(name, row);
|
||||
case MetaColumn::FDT_UINT64: return value<UInt64>(name, row);
|
||||
case MetaColumn::FDT_FLOAT: return value<float>(name, row);
|
||||
case MetaColumn::FDT_DOUBLE: return value<double>(name, row);
|
||||
case MetaColumn::FDT_STRING: return value<std::string>(name, row);
|
||||
case MetaColumn::FDT_BLOB: return value<BLOB>(name, row);
|
||||
default:
|
||||
throw Poco::InvalidArgumentException("Data type not supported.");
|
||||
}
|
||||
|
@ -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 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)
|
||||
{
|
||||
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
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
|
||||
#include "Poco/Data/StatementImpl.h"
|
||||
#include "Poco/Data/SessionImpl.h"
|
||||
#include "Poco/Data/DataException.h"
|
||||
#include "Poco/Data/AbstractBinder.h"
|
||||
#include "Poco/Data/Extraction.h"
|
||||
@ -44,15 +45,26 @@
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
using Poco::icompare;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
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),
|
||||
_extrLimit(upperLimit((Poco::UInt32) Limit::LIMIT_UNLIMITED, false)),
|
||||
_lowerLimit(0),
|
||||
_columnsExtracted(0),
|
||||
_rSession(rSession),
|
||||
_storage(STORAGE_UNKNOWN_IMPL),
|
||||
_ostr(),
|
||||
_bindings()
|
||||
{
|
||||
@ -254,49 +266,138 @@ 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
const MetaColumn& mc = metaColumn(i);
|
||||
switch (mc.type())
|
||||
{
|
||||
case MetaColumn::FDT_BOOL:
|
||||
case MetaColumn::FDT_INT8:
|
||||
addInternalExtract<Int8, std::vector<Int8> >(mc);
|
||||
case MetaColumn::FDT_INT8:
|
||||
if (0 == icompare(VECTOR, storage))
|
||||
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;
|
||||
case MetaColumn::FDT_UINT8:
|
||||
addInternalExtract<UInt8, std::vector<UInt8> >(mc);
|
||||
if (0 == icompare(VECTOR, storage))
|
||||
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;
|
||||
case MetaColumn::FDT_INT16:
|
||||
addInternalExtract<Int16, std::vector<Int16> >(mc);
|
||||
if (0 == icompare(VECTOR, storage))
|
||||
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;
|
||||
case MetaColumn::FDT_UINT16:
|
||||
addInternalExtract<UInt16, std::vector<UInt16> >(mc);
|
||||
if (0 == icompare(VECTOR, storage))
|
||||
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;
|
||||
case MetaColumn::FDT_INT32:
|
||||
addInternalExtract<Int32, std::vector<Int32> >(mc);
|
||||
if (0 == icompare(VECTOR, storage))
|
||||
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;
|
||||
case MetaColumn::FDT_UINT32:
|
||||
addInternalExtract<UInt32, std::vector<UInt32> >(mc);
|
||||
if (0 == icompare(VECTOR, storage))
|
||||
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;
|
||||
case MetaColumn::FDT_INT64:
|
||||
addInternalExtract<Int64, std::vector<Int64> >(mc);
|
||||
if (0 == icompare(VECTOR, storage))
|
||||
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;
|
||||
case MetaColumn::FDT_UINT64:
|
||||
addInternalExtract<UInt64, std::vector<UInt64> >(mc);
|
||||
if (0 == icompare(VECTOR, storage))
|
||||
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;
|
||||
case MetaColumn::FDT_FLOAT:
|
||||
addInternalExtract<float, std::vector<float> >(mc);
|
||||
if (0 == icompare(VECTOR, storage))
|
||||
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;
|
||||
case MetaColumn::FDT_DOUBLE:
|
||||
addInternalExtract<double, std::vector<double> >(mc);
|
||||
if (0 == icompare(VECTOR, storage))
|
||||
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;
|
||||
case MetaColumn::FDT_STRING:
|
||||
addInternalExtract<std::string, std::vector<std::string> >(mc);
|
||||
if (0 == icompare(VECTOR, storage))
|
||||
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;
|
||||
case MetaColumn::FDT_BLOB:
|
||||
addInternalExtract<BLOB, std::vector<BLOB> >(mc);
|
||||
if (0 == icompare(VECTOR, storage))
|
||||
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;
|
||||
default:
|
||||
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);
|
||||
|
||||
@ -417,7 +417,156 @@ void DataTest::testColumn()
|
||||
assert (c.rowCount() == 0);
|
||||
assert (c1.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, testBLOB);
|
||||
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;
|
||||
}
|
||||
|
@ -53,7 +53,9 @@ public:
|
||||
void testProperties();
|
||||
void testBLOB();
|
||||
void testBLOBStreams();
|
||||
void testColumn();
|
||||
void testColumnVector();
|
||||
void testColumnDeque();
|
||||
void testColumnList();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
@ -61,7 +61,7 @@ SessionImpl::~SessionImpl()
|
||||
|
||||
Poco::Data::StatementImpl* SessionImpl::createStatementImpl()
|
||||
{
|
||||
return new TestStatementImpl;
|
||||
return new TestStatementImpl(*this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
|
||||
#include "TestStatementImpl.h"
|
||||
#include "SessionImpl.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@ -38,7 +39,8 @@ namespace Data {
|
||||
namespace Test {
|
||||
|
||||
|
||||
TestStatementImpl::TestStatementImpl()
|
||||
TestStatementImpl::TestStatementImpl(SessionImpl& rSession):
|
||||
Poco::Data::StatementImpl(rSession)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -44,20 +44,19 @@
|
||||
#include "Preparation.h"
|
||||
|
||||
|
||||
struct sqlite3;
|
||||
struct sqlite3_stmt;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace Test {
|
||||
|
||||
|
||||
class SessionImpl;
|
||||
|
||||
|
||||
class TestStatementImpl: public Poco::Data::StatementImpl
|
||||
/// A no-op implementation of TestStatementImpl for testing.
|
||||
{
|
||||
public:
|
||||
TestStatementImpl();
|
||||
TestStatementImpl(SessionImpl& rSession);
|
||||
/// Creates the TestStatementImpl.
|
||||
|
||||
~TestStatementImpl();
|
||||
|
Loading…
Reference in New Issue
Block a user