Branch data Line data Source code
1 : : /******************************************************************************
2 : : ------------- Copyright (c) 2009-2023 H a r a l d A c h i t z ---------------
3 : : ---------- < h a r a l d dot a c h i t z at g m a i l dot c o m > ------------
4 : : ---- This Source Code Form is subject to the terms of the Mozilla Public -----
5 : : ---- License, v. 2.0. If a copy of the MPL was not distributed with this -----
6 : : ---------- file, You can obtain one at http://mozilla.org/MPL/2.0/. ----------
7 : : ******************************************************************************/
8 : :
9 : : #include <sl3/dbvalue.hpp>
10 : : #include <sl3/error.hpp>
11 : :
12 : : #include <algorithm>
13 : : #include <cmath>
14 : : #include <iomanip>
15 : : #include <limits>
16 : : #include <ostream>
17 : : #include <type_traits>
18 : :
19 : : #include <iostream>
20 : :
21 : : namespace sl3
22 : : {
23 : :
24 : : namespace
25 : : {
26 : : template <typename T>
27 : : constexpr bool
28 : 123 : oneof (const T&)
29 : : {
30 : 123 : return false;
31 : : }
32 : :
33 : : template <typename T, typename T1, typename... REST>
34 : : constexpr bool
35 : 689 : oneof (const T& a, const T1& b, REST... rest)
36 : : {
37 : 689 : return (a == b ? true : oneof (a, rest...));
38 : : }
39 : :
40 : : struct check
41 : : {
42 : 22 : check (Type t)
43 : 22 : : type (t)
44 : : {
45 : 22 : } //----------------------------------------------------------------------
46 : :
47 : : bool
48 : : notNull ()
49 : : {
50 : : return type != Type::Null;
51 : : } //----------------------------------------------------------------------
52 : :
53 : : template <typename... ARGS>
54 : : bool
55 : 2 : oneOf (ARGS... args)
56 : : {
57 : 2 : return oneof (type, args...);
58 : :
59 : : } //--------------------------------------------------------------------
60 : :
61 : : bool
62 : 20 : sameAs (Type t)
63 : : {
64 : 20 : return type == t;
65 : : } //----------------------------------------------------------------------
66 : :
67 : : private:
68 : : Type type;
69 : : };
70 : :
71 : : struct ensure
72 : : {
73 : 435 : ensure (Type t)
74 : 435 : : type (t)
75 : : {
76 : 435 : } //----------------------------------------------------------------------
77 : :
78 : : ensure&
79 : : notNull ()
80 : : {
81 : : if (type == Type::Null)
82 : : throw ErrNullValueAccess ();
83 : :
84 : : return *this;
85 : : } //----------------------------------------------------------------------
86 : :
87 : : template <typename... ARGS>
88 : : ensure&
89 : 435 : oneOf (ARGS... args)
90 : : {
91 : 435 : if (!oneof (type, args...))
92 : 123 : throw ErrTypeMisMatch (typeName (type)
93 : : + " not one of required types");
94 : :
95 : 312 : return *this;
96 : : } //--------------------------------------------------------------------
97 : :
98 : : ensure&
99 : : sameAs (Type t)
100 : : {
101 : : if (type != t)
102 : : throw ErrTypeMisMatch (typeName (type) + "!=" + typeName (t));
103 : :
104 : : return *this;
105 : : } //----------------------------------------------------------------------
106 : :
107 : : private:
108 : : Type type;
109 : : };
110 : :
111 : : std::string
112 : 3 : assignmentTypeName (const DbValue& value)
113 : : {
114 : 3 : if (value.dbtype () == Type::Variant)
115 : : {
116 : 0 : return typeName (value.dbtype ()) + " with storage type"
117 : 0 : + typeName (value.type ());
118 : : }
119 : :
120 : 3 : return typeName (value.dbtype ());
121 : : }
122 : :
123 : : } //--------------------------------------------------------------------------
124 : :
125 : : bool
126 : 3 : dbval_type_eq (const DbValue& a, const DbValue& b) noexcept
127 : : {
128 : 3 : if (a.dbtype () == b.dbtype ())
129 : : {
130 : 1 : return value_type_eq (a.getValue (), b.getValue ());
131 : : }
132 : :
133 : 2 : return false;
134 : : }
135 : :
136 : : bool
137 : 4 : dbval_type_lt (const DbValue& a, const DbValue& b) noexcept
138 : : {
139 : 4 : if (value_type_lt (a.getValue (), b.getValue ()))
140 : : {
141 : 1 : return true;
142 : : }
143 : :
144 : 3 : if (value_type_eq (a.getValue (), b.getValue ()))
145 : : { // a variant is bigger
146 : 1 : return a.dbtype () < b.dbtype ();
147 : : }
148 : :
149 : 2 : return false;
150 : : }
151 : :
152 : : // how, and does this make sense?
153 : :
154 : : bool
155 : 2 : dbval_eq (const DbValue& a, const DbValue& b) noexcept
156 : : {
157 : 2 : return value_eq (a.getValue (), b.getValue ());
158 : : }
159 : :
160 : : bool
161 : 17 : dbval_lt (const DbValue& a, const DbValue& b) noexcept
162 : : {
163 : 17 : return value_lt (a.getValue (), b.getValue ());
164 : : }
165 : :
166 : 384 : DbValue::DbValue (Type type) noexcept
167 : 384 : : _type (type == Type::Null ? Type::Variant : type)
168 : : {
169 : 384 : }
170 : :
171 : 54 : DbValue::DbValue (int val, Type type)
172 : 54 : : DbValue (type)
173 : : {
174 : 54 : ensure (type).oneOf (Type::Int, Type::Variant);
175 : 53 : _value = val;
176 : 54 : }
177 : :
178 : 73 : DbValue::DbValue (int64_t val, Type type)
179 : 73 : : DbValue (type)
180 : : {
181 : 73 : ensure (type).oneOf (Type::Int, Type::Variant);
182 : 71 : _value = val;
183 : 73 : }
184 : :
185 : 101 : DbValue::DbValue (std::string val, Type type)
186 : 101 : : DbValue (type)
187 : : {
188 : 101 : ensure (type).oneOf (Type::Text, Type::Variant);
189 : 98 : _value = val;
190 : 101 : }
191 : :
192 : 61 : DbValue::DbValue (double val, Type type)
193 : 61 : : DbValue (type)
194 : : {
195 : 61 : ensure (type).oneOf (Type::Real, Type::Variant);
196 : 58 : _value = val;
197 : 61 : }
198 : :
199 : 22 : DbValue::DbValue (Blob val, Type type)
200 : 22 : : DbValue (type)
201 : : {
202 : 22 : ensure (type).oneOf (Type::Blob, Type::Variant);
203 : 20 : _value = val;
204 : 22 : }
205 : :
206 : : DbValue&
207 : 54 : DbValue::operator= (const DbValue& other)
208 : : {
209 : 54 : if (!canAssign (other))
210 : : {
211 : 4 : throw ErrTypeMisMatch (typeName (_type) + "="
212 : 6 : + assignmentTypeName (other));
213 : : }
214 : :
215 : 52 : assign (other);
216 : 52 : return *this;
217 : : }
218 : :
219 : : DbValue&
220 : 11 : DbValue::operator= (DbValue&& other)
221 : : {
222 : 11 : if (!canAssign (other))
223 : : {
224 : 2 : throw ErrTypeMisMatch (typeName (_type) + "="
225 : 3 : + assignmentTypeName (other));
226 : : }
227 : 10 : _value = std::move (other._value);
228 : :
229 : 10 : return *this;
230 : : }
231 : :
232 : : DbValue&
233 : 11 : DbValue::operator= (int val)
234 : : {
235 : 11 : set (val);
236 : 3 : return *this;
237 : : }
238 : :
239 : : DbValue&
240 : 9 : DbValue::operator= (const int64_t& val)
241 : : {
242 : 9 : set (val);
243 : 1 : return *this;
244 : : }
245 : :
246 : : DbValue&
247 : 9 : DbValue::operator= (const double& val)
248 : : {
249 : 9 : set (val);
250 : 1 : return *this;
251 : : }
252 : :
253 : : DbValue&
254 : 10 : DbValue::operator= (const std::string& val)
255 : : {
256 : 10 : set (val);
257 : 2 : return *this;
258 : : }
259 : :
260 : : DbValue&
261 : 9 : DbValue::operator= (const Blob& val)
262 : : {
263 : 9 : set (val);
264 : 1 : return *this;
265 : : }
266 : :
267 : : DbValue&
268 : 34 : DbValue::operator= (const Value& val)
269 : : {
270 : 34 : ensure (_type).oneOf (val.getType (), Type::Variant);
271 : 2 : _value = val;
272 : 2 : return *this;
273 : : }
274 : :
275 : : void
276 : 20 : DbValue::set (int val)
277 : : {
278 : : // not sure if I leaf this conversion,
279 : : // but its better in text dbval.set(12); it type is real
280 : 20 : if (_type == Type::Real)
281 : 1 : set (static_cast<double> (val));
282 : : else
283 : 19 : set (static_cast<int64_t> (val));
284 : 4 : }
285 : :
286 : : void
287 : 36 : DbValue::set (int64_t val)
288 : : {
289 : 36 : ensure (_type).oneOf (Type::Int, Type::Variant);
290 : 4 : _value = val;
291 : 4 : }
292 : :
293 : : void
294 : 18 : DbValue::set (double val)
295 : : {
296 : 18 : ensure (_type).oneOf (Type::Real, Type::Variant);
297 : 2 : _value = val;
298 : 2 : }
299 : :
300 : : void
301 : 19 : DbValue::set (const std::string& val)
302 : : {
303 : 19 : ensure (_type).oneOf (Type::Text, Type::Variant);
304 : 3 : _value = val;
305 : 3 : }
306 : :
307 : : const Value&
308 : 82 : DbValue::getValue () const noexcept
309 : : {
310 : 82 : return _value;
311 : : }
312 : :
313 : : void
314 : 17 : DbValue::set (const Blob& val)
315 : : {
316 : 17 : ensure (_type).oneOf (Type::Blob, Type::Variant);
317 : 1 : _value = val;
318 : 1 : }
319 : :
320 : : const int64_t&
321 : 44 : DbValue::getInt () const
322 : : {
323 : 44 : return _value.int64 ();
324 : : }
325 : :
326 : : int64_t
327 : 18 : DbValue::getInt (int64_t defval) const
328 : : {
329 : 18 : if (isNull ())
330 : 4 : return defval;
331 : :
332 : 14 : return _value.int64 ();
333 : : }
334 : :
335 : : const double&
336 : 21 : DbValue::getReal () const
337 : : {
338 : 21 : return _value.real ();
339 : : }
340 : :
341 : : double
342 : 7 : DbValue::getReal (double defval) const
343 : : {
344 : 7 : if (isNull ())
345 : 2 : return defval;
346 : :
347 : 5 : return _value.real ();
348 : : }
349 : :
350 : : const std::string&
351 : 53 : DbValue::getText () const
352 : : {
353 : 53 : return _value.text ();
354 : : }
355 : :
356 : : std::string
357 : 7 : DbValue::getText (const std::string& defval) const
358 : : {
359 : 7 : if (isNull ())
360 : 2 : return defval;
361 : :
362 : 5 : return _value.text ();
363 : : }
364 : :
365 : : const Blob&
366 : 16 : DbValue::getBlob () const
367 : : {
368 : 16 : return _value.blob ();
369 : : }
370 : :
371 : : Blob
372 : 7 : DbValue::getBlob (const Blob& defval) const
373 : : {
374 : 7 : if (isNull ())
375 : 2 : return defval;
376 : :
377 : 5 : return _value.blob ();
378 : : }
379 : :
380 : : int64_t
381 : 6 : DbValue::get (int64_t defval) const
382 : : {
383 : 6 : if (_value.getType () != Type::Int)
384 : 5 : return defval;
385 : :
386 : 1 : return _value.int64 ();
387 : : }
388 : :
389 : : int64_t
390 : 6 : DbValue::get (int defval) const
391 : : {
392 : 6 : if (_value.getType () != Type::Int)
393 : 5 : return defval;
394 : :
395 : 1 : return _value.int64 ();
396 : : }
397 : :
398 : : double
399 : 7 : DbValue::get (double defval) const
400 : : {
401 : 7 : if (_value.getType () != Type::Real)
402 : 6 : return defval;
403 : :
404 : 1 : return _value.real ();
405 : : }
406 : :
407 : : std::string // TODO consider change to reference, with warning in the doc
408 : 9 : DbValue::get (const std::string& defval) const
409 : : {
410 : 9 : if (_value.getType () != Type::Text)
411 : 8 : return defval;
412 : :
413 : 1 : return _value.text ();
414 : : }
415 : :
416 : : Blob // TODO consider change to reference, with warning in the doc
417 : 7 : DbValue::get (const Blob& defval) const
418 : : {
419 : 7 : if (_value.getType () != Type::Blob)
420 : 6 : return defval;
421 : :
422 : 1 : return _value.blob ();
423 : : }
424 : :
425 : : std::string
426 : 2 : DbValue::ejectText ()
427 : : {
428 : 2 : return _value.ejectText ();
429 : : }
430 : :
431 : : Blob
432 : 2 : DbValue::ejectBlob ()
433 : : {
434 : 2 : return _value.ejectBlob ();
435 : : }
436 : :
437 : : std::ostream&
438 : 18 : operator<< (std::ostream& stm, const sl3::DbValue& v)
439 : : {
440 : 18 : stm << v.getValue ();
441 : 18 : return stm;
442 : : }
443 : :
444 : : void
445 : 1 : DbValue::setNull ()
446 : : {
447 : 1 : _value.setNull ();
448 : 1 : }
449 : :
450 : : bool
451 : 49 : DbValue::isNull () const
452 : : {
453 : 49 : return _value.isNull ();
454 : : }
455 : :
456 : : Type
457 : 352 : DbValue::dbtype () const
458 : : {
459 : 352 : return _type;
460 : : }
461 : :
462 : : Type
463 : 144 : DbValue::type () const
464 : : {
465 : 144 : return _value.getType ();
466 : : }
467 : :
468 : : bool
469 : 77 : DbValue::canAssign (const DbValue& other) const
470 : : {
471 : 77 : if (this->dbtype () != Type::Variant)
472 : : {
473 : 22 : if (other.dbtype () == Type::Variant)
474 : : {
475 : 2 : return check (other.type ()).oneOf (_type, Type::Null);
476 : : }
477 : : else
478 : : {
479 : 20 : return check (_type).sameAs (other.dbtype ());
480 : : }
481 : : }
482 : :
483 : 55 : return true;
484 : : }
485 : :
486 : : void
487 : 55 : DbValue::assign (const DbValue& other)
488 : : {
489 : 55 : _value = other._value;
490 : 55 : }
491 : :
492 : : } // ns
|