mirror of
https://github.com/pocoproject/poco.git
synced 2025-01-18 16:37:13 +01:00
GH #499: Poco::Data::Statement::execute returns wrong value when zero results (ODBC)
This commit is contained in:
parent
55dffd864f
commit
86b81bfcbd
@ -50,7 +50,7 @@ protected:
|
|||||||
virtual std::size_t columnsReturned() const;
|
virtual std::size_t columnsReturned() const;
|
||||||
/// Returns number of columns returned by query.
|
/// Returns number of columns returned by query.
|
||||||
|
|
||||||
virtual std::size_t affectedRowCount() const;
|
virtual int affectedRowCount() const;
|
||||||
/// Returns the number of affected rows.
|
/// Returns the number of affected rows.
|
||||||
/// Used to find out the number of rows affected by insert, delete or update.
|
/// Used to find out the number of rows affected by insert, delete or update.
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ public:
|
|||||||
bool fetchColumn(std::size_t n, MYSQL_BIND *bind);
|
bool fetchColumn(std::size_t n, MYSQL_BIND *bind);
|
||||||
/// Fetches the column.
|
/// Fetches the column.
|
||||||
|
|
||||||
std::size_t getAffectedRowCount() const;
|
int getAffectedRowCount() const;
|
||||||
|
|
||||||
operator MYSQL_STMT* ();
|
operator MYSQL_STMT* ();
|
||||||
/// Cast operator to native handle type.
|
/// Cast operator to native handle type.
|
||||||
@ -78,7 +78,7 @@ private:
|
|||||||
MYSQL* _pSessionHandle;
|
MYSQL* _pSessionHandle;
|
||||||
MYSQL_STMT* _pHandle;
|
MYSQL_STMT* _pHandle;
|
||||||
int _state;
|
int _state;
|
||||||
std::size_t _affectedRowCount;
|
int _affectedRowCount;
|
||||||
std::string _query;
|
std::string _query;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ std::size_t MySQLStatementImpl::columnsReturned() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::size_t MySQLStatementImpl::affectedRowCount() const
|
int MySQLStatementImpl::affectedRowCount() const
|
||||||
{
|
{
|
||||||
return _stmt.getAffectedRowCount();
|
return _stmt.getAffectedRowCount();
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ bool StatementExecutor::fetchColumn(std::size_t n, MYSQL_BIND *bind)
|
|||||||
return (res == 0);
|
return (res == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t StatementExecutor::getAffectedRowCount() const
|
int StatementExecutor::getAffectedRowCount() const
|
||||||
{
|
{
|
||||||
return _affectedRowCount;
|
return _affectedRowCount;
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ protected:
|
|||||||
std::size_t columnsReturned() const;
|
std::size_t columnsReturned() const;
|
||||||
/// Returns number of columns returned by query.
|
/// Returns number of columns returned by query.
|
||||||
|
|
||||||
std::size_t affectedRowCount() const;
|
int affectedRowCount() const;
|
||||||
/// Returns the number of affected rows.
|
/// Returns the number of affected rows.
|
||||||
/// Used to find out the number of rows affected by insert or update.
|
/// Used to find out the number of rows affected by insert or update.
|
||||||
|
|
||||||
|
@ -440,7 +440,7 @@ const MetaColumn& ODBCStatementImpl::metaColumn(std::size_t pos) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::size_t ODBCStatementImpl::affectedRowCount() const
|
int ODBCStatementImpl::affectedRowCount() const
|
||||||
{
|
{
|
||||||
if (0 == _affectedRowCount)
|
if (0 == _affectedRowCount)
|
||||||
{
|
{
|
||||||
|
@ -596,6 +596,7 @@ CppUnit::Test* ODBCDB2Test::suite()
|
|||||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCDB2Test");
|
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCDB2Test");
|
||||||
|
|
||||||
CppUnit_addTest(pSuite, ODBCDB2Test, testBareboneODBC);
|
CppUnit_addTest(pSuite, ODBCDB2Test, testBareboneODBC);
|
||||||
|
CppUnit_addTest(pSuite, ODBCDB2Test, testZeroRows);
|
||||||
CppUnit_addTest(pSuite, ODBCDB2Test, testSimpleAccess);
|
CppUnit_addTest(pSuite, ODBCDB2Test, testSimpleAccess);
|
||||||
CppUnit_addTest(pSuite, ODBCDB2Test, testComplexType);
|
CppUnit_addTest(pSuite, ODBCDB2Test, testComplexType);
|
||||||
CppUnit_addTest(pSuite, ODBCDB2Test, testSimpleAccessVector);
|
CppUnit_addTest(pSuite, ODBCDB2Test, testSimpleAccessVector);
|
||||||
|
@ -421,6 +421,7 @@ CppUnit::Test* ODBCMySQLTest::suite()
|
|||||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCMySQLTest");
|
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCMySQLTest");
|
||||||
|
|
||||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testBareboneODBC);
|
CppUnit_addTest(pSuite, ODBCMySQLTest, testBareboneODBC);
|
||||||
|
CppUnit_addTest(pSuite, ODBCMySQLTest, testZeroRows);
|
||||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testSimpleAccess);
|
CppUnit_addTest(pSuite, ODBCMySQLTest, testSimpleAccess);
|
||||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testComplexType);
|
CppUnit_addTest(pSuite, ODBCMySQLTest, testComplexType);
|
||||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testSimpleAccessVector);
|
CppUnit_addTest(pSuite, ODBCMySQLTest, testSimpleAccessVector);
|
||||||
|
@ -856,6 +856,7 @@ CppUnit::Test* ODBCOracleTest::suite()
|
|||||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCOracleTest");
|
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCOracleTest");
|
||||||
|
|
||||||
CppUnit_addTest(pSuite, ODBCOracleTest, testBareboneODBC);
|
CppUnit_addTest(pSuite, ODBCOracleTest, testBareboneODBC);
|
||||||
|
CppUnit_addTest(pSuite, ODBCOracleTest, testZeroRows);
|
||||||
CppUnit_addTest(pSuite, ODBCOracleTest, testSimpleAccess);
|
CppUnit_addTest(pSuite, ODBCOracleTest, testSimpleAccess);
|
||||||
CppUnit_addTest(pSuite, ODBCOracleTest, testComplexType);
|
CppUnit_addTest(pSuite, ODBCOracleTest, testComplexType);
|
||||||
CppUnit_addTest(pSuite, ODBCOracleTest, testComplexTypeTuple);
|
CppUnit_addTest(pSuite, ODBCOracleTest, testComplexTypeTuple);
|
||||||
|
@ -585,6 +585,7 @@ CppUnit::Test* ODBCPostgreSQLTest::suite()
|
|||||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCPostgreSQLTest");
|
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCPostgreSQLTest");
|
||||||
|
|
||||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testBareboneODBC);
|
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testBareboneODBC);
|
||||||
|
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testZeroRows);
|
||||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSimpleAccess);
|
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSimpleAccess);
|
||||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testComplexType);
|
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testComplexType);
|
||||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSimpleAccessVector);
|
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSimpleAccessVector);
|
||||||
|
@ -737,6 +737,7 @@ CppUnit::Test* ODBCSQLServerTest::suite()
|
|||||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCSQLServerTest");
|
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCSQLServerTest");
|
||||||
|
|
||||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testBareboneODBC);
|
CppUnit_addTest(pSuite, ODBCSQLServerTest, testBareboneODBC);
|
||||||
|
CppUnit_addTest(pSuite, ODBCSQLServerTest, testZeroRows);
|
||||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSimpleAccess);
|
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSimpleAccess);
|
||||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testComplexType);
|
CppUnit_addTest(pSuite, ODBCSQLServerTest, testComplexType);
|
||||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSimpleAccessVector);
|
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSimpleAccessVector);
|
||||||
|
@ -325,6 +325,7 @@ CppUnit::Test* ODBCSQLiteTest::suite()
|
|||||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCSQLiteTest");
|
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCSQLiteTest");
|
||||||
|
|
||||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testBareboneODBC);
|
CppUnit_addTest(pSuite, ODBCSQLiteTest, testBareboneODBC);
|
||||||
|
CppUnit_addTest(pSuite, ODBCSQLiteTest, testZeroRows);
|
||||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSimpleAccess);
|
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSimpleAccess);
|
||||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testComplexType);
|
CppUnit_addTest(pSuite, ODBCSQLiteTest, testComplexType);
|
||||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSimpleAccessVector);
|
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSimpleAccessVector);
|
||||||
|
@ -79,6 +79,23 @@ ODBCTest::~ODBCTest()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ODBCTest::testZeroRows()
|
||||||
|
{
|
||||||
|
if (!_pSession) fail ("Test not available.");
|
||||||
|
|
||||||
|
std::string tableName("Person");
|
||||||
|
|
||||||
|
for (int i = 0; i < 8;)
|
||||||
|
{
|
||||||
|
recreatePersonTable();
|
||||||
|
_pSession->setFeature("autoBind", bindValue(i));
|
||||||
|
_pSession->setFeature("autoExtract", bindValue(i+1));
|
||||||
|
_pExecutor->zeroRows();
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ODBCTest::testSimpleAccess()
|
void ODBCTest::testSimpleAccess()
|
||||||
{
|
{
|
||||||
if (!_pSession) fail ("Test not available.");
|
if (!_pSession) fail ("Test not available.");
|
||||||
|
@ -49,6 +49,7 @@ public:
|
|||||||
|
|
||||||
virtual void testBareboneODBC() = 0;
|
virtual void testBareboneODBC() = 0;
|
||||||
|
|
||||||
|
virtual void testZeroRows();
|
||||||
virtual void testSimpleAccess();
|
virtual void testSimpleAccess();
|
||||||
virtual void testComplexType();
|
virtual void testComplexType();
|
||||||
virtual void testComplexTypeTuple();
|
virtual void testComplexTypeTuple();
|
||||||
|
@ -942,6 +942,13 @@ void SQLExecutor::execute(const std::string& sql)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SQLExecutor::zeroRows()
|
||||||
|
{
|
||||||
|
Statement stmt = (session() << "SELECT * FROM Person WHERE 0 = 1");
|
||||||
|
assert(0 == stmt.execute());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SQLExecutor::simpleAccess()
|
void SQLExecutor::simpleAccess()
|
||||||
{
|
{
|
||||||
std::string funct = "simpleAccess()";
|
std::string funct = "simpleAccess()";
|
||||||
|
@ -115,6 +115,7 @@ public:
|
|||||||
/// (e.g. SQLGetData() restrictions relaxation policy, if any).
|
/// (e.g. SQLGetData() restrictions relaxation policy, if any).
|
||||||
/// If these test pass, subsequent tests failures are likely ours.
|
/// If these test pass, subsequent tests failures are likely ours.
|
||||||
|
|
||||||
|
void zeroRows();
|
||||||
void simpleAccess();
|
void simpleAccess();
|
||||||
void complexType();
|
void complexType();
|
||||||
void complexTypeTuple();
|
void complexTypeTuple();
|
||||||
|
@ -54,7 +54,7 @@ protected:
|
|||||||
std::size_t columnsReturned() const;
|
std::size_t columnsReturned() const;
|
||||||
/// Returns number of columns returned by query.
|
/// Returns number of columns returned by query.
|
||||||
|
|
||||||
std::size_t affectedRowCount() const;
|
int affectedRowCount() const;
|
||||||
/// Returns the number of affected rows.
|
/// Returns the number of affected rows.
|
||||||
/// Used to find out the number of rows affected by insert, delete or update.
|
/// Used to find out the number of rows affected by insert, delete or update.
|
||||||
/// All changes are counted, even if they are later undone by a ROLLBACK or ABORT.
|
/// All changes are counted, even if they are later undone by a ROLLBACK or ABORT.
|
||||||
@ -113,14 +113,14 @@ private:
|
|||||||
BinderPtr _pBinder;
|
BinderPtr _pBinder;
|
||||||
ExtractorPtr _pExtractor;
|
ExtractorPtr _pExtractor;
|
||||||
MetaColumnVecVec _columns;
|
MetaColumnVecVec _columns;
|
||||||
std::size_t _affectedRowCount;
|
int _affectedRowCount;
|
||||||
StrPtr _pLeftover;
|
StrPtr _pLeftover;
|
||||||
BindIt _bindBegin;
|
BindIt _bindBegin;
|
||||||
bool _canBind;
|
bool _canBind;
|
||||||
bool _isExtracted;
|
bool _isExtracted;
|
||||||
bool _canCompile;
|
bool _canCompile;
|
||||||
|
|
||||||
static const std::size_t POCO_SQLITE_INV_ROW_CNT;
|
static const int POCO_SQLITE_INV_ROW_CNT;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ namespace Data {
|
|||||||
namespace SQLite {
|
namespace SQLite {
|
||||||
|
|
||||||
|
|
||||||
const std::size_t SQLiteStatementImpl::POCO_SQLITE_INV_ROW_CNT = std::numeric_limits<std::size_t>::max();
|
const int SQLiteStatementImpl::POCO_SQLITE_INV_ROW_CNT = std::numeric_limits<std::size_t>::max();
|
||||||
|
|
||||||
|
|
||||||
SQLiteStatementImpl::SQLiteStatementImpl(Poco::Data::SessionImpl& rSession, sqlite3* pDB):
|
SQLiteStatementImpl::SQLiteStatementImpl(Poco::Data::SessionImpl& rSession, sqlite3* pDB):
|
||||||
@ -302,7 +302,7 @@ const MetaColumn& SQLiteStatementImpl::metaColumn(std::size_t pos) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::size_t SQLiteStatementImpl::affectedRowCount() const
|
int SQLiteStatementImpl::affectedRowCount() const
|
||||||
{
|
{
|
||||||
if (_affectedRowCount != POCO_SQLITE_INV_ROW_CNT) return _affectedRowCount;
|
if (_affectedRowCount != POCO_SQLITE_INV_ROW_CNT) return _affectedRowCount;
|
||||||
return _pStmt == 0 || sqlite3_stmt_readonly(_pStmt) ? 0 : sqlite3_changes(_pDB);
|
return _pStmt == 0 || sqlite3_stmt_readonly(_pStmt) ? 0 : sqlite3_changes(_pDB);
|
||||||
|
@ -295,6 +295,16 @@ void SQLiteTest::testBinding()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SQLiteTest::testZeroRows()
|
||||||
|
{
|
||||||
|
Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||||
|
tmp << "DROP TABLE IF EXISTS ZeroTest", now;
|
||||||
|
tmp << "CREATE TABLE IF NOT EXISTS ZeroTest (zt INTEGER(3))", now;
|
||||||
|
Statement stmt = (tmp << "SELECT * FROM ZeroTest");
|
||||||
|
assert(0 == stmt.execute());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SQLiteTest::testSimpleAccess()
|
void SQLiteTest::testSimpleAccess()
|
||||||
{
|
{
|
||||||
Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||||
@ -3361,6 +3371,7 @@ CppUnit::Test* SQLiteTest::suite()
|
|||||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SQLiteTest");
|
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SQLiteTest");
|
||||||
|
|
||||||
CppUnit_addTest(pSuite, SQLiteTest, testBinding);
|
CppUnit_addTest(pSuite, SQLiteTest, testBinding);
|
||||||
|
CppUnit_addTest(pSuite, SQLiteTest, testZeroRows);
|
||||||
CppUnit_addTest(pSuite, SQLiteTest, testSimpleAccess);
|
CppUnit_addTest(pSuite, SQLiteTest, testSimpleAccess);
|
||||||
CppUnit_addTest(pSuite, SQLiteTest, testInMemory);
|
CppUnit_addTest(pSuite, SQLiteTest, testInMemory);
|
||||||
CppUnit_addTest(pSuite, SQLiteTest, testNullCharPointer);
|
CppUnit_addTest(pSuite, SQLiteTest, testNullCharPointer);
|
||||||
|
@ -35,6 +35,7 @@ public:
|
|||||||
~SQLiteTest();
|
~SQLiteTest();
|
||||||
|
|
||||||
void testBinding();
|
void testBinding();
|
||||||
|
void testZeroRows();
|
||||||
void testSimpleAccess();
|
void testSimpleAccess();
|
||||||
void testInMemory();
|
void testInMemory();
|
||||||
void testNullCharPointer();
|
void testNullCharPointer();
|
||||||
|
@ -416,7 +416,7 @@ private:
|
|||||||
Mutex _mutex;
|
Mutex _mutex;
|
||||||
AsyncExecMethodPtr _pAsyncExec;
|
AsyncExecMethodPtr _pAsyncExec;
|
||||||
std::vector<Any> _arguments;
|
std::vector<Any> _arguments;
|
||||||
RowFormatter::Ptr _pRowFormatter;
|
RowFormatter::Ptr _pRowFormatter;
|
||||||
mutable std::string _stmtString;
|
mutable std::string _stmtString;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -161,9 +161,13 @@ protected:
|
|||||||
virtual std::size_t columnsReturned() const = 0;
|
virtual std::size_t columnsReturned() const = 0;
|
||||||
/// Returns number of columns returned by query.
|
/// Returns number of columns returned by query.
|
||||||
|
|
||||||
virtual std::size_t affectedRowCount() const = 0;
|
virtual int affectedRowCount() const = 0;
|
||||||
/// Returns the number of affected rows.
|
/// Returns the number of affected rows.
|
||||||
/// Used to find out the number of rows affected by insert, delete or update.
|
/// Used to find out the number of rows affected by insert, delete or update.
|
||||||
|
///
|
||||||
|
/// Some back-ends may return a negative number in certain circumstances (e.g.
|
||||||
|
/// some ODBC drivers when this function is called after a select statement
|
||||||
|
/// execution).
|
||||||
|
|
||||||
virtual const MetaColumn& metaColumn(std::size_t pos) const = 0;
|
virtual const MetaColumn& metaColumn(std::size_t pos) const = 0;
|
||||||
/// Returns column meta data.
|
/// Returns column meta data.
|
||||||
|
@ -144,7 +144,14 @@ std::size_t StatementImpl::executeWithLimit()
|
|||||||
else
|
else
|
||||||
_state = ST_PAUSED;
|
_state = ST_PAUSED;
|
||||||
|
|
||||||
return count ? count : affectedRowCount();
|
int affectedRows = affectedRowCount();
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
if (affectedRows > 0)
|
||||||
|
return affectedRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -159,7 +166,14 @@ std::size_t StatementImpl::executeWithoutLimit()
|
|||||||
while (hasNext()) count += next();
|
while (hasNext()) count += next();
|
||||||
} while (canBind());
|
} while (canBind());
|
||||||
|
|
||||||
return count ? count : affectedRowCount();
|
int affectedRows = affectedRowCount();
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
if (affectedRows > 0)
|
||||||
|
return affectedRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ protected:
|
|||||||
std::size_t columnsReturned() const;
|
std::size_t columnsReturned() const;
|
||||||
/// Returns number of columns returned by query.
|
/// Returns number of columns returned by query.
|
||||||
|
|
||||||
std::size_t affectedRowCount() const;
|
int affectedRowCount() const;
|
||||||
/// Returns the number of affected rows.
|
/// Returns the number of affected rows.
|
||||||
/// Used to find out the number of rows affected by insert or update.
|
/// Used to find out the number of rows affected by insert or update.
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ inline AbstractBinding::BinderPtr TestStatementImpl::binder()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline std::size_t TestStatementImpl::affectedRowCount() const
|
inline int TestStatementImpl::affectedRowCount() const
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user