From 23d7d2c6cb1edbde2c7e1a2a9d2fc23460518ece Mon Sep 17 00:00:00 2001 From: Ostropik Date: Sat, 7 Oct 2017 02:32:29 +0300 Subject: [PATCH] fix ODBC: losing input data in case PD_IN_OUT paramater type (#1280) * fix: losing input data in case PD_IN_OUT paramater type * - fix allso applied for wide string - added test case 'testStoredProcedureAnyString()' for reproducing --- Data/ODBC/src/Binder.cpp | 6 ++++++ Data/ODBC/testsuite/src/ODBCOracleTest.cpp | 15 +++++++++++++++ Data/ODBC/testsuite/src/ODBCOracleTest.h | 1 + Data/include/Poco/Data/AbstractBinder.h | 7 +++++++ 4 files changed, 29 insertions(+) diff --git a/Data/ODBC/src/Binder.cpp b/Data/ODBC/src/Binder.cpp index 53deaaa1d..92aeac83c 100644 --- a/Data/ODBC/src/Binder.cpp +++ b/Data/ODBC/src/Binder.cpp @@ -185,6 +185,10 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir, const { getColumnOrParameterSize(pos, size); char* pChar = (char*) std::calloc(size, sizeof(char)); + + if (isInOutBound(dir)) + std::strcpy(pChar,val.c_str()); + pVal = (SQLPOINTER) pChar; _outParams.insert(ParamMap::value_type(pVal, size)); _strings.insert(StringMap::value_type(pChar, const_cast(&val))); @@ -240,6 +244,8 @@ void Binder::bind(std::size_t pos, const UTF16String& val, Direction dir, const getColumnOrParameterSize(pos, size); CharT* pChar = (CharT*)std::calloc(size, sizeof(CharT)); pVal = (SQLPOINTER)pChar; + if (isInOutBound(dir)) + std::wcscpy(pChar,val.c_str()); _outParams.insert(ParamMap::value_type(pVal, size)); _utf16Strings.insert(UTF16StringMap::value_type(pChar, const_cast(&val))); } diff --git a/Data/ODBC/testsuite/src/ODBCOracleTest.cpp b/Data/ODBC/testsuite/src/ODBCOracleTest.cpp index 4ddad4f24..535320c13 100644 --- a/Data/ODBC/testsuite/src/ODBCOracleTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCOracleTest.cpp @@ -355,6 +355,20 @@ void ODBCOracleTest::testStoredProcedureAny() } } +void ODBCOracleTest::testStoredProcedureAnyString() +{ + Any sInOut = std::string("Hello"); + + *_pSession << "CREATE OR REPLACE " + "PROCEDURE storedProcedure(inParam IN OUT VARCHAR2) IS " + " BEGIN inParam := inParam||' world!'; " + "END storedProcedure;" , now; + + *_pSession << "{call storedProcedure(?)}", io(sInOut), now; + assert("Hello world!" == AnyCast(sInOut)); + *_pSession << "DROP PROCEDURE storedProcedure;", now; +} + void ODBCOracleTest::testStoredProcedureDynamicAny() { @@ -933,6 +947,7 @@ CppUnit::Test* ODBCOracleTest::suite() CppUnit_addTest(pSuite, ODBCOracleTest, testStoredProcedure); CppUnit_addTest(pSuite, ODBCOracleTest, testCursorStoredProcedure); CppUnit_addTest(pSuite, ODBCOracleTest, testStoredProcedureAny); + CppUnit_addTest(pSuite, ODBCOracleTest, testStoredProcedureAnyString); CppUnit_addTest(pSuite, ODBCOracleTest, testStoredProcedureDynamicAny); CppUnit_addTest(pSuite, ODBCOracleTest, testStoredFunction); CppUnit_addTest(pSuite, ODBCOracleTest, testCursorStoredFunction); diff --git a/Data/ODBC/testsuite/src/ODBCOracleTest.h b/Data/ODBC/testsuite/src/ODBCOracleTest.h index d1f724744..ecf61c8e9 100644 --- a/Data/ODBC/testsuite/src/ODBCOracleTest.h +++ b/Data/ODBC/testsuite/src/ODBCOracleTest.h @@ -45,6 +45,7 @@ public: void testStoredFunction(); void testCursorStoredFunction(); void testStoredProcedureAny(); + void testStoredProcedureAnyString(); void testStoredProcedureDynamicAny(); void testAutoTransaction(); diff --git a/Data/include/Poco/Data/AbstractBinder.h b/Data/include/Poco/Data/AbstractBinder.h index 361a5dc6c..043c76cb0 100644 --- a/Data/include/Poco/Data/AbstractBinder.h +++ b/Data/include/Poco/Data/AbstractBinder.h @@ -405,6 +405,9 @@ public: static bool isInBound(Direction dir); /// Returns true if direction is in bound; + + static bool isInOutBound(Direction dir); + /// Returns true if direction is in and out bound; }; @@ -422,6 +425,10 @@ inline bool AbstractBinder::isOutBound(Direction dir) return PD_OUT == dir || PD_IN_OUT == dir; } +inline bool AbstractBinder::isInOutBound(Direction dir) +{ + return PD_IN_OUT == dir; +} inline bool AbstractBinder::isInBound(Direction dir) {