1//===----------------------------------------------------------------------===//
2// DuckDB
3//
4// duckdb/common/types/value.hpp
5//
6//
7//===----------------------------------------------------------------------===//
8
9#pragma once
10
11#include "duckdb/common/common.hpp"
12#include "duckdb/common/exception.hpp"
13
14#include <iosfwd>
15#include <memory.h>
16
17namespace duckdb {
18
19class Deserializer;
20class Serializer;
21
22//! The Value object holds a single arbitrary value of any type that can be
23//! stored in the database.
24class Value {
25 friend class Vector;
26
27public:
28 //! Create an empty NULL value of the specified type
29 Value(TypeId type = TypeId::INT32) : type(type), is_null(true) {
30 }
31 //! Create a BIGINT value
32 Value(int32_t val) : type(TypeId::INT32), is_null(false) {
33 value_.integer = val;
34 }
35 //! Create a BIGINT value
36 Value(int64_t val) : type(TypeId::INT64), is_null(false) {
37 value_.bigint = val;
38 }
39 //! Create a FLOAT value
40 Value(float val) : type(TypeId::FLOAT), is_null(false) {
41 value_.float_ = val;
42 }
43 //! Create a DOUBLE value
44 Value(double val) : type(TypeId::DOUBLE), is_null(false) {
45 value_.double_ = val;
46 }
47 //! Create a VARCHAR value
48 Value(const char *val) : Value(val ? string(val) : string()) {
49 }
50 Value(string_t val);
51 //! Create a VARCHAR value
52 Value(string val);
53
54 //! Create the lowest possible value of a given type (numeric only)
55 static Value MinimumValue(TypeId type);
56 //! Create the highest possible value of a given type (numeric only)
57 static Value MaximumValue(TypeId type);
58 //! Create a Numeric value of the specified type with the specified value
59 static Value Numeric(TypeId id, int64_t value);
60
61 //! Create a tinyint Value from a specified value
62 static Value BOOLEAN(int8_t value);
63 //! Create a tinyint Value from a specified value
64 static Value TINYINT(int8_t value);
65 //! Create a smallint Value from a specified value
66 static Value SMALLINT(int16_t value);
67 //! Create an integer Value from a specified value
68 static Value INTEGER(int32_t value);
69 //! Create a bigint Value from a specified value
70 static Value BIGINT(int64_t value);
71 //! Create a hash Value from a specified value
72 static Value HASH(hash_t value);
73 //! Create a pointer Value from a specified value
74 static Value POINTER(uintptr_t value);
75 //! Create a date Value from a specified date
76 static Value DATE(date_t date);
77 //! Create a date Value from a specified date
78 static Value DATE(int32_t year, int32_t month, int32_t day);
79 //! Create a time Value from a specified date
80 static Value TIME(int32_t hour, int32_t min, int32_t sec, int32_t msec);
81 //! Create a timestamp Value from a specified date/time combination
82 static Value TIMESTAMP(date_t date, dtime_t time);
83 //! Create a timestamp Value from a specified timestamp
84 static Value TIMESTAMP(timestamp_t timestamp);
85 //! Create a timestamp Value from a specified timestamp in separate values
86 static Value TIMESTAMP(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, int32_t sec,
87 int32_t msec);
88
89 //! Create a float Value from a specified value
90 static Value FLOAT(float value);
91 //! Create a double Value from a specified value
92 static Value DOUBLE(double value);
93 //! Create a struct value with given list of entries
94 static Value STRUCT(child_list_t<Value> values);
95 //! Create a list value with the given entries
96 static Value LIST(std::vector<Value> values);
97
98 //! Create a blob Value from a specified value
99 static Value BLOB(string data, bool must_cast = true);
100
101 template <class T> T GetValue() {
102 throw NotImplementedException("Unimplemented template type for Value::GetValue");
103 }
104 template <class T> static Value CreateValue(T value) {
105 throw NotImplementedException("Unimplemented template type for Value::CreateValue");
106 }
107
108 //! Return a copy of this value
109 Value Copy() const {
110 return Value(*this);
111 }
112
113 //! Convert this value to a string
114 string ToString() const;
115 //! Convert this value to a string, with the given display format
116 string ToString(SQLType type) const;
117
118 //! Cast this value to another type
119 Value CastAs(TypeId target_type, bool strict = false) const;
120 //! Cast this value to another type
121 Value CastAs(SQLType source_type, SQLType target_type, bool strict = false);
122 //! Tries to cast value to another type, throws exception if its not possible
123 bool TryCastAs(SQLType source_type, SQLType target_type, bool strict = false);
124
125 //! The type of the value
126 TypeId type;
127 //! Whether or not the value is NULL
128 bool is_null;
129
130 SQLType GetSQLType() {
131 return sql_type.id == SQLTypeId::INVALID ? SQLTypeFromInternalType(type) : sql_type;
132 }
133
134 //! The value of the object, if it is of a constant size Type
135 union Val {
136 int8_t boolean;
137 int8_t tinyint;
138 int16_t smallint;
139 int32_t integer;
140 int64_t bigint;
141 float float_;
142 double double_;
143 uintptr_t pointer;
144 uint64_t hash;
145 } value_;
146
147 //! The value of the object, if it is of a variable size type
148 string str_value;
149
150 child_list_t<Value> struct_value;
151 std::vector<Value> list_value;
152
153 //! Serializes a Value to a stand-alone binary blob
154 void Serialize(Serializer &serializer);
155 //! Deserializes a Value from a blob
156 static Value Deserialize(Deserializer &source);
157
158 //===--------------------------------------------------------------------===//
159 // Numeric Operators
160 //===--------------------------------------------------------------------===//
161 Value operator+(const Value &rhs) const;
162 Value operator-(const Value &rhs) const;
163 Value operator*(const Value &rhs) const;
164 Value operator/(const Value &rhs) const;
165 Value operator%(const Value &rhs) const;
166
167 //===--------------------------------------------------------------------===//
168 // Comparison Operators
169 //===--------------------------------------------------------------------===//
170 bool operator==(const Value &rhs) const;
171 bool operator!=(const Value &rhs) const;
172 bool operator<(const Value &rhs) const;
173 bool operator>(const Value &rhs) const;
174 bool operator<=(const Value &rhs) const;
175 bool operator>=(const Value &rhs) const;
176
177 bool operator==(const int64_t &rhs) const;
178 bool operator!=(const int64_t &rhs) const;
179 bool operator<(const int64_t &rhs) const;
180 bool operator>(const int64_t &rhs) const;
181 bool operator<=(const int64_t &rhs) const;
182 bool operator>=(const int64_t &rhs) const;
183
184 static bool FloatIsValid(float value);
185 static bool DoubleIsValid(double value);
186 //! Returns true if the values are (approximately) equivalent. Note this is NOT the SQL equivalence. For this
187 //! function, NULL values are equivalent and floating point values that are close are equivalent.
188 static bool ValuesAreEqual(Value result_value, Value value);
189
190 friend std::ostream &operator<<(std::ostream &out, const Value &val) {
191 out << val.ToString();
192 return out;
193 }
194 void Print();
195
196private:
197 SQLType sql_type = SQLType(SQLTypeId::INVALID);
198
199private:
200 template <class T> T GetValueInternal();
201 //! Templated helper function for casting
202 template <class DST, class OP> static DST _cast(const Value &v);
203
204 //! Templated helper function for binary operations
205 template <class OP>
206 static void _templated_binary_operation(const Value &left, const Value &right, Value &result, bool ignore_null);
207
208 //! Templated helper function for boolean operations
209 template <class OP> static bool _templated_boolean_operation(const Value &left, const Value &right);
210};
211
212template <> Value Value::CreateValue(bool value);
213template <> Value Value::CreateValue(int8_t value);
214template <> Value Value::CreateValue(int16_t value);
215template <> Value Value::CreateValue(int32_t value);
216template <> Value Value::CreateValue(int64_t value);
217template <> Value Value::CreateValue(const char *value);
218template <> Value Value::CreateValue(string value);
219template <> Value Value::CreateValue(string_t value);
220template <> Value Value::CreateValue(float value);
221template <> Value Value::CreateValue(double value);
222template <> Value Value::CreateValue(Value value);
223
224template <> bool Value::GetValue();
225template <> int8_t Value::GetValue();
226template <> int16_t Value::GetValue();
227template <> int32_t Value::GetValue();
228template <> int64_t Value::GetValue();
229template <> string Value::GetValue();
230template <> float Value::GetValue();
231template <> double Value::GetValue();
232
233} // namespace duckdb
234