mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-13 10:32:57 +01:00
std::string stored proc in-bound binding
This commit is contained in:
parent
7944f7868b
commit
f5d1b17306
@ -68,7 +68,10 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
|
||||
{
|
||||
public:
|
||||
typedef AbstractBinder::Direction Direction;
|
||||
typedef std::map<SQLPOINTER, SQLLEN> ParameterMap;
|
||||
typedef Tuple<SQLPOINTER, SQLLEN, SQLSMALLINT, SQLSMALLINT> ParamTuple;
|
||||
typedef std::vector<ParamTuple> ParamVec;
|
||||
|
||||
static const size_t DEFAULT_PARAM_SIZE = 1024;
|
||||
|
||||
enum ParameterBinding
|
||||
{
|
||||
@ -138,15 +141,18 @@ public:
|
||||
std::size_t parameterSize(SQLPOINTER pAddr) const;
|
||||
/// Returns bound data size for parameter at specified position.
|
||||
|
||||
void sync(Direction direction);
|
||||
/// Synchronizes non-POD parameters.
|
||||
void synchronize();
|
||||
/// Transfers the results of non-POD outbound parameters from internal
|
||||
/// holders back into the externally supplied buffers.
|
||||
|
||||
ParameterMap& outParameters();
|
||||
ParamVec& outParameters();
|
||||
/// Returns map of output parameter pointers and sizes.
|
||||
|
||||
private:
|
||||
typedef std::vector<SQLLEN*> LengthVec;
|
||||
typedef std::map<SQL_TIMESTAMP_STRUCT*, DateTime*> TimestampMap;
|
||||
typedef std::map<char*, std::string*> StringMap;
|
||||
typedef std::map<char*, BLOB*> BLOBMap;
|
||||
|
||||
void describeParameter(std::size_t pos);
|
||||
/// Sets the description field for the parameter, if needed.
|
||||
@ -156,17 +162,22 @@ private:
|
||||
/// This is a private no-op in this implementation
|
||||
/// due to security risk.
|
||||
|
||||
std::size_t getParamSize(std::size_t pos);
|
||||
/// Returns parameter size as defined by data source.
|
||||
/// Used to determine buffer size for variable size out-bound parameters
|
||||
/// (string and BLOB).
|
||||
|
||||
SQLSMALLINT getParamType(Direction dir) const;
|
||||
/// Returns ODBC parameter type based on the parameter binding direction
|
||||
/// specified by user.
|
||||
|
||||
template <typename T>
|
||||
void bindImpl(std::size_t pos, T& val, SQLSMALLINT cDataType, Direction dir)
|
||||
{
|
||||
_lengthIndicator.push_back(0);
|
||||
|
||||
int sqlDataType = Utility::sqlDataType(cDataType);
|
||||
SQLINTEGER colSize = 0;
|
||||
SQLSMALLINT decDigits = 0;
|
||||
|
||||
if (_pTypeInfo)
|
||||
{
|
||||
try
|
||||
@ -180,12 +191,12 @@ private:
|
||||
(SQLUSMALLINT) pos + 1,
|
||||
getParamType(dir),
|
||||
cDataType,
|
||||
sqlDataType,
|
||||
Utility::sqlDataType(cDataType),
|
||||
colSize,
|
||||
decDigits,
|
||||
(SQLPOINTER) &val,
|
||||
0,
|
||||
_lengthIndicator.back())))
|
||||
0)))
|
||||
{
|
||||
throw StatementException(_rStmt, "SQLBindParameter()");
|
||||
}
|
||||
@ -193,10 +204,12 @@ private:
|
||||
|
||||
const StatementHandle& _rStmt;
|
||||
LengthVec _lengthIndicator;
|
||||
ParameterMap _inParams;
|
||||
ParameterMap _outParams;
|
||||
ParamVec _inParams;
|
||||
ParamVec _outParams;
|
||||
ParameterBinding _paramBinding;
|
||||
TimestampMap _timestamps;
|
||||
StringMap _strings;
|
||||
BLOBMap _blobs;
|
||||
const TypeInfo* _pTypeInfo;
|
||||
};
|
||||
|
||||
@ -288,12 +301,24 @@ inline Binder::ParameterBinding Binder::getDataBinding() const
|
||||
}
|
||||
|
||||
|
||||
inline Binder::ParameterMap& Binder::outParameters()
|
||||
inline Binder::ParamVec& Binder::outParameters()
|
||||
{
|
||||
return _outParams;
|
||||
}
|
||||
|
||||
|
||||
inline std::size_t Binder::getParamSize(std::size_t pos)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Parameter(_rStmt, pos).columnSize();
|
||||
}catch (StatementException&)
|
||||
{
|
||||
return DEFAULT_PARAM_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::ODBC
|
||||
|
||||
|
||||
|
@ -128,6 +128,8 @@ private:
|
||||
/// Called whenever SQLExecute returns SQL_NEED_DATA. This is expected
|
||||
/// behavior for PB_AT_EXEC binding mode.
|
||||
|
||||
void getData();
|
||||
|
||||
void fillColumns();
|
||||
void checkError(SQLRETURN rc, const std::string& msg="");
|
||||
|
||||
|
@ -67,15 +67,41 @@ Binder::~Binder()
|
||||
TimestampMap::iterator itTS = _timestamps.begin();
|
||||
TimestampMap::iterator itTSEnd = _timestamps.end();
|
||||
for(; itTS != itTSEnd; ++itTS) delete itTS->first;
|
||||
|
||||
StringMap::iterator itStr = _strings.begin();
|
||||
StringMap::iterator itStrEnd = _strings.end();
|
||||
for(; itStr != itStrEnd; ++itStr) std::free(itStr->first);
|
||||
|
||||
BLOBMap::iterator itB = _blobs.begin();
|
||||
BLOBMap::iterator itBEnd = _blobs.end();
|
||||
for(; itB != itBEnd; ++itB) std::free(itB->first);
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
|
||||
{
|
||||
if (isOutBound(dir))
|
||||
throw InvalidAccessException("std::string can only be in-bound");
|
||||
|
||||
SQLPOINTER pVal = 0;
|
||||
SQLINTEGER size = (SQLINTEGER) val.size();
|
||||
|
||||
if (isOutBound(dir))
|
||||
{
|
||||
Parameter p(_rStmt, pos);
|
||||
size = p.columnSize();
|
||||
char* pChar = (char*) std::calloc(size, sizeof(char));
|
||||
ParamTuple pt(pChar, size, SQL_C_CHAR, SQL_LONGVARCHAR);
|
||||
_outParams.push_back(pt);
|
||||
_strings.insert(StringMap::value_type(pChar, const_cast<std::string*>(&val)));
|
||||
pVal = (SQLPOINTER) pChar;
|
||||
}
|
||||
else if (isInBound(dir))
|
||||
{
|
||||
pVal = (SQLPOINTER) val.c_str();
|
||||
ParamTuple pt((SQLPOINTER) pVal, size, SQL_C_CHAR, SQL_LONGVARCHAR);
|
||||
_inParams.push_back(pt);
|
||||
}
|
||||
else
|
||||
throw IllegalStateException("Parameter must be [in] OR [out] bound.");
|
||||
|
||||
SQLLEN* pLenIn = new SQLLEN;
|
||||
*pLenIn = SQL_NTS;
|
||||
|
||||
@ -83,20 +109,15 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
|
||||
*pLenIn = SQL_LEN_DATA_AT_EXEC(size);
|
||||
|
||||
_lengthIndicator.push_back(pLenIn);
|
||||
if (isInBound(dir))
|
||||
_inParams.insert(ParameterMap::value_type((SQLPOINTER) val.c_str(), size));
|
||||
//TODO
|
||||
//if (isOutBound(dir))
|
||||
// _outParams.insert(ParameterMap::value_type((SQLPOINTER) pTS, size));
|
||||
|
||||
if (Utility::isError(SQLBindParameter(_rStmt,
|
||||
(SQLUSMALLINT) pos + 1,
|
||||
SQL_PARAM_INPUT,
|
||||
getParamType(dir),
|
||||
SQL_C_CHAR,
|
||||
SQL_LONGVARCHAR,
|
||||
(SQLUINTEGER) size,
|
||||
0,
|
||||
(SQLPOINTER) val.c_str(),
|
||||
pVal,
|
||||
(SQLINTEGER) size,
|
||||
_lengthIndicator.back())))
|
||||
{
|
||||
@ -107,9 +128,7 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
|
||||
|
||||
void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir)
|
||||
{
|
||||
if (isOutBound(dir))
|
||||
throw InvalidAccessException("BLOB can only be in-bound");
|
||||
|
||||
SQLPOINTER pVal = 0;
|
||||
SQLINTEGER size = (SQLINTEGER) val.size();
|
||||
SQLLEN* pLenIn = new SQLLEN;
|
||||
*pLenIn = size;
|
||||
@ -118,20 +137,33 @@ void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir)
|
||||
*pLenIn = SQL_LEN_DATA_AT_EXEC(size);
|
||||
|
||||
_lengthIndicator.push_back(pLenIn);
|
||||
if (isInBound(dir))
|
||||
_inParams.insert(ParameterMap::value_type((SQLPOINTER) val.rawContent(), size));
|
||||
//TODO
|
||||
//if (isOutBound(dir))
|
||||
// _outParams.insert(ParameterMap::value_type((SQLPOINTER) pTS, size));
|
||||
|
||||
if (isOutBound(dir))
|
||||
{
|
||||
size = getParamSize(pos);
|
||||
char* pChar = (char*) std::calloc(size, sizeof(char));
|
||||
ParamTuple pt(pChar, size, SQL_C_BINARY, SQL_LONGVARBINARY);
|
||||
_outParams.push_back(pt);
|
||||
_blobs.insert(BLOBMap::value_type(pChar, const_cast<BLOB*>(&val)));
|
||||
pVal = (SQLPOINTER) pChar;
|
||||
}
|
||||
else if (isInBound(dir))
|
||||
{
|
||||
pVal = (SQLPOINTER) val.rawContent();
|
||||
ParamTuple pt((SQLPOINTER) pVal, size, SQL_C_BINARY, SQL_LONGVARBINARY);
|
||||
_inParams.push_back(pt);
|
||||
}
|
||||
else
|
||||
throw IllegalStateException("Parameter must be [in] OR [out] bound.");
|
||||
|
||||
if (Utility::isError(SQLBindParameter(_rStmt,
|
||||
(SQLUSMALLINT) pos + 1,
|
||||
SQL_PARAM_INPUT,
|
||||
getParamType(dir),
|
||||
SQL_C_BINARY,
|
||||
SQL_LONGVARBINARY,
|
||||
(SQLUINTEGER) size,
|
||||
0,
|
||||
(SQLPOINTER) val.rawContent(),
|
||||
pVal,
|
||||
(SQLINTEGER) size,
|
||||
_lengthIndicator.back())))
|
||||
{
|
||||
@ -183,8 +215,15 @@ void Binder::bind(std::size_t pos, const Poco::DateTime& val, Direction dir)
|
||||
|
||||
std::size_t Binder::parameterSize(SQLPOINTER pAddr) const
|
||||
{
|
||||
ParameterMap::const_iterator it = _inParams.find(pAddr);
|
||||
if (it != _inParams.end()) return it->second;
|
||||
ParamVec::const_iterator it = _inParams.begin();
|
||||
ParamVec::const_iterator end = _inParams.end();
|
||||
for (; it != end; ++it)
|
||||
if (it->get<0>() == pAddr) return it->get<1>();
|
||||
|
||||
it = _outParams.begin();
|
||||
end = _outParams.end();
|
||||
for (; it != end; ++it)
|
||||
if (it->get<0>() == pAddr) return it->get<1>();
|
||||
|
||||
throw NotFoundException("Requested data size not found.");
|
||||
}
|
||||
@ -210,17 +249,22 @@ SQLSMALLINT Binder::getParamType(Direction dir) const
|
||||
}
|
||||
|
||||
|
||||
void Binder::sync(Direction direction)
|
||||
void Binder::synchronize()
|
||||
{
|
||||
TimestampMap::iterator itTS = _timestamps.begin();
|
||||
TimestampMap::iterator itTSEnd = _timestamps.end();
|
||||
for(; itTS != itTSEnd; ++itTS)
|
||||
{
|
||||
if (PD_OUT == direction) // SQL_TIMESTAMP_STRUCT => DateTime
|
||||
Utility::dateTimeSync(*itTS->second, *itTS->first);
|
||||
else // DateTime => SQL_TIMESTAMP_STRUCT
|
||||
Utility::dateTimeSync(*itTS->first, *itTS->second);
|
||||
}
|
||||
Utility::dateTimeSync(*itTS->second, *itTS->first);
|
||||
|
||||
StringMap::iterator itStr = _strings.begin();
|
||||
StringMap::iterator itStrEnd = _strings.end();
|
||||
for(; itStr != itStrEnd; ++itStr)
|
||||
itStr->second->assign(itStr->first, strlen(itStr->first));
|
||||
|
||||
BLOBMap::iterator itB = _blobs.begin();
|
||||
BLOBMap::iterator itBEnd = _blobs.end();
|
||||
for(; itB != itBEnd; ++itB)
|
||||
itB->second->assignRaw(itB->first, strlen(itB->first));
|
||||
}
|
||||
|
||||
|
||||
|
@ -126,10 +126,6 @@ void ODBCStatementImpl::compileImpl()
|
||||
// these calls must occur before.
|
||||
fixupBinding(); doBind(false, true);
|
||||
|
||||
// Following code creates internal extraction storage in case when none is provided by user.
|
||||
// Under normal circumstances, this is the responsibility of the Data framework. Due to some
|
||||
// ODBC peculiarities, for ODBC it is implemented here. Data library detects this being already
|
||||
// done and does not try to do it again.
|
||||
bool dataAvailable = hasData();
|
||||
if (dataAvailable && !extractions().size())
|
||||
{
|
||||
@ -195,7 +191,9 @@ void ODBCStatementImpl::bindImpl()
|
||||
if (SQL_NEED_DATA == rc) putData();
|
||||
else checkError(rc, "SQLExecute()");
|
||||
|
||||
_pBinder->sync(Binder::PD_OUT);
|
||||
getData();
|
||||
|
||||
_pBinder->synchronize();
|
||||
}
|
||||
|
||||
|
||||
@ -215,22 +213,42 @@ void ODBCStatementImpl::putData()
|
||||
}while (SQL_NEED_DATA == (rc = SQLParamData(_stmt, &pParam)));
|
||||
|
||||
checkError(rc, "SQLParamData()");
|
||||
}
|
||||
|
||||
/* TODO: this is how manual extraction of parameters should work
|
||||
in practice, for the time being, we only support automatic binding for output params
|
||||
Binder::ParameterMap outParamMap = _pBinder->outParameters();
|
||||
Binder::ParameterMap::iterator it = outParamMap.begin();
|
||||
Binder::ParameterMap::iterator end = outParamMap.end();
|
||||
|
||||
void ODBCStatementImpl::getData()
|
||||
{
|
||||
Binder::ParamVec& outParams = _pBinder->outParameters();
|
||||
if (0 == outParams.size()) return;
|
||||
|
||||
Binder::ParamVec::iterator it = outParams.begin();
|
||||
Binder::ParamVec::iterator end = outParams.end();
|
||||
for (int i = 1; it != end; ++it, ++i)
|
||||
{
|
||||
SQLINTEGER retLen = 0;
|
||||
while (SQL_NO_DATA != (rc = SQLGetData(_stmt, i, SQL_C_TYPE_TIMESTAMP, (SQLPOINTER) (it->first + retLen), it->second - retLen, &retLen)))
|
||||
if (0 == retLen || SQL_NULL_DATA == retLen) break;
|
||||
char* ptr = (char*) it->get<0>();
|
||||
SQLINTEGER len = it->get<1>();
|
||||
//NB: Oracle SQLGetData call returns string data, but does NOT report the returned length.
|
||||
// (no other drivers tested for this functionality yet)
|
||||
// Thus, for the string length we trust ptr being zeroed when allocated in binder.
|
||||
// As a "safety net", the last member of the binder-supplied char* array is set to '\0' (see below)
|
||||
while (len > 0 && SQL_NO_DATA != (SQLGetData(_stmt, i, it->get<2>(), (SQLPOINTER) ptr, len, &retLen)))
|
||||
{
|
||||
if (0 == retLen ||
|
||||
SQL_NULL_DATA == retLen ||
|
||||
SQL_NO_TOTAL == retLen)
|
||||
break;
|
||||
|
||||
StatementException se(_stmt);
|
||||
std::cout << se.toString();
|
||||
if (ptr + retLen < ptr + len)
|
||||
{
|
||||
ptr += retLen;
|
||||
len -= retLen;
|
||||
}
|
||||
}
|
||||
|
||||
//just in case, terminate the string
|
||||
((char*) it->get<0>())[it->get<1>()-1] = '\0';
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -925,6 +925,36 @@ void ODBCOracleTest::testStoredProcedure()
|
||||
|
||||
k += 2;
|
||||
}
|
||||
|
||||
//string and BLOB for automatic binding only
|
||||
_pSession->setFeature("autoBind", true);
|
||||
|
||||
*_pSession << "CREATE OR REPLACE "
|
||||
"PROCEDURE storedProcedure(inParam IN VARCHAR2, outParam OUT VARCHAR2) IS "
|
||||
" BEGIN outParam := inParam; "
|
||||
"END storedProcedure;" , now;
|
||||
|
||||
std::string inParam = "123";
|
||||
std::string outParam;
|
||||
try{
|
||||
*_pSession << "{call storedProcedure(?,?)}", in(inParam), out(outParam), now;
|
||||
}catch(StatementException& ex){std::cout << ex.toString();}
|
||||
assert(inParam == outParam);
|
||||
dropObject("PROCEDURE", "storedProcedure");
|
||||
/*TODO - currently failing
|
||||
*_pSession << "CREATE OR REPLACE "
|
||||
"PROCEDURE storedProcedure(inParam IN BLOB, outParam OUT BLOB) IS "
|
||||
" BEGIN outParam := inParam; "
|
||||
"END storedProcedure;" , now;
|
||||
|
||||
BLOB inBLOB = "123";
|
||||
BLOB outBLOB;
|
||||
try{
|
||||
*_pSession << "{call storedProcedure(?,?)}", in(inBLOB), out(outBLOB), now;
|
||||
}catch(StatementException& ex){std::cout << ex.toString();}
|
||||
assert(inBLOB == outBLOB);
|
||||
dropObject("PROCEDURE", "storedProcedure");
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@ -937,10 +967,12 @@ void ODBCOracleTest::testStoredFunction()
|
||||
_pSession->setFeature("autoBind", bindValues[k]);
|
||||
_pSession->setFeature("autoExtract", bindValues[k+1]);
|
||||
|
||||
try{
|
||||
*_pSession << "CREATE OR REPLACE "
|
||||
"FUNCTION storedFunction RETURN NUMBER IS "
|
||||
" BEGIN return(-1); "
|
||||
" END storedFunction;" , now;
|
||||
}catch(StatementException& se) { std::cout << se.toString() << std::endl; }
|
||||
|
||||
int i = 0;
|
||||
*_pSession << "{? = call storedFunction()}", out(i), now;
|
||||
@ -997,6 +1029,23 @@ void ODBCOracleTest::testStoredFunction()
|
||||
|
||||
k += 2;
|
||||
}
|
||||
|
||||
//string and BLOB for automatic binding only
|
||||
_pSession->setFeature("autoBind", true);
|
||||
|
||||
*_pSession << "CREATE OR REPLACE "
|
||||
"FUNCTION storedFunction(inParam IN VARCHAR2, outParam OUT VARCHAR2) RETURN VARCHAR2 IS "
|
||||
" BEGIN outParam := inParam; RETURN outParam;"
|
||||
"END storedFunction;" , now;
|
||||
|
||||
std::string inParam = "123";
|
||||
std::string outParam;
|
||||
std::string ret;
|
||||
*_pSession << "{? = call storedFunction(?,?)}", out(ret), in(inParam), out(outParam), now;
|
||||
assert("123" == inParam);
|
||||
assert(inParam == outParam);
|
||||
assert(ret == outParam);
|
||||
dropObject("PROCEDURE", "storedFunction");
|
||||
}
|
||||
|
||||
|
||||
@ -1013,7 +1062,8 @@ void ODBCOracleTest::dropObject(const std::string& type, const std::string& name
|
||||
StatementDiagnostics::Iterator it = flds.begin();
|
||||
for (; it != flds.end(); ++it)
|
||||
{
|
||||
if (942 == it->_nativeError)//ORA-00942 (table does not exist)
|
||||
if (4043 == it->_nativeError || //ORA-04043 (object does not exist)
|
||||
942 == it->_nativeError)//ORA-00942 (table does not exist)
|
||||
{
|
||||
ignoreError = true;
|
||||
break;
|
||||
|
@ -136,6 +136,7 @@ inline const std::vector<char>& BLOB::content() const
|
||||
|
||||
inline const char* BLOB::rawContent() const
|
||||
{
|
||||
poco_assert (_pContent->size());
|
||||
return &(*_pContent)[0];
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,8 @@
|
||||
#include "Poco/Format.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
@ -239,13 +241,54 @@ private:
|
||||
void resetExtraction();
|
||||
/// Resets binding so it can be reused again.
|
||||
|
||||
template <class T, class C>
|
||||
template <class T>
|
||||
void addInternalExtract(const MetaColumn& mc)
|
||||
/// Utility function to create and add an internal extraction.
|
||||
/// Creates and adds the internal extraction.
|
||||
///
|
||||
/// The decision about internal extraction container is done
|
||||
/// in a following way:
|
||||
///
|
||||
/// If this statement has _storage member set, that setting
|
||||
/// overrides the session setting for storage, otherwise the
|
||||
/// session setting is used.
|
||||
/// If neither this statement nor the session have the storage
|
||||
/// type set, std::vector is the default container type used.
|
||||
{
|
||||
C* pData = new C;
|
||||
Column<T,C>* pCol = new Column<T,C>(mc, pData);
|
||||
addExtract(new InternalExtraction<T,C>(*pData, pCol));
|
||||
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.empty()) storage = VECTOR;
|
||||
|
||||
if (0 == icompare(VECTOR, storage))
|
||||
{
|
||||
std::vector<T>* pData = new std::vector<T>;
|
||||
Column<T,std::vector<T> >* pCol = new Column<T, std::vector<T> >(mc, pData);
|
||||
addExtract(new InternalExtraction<T, std::vector<T> >(*pData, pCol));
|
||||
}
|
||||
else if (0 == icompare(LIST, storage))
|
||||
{
|
||||
std::list<T>* pData = new std::list<T>;
|
||||
Column<T,std::list<T> >* pCol = new Column<T, std::list<T> >(mc, pData);
|
||||
addExtract(new InternalExtraction<T, std::list<T> >(*pData, pCol));
|
||||
}
|
||||
else if (0 == icompare(DEQUE, storage))
|
||||
{
|
||||
std::deque<T>* pData = new std::deque<T>;
|
||||
Column<T,std::deque<T> >* pCol = new Column<T, std::deque<T> >(mc, pData);
|
||||
addExtract(new InternalExtraction<T, std::deque<T> >(*pData, pCol));
|
||||
}
|
||||
}
|
||||
|
||||
StatementImpl(const StatementImpl& stmt);
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include "Poco/Data/Extraction.h"
|
||||
#include "Poco/Data/BLOB.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/DateTime.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
@ -283,20 +283,6 @@ void StatementImpl::setStorage(const std::string& storage)
|
||||
|
||||
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);
|
||||
@ -304,101 +290,31 @@ void StatementImpl::makeExtractors(Poco::UInt32 count)
|
||||
{
|
||||
case MetaColumn::FDT_BOOL:
|
||||
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;
|
||||
addInternalExtract<Int8>(mc); break;
|
||||
case MetaColumn::FDT_UINT8:
|
||||
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;
|
||||
addInternalExtract<UInt8>(mc); break;
|
||||
case MetaColumn::FDT_INT16:
|
||||
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;
|
||||
addInternalExtract<Int16>(mc); break;
|
||||
case MetaColumn::FDT_UINT16:
|
||||
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;
|
||||
addInternalExtract<UInt16>(mc); break;
|
||||
case MetaColumn::FDT_INT32:
|
||||
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;
|
||||
addInternalExtract<Int32>(mc); break;
|
||||
case MetaColumn::FDT_UINT32:
|
||||
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;
|
||||
addInternalExtract<UInt32>(mc); break;
|
||||
case MetaColumn::FDT_INT64:
|
||||
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;
|
||||
addInternalExtract<Int64>(mc); break;
|
||||
case MetaColumn::FDT_UINT64:
|
||||
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;
|
||||
addInternalExtract<UInt64>(mc); break;
|
||||
case MetaColumn::FDT_FLOAT:
|
||||
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;
|
||||
addInternalExtract<float>(mc); break;
|
||||
case MetaColumn::FDT_DOUBLE:
|
||||
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;
|
||||
addInternalExtract<double>(mc); break;
|
||||
case MetaColumn::FDT_STRING:
|
||||
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;
|
||||
addInternalExtract<std::string>(mc); break;
|
||||
case MetaColumn::FDT_BLOB:
|
||||
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;
|
||||
addInternalExtract<BLOB>(mc); break;
|
||||
case MetaColumn::FDT_TIMESTAMP:
|
||||
addInternalExtract<DateTime>(mc); break;
|
||||
default:
|
||||
throw Poco::InvalidArgumentException("Data type not supported.");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user