mirror of
https://github.com/pocoproject/poco.git
synced 2025-04-26 18:11:29 +02:00
fix(Data): RecordSet issue since 1.10.0 (#4739)
* fix(Data): RecordSet issue since 1.10.0 * fix(RecordSet): copy, move #4525
This commit is contained in:
parent
e5752a5c6d
commit
9a97e7ca0d
@ -238,6 +238,29 @@ private:
|
|||||||
} } // namespace Poco::Data
|
} } // namespace Poco::Data
|
||||||
|
|
||||||
|
|
||||||
|
RecordSet getRecordsetMove(Session& session, const std::string& sql)
|
||||||
|
{
|
||||||
|
Statement select(session);
|
||||||
|
select << sql;
|
||||||
|
select.execute();
|
||||||
|
|
||||||
|
// return directly
|
||||||
|
return RecordSet(select);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RecordSet getRecordsetCopyRVO(Session& session, const std::string& sql)
|
||||||
|
{
|
||||||
|
Statement select(session);
|
||||||
|
select << sql;
|
||||||
|
select.execute();
|
||||||
|
|
||||||
|
// return temp copy (RVO)
|
||||||
|
RecordSet recordSet(select);
|
||||||
|
return recordSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int SQLiteTest::_insertCounter;
|
int SQLiteTest::_insertCounter;
|
||||||
int SQLiteTest::_updateCounter;
|
int SQLiteTest::_updateCounter;
|
||||||
int SQLiteTest::_deleteCounter;
|
int SQLiteTest::_deleteCounter;
|
||||||
@ -3636,6 +3659,96 @@ void SQLiteTest::testTransactionTypeProperty()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SQLiteTest::testRecordsetCopyMove()
|
||||||
|
{
|
||||||
|
Session session(Poco::Data::SQLite::Connector::KEY, ":memory:");
|
||||||
|
|
||||||
|
{
|
||||||
|
auto recordSet = getRecordsetMove(session, "SELECT sqlite_version()");
|
||||||
|
assertTrue(recordSet.moveFirst());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto recordSet = getRecordsetCopyRVO(session, "SELECT sqlite_version()");
|
||||||
|
assertTrue(recordSet.moveFirst());
|
||||||
|
}
|
||||||
|
|
||||||
|
session << "CREATE TABLE Vectors (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now;
|
||||||
|
|
||||||
|
std::vector<Tuple<int, double, std::string> > v;
|
||||||
|
v.push_back(Tuple<int, double, std::string>(1, 1.5f, "3"));
|
||||||
|
v.push_back(Tuple<int, double, std::string>(2, 2.5f, "4"));
|
||||||
|
v.push_back(Tuple<int, double, std::string>(3, 3.5f, "5"));
|
||||||
|
v.push_back(Tuple<int, double, std::string>(4, 4.5f, "6"));
|
||||||
|
|
||||||
|
session << "INSERT INTO Vectors VALUES (?,?,?)", use(v), now;
|
||||||
|
|
||||||
|
RecordSet rset(session, "SELECT * FROM Vectors");
|
||||||
|
std::ostringstream osLoop;
|
||||||
|
RecordSet::Iterator it = rset.begin();
|
||||||
|
RecordSet::Iterator end = rset.end();
|
||||||
|
for (int i = 1; it != end; ++it, ++i)
|
||||||
|
{
|
||||||
|
assertTrue(it->get(0) == i);
|
||||||
|
osLoop << *it;
|
||||||
|
}
|
||||||
|
assertTrue(!osLoop.str().empty());
|
||||||
|
std::ostringstream osCopy;
|
||||||
|
std::copy(rset.begin(), rset.end(), std::ostream_iterator<Row>(osCopy));
|
||||||
|
assertTrue(osLoop.str() == osCopy.str());
|
||||||
|
|
||||||
|
// copy
|
||||||
|
RecordSet rsetCopy(rset);
|
||||||
|
osLoop.str("");
|
||||||
|
it = rsetCopy.begin();
|
||||||
|
end = rsetCopy.end();
|
||||||
|
for (int i = 1; it != end; ++it, ++i)
|
||||||
|
{
|
||||||
|
assertTrue(it->get(0) == i);
|
||||||
|
osLoop << *it;
|
||||||
|
}
|
||||||
|
assertTrue(!osLoop.str().empty());
|
||||||
|
|
||||||
|
osCopy.str("");
|
||||||
|
std::copy(rsetCopy.begin(), rsetCopy.end(), std::ostream_iterator<Row>(osCopy));
|
||||||
|
assertTrue(osLoop.str() == osCopy.str());
|
||||||
|
|
||||||
|
// move
|
||||||
|
RecordSet rsetMove(std::move(rsetCopy));
|
||||||
|
osLoop.str("");
|
||||||
|
it = rsetMove.begin();
|
||||||
|
end = rsetMove.end();
|
||||||
|
for (int i = 1; it != end; ++it, ++i)
|
||||||
|
{
|
||||||
|
assertTrue(it->get(0) == i);
|
||||||
|
osLoop << *it;
|
||||||
|
}
|
||||||
|
assertTrue(!osLoop.str().empty());
|
||||||
|
|
||||||
|
osCopy.str("");
|
||||||
|
std::copy(rsetMove.begin(), rsetMove.end(), std::ostream_iterator<Row>(osCopy));
|
||||||
|
assertTrue(osLoop.str() == osCopy.str());
|
||||||
|
|
||||||
|
// moved from object must remain in valid unspecified state
|
||||||
|
// and can be reused
|
||||||
|
assertEqual(0, rsetCopy.rowCount());
|
||||||
|
rsetCopy = (session << "SELECT * FROM Vectors", now);
|
||||||
|
assertEqual(v.size(), rsetCopy.rowCount());
|
||||||
|
osLoop.str("");
|
||||||
|
it = rsetCopy.begin();
|
||||||
|
end = rsetCopy.end();
|
||||||
|
for (int i = 1; it != end; ++it, ++i)
|
||||||
|
{
|
||||||
|
assertTrue(it->get(0) == i);
|
||||||
|
osLoop << *it;
|
||||||
|
}
|
||||||
|
assertTrue(!osLoop.str().empty());
|
||||||
|
osCopy.str("");
|
||||||
|
std::copy(rsetCopy.begin(), rsetCopy.end(), std::ostream_iterator<Row>(osCopy));
|
||||||
|
assertTrue(osLoop.str() == osCopy.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SQLiteTest::setUp()
|
void SQLiteTest::setUp()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -3746,6 +3859,7 @@ CppUnit::Test* SQLiteTest::suite()
|
|||||||
CppUnit_addTest(pSuite, SQLiteTest, testFTS3);
|
CppUnit_addTest(pSuite, SQLiteTest, testFTS3);
|
||||||
CppUnit_addTest(pSuite, SQLiteTest, testIllegalFilePath);
|
CppUnit_addTest(pSuite, SQLiteTest, testIllegalFilePath);
|
||||||
CppUnit_addTest(pSuite, SQLiteTest, testTransactionTypeProperty);
|
CppUnit_addTest(pSuite, SQLiteTest, testTransactionTypeProperty);
|
||||||
|
CppUnit_addTest(pSuite, SQLiteTest, testRecordsetCopyMove);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
}
|
}
|
||||||
|
@ -144,6 +144,8 @@ public:
|
|||||||
void testIllegalFilePath();
|
void testIllegalFilePath();
|
||||||
void testTransactionTypeProperty();
|
void testTransactionTypeProperty();
|
||||||
|
|
||||||
|
void testRecordsetCopyMove();
|
||||||
|
|
||||||
void setUp();
|
void setUp();
|
||||||
void tearDown();
|
void tearDown();
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ class Data_API RecordSet: private Statement
|
|||||||
/// a limit for the Statement.
|
/// a limit for the Statement.
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using RowMap = std::map<std::size_t, Row*>;
|
using RowMap = std::map<std::size_t, std::shared_ptr<Row>>;
|
||||||
using ConstIterator = const RowIterator;
|
using ConstIterator = const RowIterator;
|
||||||
using Iterator = RowIterator;
|
using Iterator = RowIterator;
|
||||||
|
|
||||||
|
@ -524,6 +524,9 @@ protected:
|
|||||||
Session session();
|
Session session();
|
||||||
/// Returns the underlying session.
|
/// Returns the underlying session.
|
||||||
|
|
||||||
|
void clear() noexcept;
|
||||||
|
/// Clears the statement.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Result& doAsyncExec(bool reset = true);
|
const Result& doAsyncExec(bool reset = true);
|
||||||
/// Asynchronously executes the statement.
|
/// Asynchronously executes the statement.
|
||||||
|
@ -60,10 +60,11 @@ RecordSet::RecordSet(Session& rSession,
|
|||||||
|
|
||||||
|
|
||||||
RecordSet::RecordSet(const RecordSet& other):
|
RecordSet::RecordSet(const RecordSet& other):
|
||||||
Statement(other.impl()),
|
Statement(other),
|
||||||
_currentRow(other._currentRow),
|
_currentRow(other._currentRow),
|
||||||
_pBegin(new RowIterator(this, 0 == rowsExtracted())),
|
_pBegin(new RowIterator(this, 0 == rowsExtracted())),
|
||||||
_pEnd(new RowIterator(this, true)),
|
_pEnd(new RowIterator(this, true)),
|
||||||
|
_rowMap(other._rowMap),
|
||||||
_pFilter(other._pFilter),
|
_pFilter(other._pFilter),
|
||||||
_totalRowCount(other._totalRowCount)
|
_totalRowCount(other._totalRowCount)
|
||||||
{
|
{
|
||||||
@ -72,12 +73,21 @@ RecordSet::RecordSet(const RecordSet& other):
|
|||||||
|
|
||||||
RecordSet::RecordSet(RecordSet&& other) noexcept:
|
RecordSet::RecordSet(RecordSet&& other) noexcept:
|
||||||
Statement(std::move(other)),
|
Statement(std::move(other)),
|
||||||
_currentRow(std::move(other._currentRow)),
|
_currentRow(other._currentRow),
|
||||||
_pBegin(std::move(other._pBegin)),
|
_pBegin(new RowIterator(this, 0 == rowsExtracted())),
|
||||||
_pEnd(std::move(other._pEnd)),
|
_pEnd(new RowIterator(this, true)),
|
||||||
_pFilter(std::move(other._pFilter)),
|
_rowMap(std::move(other._rowMap)),
|
||||||
_totalRowCount(std::move(other._totalRowCount))
|
_pFilter(other._pFilter),
|
||||||
|
_totalRowCount(other._totalRowCount)
|
||||||
{
|
{
|
||||||
|
other._currentRow = 0;
|
||||||
|
delete other._pBegin;
|
||||||
|
other._pBegin = nullptr;
|
||||||
|
delete other._pEnd;
|
||||||
|
other._pEnd = nullptr;
|
||||||
|
other._rowMap.clear();
|
||||||
|
other._pFilter.reset();
|
||||||
|
other._totalRowCount = UNKNOWN_TOTAL_ROW_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -87,10 +97,6 @@ RecordSet::~RecordSet()
|
|||||||
{
|
{
|
||||||
delete _pBegin;
|
delete _pBegin;
|
||||||
delete _pEnd;
|
delete _pEnd;
|
||||||
|
|
||||||
RowMap::iterator it = _rowMap.begin();
|
|
||||||
RowMap::iterator end = _rowMap.end();
|
|
||||||
for (; it != end; ++it) delete it->second;
|
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
@ -103,10 +109,19 @@ RecordSet& RecordSet::operator = (RecordSet&& other) noexcept
|
|||||||
{
|
{
|
||||||
Statement::operator = (std::move(other));
|
Statement::operator = (std::move(other));
|
||||||
_currentRow = std::move(other._currentRow);
|
_currentRow = std::move(other._currentRow);
|
||||||
_pBegin = std::move(other._pBegin);
|
other._currentRow = 0;
|
||||||
_pEnd = std::move(other._pEnd);
|
_pBegin = new RowIterator(this, 0 == rowsExtracted());
|
||||||
|
delete other._pBegin;
|
||||||
|
other._pBegin = nullptr;
|
||||||
|
_pEnd = new RowIterator(this, true);
|
||||||
|
delete other._pEnd;
|
||||||
|
other._pEnd = nullptr;
|
||||||
|
_rowMap = std::move(other._rowMap);
|
||||||
|
other._rowMap.clear();
|
||||||
_pFilter = std::move(other._pFilter);
|
_pFilter = std::move(other._pFilter);
|
||||||
|
other._pFilter.reset();
|
||||||
_totalRowCount = std::move(other._totalRowCount);
|
_totalRowCount = std::move(other._totalRowCount);
|
||||||
|
other._totalRowCount = UNKNOWN_TOTAL_ROW_COUNT;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -121,9 +136,6 @@ void RecordSet::reset(const Statement& stmt)
|
|||||||
_currentRow = 0;
|
_currentRow = 0;
|
||||||
_totalRowCount = UNKNOWN_TOTAL_ROW_COUNT;
|
_totalRowCount = UNKNOWN_TOTAL_ROW_COUNT;
|
||||||
|
|
||||||
RowMap::iterator it = _rowMap.begin();
|
|
||||||
RowMap::iterator end = _rowMap.end();
|
|
||||||
for (; it != end; ++it) delete it->second;
|
|
||||||
_rowMap.clear();
|
_rowMap.clear();
|
||||||
|
|
||||||
Statement::operator = (stmt);
|
Statement::operator = (stmt);
|
||||||
@ -487,7 +499,7 @@ Row& RecordSet::row(std::size_t pos)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pRow = it->second;
|
pRow = it->second.get();
|
||||||
poco_check_ptr (pRow);
|
poco_check_ptr (pRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -497,7 +509,7 @@ Row& RecordSet::row(std::size_t pos)
|
|||||||
|
|
||||||
std::size_t RecordSet::rowCount() const
|
std::size_t RecordSet::rowCount() const
|
||||||
{
|
{
|
||||||
if (extractions().size() == 0) return 0;
|
if (!impl() || extractions().size() == 0) return 0;
|
||||||
|
|
||||||
std::size_t rc = subTotalRowCount();
|
std::size_t rc = subTotalRowCount();
|
||||||
if (!isFiltered()) return rc;
|
if (!isFiltered()) return rc;
|
||||||
|
@ -41,9 +41,11 @@ RowIterator::RowIterator(const RowIterator& other):
|
|||||||
|
|
||||||
|
|
||||||
RowIterator::RowIterator(RowIterator&& other) noexcept:
|
RowIterator::RowIterator(RowIterator&& other) noexcept:
|
||||||
_pRecordSet(std::move(other._pRecordSet)),
|
_pRecordSet(other._pRecordSet),
|
||||||
_position(std::move(other._position))
|
_position(other._position)
|
||||||
{
|
{
|
||||||
|
other._pRecordSet = nullptr;
|
||||||
|
other._position = POSITION_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
RowIterator::~RowIterator()
|
RowIterator::~RowIterator()
|
||||||
|
@ -70,23 +70,14 @@ Statement::Statement(Statement&& stmt) noexcept:
|
|||||||
_parseError(std::move(stmt._parseError)),
|
_parseError(std::move(stmt._parseError)),
|
||||||
#endif
|
#endif
|
||||||
_pImpl(std::move(stmt._pImpl)),
|
_pImpl(std::move(stmt._pImpl)),
|
||||||
_async(std::move(stmt._async)),
|
_async(stmt._async),
|
||||||
_pResult(std::move(stmt._pResult)),
|
_pResult(std::move(stmt._pResult)),
|
||||||
_pAsyncExec(std::move(stmt._pAsyncExec)),
|
_pAsyncExec(std::move(stmt._pAsyncExec)),
|
||||||
_arguments(std::move(stmt._arguments)),
|
_arguments(std::move(stmt._arguments)),
|
||||||
_pRowFormatter(std::move(stmt._pRowFormatter)),
|
_pRowFormatter(std::move(stmt._pRowFormatter)),
|
||||||
_stmtString(std::move(stmt._stmtString))
|
_stmtString(std::move(stmt._stmtString))
|
||||||
{
|
{
|
||||||
stmt._pImpl = nullptr;
|
stmt.clear();
|
||||||
stmt._async = false;
|
|
||||||
stmt._pResult = nullptr;
|
|
||||||
stmt._pAsyncExec = nullptr;
|
|
||||||
stmt._arguments.clear();
|
|
||||||
stmt._pRowFormatter = nullptr;
|
|
||||||
_stmtString.clear();
|
|
||||||
#ifndef POCO_DATA_NO_SQL_PARSER
|
|
||||||
_parseError.clear();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -95,6 +86,22 @@ Statement::~Statement()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Statement::clear() noexcept
|
||||||
|
{
|
||||||
|
_pImpl.reset();
|
||||||
|
_async = false;
|
||||||
|
_pResult = nullptr;
|
||||||
|
_pAsyncExec = nullptr;
|
||||||
|
_arguments.clear();
|
||||||
|
_pRowFormatter = nullptr;
|
||||||
|
_stmtString.clear();
|
||||||
|
#ifndef POCO_DATA_NO_SQL_PARSER
|
||||||
|
_pParseResult = nullptr;
|
||||||
|
_parseError.clear();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Statement& Statement::operator = (const Statement& stmt)
|
Statement& Statement::operator = (const Statement& stmt)
|
||||||
{
|
{
|
||||||
Statement tmp(stmt);
|
Statement tmp(stmt);
|
||||||
@ -123,7 +130,7 @@ Statement& Statement::operator = (Statement&& stmt) noexcept
|
|||||||
_pRowFormatter = std::move(stmt._pRowFormatter);
|
_pRowFormatter = std::move(stmt._pRowFormatter);
|
||||||
stmt._pRowFormatter = nullptr;
|
stmt._pRowFormatter = nullptr;
|
||||||
_stmtString = std::move(stmt._stmtString);
|
_stmtString = std::move(stmt._stmtString);
|
||||||
_stmtString.clear();
|
stmt._stmtString.clear();
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user