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 | |
17 | namespace duckdb { |
18 | |
19 | class Deserializer; |
20 | class Serializer; |
21 | |
22 | //! The Value object holds a single arbitrary value of any type that can be |
23 | //! stored in the database. |
24 | class Value { |
25 | friend class Vector; |
26 | |
27 | public: |
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 | |
196 | private: |
197 | SQLType sql_type = SQLType(SQLTypeId::INVALID); |
198 | |
199 | private: |
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 | |
212 | template <> Value Value::CreateValue(bool value); |
213 | template <> Value Value::CreateValue(int8_t value); |
214 | template <> Value Value::CreateValue(int16_t value); |
215 | template <> Value Value::CreateValue(int32_t value); |
216 | template <> Value Value::CreateValue(int64_t value); |
217 | template <> Value Value::CreateValue(const char *value); |
218 | template <> Value Value::CreateValue(string value); |
219 | template <> Value Value::CreateValue(string_t value); |
220 | template <> Value Value::CreateValue(float value); |
221 | template <> Value Value::CreateValue(double value); |
222 | template <> Value Value::CreateValue(Value value); |
223 | |
224 | template <> bool Value::GetValue(); |
225 | template <> int8_t Value::GetValue(); |
226 | template <> int16_t Value::GetValue(); |
227 | template <> int32_t Value::GetValue(); |
228 | template <> int64_t Value::GetValue(); |
229 | template <> string Value::GetValue(); |
230 | template <> float Value::GetValue(); |
231 | template <> double Value::GetValue(); |
232 | |
233 | } // namespace duckdb |
234 | |