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