Stored procedure support

This commit is contained in:
Aleksandar Fabijanic 2007-05-25 22:15:46 +00:00
parent 2bb4746848
commit 911d0c5b82
8 changed files with 209 additions and 8 deletions

View File

@ -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,

View File

@ -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;

View File

@ -117,6 +117,7 @@ public:
void testInternalExtraction();
void testStoredProcedure();
void testStoredFunction();
void setUp();
void tearDown();

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -41,7 +41,9 @@ namespace Poco {
namespace Data {
AbstractBinder::AbstractBinder()
AbstractBinder::AbstractBinder():
_inBound(true),
_outBound(false)
{
}

View File

@ -42,7 +42,9 @@ namespace Data {
AbstractBinding::AbstractBinding():
_pBinder(0)
_pBinder(0),
_inBound(true),
_outBound(false)
{
}