Skip to content

Commit

Permalink
fix(Data): RecordSet issue since 1.10.0 (#4739)
Browse files Browse the repository at this point in the history
* fix(Data): RecordSet issue since 1.10.0

* fix(RecordSet): copy, move #4525
  • Loading branch information
aleks-f authored Oct 16, 2024
1 parent e5752a5 commit 9a97e7c
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 32 deletions.
114 changes: 114 additions & 0 deletions Data/SQLite/testsuite/src/SQLiteTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,29 @@ class TypeHandler<Person>
} } // 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::_updateCounter;
int SQLiteTest::_deleteCounter;
Expand Down Expand Up @@ -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()
{
}
Expand Down Expand Up @@ -3746,6 +3859,7 @@ CppUnit::Test* SQLiteTest::suite()
CppUnit_addTest(pSuite, SQLiteTest, testFTS3);
CppUnit_addTest(pSuite, SQLiteTest, testIllegalFilePath);
CppUnit_addTest(pSuite, SQLiteTest, testTransactionTypeProperty);
CppUnit_addTest(pSuite, SQLiteTest, testRecordsetCopyMove);

return pSuite;
}
2 changes: 2 additions & 0 deletions Data/SQLite/testsuite/src/SQLiteTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ class SQLiteTest: public CppUnit::TestCase
void testIllegalFilePath();
void testTransactionTypeProperty();

void testRecordsetCopyMove();

void setUp();
void tearDown();

Expand Down
2 changes: 1 addition & 1 deletion Data/include/Poco/Data/RecordSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class Data_API RecordSet: private Statement
/// a limit for the Statement.
{
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 Iterator = RowIterator;

Expand Down
3 changes: 3 additions & 0 deletions Data/include/Poco/Data/Statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,9 @@ class Data_API Statement
Session session();
/// Returns the underlying session.

void clear() noexcept;
/// Clears the statement.

private:
const Result& doAsyncExec(bool reset = true);
/// Asynchronously executes the statement.
Expand Down
46 changes: 29 additions & 17 deletions Data/src/RecordSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,11 @@ RecordSet::RecordSet(Session& rSession,


RecordSet::RecordSet(const RecordSet& other):
Statement(other.impl()),
Statement(other),
_currentRow(other._currentRow),
_pBegin(new RowIterator(this, 0 == rowsExtracted())),
_pEnd(new RowIterator(this, true)),
_rowMap(other._rowMap),
_pFilter(other._pFilter),
_totalRowCount(other._totalRowCount)
{
Expand All @@ -72,12 +73,21 @@ RecordSet::RecordSet(const RecordSet& other):

RecordSet::RecordSet(RecordSet&& other) noexcept:
Statement(std::move(other)),
_currentRow(std::move(other._currentRow)),
_pBegin(std::move(other._pBegin)),
_pEnd(std::move(other._pEnd)),
_pFilter(std::move(other._pFilter)),
_totalRowCount(std::move(other._totalRowCount))
_currentRow(other._currentRow),
_pBegin(new RowIterator(this, 0 == rowsExtracted())),
_pEnd(new RowIterator(this, true)),
_rowMap(std::move(other._rowMap)),
_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;
}


Expand All @@ -87,10 +97,6 @@ RecordSet::~RecordSet()
{
delete _pBegin;
delete _pEnd;

RowMap::iterator it = _rowMap.begin();
RowMap::iterator end = _rowMap.end();
for (; it != end; ++it) delete it->second;
}
catch (...)
{
Expand All @@ -103,10 +109,19 @@ RecordSet& RecordSet::operator = (RecordSet&& other) noexcept
{
Statement::operator = (std::move(other));
_currentRow = std::move(other._currentRow);
_pBegin = std::move(other._pBegin);
_pEnd = std::move(other._pEnd);
other._currentRow = 0;
_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);
other._pFilter.reset();
_totalRowCount = std::move(other._totalRowCount);
other._totalRowCount = UNKNOWN_TOTAL_ROW_COUNT;

return *this;
}
Expand All @@ -121,9 +136,6 @@ void RecordSet::reset(const Statement& stmt)
_currentRow = 0;
_totalRowCount = UNKNOWN_TOTAL_ROW_COUNT;

RowMap::iterator it = _rowMap.begin();
RowMap::iterator end = _rowMap.end();
for (; it != end; ++it) delete it->second;
_rowMap.clear();

Statement::operator = (stmt);
Expand Down Expand Up @@ -487,7 +499,7 @@ Row& RecordSet::row(std::size_t pos)
}
else
{
pRow = it->second;
pRow = it->second.get();
poco_check_ptr (pRow);
}

Expand All @@ -497,7 +509,7 @@ Row& RecordSet::row(std::size_t pos)

std::size_t RecordSet::rowCount() const
{
if (extractions().size() == 0) return 0;
if (!impl() || extractions().size() == 0) return 0;

std::size_t rc = subTotalRowCount();
if (!isFiltered()) return rc;
Expand Down
6 changes: 4 additions & 2 deletions Data/src/RowIterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ RowIterator::RowIterator(const RowIterator& other):


RowIterator::RowIterator(RowIterator&& other) noexcept:
_pRecordSet(std::move(other._pRecordSet)),
_position(std::move(other._position))
_pRecordSet(other._pRecordSet),
_position(other._position)
{
other._pRecordSet = nullptr;
other._position = POSITION_END;
}

RowIterator::~RowIterator()
Expand Down
31 changes: 19 additions & 12 deletions Data/src/Statement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,14 @@ Statement::Statement(Statement&& stmt) noexcept:
_parseError(std::move(stmt._parseError)),
#endif
_pImpl(std::move(stmt._pImpl)),
_async(std::move(stmt._async)),
_async(stmt._async),
_pResult(std::move(stmt._pResult)),
_pAsyncExec(std::move(stmt._pAsyncExec)),
_arguments(std::move(stmt._arguments)),
_pRowFormatter(std::move(stmt._pRowFormatter)),
_stmtString(std::move(stmt._stmtString))
{
stmt._pImpl = nullptr;
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
stmt.clear();
}


Expand All @@ -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 tmp(stmt);
Expand Down Expand Up @@ -123,7 +130,7 @@ Statement& Statement::operator = (Statement&& stmt) noexcept
_pRowFormatter = std::move(stmt._pRowFormatter);
stmt._pRowFormatter = nullptr;
_stmtString = std::move(stmt._stmtString);
_stmtString.clear();
stmt._stmtString.clear();

return *this;
}
Expand Down

0 comments on commit 9a97e7c

Please sign in to comment.