fixed GH #1532: RecordSet and RowFilter: bad use of reference counter

This commit is contained in:
Guenter Obiltschnig
2016-12-30 10:06:06 +01:00
parent 760286f86f
commit e46e610b84
4 changed files with 21 additions and 17 deletions

View File

@@ -26,10 +26,12 @@
#include "Poco/Data/BulkExtraction.h" #include "Poco/Data/BulkExtraction.h"
#include "Poco/Data/Statement.h" #include "Poco/Data/Statement.h"
#include "Poco/Data/RowIterator.h" #include "Poco/Data/RowIterator.h"
#include "Poco/Data/RowFilter.h"
#include "Poco/Data/LOB.h" #include "Poco/Data/LOB.h"
#include "Poco/String.h" #include "Poco/String.h"
#include "Poco/Dynamic/Var.h" #include "Poco/Dynamic/Var.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include "Poco/AutoPtr.h"
#include <ostream> #include <ostream>
#include <limits> #include <limits>
@@ -98,7 +100,6 @@ public:
_currentRow(0), _currentRow(0),
_pBegin(new RowIterator(this, 0 == rowsExtracted())), _pBegin(new RowIterator(this, 0 == rowsExtracted())),
_pEnd(new RowIterator(this, true)), _pEnd(new RowIterator(this, true)),
_pFilter(0),
_totalRowCount(UNKNOWN_TOTAL_ROW_COUNT) _totalRowCount(UNKNOWN_TOTAL_ROW_COUNT)
/// Creates the RecordSet. /// Creates the RecordSet.
{ {
@@ -480,17 +481,17 @@ private:
/// Returns true if the specified row is allowed by the /// Returns true if the specified row is allowed by the
/// currently active filter. /// currently active filter.
void filter(RowFilter* pFilter); void filter(const Poco::AutoPtr<RowFilter>& pFilter);
/// Sets the filter for the RecordSet. /// Sets the filter for the RecordSet.
const RowFilter* getFilter() const; const Poco::AutoPtr<RowFilter>& getFilter() const;
/// Returns the filter associated with the RecordSet. /// Returns the filter associated with the RecordSet.
std::size_t _currentRow; std::size_t _currentRow;
RowIterator* _pBegin; RowIterator* _pBegin;
RowIterator* _pEnd; RowIterator* _pEnd;
RowMap _rowMap; RowMap _rowMap;
RowFilter* _pFilter; Poco::AutoPtr<RowFilter> _pFilter;
std::size_t _totalRowCount; std::size_t _totalRowCount;
friend class RowIterator; friend class RowIterator;
@@ -656,7 +657,7 @@ inline RecordSet::Iterator RecordSet::end()
} }
inline const RowFilter* RecordSet::getFilter() const inline const Poco::AutoPtr<RowFilter>& RecordSet::getFilter() const
{ {
return _pFilter; return _pFilter;
} }

View File

@@ -21,7 +21,6 @@
#include "Poco/Data/Data.h" #include "Poco/Data/Data.h"
#include "Poco/Data/RecordSet.h"
#include "Poco/Dynamic/Var.h" #include "Poco/Dynamic/Var.h"
#include "Poco/Tuple.h" #include "Poco/Tuple.h"
#include "Poco/String.h" #include "Poco/String.h"
@@ -36,6 +35,9 @@ namespace Poco {
namespace Data { namespace Data {
class RecordSet;
class Data_API RowFilter: public RefCountedObject class Data_API RowFilter: public RefCountedObject
/// RowFilter class provides row filtering functionality. /// RowFilter class provides row filtering functionality.
/// A filter contains a set of criteria (field name, value and /// A filter contains a set of criteria (field name, value and
@@ -93,7 +95,7 @@ public:
void add(const std::string& name, Comparison comparison, const T& value, LogicOperator op = OP_OR) void add(const std::string& name, Comparison comparison, const T& value, LogicOperator op = OP_OR)
/// Adds value to the filter. /// Adds value to the filter.
{ {
if (_pRecordSet) _pRecordSet->moveFirst(); rewindRecordSet();
_comparisonMap.insert(ComparisonMap::value_type(toUpper(name), _comparisonMap.insert(ComparisonMap::value_type(toUpper(name),
ComparisonEntry(value, comparison, op))); ComparisonEntry(value, comparison, op)));
} }
@@ -165,6 +167,8 @@ private:
Comparison getComparison(const std::string& comp) const; Comparison getComparison(const std::string& comp) const;
void rewindRecordSet();
Comparisons _comparisons; Comparisons _comparisons;
ComparisonMap _comparisonMap; ComparisonMap _comparisonMap;
mutable RecordSet* _pRecordSet; mutable RecordSet* _pRecordSet;

View File

@@ -41,7 +41,6 @@ RecordSet::RecordSet(const Statement& rStatement,
_currentRow(0), _currentRow(0),
_pBegin(new RowIterator(this, 0 == rowsExtracted())), _pBegin(new RowIterator(this, 0 == rowsExtracted())),
_pEnd(new RowIterator(this, true)), _pEnd(new RowIterator(this, true)),
_pFilter(0),
_totalRowCount(UNKNOWN_TOTAL_ROW_COUNT) _totalRowCount(UNKNOWN_TOTAL_ROW_COUNT)
{ {
if (pRowFormatter) setRowFormatter(pRowFormatter); if (pRowFormatter) setRowFormatter(pRowFormatter);
@@ -55,7 +54,6 @@ RecordSet::RecordSet(Session& rSession,
_currentRow(0), _currentRow(0),
_pBegin(new RowIterator(this, 0 == rowsExtracted())), _pBegin(new RowIterator(this, 0 == rowsExtracted())),
_pEnd(new RowIterator(this, true)), _pEnd(new RowIterator(this, true)),
_pFilter(0),
_totalRowCount(UNKNOWN_TOTAL_ROW_COUNT) _totalRowCount(UNKNOWN_TOTAL_ROW_COUNT)
{ {
if (pRowFormatter) setRowFormatter(pRowFormatter); if (pRowFormatter) setRowFormatter(pRowFormatter);
@@ -70,7 +68,6 @@ RecordSet::RecordSet(const RecordSet& other):
_pFilter(other._pFilter), _pFilter(other._pFilter),
_totalRowCount(other._totalRowCount) _totalRowCount(other._totalRowCount)
{ {
if (_pFilter) _pFilter->duplicate();
} }
@@ -80,7 +77,6 @@ RecordSet::~RecordSet()
{ {
delete _pBegin; delete _pBegin;
delete _pEnd; delete _pEnd;
if (_pFilter) _pFilter->release();
RowMap::iterator it = _rowMap.begin(); RowMap::iterator it = _rowMap.begin();
RowMap::iterator itEnd = _rowMap.end(); RowMap::iterator itEnd = _rowMap.end();
@@ -395,11 +391,9 @@ std::ostream& RecordSet::copy(std::ostream& os, std::size_t offset, std::size_t
} }
void RecordSet::filter(RowFilter* pFilter) void RecordSet::filter(const Poco::AutoPtr<RowFilter>& pFilter)
{ {
if (_pFilter) _pFilter->release();
_pFilter = pFilter; _pFilter = pFilter;
if (_pFilter) _pFilter->duplicate();
} }

View File

@@ -20,6 +20,7 @@
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include <functional> #include <functional>
namespace Poco { namespace Poco {
namespace Data { namespace Data {
@@ -53,8 +54,6 @@ void RowFilter::init()
_comparisons.insert(Comparisons::value_type("<>", VALUE_NOT_EQUAL)); _comparisons.insert(Comparisons::value_type("<>", VALUE_NOT_EQUAL));
_comparisons.insert(Comparisons::value_type("!=", VALUE_NOT_EQUAL)); _comparisons.insert(Comparisons::value_type("!=", VALUE_NOT_EQUAL));
_comparisons.insert(Comparisons::value_type("IS NULL", VALUE_IS_NULL)); _comparisons.insert(Comparisons::value_type("IS NULL", VALUE_IS_NULL));
duplicate();
} }
@@ -62,7 +61,6 @@ RowFilter::~RowFilter()
{ {
try try
{ {
release();
if (_pRecordSet) _pRecordSet->filter(0); if (_pRecordSet) _pRecordSet->filter(0);
if (_pParent.get()) _pParent->removeFilter(this); if (_pParent.get()) _pParent->removeFilter(this);
} }
@@ -201,6 +199,7 @@ void RowFilter::doCompare(Poco::Dynamic::Var& ret,
} }
} }
RecordSet& RowFilter::recordSet() const RecordSet& RowFilter::recordSet() const
{ {
if (!_pRecordSet) if (!_pRecordSet)
@@ -214,4 +213,10 @@ RecordSet& RowFilter::recordSet() const
} }
void RowFilter::rewindRecordSet()
{
if (_pRecordSet) _pRecordSet->moveFirst();
}
} } // namespace Poco::Data } } // namespace Poco::Data