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