OmniSciDB  ca0c39ec8f
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
InlineNullValues.h
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef INLINENULLVALUES_H
18 #define INLINENULLVALUES_H
19 
20 #include "../Logger/Logger.h"
21 #include "funcannotations.h"
22 
23 #include <cassert>
24 #include <cfloat>
25 #include <cstdint>
26 #include <cstdlib>
27 #include <limits>
28 
29 #define NULL_BOOLEAN INT8_MIN
30 #define NULL_TINYINT INT8_MIN
31 #define NULL_SMALLINT INT16_MIN
32 #define NULL_INT INT32_MIN
33 #define NULL_BIGINT INT64_MIN
34 #define NULL_FLOAT FLT_MIN
35 #define NULL_DOUBLE DBL_MIN
36 
37 #define NULL_ARRAY_BOOLEAN (INT8_MIN + 1)
38 #define NULL_ARRAY_TINYINT (INT8_MIN + 1)
39 #define NULL_ARRAY_SMALLINT (INT16_MIN + 1)
40 #define NULL_ARRAY_INT (INT32_MIN + 1)
41 #define NULL_ARRAY_BIGINT (INT64_MIN + 1)
42 #define NULL_ARRAY_FLOAT (FLT_MIN * 2.0)
43 #define NULL_ARRAY_DOUBLE (DBL_MIN * 2.0)
44 
45 #define NULL_ARRAY_COMPRESSED_32 0x80000000U
46 
47 #if !(defined(__CUDACC__) || defined(NO_BOOST))
48 #define CONSTEXPR constexpr
49 #else
50 #define CONSTEXPR
51 #endif
52 
53 template <class T>
54 constexpr inline int64_t inline_int_null_value() {
55  return std::is_signed<T>::value ? std::numeric_limits<T>::min()
56  : std::numeric_limits<T>::max();
57 }
58 
59 template <class T>
60 constexpr inline int64_t inline_int_null_array_value() {
61  return std::is_signed<T>::value ? std::numeric_limits<T>::min() + 1
62  : std::numeric_limits<T>::max() - 1;
63  // TODO: null_array values in signed types would step on max valid value
64  // in fixlen unsigned arrays, the max valid value may need to be lowered.
65 }
66 
67 template <class T>
68 constexpr inline int64_t max_valid_int_value() {
69  return std::is_signed<T>::value ? std::numeric_limits<T>::max()
70  : std::numeric_limits<T>::max() - 1;
71 }
72 
73 template <typename T>
74 constexpr inline T inline_fp_null_value() {
75 #if !(defined(__CUDACC__) || defined(NO_BOOST))
76  LOG(FATAL) << "Only float or double overloads should be called.";
77 #else
78  assert(false);
79 #endif
80  return T{};
81 }
82 
83 template <>
84 constexpr inline float inline_fp_null_value<float>() {
85  return NULL_FLOAT;
86 }
87 
88 template <>
89 constexpr inline double inline_fp_null_value<double>() {
90  return NULL_DOUBLE;
91 }
92 
93 template <typename T>
95 #if !(defined(__CUDACC__) || defined(NO_BOOST))
96  LOG(FATAL) << "Only float or double overloads should be called.";
97 #else
98  assert(false);
99 #endif
100  return T{};
101 }
102 
103 template <>
105  return NULL_ARRAY_FLOAT;
106 }
107 
108 template <>
110  return NULL_ARRAY_DOUBLE;
111 }
112 
113 #ifndef NO_BOOST
114 template <typename SQL_TYPE_INFO>
115 inline int64_t inline_int_null_val(const SQL_TYPE_INFO& ti) {
116  auto type = ti.get_type();
117  if (ti.is_string()) {
118  CHECK_EQ(kENCODING_DICT, ti.get_compression());
119  CHECK_EQ(4, ti.get_logical_size());
120  type = kINT;
121  } else {
122  CHECK_EQ(kENCODING_NONE, ti.get_compression());
123  }
124  switch (type) {
125  case kBOOLEAN:
126  return inline_int_null_value<int8_t>();
127  case kTINYINT:
128  return inline_int_null_value<int8_t>();
129  case kSMALLINT:
130  return inline_int_null_value<int16_t>();
131  case kINT:
132  return inline_int_null_value<int32_t>();
133  case kBIGINT:
134  return inline_int_null_value<int64_t>();
135  case kTIMESTAMP:
136  case kTIME:
137  if (ti.get_compression() == kENCODING_FIXED) {
139  }
140  case kDATE:
141  case kINTERVAL_DAY_TIME:
143  return inline_int_null_value<int64_t>();
144  case kDECIMAL:
145  case kNUMERIC:
146  return inline_int_null_value<int64_t>();
147  default:
148  abort();
149  }
150 }
151 
152 template <typename SQL_TYPE_INFO>
153 inline int64_t inline_fixed_encoding_null_val(const SQL_TYPE_INFO& ti) {
154  if (ti.get_compression() == kENCODING_NONE) {
155  return inline_int_null_val(ti);
156  }
157  if (ti.get_compression() == kENCODING_DATE_IN_DAYS) {
158  switch (ti.get_comp_param()) {
159  case 0:
160  case 32:
161  return inline_int_null_value<int32_t>();
162  case 16:
163  return inline_int_null_value<int16_t>();
164  default:
165 #ifndef __CUDACC__
166  CHECK(false) << "Unknown encoding width for date in days: "
167  << ti.get_comp_param();
168 #else
169  CHECK(false);
170 #endif
171  }
172  }
173  if (ti.get_compression() == kENCODING_DICT) {
174  CHECK(ti.is_string());
175  switch (ti.get_size()) {
176  case 1:
177  return inline_int_null_value<uint8_t>();
178  case 2:
179  return inline_int_null_value<uint16_t>();
180  case 4:
181  return inline_int_null_value<int32_t>();
182  default:
183 #ifndef __CUDACC__
184  CHECK(false) << "Unknown size for dictionary encoded type: " << ti.get_size();
185 #else
186  CHECK(false);
187 #endif
188  }
189  }
190  CHECK_EQ(kENCODING_FIXED, ti.get_compression());
191  CHECK(ti.is_integer() || ti.is_time() || ti.is_decimal());
192  CHECK_EQ(0, ti.get_comp_param() % 8);
193  return -(1LL << (ti.get_comp_param() - 1));
194 }
195 
196 template <typename SQL_TYPE_INFO>
197 inline double inline_fp_null_val(const SQL_TYPE_INFO& ti) {
198  CHECK(ti.is_fp());
199  const auto type = ti.get_type();
200  switch (type) {
201  case kFLOAT:
203  case kDOUBLE:
205  default:
206  abort();
207  }
208 }
209 
210 // NULL_ARRAY sentinels
211 template <typename SQL_TYPE_INFO>
212 inline int64_t inline_int_null_array_val(const SQL_TYPE_INFO& ti) {
213  auto type = ti.get_type();
214  if (ti.is_string()) {
215  CHECK_EQ(kENCODING_DICT, ti.get_compression());
216  CHECK_EQ(4, ti.get_logical_size());
217  type = kINT;
218  } else {
219  CHECK_EQ(kENCODING_NONE, ti.get_compression());
220  }
221  // For all of the types below NULL sentinel is min of the range,
222  // the value right above it is the NULL_ARRAY sentinel
223  switch (type) {
224  case kBOOLEAN:
225  return inline_int_null_array_value<int8_t>();
226  case kTINYINT:
227  return inline_int_null_array_value<int8_t>();
228  case kSMALLINT:
229  return inline_int_null_array_value<int16_t>();
230  case kINT:
231  return inline_int_null_array_value<int32_t>();
232  case kBIGINT:
233  return inline_int_null_array_value<int64_t>();
234  case kTIMESTAMP:
235  case kTIME:
236  if (ti.get_compression() == kENCODING_FIXED) {
238  }
239  case kDATE:
240  case kINTERVAL_DAY_TIME:
242  return inline_int_null_array_value<int64_t>();
243  case kDECIMAL:
244  case kNUMERIC:
245  return inline_int_null_array_value<int64_t>();
246  default:
247  abort();
248  }
249 }
250 
251 template <typename SQL_TYPE_INFO>
252 inline int64_t inline_fixed_encoding_null_array_val(const SQL_TYPE_INFO& ti) {
253  if (ti.get_compression() == kENCODING_NONE) {
254  return inline_int_null_array_val(ti);
255  }
256  if (ti.get_compression() == kENCODING_DATE_IN_DAYS) {
257  switch (ti.get_comp_param()) {
258  case 0:
259  case 32:
260  return inline_int_null_array_value<int32_t>();
261  case 16:
262  return inline_int_null_array_value<int16_t>();
263  default:
264 #ifndef __CUDACC__
265  CHECK(false) << "Unknown encoding width for date in days: "
266  << ti.get_comp_param();
267 #else
268  CHECK(false);
269 #endif
270  }
271  }
272  if (ti.get_compression() == kENCODING_DICT) {
273  CHECK(ti.is_string());
274  switch (ti.get_size()) {
275  case 1:
276  return inline_int_null_array_value<uint8_t>();
277  case 2:
278  return inline_int_null_array_value<uint16_t>();
279  case 4:
280  return inline_int_null_array_value<int32_t>();
281  default:
282 #ifndef __CUDACC__
283  CHECK(false) << "Unknown size for dictionary encoded type: " << ti.get_size();
284 #else
285  CHECK(false);
286 #endif
287  }
288  }
289 #ifndef __CUDACC__
290  CHECK(false) << "Currently don't support fixed length arrays with fixed encoding";
291 #else
292  CHECK(false);
293 #endif
294  CHECK_EQ(kENCODING_FIXED, ti.get_compression());
295  CHECK(ti.is_integer() || ti.is_time() || ti.is_decimal());
296  CHECK_EQ(0, ti.get_comp_param() % 8);
297  // The value of the NULL sentinel for fixed encoding is:
298  // -(1LL << (ti.get_comp_param() - 1))
299  // NULL_ARRAY sentinel would have to be the value just above NULL:
300  return -(1LL << (ti.get_comp_param() - 1)) + 1;
301 }
302 
303 #endif // NO_BOOST
304 
305 #include <type_traits>
306 
307 namespace serialize_detail {
308 template <int overload>
309 struct IntType;
310 template <>
311 struct IntType<1> {
312  using type = uint8_t;
313 };
314 template <>
315 struct IntType<2> {
316  using type = uint16_t;
317 };
318 template <>
319 struct IntType<4> {
320  using type = uint32_t;
321 };
322 template <>
323 struct IntType<8> {
324  using type = uint64_t;
325 };
326 } // namespace serialize_detail
327 
328 template <typename T, bool array = false>
331  using TT = typename serialize_detail::IntType<sizeof(T)>::type;
332  T nv = 0;
333  if
334  CONSTEXPR(std::is_floating_point<T>::value) {
335  if
336  CONSTEXPR(array) { nv = inline_fp_null_array_value<T>(); }
337  else {
338  nv = inline_fp_null_value<T>();
339  }
340  }
341  else if
342  CONSTEXPR(std::is_integral<T>::value) {
343  if
344  CONSTEXPR(array) { nv = inline_int_null_array_value<T>(); }
345  else {
346  nv = inline_int_null_value<T>();
347  }
348  }
349 #if !(defined(__CUDACC__) || defined(NO_BOOST))
350  else {
351  CHECK(false) << "Serializing null values of floating point or integral types only is "
352  "supported.";
353  }
354 #endif
355  return *(TT*)(&nv);
356 }
357 
358 template <typename T, bool array = false>
359 CONSTEXPR DEVICE inline bool is_null(const T& value) {
360  using TT = typename serialize_detail::IntType<sizeof(T)>::type;
361  return serialized_null_value<T, array>() == *(TT*)(&value);
362 }
363 
364 template <typename T>
366  if
367  CONSTEXPR(std::is_floating_point<T>::value) { return inline_fp_null_value<T>(); }
368  else if
369  CONSTEXPR(std::is_integral<T>::value) { return inline_int_null_value<T>(); }
370 #if !(defined(__CUDACC__) || defined(NO_BOOST))
371  else {
372  CHECK(false) << "Serializing null values of floating point or integral types only is "
373  "supported.";
374  }
375 #endif
376  return inline_int_null_value<int32_t>(); // dummy return
377 }
378 
379 template <typename T, bool array = false>
380 CONSTEXPR DEVICE inline void set_null(T& value) {
381  using TT = typename serialize_detail::IntType<sizeof(T)>::type;
382  *(TT*)(&value) = serialized_null_value<T, array>();
383 }
384 
385 #endif
#define CHECK_EQ(x, y)
Definition: Logger.h:230
#define NULL_DOUBLE
Definition: sqltypes.h:64
constexpr T inline_fp_null_value()
CONSTEXPR DEVICE serialize_detail::IntType< sizeof(T)>::type serialized_null_value()
#define NULL_FLOAT
#define LOG(tag)
Definition: Logger.h:216
DEVICE T inline_fp_null_array_value()
DEVICE float inline_fp_null_array_value< float >()
double inline_fp_null_val(const SQL_TYPE_INFO &ti)
#define DEVICE
CONSTEXPR DEVICE bool is_null(const T &value)
#define CONSTEXPR
DEVICE TextEncodingDict inline_null_value()
Definition: heavydbTypes.h:166
DEVICE double inline_fp_null_array_value< double >()
CONSTEXPR DEVICE void set_null(T &value)
#define NULL_ARRAY_FLOAT
int64_t inline_int_null_array_val(const SQL_TYPE_INFO &ti)
Definition: sqltypes.h:68
constexpr int64_t inline_int_null_value()
constexpr float inline_fp_null_value< float >()
constexpr double inline_fp_null_value< double >()
int64_t inline_fixed_encoding_null_array_val(const SQL_TYPE_INFO &ti)
#define NULL_ARRAY_DOUBLE
#define CHECK(condition)
Definition: Logger.h:222
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
int64_t inline_fixed_encoding_null_val(const SQL_TYPE_INFO &ti)
Definition: sqltypes.h:60
constexpr int64_t inline_int_null_array_value()
constexpr int64_t max_valid_int_value()