1//
2// Row.cpp
3//
4// Library: SQL
5// Package: SQLCore
6// Module: Row
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/SQL/Row.h"
16#include "Poco/SQL/SimpleRowFormatter.h"
17#include "Poco/String.h"
18#include "Poco/Exception.h"
19
20
21namespace Poco {
22namespace SQL {
23
24
25std::ostream& operator << (std::ostream &os, const Row& row)
26{
27 os << row.valuesToString();
28 return os;
29}
30
31
32Row::Row():
33 _pNames(0),
34 _pSortMap(new SortMap),
35 _pFormatter(new SimpleRowFormatter)
36{
37}
38
39
40Row::Row(NameVecPtr pNames,
41 const RowFormatter::Ptr& pFormatter): _pNames(pNames)
42{
43 if (!_pNames) throw NullPointerException();
44 init(0, pFormatter);
45}
46
47
48Row::Row(NameVecPtr pNames,
49 const SortMapPtr& pSortMap,
50 const RowFormatter::Ptr& pFormatter): _pNames(pNames)
51{
52 if (!_pNames) throw NullPointerException();
53 init(pSortMap, pFormatter);
54}
55
56
57void Row::init(const SortMapPtr& pSortMap, const RowFormatter::Ptr& pFormatter)
58{
59 setFormatter(pFormatter);
60 setSortMap(pSortMap);
61
62 NameVec::size_type sz = _pNames->size();
63 if (sz)
64 {
65 _values.resize(sz);
66 // Row sortability in the strict weak ordering sense is
67 // an invariant, hence we must start with a zero here.
68 // If null value is later retrieved from DB, the
69 // Var::empty() call should be used to empty
70 // the corresponding Row value.
71 _values[0] = 0;
72 addSortField(0);
73 }
74}
75
76
77Row::~Row()
78{
79}
80
81
82Poco::Dynamic::Var& Row::get(std::size_t col)
83{
84 try
85 {
86 return _values.at(col);
87 }
88 catch (std::out_of_range& re)
89 {
90 throw RangeException(re.what());
91 }
92}
93
94
95const Poco::Dynamic::Var& Row::get(std::size_t col) const
96{
97 try
98 {
99 return _values.at(col);
100 }
101 catch (std::out_of_range& re)
102 {
103 throw RangeException(re.what());
104 }
105}
106
107
108std::size_t Row::getPosition(const std::string& name) const
109{
110 if (!_pNames)
111 throw NullPointerException();
112
113 NameVec::const_iterator it = _pNames->begin();
114 NameVec::const_iterator end = _pNames->end();
115 std::size_t col = 0;
116 for (; it != end; ++it, ++col)
117 if (0 == icompare(name, *it)) return col;
118
119 throw NotFoundException(name);
120}
121
122
123void Row::addSortField(std::size_t pos)
124{
125 poco_assert (pos <= _values.size());
126
127 SortMap::iterator it = _pSortMap->begin();
128 SortMap::iterator end = _pSortMap->end();
129 for (; it != end; ++it)
130 {
131 if (it->get<0>() == pos) return;
132 }
133
134 ComparisonType ct;
135 if (_values[pos].isEmpty())
136 {
137 ct = COMPARE_AS_EMPTY;
138 }
139 else if ((_values[pos].type() == typeid(Poco::Int8)) ||
140 (_values[pos].type() == typeid(Poco::UInt8)) ||
141 (_values[pos].type() == typeid(Poco::Int16)) ||
142 (_values[pos].type() == typeid(Poco::UInt16)) ||
143 (_values[pos].type() == typeid(Poco::Int32)) ||
144 (_values[pos].type() == typeid(Poco::UInt32)) ||
145 (_values[pos].type() == typeid(Poco::Int64)) ||
146 (_values[pos].type() == typeid(Poco::UInt64)) ||
147 (_values[pos].type() == typeid(bool)))
148 {
149 ct = COMPARE_AS_INTEGER;
150 }
151 else if ((_values[pos].type() == typeid(float)) ||
152 (_values[pos].type() == typeid(double)))
153 {
154 ct = COMPARE_AS_FLOAT;
155 }
156 else
157 {
158 ct = COMPARE_AS_STRING;
159 }
160
161 _pSortMap->push_back(SortTuple(pos, ct));
162}
163
164
165void Row::addSortField(const std::string& name)
166{
167 addSortField(getPosition(name));
168}
169
170
171void Row::removeSortField(std::size_t pos)
172{
173 SortMap::iterator it = _pSortMap->begin();
174 SortMap::iterator end = _pSortMap->end();
175 for (; it != end; ++it)
176 {
177 if (it->get<0>() == pos)
178 {
179 _pSortMap->erase(it);
180 return;
181 }
182 }
183}
184
185
186void Row::removeSortField(const std::string& name)
187{
188 removeSortField(getPosition(name));
189}
190
191
192void Row::replaceSortField(std::size_t oldPos, std::size_t newPos)
193{
194 poco_assert (oldPos <= _values.size());
195 poco_assert (newPos <= _values.size());
196
197 ComparisonType ct;
198
199 if (_values[newPos].isEmpty())
200 {
201 ct = COMPARE_AS_EMPTY;
202 }
203 else if ((_values[newPos].type() == typeid(Poco::Int8)) ||
204 (_values[newPos].type() == typeid(Poco::UInt8)) ||
205 (_values[newPos].type() == typeid(Poco::Int16)) ||
206 (_values[newPos].type() == typeid(Poco::UInt16)) ||
207 (_values[newPos].type() == typeid(Poco::Int32)) ||
208 (_values[newPos].type() == typeid(Poco::UInt32)) ||
209 (_values[newPos].type() == typeid(Poco::Int64)) ||
210 (_values[newPos].type() == typeid(Poco::UInt64)) ||
211 (_values[newPos].type() == typeid(bool)))
212 {
213 ct = COMPARE_AS_INTEGER;
214 }
215 else if ((_values[newPos].type() == typeid(float)) ||
216 (_values[newPos].type() == typeid(double)))
217 {
218 ct = COMPARE_AS_FLOAT;
219 }
220 else
221 {
222 ct = COMPARE_AS_STRING;
223 }
224
225 SortMap::iterator it = _pSortMap->begin();
226 SortMap::iterator end = _pSortMap->end();
227 for (; it != end; ++it)
228 {
229 if (it->get<0>() == oldPos)
230 {
231 *it = SortTuple(newPos, ct);
232 return;
233 }
234 }
235
236 throw NotFoundException("Field not found");
237}
238
239
240void Row::replaceSortField(const std::string& oldName, const std::string& newName)
241{
242 replaceSortField(getPosition(oldName), getPosition(newName));
243}
244
245
246void Row::resetSort()
247{
248 _pSortMap->clear();
249 if (_values.size()) addSortField(0);
250}
251
252
253bool Row::isEqualSize(const Row& other) const
254{
255 return (other._values.size() == _values.size());
256}
257
258
259bool Row::isEqualType(const Row& other) const
260{
261 std::vector<Poco::Dynamic::Var>::const_iterator it = _values.begin();
262 std::vector<Poco::Dynamic::Var>::const_iterator end = _values.end();
263 for (int i = 0; it != end; ++it, ++i)
264 {
265 if (it->type() != other._values[i].type())
266 return false;
267 }
268
269 return true;
270}
271
272
273bool Row::operator == (const Row& other) const
274{
275 if (!isEqualSize(other)) return false;
276 if (!isEqualType(other)) return false;
277
278 std::vector<Poco::Dynamic::Var>::const_iterator it = _values.begin();
279 std::vector<Poco::Dynamic::Var>::const_iterator end = _values.end();
280 for (int i = 0; it != end; ++it, ++i)
281 {
282 if ((*it).convert<std::string>() != other._values[i].convert<std::string>())
283 return false;
284 }
285
286 return true;
287}
288
289
290bool Row::operator != (const Row& other) const
291{
292 return !(*this == other);
293}
294
295
296bool Row::operator < (const Row& other) const
297{
298 if (*_pSortMap != *other._pSortMap)
299 throw InvalidAccessException("Rows compared have different sorting criteria.");
300
301 SortMap::const_iterator it = _pSortMap->begin();
302 SortMap::const_iterator end = _pSortMap->end();
303 for (; it != end; ++it)
304 {
305 switch (it->get<1>())
306 {
307 case COMPARE_AS_EMPTY:
308 return false;
309
310 case COMPARE_AS_INTEGER:
311 if (_values[it->get<0>()].convert<Poco::Int64>() <
312 other._values[it->get<0>()].convert<Poco::Int64>())
313 return true;
314 else if (_values[it->get<0>()].convert<Poco::Int64>() !=
315 other._values[it->get<0>()].convert<Poco::Int64>())
316 return false;
317 break;
318
319 case COMPARE_AS_FLOAT:
320 if (_values[it->get<0>()].convert<double>() <
321 other._values[it->get<0>()].convert<double>())
322 return true;
323 else if (_values[it->get<0>()].convert<double>() !=
324 other._values[it->get<0>()].convert<double>())
325 return false;
326 break;
327
328 case COMPARE_AS_STRING:
329 if (_values[it->get<0>()].convert<std::string>() <
330 other._values[it->get<0>()].convert<std::string>())
331 return true;
332 else if (_values[it->get<0>()].convert<std::string>() !=
333 other._values[it->get<0>()].convert<std::string>())
334 return false;
335 break;
336
337 default:
338 throw IllegalStateException("Unknown comparison criteria.");
339 }
340 }
341
342 return false;
343}
344
345
346void Row::setFormatter(const RowFormatter::Ptr& pFormatter)
347{
348 if (pFormatter.get())
349 _pFormatter = pFormatter;
350 else
351 _pFormatter = new SimpleRowFormatter;
352}
353
354
355void Row::setSortMap(const SortMapPtr& pSortMap)
356{
357 if (pSortMap.get())
358 _pSortMap = pSortMap;
359 else
360 _pSortMap = new SortMap;
361}
362
363
364const std::string& Row::namesToString() const
365{
366 if (!_pNames)
367 throw NullPointerException();
368
369 return _pFormatter->formatNames(names(), _nameStr);
370}
371
372
373void Row::formatNames() const
374{
375 if (!_pNames)
376 throw NullPointerException();
377
378 return _pFormatter->formatNames(names());
379}
380
381
382} } // namespace Poco::SQL
383