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