batch statements (multiple results) support

This commit is contained in:
Aleksandar Fabijanic
2007-11-06 02:18:32 +00:00
parent ae34e0ff3b
commit 95c5230389
18 changed files with 284 additions and 195 deletions

View File

@@ -126,6 +126,9 @@ private:
void makeInternalExtractors(); void makeInternalExtractors();
/// Creates internal extractors if none were supplied from the user. /// Creates internal extractors if none were supplied from the user.
bool isStoredProcedure() const;
/// Returns true if SQL is a stored procedure call.
void doPrepare(); void doPrepare();
/// Prepares placeholders for data returned by statement. /// Prepares placeholders for data returned by statement.
/// It is called during statement compilation for SQL statements /// It is called during statement compilation for SQL statements

View File

@@ -199,6 +199,9 @@ private:
void prepareImpl(std::size_t pos); void prepareImpl(std::size_t pos);
/// Utility function to prepare Any and DynamicAny /// Utility function to prepare Any and DynamicAny
void resize() const;
/// Resize the values and lengths vectors.
template <typename T> template <typename T>
void preparePOD(std::size_t pos, SQLSMALLINT valueType) void preparePOD(std::size_t pos, SQLSMALLINT valueType)
{ {

View File

@@ -284,25 +284,17 @@ bool ODBCStatementImpl::hasNext()
if (!nextRowReady()) if (!nextRowReady())
{ {
try try { activateNextDataSet(); }
{ catch (InvalidAccessException&)
activateNextDataSet(); { return false; }
} catch (InvalidAccessException&)
{ try { checkError(SQLMoreResults(_stmt)); }
return false; catch (NoDataException&)
} { return false; }
addPreparation(); addPreparation();
doPrepare(); doPrepare();
fixupExtraction(); fixupExtraction();
try
{
checkError(SQLMoreResults(_stmt));
} catch (NoDataException&)
{
return false;
}
makeStep(); makeStep();
} }
else if (Utility::isError(_nextResponse)) else if (Utility::isError(_nextResponse))
@@ -408,4 +400,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 } } } // namespace Poco::Data::ODBC

View File

@@ -62,6 +62,7 @@ Preparation::Preparation(const Preparation& other):
_maxFieldSize(other._maxFieldSize), _maxFieldSize(other._maxFieldSize),
_dataExtraction(other._dataExtraction) _dataExtraction(other._dataExtraction)
{ {
resize();
} }
@@ -79,21 +80,23 @@ Preparation::~Preparation()
std::size_t Preparation::columns() const std::size_t Preparation::columns() const
{ {
if (_pValues.empty()) if (_pValues.empty()) resize();
{
SQLSMALLINT nCol = 0;
if (!Utility::isError(SQLNumResultCols(_rStmt, &nCol)) &&
0 != nCol)
{
_pValues.resize(nCol, 0);
_pLengths.resize(nCol, 0);
}
}
return _pValues.size(); return _pValues.size();
} }
void Preparation::resize() const
{
SQLSMALLINT nCol = 0;
if (!Utility::isError(SQLNumResultCols(_rStmt, &nCol)) &&
0 != nCol)
{
_pValues.resize(nCol, 0);
_pLengths.resize(nCol, 0);
}
}
Poco::Any& Preparation::operator [] (std::size_t pos) Poco::Any& Preparation::operator [] (std::size_t pos)
{ {
poco_assert (pos >= 0 && pos < _pValues.size()); poco_assert (pos >= 0 && pos < _pValues.size());

View File

@@ -1201,6 +1201,22 @@ void ODBCDB2Test::testDynamicAny()
} }
void ODBCDB2Test::testMultipleResults()
{
if (!_pSession) fail ("Test not available.");
for (int i = 0; i < 8;)
{
recreatePersonTable();
_pSession->setFeature("autoBind", bindValues[i]);
_pSession->setFeature("autoExtract", bindValues[i+1]);
_pExecutor->multipleResults();
i += 2;
}
}
void ODBCDB2Test::dropObject(const std::string& type, const std::string& name) void ODBCDB2Test::dropObject(const std::string& type, const std::string& name)
{ {
try try
@@ -1350,7 +1366,11 @@ bool ODBCDB2Test::canConnect(const std::string& driver, const std::string& dsn)
{ {
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=db2admin;"
"Pwd=db2admin;",
dsn);
return true; return true;
} }
} }
@@ -1470,6 +1490,7 @@ CppUnit::Test* ODBCDB2Test::suite()
CppUnit_addTest(pSuite, ODBCDB2Test, testAsync); CppUnit_addTest(pSuite, ODBCDB2Test, testAsync);
CppUnit_addTest(pSuite, ODBCDB2Test, testAny); CppUnit_addTest(pSuite, ODBCDB2Test, testAny);
CppUnit_addTest(pSuite, ODBCDB2Test, testDynamicAny); CppUnit_addTest(pSuite, ODBCDB2Test, testDynamicAny);
CppUnit_addTest(pSuite, ODBCDB2Test, testMultipleResults);
return pSuite; return pSuite;
} }

View File

@@ -132,6 +132,8 @@ public:
void testAny(); void testAny();
void testDynamicAny(); void testDynamicAny();
void testMultipleResults();
void setUp(); void setUp();
void tearDown(); void tearDown();

View File

@@ -108,6 +108,9 @@ void ODBCMySQLTest::testBareboneODBC()
_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL, false); _pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL, false);
_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND, false); _pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND, false);
/*
MySQL supports batch statements as of 3.51.18
http://bugs.mysql.com/bug.php?id=7445
tableCreateString = "CREATE TABLE Test " tableCreateString = "CREATE TABLE Test "
"(First VARCHAR(30)," "(First VARCHAR(30),"
@@ -118,6 +121,7 @@ void ODBCMySQLTest::testBareboneODBC()
_pExecutor->bareboneODBCMultiResultTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND); _pExecutor->bareboneODBCMultiResultTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND);
_pExecutor->bareboneODBCMultiResultTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL); _pExecutor->bareboneODBCMultiResultTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL);
_pExecutor->bareboneODBCMultiResultTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND); _pExecutor->bareboneODBCMultiResultTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND);
*/
} }
@@ -989,6 +993,27 @@ void ODBCMySQLTest::testDynamicAny()
} }
void ODBCMySQLTest::testMultipleResults()
{
/*
MySQL supports batch statements as of 3.51.18
http://bugs.mysql.com/bug.php?id=7445
if (!_pSession) fail ("Test not available.");
for (int i = 0; i < 8;)
{
recreatePersonTable();
_pSession->setFeature("autoBind", bindValues[i]);
_pSession->setFeature("autoExtract", bindValues[i+1]);
_pExecutor->multipleResults();
i += 2;
}
*/
}
void ODBCMySQLTest::dropObject(const std::string& type, const std::string& name) void ODBCMySQLTest::dropObject(const std::string& type, const std::string& name)
{ {
*_pSession << format("DROP %s IF EXISTS %s", type, name), now; *_pSession << format("DROP %s IF EXISTS %s", type, name), now;
@@ -1239,6 +1264,7 @@ CppUnit::Test* ODBCMySQLTest::suite()
CppUnit_addTest(pSuite, ODBCMySQLTest, testAsync); CppUnit_addTest(pSuite, ODBCMySQLTest, testAsync);
CppUnit_addTest(pSuite, ODBCMySQLTest, testAny); CppUnit_addTest(pSuite, ODBCMySQLTest, testAny);
CppUnit_addTest(pSuite, ODBCMySQLTest, testDynamicAny); CppUnit_addTest(pSuite, ODBCMySQLTest, testDynamicAny);
CppUnit_addTest(pSuite, ODBCMySQLTest, testMultipleResults);
return pSuite; return pSuite;
} }

View File

@@ -132,6 +132,8 @@ public:
void testAny(); void testAny();
void testDynamicAny(); void testDynamicAny();
void testMultipleResults();
void setUp(); void setUp();
void tearDown(); void tearDown();

View File

@@ -131,17 +131,17 @@ void ODBCOracleTest::testBarebone()
"Third NUMBER)"; "Third NUMBER)";
*_pSession << "CREATE OR REPLACE " *_pSession << "CREATE OR REPLACE "
"PROCEDURE multiResultsProcedure(tmp1 OUT SYS_REFCURSOR, " "PROCEDURE multiResultsProcedure(ret1 OUT SYS_REFCURSOR, "
"tmp2 OUT SYS_REFCURSOR," "ret2 OUT SYS_REFCURSOR,"
"tmp3 OUT SYS_REFCURSOR," "ret3 OUT SYS_REFCURSOR,"
"tmp4 OUT SYS_REFCURSOR," "ret4 OUT SYS_REFCURSOR,"
"tmp5 OUT SYS_REFCURSOR) IS " "ret5 OUT SYS_REFCURSOR) IS "
"BEGIN " "BEGIN "
"OPEN tmp1 FOR SELECT * FROM Test WHERE First = '1';" "OPEN ret1 FOR SELECT * FROM Test WHERE First = '1';"
"OPEN tmp2 FOR SELECT * FROM Test WHERE First = '2';" "OPEN ret2 FOR SELECT * FROM Test WHERE First = '2';"
"OPEN tmp3 FOR SELECT * FROM Test WHERE First = '3';" "OPEN ret3 FOR SELECT * FROM Test WHERE First = '3';"
"OPEN tmp4 FOR SELECT * FROM Test WHERE First = '4';" "OPEN ret4 FOR SELECT * FROM Test WHERE First = '4';"
"OPEN tmp5 FOR SELECT * FROM Test WHERE First = '5';" "OPEN ret5 FOR SELECT * FROM Test WHERE First = '5';"
"END multiResultsProcedure;" , now; "END multiResultsProcedure;" , now;
_pExecutor->bareboneODBCMultiResultTest(_dbConnString, _pExecutor->bareboneODBCMultiResultTest(_dbConnString,
@@ -1109,7 +1109,7 @@ void ODBCOracleTest::testStoredProcedureDynamicAny()
} }
void ODBCOracleTest::testStoredCursorProcedure() void ODBCOracleTest::testCursorStoredProcedure()
{ {
if (!_pSession) fail ("Test not available."); if (!_pSession) fail ("Test not available.");
@@ -1251,7 +1251,7 @@ void ODBCOracleTest::testStoredFunction()
} }
void ODBCOracleTest::testStoredCursorFunction() void ODBCOracleTest::testCursorStoredFunction()
{ {
if (!_pSession) fail ("Test not available."); if (!_pSession) fail ("Test not available.");
@@ -1367,6 +1367,39 @@ void ODBCOracleTest::testDynamicAny()
} }
void ODBCOracleTest::testMultipleResults()
{
if (!_pSession) fail ("Test not available.");
std::string sql = "CREATE OR REPLACE "
"PROCEDURE multiResultsProcedure(paramAge1 IN NUMBER,"
" paramAge2 IN NUMBER,"
" ret1 OUT SYS_REFCURSOR, "
" ret2 OUT SYS_REFCURSOR,"
" ret3 OUT SYS_REFCURSOR) IS "
"BEGIN "
" OPEN ret1 FOR SELECT * FROM Person WHERE Age = paramAge1;"
" OPEN ret2 FOR SELECT Age FROM Person WHERE FirstName = 'Bart';"
" OPEN ret3 FOR SELECT * FROM Person WHERE Age = paramAge2;"
"END multiResultsProcedure;";
for (int i = 0; i < 8;)
{
recreatePersonTable();
*_pSession << sql, now;
_pSession->setFeature("autoBind", bindValues[i]);
_pSession->setFeature("autoExtract", bindValues[i+1]);
_pExecutor->multipleResults("{call multiResultsProcedure(?, ?)}");
i += 2;
}
}
void ODBCOracleTest::dropObject(const std::string& type, const std::string& name) void ODBCOracleTest::dropObject(const std::string& type, const std::string& name)
{ {
try try
@@ -1593,14 +1626,16 @@ bool ODBCOracleTest::init(const std::string& driver, const std::string& dsn)
_pExecutor = new SQLExecutor(driver + " SQL Executor", _pSession); _pExecutor = new SQLExecutor(driver + " SQL Executor", _pSession);
#ifdef POCO_OS_FAMILY_WINDOWS
// Workaround: // Workaround:
// //
// Barebone ODBC test is called initially for Oracle only. // Barebone ODBC test is called automatically on startup for Oracle.
// The test framework does not exit cleanly if // The test framework does not exit cleanly if
// Oracle tests are enabled (i.e. Oracle driver is found) // Oracle tests are enabled (i.e. Oracle driver is found)
// but no tests are executed. // but no tests are executed.
// The exact reason for this behavior is unknown at this time. // The exact reason for this behavior is unknown at this time.
testBarebone(); testBarebone();
#endif
return true; return true;
} }
@@ -1661,11 +1696,11 @@ 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, testStoredCursorProcedure); CppUnit_addTest(pSuite, ODBCOracleTest, testCursorStoredProcedure);
CppUnit_addTest(pSuite, ODBCOracleTest, testStoredProcedureAny); CppUnit_addTest(pSuite, ODBCOracleTest, testStoredProcedureAny);
CppUnit_addTest(pSuite, ODBCOracleTest, testStoredProcedureDynamicAny); CppUnit_addTest(pSuite, ODBCOracleTest, testStoredProcedureDynamicAny);
CppUnit_addTest(pSuite, ODBCOracleTest, testStoredFunction); CppUnit_addTest(pSuite, ODBCOracleTest, testStoredFunction);
CppUnit_addTest(pSuite, ODBCOracleTest, testStoredCursorFunction); CppUnit_addTest(pSuite, ODBCOracleTest, testCursorStoredFunction);
CppUnit_addTest(pSuite, ODBCOracleTest, testInternalExtraction); CppUnit_addTest(pSuite, ODBCOracleTest, testInternalExtraction);
CppUnit_addTest(pSuite, ODBCOracleTest, testInternalStorageType); CppUnit_addTest(pSuite, ODBCOracleTest, testInternalStorageType);
CppUnit_addTest(pSuite, ODBCOracleTest, testNull); CppUnit_addTest(pSuite, ODBCOracleTest, testNull);
@@ -1673,6 +1708,7 @@ CppUnit::Test* ODBCOracleTest::suite()
CppUnit_addTest(pSuite, ODBCOracleTest, testAsync); CppUnit_addTest(pSuite, ODBCOracleTest, testAsync);
CppUnit_addTest(pSuite, ODBCOracleTest, testAny); CppUnit_addTest(pSuite, ODBCOracleTest, testAny);
CppUnit_addTest(pSuite, ODBCOracleTest, testDynamicAny); CppUnit_addTest(pSuite, ODBCOracleTest, testDynamicAny);
CppUnit_addTest(pSuite, ODBCOracleTest, testMultipleResults);
return pSuite; return pSuite;
} }

View File

@@ -120,9 +120,9 @@ public:
void testInternalStorageType(); void testInternalStorageType();
void testStoredProcedure(); void testStoredProcedure();
void testStoredCursorProcedure(); void testCursorStoredProcedure();
void testStoredFunction(); void testStoredFunction();
void testStoredCursorFunction(); void testCursorStoredFunction();
void testStoredProcedureAny(); void testStoredProcedureAny();
void testStoredProcedureDynamicAny(); void testStoredProcedureDynamicAny();
@@ -134,6 +134,8 @@ public:
void testAny(); void testAny();
void testDynamicAny(); void testDynamicAny();
void testMultipleResults();
void setUp(); void setUp();
void tearDown(); void tearDown();

View File

@@ -123,7 +123,8 @@ void ODBCPostgreSQLTest::testBareboneODBC()
_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL, false); _pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL, false);
_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND, false); _pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND, false);
//neither pSQL ODBC nor Mammoth drivers support multiple results properly
/*
tableCreateString = "CREATE TABLE Test " tableCreateString = "CREATE TABLE Test "
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second INTEGER," "Second INTEGER,"
@@ -133,6 +134,7 @@ void ODBCPostgreSQLTest::testBareboneODBC()
_pExecutor->bareboneODBCMultiResultTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND); _pExecutor->bareboneODBCMultiResultTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND);
_pExecutor->bareboneODBCMultiResultTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL); _pExecutor->bareboneODBCMultiResultTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL);
_pExecutor->bareboneODBCMultiResultTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND); _pExecutor->bareboneODBCMultiResultTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND);
*/
} }
@@ -1113,6 +1115,8 @@ void ODBCPostgreSQLTest::testDynamicAny()
void ODBCPostgreSQLTest::testMultipleResults() void ODBCPostgreSQLTest::testMultipleResults()
{ {
//neither pSQL ODBC nor Mammoth drivers support multiple results properly
/*
if (!_pSession) fail ("Test not available."); if (!_pSession) fail ("Test not available.");
for (int i = 0; i < 8;) for (int i = 0; i < 8;)
@@ -1124,6 +1128,7 @@ void ODBCPostgreSQLTest::testMultipleResults()
i += 2; i += 2;
} }
*/
} }

View File

@@ -45,7 +45,7 @@
// uncomment to use Mammoth ODBCng driver // uncomment to use Mammoth ODBCng driver
//#define POCO_ODBC_USE_MAMMOTH_NG #define POCO_ODBC_USE_MAMMOTH_NG
class ODBCPostgreSQLTest: public CppUnit::TestCase class ODBCPostgreSQLTest: public CppUnit::TestCase

View File

@@ -987,14 +987,8 @@ Deprecated types are not supported as output parameters. Use current large obje
} }
void ODBCSQLServerTest::testStoredCursorProcedure() void ODBCSQLServerTest::testCursorStoredProcedure()
{ {
/*TODO: Support for returning recordsets from MS SQL Server is currently limited.
In order for it to work, nothing else but the recordset (not even output parameters)
can be returned.
To achieve full functionality, SQLMoreResults functionality probably must be incorporated
into the framework.
*/
if (!_pSession) fail ("Test not available."); if (!_pSession) fail ("Test not available.");
for (int k = 0; k < 8;) for (int k = 0; k < 8;)
@@ -1204,63 +1198,6 @@ void ODBCSQLServerTest::testStoredFunction()
} }
void ODBCSQLServerTest::testStoredCursorFunction()
{
/* TODO (see comments about errors below - probably needs SQLMoreResults to function properly)
if (!_pSession) fail ("Test not available.");
for (int k = 0; k < 8;)
{
_pSession->setFeature("autoBind", bindValues[k]);
_pSession->setFeature("autoExtract", bindValues[k+1]);
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;
dropObject("PROCEDURE", "storedCursorFunction");
*_pSession << "CREATE PROCEDURE storedCursorFunction(@ageLimit int) AS "
"BEGIN "
" SELECT * "
" FROM Person "
" WHERE Age < @ageLimit "
" ORDER BY Age DESC; "
" RETURN @ageLimit; "
"END;"
, now;
people.clear();
int age = 13;
int result = 0;
*_pSession << "{? = call storedCursorFunction(?)}", out(result), in(age), into(people), now;
//assert (result == age); //fails (result == 0)
assert (2 == people.size());
assert (Person("Simpson", "Bart", "Springfield", 12) == people[0]);
assert (Person("Simpson", "Lisa", "Springfield", 10) == people[1]);
result = 0;
Statement stmt = ((*_pSession << "{? = call storedCursorFunction(?)}", out(result), 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");//fails ([Microsoft][ODBC SQL Server Driver]Connection is busy with results for another hstmt")
dropObject("PROCEDURE", "storedCursorFunction");
k += 2;
}
*/
}
void ODBCSQLServerTest::testRowIterator() void ODBCSQLServerTest::testRowIterator()
{ {
if (!_pSession) fail ("Test not available."); if (!_pSession) fail ("Test not available.");
@@ -1638,11 +1575,10 @@ CppUnit::Test* ODBCSQLServerTest::suite()
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTuple); CppUnit_addTest(pSuite, ODBCSQLServerTest, testTuple);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testTupleVector); CppUnit_addTest(pSuite, ODBCSQLServerTest, testTupleVector);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testStoredProcedure); CppUnit_addTest(pSuite, ODBCSQLServerTest, testStoredProcedure);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testStoredCursorProcedure); CppUnit_addTest(pSuite, ODBCSQLServerTest, testCursorStoredProcedure);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testStoredProcedureAny); CppUnit_addTest(pSuite, ODBCSQLServerTest, testStoredProcedureAny);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testStoredProcedureDynamicAny); CppUnit_addTest(pSuite, ODBCSQLServerTest, testStoredProcedureDynamicAny);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testStoredFunction); CppUnit_addTest(pSuite, ODBCSQLServerTest, testStoredFunction);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testStoredCursorFunction);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testInternalExtraction); CppUnit_addTest(pSuite, ODBCSQLServerTest, testInternalExtraction);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testInternalStorageType); CppUnit_addTest(pSuite, ODBCSQLServerTest, testInternalStorageType);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testNull); CppUnit_addTest(pSuite, ODBCSQLServerTest, testNull);

View File

@@ -120,11 +120,10 @@ public:
void testTupleVector(); void testTupleVector();
void testStoredProcedure(); void testStoredProcedure();
void testStoredCursorProcedure(); void testCursorStoredProcedure();
void testStoredProcedureAny(); void testStoredProcedureAny();
void testStoredProcedureDynamicAny(); void testStoredProcedureDynamicAny();
void testStoredFunction(); void testStoredFunction();
void testStoredCursorFunction();
void testInternalExtraction(); void testInternalExtraction();
void testInternalStorageType(); void testInternalStorageType();

View File

@@ -56,12 +56,13 @@
#include <iterator> #include <iterator>
#define print_odbc_error(r, h) \ #define poco_odbc_check(r, h) \
if (!SQL_SUCCEEDED(r)) \ if (!SQL_SUCCEEDED(r)) \
{ \ { \
StatementException se(h); \ StatementException se(h); \
std::cout << se.toString() << std::endl; \ std::cout << se.toString() << std::endl; \
} } \
assert (SQL_SUCCEEDED(r));
using namespace Poco::Data; using namespace Poco::Data;
@@ -218,13 +219,13 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
// Environment begin // Environment begin
rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0); rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
// Connection begin // Connection begin
rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
POCO_SQLCHAR connectOutput[512] = {0}; POCO_SQLCHAR connectOutput[512] = {0};
SQLSMALLINT result; SQLSMALLINT result;
@@ -236,14 +237,14 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
, sizeof(connectOutput) , sizeof(connectOutput)
, &result , &result
, SQL_DRIVER_NOPROMPT); , SQL_DRIVER_NOPROMPT);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
// retrieve datetime type information for this DBMS // retrieve datetime type information for this DBMS
rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLGetTypeInfo(hstmt, SQL_TIMESTAMP); rc = SQLGetTypeInfo(hstmt, SQL_TIMESTAMP);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
SQLINTEGER dateTimeColSize = 0; SQLINTEGER dateTimeColSize = 0;
SQLSMALLINT dateTimeDecDigits = 0; SQLSMALLINT dateTimeDecDigits = 0;
@@ -252,19 +253,19 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
if (SQL_SUCCEEDED(rc)) if (SQL_SUCCEEDED(rc))
{ {
rc = SQLGetData(hstmt, 3, SQL_C_SLONG, &dateTimeColSize, sizeof(SQLINTEGER), 0); rc = SQLGetData(hstmt, 3, SQL_C_SLONG, &dateTimeColSize, sizeof(SQLINTEGER), 0);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLGetData(hstmt, 14, SQL_C_SSHORT, &dateTimeDecDigits, sizeof(SQLSMALLINT), 0); rc = SQLGetData(hstmt, 14, SQL_C_SSHORT, &dateTimeDecDigits, sizeof(SQLSMALLINT), 0);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
} }
else if (SQL_NO_DATA == rc) else if (SQL_NO_DATA == rc)
std::cerr << "Warning: no data type info returned by driver." << std::endl; std::cerr << "Warning: no data type info returned by driver." << std::endl;
rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
// Statement begin // Statement begin
rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
std::string sql = "DROP TABLE Test"; std::string sql = "DROP TABLE Test";
POCO_SQLCHAR* pStr = (POCO_SQLCHAR*) sql.c_str(); POCO_SQLCHAR* pStr = (POCO_SQLCHAR*) sql.c_str();
@@ -275,15 +276,15 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
sql = tableCreateString; sql = tableCreateString;
pStr = (POCO_SQLCHAR*) sql.c_str(); pStr = (POCO_SQLCHAR*) sql.c_str();
rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length()); rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length());
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLExecute(hstmt); rc = SQLExecute(hstmt);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
sql = "INSERT INTO Test VALUES (?,?,?,?,?,?)"; sql = "INSERT INTO Test VALUES (?,?,?,?,?,?)";
pStr = (POCO_SQLCHAR*) sql.c_str(); pStr = (POCO_SQLCHAR*) sql.c_str();
rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length()); rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length());
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
std::string str[3] = { "111", "222", "333" }; std::string str[3] = { "111", "222", "333" };
int fourth = 4; int fourth = 4;
@@ -314,7 +315,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
(SQLPOINTER) str[0].c_str(), (SQLPOINTER) str[0].c_str(),
size, size,
&li); &li);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
size = (SQLINTEGER) str[1].size(); size = (SQLINTEGER) str[1].size();
if (SQLExecutor::PB_AT_EXEC == bindMode) if (SQLExecutor::PB_AT_EXEC == bindMode)
@@ -330,7 +331,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
(SQLPOINTER) str[1].c_str(), (SQLPOINTER) str[1].c_str(),
size, size,
&li); &li);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
size = (SQLINTEGER) str[2].size(); size = (SQLINTEGER) str[2].size();
if (SQLExecutor::PB_AT_EXEC == bindMode) if (SQLExecutor::PB_AT_EXEC == bindMode)
@@ -347,7 +348,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
(SQLPOINTER) str[2].data(), (SQLPOINTER) str[2].data(),
size, size,
&li); &li);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLBindParameter(hstmt, rc = SQLBindParameter(hstmt,
(SQLUSMALLINT) 4, (SQLUSMALLINT) 4,
@@ -359,7 +360,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
(SQLPOINTER) &fourth, (SQLPOINTER) &fourth,
0, 0,
0); 0);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLBindParameter(hstmt, rc = SQLBindParameter(hstmt,
(SQLUSMALLINT) 5, (SQLUSMALLINT) 5,
@@ -371,7 +372,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
(SQLPOINTER) &fifth, (SQLPOINTER) &fifth,
0, 0,
0); 0);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLBindParameter(hstmt, rc = SQLBindParameter(hstmt,
(SQLUSMALLINT) 6, (SQLUSMALLINT) 6,
@@ -383,7 +384,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
(SQLPOINTER) &sixth, (SQLPOINTER) &sixth,
0, 0,
0); 0);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
size = 0; size = 0;
if (SQLExecutor::PB_AT_EXEC == bindMode) if (SQLExecutor::PB_AT_EXEC == bindMode)
@@ -414,12 +415,12 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
++i; ++i;
}while (SQL_NEED_DATA == (rc = SQLParamData(hstmt, &pParam))); }while (SQL_NEED_DATA == (rc = SQLParamData(hstmt, &pParam)));
} }
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
sql = "SELECT * FROM Test"; sql = "SELECT * FROM Test";
pStr = (POCO_SQLCHAR*) sql.c_str(); pStr = (POCO_SQLCHAR*) sql.c_str();
rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length()); rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length());
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
char chr[3][5] = {{ 0 }}; char chr[3][5] = {{ 0 }};
SQLLEN lengths[6] = { 0 }; SQLLEN lengths[6] = { 0 };
@@ -435,7 +436,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
(SQLPOINTER) chr[0], (SQLPOINTER) chr[0],
(SQLINTEGER) 4, (SQLINTEGER) 4,
&lengths[0]); &lengths[0]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLBindCol(hstmt, rc = SQLBindCol(hstmt,
(SQLUSMALLINT) 2, (SQLUSMALLINT) 2,
@@ -443,7 +444,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
(SQLPOINTER) chr[1], (SQLPOINTER) chr[1],
(SQLINTEGER) 4, (SQLINTEGER) 4,
&lengths[1]); &lengths[1]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLBindCol(hstmt, rc = SQLBindCol(hstmt,
(SQLUSMALLINT) 3, (SQLUSMALLINT) 3,
@@ -451,7 +452,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
(SQLPOINTER) chr[2], (SQLPOINTER) chr[2],
(SQLINTEGER) 4, (SQLINTEGER) 4,
&lengths[2]); &lengths[2]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLBindCol(hstmt, rc = SQLBindCol(hstmt,
(SQLUSMALLINT) 4, (SQLUSMALLINT) 4,
@@ -459,7 +460,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
(SQLPOINTER) &fourth, (SQLPOINTER) &fourth,
(SQLINTEGER) 0, (SQLINTEGER) 0,
&lengths[3]); &lengths[3]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLBindCol(hstmt, rc = SQLBindCol(hstmt,
(SQLUSMALLINT) 5, (SQLUSMALLINT) 5,
@@ -467,7 +468,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
(SQLPOINTER) &fifth, (SQLPOINTER) &fifth,
(SQLINTEGER) 0, (SQLINTEGER) 0,
&lengths[4]); &lengths[4]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLBindCol(hstmt, rc = SQLBindCol(hstmt,
(SQLUSMALLINT) 6, (SQLUSMALLINT) 6,
@@ -475,13 +476,13 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
(SQLPOINTER) &sixth, (SQLPOINTER) &sixth,
(SQLINTEGER) 0, (SQLINTEGER) 0,
&lengths[5]); &lengths[5]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
} }
rc = SQLExecute(hstmt); rc = SQLExecute(hstmt);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLFetch(hstmt); rc = SQLFetch(hstmt);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
if (SQLExecutor::DE_MANUAL == extractMode) if (SQLExecutor::DE_MANUAL == extractMode)
{ {
@@ -491,7 +492,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
chr[0], chr[0],
4, 4,
&lengths[0]); &lengths[0]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLGetData(hstmt, rc = SQLGetData(hstmt,
(SQLUSMALLINT) 2, (SQLUSMALLINT) 2,
@@ -499,7 +500,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
chr[1], chr[1],
4, 4,
&lengths[1]); &lengths[1]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLGetData(hstmt, rc = SQLGetData(hstmt,
(SQLUSMALLINT) 3, (SQLUSMALLINT) 3,
@@ -507,7 +508,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
chr[2], chr[2],
3, 3,
&lengths[2]); &lengths[2]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLGetData(hstmt, rc = SQLGetData(hstmt,
(SQLUSMALLINT) 4, (SQLUSMALLINT) 4,
@@ -515,7 +516,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
&fourth, &fourth,
0, 0,
&lengths[3]); &lengths[3]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLGetData(hstmt, rc = SQLGetData(hstmt,
(SQLUSMALLINT) 5, (SQLUSMALLINT) 5,
@@ -523,7 +524,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
&fifth, &fifth,
0, 0,
&lengths[4]); &lengths[4]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLGetData(hstmt, rc = SQLGetData(hstmt,
(SQLUSMALLINT) 6, (SQLUSMALLINT) 6,
@@ -531,7 +532,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
&sixth, &sixth,
0, 0,
&lengths[5]); &lengths[5]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
} }
assert (0 == strncmp("111", chr[0], 3)); assert (0 == strncmp("111", chr[0], 3));
@@ -550,25 +551,25 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
} }
rc = SQLCloseCursor(hstmt); rc = SQLCloseCursor(hstmt);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
sql = "DROP TABLE Test"; sql = "DROP TABLE Test";
pStr = (POCO_SQLCHAR*) sql.c_str(); pStr = (POCO_SQLCHAR*) sql.c_str();
rc = SQLExecDirect(hstmt, pStr, (SQLINTEGER) sql.length()); rc = SQLExecDirect(hstmt, pStr, (SQLINTEGER) sql.length());
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
// Connection end // Connection end
rc = SQLDisconnect(hdbc); rc = SQLDisconnect(hdbc);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLFreeHandle(SQL_HANDLE_DBC, hdbc); rc = SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
// Environment end // Environment end
rc = SQLFreeHandle(SQL_HANDLE_ENV, henv); rc = SQLFreeHandle(SQL_HANDLE_ENV, henv);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
} }
@@ -586,13 +587,13 @@ void SQLExecutor::bareboneODBCMultiResultTest(const std::string& dbConnString,
// Environment begin // Environment begin
rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0); rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
// Connection begin // Connection begin
rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
POCO_SQLCHAR connectOutput[512] = {0}; POCO_SQLCHAR connectOutput[512] = {0};
SQLSMALLINT result; SQLSMALLINT result;
@@ -604,11 +605,11 @@ void SQLExecutor::bareboneODBCMultiResultTest(const std::string& dbConnString,
, sizeof(connectOutput) , sizeof(connectOutput)
, &result , &result
, SQL_DRIVER_NOPROMPT); , SQL_DRIVER_NOPROMPT);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
// Statement begin // Statement begin
rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
std::string sql = "DROP TABLE Test"; std::string sql = "DROP TABLE Test";
POCO_SQLCHAR* pStr = (POCO_SQLCHAR*) sql.c_str(); POCO_SQLCHAR* pStr = (POCO_SQLCHAR*) sql.c_str();
@@ -619,17 +620,17 @@ void SQLExecutor::bareboneODBCMultiResultTest(const std::string& dbConnString,
sql = tableCreateString; sql = tableCreateString;
pStr = (POCO_SQLCHAR*) sql.c_str(); pStr = (POCO_SQLCHAR*) sql.c_str();
rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length()); rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length());
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLExecute(hstmt); rc = SQLExecute(hstmt);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
// insert multiple rows // insert multiple rows
pStr = (POCO_SQLCHAR*) insert.c_str(); pStr = (POCO_SQLCHAR*) insert.c_str();
rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) insert.length()); rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) insert.length());
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLExecute(hstmt); rc = SQLExecute(hstmt);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
do do
{ {
SQLINTEGER rowCount = 0; SQLINTEGER rowCount = 0;
@@ -638,10 +639,49 @@ void SQLExecutor::bareboneODBCMultiResultTest(const std::string& dbConnString,
} while (SQL_NO_DATA != SQLMoreResults(hstmt)); } while (SQL_NO_DATA != SQLMoreResults(hstmt));
// make sure all five rows made it in
sql = "select count(*) from Test";
int count = 0;
SQLLEN length = 0;
pStr = (POCO_SQLCHAR*) sql.c_str();
rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length());
poco_odbc_check (rc, hstmt);
if (SQLExecutor::DE_BOUND == extractMode)
{
rc = SQLBindCol(hstmt,
(SQLUSMALLINT) 1,
SQL_C_SLONG,
(SQLPOINTER) &count,
(SQLINTEGER) 0,
&length);
poco_odbc_check (rc, hstmt);
}
rc = SQLExecute(hstmt);
poco_odbc_check (rc, hstmt);
rc = SQLFetch(hstmt);
poco_odbc_check (rc, hstmt);
if (SQLExecutor::DE_MANUAL == extractMode)
{
rc = SQLGetData(hstmt,
(SQLUSMALLINT) 1,
SQL_C_SLONG,
&count,
0,
&length);
poco_odbc_check (rc, hstmt);
}
assert (5 == count);
rc = SQLCloseCursor(hstmt);
poco_odbc_check (rc, hstmt);
// select multiple rows // select multiple rows
pStr = (POCO_SQLCHAR*) select.c_str(); pStr = (POCO_SQLCHAR*) select.c_str();
rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) select.length()); rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) select.length());
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
char chr[5] = { 0 }; char chr[5] = { 0 };
SQLLEN lengths[3] = { 0 }; SQLLEN lengths[3] = { 0 };
@@ -656,7 +696,7 @@ void SQLExecutor::bareboneODBCMultiResultTest(const std::string& dbConnString,
(SQLPOINTER) chr, (SQLPOINTER) chr,
(SQLINTEGER) 4, (SQLINTEGER) 4,
&lengths[0]); &lengths[0]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLBindCol(hstmt, rc = SQLBindCol(hstmt,
(SQLUSMALLINT) 2, (SQLUSMALLINT) 2,
@@ -664,7 +704,7 @@ void SQLExecutor::bareboneODBCMultiResultTest(const std::string& dbConnString,
(SQLPOINTER) &second, (SQLPOINTER) &second,
(SQLINTEGER) 0, (SQLINTEGER) 0,
&lengths[1]); &lengths[1]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLBindCol(hstmt, rc = SQLBindCol(hstmt,
(SQLUSMALLINT) 3, (SQLUSMALLINT) 3,
@@ -672,22 +712,21 @@ void SQLExecutor::bareboneODBCMultiResultTest(const std::string& dbConnString,
(SQLPOINTER) &third, (SQLPOINTER) &third,
(SQLINTEGER) 0, (SQLINTEGER) 0,
&lengths[2]); &lengths[2]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
} }
rc = SQLExecute(hstmt); rc = SQLExecute(hstmt);
print_odbc_error (rc, hstmt); poco_odbc_check (rc, hstmt);
assert (SQL_SUCCEEDED(rc));
char one = 0x31; char one = 0x31;
int two = 2; int two = 2;
float three = 3.5; float three = 3.5;
count = 0;
do do
{ {
rc = SQLFetch(hstmt); rc = SQLFetch(hstmt);
print_odbc_error (rc, hstmt); poco_odbc_check (rc, hstmt);
assert (SQL_SUCCEEDED(rc));
if (SQLExecutor::DE_MANUAL == extractMode) if (SQLExecutor::DE_MANUAL == extractMode)
{ {
@@ -697,7 +736,7 @@ void SQLExecutor::bareboneODBCMultiResultTest(const std::string& dbConnString,
chr, chr,
4, 4,
&lengths[0]); &lengths[0]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLGetData(hstmt, rc = SQLGetData(hstmt,
(SQLUSMALLINT) 2, (SQLUSMALLINT) 2,
@@ -705,7 +744,7 @@ void SQLExecutor::bareboneODBCMultiResultTest(const std::string& dbConnString,
&second, &second,
0, 0,
&lengths[1]); &lengths[1]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLGetData(hstmt, rc = SQLGetData(hstmt,
(SQLUSMALLINT) 3, (SQLUSMALLINT) 3,
@@ -713,7 +752,7 @@ void SQLExecutor::bareboneODBCMultiResultTest(const std::string& dbConnString,
&third, &third,
0, 0,
&lengths[2]); &lengths[2]);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
} }
assert (one++ == chr[0]); assert (one++ == chr[0]);
@@ -721,25 +760,28 @@ void SQLExecutor::bareboneODBCMultiResultTest(const std::string& dbConnString,
assert (three == third); assert (three == third);
three += 1.0; three += 1.0;
++count;
} while (SQL_NO_DATA != SQLMoreResults(hstmt)); } while (SQL_NO_DATA != SQLMoreResults(hstmt));
assert (5 == count);
sql = "DROP TABLE Test"; sql = "DROP TABLE Test";
pStr = (POCO_SQLCHAR*) sql.c_str(); pStr = (POCO_SQLCHAR*) sql.c_str();
rc = SQLExecDirect(hstmt, pStr, (SQLINTEGER) sql.length()); rc = SQLExecDirect(hstmt, pStr, (SQLINTEGER) sql.length());
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
// Connection end // Connection end
rc = SQLDisconnect(hdbc); rc = SQLDisconnect(hdbc);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
rc = SQLFreeHandle(SQL_HANDLE_DBC, hdbc); rc = SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
// Environment end // Environment end
rc = SQLFreeHandle(SQL_HANDLE_ENV, henv); rc = SQLFreeHandle(SQL_HANDLE_ENV, henv);
assert (SQL_SUCCEEDED(rc)); poco_odbc_check (rc, hstmt);
} }
@@ -2569,7 +2611,7 @@ void SQLExecutor::dynamicAny()
} }
void SQLExecutor::multipleResults() void SQLExecutor::multipleResults(const std::string& sql)
{ {
typedef Tuple<std::string, std::string, std::string, int> Person; typedef Tuple<std::string, std::string, std::string, int> Person;
std::vector<Person> people; std::vector<Person> people;
@@ -2578,16 +2620,22 @@ void SQLExecutor::multipleResults()
people.push_back(Person("Simpson", "Lisa", "Springfield", 10)); people.push_back(Person("Simpson", "Lisa", "Springfield", 10));
*_pSession << "INSERT INTO Person VALUES (?, ?, ?, ?)", use(people), now; *_pSession << "INSERT INTO Person VALUES (?, ?, ?, ?)", use(people), now;
Person Homer, Lisa, Bart; Person pHomer, pLisa;
int aHomer(42), aLisa(10), aBart(0);
*_pSession << "SELECT * FROM Person WHERE FirstName = 'Homer'; " try {
"SELECT * FROM Person WHERE FirstName = 'Bart'; " *_pSession << sql
"SELECT * FROM Person WHERE FirstName = 'Lisa'; " , into(pHomer), use(aHomer)
, into(Homer, 0), into(Bart, 1), into(Lisa, 2) , into(aBart, 1)
, into(pLisa, 2), use(aLisa)
, now; , now;
} catch (StatementException& ex)
{
std::cout << ex.toString() << std::endl;
}
assert (Person("Simpson", "Homer", "Springfield", 42) == Homer); assert (Person("Simpson", "Homer", "Springfield", 42) == pHomer);
assert (Person("Simpson", "Bart", "Springfield", 12) == Bart); assert (12 == aBart);
assert (Person("Simpson", "Lisa", "Springfield", 10) == Lisa); assert (Person("Simpson", "Lisa", "Springfield", 10) == pLisa);
} }

View File

@@ -146,7 +146,10 @@ public:
void any(); void any();
void dynamicAny(); void dynamicAny();
void multipleResults(); void multipleResults(const std::string& sql =
"SELECT * FROM Person WHERE Age = ?; "
"SELECT Age FROM Person WHERE FirstName = 'Bart'; "
"SELECT * FROM Person WHERE Age = ?; ");
private: private:
static const std::string MULTI_INSERT; static const std::string MULTI_INSERT;

View File

@@ -600,7 +600,7 @@ Binding<T>* in(const T& t, const std::string& name = "")
template <typename T> template <typename T>
Binding<T>* out(const T& t, const std::string& name = "") Binding<T>* out(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);
@@ -610,7 +610,7 @@ Binding<T>* out(const T& t, const std::string& name = "")
template <typename T> template <typename T>
Binding<T>* io(const T& t, const std::string& name = "") Binding<T>* io(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);

View File

@@ -346,7 +346,6 @@ Poco::UInt32 StatementImpl::activateNextDataSet()
void StatementImpl::addExtract(AbstractExtraction* pExtraction) void StatementImpl::addExtract(AbstractExtraction* pExtraction)
{ {
poco_check_ptr (pExtraction); poco_check_ptr (pExtraction);
Poco::UInt32 pos = pExtraction->position(); Poco::UInt32 pos = pExtraction->position();
if (pos >= _extractors.size()) if (pos >= _extractors.size())
_extractors.resize(pos + 1); _extractors.resize(pos + 1);