1 | #include "duckdb/common/types/value.hpp" |
2 | |
3 | #include "duckdb/common/exception.hpp" |
4 | #include "duckdb/common/limits.hpp" |
5 | #include "duckdb/common/operator/aggregate_operators.hpp" |
6 | #include "duckdb/common/operator/cast_operators.hpp" |
7 | #include "duckdb/common/operator/comparison_operators.hpp" |
8 | |
9 | #include "utf8proc_wrapper.hpp" |
10 | #include "duckdb/common/operator/numeric_binary_operators.hpp" |
11 | #include "duckdb/common/printer.hpp" |
12 | #include "duckdb/common/serializer.hpp" |
13 | #include "duckdb/common/types/date.hpp" |
14 | #include "duckdb/common/types/null_value.hpp" |
15 | #include "duckdb/common/types/time.hpp" |
16 | #include "duckdb/common/types/timestamp.hpp" |
17 | #include "duckdb/common/types/vector.hpp" |
18 | #include "duckdb/common/value_operations/value_operations.hpp" |
19 | #include "duckdb/common/vector_operations/vector_operations.hpp" |
20 | #include "duckdb/common/string_util.hpp" |
21 | |
22 | using namespace duckdb; |
23 | using namespace std; |
24 | |
25 | Value::Value(string_t val) : Value(string(val.GetData(), val.GetSize())) { |
26 | } |
27 | |
28 | Value::Value(string val) : type(TypeId::VARCHAR), is_null(false) { |
29 | auto utf_type = Utf8Proc::Analyze(val); |
30 | switch (utf_type) { |
31 | case UnicodeType::INVALID: |
32 | throw Exception("String value is not valid UTF8" ); |
33 | case UnicodeType::ASCII: |
34 | str_value = val; |
35 | break; |
36 | case UnicodeType::UNICODE: |
37 | str_value = Utf8Proc::Normalize(val); |
38 | break; |
39 | } |
40 | } |
41 | |
42 | Value Value::MinimumValue(TypeId type) { |
43 | Value result; |
44 | result.type = type; |
45 | result.is_null = false; |
46 | switch (type) { |
47 | case TypeId::BOOL: |
48 | result.value_.boolean = false; |
49 | break; |
50 | case TypeId::INT8: |
51 | result.value_.tinyint = std::numeric_limits<int8_t>::min(); |
52 | break; |
53 | case TypeId::INT16: |
54 | result.value_.smallint = std::numeric_limits<int16_t>::min(); |
55 | break; |
56 | case TypeId::INT32: |
57 | result.value_.integer = std::numeric_limits<int32_t>::min(); |
58 | break; |
59 | case TypeId::INT64: |
60 | result.value_.bigint = std::numeric_limits<int64_t>::min(); |
61 | break; |
62 | case TypeId::FLOAT: |
63 | result.value_.float_ = std::numeric_limits<float>::min(); |
64 | break; |
65 | case TypeId::DOUBLE: |
66 | result.value_.double_ = std::numeric_limits<double>::min(); |
67 | break; |
68 | case TypeId::POINTER: |
69 | result.value_.pointer = std::numeric_limits<uintptr_t>::min(); |
70 | break; |
71 | default: |
72 | throw InvalidTypeException(type, "MinimumValue requires numeric type" ); |
73 | } |
74 | return result; |
75 | } |
76 | |
77 | Value Value::MaximumValue(TypeId type) { |
78 | Value result; |
79 | result.type = type; |
80 | result.is_null = false; |
81 | switch (type) { |
82 | case TypeId::BOOL: |
83 | result.value_.boolean = true; |
84 | break; |
85 | case TypeId::INT8: |
86 | result.value_.tinyint = std::numeric_limits<int8_t>::max(); |
87 | break; |
88 | case TypeId::INT16: |
89 | result.value_.smallint = std::numeric_limits<int16_t>::max(); |
90 | break; |
91 | case TypeId::INT32: |
92 | result.value_.integer = std::numeric_limits<int32_t>::max(); |
93 | break; |
94 | case TypeId::INT64: |
95 | result.value_.bigint = std::numeric_limits<int64_t>::max(); |
96 | break; |
97 | case TypeId::FLOAT: |
98 | result.value_.float_ = std::numeric_limits<float>::max(); |
99 | break; |
100 | case TypeId::DOUBLE: |
101 | result.value_.double_ = std::numeric_limits<double>::max(); |
102 | break; |
103 | case TypeId::POINTER: |
104 | result.value_.pointer = std::numeric_limits<uintptr_t>::max(); |
105 | break; |
106 | default: |
107 | throw InvalidTypeException(type, "MaximumValue requires numeric type" ); |
108 | } |
109 | return result; |
110 | } |
111 | |
112 | Value Value::BOOLEAN(int8_t value) { |
113 | Value result(TypeId::BOOL); |
114 | result.value_.boolean = value ? true : false; |
115 | result.is_null = false; |
116 | return result; |
117 | } |
118 | |
119 | Value Value::TINYINT(int8_t value) { |
120 | Value result(TypeId::INT8); |
121 | result.value_.tinyint = value; |
122 | result.is_null = false; |
123 | return result; |
124 | } |
125 | |
126 | Value Value::SMALLINT(int16_t value) { |
127 | Value result(TypeId::INT16); |
128 | result.value_.smallint = value; |
129 | result.is_null = false; |
130 | return result; |
131 | } |
132 | |
133 | Value Value::INTEGER(int32_t value) { |
134 | Value result(TypeId::INT32); |
135 | result.value_.integer = value; |
136 | result.is_null = false; |
137 | return result; |
138 | } |
139 | |
140 | Value Value::BIGINT(int64_t value) { |
141 | Value result(TypeId::INT64); |
142 | result.value_.bigint = value; |
143 | result.is_null = false; |
144 | return result; |
145 | } |
146 | |
147 | //Value Value::BLOB(string value) { |
148 | // Value result(TypeId::VARCHAR); |
149 | // result.str_value = value; |
150 | // result.is_null = false; |
151 | // result.sql_type = SQLType::VARBINARY; |
152 | // return result; |
153 | //} |
154 | |
155 | bool Value::FloatIsValid(float value) { |
156 | return !(std::isnan(value) || std::isinf(value)); |
157 | } |
158 | |
159 | bool Value::DoubleIsValid(double value) { |
160 | return !(std::isnan(value) || std::isinf(value)); |
161 | } |
162 | |
163 | Value Value::FLOAT(float value) { |
164 | if (!Value::FloatIsValid(value)) { |
165 | throw OutOfRangeException("Invalid float value %f" , value); |
166 | } |
167 | Value result(TypeId::FLOAT); |
168 | result.value_.float_ = value; |
169 | result.is_null = false; |
170 | return result; |
171 | } |
172 | |
173 | Value Value::DOUBLE(double value) { |
174 | if (!Value::DoubleIsValid(value)) { |
175 | throw OutOfRangeException("Invalid double value %f" , value); |
176 | } |
177 | Value result(TypeId::DOUBLE); |
178 | result.value_.double_ = value; |
179 | result.is_null = false; |
180 | return result; |
181 | } |
182 | |
183 | Value Value::HASH(hash_t value) { |
184 | Value result(TypeId::HASH); |
185 | result.value_.hash = value; |
186 | result.is_null = false; |
187 | return result; |
188 | } |
189 | |
190 | Value Value::POINTER(uintptr_t value) { |
191 | Value result(TypeId::POINTER); |
192 | result.value_.pointer = value; |
193 | result.is_null = false; |
194 | return result; |
195 | } |
196 | |
197 | Value Value::DATE(date_t date) { |
198 | auto val = Value::INTEGER(date); |
199 | val.sql_type = SQLType::DATE; |
200 | return val; |
201 | } |
202 | |
203 | Value Value::DATE(int32_t year, int32_t month, int32_t day) { |
204 | auto val = Value::INTEGER(Date::FromDate(year, month, day)); |
205 | val.sql_type = SQLType::DATE; |
206 | return val; |
207 | } |
208 | |
209 | Value Value::TIME(int32_t hour, int32_t min, int32_t sec, int32_t msec) { |
210 | auto val = Value::INTEGER(Time::FromTime(hour, min, sec, msec)); |
211 | val.sql_type = SQLType::TIME; |
212 | return val; |
213 | } |
214 | |
215 | Value Value::TIMESTAMP(timestamp_t timestamp) { |
216 | auto val = Value::BIGINT(timestamp); |
217 | val.sql_type = SQLType::TIMESTAMP; |
218 | return val; |
219 | } |
220 | |
221 | Value Value::TIMESTAMP(date_t date, dtime_t time) { |
222 | auto val = Value::BIGINT(Timestamp::FromDatetime(date, time)); |
223 | val.sql_type = SQLType::TIMESTAMP; |
224 | return val; |
225 | } |
226 | |
227 | Value Value::TIMESTAMP(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, int32_t sec, int32_t msec) { |
228 | auto val = Value::TIMESTAMP(Date::FromDate(year, month, day), Time::FromTime(hour, min, sec, msec)); |
229 | val.sql_type = SQLType::TIMESTAMP; |
230 | return val; |
231 | } |
232 | |
233 | Value Value::STRUCT(child_list_t<Value> values) { |
234 | Value result(TypeId::STRUCT); |
235 | result.struct_value = move(values); |
236 | result.is_null = false; |
237 | return result; |
238 | } |
239 | |
240 | Value Value::LIST(vector<Value> values) { |
241 | Value result(TypeId::LIST); |
242 | result.list_value = move(values); |
243 | result.is_null = false; |
244 | return result; |
245 | } |
246 | |
247 | Value Value::BLOB(string data, bool must_cast) { |
248 | Value result(TypeId::VARCHAR); |
249 | result.sql_type = SQLType::BLOB; |
250 | result.is_null = false; |
251 | // hex string identifier: "\\x", must be double '\' |
252 | // single '\x' is a special char for hex chars in C++, |
253 | // e.g., '\xAA' will be transformed into the char "ª" (1010 1010), |
254 | // and Postgres uses double "\\x" for hex -> SELECT E'\\xDEADBEEF'; |
255 | if(must_cast && data.size() >= 2 && data.substr(0,2) == "\\x" ) { |
256 | size_t hex_size = (data.size() - 2) / 2; |
257 | unique_ptr<char[]> hex_data(new char[hex_size + 1]); |
258 | string_t hex_str(hex_data.get(), hex_size); |
259 | CastFromBlob::FromHexToBytes(string_t(data), hex_str); |
260 | result.str_value = string(hex_str.GetData()); |
261 | } else { |
262 | // raw string |
263 | result.str_value = data; |
264 | } |
265 | return result; |
266 | } |
267 | |
268 | //===--------------------------------------------------------------------===// |
269 | // CreateValue |
270 | //===--------------------------------------------------------------------===// |
271 | template <> Value Value::CreateValue(bool value) { |
272 | return Value::BOOLEAN(value); |
273 | } |
274 | |
275 | template <> Value Value::CreateValue(int8_t value) { |
276 | return Value::TINYINT(value); |
277 | } |
278 | |
279 | template <> Value Value::CreateValue(int16_t value) { |
280 | return Value::SMALLINT(value); |
281 | } |
282 | |
283 | template <> Value Value::CreateValue(int32_t value) { |
284 | return Value::INTEGER(value); |
285 | } |
286 | |
287 | template <> Value Value::CreateValue(int64_t value) { |
288 | return Value::BIGINT(value); |
289 | } |
290 | |
291 | template <> Value Value::CreateValue(const char *value) { |
292 | return Value(string(value)); |
293 | } |
294 | |
295 | template <> Value Value::CreateValue(string value) { |
296 | return Value::BLOB(value); |
297 | } |
298 | |
299 | template <> Value Value::CreateValue(string_t value) { |
300 | return Value(value); |
301 | } |
302 | |
303 | template <> Value Value::CreateValue(float value) { |
304 | return Value::FLOAT(value); |
305 | } |
306 | |
307 | template <> Value Value::CreateValue(double value) { |
308 | return Value::DOUBLE(value); |
309 | } |
310 | |
311 | template <> Value Value::CreateValue(Value value) { |
312 | return value; |
313 | } |
314 | //===--------------------------------------------------------------------===// |
315 | // GetValue |
316 | //===--------------------------------------------------------------------===// |
317 | template <class T> T Value::GetValueInternal() { |
318 | if (is_null) { |
319 | return NullValue<T>(); |
320 | } |
321 | switch (type) { |
322 | case TypeId::BOOL: |
323 | return Cast::Operation<bool, T>(value_.boolean); |
324 | case TypeId::INT8: |
325 | return Cast::Operation<int8_t, T>(value_.tinyint); |
326 | case TypeId::INT16: |
327 | return Cast::Operation<int16_t, T>(value_.smallint); |
328 | case TypeId::INT32: |
329 | return Cast::Operation<int32_t, T>(value_.integer); |
330 | case TypeId::INT64: |
331 | return Cast::Operation<int64_t, T>(value_.bigint); |
332 | case TypeId::FLOAT: |
333 | return Cast::Operation<float, T>(value_.float_); |
334 | case TypeId::DOUBLE: |
335 | return Cast::Operation<double, T>(value_.double_); |
336 | case TypeId::VARCHAR: |
337 | return Cast::Operation<string_t, T>(str_value.c_str()); |
338 | default: |
339 | throw NotImplementedException("Unimplemented type for GetValue()" ); |
340 | } |
341 | } |
342 | |
343 | template <> bool Value::GetValue() { |
344 | return GetValueInternal<bool>(); |
345 | } |
346 | template <> int8_t Value::GetValue() { |
347 | return GetValueInternal<int8_t>(); |
348 | } |
349 | template <> int16_t Value::GetValue() { |
350 | return GetValueInternal<int16_t>(); |
351 | } |
352 | template <> int32_t Value::GetValue() { |
353 | return GetValueInternal<int32_t>(); |
354 | } |
355 | template <> int64_t Value::GetValue() { |
356 | return GetValueInternal<int64_t>(); |
357 | } |
358 | template <> string Value::GetValue() { |
359 | return GetValueInternal<string>(); |
360 | } |
361 | template <> float Value::GetValue() { |
362 | return GetValueInternal<float>(); |
363 | } |
364 | template <> double Value::GetValue() { |
365 | return GetValueInternal<double>(); |
366 | } |
367 | |
368 | Value Value::Numeric(TypeId type, int64_t value) { |
369 | assert(!TypeIsIntegral(type) || |
370 | (value >= duckdb::MinimumValue(type) && (value < 0 || (uint64_t)value <= duckdb::MaximumValue(type)))); |
371 | Value val(type); |
372 | val.is_null = false; |
373 | switch (type) { |
374 | case TypeId::INT8: |
375 | assert(value <= std::numeric_limits<int8_t>::max()); |
376 | return Value::TINYINT((int8_t)value); |
377 | case TypeId::INT16: |
378 | assert(value <= std::numeric_limits<int16_t>::max()); |
379 | return Value::SMALLINT((int16_t)value); |
380 | case TypeId::INT32: |
381 | assert(value <= std::numeric_limits<int32_t>::max()); |
382 | return Value::INTEGER((int32_t)value); |
383 | case TypeId::INT64: |
384 | return Value::BIGINT(value); |
385 | case TypeId::FLOAT: |
386 | return Value((float)value); |
387 | case TypeId::DOUBLE: |
388 | return Value((double)value); |
389 | case TypeId::HASH: |
390 | return Value::HASH(value); |
391 | case TypeId::POINTER: |
392 | return Value::POINTER(value); |
393 | default: |
394 | throw InvalidTypeException(type, "Numeric requires numeric type" ); |
395 | } |
396 | return val; |
397 | } |
398 | |
399 | string Value::ToString(SQLType sql_type) const { |
400 | if (is_null) { |
401 | return "NULL" ; |
402 | } |
403 | switch (sql_type.id) { |
404 | case SQLTypeId::BOOLEAN: |
405 | return value_.boolean ? "True" : "False" ; |
406 | case SQLTypeId::TINYINT: |
407 | return to_string(value_.tinyint); |
408 | case SQLTypeId::SMALLINT: |
409 | return to_string(value_.smallint); |
410 | case SQLTypeId::INTEGER: |
411 | return to_string(value_.integer); |
412 | case SQLTypeId::BIGINT: |
413 | return to_string(value_.bigint); |
414 | case SQLTypeId::FLOAT: |
415 | return to_string(value_.float_); |
416 | case SQLTypeId::DOUBLE: |
417 | return to_string(value_.double_); |
418 | case SQLTypeId::DATE: |
419 | return Date::ToString(value_.integer); |
420 | case SQLTypeId::TIME: |
421 | return Time::ToString(value_.integer); |
422 | case SQLTypeId::TIMESTAMP: |
423 | return Timestamp::ToString(value_.bigint); |
424 | case SQLTypeId::VARCHAR: |
425 | return str_value; |
426 | case SQLTypeId::BLOB: { |
427 | unique_ptr<char[]> hex_data(new char[str_value.size() * 2 + 2 + 1]); |
428 | string_t hex_str(hex_data.get(), str_value.size() * 2 + 2); |
429 | CastFromBlob::ToHexString(string_t(str_value), hex_str); |
430 | string result(hex_str.GetData()); |
431 | return result; |
432 | } |
433 | case SQLTypeId::STRUCT: { |
434 | string ret = "<" ; |
435 | for (size_t i = 0; i < struct_value.size(); i++) { |
436 | auto &child = struct_value[i]; |
437 | ret += child.first + ": " + child.second.ToString(); |
438 | if (i < struct_value.size() - 1) { |
439 | ret += ", " ; |
440 | } |
441 | } |
442 | ret += ">" ; |
443 | return ret; |
444 | } |
445 | case SQLTypeId::LIST: { |
446 | string ret = "[" ; |
447 | for (size_t i = 0; i < list_value.size(); i++) { |
448 | auto &child = list_value[i]; |
449 | ret += child.ToString(); |
450 | if (i < list_value.size() - 1) { |
451 | ret += ", " ; |
452 | } |
453 | } |
454 | ret += "]" ; |
455 | return ret; |
456 | } |
457 | default: |
458 | throw NotImplementedException("Unimplemented type for printing" ); |
459 | } |
460 | } |
461 | |
462 | string Value::ToString() const { |
463 | switch (type) { |
464 | case TypeId::POINTER: |
465 | return to_string(value_.pointer); |
466 | case TypeId::HASH: |
467 | return to_string(value_.hash); |
468 | default: |
469 | return ToString(SQLTypeFromInternalType(type)); |
470 | } |
471 | } |
472 | |
473 | //===--------------------------------------------------------------------===// |
474 | // Numeric Operators |
475 | //===--------------------------------------------------------------------===// |
476 | Value Value::operator+(const Value &rhs) const { |
477 | return ValueOperations::Add(*this, rhs); |
478 | } |
479 | |
480 | Value Value::operator-(const Value &rhs) const { |
481 | return ValueOperations::Subtract(*this, rhs); |
482 | } |
483 | |
484 | Value Value::operator*(const Value &rhs) const { |
485 | return ValueOperations::Multiply(*this, rhs); |
486 | } |
487 | |
488 | Value Value::operator/(const Value &rhs) const { |
489 | return ValueOperations::Divide(*this, rhs); |
490 | } |
491 | |
492 | Value Value::operator%(const Value &rhs) const { |
493 | throw NotImplementedException("value modulo" ); |
494 | // return ValueOperations::Modulo(*this, rhs); |
495 | } |
496 | |
497 | //===--------------------------------------------------------------------===// |
498 | // Comparison Operators |
499 | //===--------------------------------------------------------------------===// |
500 | bool Value::operator==(const Value &rhs) const { |
501 | return ValueOperations::Equals(*this, rhs); |
502 | } |
503 | |
504 | bool Value::operator!=(const Value &rhs) const { |
505 | return ValueOperations::NotEquals(*this, rhs); |
506 | } |
507 | |
508 | bool Value::operator<(const Value &rhs) const { |
509 | return ValueOperations::LessThan(*this, rhs); |
510 | } |
511 | |
512 | bool Value::operator>(const Value &rhs) const { |
513 | return ValueOperations::GreaterThan(*this, rhs); |
514 | } |
515 | |
516 | bool Value::operator<=(const Value &rhs) const { |
517 | return ValueOperations::LessThanEquals(*this, rhs); |
518 | } |
519 | |
520 | bool Value::operator>=(const Value &rhs) const { |
521 | return ValueOperations::GreaterThanEquals(*this, rhs); |
522 | } |
523 | |
524 | bool Value::operator==(const int64_t &rhs) const { |
525 | return *this == Value::Numeric(type, rhs); |
526 | } |
527 | |
528 | bool Value::operator!=(const int64_t &rhs) const { |
529 | return *this != Value::Numeric(type, rhs); |
530 | } |
531 | |
532 | bool Value::operator<(const int64_t &rhs) const { |
533 | return *this < Value::Numeric(type, rhs); |
534 | } |
535 | |
536 | bool Value::operator>(const int64_t &rhs) const { |
537 | return *this > Value::Numeric(type, rhs); |
538 | } |
539 | |
540 | bool Value::operator<=(const int64_t &rhs) const { |
541 | return *this <= Value::Numeric(type, rhs); |
542 | } |
543 | |
544 | bool Value::operator>=(const int64_t &rhs) const { |
545 | return *this >= Value::Numeric(type, rhs); |
546 | } |
547 | |
548 | Value Value::CastAs(SQLType source_type, SQLType target_type, bool strict) { |
549 | if (source_type == target_type) { |
550 | return Copy(); |
551 | } |
552 | Vector input, result; |
553 | input.Reference(*this); |
554 | result.Initialize(GetInternalType(target_type)); |
555 | VectorOperations::Cast(input, result, source_type, target_type, 1, strict); |
556 | return result.GetValue(0); |
557 | } |
558 | |
559 | Value Value::CastAs(TypeId target_type, bool strict) const { |
560 | if (target_type == type) { |
561 | return Copy(); // in case of types that have no SQLType equivalent such as POINTER |
562 | } |
563 | return Copy().CastAs(SQLTypeFromInternalType(type), SQLTypeFromInternalType(target_type), strict); |
564 | } |
565 | |
566 | bool Value::TryCastAs(SQLType source_type, SQLType target_type, bool strict) { |
567 | Value new_value; |
568 | try { |
569 | new_value = CastAs(source_type, target_type, strict); |
570 | } catch (Exception &) { |
571 | return false; |
572 | } |
573 | type = new_value.type; |
574 | is_null = new_value.is_null; |
575 | value_ = new_value.value_; |
576 | str_value = new_value.str_value; |
577 | struct_value = new_value.struct_value; |
578 | list_value = new_value.list_value; |
579 | return true; |
580 | } |
581 | |
582 | void Value::Serialize(Serializer &serializer) { |
583 | serializer.Write<TypeId>(type); |
584 | serializer.Write<bool>(is_null); |
585 | if (!is_null) { |
586 | switch (type) { |
587 | case TypeId::BOOL: |
588 | serializer.Write<int8_t>(value_.boolean); |
589 | break; |
590 | case TypeId::INT8: |
591 | serializer.Write<int8_t>(value_.tinyint); |
592 | break; |
593 | case TypeId::INT16: |
594 | serializer.Write<int16_t>(value_.smallint); |
595 | break; |
596 | case TypeId::INT32: |
597 | serializer.Write<int32_t>(value_.integer); |
598 | break; |
599 | case TypeId::INT64: |
600 | serializer.Write<int64_t>(value_.bigint); |
601 | break; |
602 | case TypeId::FLOAT: |
603 | serializer.Write<double>(value_.float_); |
604 | break; |
605 | case TypeId::DOUBLE: |
606 | serializer.Write<double>(value_.double_); |
607 | break; |
608 | case TypeId::POINTER: |
609 | serializer.Write<uintptr_t>(value_.pointer); |
610 | break; |
611 | case TypeId::VARCHAR: |
612 | serializer.WriteString(str_value); |
613 | break; |
614 | default: |
615 | throw NotImplementedException("Value type not implemented for serialization!" ); |
616 | } |
617 | } |
618 | } |
619 | |
620 | Value Value::Deserialize(Deserializer &source) { |
621 | auto type = source.Read<TypeId>(); |
622 | auto is_null = source.Read<bool>(); |
623 | Value new_value = Value(type); |
624 | if (is_null) { |
625 | return new_value; |
626 | } |
627 | new_value.is_null = false; |
628 | switch (type) { |
629 | case TypeId::BOOL: |
630 | new_value.value_.boolean = source.Read<int8_t>(); |
631 | break; |
632 | case TypeId::INT8: |
633 | new_value.value_.tinyint = source.Read<int8_t>(); |
634 | break; |
635 | case TypeId::INT16: |
636 | new_value.value_.smallint = source.Read<int16_t>(); |
637 | break; |
638 | case TypeId::INT32: |
639 | new_value.value_.integer = source.Read<int32_t>(); |
640 | break; |
641 | case TypeId::INT64: |
642 | new_value.value_.bigint = source.Read<int64_t>(); |
643 | break; |
644 | case TypeId::FLOAT: |
645 | new_value.value_.float_ = source.Read<float>(); |
646 | break; |
647 | case TypeId::DOUBLE: |
648 | new_value.value_.double_ = source.Read<double>(); |
649 | break; |
650 | case TypeId::POINTER: |
651 | new_value.value_.pointer = source.Read<uint64_t>(); |
652 | break; |
653 | case TypeId::VARCHAR: |
654 | new_value.str_value = source.Read<string>(); |
655 | break; |
656 | default: |
657 | throw NotImplementedException("Value type not implemented for deserialization" ); |
658 | } |
659 | return new_value; |
660 | } |
661 | |
662 | void Value::Print() { |
663 | Printer::Print(ToString()); |
664 | } |
665 | |
666 | bool Value::ValuesAreEqual(Value result_value, Value value) { |
667 | if (result_value.is_null && value.is_null) { |
668 | // NULL = NULL in checking code |
669 | return true; |
670 | } |
671 | switch (value.type) { |
672 | case TypeId::FLOAT: { |
673 | auto other = result_value.CastAs(TypeId::FLOAT); |
674 | float ldecimal = value.value_.float_; |
675 | float rdecimal = other.value_.float_; |
676 | return ApproxEqual(ldecimal, rdecimal); |
677 | } |
678 | case TypeId::DOUBLE: { |
679 | auto other = result_value.CastAs(TypeId::DOUBLE); |
680 | double ldecimal = value.value_.double_; |
681 | double rdecimal = other.value_.double_; |
682 | return ApproxEqual(ldecimal, rdecimal); |
683 | } |
684 | case TypeId::VARCHAR: { |
685 | auto other = result_value.CastAs(TypeId::VARCHAR); |
686 | // some results might contain padding spaces, e.g. when rendering |
687 | // VARCHAR(10) and the string only has 6 characters, they will be padded |
688 | // with spaces to 10 in the rendering. We don't do that here yet as we |
689 | // are looking at internal structures. So just ignore any extra spaces |
690 | // on the right |
691 | string left = other.str_value; |
692 | string right = value.str_value; |
693 | StringUtil::RTrim(left); |
694 | StringUtil::RTrim(right); |
695 | return left == right; |
696 | } |
697 | default: |
698 | return value == result_value; |
699 | } |
700 | } |
701 | |