mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-27 19:10:20 +01:00
support for stored procedures returning recordset
This commit is contained in:
@@ -118,6 +118,16 @@ private:
|
|||||||
void doBind(bool clear = true, bool reset = false);
|
void doBind(bool clear = true, bool reset = false);
|
||||||
/// Binds parameters.
|
/// Binds parameters.
|
||||||
|
|
||||||
|
void makeInternalExtractors();
|
||||||
|
/// Creates internal extractors if none were supplied from the user.
|
||||||
|
|
||||||
|
void doPrepare();
|
||||||
|
/// Prepares placeholders for data returned by statement.
|
||||||
|
/// It is called during statement compilation for SQL statements
|
||||||
|
/// returning data. For stored procedures returning datasets,
|
||||||
|
/// it is called upon the first check for data availability
|
||||||
|
/// (see hasNext() function).
|
||||||
|
|
||||||
bool hasData() const;
|
bool hasData() const;
|
||||||
/// Returns true if statement returns data.
|
/// Returns true if statement returns data.
|
||||||
|
|
||||||
@@ -133,12 +143,6 @@ private:
|
|||||||
void fillColumns();
|
void fillColumns();
|
||||||
void checkError(SQLRETURN rc, const std::string& msg="");
|
void checkError(SQLRETURN rc, const std::string& msg="");
|
||||||
|
|
||||||
bool isStoredProcedure() const;
|
|
||||||
/// Returns true if this statement is stored procedure.
|
|
||||||
/// Only the ODBC CALL escape sequence is supported.
|
|
||||||
/// The function checks whether trimmed statement
|
|
||||||
/// text begins with '{' and ends with '}';
|
|
||||||
|
|
||||||
const SQLHDBC& _rConnection;
|
const SQLHDBC& _rConnection;
|
||||||
const StatementHandle _stmt;
|
const StatementHandle _stmt;
|
||||||
Poco::SharedPtr<Preparation> _pPreparation;
|
Poco::SharedPtr<Preparation> _pPreparation;
|
||||||
@@ -147,6 +151,7 @@ private:
|
|||||||
bool _stepCalled;
|
bool _stepCalled;
|
||||||
int _nextResponse;
|
int _nextResponse;
|
||||||
ColumnPtrVec _columnPtrs;
|
ColumnPtrVec _columnPtrs;
|
||||||
|
bool _prepared;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -177,7 +182,7 @@ inline Poco::UInt32 ODBCStatementImpl::columnsReturned() const
|
|||||||
inline bool ODBCStatementImpl::hasData() const
|
inline bool ODBCStatementImpl::hasData() const
|
||||||
{
|
{
|
||||||
poco_assert_dbg (_pPreparation);
|
poco_assert_dbg (_pPreparation);
|
||||||
return (_pPreparation->columns(!isStoredProcedure()) > 0);
|
return (_pPreparation->columns() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -150,9 +150,9 @@ public:
|
|||||||
void prepare(std::size_t pos, const Poco::Any&);
|
void prepare(std::size_t pos, const Poco::Any&);
|
||||||
/// Prepares an Any.
|
/// Prepares an Any.
|
||||||
|
|
||||||
std::size_t columns(bool resize = true) const;
|
std::size_t columns() const;
|
||||||
/// Returns the number of columns.
|
/// Returns the number of columns.
|
||||||
/// Resizes the internal storage iff resize is true.
|
/// Resizes the internal storage iff the size is zero.
|
||||||
|
|
||||||
Poco::Any& operator [] (std::size_t pos);
|
Poco::Any& operator [] (std::size_t pos);
|
||||||
/// Returns reference to column data.
|
/// Returns reference to column data.
|
||||||
@@ -337,25 +337,6 @@ inline void Preparation::prepare(std::size_t pos, const Poco::DateTime&)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline std::size_t Preparation::maxDataSize(std::size_t pos) const
|
|
||||||
{
|
|
||||||
poco_assert (pos >= 0 && pos < _pValues.size());
|
|
||||||
|
|
||||||
std::size_t sz = 0;
|
|
||||||
std::size_t maxsz = getMaxFieldSize();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
sz = ODBCColumn(_rStmt, pos).length();
|
|
||||||
}
|
|
||||||
catch (StatementException&)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
if (!sz || sz > maxsz) sz = maxsz;
|
|
||||||
return sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline int Preparation::actualDataSize(std::size_t pos) const
|
inline int Preparation::actualDataSize(std::size_t pos) const
|
||||||
{
|
{
|
||||||
poco_assert (pos >= 0 && pos < _pValues.size());
|
poco_assert (pos >= 0 && pos < _pValues.size());
|
||||||
|
|||||||
@@ -55,7 +55,8 @@ ODBCStatementImpl::ODBCStatementImpl(SessionImpl& rSession):
|
|||||||
_rConnection(rSession.dbc()),
|
_rConnection(rSession.dbc()),
|
||||||
_stmt(rSession.dbc()),
|
_stmt(rSession.dbc()),
|
||||||
_stepCalled(false),
|
_stepCalled(false),
|
||||||
_nextResponse(0)
|
_nextResponse(0),
|
||||||
|
_prepared(false)
|
||||||
{
|
{
|
||||||
if (session().getFeature("autoBind"))
|
if (session().getFeature("autoBind"))
|
||||||
{
|
{
|
||||||
@@ -120,15 +121,28 @@ void ODBCStatementImpl::compileImpl()
|
|||||||
// these calls must occur before.
|
// these calls must occur before.
|
||||||
fixupBinding(); doBind(false, true);
|
fixupBinding(); doBind(false, true);
|
||||||
|
|
||||||
bool dataAvailable = hasData();
|
makeInternalExtractors();
|
||||||
if (dataAvailable && !extractions().size())
|
doPrepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ODBCStatementImpl::makeInternalExtractors()
|
||||||
|
{
|
||||||
|
if (hasData() && !extractions().size())
|
||||||
{
|
{
|
||||||
fillColumns();
|
fillColumns();
|
||||||
makeExtractors(columnsReturned());
|
makeExtractors(columnsReturned());
|
||||||
|
fixupExtraction();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Preparation::DE_BOUND == ext && dataAvailable)
|
|
||||||
|
void ODBCStatementImpl::doPrepare()
|
||||||
{
|
{
|
||||||
|
if (!_prepared && session().getFeature("autoExtract") && hasData())
|
||||||
|
{
|
||||||
|
poco_check_ptr (_pPreparation);
|
||||||
|
|
||||||
Extractions& extracts = extractions();
|
Extractions& extracts = extractions();
|
||||||
Extractions::iterator it = extracts.begin();
|
Extractions::iterator it = extracts.begin();
|
||||||
Extractions::iterator itEnd = extracts.end();
|
Extractions::iterator itEnd = extracts.end();
|
||||||
@@ -139,6 +153,7 @@ void ODBCStatementImpl::compileImpl()
|
|||||||
pos += (*it)->numOfColumnsHandled();
|
pos += (*it)->numOfColumnsHandled();
|
||||||
delete pAP;
|
delete pAP;
|
||||||
}
|
}
|
||||||
|
_prepared = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,6 +255,11 @@ bool ODBCStatementImpl::hasNext()
|
|||||||
{
|
{
|
||||||
if (hasData())
|
if (hasData())
|
||||||
{
|
{
|
||||||
|
if (!extractions().size())
|
||||||
|
makeInternalExtractors();
|
||||||
|
|
||||||
|
if (!_prepared) doPrepare();
|
||||||
|
|
||||||
if (_stepCalled)
|
if (_stepCalled)
|
||||||
return _stepCalled = nextRowReady();
|
return _stepCalled = nextRowReady();
|
||||||
|
|
||||||
@@ -347,13 +367,4 @@ void ODBCStatementImpl::fillColumns()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ODBCStatementImpl::isStoredProcedure() const
|
|
||||||
{
|
|
||||||
std::string str = toString();
|
|
||||||
if (trimInPlace(str).size() < 2) return false;
|
|
||||||
|
|
||||||
return ('{' == str[0] && '}' == str[str.size()-1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} } } // namespace Poco::Data::ODBC
|
} } } // namespace Poco::Data::ODBC
|
||||||
|
|||||||
@@ -69,9 +69,9 @@ Preparation::~Preparation()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::size_t Preparation::columns(bool resize) const
|
std::size_t Preparation::columns() const
|
||||||
{
|
{
|
||||||
if (_pValues.empty() && resize)
|
if (_pValues.empty())
|
||||||
{
|
{
|
||||||
SQLSMALLINT nCol = 0;
|
SQLSMALLINT nCol = 0;
|
||||||
if (!Utility::isError(SQLNumResultCols(_rStmt, &nCol)) &&
|
if (!Utility::isError(SQLNumResultCols(_rStmt, &nCol)) &&
|
||||||
@@ -145,4 +145,22 @@ void Preparation::prepare(std::size_t pos, const Poco::Any&)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::size_t Preparation::maxDataSize(std::size_t pos) const
|
||||||
|
{
|
||||||
|
poco_assert (pos >= 0 && pos < _pValues.size());
|
||||||
|
|
||||||
|
std::size_t sz = 0;
|
||||||
|
std::size_t maxsz = getMaxFieldSize();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sz = ODBCColumn(_rStmt, pos).length();
|
||||||
|
}
|
||||||
|
catch (StatementException&) { }
|
||||||
|
|
||||||
|
if (!sz || sz > maxsz) sz = maxsz;
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } } // namespace Poco::Data::ODBC
|
} } } // namespace Poco::Data::ODBC
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
#include "Poco/Exception.h"
|
#include "Poco/Exception.h"
|
||||||
#include "Poco/Data/Common.h"
|
#include "Poco/Data/Common.h"
|
||||||
#include "Poco/Data/BLOB.h"
|
#include "Poco/Data/BLOB.h"
|
||||||
|
#include "Poco/Data/RecordSet.h"
|
||||||
#include "Poco/Data/StatementImpl.h"
|
#include "Poco/Data/StatementImpl.h"
|
||||||
#include "Poco/Data/ODBC/Connector.h"
|
#include "Poco/Data/ODBC/Connector.h"
|
||||||
#include "Poco/Data/ODBC/Utility.h"
|
#include "Poco/Data/ODBC/Utility.h"
|
||||||
@@ -998,6 +999,45 @@ void ODBCOracleTest::testStoredFunction()
|
|||||||
assert(-1 == i);
|
assert(-1 == i);
|
||||||
dropObject("FUNCTION", "storedFunction");
|
dropObject("FUNCTION", "storedFunction");
|
||||||
|
|
||||||
|
recreatePersonTable();
|
||||||
|
typedef Tuple<std::string, std::string, std::string, int> Person;
|
||||||
|
std::vector<Person> people;
|
||||||
|
people.push_back(Person("Simpson", "Homer", "Springfield", 42));
|
||||||
|
people.push_back(Person("Simpson", "Bart", "Springfield", 12));
|
||||||
|
people.push_back(Person("Simpson", "Lisa", "Springfield", 10));
|
||||||
|
*_pSession << "INSERT INTO Person VALUES (?, ?, ?, ?)", use(people), now;
|
||||||
|
|
||||||
|
*_pSession << "CREATE OR REPLACE "
|
||||||
|
"FUNCTION storedCursorFunction(ageLimit IN NUMBER) RETURN SYS_REFCURSOR IS "
|
||||||
|
" ret SYS_REFCURSOR; "
|
||||||
|
" BEGIN "
|
||||||
|
" OPEN ret FOR "
|
||||||
|
" SELECT * "
|
||||||
|
" FROM Person "
|
||||||
|
" WHERE Age < ageLimit "
|
||||||
|
" ORDER BY Age DESC; "
|
||||||
|
" RETURN ret; "
|
||||||
|
" END storedCursorFunction;" , now;
|
||||||
|
|
||||||
|
people.clear();
|
||||||
|
int age = 13;
|
||||||
|
|
||||||
|
*_pSession << "{call storedCursorFunction(?)}", in(age), into(people), now;
|
||||||
|
|
||||||
|
assert (2 == people.size());
|
||||||
|
assert (Person("Simpson", "Bart", "Springfield", 12) == people[0]);
|
||||||
|
assert (Person("Simpson", "Lisa", "Springfield", 10) == people[1]);
|
||||||
|
|
||||||
|
Statement stmt = ((*_pSession << "{call storedCursorFunction(?)}", in(age), now));
|
||||||
|
RecordSet rs(stmt);
|
||||||
|
assert (rs["LastName"] == "Simpson");
|
||||||
|
assert (rs["FirstName"] == "Bart");
|
||||||
|
assert (rs["Address"] == "Springfield");
|
||||||
|
assert (rs["Age"] == 12);
|
||||||
|
|
||||||
|
dropObject("TABLE", "Person");
|
||||||
|
dropObject("FUNCTION", "storedCursorFunction");
|
||||||
|
|
||||||
*_pSession << "CREATE OR REPLACE "
|
*_pSession << "CREATE OR REPLACE "
|
||||||
"FUNCTION storedFunction(inParam IN NUMBER) RETURN NUMBER IS "
|
"FUNCTION storedFunction(inParam IN NUMBER) RETURN NUMBER IS "
|
||||||
" BEGIN RETURN(inParam*inParam); "
|
" BEGIN RETURN(inParam*inParam); "
|
||||||
@@ -1092,6 +1132,7 @@ void ODBCOracleTest::testAsync()
|
|||||||
_pSession->setFeature("autoBind", bindValues[i]);
|
_pSession->setFeature("autoBind", bindValues[i]);
|
||||||
_pSession->setFeature("autoExtract", bindValues[i+1]);
|
_pSession->setFeature("autoExtract", bindValues[i+1]);
|
||||||
_pExecutor->asynchronous();
|
_pExecutor->asynchronous();
|
||||||
|
|
||||||
i += 2;
|
i += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1257,7 +1257,11 @@ bool ODBCSQLServerTest::canConnect(const std::string& driver, const std::string&
|
|||||||
{
|
{
|
||||||
std::cout << "DSN found: " << itDSN->first
|
std::cout << "DSN found: " << itDSN->first
|
||||||
<< " (" << itDSN->second << ')' << std::endl;
|
<< " (" << itDSN->second << ')' << std::endl;
|
||||||
format(_dbConnString, "DSN=%s", dsn);
|
format(_dbConnString,
|
||||||
|
"DSN=%s;"
|
||||||
|
"UID=test;"
|
||||||
|
"PWD=test;"
|
||||||
|
"DATABASE=test;", dsn);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2245,7 +2245,7 @@ void SQLExecutor::asynchronous()
|
|||||||
{
|
{
|
||||||
Session tmp = *_pSession;
|
Session tmp = *_pSession;
|
||||||
|
|
||||||
int rowCount = 500;
|
int rowCount = 2000;
|
||||||
std::vector<int> data(rowCount);
|
std::vector<int> data(rowCount);
|
||||||
Statement stmt = (tmp << "INSERT INTO Strings VALUES(?)", use(data));
|
Statement stmt = (tmp << "INSERT INTO Strings VALUES(?)", use(data));
|
||||||
Statement::Result result = stmt.executeAsync();
|
Statement::Result result = stmt.executeAsync();
|
||||||
@@ -2256,31 +2256,37 @@ void SQLExecutor::asynchronous()
|
|||||||
assert (stmt1.isAsync());
|
assert (stmt1.isAsync());
|
||||||
assert (stmt1.wait() == rowCount);
|
assert (stmt1.wait() == rowCount);
|
||||||
|
|
||||||
|
// +++ if this part of the test case fails, increase the rowCount until achieved
|
||||||
|
// that first execute is still executing when the second one is called
|
||||||
stmt1.execute();
|
stmt1.execute();
|
||||||
try {
|
try {
|
||||||
stmt1.execute();
|
stmt1.execute();
|
||||||
fail ("must fail");
|
fail ("execute() must fail");
|
||||||
} catch (InvalidAccessException&)
|
} catch (InvalidAccessException&)
|
||||||
{
|
{
|
||||||
stmt1.wait();
|
stmt1.wait();
|
||||||
stmt1.execute();
|
stmt1.execute();
|
||||||
stmt1.wait();
|
stmt1.wait();
|
||||||
}
|
}
|
||||||
|
// ---
|
||||||
|
|
||||||
stmt = tmp << "SELECT * FROM Strings", into(data), async, now;
|
stmt = tmp << "SELECT * FROM Strings", into(data), async, now;
|
||||||
assert (stmt.isAsync());
|
assert (stmt.isAsync());
|
||||||
stmt.wait();
|
stmt.wait();
|
||||||
assert (stmt.execute() == 0);
|
assert (stmt.execute() == 0);
|
||||||
|
|
||||||
|
// +++ if this part of the test case fails, increase the rowCount until achieved
|
||||||
|
// that first execute is still executing when the second one is called
|
||||||
try {
|
try {
|
||||||
result = stmt.executeAsync();
|
result = stmt.executeAsync();
|
||||||
fail ("must fail");
|
fail ("executeAsync() must fail");
|
||||||
} catch (InvalidAccessException&)
|
} catch (InvalidAccessException&)
|
||||||
{
|
{
|
||||||
assert (stmt.isAsync());
|
assert (stmt.isAsync());
|
||||||
stmt.wait();
|
stmt.wait();
|
||||||
result = stmt.executeAsync();
|
result = stmt.executeAsync();
|
||||||
}
|
}
|
||||||
|
// ---
|
||||||
|
|
||||||
assert (stmt.wait() == rowCount);
|
assert (stmt.wait() == rowCount);
|
||||||
assert (result.data() == rowCount);
|
assert (result.data() == rowCount);
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ public:
|
|||||||
_end(val.end())
|
_end(val.end())
|
||||||
/// Creates the Binding.
|
/// Creates the Binding.
|
||||||
{
|
{
|
||||||
if (numOfRowsHandled() == 0)
|
if (PD_IN == direction && numOfRowsHandled() == 0)
|
||||||
throw BindingException("It is illegal to bind to an empty data collection");
|
throw BindingException("It is illegal to bind to an empty data collection");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +249,7 @@ public:
|
|||||||
_end(val.end())
|
_end(val.end())
|
||||||
/// Creates the Binding.
|
/// Creates the Binding.
|
||||||
{
|
{
|
||||||
if (numOfRowsHandled() == 0)
|
if (PD_IN == direction && numOfRowsHandled() == 0)
|
||||||
throw BindingException("It is illegal to bind to an empty data collection");
|
throw BindingException("It is illegal to bind to an empty data collection");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,7 +306,7 @@ public:
|
|||||||
_end(val.end())
|
_end(val.end())
|
||||||
/// Creates the Binding.
|
/// Creates the Binding.
|
||||||
{
|
{
|
||||||
if (numOfRowsHandled() == 0)
|
if (PD_IN == direction && numOfRowsHandled() == 0)
|
||||||
throw BindingException("It is illegal to bind to an empty data collection");
|
throw BindingException("It is illegal to bind to an empty data collection");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,7 +363,7 @@ public:
|
|||||||
_end(val.end())
|
_end(val.end())
|
||||||
/// Creates the Binding.
|
/// Creates the Binding.
|
||||||
{
|
{
|
||||||
if (numOfRowsHandled() == 0)
|
if (PD_IN == direction && numOfRowsHandled() == 0)
|
||||||
throw BindingException("It is illegal to bind to an empty data collection");
|
throw BindingException("It is illegal to bind to an empty data collection");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,7 +420,7 @@ public:
|
|||||||
_end(val.end())
|
_end(val.end())
|
||||||
/// Creates the Binding.
|
/// Creates the Binding.
|
||||||
{
|
{
|
||||||
if (numOfRowsHandled() == 0)
|
if (PD_IN == direction && numOfRowsHandled() == 0)
|
||||||
throw BindingException("It is illegal to bind to an empty data collection");
|
throw BindingException("It is illegal to bind to an empty data collection");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,7 +477,7 @@ public:
|
|||||||
_end(val.end())
|
_end(val.end())
|
||||||
/// Creates the Binding.
|
/// Creates the Binding.
|
||||||
{
|
{
|
||||||
if (numOfRowsHandled() == 0)
|
if (PD_IN == direction && numOfRowsHandled() == 0)
|
||||||
throw BindingException("It is illegal to bind to an empty data collection");
|
throw BindingException("It is illegal to bind to an empty data collection");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,7 +534,7 @@ public:
|
|||||||
_end(val.end())
|
_end(val.end())
|
||||||
/// Creates the Binding.
|
/// Creates the Binding.
|
||||||
{
|
{
|
||||||
if (numOfRowsHandled() == 0)
|
if (PD_IN == direction && numOfRowsHandled() == 0)
|
||||||
throw BindingException("It is illegal to bind to an empty data collection");
|
throw BindingException("It is illegal to bind to an empty data collection");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -579,7 +579,8 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename T> Binding<T>* use(const T& t, const std::string& name = "")
|
template <typename T>
|
||||||
|
Binding<T>* use(const T& t, const std::string& name = "")
|
||||||
/// Convenience function for a more compact Binding creation.
|
/// Convenience function for a more compact Binding creation.
|
||||||
{
|
{
|
||||||
Binding<T>* pB = new Binding<T>(t, name, AbstractBinding::PD_IN);
|
Binding<T>* pB = new Binding<T>(t, name, AbstractBinding::PD_IN);
|
||||||
@@ -588,7 +589,8 @@ template <typename T> Binding<T>* use(const T& t, const std::string& name = "")
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T> Binding<T>* in(const T& t, const std::string& name = "")
|
template <typename T>
|
||||||
|
Binding<T>* in(const T& t, const std::string& name = "")
|
||||||
/// Convenience function for a more compact Binding creation.
|
/// Convenience function for a more compact Binding creation.
|
||||||
{
|
{
|
||||||
Binding<T>* pB = new Binding<T>(t, name, AbstractBinding::PD_IN);
|
Binding<T>* pB = new Binding<T>(t, name, AbstractBinding::PD_IN);
|
||||||
@@ -597,7 +599,8 @@ template <typename T> Binding<T>* in(const T& t, const std::string& name = "")
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T> Binding<T>* out(const T& t, const std::string& name = "")
|
template <typename T>
|
||||||
|
Binding<T>* out(const T& t, const std::string& name = "")
|
||||||
/// Convenience function for a more compact Binding creation.
|
/// Convenience function for a more compact Binding creation.
|
||||||
{
|
{
|
||||||
Binding<T>* pB = new Binding<T>(t, name, AbstractBinding::PD_OUT);
|
Binding<T>* pB = new Binding<T>(t, name, AbstractBinding::PD_OUT);
|
||||||
@@ -606,7 +609,8 @@ template <typename T> Binding<T>* out(const T& t, const std::string& name = "")
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T> Binding<T>* io(const T& t, const std::string& name = "")
|
template <typename T>
|
||||||
|
Binding<T>* io(const T& t, const std::string& name = "")
|
||||||
/// Convenience function for a more compact Binding creation.
|
/// Convenience function for a more compact Binding creation.
|
||||||
{
|
{
|
||||||
Binding<T>* pB = new Binding<T>(t, name, AbstractBinding::PD_IN_OUT);
|
Binding<T>* pB = new Binding<T>(t, name, AbstractBinding::PD_IN_OUT);
|
||||||
|
|||||||
@@ -632,14 +632,16 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename T> Extraction<T>* into(T& t)
|
template <typename T>
|
||||||
/// Convenience function to allow for a more compact creation of a default extraction object
|
Extraction<T>* into(T& t)
|
||||||
|
/// Convenience function to allow for a more compact creation of an extraction object
|
||||||
{
|
{
|
||||||
return new Extraction<T>(t);
|
return new Extraction<T>(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T> Extraction<T>* into(T& t, const T& def)
|
template <typename T>
|
||||||
|
Extraction<T>* into(T& t, const T& def)
|
||||||
/// Convenience function to allow for a more compact creation of an extraction object with the given default
|
/// Convenience function to allow for a more compact creation of an extraction object with the given default
|
||||||
{
|
{
|
||||||
return new Extraction<T>(t, def);
|
return new Extraction<T>(t, def);
|
||||||
|
|||||||
@@ -235,6 +235,9 @@ protected:
|
|||||||
/// When connector-specific behavior is desired, it should be overriden
|
/// When connector-specific behavior is desired, it should be overriden
|
||||||
/// by the statement implementation.
|
/// by the statement implementation.
|
||||||
|
|
||||||
|
void fixupExtraction();
|
||||||
|
/// Sets the AbstractExtractor at the extractors.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void compile();
|
void compile();
|
||||||
/// Compiles the statement, if not yet compiled. doesn't bind yet
|
/// Compiles the statement, if not yet compiled. doesn't bind yet
|
||||||
@@ -248,9 +251,6 @@ private:
|
|||||||
Poco::UInt32 executeWithoutLimit();
|
Poco::UInt32 executeWithoutLimit();
|
||||||
/// Executes without an upper limit set.
|
/// Executes without an upper limit set.
|
||||||
|
|
||||||
void fixupExtraction();
|
|
||||||
/// Sets the AbstractExtractor at the extractors.
|
|
||||||
|
|
||||||
void resetExtraction();
|
void resetExtraction();
|
||||||
/// Resets binding so it can be reused again.
|
/// Resets binding so it can be reused again.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user