1 | // |
2 | // Row.h |
3 | // |
4 | // Library: SQL |
5 | // Package: SQLCore |
6 | // Module: Row |
7 | // |
8 | // Definition of the Row class. |
9 | // |
10 | // Copyright (c) 2006, Applied Informatics Software Engineering GmbH. |
11 | // and Contributors. |
12 | // |
13 | // SPDX-License-Identifier: BSL-1.0 |
14 | // |
15 | |
16 | |
17 | #ifndef SQL_Row_INCLUDED |
18 | #define SQL_Row_INCLUDED |
19 | |
20 | |
21 | #include "Poco/SQL/SQL.h" |
22 | #include "Poco/SQL/RowFormatter.h" |
23 | #include "Poco/Dynamic/Var.h" |
24 | #include "Poco/Tuple.h" |
25 | #include "Poco/SharedPtr.h" |
26 | #include <vector> |
27 | #include <string> |
28 | #include <ostream> |
29 | |
30 | |
31 | namespace Poco { |
32 | namespace SQL { |
33 | |
34 | |
35 | class RecordSet; |
36 | |
37 | |
38 | class Poco_SQL_API Row |
39 | /// Row class provides a data type for RecordSet iteration purposes. |
40 | /// Dereferencing a RowIterator returns Row. |
41 | /// Rows are sortable. The sortability is maintained at all times (i.e. there |
42 | /// is always at least one column specified as a sorting criteria) . |
43 | /// The default and minimal sorting criteria is the first field (position 0). |
44 | /// The default sorting criteria can be replaced with any other field by |
45 | /// calling replaceSortField() member function. |
46 | /// Additional fields can be added to sorting criteria, in which case the |
47 | /// field precedence corresponds to addition order (i.e. later added fields |
48 | /// have lower sorting precedence). |
49 | /// These features make Row suitable for use with standard sorted |
50 | /// containers and algorithms. The main constraint is that all the rows from |
51 | /// a set that is being sorted must have the same sorting criteria (i.e., the same |
52 | /// set of fields must be in sorting criteria in the same order). Since rows don't |
53 | /// know about each other, it is the programmer's responsibility to ensure this |
54 | /// constraint is satisfied. |
55 | /// Field names are a shared pointer to a vector of strings. For efficiency sake, |
56 | /// a constructor taking a shared pointer to names vector argument is provided. |
57 | /// The stream operator is provided for Row data type as a free-standing function. |
58 | { |
59 | public: |
60 | typedef RowFormatter::NameVec NameVec; |
61 | typedef RowFormatter::NameVecPtr NameVecPtr; |
62 | typedef RowFormatter::ValueVec ValueVec; |
63 | |
64 | enum ComparisonType |
65 | { |
66 | COMPARE_AS_EMPTY, |
67 | COMPARE_AS_INTEGER, |
68 | COMPARE_AS_FLOAT, |
69 | COMPARE_AS_STRING |
70 | }; |
71 | |
72 | typedef Tuple<std::size_t, ComparisonType> SortTuple; |
73 | typedef std::vector<SortTuple> SortMap; |
74 | /// The type for map holding fields used for sorting criteria. |
75 | /// Fields are added sequentially and have precedence that |
76 | /// corresponds to field adding sequence order (rather than field's |
77 | /// position in the row). |
78 | /// This requirement rules out use of std::map due to its sorted nature. |
79 | typedef SharedPtr<SortMap> SortMapPtr; |
80 | |
81 | Row(); |
82 | /// Creates the Row. |
83 | |
84 | Row(NameVecPtr pNames, |
85 | const RowFormatter::Ptr& pFormatter = 0); |
86 | /// Creates the Row. |
87 | |
88 | Row(NameVecPtr pNames, |
89 | const SortMapPtr& pSortMap, |
90 | const RowFormatter::Ptr& pFormatter = 0); |
91 | /// Creates the Row. |
92 | |
93 | ~Row(); |
94 | /// Destroys the Row. |
95 | |
96 | Poco::Dynamic::Var& get(std::size_t col); |
97 | /// Returns the reference to data value at column location. |
98 | |
99 | Poco::Dynamic::Var& operator [] (std::size_t col); |
100 | /// Returns the reference to data value at column location. |
101 | |
102 | Poco::Dynamic::Var& operator [] (const std::string& name); |
103 | /// Returns the reference to data value at named column location. |
104 | |
105 | const Poco::Dynamic::Var& get(std::size_t col) const; |
106 | /// Returns the reference to data value at column location. |
107 | |
108 | const Poco::Dynamic::Var& operator [] (std::size_t col) const; |
109 | /// Returns the reference to data value at column location. |
110 | |
111 | const Poco::Dynamic::Var& operator [] (const std::string& name) const; |
112 | /// Returns the reference to data value at named column location. |
113 | |
114 | template <typename T> |
115 | void append(const std::string& name, const T& val) |
116 | /// Appends the value to the row. |
117 | { |
118 | if (!_pNames) _pNames = new NameVec; |
119 | _values.push_back(val); |
120 | _pNames->push_back(name); |
121 | if (1 == _values.size()) addSortField(0); |
122 | } |
123 | |
124 | template <typename T> |
125 | void set(std::size_t pos, const T& val) |
126 | /// Assigns the value to the row. |
127 | { |
128 | try |
129 | { |
130 | _values.at(pos) = val; |
131 | } |
132 | catch (std::out_of_range&) |
133 | { |
134 | throw RangeException("Invalid column number." ); |
135 | } |
136 | } |
137 | |
138 | template <typename T> |
139 | void set(const std::string& name, const T& val) |
140 | /// Assigns the value to the row. |
141 | { |
142 | NameVec::iterator it = _pNames->begin(); |
143 | NameVec::iterator end = _pNames->end(); |
144 | for (int i = 0; it != end; ++it, ++i) |
145 | { |
146 | if (*it == name) |
147 | return set(i, val); |
148 | } |
149 | |
150 | std::ostringstream os; |
151 | os << "Column with name " << name << " not found." ; |
152 | throw NotFoundException(os.str()); |
153 | } |
154 | |
155 | std::size_t fieldCount() const; |
156 | /// Returns the number of fields in this row. |
157 | |
158 | void reset(); |
159 | /// Resets the row by clearing all field names and values. |
160 | |
161 | void separator(const std::string& sep); |
162 | /// Sets the separator. |
163 | |
164 | void addSortField(std::size_t pos); |
165 | /// Adds the field used for sorting. |
166 | |
167 | void addSortField(const std::string& name); |
168 | /// Adds the field used for sorting. |
169 | |
170 | void removeSortField(std::size_t pos); |
171 | /// Removes the field used for sorting. |
172 | |
173 | void removeSortField(const std::string& name); |
174 | /// Removes the field used for sorting. |
175 | |
176 | void replaceSortField(std::size_t oldPos, std::size_t newPos); |
177 | /// Replaces the field used for sorting. |
178 | |
179 | void replaceSortField(const std::string& oldName, const std::string& newName); |
180 | /// Replaces the field used for sorting. |
181 | |
182 | void resetSort(); |
183 | /// Resets the sorting criteria to field 0 only. |
184 | |
185 | const std::string& namesToString() const; |
186 | /// Converts the column names to string. |
187 | |
188 | void formatNames() const; |
189 | /// Formats the column names. |
190 | |
191 | const std::string& valuesToString() const; |
192 | /// Converts the row values to string and returns the formatted string. |
193 | |
194 | void formatValues() const; |
195 | /// Formats the row values. |
196 | |
197 | bool operator == (const Row& other) const; |
198 | /// Equality operator. |
199 | |
200 | bool operator != (const Row& other) const; |
201 | /// Inequality operator. |
202 | |
203 | bool operator < (const Row& other) const; |
204 | /// Less-than operator. |
205 | |
206 | const NameVecPtr names() const; |
207 | /// Returns the shared pointer to names vector. |
208 | |
209 | const ValueVec& values() const; |
210 | /// Returns the const reference to values vector. |
211 | |
212 | void setFormatter(const RowFormatter::Ptr& pFormatter = 0); |
213 | /// Sets the formatter for this row and takes the |
214 | /// shared ownership of it. |
215 | |
216 | const RowFormatter& getFormatter() const; |
217 | /// Returns the reference to the formatter. |
218 | |
219 | void setSortMap(const SortMapPtr& pSortMap = 0); |
220 | /// Adds the sorting fields entry and takes the |
221 | /// shared ownership of it. |
222 | |
223 | const SortMapPtr& getSortMap() const; |
224 | /// Returns the reference to the sorting fields. |
225 | |
226 | private: |
227 | void init(const SortMapPtr& pSortMap, const RowFormatter::Ptr& pFormatter); |
228 | |
229 | ValueVec& values(); |
230 | /// Returns the reference to values vector. |
231 | |
232 | std::size_t getPosition(const std::string& name) const; |
233 | bool isEqualSize(const Row& other) const; |
234 | bool isEqualType(const Row& other) const; |
235 | |
236 | NameVecPtr _pNames; |
237 | ValueVec _values; |
238 | SortMapPtr _pSortMap; |
239 | mutable RowFormatter::Ptr _pFormatter; |
240 | mutable std::string _nameStr; |
241 | mutable std::string _valueStr; |
242 | }; |
243 | |
244 | |
245 | Poco_SQL_API std::ostream& operator << (std::ostream &os, const Row& row); |
246 | |
247 | |
248 | /// |
249 | /// inlines |
250 | /// |
251 | inline std::size_t Row::fieldCount() const |
252 | { |
253 | return static_cast<std::size_t>(_values.size()); |
254 | } |
255 | |
256 | |
257 | inline void Row::reset() |
258 | { |
259 | _pNames->clear(); |
260 | _values.clear(); |
261 | } |
262 | |
263 | |
264 | inline const Row::NameVecPtr Row::names() const |
265 | { |
266 | return _pNames; |
267 | } |
268 | |
269 | |
270 | inline const Row::ValueVec& Row::values() const |
271 | { |
272 | return _values; |
273 | } |
274 | |
275 | |
276 | inline Row::ValueVec& Row::values() |
277 | { |
278 | return _values; |
279 | } |
280 | |
281 | |
282 | inline Poco::Dynamic::Var& Row::operator [] (std::size_t col) |
283 | { |
284 | return get(col); |
285 | } |
286 | |
287 | |
288 | inline Poco::Dynamic::Var& Row::operator [] (const std::string& name) |
289 | { |
290 | return get(getPosition(name)); |
291 | } |
292 | |
293 | |
294 | inline const Poco::Dynamic::Var& Row::operator [] (std::size_t col) const |
295 | { |
296 | return get(col); |
297 | } |
298 | |
299 | |
300 | inline const Poco::Dynamic::Var& Row::operator [] (const std::string& name) const |
301 | { |
302 | return get(getPosition(name)); |
303 | } |
304 | |
305 | |
306 | inline const RowFormatter& Row::getFormatter() const |
307 | { |
308 | return *_pFormatter; |
309 | } |
310 | |
311 | |
312 | inline const Row::SortMapPtr& Row::getSortMap() const |
313 | { |
314 | return _pSortMap; |
315 | } |
316 | |
317 | |
318 | inline const std::string& Row::valuesToString() const |
319 | { |
320 | return _pFormatter->formatValues(values(), _valueStr); |
321 | } |
322 | |
323 | |
324 | inline void Row::formatValues() const |
325 | { |
326 | return _pFormatter->formatValues(values()); |
327 | } |
328 | |
329 | |
330 | } } // namespace Poco::SQL |
331 | |
332 | |
333 | #endif // Data_Row_INCLUDED |
334 | |