OmniSciDB  c0231cc57d
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TypedDataAccessors.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 H_TypedDataAccessors__
18 #define H_TypedDataAccessors__
19 
20 #include <cmath>
21 #include <cstring>
22 #include "Logger/Logger.h"
23 #include "Shared/DateConverters.h"
25 #include "Shared/sqltypes.h"
26 
27 namespace {
28 
29 template <typename LHT, typename RHT>
30 inline void value_truncated(const LHT& lhs, const RHT& rhs) {
31  std::ostringstream os;
32  os << "Value " << rhs << " would be truncated to "
33  << (std::is_same<LHT, uint8_t>::value || std::is_same<LHT, int8_t>::value
34  ? (int64_t)lhs
35  : lhs);
36  throw std::runtime_error(os.str());
37 };
38 
39 template <typename T>
40 inline bool is_null(const T& v, const SQLTypeInfo& t) {
41  if (std::is_floating_point<T>::value) {
42  return v == inline_fp_null_value<T>();
43  }
44  switch (t.get_logical_size()) {
45  case 1:
46  return v == inline_int_null_value<int8_t>();
47  case 2:
48  return v == inline_int_null_value<int16_t>();
49  case 4:
50  return v == inline_int_null_value<int32_t>();
51  case 8:
52  return v == inline_int_null_value<int64_t>();
53  default:
54  abort();
55  }
56 }
57 
58 template <typename LHT, typename RHT>
59 inline bool integer_setter(LHT& lhs, const RHT& rhs, const SQLTypeInfo& t) {
60  const int64_t r = is_null(rhs, t) ? inline_int_null_value<LHT>() : rhs;
61  if ((lhs = r) != r) {
62  value_truncated(lhs, r);
63  }
64  return true;
65 }
66 
67 inline int get_element_size(const SQLTypeInfo& t) {
68  if (t.is_string_array()) {
69  return sizeof(int32_t);
70  }
71  if (!t.is_array()) {
72  return t.get_size();
73  }
74  return SQLTypeInfo(t.get_subtype(),
75  t.get_dimension(),
76  t.get_scale(),
77  false,
78  t.get_compression(),
79  t.get_comp_param(),
80  kNULLT)
81  .get_size();
82 }
83 
84 inline bool is_null_string_index(const int size, const int32_t sidx) {
85  switch (size) {
86  case 1:
87  return sidx == inline_int_null_value<uint8_t>();
88  case 2:
89  return sidx == inline_int_null_value<uint16_t>();
90  case 4:
91  return sidx == inline_int_null_value<int32_t>();
92  default:
93  abort();
94  }
95 }
96 
97 inline int32_t get_string_index(void* ptr, const int size) {
98  switch (size) {
99  case 1:
100  return *(uint8_t*)ptr;
101  case 2:
102  return *(uint16_t*)ptr;
103  case 4:
104  return *(int32_t*)ptr;
105  default:
106  abort();
107  }
108 }
109 
110 inline bool set_string_index(void* ptr, const SQLTypeInfo& etype, int32_t sidx) {
111  switch (get_element_size(etype)) {
112  case 1:
113  return integer_setter(*(uint8_t*)ptr, sidx, etype);
114  break;
115  case 2:
116  return integer_setter(*(uint16_t*)ptr, sidx, etype);
117  break;
118  case 4:
119  return integer_setter(*(int32_t*)ptr, sidx, etype);
120  break;
121  default:
122  abort();
123  }
124 }
125 
126 template <typename T>
127 static void put_scalar(void* ndptr,
128  const SQLTypeInfo& etype,
129  const int esize,
130  const T oval) {
131  // round floating oval to nearest integer
132  auto rval = oval;
133  if (std::is_floating_point<T>::value) {
134  if (etype.is_integer() || etype.is_time() || etype.is_timeinterval() ||
135  etype.is_decimal()) {
136  rval = round(rval);
137  }
138  }
139  switch (etype.get_type()) {
140  case kBOOLEAN:
141  case kTIME:
142  case kTIMESTAMP:
143  case kDATE:
144  case kTINYINT:
145  case kSMALLINT:
146  case kINT:
147  case kBIGINT:
148  case kINTERVAL_DAY_TIME:
150  case kNUMERIC:
151  case kDECIMAL:
152  switch (esize) {
153  case 1:
154  integer_setter(*(int8_t*)ndptr, rval, etype);
155  break;
156  case 2:
157  integer_setter(*(int16_t*)ndptr, rval, etype);
158  break;
159  case 4:
160  integer_setter(*(int32_t*)ndptr, rval, etype);
161  break;
162  case 8:
163  integer_setter(*(int64_t*)ndptr, rval, etype);
164  break;
165  default:
166  abort();
167  }
168  break;
169  case kFLOAT:
170  *(float*)ndptr = rval;
171  break;
172  case kDOUBLE:
173  *(double*)ndptr = rval;
174  break;
175  default:
176  if (etype.is_string() && !etype.is_varlen()) {
177  set_string_index(ndptr, etype, rval);
178  } else {
179  abort();
180  }
181  break;
182  }
183 }
184 
185 inline double decimal_to_double(const SQLTypeInfo& otype, int64_t oval) {
186  return oval / pow(10, otype.get_scale());
187 }
188 
189 template <typename T>
190 inline void put_scalar(void* ndptr,
191  const SQLTypeInfo& ntype,
192  const T oval,
193  const std::string col_name,
194  const SQLTypeInfo* otype = nullptr) {
195  const auto& etype = ntype.is_array() ? SQLTypeInfo(ntype.get_subtype(),
196  ntype.get_dimension(),
197  ntype.get_scale(),
198  ntype.get_notnull(),
199  ntype.get_compression(),
200  ntype.get_comp_param(),
201  kNULLT)
202  : ntype;
203  const auto esize = get_element_size(etype);
204  const auto isnull = is_null(oval, etype);
205  if (etype.get_notnull() && isnull) {
206  throw std::runtime_error("NULL value on NOT NULL column '" + col_name + "'");
207  }
208 
209  switch (etype.get_type()) {
210  case kNUMERIC:
211  case kDECIMAL:
212  if (otype && otype->is_decimal()) {
213  put_scalar<int64_t>(ndptr,
214  etype,
215  esize,
216  isnull ? inline_int_null_value<int64_t>()
217  : convert_decimal_value_to_scale(oval, *otype, etype));
218  } else {
219  put_scalar<T>(ndptr,
220  etype,
221  esize,
222  isnull ? inline_int_null_value<int64_t>()
223  : oval * pow(10, etype.get_scale()));
224  }
225  break;
226  case kDATE:
227  // For small dates, we store in days but decode in seconds
228  // therefore we have to scale the decoded value in order to
229  // make value storable.
230  // Should be removed when we refactor code to use DateConverterFactory
231  // from TargetValueConverterFactories so that we would
232  // have everything in one place.
233  if (etype.is_date_in_days()) {
234  put_scalar<T>(ndptr,
235  etype,
236  get_element_size(etype),
237  isnull ? inline_int_null_value<int64_t>()
239  static_cast<int64_t>(oval)));
240  } else {
241  put_scalar<T>(ndptr, etype, get_element_size(etype), oval);
242  }
243  break;
244  default:
245  if (otype && otype->is_decimal()) {
246  put_scalar<double>(ndptr, etype, decimal_to_double(*otype, oval), col_name);
247  } else {
248  put_scalar<T>(ndptr, etype, get_element_size(etype), oval);
249  }
250  break;
251  }
252 }
253 
254 inline void put_null(void* ndptr, const SQLTypeInfo& ntype, const std::string col_name) {
255  if (ntype.get_notnull()) {
256  throw std::runtime_error("NULL value on NOT NULL column '" + col_name + "'");
257  }
258 
259  switch (ntype.get_type()) {
260  case kBOOLEAN:
261  case kTINYINT:
262  case kSMALLINT:
263  case kINT:
264  case kBIGINT:
265  case kTIME:
266  case kTIMESTAMP:
267  case kDATE:
268  case kINTERVAL_DAY_TIME:
270  case kNUMERIC:
271  case kDECIMAL:
272  case kTEXT:
273  switch (ntype.get_size()) {
274  case 1:
275  *(int8_t*)ndptr = inline_int_null_value<int8_t>();
276  break;
277  case 2:
278  *(int16_t*)ndptr = inline_int_null_value<int16_t>();
279  break;
280  case 4:
281  *(int32_t*)ndptr = inline_int_null_value<int32_t>();
282  break;
283  case 8:
284  *(int64_t*)ndptr = inline_int_null_value<int64_t>();
285  break;
286  default:
287  abort();
288  }
289  break;
290  case kFLOAT:
291  *(float*)ndptr = inline_fp_null_value<float>();
292  break;
293  case kDOUBLE:
294  *(double*)ndptr = inline_fp_null_value<double>();
295  break;
296  default:
299  CHECK(false);
300  }
301 }
302 
303 inline void put_null_array(void* ndptr,
304  const SQLTypeInfo& ntype,
305  const std::string col_name) {
306  if (ntype.get_notnull()) {
307  throw std::runtime_error("NULL value on NOT NULL column '" + col_name + "'");
308  }
309 
310  switch (ntype.get_type()) {
311  case kBOOLEAN:
312  case kTINYINT:
313  case kSMALLINT:
314  case kINT:
315  case kBIGINT:
316  case kTIME:
317  case kTIMESTAMP:
318  case kDATE:
319  case kINTERVAL_DAY_TIME:
321  case kNUMERIC:
322  case kDECIMAL:
323  case kTEXT:
324  switch (ntype.get_size()) {
325  case 1:
326  *(int8_t*)ndptr = inline_int_null_array_value<int8_t>();
327  break;
328  case 2:
329  *(int16_t*)ndptr = inline_int_null_array_value<int16_t>();
330  break;
331  case 4:
332  *(int32_t*)ndptr = inline_int_null_array_value<int32_t>();
333  break;
334  case 8:
335  *(int64_t*)ndptr = inline_int_null_array_value<int64_t>();
336  break;
337  default:
338  abort();
339  }
340  break;
341  case kFLOAT:
342  *(float*)ndptr = inline_fp_null_array_value<float>();
343  break;
344  case kDOUBLE:
345  *(double*)ndptr = inline_fp_null_array_value<double>();
346  break;
347  default:
350  CHECK(false);
351  }
352 }
353 
354 template <typename T>
355 inline bool get_scalar(void* ndptr, const SQLTypeInfo& ntype, T& v) {
356  switch (ntype.get_type()) {
357  case kBOOLEAN:
358  case kTINYINT:
359  case kSMALLINT:
360  case kINT:
361  case kBIGINT:
362  case kTIME:
363  case kTIMESTAMP:
364  case kDATE:
365  case kINTERVAL_DAY_TIME:
367  case kNUMERIC:
368  case kDECIMAL:
369  switch (ntype.get_size()) {
370  case 1:
371  return inline_int_null_value<int8_t>() == (v = *(int8_t*)ndptr);
372  case 2:
373  return inline_int_null_value<int16_t>() == (v = *(int16_t*)ndptr);
374  case 4:
375  return inline_int_null_value<int32_t>() == (v = *(int32_t*)ndptr);
376  case 8:
377  return inline_int_null_value<int64_t>() == (v = *(int64_t*)ndptr);
378  break;
379  default:
380  abort();
381  }
382  break;
383  case kFLOAT:
384  return inline_fp_null_value<float>() == (v = *(float*)ndptr);
385  case kDOUBLE:
386  return inline_fp_null_value<double>() == (v = *(double*)ndptr);
387  case kTEXT:
388  v = get_string_index(ndptr, ntype.get_size());
389  return is_null_string_index(ntype.get_size(), v);
390  default:
391  abort();
392  }
393 }
394 
396  public:
397  template <typename TYPE_INFO, typename VAL>
398  auto operator()(TYPE_INFO const& ti, VAL const&) const {
399  using FloatOrIntSelector =
400  typename std::conditional<std::is_floating_point<std::decay_t<VAL> >::value,
401  FPSelector,
403  return get_null_sentinel_for_type(ti, FloatOrIntSelector());
404  }
405 
406  private:
407  struct IntSelector {};
408  struct FPSelector {};
409 
410  template <typename TYPE_INFO>
411  int64_t get_null_sentinel_for_type(TYPE_INFO const& ti, IntSelector const&) const {
413  }
414 
415  template <typename TYPE_INFO>
416  double get_null_sentinel_for_type(TYPE_INFO const& ti, FPSelector const&) const {
417  return inline_fp_null_val(ti);
418  }
419 };
420 
421 template <typename T>
422 inline void set_minmax(T& min, T& max, T const val) {
423  if (val < min) {
424  min = val;
425  }
426  if (val > max) {
427  max = val;
428  }
429 }
430 
431 template <typename T>
432 inline void set_minmax(T& min, T& max, bool& null_flag, T const val, T null_sentinel) {
433  if (val == null_sentinel) {
434  null_flag = true;
435  } else {
436  if (val < min) {
437  min = val;
438  }
439  if (val > max) {
440  max = val;
441  }
442  }
443 }
444 
445 } // namespace
446 #endif
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:405
HOST DEVICE int get_size() const
Definition: sqltypes.h:414
Definition: sqltypes.h:63
double decimal_to_double(const SQLTypeInfo &otype, int64_t oval)
bool is_null_string_index(const int size, const int32_t sidx)
HOST DEVICE int get_scale() const
Definition: sqltypes.h:409
DEVICE float inline_fp_null_array_value< float >()
bool is_varlen() const
Definition: sqltypes.h:640
void value_truncated(const LHT &lhs, const RHT &rhs)
SQLTypeInfo get_logical_type_info(const SQLTypeInfo &type_info)
Definition: sqltypes.h:1221
Constants for Builtin SQL Types supported by HEAVY.AI.
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:404
double inline_fp_null_val(const SQL_TYPE_INFO &ti)
bool is_time() const
Definition: sqltypes.h:606
static void put_scalar(void *ndptr, const SQLTypeInfo &etype, const int esize, const T oval)
CONSTEXPR DEVICE bool is_null(const T &value)
bool get_scalar(void *ndptr, const SQLTypeInfo &ntype, T &v)
DEVICE double inline_fp_null_array_value< double >()
int get_logical_size() const
Definition: sqltypes.h:424
bool is_integer() const
Definition: sqltypes.h:602
void put_null_array(void *ndptr, const SQLTypeInfo &ntype, const std::string col_name)
bool is_timeinterval() const
Definition: sqltypes.h:611
auto operator()(TYPE_INFO const &ti, VAL const &) const
double get_null_sentinel_for_type(TYPE_INFO const &ti, FPSelector const &) const
int64_t get_null_sentinel_for_type(TYPE_INFO const &ti, IntSelector const &) const
void put_null(void *ndptr, const SQLTypeInfo &ntype, const std::string col_name)
Definition: sqltypes.h:66
Definition: sqltypes.h:67
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:412
int64_t convert_decimal_value_to_scale(const int64_t decimal_value, const SQLTypeInfo &type_info, const SQLTypeInfo &new_type_info)
Definition: Datum.cpp:562
constexpr float inline_fp_null_value< float >()
HOST DEVICE int get_dimension() const
Definition: sqltypes.h:406
constexpr double inline_fp_null_value< double >()
HOST DEVICE int get_comp_param() const
Definition: sqltypes.h:413
bool set_string_index(void *ptr, const SQLTypeInfo &etype, int32_t sidx)
bool integer_setter(LHT &lhs, const RHT &rhs, const SQLTypeInfo &t)
#define CHECK(condition)
Definition: Logger.h:222
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
int64_t get_epoch_days_from_seconds(const int64_t seconds)
Definition: sqltypes.h:59
bool is_string() const
Definition: sqltypes.h:600
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:411
void set_minmax(T &min, T &max, T const val)
int32_t get_string_index(void *ptr, const int size)
bool is_string_array() const
Definition: sqltypes.h:601
bool is_decimal() const
Definition: sqltypes.h:603
bool is_array() const
Definition: sqltypes.h:608