1 | #include "duckdb/common/types.hpp" |
2 | |
3 | #include "duckdb/common/exception.hpp" |
4 | #include "duckdb/common/serializer.hpp" |
5 | #include "duckdb/common/string_util.hpp" |
6 | #include "duckdb/common/types/string_type.hpp" |
7 | |
8 | #include <cmath> |
9 | |
10 | using namespace std; |
11 | |
12 | namespace duckdb { |
13 | |
14 | const SQLType SQLType::SQLNULL = SQLType(SQLTypeId::SQLNULL); |
15 | const SQLType SQLType::BOOLEAN = SQLType(SQLTypeId::BOOLEAN); |
16 | const SQLType SQLType::TINYINT = SQLType(SQLTypeId::TINYINT); |
17 | const SQLType SQLType::SMALLINT = SQLType(SQLTypeId::SMALLINT); |
18 | const SQLType SQLType::INTEGER = SQLType(SQLTypeId::INTEGER); |
19 | const SQLType SQLType::BIGINT = SQLType(SQLTypeId::BIGINT); |
20 | const SQLType SQLType::FLOAT = SQLType(SQLTypeId::FLOAT); |
21 | const SQLType SQLType::DOUBLE = SQLType(SQLTypeId::DOUBLE); |
22 | const SQLType SQLType::DATE = SQLType(SQLTypeId::DATE); |
23 | const SQLType SQLType::TIMESTAMP = SQLType(SQLTypeId::TIMESTAMP); |
24 | const SQLType SQLType::TIME = SQLType(SQLTypeId::TIME); |
25 | |
26 | const SQLType SQLType::VARCHAR = SQLType(SQLTypeId::VARCHAR); |
27 | const SQLType SQLType::VARBINARY = SQLType(SQLTypeId::VARBINARY); |
28 | |
29 | const SQLType SQLType::BLOB = SQLType(SQLTypeId::BLOB); |
30 | |
31 | // TODO these are incomplete and should maybe not exist as such |
32 | const SQLType SQLType::STRUCT = SQLType(SQLTypeId::STRUCT); |
33 | const SQLType SQLType::LIST = SQLType(SQLTypeId::LIST); |
34 | |
35 | const SQLType SQLType::ANY = SQLType(SQLTypeId::ANY); |
36 | |
37 | const vector<SQLType> SQLType::NUMERIC = { |
38 | SQLType::TINYINT, SQLType::SMALLINT, SQLType::INTEGER, SQLType::BIGINT, |
39 | SQLType::FLOAT, SQLType::DOUBLE, SQLType(SQLTypeId::DECIMAL)}; |
40 | |
41 | const vector<SQLType> SQLType::INTEGRAL = {SQLType::TINYINT, SQLType::SMALLINT, SQLType::INTEGER, SQLType::BIGINT}; |
42 | |
43 | const vector<SQLType> SQLType::ALL_TYPES = { |
44 | SQLType::BOOLEAN, SQLType::TINYINT, SQLType::SMALLINT, SQLType::INTEGER, SQLType::BIGINT, |
45 | SQLType::DATE, SQLType::TIMESTAMP, SQLType::DOUBLE, SQLType::FLOAT, SQLType(SQLTypeId::DECIMAL), |
46 | SQLType::VARCHAR, SQLType::BLOB}; |
47 | // TODO add LIST/STRUCT here |
48 | |
49 | const TypeId ROW_TYPE = TypeId::INT64; |
50 | |
51 | string TypeIdToString(TypeId type) { |
52 | switch (type) { |
53 | case TypeId::BOOL: |
54 | return "BOOL" ; |
55 | case TypeId::INT8: |
56 | return "INT8" ; |
57 | case TypeId::INT16: |
58 | return "INT16" ; |
59 | case TypeId::INT32: |
60 | return "INT32" ; |
61 | case TypeId::INT64: |
62 | return "INT64" ; |
63 | case TypeId::HASH: |
64 | return "HASH" ; |
65 | case TypeId::POINTER: |
66 | return "POINTER" ; |
67 | case TypeId::FLOAT: |
68 | return "FLOAT" ; |
69 | case TypeId::DOUBLE: |
70 | return "DOUBLE" ; |
71 | case TypeId::VARCHAR: |
72 | return "VARCHAR" ; |
73 | case TypeId::VARBINARY: |
74 | return "VARBINARY" ; |
75 | case TypeId::STRUCT: |
76 | return "STRUCT<?>" ; |
77 | case TypeId::LIST: |
78 | return "LIST<?>" ; |
79 | default: |
80 | throw ConversionException("Invalid TypeId %d" , type); |
81 | } |
82 | } |
83 | |
84 | idx_t GetTypeIdSize(TypeId type) { |
85 | switch (type) { |
86 | case TypeId::BOOL: |
87 | return sizeof(bool); |
88 | case TypeId::INT8: |
89 | return sizeof(int8_t); |
90 | case TypeId::INT16: |
91 | return sizeof(int16_t); |
92 | case TypeId::INT32: |
93 | return sizeof(int32_t); |
94 | case TypeId::INT64: |
95 | return sizeof(int64_t); |
96 | case TypeId::FLOAT: |
97 | return sizeof(float); |
98 | case TypeId::DOUBLE: |
99 | return sizeof(double); |
100 | case TypeId::HASH: |
101 | return sizeof(hash_t); |
102 | case TypeId::POINTER: |
103 | return sizeof(uintptr_t); |
104 | case TypeId::VARCHAR: |
105 | return sizeof(string_t); |
106 | case TypeId::STRUCT: |
107 | return 0; // no own payload |
108 | case TypeId::LIST: |
109 | return 16; // offset + len |
110 | case TypeId::VARBINARY: |
111 | return sizeof(blob_t); |
112 | default: |
113 | throw ConversionException("Invalid TypeId %d" , type); |
114 | } |
115 | } |
116 | |
117 | SQLType SQLTypeFromInternalType(TypeId type) { |
118 | switch (type) { |
119 | case TypeId::BOOL: |
120 | return SQLType(SQLTypeId::BOOLEAN); |
121 | case TypeId::INT8: |
122 | return SQLType::TINYINT; |
123 | case TypeId::INT16: |
124 | return SQLType::SMALLINT; |
125 | case TypeId::INT32: |
126 | return SQLType::INTEGER; |
127 | case TypeId::INT64: |
128 | return SQLType::BIGINT; |
129 | case TypeId::FLOAT: |
130 | return SQLType::FLOAT; |
131 | case TypeId::DOUBLE: |
132 | return SQLType::DOUBLE; |
133 | case TypeId::VARCHAR: |
134 | return SQLType::VARCHAR; |
135 | case TypeId::VARBINARY: |
136 | return SQLType(SQLTypeId::VARBINARY); |
137 | case TypeId::STRUCT: |
138 | return SQLType(SQLTypeId::STRUCT); // TODO we do not know the child types here |
139 | case TypeId::LIST: |
140 | return SQLType(SQLTypeId::LIST); |
141 | default: |
142 | throw ConversionException("Invalid TypeId %d" , type); |
143 | } |
144 | } |
145 | |
146 | bool TypeIsConstantSize(TypeId type) { |
147 | return (type >= TypeId::BOOL && type <= TypeId::DOUBLE) || |
148 | (type >= TypeId::FIXED_SIZE_BINARY && type <= TypeId::DECIMAL) || type == TypeId::HASH || |
149 | type == TypeId::POINTER; |
150 | } |
151 | bool TypeIsIntegral(TypeId type) { |
152 | return (type >= TypeId::UINT8 && type <= TypeId::INT64) || type == TypeId::HASH || type == TypeId::POINTER; |
153 | } |
154 | bool TypeIsNumeric(TypeId type) { |
155 | return type >= TypeId::UINT8 && type <= TypeId::DOUBLE; |
156 | } |
157 | bool TypeIsInteger(TypeId type) { |
158 | return type >= TypeId::UINT8 && type <= TypeId::INT64; |
159 | } |
160 | |
161 | void SQLType::Serialize(Serializer &serializer) { |
162 | serializer.Write(id); |
163 | serializer.Write(width); |
164 | serializer.Write(scale); |
165 | serializer.WriteString(collation); |
166 | } |
167 | |
168 | SQLType SQLType::Deserialize(Deserializer &source) { |
169 | auto id = source.Read<SQLTypeId>(); |
170 | auto width = source.Read<uint16_t>(); |
171 | auto scale = source.Read<uint8_t>(); |
172 | auto collation = source.Read<string>(); |
173 | return SQLType(id, width, scale, collation); |
174 | } |
175 | |
176 | string SQLTypeIdToString(SQLTypeId id) { |
177 | switch (id) { |
178 | case SQLTypeId::BOOLEAN: |
179 | return "BOOLEAN" ; |
180 | case SQLTypeId::TINYINT: |
181 | return "TINYINT" ; |
182 | case SQLTypeId::SMALLINT: |
183 | return "SMALLINT" ; |
184 | case SQLTypeId::INTEGER: |
185 | return "INTEGER" ; |
186 | case SQLTypeId::BIGINT: |
187 | return "BIGINT" ; |
188 | case SQLTypeId::DATE: |
189 | return "DATE" ; |
190 | case SQLTypeId::TIME: |
191 | return "TIME" ; |
192 | case SQLTypeId::TIMESTAMP: |
193 | return "TIMESTAMP" ; |
194 | case SQLTypeId::FLOAT: |
195 | return "FLOAT" ; |
196 | case SQLTypeId::DOUBLE: |
197 | return "DOUBLE" ; |
198 | case SQLTypeId::DECIMAL: |
199 | return "DECIMAL" ; |
200 | case SQLTypeId::VARCHAR: |
201 | return "VARCHAR" ; |
202 | case SQLTypeId::BLOB: |
203 | return "BLOB" ; |
204 | case SQLTypeId::VARBINARY: |
205 | return "VARBINARY" ; |
206 | case SQLTypeId::CHAR: |
207 | return "CHAR" ; |
208 | case SQLTypeId::SQLNULL: |
209 | return "NULL" ; |
210 | case SQLTypeId::ANY: |
211 | return "ANY" ; |
212 | case SQLTypeId::STRUCT: |
213 | return "STRUCT<?>" ; |
214 | case SQLTypeId::LIST: |
215 | return "LIST<?>" ; |
216 | default: |
217 | return "INVALID" ; |
218 | } |
219 | } |
220 | |
221 | string SQLTypeToString(SQLType type) { |
222 | // FIXME: display width/scale |
223 | switch (type.id) { |
224 | case SQLTypeId::STRUCT: { |
225 | string ret = "STRUCT<" ; |
226 | for (size_t i = 0; i < type.child_type.size(); i++) { |
227 | ret += type.child_type[i].first + ": " + SQLTypeToString(type.child_type[i].second); |
228 | if (i < type.child_type.size() - 1) { |
229 | ret += ", " ; |
230 | } |
231 | } |
232 | ret += ">" ; |
233 | return ret; |
234 | } |
235 | case SQLTypeId::LIST: { |
236 | if (type.child_type.size() == 0) { |
237 | return "LIST<?>" ; |
238 | } |
239 | if (type.child_type.size() != 1) { |
240 | throw Exception("List needs a single child element" ); |
241 | } |
242 | return "LIST<" + SQLTypeToString(type.child_type[0].second) + ">" ; |
243 | } |
244 | default: |
245 | return SQLTypeIdToString(type.id); |
246 | } |
247 | } |
248 | |
249 | SQLType TransformStringToSQLType(string str) { |
250 | auto lower_str = StringUtil::Lower(str); |
251 | // Transform column type |
252 | if (lower_str == "int" || lower_str == "int4" || lower_str == "signed" || lower_str == "integer" || |
253 | lower_str == "integral" || lower_str == "int32" ) { |
254 | return SQLType::INTEGER; |
255 | } else if (lower_str == "varchar" || lower_str == "bpchar" || lower_str == "text" || lower_str == "string" || |
256 | lower_str == "char" ) { |
257 | return SQLType::VARCHAR; |
258 | } else if (lower_str == "bytea" || lower_str == "blob" ) { |
259 | return SQLType::BLOB; |
260 | } else if (lower_str == "int8" || lower_str == "bigint" || lower_str == "int64" || lower_str == "long" ) { |
261 | return SQLType::BIGINT; |
262 | } else if (lower_str == "int2" || lower_str == "smallint" || lower_str == "short" || lower_str == "int16" ) { |
263 | return SQLType::SMALLINT; |
264 | } else if (lower_str == "timestamp" || lower_str == "datetime" ) { |
265 | return SQLType::TIMESTAMP; |
266 | } else if (lower_str == "bool" || lower_str == "boolean" || lower_str == "logical" ) { |
267 | return SQLType(SQLTypeId::BOOLEAN); |
268 | } else if (lower_str == "real" || lower_str == "float4" || lower_str == "float" ) { |
269 | return SQLType::FLOAT; |
270 | } else if (lower_str == "double" || lower_str == "numeric" || lower_str == "float8" ) { |
271 | return SQLType::DOUBLE; |
272 | } else if (lower_str == "tinyint" || lower_str == "int1" ) { |
273 | return SQLType::TINYINT; |
274 | } else if (lower_str == "varbinary" ) { |
275 | return SQLType(SQLTypeId::VARBINARY); |
276 | } else if (lower_str == "date" ) { |
277 | return SQLType::DATE; |
278 | } else if (lower_str == "time" ) { |
279 | return SQLType::TIME; |
280 | } else { |
281 | throw NotImplementedException("DataType %s not supported yet...\n" , str.c_str()); |
282 | } |
283 | } |
284 | |
285 | bool SQLType::IsIntegral() const { |
286 | switch (id) { |
287 | case SQLTypeId::TINYINT: |
288 | case SQLTypeId::SMALLINT: |
289 | case SQLTypeId::INTEGER: |
290 | case SQLTypeId::BIGINT: |
291 | return true; |
292 | default: |
293 | return false; |
294 | } |
295 | } |
296 | |
297 | bool SQLType::IsNumeric() const { |
298 | switch (id) { |
299 | case SQLTypeId::TINYINT: |
300 | case SQLTypeId::SMALLINT: |
301 | case SQLTypeId::INTEGER: |
302 | case SQLTypeId::BIGINT: |
303 | case SQLTypeId::FLOAT: |
304 | case SQLTypeId::DOUBLE: |
305 | case SQLTypeId::DECIMAL: |
306 | return true; |
307 | default: |
308 | return false; |
309 | } |
310 | } |
311 | |
312 | bool SQLType::IsMoreGenericThan(SQLType &other) const { |
313 | if (other.id == id) { |
314 | return false; |
315 | } |
316 | |
317 | if (other.id == SQLTypeId::SQLNULL) { |
318 | return true; |
319 | } |
320 | |
321 | switch (id) { |
322 | case SQLTypeId::SMALLINT: |
323 | switch (other.id) { |
324 | case SQLTypeId::TINYINT: |
325 | return true; |
326 | default: |
327 | return false; |
328 | } |
329 | case SQLTypeId::INTEGER: |
330 | switch (other.id) { |
331 | case SQLTypeId::TINYINT: |
332 | case SQLTypeId::SMALLINT: |
333 | return true; |
334 | default: |
335 | return false; |
336 | } |
337 | case SQLTypeId::BIGINT: |
338 | switch (other.id) { |
339 | case SQLTypeId::TINYINT: |
340 | case SQLTypeId::SMALLINT: |
341 | case SQLTypeId::INTEGER: |
342 | return true; |
343 | default: |
344 | return false; |
345 | } |
346 | case SQLTypeId::DOUBLE: |
347 | switch (other.id) { |
348 | case SQLTypeId::TINYINT: |
349 | case SQLTypeId::SMALLINT: |
350 | case SQLTypeId::INTEGER: |
351 | case SQLTypeId::BIGINT: |
352 | return true; |
353 | default: |
354 | return false; |
355 | } |
356 | return false; |
357 | case SQLTypeId::DATE: |
358 | return false; |
359 | case SQLTypeId::TIMESTAMP: |
360 | switch (other.id) { |
361 | case SQLTypeId::TIME: |
362 | case SQLTypeId::DATE: |
363 | return true; |
364 | default: |
365 | return false; |
366 | } |
367 | case SQLTypeId::VARCHAR: |
368 | return true; |
369 | default: |
370 | return false; |
371 | } |
372 | |
373 | return true; |
374 | } |
375 | |
376 | TypeId GetInternalType(SQLType type) { |
377 | switch (type.id) { |
378 | case SQLTypeId::BOOLEAN: |
379 | return TypeId::BOOL; |
380 | case SQLTypeId::TINYINT: |
381 | return TypeId::INT8; |
382 | case SQLTypeId::SMALLINT: |
383 | return TypeId::INT16; |
384 | case SQLTypeId::SQLNULL: |
385 | case SQLTypeId::DATE: |
386 | case SQLTypeId::TIME: |
387 | case SQLTypeId::INTEGER: |
388 | return TypeId::INT32; |
389 | case SQLTypeId::BIGINT: |
390 | case SQLTypeId::TIMESTAMP: |
391 | return TypeId::INT64; |
392 | case SQLTypeId::FLOAT: |
393 | return TypeId::FLOAT; |
394 | case SQLTypeId::DOUBLE: |
395 | return TypeId::DOUBLE; |
396 | case SQLTypeId::DECIMAL: |
397 | // FIXME: for now |
398 | return TypeId::DOUBLE; |
399 | case SQLTypeId::VARCHAR: |
400 | case SQLTypeId::CHAR: |
401 | case SQLTypeId::BLOB: |
402 | return TypeId::VARCHAR; |
403 | case SQLTypeId::VARBINARY: |
404 | return TypeId::VARBINARY; |
405 | case SQLTypeId::STRUCT: |
406 | return TypeId::STRUCT; |
407 | case SQLTypeId::LIST: |
408 | return TypeId::LIST; |
409 | case SQLTypeId::ANY: |
410 | return TypeId::INVALID; |
411 | default: |
412 | throw ConversionException("Invalid SQLType %s" , SQLTypeToString(type).c_str()); |
413 | } |
414 | } |
415 | |
416 | SQLType MaxSQLType(SQLType left, SQLType right) { |
417 | if (left.id < right.id) { |
418 | return right; |
419 | } else if (right.id < left.id) { |
420 | return left; |
421 | } else if (left.width > right.width || left.collation > right.collation) { |
422 | return left; |
423 | } else { |
424 | return right; |
425 | } |
426 | } |
427 | |
428 | bool ApproxEqual(float ldecimal, float rdecimal) { |
429 | float epsilon = fabs(rdecimal) * 0.01; |
430 | return fabs(ldecimal - rdecimal) <= epsilon; |
431 | } |
432 | |
433 | bool ApproxEqual(double ldecimal, double rdecimal) { |
434 | double epsilon = fabs(rdecimal) * 0.01; |
435 | return fabs(ldecimal - rdecimal) <= epsilon; |
436 | } |
437 | |
438 | } // namespace duckdb |
439 | |