mirror of
https://github.com/pocoproject/poco.git
synced 2025-01-18 08:22:37 +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;
|
||||
/// Returns number of columns returned by query.
|
||||
|
||||
virtual std::size_t affectedRowCount() const;
|
||||
virtual int affectedRowCount() const;
|
||||
/// Returns the number of affected rows.
|
||||
/// 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);
|
||||
/// Fetches the column.
|
||||
|
||||
std::size_t getAffectedRowCount() const;
|
||||
int getAffectedRowCount() const;
|
||||
|
||||
operator MYSQL_STMT* ();
|
||||
/// Cast operator to native handle type.
|
||||
@ -78,7 +78,7 @@ private:
|
||||
MYSQL* _pSessionHandle;
|
||||
MYSQL_STMT* _pHandle;
|
||||
int _state;
|
||||
std::size_t _affectedRowCount;
|
||||
int _affectedRowCount;
|
||||
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();
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ bool StatementExecutor::fetchColumn(std::size_t n, MYSQL_BIND *bind)
|
||||
return (res == 0);
|
||||
}
|
||||
|
||||
std::size_t StatementExecutor::getAffectedRowCount() const
|
||||
int StatementExecutor::getAffectedRowCount() const
|
||||
{
|
||||
return _affectedRowCount;
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ protected:
|
||||
std::size_t columnsReturned() const;
|
||||
/// Returns number of columns returned by query.
|
||||
|
||||
std::size_t affectedRowCount() const;
|
||||
int affectedRowCount() const;
|
||||
/// Returns the number of affected rows.
|
||||
/// 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)
|
||||
{
|
||||
|
@ -596,6 +596,7 @@ CppUnit::Test* ODBCDB2Test::suite()
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCDB2Test");
|
||||
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testBareboneODBC);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testZeroRows);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testSimpleAccess);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testComplexType);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testSimpleAccessVector);
|
||||
|
@ -421,6 +421,7 @@ CppUnit::Test* ODBCMySQLTest::suite()
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCMySQLTest");
|
||||
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testBareboneODBC);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testZeroRows);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testSimpleAccess);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testComplexType);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testSimpleAccessVector);
|
||||
|
@ -856,6 +856,7 @@ CppUnit::Test* ODBCOracleTest::suite()
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCOracleTest");
|
||||
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testBareboneODBC);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testZeroRows);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testSimpleAccess);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testComplexType);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testComplexTypeTuple);
|
||||
|
@ -585,6 +585,7 @@ CppUnit::Test* ODBCPostgreSQLTest::suite()
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCPostgreSQLTest");
|
||||
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testBareboneODBC);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testZeroRows);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSimpleAccess);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testComplexType);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSimpleAccessVector);
|
||||
|
@ -737,6 +737,7 @@ CppUnit::Test* ODBCSQLServerTest::suite()
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCSQLServerTest");
|
||||
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testBareboneODBC);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testZeroRows);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSimpleAccess);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testComplexType);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSimpleAccessVector);
|
||||
|
@ -325,6 +325,7 @@ CppUnit::Test* ODBCSQLiteTest::suite()
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCSQLiteTest");
|
||||
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testBareboneODBC);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testZeroRows);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSimpleAccess);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testComplexType);
|
||||
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()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
@ -49,6 +49,7 @@ public:
|
||||
|
||||
virtual void testBareboneODBC() = 0;
|
||||
|
||||
virtual void testZeroRows();
|
||||
virtual void testSimpleAccess();
|
||||
virtual void testComplexType();
|
||||
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()
|
||||
{
|
||||
std::string funct = "simpleAccess()";
|
||||
|
@ -115,6 +115,7 @@ public:
|
||||
/// (e.g. SQLGetData() restrictions relaxation policy, if any).
|
||||
/// If these test pass, subsequent tests failures are likely ours.
|
||||
|
||||
void zeroRows();
|
||||
void simpleAccess();
|
||||
void complexType();
|
||||
void complexTypeTuple();
|
||||
|
@ -54,7 +54,7 @@ protected:
|
||||
std::size_t columnsReturned() const;
|
||||
/// Returns number of columns returned by query.
|
||||
|
||||
std::size_t affectedRowCount() const;
|
||||
int affectedRowCount() const;
|
||||
/// Returns the number of affected rows.
|
||||
/// 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.
|
||||
@ -113,14 +113,14 @@ private:
|
||||
BinderPtr _pBinder;
|
||||
ExtractorPtr _pExtractor;
|
||||
MetaColumnVecVec _columns;
|
||||
std::size_t _affectedRowCount;
|
||||
int _affectedRowCount;
|
||||
StrPtr _pLeftover;
|
||||
BindIt _bindBegin;
|
||||
bool _canBind;
|
||||
bool _isExtracted;
|
||||
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 {
|
||||
|
||||
|
||||
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):
|
||||
@ -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;
|
||||
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()
|
||||
{
|
||||
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_addTest(pSuite, SQLiteTest, testBinding);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testZeroRows);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testSimpleAccess);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testInMemory);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testNullCharPointer);
|
||||
|
@ -35,6 +35,7 @@ public:
|
||||
~SQLiteTest();
|
||||
|
||||
void testBinding();
|
||||
void testZeroRows();
|
||||
void testSimpleAccess();
|
||||
void testInMemory();
|
||||
void testNullCharPointer();
|
||||
|
@ -416,7 +416,7 @@ private:
|
||||
Mutex _mutex;
|
||||
AsyncExecMethodPtr _pAsyncExec;
|
||||
std::vector<Any> _arguments;
|
||||
RowFormatter::Ptr _pRowFormatter;
|
||||
RowFormatter::Ptr _pRowFormatter;
|
||||
mutable std::string _stmtString;
|
||||
};
|
||||
|
||||
|
@ -161,9 +161,13 @@ protected:
|
||||
virtual std::size_t columnsReturned() const = 0;
|
||||
/// 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.
|
||||
/// 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;
|
||||
/// Returns column meta data.
|
||||
|
@ -144,7 +144,14 @@ std::size_t StatementImpl::executeWithLimit()
|
||||
else
|
||||
_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 (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;
|
||||
/// Returns number of columns returned by query.
|
||||
|
||||
std::size_t affectedRowCount() const;
|
||||
int affectedRowCount() const;
|
||||
/// Returns the number of affected rows.
|
||||
/// 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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user