Browse Source

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

Guenter Obiltschnig 9 years ago
parent
commit
642bf58480

+ 6 - 5
Data/include/Poco/Data/RecordSet.h

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

+ 6 - 2
Data/include/Poco/Data/RowFilter.h

@@ -21,7 +21,6 @@
 
 
 #include "Poco/Data/Data.h"
-#include "Poco/Data/RecordSet.h"
 #include "Poco/Dynamic/Var.h"
 #include "Poco/Tuple.h"
 #include "Poco/String.h"
@@ -36,6 +35,9 @@ namespace Poco {
 namespace Data {
 
 
+class RecordSet;
+
+
 class Data_API RowFilter: public RefCountedObject
 	/// RowFilter class provides row filtering functionality.
 	/// 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)
 		/// Adds value to the filter.
 	{
-		if (_pRecordSet) _pRecordSet->moveFirst();
+		rewindRecordSet();
 		_comparisonMap.insert(ComparisonMap::value_type(toUpper(name),
 			ComparisonEntry(value, comparison, op)));
 	}
@@ -164,6 +166,8 @@ private:
 	RecordSet& recordSet() const;
 
 	Comparison getComparison(const std::string& comp) const;
+	
+	void rewindRecordSet();
 
 	Comparisons        _comparisons;
 	ComparisonMap      _comparisonMap;

+ 1 - 7
Data/src/RecordSet.cpp

@@ -41,7 +41,6 @@ RecordSet::RecordSet(const Statement& rStatement,
 	_currentRow(0),
 	_pBegin(new RowIterator(this, 0 == rowsExtracted())),
 	_pEnd(new RowIterator(this, true)),
-	_pFilter(0),
 	_totalRowCount(UNKNOWN_TOTAL_ROW_COUNT)
 {
 	if (pRowFormatter) setRowFormatter(pRowFormatter);
@@ -55,7 +54,6 @@ RecordSet::RecordSet(Session& rSession,
 	_currentRow(0),
 	_pBegin(new RowIterator(this, 0 == rowsExtracted())),
 	_pEnd(new RowIterator(this, true)),
-	_pFilter(0),
 	_totalRowCount(UNKNOWN_TOTAL_ROW_COUNT)
 {
 	if (pRowFormatter) setRowFormatter(pRowFormatter);
@@ -70,7 +68,6 @@ RecordSet::RecordSet(const RecordSet& other):
 	_pFilter(other._pFilter),
 	_totalRowCount(other._totalRowCount)
 {
-	if (_pFilter) _pFilter->duplicate();
 }
 
 
@@ -80,7 +77,6 @@ RecordSet::~RecordSet()
 	{
 		delete _pBegin;
 		delete _pEnd;
-		if (_pFilter) _pFilter->release();
 
 		RowMap::iterator it = _rowMap.begin();
 		RowMap::iterator end = _rowMap.end();
@@ -377,11 +373,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;
-	if (_pFilter) _pFilter->duplicate();
 }
 
 

+ 8 - 3
Data/src/RowFilter.cpp

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