mirror of
https://github.com/pocoproject/poco.git
synced 2025-01-23 02:28:59 +01:00
* Fix for issue #1043 The fix for this issue was partially implemented in development branch. However, there are still some issue, that were not covered: 1. The std::string overload will sets SQL_LONGVARCHAR as fSqlType if the output parameter is of type VARCHAR(MAX) 2. The UTF16String overload of bind method: a) always resolves fSqlType using the size of formal parameter const std::string& val. b) allocates half of the size of the SP's output parameter. 3. The _utf16Strings member is not sychronized in Binder::synchronize() method. 4. The _utf16Strings member is not reset in Binder::reset() method. * Fixed compiler error for GCC Fixed compiler error caused by improper getting of UTF16String length in Binder::synchronize() * Fix input param initialization in unit test
This commit is contained in:
parent
3dfcc83257
commit
262079b0f0
@ -111,6 +111,13 @@ void Binder::freeMemory()
|
||||
for (; itStr != itStrEnd; ++itStr) std::free(itStr->first);
|
||||
}
|
||||
|
||||
if (_utf16Strings.size() > 0)
|
||||
{
|
||||
UTF16StringMap::iterator itStr = _utf16Strings.begin();
|
||||
UTF16StringMap::iterator itStrEnd = _utf16Strings.end();
|
||||
for (; itStr != itStrEnd; ++itStr) std::free(itStr->first);
|
||||
}
|
||||
|
||||
if (_charPtrs.size() > 0)
|
||||
{
|
||||
CharPtrVec::iterator itChr = _charPtrs.begin();
|
||||
@ -172,7 +179,6 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir, const
|
||||
SQLPOINTER pVal = 0;
|
||||
SQLINTEGER size = (SQLINTEGER) val.size();
|
||||
|
||||
SQLSMALLINT sqType = SQL_LONGVARCHAR;
|
||||
if (isOutBound(dir))
|
||||
{
|
||||
getColumnOrParameterSize(pos, size);
|
||||
@ -180,13 +186,11 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir, const
|
||||
pVal = (SQLPOINTER) pChar;
|
||||
_outParams.insert(ParamMap::value_type(pVal, size));
|
||||
_strings.insert(StringMap::value_type(pChar, const_cast<std::string*>(&val)));
|
||||
if (size < _maxCharColLength) sqType = SQL_VARCHAR;
|
||||
}
|
||||
else if (isInBound(dir))
|
||||
{
|
||||
pVal = (SQLPOINTER) val.c_str();
|
||||
_inParams.insert(ParamMap::value_type(pVal, size));
|
||||
if (size < _maxCharColLength) sqType = SQL_VARCHAR;
|
||||
}
|
||||
else
|
||||
throw InvalidArgumentException("Parameter must be [in] OR [out] bound.");
|
||||
@ -204,6 +208,8 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir, const
|
||||
|
||||
_lengthIndicator.push_back(pLenIn);
|
||||
|
||||
SQLSMALLINT sqType = (size <= _maxCharColLength) ? SQL_VARCHAR : SQL_LONGVARCHAR;
|
||||
|
||||
if (Utility::isError(SQLBindParameter(_rStmt,
|
||||
(SQLUSMALLINT) pos + 1,
|
||||
toODBCDirection(dir),
|
||||
@ -226,11 +232,11 @@ void Binder::bind(std::size_t pos, const UTF16String& val, Direction dir, const
|
||||
|
||||
SQLPOINTER pVal = 0;
|
||||
SQLINTEGER size = (SQLINTEGER)(val.size() * sizeof(CharT));
|
||||
SQLSMALLINT sqType = (val.size() < _maxWCharColLength) ? SQL_WVARCHAR : SQL_WLONGVARCHAR;
|
||||
|
||||
if (isOutBound(dir))
|
||||
{
|
||||
getColumnOrParameterSize(pos, size);
|
||||
CharT* pChar = (CharT*)std::calloc(size, 1);
|
||||
CharT* pChar = (CharT*)std::calloc(size, sizeof(CharT));
|
||||
pVal = (SQLPOINTER)pChar;
|
||||
_outParams.insert(ParamMap::value_type(pVal, size));
|
||||
_utf16Strings.insert(UTF16StringMap::value_type(pChar, const_cast<UTF16String*>(&val)));
|
||||
@ -259,6 +265,8 @@ void Binder::bind(std::size_t pos, const UTF16String& val, Direction dir, const
|
||||
|
||||
_lengthIndicator.push_back(pLenIn);
|
||||
|
||||
SQLSMALLINT sqType = (size <= _maxWCharColLength) ? SQL_WVARCHAR : SQL_WLONGVARCHAR;
|
||||
|
||||
if (Utility::isError(SQLBindParameter(_rStmt,
|
||||
(SQLUSMALLINT)pos + 1,
|
||||
toODBCDirection(dir),
|
||||
@ -478,6 +486,14 @@ void Binder::synchronize()
|
||||
it->second->assign(it->first, std::strlen(it->first));
|
||||
}
|
||||
|
||||
if (_utf16Strings.size())
|
||||
{
|
||||
UTF16StringMap::iterator it = _utf16Strings.begin();
|
||||
UTF16StringMap::iterator end = _utf16Strings.end();
|
||||
for (; it != end; ++it)
|
||||
it->second->assign(it->first, UTF16CharTraits::length((UTF16CharTraits::char_type*)it->first));
|
||||
}
|
||||
|
||||
if (_nullCbMap.size())
|
||||
{
|
||||
NullCbMap::iterator it = _nullCbMap.begin();
|
||||
@ -506,6 +522,8 @@ void Binder::reset()
|
||||
_timestamps.clear();
|
||||
if (_strings.size() > 0)
|
||||
_strings.clear();
|
||||
if (_utf16Strings.size() > 0)
|
||||
_utf16Strings.clear();
|
||||
if (_dateVecVec.size() > 0)
|
||||
_dateVecVec.clear();
|
||||
if (_timeVecVec.size() > 0)
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "Poco/Any.h"
|
||||
#include "Poco/DynamicAny.h"
|
||||
#include "Poco/Tuple.h"
|
||||
#include "Poco/UTFString.h"
|
||||
#include "Poco/DateTime.h"
|
||||
#include "Poco/Data/RecordSet.h"
|
||||
#include "Poco/Data/ODBC/Diagnostics.h"
|
||||
@ -41,6 +42,7 @@ using Poco::Any;
|
||||
using Poco::AnyCast;
|
||||
using Poco::DynamicAny;
|
||||
using Poco::DateTime;
|
||||
using Poco::UTF16String;
|
||||
|
||||
|
||||
// uncomment to force FreeTDS on Windows
|
||||
@ -297,27 +299,47 @@ void ODBCSQLServerTest::testStoredProcedure()
|
||||
|
||||
k += 2;
|
||||
}
|
||||
/*TODO - currently fails with following error:
|
||||
|
||||
[Microsoft][ODBC SQL Server Driver][SQL Server]Invalid parameter
|
||||
2 (''): Data type 0x23 is a deprecated large object, or LOB, but is marked as output parameter.
|
||||
Deprecated types are not supported as output parameters. Use current large object types instead.
|
||||
{
|
||||
session().setFeature("autoBind", true);
|
||||
session() << "CREATE PROCEDURE storedProcedure(@inParam VARCHAR(MAX), @outParam VARCHAR(MAX) OUTPUT) AS "
|
||||
"BEGIN "
|
||||
"SET @outParam = @inParam; "
|
||||
"END;"
|
||||
, now;
|
||||
|
||||
session().setFeature("autoBind", true);
|
||||
session() << "CREATE PROCEDURE storedProcedure(@inParam VARCHAR(MAX), @outParam VARCHAR(MAX) OUTPUT) AS "
|
||||
"BEGIN "
|
||||
"SET @outParam = @inParam; "
|
||||
"END;"
|
||||
, now;
|
||||
std::string inParam = "123";
|
||||
std::string outParam;
|
||||
try {
|
||||
session() << "{call storedProcedure(?, ?)}", in(inParam), out(outParam), now;
|
||||
}
|
||||
catch(StatementException& ex) {
|
||||
std::cout << ex.toString();
|
||||
}
|
||||
assert(outParam == inParam);
|
||||
dropObject("PROCEDURE", "storedProcedure");
|
||||
}
|
||||
|
||||
std::string inParam = "123";
|
||||
std::string outParam;
|
||||
try{
|
||||
session() << "{call storedProcedure(?, ?)}", in(inParam), out(outParam), now;
|
||||
}catch(StatementException& ex){std::cout << ex.toString();}
|
||||
assert(outParam == inParam);
|
||||
dropObject("PROCEDURE", "storedProcedure");
|
||||
*/
|
||||
{
|
||||
session().setFeature("autoBind", true);
|
||||
session() << "CREATE PROCEDURE storedProcedure(@inParam NVARCHAR(MAX), @outParam NVARCHAR(MAX) OUTPUT) AS "
|
||||
"BEGIN "
|
||||
"SET @outParam = @inParam; "
|
||||
"END;"
|
||||
, now;
|
||||
|
||||
UTF16String::value_type cs[] = { L'1', L'2', L'3', L'\0' };
|
||||
UTF16String inParam(cs);
|
||||
UTF16String outParam;
|
||||
try {
|
||||
session() << "{call storedProcedure(?, ?)}", in(inParam), out(outParam), now;
|
||||
}
|
||||
catch (StatementException& ex) {
|
||||
std::cout << ex.toString();
|
||||
}
|
||||
assert(outParam == inParam);
|
||||
dropObject("PROCEDURE", "storedProcedure");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user