mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-12 18:20:26 +01:00
Stored procedure support
This commit is contained in:
parent
2bb4746848
commit
911d0c5b82
@ -165,9 +165,17 @@ private:
|
||||
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,
|
||||
(SQLUSMALLINT) pos + 1,
|
||||
SQL_PARAM_INPUT,
|
||||
ioType,
|
||||
cDataType,
|
||||
sqlDataType,
|
||||
columnSize,
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "CppUnit/TestCaller.h"
|
||||
#include "CppUnit/TestSuite.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Tuple.h"
|
||||
#include "Poco/Format.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Data/Common.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;
|
||||
|
||||
|
||||
@ -827,7 +829,98 @@ void ODBCOracleTest::testInternalExtraction()
|
||||
|
||||
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, testTupleVector);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testStoredProcedure);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testStoredFunction);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testInternalExtraction);
|
||||
|
||||
return pSuite;
|
||||
|
@ -117,6 +117,7 @@ public:
|
||||
|
||||
void testInternalExtraction();
|
||||
void testStoredProcedure();
|
||||
void testStoredFunction();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
@ -106,9 +106,52 @@ public:
|
||||
|
||||
virtual void bind(std::size_t pos, const BLOB& val) = 0;
|
||||
/// 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
|
||||
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
||||
|
||||
|
||||
#include "Poco/Data/Data.h"
|
||||
#include "Poco/Data/AbstractBinder.h"
|
||||
#include "Poco/Any.h"
|
||||
#include "Poco/RefCountedObject.h"
|
||||
#include "Poco/AutoPtr.h"
|
||||
@ -52,9 +53,6 @@ namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
|
||||
class AbstractBinder;
|
||||
|
||||
|
||||
class Data_API AbstractBinding: public Poco::RefCountedObject
|
||||
/// AbstractBinding connects a value with a placeholder via an AbstractBinder interface.
|
||||
{
|
||||
@ -92,8 +90,16 @@ public:
|
||||
virtual void reset() = 0;
|
||||
/// 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:
|
||||
AbstractBinder* _pBinder;
|
||||
bool _inBound;
|
||||
bool _outBound;
|
||||
};
|
||||
|
||||
|
||||
@ -106,7 +112,11 @@ typedef std::vector<AbstractBindingPtr> AbstractBindingVec;
|
||||
//
|
||||
inline void AbstractBinding::setBinder(AbstractBinder* pBinder)
|
||||
{
|
||||
poco_check_ptr (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
|
||||
|
||||
|
||||
|
@ -478,7 +478,36 @@ private:
|
||||
template <typename T> Binding<T>* use(const T& t)
|
||||
/// 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 {
|
||||
|
||||
|
||||
AbstractBinder::AbstractBinder()
|
||||
AbstractBinder::AbstractBinder():
|
||||
_inBound(true),
|
||||
_outBound(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,9 @@ namespace Data {
|
||||
|
||||
|
||||
AbstractBinding::AbstractBinding():
|
||||
_pBinder(0)
|
||||
_pBinder(0),
|
||||
_inBound(true),
|
||||
_outBound(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user