OmniSciDB  06b3bd477c
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OutputBufferInitialization.cpp
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 
18 #include "BufferCompaction.h"
20 #include "TypePunning.h"
21 
22 #include "../Analyzer/Analyzer.h"
23 
24 extern bool g_bigint_count;
25 
26 std::vector<int64_t> init_agg_val_vec(const std::vector<TargetInfo>& targets,
28  std::vector<int64_t> agg_init_vals;
29  agg_init_vals.reserve(query_mem_desc.getSlotCount());
30  const bool is_group_by{query_mem_desc.isGroupBy()};
31  for (size_t target_idx = 0, agg_col_idx = 0; target_idx < targets.size();
32  ++target_idx, ++agg_col_idx) {
33  CHECK_LT(agg_col_idx, query_mem_desc.getSlotCount());
34  const auto agg_info = targets[target_idx];
35  if (!agg_info.is_agg || agg_info.agg_kind == kSAMPLE) {
36  if (agg_info.agg_kind == kSAMPLE && agg_info.sql_type.is_string() &&
37  agg_info.sql_type.get_compression() != kENCODING_NONE) {
38  agg_init_vals.push_back(
39  get_agg_initial_val(agg_info.agg_kind,
40  agg_info.sql_type,
41  is_group_by,
42  query_mem_desc.getCompactByteWidth()));
43  continue;
44  }
45  if (query_mem_desc.getPaddedSlotWidthBytes(agg_col_idx) > 0) {
46  agg_init_vals.push_back(0);
47  }
48  if (agg_info.sql_type.is_array() ||
49  (agg_info.sql_type.is_string() &&
50  agg_info.sql_type.get_compression() == kENCODING_NONE)) {
51  agg_init_vals.push_back(0);
52  }
53  if (agg_info.sql_type.is_geometry()) {
54  agg_init_vals.push_back(0);
55  for (auto i = 1; i < agg_info.sql_type.get_physical_coord_cols(); ++i) {
56  agg_init_vals.push_back(0);
57  agg_init_vals.push_back(0);
58  }
59  }
60  continue;
61  }
62  CHECK_GT(query_mem_desc.getPaddedSlotWidthBytes(agg_col_idx), 0);
63  const bool float_argument_input = takes_float_argument(agg_info);
64  const auto chosen_bytes = query_mem_desc.isLogicalSizedColumnsAllowed()
65  ? query_mem_desc.getPaddedSlotWidthBytes(agg_col_idx)
66  : query_mem_desc.getCompactByteWidth();
67  auto init_ti = get_compact_type(agg_info);
68  if (!is_group_by) {
69  init_ti.set_notnull(false);
70  }
71  agg_init_vals.push_back(
72  get_agg_initial_val(agg_info.agg_kind,
73  init_ti,
74  is_group_by || float_argument_input,
75  (float_argument_input ? sizeof(float) : chosen_bytes)));
76  if (kAVG == agg_info.agg_kind) {
77  ++agg_col_idx;
78  agg_init_vals.push_back(0);
79  }
80  }
81  return agg_init_vals;
82 }
83 
84 std::pair<int64_t, int64_t> inline_int_max_min(const size_t byte_width) {
85  switch (byte_width) {
86  case 1:
87  return std::make_pair(std::numeric_limits<int8_t>::max(),
88  std::numeric_limits<int8_t>::min());
89  case 2:
90  return std::make_pair(std::numeric_limits<int16_t>::max(),
91  std::numeric_limits<int16_t>::min());
92  case 4:
93  return std::make_pair(std::numeric_limits<int32_t>::max(),
94  std::numeric_limits<int32_t>::min());
95  case 8:
96  return std::make_pair(std::numeric_limits<int64_t>::max(),
97  std::numeric_limits<int64_t>::min());
98  default:
99  abort();
100  }
101 }
102 
103 std::pair<uint64_t, uint64_t> inline_uint_max_min(const size_t byte_width) {
104  switch (byte_width) {
105  case 1:
106  return std::make_pair(std::numeric_limits<uint8_t>::max(),
107  std::numeric_limits<uint8_t>::min());
108  case 2:
109  return std::make_pair(std::numeric_limits<uint16_t>::max(),
110  std::numeric_limits<uint16_t>::min());
111  case 4:
112  return std::make_pair(std::numeric_limits<uint32_t>::max(),
113  std::numeric_limits<uint32_t>::min());
114  case 8:
115  return std::make_pair(std::numeric_limits<uint64_t>::max(),
116  std::numeric_limits<uint64_t>::min());
117  default:
118  abort();
119  }
120 }
121 
122 // TODO(alex): proper types for aggregate
123 int64_t get_agg_initial_val(const SQLAgg agg,
124  const SQLTypeInfo& ti,
125  const bool enable_compaction,
126  const unsigned min_byte_width_to_compact) {
127  CHECK(!ti.is_string() || (agg == kSINGLE_VALUE || agg == kSAMPLE));
128  const auto byte_width =
129  enable_compaction
130  ? compact_byte_width(static_cast<unsigned>(get_bit_width(ti) >> 3),
131  unsigned(min_byte_width_to_compact))
132  : sizeof(int64_t);
133  CHECK(ti.get_logical_size() < 0 ||
134  byte_width >= static_cast<unsigned>(ti.get_logical_size()));
135  switch (agg) {
136  case kAVG:
137  case kSUM: {
138  if (!ti.get_notnull()) {
139  if (ti.is_fp()) {
140  switch (byte_width) {
141  case 4: {
142  const float null_float = inline_fp_null_val(ti);
143  return *reinterpret_cast<const int32_t*>(may_alias_ptr(&null_float));
144  }
145  case 8: {
146  const double null_double = inline_fp_null_val(ti);
147  return *reinterpret_cast<const int64_t*>(may_alias_ptr(&null_double));
148  }
149  default:
150  CHECK(false);
151  }
152  } else {
153  return inline_int_null_val(ti);
154  }
155  }
156  switch (byte_width) {
157  case 4: {
158  const float zero_float{0.};
159  return ti.is_fp()
160  ? *reinterpret_cast<const int32_t*>(may_alias_ptr(&zero_float))
161  : 0;
162  }
163  case 8: {
164  const double zero_double{0.};
165  return ti.is_fp()
166  ? *reinterpret_cast<const int64_t*>(may_alias_ptr(&zero_double))
167  : 0;
168  }
169  default:
170  CHECK(false);
171  }
172  }
173  case kCOUNT:
175  return 0;
176  case kMIN: {
177  switch (byte_width) {
178  case 1: {
179  CHECK(!ti.is_fp());
180  return ti.get_notnull() ? std::numeric_limits<int8_t>::max()
181  : inline_int_null_val(ti);
182  }
183  case 2: {
184  CHECK(!ti.is_fp());
185  return ti.get_notnull() ? std::numeric_limits<int16_t>::max()
186  : inline_int_null_val(ti);
187  }
188  case 4: {
189  const float max_float = std::numeric_limits<float>::max();
190  const float null_float =
191  ti.is_fp() ? static_cast<float>(inline_fp_null_val(ti)) : 0.;
192  return ti.is_fp()
193  ? (ti.get_notnull()
194  ? *reinterpret_cast<const int32_t*>(may_alias_ptr(&max_float))
195  : *reinterpret_cast<const int32_t*>(
196  may_alias_ptr(&null_float)))
197  : (ti.get_notnull() ? std::numeric_limits<int32_t>::max()
198  : inline_int_null_val(ti));
199  }
200  case 8: {
201  const double max_double = std::numeric_limits<double>::max();
202  const double null_double{ti.is_fp() ? inline_fp_null_val(ti) : 0.};
203  return ti.is_fp() ? (ti.get_notnull() ? *reinterpret_cast<const int64_t*>(
204  may_alias_ptr(&max_double))
205  : *reinterpret_cast<const int64_t*>(
206  may_alias_ptr(&null_double)))
207  : (ti.get_notnull() ? std::numeric_limits<int64_t>::max()
208  : inline_int_null_val(ti));
209  }
210  default:
211  CHECK(false);
212  }
213  }
214  case kSINGLE_VALUE:
215  case kSAMPLE:
216  case kMAX: {
217  switch (byte_width) {
218  case 1: {
219  CHECK(!ti.is_fp());
220  return ti.get_notnull() ? std::numeric_limits<int8_t>::min()
221  : inline_int_null_val(ti);
222  }
223  case 2: {
224  CHECK(!ti.is_fp());
225  return ti.get_notnull() ? std::numeric_limits<int16_t>::min()
226  : inline_int_null_val(ti);
227  }
228  case 4: {
229  const float min_float = -std::numeric_limits<float>::max();
230  const float null_float =
231  ti.is_fp() ? static_cast<float>(inline_fp_null_val(ti)) : 0.;
232  return (ti.is_fp())
233  ? (ti.get_notnull()
234  ? *reinterpret_cast<const int32_t*>(may_alias_ptr(&min_float))
235  : *reinterpret_cast<const int32_t*>(
236  may_alias_ptr(&null_float)))
237  : (ti.get_notnull() ? std::numeric_limits<int32_t>::min()
238  : inline_int_null_val(ti));
239  }
240  case 8: {
241  const double min_double = -std::numeric_limits<double>::max();
242  const double null_double{ti.is_fp() ? inline_fp_null_val(ti) : 0.};
243  return ti.is_fp() ? (ti.get_notnull() ? *reinterpret_cast<const int64_t*>(
244  may_alias_ptr(&min_double))
245  : *reinterpret_cast<const int64_t*>(
246  may_alias_ptr(&null_double)))
247  : (ti.get_notnull() ? std::numeric_limits<int64_t>::min()
248  : inline_int_null_val(ti));
249  }
250  default:
251  CHECK(false);
252  }
253  }
254  default:
255  abort();
256  }
257 }
258 
259 std::vector<int64_t> init_agg_val_vec(
260  const std::vector<Analyzer::Expr*>& targets,
261  const std::list<std::shared_ptr<Analyzer::Expr>>& quals,
263  std::vector<TargetInfo> target_infos;
264  target_infos.reserve(targets.size());
265  const auto agg_col_count = query_mem_desc.getSlotCount();
266  for (size_t target_idx = 0, agg_col_idx = 0;
267  target_idx < targets.size() && agg_col_idx < agg_col_count;
268  ++target_idx, ++agg_col_idx) {
269  const auto target_expr = targets[target_idx];
270  auto target = get_target_info(target_expr, g_bigint_count);
271  auto arg_expr = agg_arg(target_expr);
272  if (arg_expr) {
273  if (query_mem_desc.getQueryDescriptionType() ==
275  target.is_agg &&
276  (target.agg_kind == kMIN || target.agg_kind == kMAX ||
277  target.agg_kind == kSUM || target.agg_kind == kAVG)) {
278  set_notnull(target, false);
279  } else if (constrained_not_null(arg_expr, quals)) {
280  set_notnull(target, true);
281  }
282  }
283  target_infos.push_back(target);
284  }
285  return init_agg_val_vec(target_infos, query_mem_desc);
286 }
287 
288 const Analyzer::Expr* agg_arg(const Analyzer::Expr* expr) {
289  const auto agg_expr = dynamic_cast<const Analyzer::AggExpr*>(expr);
290  return agg_expr ? agg_expr->get_arg() : nullptr;
291 }
292 
294  const std::list<std::shared_ptr<Analyzer::Expr>>& quals) {
295  for (const auto& qual : quals) {
296  auto uoper = std::dynamic_pointer_cast<Analyzer::UOper>(qual);
297  if (!uoper) {
298  continue;
299  }
300  bool is_negated{false};
301  if (uoper->get_optype() == kNOT) {
302  uoper = std::dynamic_pointer_cast<Analyzer::UOper>(uoper->get_own_operand());
303  is_negated = true;
304  }
305  if (uoper && (uoper->get_optype() == kISNOTNULL ||
306  (is_negated && uoper->get_optype() == kISNULL))) {
307  if (*uoper->get_own_operand() == *expr) {
308  return true;
309  }
310  }
311  }
312  return false;
313 }
const Analyzer::Expr * agg_arg(const Analyzer::Expr *expr)
SQLAgg
Definition: sqldefs.h:71
bool constrained_not_null(const Analyzer::Expr *expr, const std::list< std::shared_ptr< Analyzer::Expr >> &quals)
const int64_t const uint32_t const uint32_t const uint32_t agg_col_count
unsigned compact_byte_width(unsigned qw, unsigned low_bound)
bool isLogicalSizedColumnsAllowed() const
TargetInfo get_target_info(const PointerType target_expr, const bool bigint_count)
Definition: TargetInfo.h:78
bool is_fp() const
Definition: sqltypes.h:419
int64_t get_agg_initial_val(const SQLAgg agg, const SQLTypeInfo &ti, const bool enable_compaction, const unsigned min_byte_width_to_compact)
Expr * get_arg() const
Definition: Analyzer.h:1097
bool takes_float_argument(const TargetInfo &target_info)
Definition: TargetInfo.h:133
#define CHECK_GT(x, y)
Definition: Logger.h:209
double inline_fp_null_val(const SQL_TYPE_INFO &ti)
Definition: sqldefs.h:73
const SQLTypeInfo get_compact_type(const TargetInfo &target)
size_t get_bit_width(const SQLTypeInfo &ti)
CHECK(cgen_state)
int get_logical_size() const
Definition: sqltypes.h:269
bool g_bigint_count
Definition: sqldefs.h:75
const int8_t getPaddedSlotWidthBytes(const size_t slot_idx) const
QueryDescriptionType getQueryDescriptionType() const
std::pair< uint64_t, uint64_t > inline_uint_max_min(const size_t byte_width)
#define CHECK_LT(x, y)
Definition: Logger.h:207
Definition: sqldefs.h:76
Descriptor for the result set buffer layout.
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
std::pair< int64_t, int64_t > inline_int_max_min(const size_t byte_width)
bool is_string() const
Definition: sqltypes.h:415
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:265
Definition: sqldefs.h:74
std::vector< int64_t > init_agg_val_vec(const std::vector< TargetInfo > &targets, const QueryMemoryDescriptor &query_mem_desc)
Definition: sqldefs.h:72
Definition: sqldefs.h:39
void set_notnull(TargetInfo &target, const bool not_null)