mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-14 11:06:57 +01:00
Stored procedure support
This commit is contained in:
parent
2bb4746848
commit
911d0c5b82
@ -165,9 +165,17 @@ private:
|
|||||||
catch (StatementException&) { }
|
catch (StatementException&) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool in = isInBound();
|
||||||
|
bool out = isOutBound();
|
||||||
|
SQLSMALLINT ioType = SQL_PARAM_TYPE_UNKNOWN;
|
||||||
|
if (in && out) ioType = SQL_PARAM_INPUT_OUTPUT;
|
||||||
|
else if(in) ioType = SQL_PARAM_INPUT;
|
||||||
|
else if(out) ioType = SQL_PARAM_OUTPUT;
|
||||||
|
else throw Poco::IllegalStateException("Binder not bound (must be [in] OR [out]).");
|
||||||
|
|
||||||
if (Utility::isError(SQLBindParameter(_rStmt,
|
if (Utility::isError(SQLBindParameter(_rStmt,
|
||||||
(SQLUSMALLINT) pos + 1,
|
(SQLUSMALLINT) pos + 1,
|
||||||
SQL_PARAM_INPUT,
|
ioType,
|
||||||
cDataType,
|
cDataType,
|
||||||
sqlDataType,
|
sqlDataType,
|
||||||
columnSize,
|
columnSize,
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "CppUnit/TestCaller.h"
|
#include "CppUnit/TestCaller.h"
|
||||||
#include "CppUnit/TestSuite.h"
|
#include "CppUnit/TestSuite.h"
|
||||||
#include "Poco/String.h"
|
#include "Poco/String.h"
|
||||||
|
#include "Poco/Tuple.h"
|
||||||
#include "Poco/Format.h"
|
#include "Poco/Format.h"
|
||||||
#include "Poco/Exception.h"
|
#include "Poco/Exception.h"
|
||||||
#include "Poco/Data/Common.h"
|
#include "Poco/Data/Common.h"
|
||||||
@ -54,6 +55,7 @@ using Poco::Data::ODBC::ConnectionException;
|
|||||||
using Poco::Data::ODBC::StatementException;
|
using Poco::Data::ODBC::StatementException;
|
||||||
using Poco::Data::ODBC::StatementDiagnostics;
|
using Poco::Data::ODBC::StatementDiagnostics;
|
||||||
using Poco::format;
|
using Poco::format;
|
||||||
|
using Poco::Tuple;
|
||||||
using Poco::NotFoundException;
|
using Poco::NotFoundException;
|
||||||
|
|
||||||
|
|
||||||
@ -827,7 +829,98 @@ void ODBCOracleTest::testInternalExtraction()
|
|||||||
|
|
||||||
void ODBCOracleTest::testStoredProcedure()
|
void ODBCOracleTest::testStoredProcedure()
|
||||||
{
|
{
|
||||||
//TODO
|
*_pSession << "CREATE OR REPLACE "
|
||||||
|
"PROCEDURE storedProcedure(outParam OUT NUMBER) IS "
|
||||||
|
" BEGIN outParam := -1; "
|
||||||
|
"END 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(inParam IN NUMBER, outParam OUT NUMBER) IS "
|
||||||
|
" BEGIN outParam := inParam*inParam; "
|
||||||
|
"END 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ODBCOracleTest::testStoredFunction()
|
||||||
|
{
|
||||||
|
*_pSession << "CREATE OR REPLACE "
|
||||||
|
"FUNCTION storedFunction RETURN NUMBER IS "
|
||||||
|
" BEGIN return(-1); "
|
||||||
|
" END storedFunction;" , now;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
*_pSession << "{? = call storedFunction()}", out(i), now;
|
||||||
|
assert(-1 == i);
|
||||||
|
*_pSession << "DROP FUNCTION storedFunction;", now;
|
||||||
|
|
||||||
|
*_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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1081,6 +1174,7 @@ CppUnit::Test* ODBCOracleTest::suite()
|
|||||||
CppUnit_addTest(pSuite, ODBCOracleTest, testTuple);
|
CppUnit_addTest(pSuite, ODBCOracleTest, testTuple);
|
||||||
CppUnit_addTest(pSuite, ODBCOracleTest, testTupleVector);
|
CppUnit_addTest(pSuite, ODBCOracleTest, testTupleVector);
|
||||||
CppUnit_addTest(pSuite, ODBCOracleTest, testStoredProcedure);
|
CppUnit_addTest(pSuite, ODBCOracleTest, testStoredProcedure);
|
||||||
|
CppUnit_addTest(pSuite, ODBCOracleTest, testStoredFunction);
|
||||||
CppUnit_addTest(pSuite, ODBCOracleTest, testInternalExtraction);
|
CppUnit_addTest(pSuite, ODBCOracleTest, testInternalExtraction);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
|
@ -117,6 +117,7 @@ public:
|
|||||||
|
|
||||||
void testInternalExtraction();
|
void testInternalExtraction();
|
||||||
void testStoredProcedure();
|
void testStoredProcedure();
|
||||||
|
void testStoredFunction();
|
||||||
|
|
||||||
void setUp();
|
void setUp();
|
||||||
void tearDown();
|
void tearDown();
|
||||||
|
@ -106,9 +106,52 @@ public:
|
|||||||
|
|
||||||
virtual void bind(std::size_t pos, const BLOB& val) = 0;
|
virtual void bind(std::size_t pos, const BLOB& val) = 0;
|
||||||
/// Binds a BLOB.
|
/// Binds a BLOB.
|
||||||
|
|
||||||
|
bool isInBound() const;
|
||||||
|
/// Returns true if binder is in-bound.
|
||||||
|
|
||||||
|
bool isOutBound() const;
|
||||||
|
/// Returns true if binder is out-bound.
|
||||||
|
|
||||||
|
void setInBound(bool inBound = true);
|
||||||
|
/// If inBound is true, binder is set to be in-bound.
|
||||||
|
|
||||||
|
void setOutBound(bool outBound = true);
|
||||||
|
/// If outBound is true, binder is set to be out-bound.
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool _inBound;
|
||||||
|
bool _outBound;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// inlines
|
||||||
|
///
|
||||||
|
inline bool AbstractBinder::isInBound() const
|
||||||
|
{
|
||||||
|
return _inBound;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool AbstractBinder::isOutBound() const
|
||||||
|
{
|
||||||
|
return _outBound;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void AbstractBinder::setInBound(bool inBound)
|
||||||
|
{
|
||||||
|
_inBound = inBound;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void AbstractBinder::setOutBound(bool outBound)
|
||||||
|
{
|
||||||
|
_outBound = outBound;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Data
|
} } // namespace Poco::Data
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Poco/Data/Data.h"
|
#include "Poco/Data/Data.h"
|
||||||
|
#include "Poco/Data/AbstractBinder.h"
|
||||||
#include "Poco/Any.h"
|
#include "Poco/Any.h"
|
||||||
#include "Poco/RefCountedObject.h"
|
#include "Poco/RefCountedObject.h"
|
||||||
#include "Poco/AutoPtr.h"
|
#include "Poco/AutoPtr.h"
|
||||||
@ -52,9 +53,6 @@ namespace Poco {
|
|||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
|
|
||||||
class AbstractBinder;
|
|
||||||
|
|
||||||
|
|
||||||
class Data_API AbstractBinding: public Poco::RefCountedObject
|
class Data_API AbstractBinding: public Poco::RefCountedObject
|
||||||
/// AbstractBinding connects a value with a placeholder via an AbstractBinder interface.
|
/// AbstractBinding connects a value with a placeholder via an AbstractBinder interface.
|
||||||
{
|
{
|
||||||
@ -92,8 +90,16 @@ public:
|
|||||||
virtual void reset() = 0;
|
virtual void reset() = 0;
|
||||||
/// Allows a binding to be reused.
|
/// Allows a binding to be reused.
|
||||||
|
|
||||||
|
void setInBound(bool inBound = true);
|
||||||
|
/// Sets the binder to be in-bound.
|
||||||
|
|
||||||
|
void setOutBound(bool outBound = true);
|
||||||
|
/// Sets the binder to be out-bound.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AbstractBinder* _pBinder;
|
AbstractBinder* _pBinder;
|
||||||
|
bool _inBound;
|
||||||
|
bool _outBound;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -106,7 +112,11 @@ typedef std::vector<AbstractBindingPtr> AbstractBindingVec;
|
|||||||
//
|
//
|
||||||
inline void AbstractBinding::setBinder(AbstractBinder* pBinder)
|
inline void AbstractBinding::setBinder(AbstractBinder* pBinder)
|
||||||
{
|
{
|
||||||
|
poco_check_ptr (pBinder);
|
||||||
_pBinder = pBinder;
|
_pBinder = pBinder;
|
||||||
|
_pBinder->setInBound(_inBound);
|
||||||
|
_pBinder->setOutBound(_outBound);
|
||||||
|
poco_assert_dbg (_inBound || _outBound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -116,6 +126,18 @@ inline AbstractBinder* AbstractBinding::getBinder() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void AbstractBinding::setInBound(bool inBound)
|
||||||
|
{
|
||||||
|
_inBound = inBound;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void AbstractBinding::setOutBound(bool outBound)
|
||||||
|
{
|
||||||
|
_outBound = outBound;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Data
|
} } // namespace Poco::Data
|
||||||
|
|
||||||
|
|
||||||
|
@ -478,7 +478,36 @@ private:
|
|||||||
template <typename T> Binding<T>* use(const T& t)
|
template <typename T> Binding<T>* use(const T& t)
|
||||||
/// Convenience function for a more compact Binding creation.
|
/// Convenience function for a more compact Binding creation.
|
||||||
{
|
{
|
||||||
return new Binding<T>(t);
|
Binding<T>* pB = new Binding<T>(t);
|
||||||
|
poco_check_ptr (pB);
|
||||||
|
return pB;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T> Binding<T>* in(const T& t)
|
||||||
|
/// Convenience function for a more compact Binding creation.
|
||||||
|
{
|
||||||
|
return use(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T> Binding<T>* out(const T& t)
|
||||||
|
/// Convenience function for a more compact Binding creation.
|
||||||
|
{
|
||||||
|
Binding<T>* pB = use(t);
|
||||||
|
pB->setInBound(false);
|
||||||
|
pB->setOutBound(true);
|
||||||
|
return pB;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T> Binding<T>* io(const T& t)
|
||||||
|
/// Convenience function for a more compact Binding creation.
|
||||||
|
{
|
||||||
|
Binding<T>* pB = use(t);
|
||||||
|
pB->setInBound(true);
|
||||||
|
pB->setOutBound(true);
|
||||||
|
return pB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,7 +41,9 @@ namespace Poco {
|
|||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
|
|
||||||
AbstractBinder::AbstractBinder()
|
AbstractBinder::AbstractBinder():
|
||||||
|
_inBound(true),
|
||||||
|
_outBound(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,9 @@ namespace Data {
|
|||||||
|
|
||||||
|
|
||||||
AbstractBinding::AbstractBinding():
|
AbstractBinding::AbstractBinding():
|
||||||
_pBinder(0)
|
_pBinder(0),
|
||||||
|
_inBound(true),
|
||||||
|
_outBound(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user