mirror of
https://github.com/pocoproject/poco.git
synced 2025-03-29 02:45:21 +01:00
Stored procedures for DB2 & PostgreSQL, StatementImpl::isStoredProcedure() function
This commit is contained in:
parent
aaea87c6e2
commit
5feefc75cd
@ -157,13 +157,8 @@ private:
|
||||
/// This is a private no-op in this implementation
|
||||
/// due to security risk.
|
||||
|
||||
std::size_t getParamSize(std::size_t pos);
|
||||
/// Returns parameter size as defined by data source.
|
||||
/// Used to determine buffer size for variable size out-bound parameters
|
||||
/// (string and BLOB).
|
||||
|
||||
SQLSMALLINT getParamType(Direction dir) const;
|
||||
/// Returns ODBC parameter type based on the parameter binding direction
|
||||
SQLSMALLINT toODBCDirection(Direction dir) const;
|
||||
/// Returns ODBC parameter direction based on the parameter binding direction
|
||||
/// specified by user.
|
||||
|
||||
template <typename T>
|
||||
@ -184,7 +179,7 @@ private:
|
||||
|
||||
if (Utility::isError(SQLBindParameter(_rStmt,
|
||||
(SQLUSMALLINT) pos + 1,
|
||||
getParamType(dir),
|
||||
toODBCDirection(dir),
|
||||
cDataType,
|
||||
Utility::sqlDataType(cDataType),
|
||||
colSize,
|
||||
|
@ -57,8 +57,8 @@ template <typename H, SQLSMALLINT handleType>
|
||||
class Diagnostics
|
||||
/// Utility class providing functionality for retrieving ODBC diagnostic
|
||||
/// records. Diagnostics object must be created with corresponding handle
|
||||
/// as constructor argument. During construction, diagnostic records with corresponding
|
||||
/// fields are populated and the object is ready for querying on various diagnostic fields.
|
||||
/// as constructor argument. During construction, diagnostic records fields
|
||||
/// are populated and the object is ready for querying.
|
||||
{
|
||||
public:
|
||||
|
||||
@ -147,12 +147,12 @@ public:
|
||||
return _fields;
|
||||
}
|
||||
|
||||
const Iterator begin() const
|
||||
Iterator begin() const
|
||||
{
|
||||
return _fields.begin();
|
||||
}
|
||||
|
||||
const Iterator end() const
|
||||
Iterator end() const
|
||||
{
|
||||
return _fields.end();
|
||||
}
|
||||
|
@ -132,6 +132,12 @@ private:
|
||||
|
||||
void fillColumns();
|
||||
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 StatementHandle _stmt;
|
||||
@ -171,7 +177,7 @@ inline Poco::UInt32 ODBCStatementImpl::columnsReturned() const
|
||||
inline bool ODBCStatementImpl::hasData() const
|
||||
{
|
||||
poco_assert_dbg (_pPreparation);
|
||||
return (_pPreparation->columns() > 0);
|
||||
return (_pPreparation->columns(!isStoredProcedure()) > 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -150,8 +150,9 @@ public:
|
||||
void prepare(std::size_t pos, const Poco::Any&);
|
||||
/// Prepares an Any.
|
||||
|
||||
std::size_t columns() const;
|
||||
std::size_t columns(bool resize = true) const;
|
||||
/// Returns the number of columns.
|
||||
/// Resizes the internal storage iff resize is true.
|
||||
|
||||
Poco::Any& operator [] (std::size_t pos);
|
||||
/// Returns reference to column data.
|
||||
|
@ -81,8 +81,26 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
|
||||
|
||||
if (isOutBound(dir))
|
||||
{
|
||||
Parameter p(_rStmt, pos);
|
||||
size = (SQLINTEGER) p.columnSize();
|
||||
try
|
||||
{
|
||||
Parameter p(_rStmt, pos);
|
||||
size = (SQLUINTEGER) p.columnSize();
|
||||
}
|
||||
catch (StatementException&)
|
||||
// some drivers (e.g. MS SQL) refuse to describe output parameters
|
||||
{
|
||||
SQLHDESC hIPD = 0;
|
||||
if (!Utility::isError(SQLGetStmtAttr(_rStmt, SQL_ATTR_IMP_PARAM_DESC, &hIPD, 0, 0)))
|
||||
{
|
||||
size = 1024;
|
||||
SQLUINTEGER sz = size;
|
||||
if (Utility::isError(SQLSetDescField(hIPD, (SQLSMALLINT) pos + 1, SQL_DESC_LENGTH, &sz, 0)))
|
||||
throw StatementException(_rStmt, "Could not set output parameter size");
|
||||
}
|
||||
else
|
||||
throw StatementException(_rStmt, "Could not get statement IPD attribute handle.");
|
||||
}
|
||||
|
||||
char* pChar = (char*) std::calloc(size, sizeof(char));
|
||||
pVal = (SQLPOINTER) pChar;
|
||||
_outParams.insert(ParamMap::value_type(pVal, size));
|
||||
@ -106,7 +124,7 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
|
||||
|
||||
if (Utility::isError(SQLBindParameter(_rStmt,
|
||||
(SQLUSMALLINT) pos + 1,
|
||||
getParamType(dir),
|
||||
toODBCDirection(dir),
|
||||
SQL_C_CHAR,
|
||||
SQL_LONGVARCHAR,
|
||||
(SQLUINTEGER) size,
|
||||
@ -181,7 +199,7 @@ void Binder::bind(std::size_t pos, const Poco::DateTime& val, Direction dir)
|
||||
|
||||
if (Utility::isError(SQLBindParameter(_rStmt,
|
||||
(SQLUSMALLINT) pos + 1,
|
||||
getParamType(dir),
|
||||
toODBCDirection(dir),
|
||||
SQL_C_TIMESTAMP,
|
||||
SQL_TIMESTAMP,
|
||||
colSize,
|
||||
@ -213,7 +231,7 @@ void Binder::bind(std::size_t pos, const char* const &pVal, Direction dir)
|
||||
}
|
||||
|
||||
|
||||
SQLSMALLINT Binder::getParamType(Direction dir) const
|
||||
SQLSMALLINT Binder::toODBCDirection(Direction dir) const
|
||||
{
|
||||
bool in = isInBound(dir);
|
||||
bool out = isOutBound(dir);
|
||||
|
@ -347,4 +347,13 @@ 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
|
||||
|
@ -69,15 +69,13 @@ Preparation::~Preparation()
|
||||
}
|
||||
|
||||
|
||||
std::size_t Preparation::columns() const
|
||||
std::size_t Preparation::columns(bool resize) const
|
||||
{
|
||||
if (_pValues.empty())
|
||||
if (_pValues.empty() && resize)
|
||||
{
|
||||
SQLSMALLINT nCol = 0;
|
||||
if (Utility::isError(SQLNumResultCols(_rStmt, &nCol)))
|
||||
throw StatementException(_rStmt);
|
||||
|
||||
if (nCol)
|
||||
if (!Utility::isError(SQLNumResultCols(_rStmt, &nCol)) &&
|
||||
0 != nCol)
|
||||
{
|
||||
_pValues.resize(nCol, 0);
|
||||
_pLengths.resize(nCol, 0);
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "CppUnit/TestSuite.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Format.h"
|
||||
#include "Poco/Tuple.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Data/Common.h"
|
||||
#include "Poco/Data/BLOB.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;
|
||||
|
||||
|
||||
@ -859,6 +861,170 @@ void ODBCDB2Test::testInternalStorageType()
|
||||
}
|
||||
|
||||
|
||||
void ODBCDB2Test::testStoredProcedure()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
for (int k = 0; k < 8;)
|
||||
{
|
||||
_pSession->setFeature("autoBind", bindValues[k]);
|
||||
_pSession->setFeature("autoExtract", bindValues[k+1]);
|
||||
|
||||
dropObject("PROCEDURE", "storedProcedure");
|
||||
*_pSession << "CREATE PROCEDURE storedProcedure(OUT outParam INTEGER) "
|
||||
"BEGIN "
|
||||
" SET outParam = -1; "
|
||||
"END" , now;
|
||||
|
||||
int i = 0;
|
||||
*_pSession << "{call storedProcedure(?)}", out(i), now;
|
||||
assert(-1 == i);
|
||||
dropObject("PROCEDURE", "storedProcedure");
|
||||
|
||||
*_pSession << "CREATE PROCEDURE storedProcedure(inParam INTEGER, OUT outParam INTEGER) "
|
||||
"BEGIN "
|
||||
" SET outParam = inParam*inParam; "
|
||||
"END" , now;
|
||||
|
||||
|
||||
i = 2;
|
||||
int j = 0;
|
||||
*_pSession << "{call storedProcedure(?, ?)}", in(i), out(j), now;
|
||||
assert(4 == j);
|
||||
dropObject("PROCEDURE", "storedProcedure");
|
||||
|
||||
*_pSession << "CREATE PROCEDURE storedProcedure(INOUT ioParam INTEGER) "
|
||||
"BEGIN "
|
||||
" SET ioParam = ioParam*ioParam; "
|
||||
"END" , now;
|
||||
|
||||
i = 2;
|
||||
*_pSession << "{call storedProcedure(?)}", io(i), now;
|
||||
assert(4 == i);
|
||||
dropObject("PROCEDURE", "storedProcedure");
|
||||
|
||||
//TIMESTAMP is not supported as stored procedure parameter in DB2
|
||||
//(SQL0182N An expression with a datetime value or a labeled duration is not valid.)
|
||||
|
||||
*_pSession << "CREATE PROCEDURE storedProcedure(inParam VARCHAR(1000), OUT outParam VARCHAR(1000)) "
|
||||
"BEGIN "
|
||||
" SET outParam = inParam; "
|
||||
"END" , now;
|
||||
|
||||
std::string inParam =
|
||||
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
|
||||
std::string outParam;
|
||||
*_pSession << "{call storedProcedure(?,?)}", in(inParam), out(outParam), now;
|
||||
assert(inParam == outParam);
|
||||
dropObject("PROCEDURE", "storedProcedure");
|
||||
|
||||
k += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODBCDB2Test::testStoredFunction()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
for (int k = 0; k < 8;)
|
||||
{
|
||||
_pSession->setFeature("autoBind", bindValues[k]);
|
||||
_pSession->setFeature("autoExtract", bindValues[k+1]);
|
||||
|
||||
dropObject("PROCEDURE", "storedFunction");
|
||||
*_pSession << "CREATE PROCEDURE storedFunction() "
|
||||
"BEGIN "
|
||||
" RETURN -1; "
|
||||
"END" , now;
|
||||
|
||||
int i = 0;
|
||||
*_pSession << "{? = call storedFunction()}", out(i), now;
|
||||
assert(-1 == i);
|
||||
dropObject("PROCEDURE", "storedFunction");
|
||||
|
||||
*_pSession << "CREATE PROCEDURE storedFunction(inParam INTEGER) "
|
||||
"BEGIN "
|
||||
" RETURN inParam*inParam; "
|
||||
"END" , now;
|
||||
|
||||
i = 2;
|
||||
int result = 0;
|
||||
*_pSession << "{? = call storedFunction(?)}", out(result), in(i), now;
|
||||
assert(4 == result);
|
||||
dropObject("PROCEDURE", "storedFunction");
|
||||
|
||||
*_pSession << "CREATE PROCEDURE storedFunction(inParam INTEGER, OUT outParam INTEGER) "
|
||||
"BEGIN "
|
||||
" SET outParam = inParam*inParam; "
|
||||
" RETURN outParam; "
|
||||
"END" , now;
|
||||
|
||||
i = 2;
|
||||
int j = 0;
|
||||
result = 0;
|
||||
*_pSession << "{? = call storedFunction(?, ?)}", out(result), in(i), out(j), now;
|
||||
assert(4 == j);
|
||||
assert(j == result);
|
||||
dropObject("PROCEDURE", "storedFunction");
|
||||
|
||||
*_pSession << "CREATE PROCEDURE storedFunction(INOUT param1 INTEGER, INOUT param2 INTEGER) "
|
||||
"BEGIN "
|
||||
" DECLARE temp INTEGER;"
|
||||
" SET temp = param1; "
|
||||
" SET param1 = param2; "
|
||||
" SET param2 = temp; "
|
||||
" RETURN param1 + param2; "
|
||||
"END" , 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);
|
||||
|
||||
dropObject("PROCEDURE", "storedFunction");
|
||||
|
||||
_pSession->setFeature("autoBind", true);
|
||||
|
||||
*_pSession << "CREATE PROCEDURE storedFunction(inParam VARCHAR(10), OUT outParam VARCHAR(10)) "
|
||||
"BEGIN "
|
||||
" SET outParam = inParam; "
|
||||
" RETURN LENGTH(outParam);"//DB2 allows only integer as return type
|
||||
"END" , now;
|
||||
|
||||
std::string inParam = "123456789";
|
||||
std::string outParam;
|
||||
int ret;
|
||||
*_pSession << "{? = call storedFunction(?,?)}", out(ret), in(inParam), out(outParam), now;
|
||||
assert(inParam == outParam);
|
||||
assert(ret == inParam.size());
|
||||
dropObject("PROCEDURE", "storedFunction");
|
||||
|
||||
k += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODBCDB2Test::dropObject(const std::string& type, const std::string& name)
|
||||
{
|
||||
try
|
||||
@ -1098,6 +1264,8 @@ CppUnit::Test* ODBCDB2Test::suite()
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testTupleVector);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testInternalExtraction);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testInternalStorageType);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testStoredProcedure);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testStoredFunction);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -119,6 +119,9 @@ public:
|
||||
void testInternalExtraction();
|
||||
void testInternalStorageType();
|
||||
|
||||
void testStoredProcedure();
|
||||
void testStoredFunction();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
|
@ -1023,7 +1023,7 @@ void ODBCOracleTest::testStoredFunction()
|
||||
k += 2;
|
||||
}
|
||||
|
||||
//string and BLOB for automatic binding only
|
||||
//string for automatic binding only
|
||||
_pSession->setFeature("autoBind", true);
|
||||
|
||||
*_pSession << "CREATE OR REPLACE "
|
||||
|
@ -51,6 +51,7 @@
|
||||
|
||||
using namespace Poco::Data;
|
||||
using Poco::Data::ODBC::Utility;
|
||||
using Poco::Data::ODBC::ODBCException;
|
||||
using Poco::Data::ODBC::ConnectionException;
|
||||
using Poco::Data::ODBC::StatementException;
|
||||
using Poco::Data::ODBC::StatementDiagnostics;
|
||||
@ -64,6 +65,11 @@ Poco::SharedPtr<Poco::Data::Session> ODBCPostgreSQLTest::_pSession = 0;
|
||||
Poco::SharedPtr<SQLExecutor> ODBCPostgreSQLTest::_pExecutor = 0;
|
||||
std::string ODBCPostgreSQLTest::_dbConnString;
|
||||
Poco::Data::ODBC::Utility::DriverMap ODBCPostgreSQLTest::_drivers;
|
||||
#ifdef POCO_OS_FAMILY_WINDOWS
|
||||
const std::string ODBCPostgreSQLTest::libDir = "C:\\\\Program Files\\\\PostgreSQL\\\\8.2\\\\lib\\\\";
|
||||
#else
|
||||
const std::string ODBCPostgreSQLTest::libDir = "/usr/local/pgsql/lib/";
|
||||
#endif
|
||||
|
||||
|
||||
ODBCPostgreSQLTest::ODBCPostgreSQLTest(const std::string& name):
|
||||
@ -857,6 +863,83 @@ void ODBCPostgreSQLTest::testInternalStorageType()
|
||||
}
|
||||
|
||||
|
||||
void ODBCPostgreSQLTest::testStoredFunction()
|
||||
{
|
||||
configurePLPgSQL();
|
||||
|
||||
for (int k = 0; k < 8;)
|
||||
{
|
||||
_pSession->setFeature("autoBind", bindValues[k]);
|
||||
_pSession->setFeature("autoExtract", bindValues[k+1]);
|
||||
|
||||
*_pSession << "CREATE FUNCTION storedFunction() RETURNS INTEGER AS '"
|
||||
"BEGIN "
|
||||
" return -1; "
|
||||
"END;'"
|
||||
"LANGUAGE 'plpgsql'", now;
|
||||
|
||||
int i = 0;
|
||||
*_pSession << "{? = call storedFunction()}", out(i), now;
|
||||
assert(-1 == i);
|
||||
dropObject("FUNCTION", "storedFunction()");
|
||||
|
||||
*_pSession << "CREATE FUNCTION storedFunction(INTEGER) RETURNS INTEGER AS '"
|
||||
"BEGIN "
|
||||
" RETURN $1 * $1; "
|
||||
"END;'"
|
||||
"LANGUAGE 'plpgsql'" , now;
|
||||
|
||||
i = 2;
|
||||
int result = 0;
|
||||
*_pSession << "{? = call storedFunction(?)}", out(result), in(i), now;
|
||||
assert(4 == result);
|
||||
dropObject("FUNCTION", "storedFunction(INTEGER)");
|
||||
/*TODO
|
||||
*_pSession << "CREATE FUNCTION storedFunction(TEXT) RETURNS TEXT AS '"
|
||||
"BEGIN "
|
||||
" RETURN $1;"
|
||||
"END;'"
|
||||
"LANGUAGE 'plpgsql'" , now;
|
||||
|
||||
std::string param = "123";
|
||||
std::string ret;
|
||||
try {
|
||||
*_pSession << "{? = call storedFunction(?)}", out(ret), in(param), now;
|
||||
}catch(StatementException & ex) { std::cout << ex.toString();}
|
||||
assert(ret == param);
|
||||
dropObject("FUNCTION", "storedFunction(TEXT)");
|
||||
*/
|
||||
|
||||
k += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODBCPostgreSQLTest::configurePLPgSQL()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
try
|
||||
{
|
||||
*_pSession << format("CREATE FUNCTION plpgsql_call_handler () "
|
||||
"RETURNS OPAQUE "
|
||||
"AS '%splpgsql.dll' "
|
||||
"LANGUAGE 'C';", libDir), now;
|
||||
|
||||
*_pSession << "CREATE LANGUAGE 'plpgsql' "
|
||||
"HANDLER plpgsql_call_handler "
|
||||
"LANCOMPILER 'PL/pgSQL'", now;
|
||||
|
||||
}catch(StatementException& ex)
|
||||
{
|
||||
if (7 != ex.diagnostics().nativeError(0))
|
||||
throw;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void ODBCPostgreSQLTest::dropObject(const std::string& type, const std::string& name)
|
||||
{
|
||||
try
|
||||
@ -1063,7 +1146,7 @@ bool ODBCPostgreSQLTest::init(const std::string& driver, const std::string& dsn)
|
||||
|
||||
if (_pSession && _pSession->isConnected())
|
||||
std::cout << "*** Connected to [" << driver << "] test database." << std::endl;
|
||||
|
||||
|
||||
_pExecutor = new SQLExecutor(driver + " SQL Executor", _pSession);
|
||||
|
||||
return true;
|
||||
@ -1073,6 +1156,7 @@ bool ODBCPostgreSQLTest::init(const std::string& driver, const std::string& dsn)
|
||||
CppUnit::Test* ODBCPostgreSQLTest::suite()
|
||||
{
|
||||
if (init("PostgreSQL ANSI", "PocoDataPostgreSQLTest"))
|
||||
//if (init("Mammoth ODBCng Beta", "Mammoth ODBCng beta"))
|
||||
{
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCPostgreSQLTest");
|
||||
|
||||
@ -1126,6 +1210,7 @@ CppUnit::Test* ODBCPostgreSQLTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTupleVector);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testInternalExtraction);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testInternalStorageType);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testStoredFunction);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -122,6 +122,8 @@ public:
|
||||
void testInternalExtraction();
|
||||
void testInternalStorageType();
|
||||
|
||||
void testStoredFunction();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
@ -140,12 +142,25 @@ private:
|
||||
|
||||
static bool init(const std::string& driver, const std::string& dsn);
|
||||
static bool canConnect(const std::string& driver, const std::string& dsn);
|
||||
|
||||
void configurePLPgSQL();
|
||||
/// Configures PL/pgSQL in the database. A reasonable defaults
|
||||
/// for the interpreter location on WIN32 and POSIX platforms are
|
||||
/// supplied (see installDir member variable).
|
||||
/// If these do not work, user must determine the proper location,
|
||||
/// modify the function and recompile.
|
||||
/// Alternative is direct database configuration for PL/pgSQL usage.
|
||||
|
||||
static Poco::Data::ODBC::Utility::DriverMap _drivers;
|
||||
static std::string _dbConnString;
|
||||
static Poco::SharedPtr<Poco::Data::Session> _pSession;
|
||||
static Poco::SharedPtr<SQLExecutor> _pExecutor;
|
||||
static const bool bindValues[8];
|
||||
static const std::string libDir;
|
||||
/// Varible determining the location of the library directory
|
||||
/// on the database installation system.
|
||||
/// Used to enable PLpgSQL language programmaticaly when
|
||||
/// it is not enabled.
|
||||
};
|
||||
|
||||
|
||||
|
@ -907,9 +907,14 @@ void ODBCSQLServerTest::testStoredProcedure()
|
||||
|
||||
k += 2;
|
||||
}
|
||||
/*TODO
|
||||
/*TODO - currently fails with following error:
|
||||
|
||||
[Microsoft][ODBC SQL Server Driver][SQL Server]Invalid parameter
|
||||
2 (''): Data type 0x23 is a deprecated large object, or LOB, but is marked as output parameter.
|
||||
Deprecated types are not supported as output parameters. Use current large object types instead.
|
||||
|
||||
_pSession->setFeature("autoBind", true);
|
||||
*_pSession << "CREATE PROCEDURE storedProcedure(@inParam VARCHAR, @outParam VARCHAR OUTPUT) AS "
|
||||
*_pSession << "CREATE PROCEDURE storedProcedure(@inParam VARCHAR(MAX), @outParam VARCHAR(MAX) OUTPUT) AS "
|
||||
"BEGIN "
|
||||
"SET @outParam = @inParam; "
|
||||
"END;"
|
||||
@ -1206,6 +1211,7 @@ CppUnit::Test* ODBCSQLServerTest::suite()
|
||||
{
|
||||
#ifdef POCO_OS_FAMILY_WINDOWS
|
||||
if (init("SQL Server", "PocoDataSQLServerTest"))
|
||||
//if (init("SQL Native Client", "PocoDataSQLServerTest"))
|
||||
#else
|
||||
if (init("FreeTDS", "PocoDataSQLServerTest"))
|
||||
#endif
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// SQLExecutor.cpp
|
||||
//
|
||||
// $Id: //poco/Main/DataConnectors/ODBC/testsuite/src/SQLExecutor.cpp#14 $
|
||||
// $Id: //poco/Main/Data/ODBC/testsuite/src/SQLExecutor.cpp#14 $
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
|
@ -222,6 +222,20 @@ protected:
|
||||
void resetBinding();
|
||||
/// Resets binding so it can be reused again.
|
||||
|
||||
virtual bool isStoredProcedure() const;
|
||||
/// Returns true if the statement is stored procedure.
|
||||
/// Used as a help to determine whether to automatically create the
|
||||
/// internal extractions when no outside extraction is supplied.
|
||||
/// The reason for this function is to prevent unnecessary internal
|
||||
/// extraction creation in cases (behavior exhibited by some ODBC drivers)
|
||||
/// when there is data available from the stored procedure call
|
||||
/// statement execution but no external extraction is supplied (as is
|
||||
/// usually the case when stored procedures are called). In such cases
|
||||
/// no storage is needed because output parameters serve as storage.
|
||||
/// At the Data framework level, this function always returns false.
|
||||
/// When connector-specific behavior is desired, it should be overriden
|
||||
/// by the statement implementation.
|
||||
|
||||
private:
|
||||
void compile();
|
||||
/// Compiles the statement, if not yet compiled. doesn't bind yet
|
||||
@ -241,6 +255,14 @@ private:
|
||||
void resetExtraction();
|
||||
/// Resets binding so it can be reused again.
|
||||
|
||||
template <class T, class C>
|
||||
InternalExtraction<T,C>* createExtract(const MetaColumn& mc)
|
||||
{
|
||||
C* pData = new C;
|
||||
Column<T,C>* pCol = new Column<T,C>(mc, pData);
|
||||
return new InternalExtraction<T,C>(*pData, pCol);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void addInternalExtract(const MetaColumn& mc)
|
||||
/// Creates and adds the internal extraction.
|
||||
@ -272,23 +294,11 @@ private:
|
||||
if (storage.empty()) storage = VECTOR;
|
||||
|
||||
if (0 == icompare(VECTOR, storage))
|
||||
{
|
||||
std::vector<T>* pData = new std::vector<T>;
|
||||
Column<T,std::vector<T> >* pCol = new Column<T, std::vector<T> >(mc, pData);
|
||||
addExtract(new InternalExtraction<T, std::vector<T> >(*pData, pCol));
|
||||
}
|
||||
addExtract(createExtract<T, std::vector<T> >(mc));
|
||||
else if (0 == icompare(LIST, storage))
|
||||
{
|
||||
std::list<T>* pData = new std::list<T>;
|
||||
Column<T,std::list<T> >* pCol = new Column<T, std::list<T> >(mc, pData);
|
||||
addExtract(new InternalExtraction<T, std::list<T> >(*pData, pCol));
|
||||
}
|
||||
addExtract(createExtract<T, std::list<T> >(mc));
|
||||
else if (0 == icompare(DEQUE, storage))
|
||||
{
|
||||
std::deque<T>* pData = new std::deque<T>;
|
||||
Column<T,std::deque<T> >* pCol = new Column<T, std::deque<T> >(mc, pData);
|
||||
addExtract(new InternalExtraction<T, std::deque<T> >(*pData, pCol));
|
||||
}
|
||||
addExtract(createExtract<T, std::deque<T> >(mc));
|
||||
}
|
||||
|
||||
StatementImpl(const StatementImpl& stmt);
|
||||
@ -389,6 +399,12 @@ inline std::size_t StatementImpl::extractionCount() const
|
||||
}
|
||||
|
||||
|
||||
inline bool StatementImpl::isStoredProcedure() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
||||
|
||||
|
||||
|
@ -153,7 +153,7 @@ void StatementImpl::compile()
|
||||
compileImpl();
|
||||
_state = ST_COMPILED;
|
||||
|
||||
if (!extractions().size())
|
||||
if (!extractions().size() && !isStoredProcedure())
|
||||
{
|
||||
Poco::UInt32 cols = columnsReturned();
|
||||
if (cols) makeExtractors(cols);
|
||||
|
Loading…
x
Reference in New Issue
Block a user