1 //
2 // RowFilter.cpp
3 //
4 // Library: Data
5 // Package: DataCore
6 // Module: RowFilter
7 //
8 // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
9 // and Contributors.
10 //
11 // SPDX-License-Identifier: BSL-1.0
12 //
13
14
15 #include "Poco/Data/RowFilter.h"
16 #include "Poco/Data/RecordSet.h"
17 #include "Poco/String.h"
18 #include "Poco/Exception.h"
19 #include <functional>
20
21
22 namespace Poco {
23 namespace Data {
24
25
RowFilter(RecordSet * pRecordSet)26 RowFilter::RowFilter(RecordSet* pRecordSet): _pRecordSet(pRecordSet), _not(false)
27 {
28 poco_check_ptr(pRecordSet);
29 init();
30 duplicate();
31 _pRecordSet->filter(this);
32 }
33
34
RowFilter(Ptr pParent,LogicOperator op)35 RowFilter::RowFilter(Ptr pParent, LogicOperator op): _pRecordSet(0),
36 _pParent(pParent),
37 _not(false)
38 {
39 poco_check_ptr(_pParent.get());
40 init();
41 duplicate();
42 _pParent->addFilter(this, op);
43 }
44
45
init()46 void RowFilter::init()
47 {
48 _comparisons.insert(Comparisons::value_type("<", VALUE_LESS_THAN));
49 _comparisons.insert(Comparisons::value_type("<=", VALUE_LESS_THAN_OR_EQUAL));
50 _comparisons.insert(Comparisons::value_type("=", VALUE_EQUAL));
51 _comparisons.insert(Comparisons::value_type("==", VALUE_EQUAL));
52 _comparisons.insert(Comparisons::value_type(">", VALUE_GREATER_THAN));
53 _comparisons.insert(Comparisons::value_type(">=", VALUE_GREATER_THAN_OR_EQUAL));
54 _comparisons.insert(Comparisons::value_type("<>", VALUE_NOT_EQUAL));
55 _comparisons.insert(Comparisons::value_type("!=", VALUE_NOT_EQUAL));
56 _comparisons.insert(Comparisons::value_type("IS NULL", VALUE_IS_NULL));
57 }
58
59
~RowFilter()60 RowFilter::~RowFilter()
61 {
62 try
63 {
64 if (_pRecordSet) _pRecordSet->filter(0);
65 if (_pParent && _pParent->has(this))
66 _pParent->removeFilter(this);
67 release();
68 }
69 catch (...)
70 {
71 poco_unexpected();
72 }
73 }
74
75
isAllowed(std::size_t row) const76 bool RowFilter::isAllowed(std::size_t row) const
77 {
78 Poco::Dynamic::Var retVal;
79 const RecordSet& rs = recordSet();
80
81 std::size_t columns = rs.columnCount();
82 ComparisonMap::const_iterator it = _comparisonMap.begin();
83 ComparisonMap::const_iterator end = _comparisonMap.end();
84 for (; it != end; ++it)
85 {
86 for (std::size_t col = 0; col < columns; ++col)
87 {
88 const std::string name = toUpper(rs.metaColumn(static_cast<UInt32>(col)).name());
89 if (_comparisonMap.find(name) == _comparisonMap.end()) continue;
90
91 Poco::Dynamic::Var ret;
92 CompT compOp = 0;
93 Poco::Dynamic::Var val = rs.value(col, row, false);
94
95 switch (it->second.get<1>())
96 {
97 case VALUE_LESS_THAN:
98 compOp = less; break;
99 case VALUE_LESS_THAN_OR_EQUAL:
100 compOp = lessOrEqual; break;
101 case VALUE_EQUAL:
102 compOp = equal; break;
103 case VALUE_GREATER_THAN:
104 compOp = greater; break;
105 case VALUE_GREATER_THAN_OR_EQUAL:
106 compOp = greaterOrEqual; break;
107 case VALUE_NOT_EQUAL:
108 compOp = notEqual; break;
109 case VALUE_IS_NULL:
110 compOp = isNull; break;
111 default:
112 throw IllegalStateException("Unsupported comparison criteria.");
113 }
114
115 doCompare(ret, val, compOp, it->second);
116 if (retVal.isEmpty()) retVal = ret;
117 else retVal = retVal || ret;
118 }
119 }
120
121 // iterate through children
122 FilterMap::const_iterator fIt = _filterMap.begin();
123 FilterMap::const_iterator fEnd = _filterMap.end();
124 for (; fIt != fEnd; ++fIt)
125 {
126 if (OP_OR == fIt->second)
127 {
128 if (retVal.isEmpty())
129 retVal = fIt->first->isAllowed(row);
130 else
131 retVal = retVal || fIt->first->isAllowed(row);
132 }
133 else if (OP_AND == fIt->second)
134 {
135 if (retVal.isEmpty())
136 retVal = fIt->first->isAllowed(row);
137 else
138 retVal = retVal && fIt->first->isAllowed(row);
139 }
140 else
141 throw IllegalStateException("Unknown logical operation.");
142 }
143
144 if (retVal.isEmpty()) retVal = true; // no filtering found
145 return (!_not) && retVal.extract<bool>();
146 }
147
148
remove(const std::string & name)149 int RowFilter::remove(const std::string& name)
150 {
151 poco_check_ptr (_pRecordSet);
152 _pRecordSet->moveFirst();
153 return static_cast<int>(_comparisonMap.erase(toUpper(name)));
154 }
155
156
getComparison(const std::string & comp) const157 RowFilter::Comparison RowFilter::getComparison(const std::string& comp) const
158 {
159 Comparisons::const_iterator it = _comparisons.find(toUpper(comp));
160 if (it == _comparisons.end())
161 throw NotFoundException("Comparison not found", comp);
162
163 return it->second;
164 }
165
166
addFilter(Ptr pFilter,LogicOperator comparison)167 void RowFilter::addFilter(Ptr pFilter, LogicOperator comparison)
168 {
169 poco_check_ptr (_pRecordSet);
170
171 pFilter->_pRecordSet = _pRecordSet;
172 _pRecordSet->moveFirst();
173 _filterMap.insert(FilterMap::value_type(pFilter, comparison));
174 }
175
176
removeFilter(Ptr pFilter)177 void RowFilter::removeFilter(Ptr pFilter)
178 {
179 poco_check_ptr (_pRecordSet);
180
181 _pRecordSet->moveFirst();
182 _filterMap.erase(pFilter);
183 pFilter->_pRecordSet = 0;
184 pFilter->_pParent = 0;
185 }
186
187
doCompare(Poco::Dynamic::Var & ret,Poco::Dynamic::Var & val,CompT comp,const ComparisonEntry & ce)188 void RowFilter::doCompare(Poco::Dynamic::Var& ret,
189 Poco::Dynamic::Var& val,
190 CompT comp,
191 const ComparisonEntry& ce)
192 {
193 if (ret.isEmpty()) ret = comp(val, ce.get<0>());
194 else
195 {
196 if (ce.get<2>() == OP_OR)
197 ret = ret || comp(val, ce.get<0>());
198 else if (ce.get<2>() == OP_AND)
199 ret = ret && comp(val, ce.get<0>());
200 else
201 throw IllegalStateException("Unknown logical operation.");
202 }
203 }
204
205
recordSet() const206 RecordSet& RowFilter::recordSet() const
207 {
208 if (!_pRecordSet)
209 {
210 Ptr pParent = _pParent;
211 while (pParent && !_pRecordSet)
212 _pRecordSet = pParent->_pRecordSet;
213 }
214 poco_check_ptr (_pRecordSet);
215 return *_pRecordSet;
216 }
217
218
rewindRecordSet()219 void RowFilter::rewindRecordSet()
220 {
221 if (_pRecordSet) _pRecordSet->moveFirst();
222 }
223
224
225 } } // namespace Poco::Data
226