OmniSciDB  0264ff685a
ResultSetIteration.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 
25 #include "Execute.h"
26 #include "Geospatial/Compression.h"
27 #include "Geospatial/Types.h"
28 #include "ParserNode.h"
30 #include "ResultSet.h"
32 #include "RuntimeFunctions.h"
33 #include "Shared/SqlTypesLayout.h"
34 #include "Shared/likely.h"
35 #include "Shared/quantile.h"
36 #include "Shared/sqltypes.h"
37 #include "TypePunning.h"
38 
39 #include <boost/math/special_functions/fpclassify.hpp>
40 
41 #include <memory>
42 #include <utility>
43 
44 namespace {
45 
46 // Interprets ptr1, ptr2 as the sum and count pair used for AVG.
48  const int8_t compact_sz1,
49  const int8_t* ptr2,
50  const int8_t compact_sz2,
51  const TargetInfo& target_info) {
52  int64_t sum{0};
53  CHECK(target_info.agg_kind == kAVG);
54  const bool float_argument_input = takes_float_argument(target_info);
55  const auto actual_compact_sz1 = float_argument_input ? sizeof(float) : compact_sz1;
56  const auto& agg_ti = target_info.agg_arg_type;
57  if (agg_ti.is_integer() || agg_ti.is_decimal()) {
58  sum = read_int_from_buff(ptr1, actual_compact_sz1);
59  } else if (agg_ti.is_fp()) {
60  switch (actual_compact_sz1) {
61  case 8: {
62  double d = *reinterpret_cast<const double*>(ptr1);
63  sum = *reinterpret_cast<const int64_t*>(may_alias_ptr(&d));
64  break;
65  }
66  case 4: {
67  double d = *reinterpret_cast<const float*>(ptr1);
68  sum = *reinterpret_cast<const int64_t*>(may_alias_ptr(&d));
69  break;
70  }
71  default:
72  CHECK(false);
73  }
74  } else {
75  CHECK(false);
76  }
77  const auto count = read_int_from_buff(ptr2, compact_sz2);
78  return pair_to_double({sum, count}, target_info.sql_type, false);
79 }
80 
81 // Given the entire buffer for the result set, buff, finds the beginning of the
82 // column for slot_idx. Only makes sense for column-wise representation.
83 const int8_t* advance_col_buff_to_slot(const int8_t* buff,
84  const QueryMemoryDescriptor& query_mem_desc,
85  const std::vector<TargetInfo>& targets,
86  const size_t slot_idx,
87  const bool separate_varlen_storage) {
88  auto crt_col_ptr = get_cols_ptr(buff, query_mem_desc);
89  const auto buffer_col_count = query_mem_desc.getBufferColSlotCount();
90  size_t agg_col_idx{0};
91  for (size_t target_idx = 0; target_idx < targets.size(); ++target_idx) {
92  if (agg_col_idx == slot_idx) {
93  return crt_col_ptr;
94  }
95  CHECK_LT(agg_col_idx, buffer_col_count);
96  const auto& agg_info = targets[target_idx];
97  crt_col_ptr =
98  advance_to_next_columnar_target_buff(crt_col_ptr, query_mem_desc, agg_col_idx);
99  if (agg_info.is_agg && agg_info.agg_kind == kAVG) {
100  if (agg_col_idx + 1 == slot_idx) {
101  return crt_col_ptr;
102  }
104  crt_col_ptr, query_mem_desc, agg_col_idx + 1);
105  }
106  agg_col_idx = advance_slot(agg_col_idx, agg_info, separate_varlen_storage);
107  }
108  CHECK(false);
109  return nullptr;
110 }
111 } // namespace
112 
113 // Gets the byte offset, starting from the beginning of the row targets buffer, of
114 // the value in position slot_idx (only makes sense for row-wise representation).
115 size_t result_set::get_byteoff_of_slot(const size_t slot_idx,
116  const QueryMemoryDescriptor& query_mem_desc) {
117  return query_mem_desc.getPaddedColWidthForRange(0, slot_idx);
118 }
119 
120 std::vector<TargetValue> ResultSet::getRowAt(
121  const size_t global_entry_idx,
122  const bool translate_strings,
123  const bool decimal_to_double,
124  const bool fixup_count_distinct_pointers,
125  const std::vector<bool>& targets_to_skip /* = {}*/) const {
126  const auto storage_lookup_result =
127  fixup_count_distinct_pointers
128  ? StorageLookupResult{storage_.get(), global_entry_idx, 0}
129  : findStorage(global_entry_idx);
130  const auto storage = storage_lookup_result.storage_ptr;
131  const auto local_entry_idx = storage_lookup_result.fixedup_entry_idx;
132  if (!fixup_count_distinct_pointers && storage->isEmptyEntry(local_entry_idx)) {
133  return {};
134  }
135 
136  const auto buff = storage->buff_;
137  CHECK(buff);
138  std::vector<TargetValue> row;
139  size_t agg_col_idx = 0;
140  int8_t* rowwise_target_ptr{nullptr};
141  int8_t* keys_ptr{nullptr};
142  const int8_t* crt_col_ptr{nullptr};
143  if (query_mem_desc_.didOutputColumnar()) {
144  keys_ptr = buff;
145  crt_col_ptr = get_cols_ptr(buff, storage->query_mem_desc_);
146  } else {
147  keys_ptr = row_ptr_rowwise(buff, query_mem_desc_, local_entry_idx);
148  const auto key_bytes_with_padding =
149  align_to_int64(get_key_bytes_rowwise(query_mem_desc_));
150  rowwise_target_ptr = keys_ptr + key_bytes_with_padding;
151  }
152  for (size_t target_idx = 0; target_idx < storage->targets_.size(); ++target_idx) {
153  const auto& agg_info = storage->targets_[target_idx];
154  if (query_mem_desc_.didOutputColumnar()) {
155  if (UNLIKELY(!targets_to_skip.empty())) {
156  row.push_back(!targets_to_skip[target_idx]
157  ? getTargetValueFromBufferColwise(crt_col_ptr,
158  keys_ptr,
159  storage->query_mem_desc_,
160  local_entry_idx,
161  global_entry_idx,
162  agg_info,
163  target_idx,
164  agg_col_idx,
165  translate_strings,
167  : nullptr);
168  } else {
169  row.push_back(getTargetValueFromBufferColwise(crt_col_ptr,
170  keys_ptr,
171  storage->query_mem_desc_,
172  local_entry_idx,
173  global_entry_idx,
174  agg_info,
175  target_idx,
176  agg_col_idx,
177  translate_strings,
179  }
180  crt_col_ptr = advance_target_ptr_col_wise(crt_col_ptr,
181  agg_info,
182  agg_col_idx,
183  storage->query_mem_desc_,
184  separate_varlen_storage_valid_);
185  } else {
186  if (UNLIKELY(!targets_to_skip.empty())) {
187  row.push_back(!targets_to_skip[target_idx]
188  ? getTargetValueFromBufferRowwise(rowwise_target_ptr,
189  keys_ptr,
190  global_entry_idx,
191  agg_info,
192  target_idx,
193  agg_col_idx,
194  translate_strings,
196  fixup_count_distinct_pointers)
197  : nullptr);
198  } else {
199  row.push_back(getTargetValueFromBufferRowwise(rowwise_target_ptr,
200  keys_ptr,
201  global_entry_idx,
202  agg_info,
203  target_idx,
204  agg_col_idx,
205  translate_strings,
207  fixup_count_distinct_pointers));
208  }
209  rowwise_target_ptr = advance_target_ptr_row_wise(rowwise_target_ptr,
210  agg_info,
211  agg_col_idx,
212  query_mem_desc_,
213  separate_varlen_storage_valid_);
214  }
215  agg_col_idx = advance_slot(agg_col_idx, agg_info, separate_varlen_storage_valid_);
216  }
217 
218  return row;
219 }
220 
221 TargetValue ResultSet::getRowAt(const size_t row_idx,
222  const size_t col_idx,
223  const bool translate_strings,
224  const bool decimal_to_double /* = true */) const {
225  std::lock_guard<std::mutex> lock(row_iteration_mutex_);
226  moveToBegin();
227  for (size_t i = 0; i < row_idx; ++i) {
228  auto crt_row = getNextRowUnlocked(translate_strings, decimal_to_double);
229  CHECK(!crt_row.empty());
230  }
231  auto crt_row = getNextRowUnlocked(translate_strings, decimal_to_double);
232  CHECK(!crt_row.empty());
233  return crt_row[col_idx];
234 }
235 
236 OneIntegerColumnRow ResultSet::getOneColRow(const size_t global_entry_idx) const {
237  const auto storage_lookup_result = findStorage(global_entry_idx);
238  const auto storage = storage_lookup_result.storage_ptr;
239  const auto local_entry_idx = storage_lookup_result.fixedup_entry_idx;
240  if (storage->isEmptyEntry(local_entry_idx)) {
241  return {0, false};
242  }
243  const auto buff = storage->buff_;
244  CHECK(buff);
245  CHECK(!query_mem_desc_.didOutputColumnar());
246  const auto keys_ptr = row_ptr_rowwise(buff, query_mem_desc_, local_entry_idx);
247  const auto key_bytes_with_padding =
248  align_to_int64(get_key_bytes_rowwise(query_mem_desc_));
249  const auto rowwise_target_ptr = keys_ptr + key_bytes_with_padding;
250  const auto tv = getTargetValueFromBufferRowwise(rowwise_target_ptr,
251  keys_ptr,
252  global_entry_idx,
253  targets_.front(),
254  0,
255  0,
256  false,
257  false,
258  false);
259  const auto scalar_tv = boost::get<ScalarTargetValue>(&tv);
260  CHECK(scalar_tv);
261  const auto ival_ptr = boost::get<int64_t>(scalar_tv);
262  CHECK(ival_ptr);
263  return {*ival_ptr, true};
264 }
265 
266 std::vector<TargetValue> ResultSet::getRowAt(const size_t logical_index) const {
267  if (logical_index >= entryCount()) {
268  return {};
269  }
270  const auto entry_idx =
271  permutation_.empty() ? logical_index : permutation_[logical_index];
272  return getRowAt(entry_idx, true, false, false);
273 }
274 
275 std::vector<TargetValue> ResultSet::getRowAtNoTranslations(
276  const size_t logical_index,
277  const std::vector<bool>& targets_to_skip /* = {}*/) const {
278  if (logical_index >= entryCount()) {
279  return {};
280  }
281  const auto entry_idx =
282  permutation_.empty() ? logical_index : permutation_[logical_index];
283  return getRowAt(entry_idx, false, false, false, targets_to_skip);
284 }
285 
286 bool ResultSet::isRowAtEmpty(const size_t logical_index) const {
287  if (logical_index >= entryCount()) {
288  return true;
289  }
290  const auto entry_idx =
291  permutation_.empty() ? logical_index : permutation_[logical_index];
292  const auto storage_lookup_result = findStorage(entry_idx);
293  const auto storage = storage_lookup_result.storage_ptr;
294  const auto local_entry_idx = storage_lookup_result.fixedup_entry_idx;
295  return storage->isEmptyEntry(local_entry_idx);
296 }
297 
298 std::vector<TargetValue> ResultSet::getNextRow(const bool translate_strings,
299  const bool decimal_to_double) const {
300  std::lock_guard<std::mutex> lock(row_iteration_mutex_);
301  if (!storage_ && !just_explain_) {
302  return {};
303  }
304  return getNextRowUnlocked(translate_strings, decimal_to_double);
305 }
306 
307 std::vector<TargetValue> ResultSet::getNextRowUnlocked(
308  const bool translate_strings,
309  const bool decimal_to_double) const {
310  if (just_explain_) {
311  if (fetched_so_far_) {
312  return {};
313  }
314  fetched_so_far_ = 1;
315  return {explanation_};
316  }
317  return getNextRowImpl(translate_strings, decimal_to_double);
318 }
319 
320 std::vector<TargetValue> ResultSet::getNextRowImpl(const bool translate_strings,
321  const bool decimal_to_double) const {
322  size_t entry_buff_idx = 0;
323  do {
324  if (keep_first_ && fetched_so_far_ >= drop_first_ + keep_first_) {
325  return {};
326  }
327 
328  entry_buff_idx = advanceCursorToNextEntry();
329 
330  if (crt_row_buff_idx_ >= entryCount()) {
331  CHECK_EQ(entryCount(), crt_row_buff_idx_);
332  return {};
333  }
334  ++crt_row_buff_idx_;
335  ++fetched_so_far_;
336 
337  } while (drop_first_ && fetched_so_far_ <= drop_first_);
338 
339  auto row = getRowAt(entry_buff_idx, translate_strings, decimal_to_double, false);
340  CHECK(!row.empty());
341 
342  return row;
343 }
344 
345 namespace {
346 
347 const int8_t* columnar_elem_ptr(const size_t entry_idx,
348  const int8_t* col1_ptr,
349  const int8_t compact_sz1) {
350  return col1_ptr + compact_sz1 * entry_idx;
351 }
352 
353 int64_t int_resize_cast(const int64_t ival, const size_t sz) {
354  switch (sz) {
355  case 8:
356  return ival;
357  case 4:
358  return static_cast<int32_t>(ival);
359  case 2:
360  return static_cast<int16_t>(ival);
361  case 1:
362  return static_cast<int8_t>(ival);
363  default:
364  UNREACHABLE();
365  }
366  UNREACHABLE();
367  return 0;
368 }
369 
370 } // namespace
371 
373  // Compute offsets for base storage and all appended storage
374  for (size_t storage_idx = 0; storage_idx < result_set_->appended_storage_.size() + 1;
375  ++storage_idx) {
376  offsets_for_storage_.emplace_back();
377 
378  const int8_t* rowwise_target_ptr{0};
379 
380  size_t agg_col_idx = 0;
381  for (size_t target_idx = 0; target_idx < result_set_->storage_->targets_.size();
382  ++target_idx) {
383  const auto& agg_info = result_set_->storage_->targets_[target_idx];
384 
385  auto ptr1 = rowwise_target_ptr;
386  const auto compact_sz1 =
387  result_set_->query_mem_desc_.getPaddedSlotWidthBytes(agg_col_idx)
388  ? result_set_->query_mem_desc_.getPaddedSlotWidthBytes(agg_col_idx)
389  : key_width_;
390 
391  const int8_t* ptr2{nullptr};
392  int8_t compact_sz2{0};
393  if ((agg_info.is_agg && agg_info.agg_kind == kAVG)) {
394  ptr2 = ptr1 + compact_sz1;
395  compact_sz2 =
396  result_set_->query_mem_desc_.getPaddedSlotWidthBytes(agg_col_idx + 1);
397  } else if (is_real_str_or_array(agg_info)) {
398  ptr2 = ptr1 + compact_sz1;
399  if (!result_set_->separate_varlen_storage_valid_) {
400  // None encoded strings explicitly attached to ResultSetStorage do not have a
401  // second slot in the QueryMemoryDescriptor col width vector
402  compact_sz2 =
403  result_set_->query_mem_desc_.getPaddedSlotWidthBytes(agg_col_idx + 1);
404  }
405  }
406  offsets_for_storage_[storage_idx].push_back(
407  TargetOffsets{ptr1,
408  static_cast<size_t>(compact_sz1),
409  ptr2,
410  static_cast<size_t>(compact_sz2)});
411  rowwise_target_ptr =
412  advance_target_ptr_row_wise(rowwise_target_ptr,
413  agg_info,
414  agg_col_idx,
415  result_set_->query_mem_desc_,
416  result_set_->separate_varlen_storage_valid_);
417 
418  agg_col_idx = advance_slot(
419  agg_col_idx, agg_info, result_set_->separate_varlen_storage_valid_);
420  }
421  CHECK_EQ(offsets_for_storage_[storage_idx].size(),
422  result_set_->storage_->targets_.size());
423  }
424 }
425 
427  const int8_t* buff,
428  const size_t entry_idx,
429  const size_t target_logical_idx,
430  const StorageLookupResult& storage_lookup_result) const {
431  CHECK(buff);
432  const int8_t* rowwise_target_ptr{nullptr};
433  const int8_t* keys_ptr{nullptr};
434 
435  const size_t storage_idx = storage_lookup_result.storage_idx;
436 
437  CHECK_LT(storage_idx, offsets_for_storage_.size());
438  CHECK_LT(target_logical_idx, offsets_for_storage_[storage_idx].size());
439 
440  const auto& offsets_for_target = offsets_for_storage_[storage_idx][target_logical_idx];
441  const auto& agg_info = result_set_->storage_->targets_[target_logical_idx];
442  const auto& type_info = agg_info.sql_type;
443 
444  keys_ptr = get_rowwise_ptr(buff, entry_idx);
445  rowwise_target_ptr = keys_ptr + key_bytes_with_padding_;
446  auto ptr1 = rowwise_target_ptr + reinterpret_cast<size_t>(offsets_for_target.ptr1);
447  if (result_set_->query_mem_desc_.targetGroupbyIndicesSize() > 0) {
448  if (result_set_->query_mem_desc_.getTargetGroupbyIndex(target_logical_idx) >= 0) {
449  ptr1 = keys_ptr +
450  result_set_->query_mem_desc_.getTargetGroupbyIndex(target_logical_idx) *
451  key_width_;
452  }
453  }
454  const auto i1 =
455  result_set_->lazyReadInt(read_int_from_buff(ptr1, offsets_for_target.compact_sz1),
456  target_logical_idx,
457  storage_lookup_result);
458  if (agg_info.is_agg && agg_info.agg_kind == kAVG) {
459  CHECK(offsets_for_target.ptr2);
460  const auto ptr2 =
461  rowwise_target_ptr + reinterpret_cast<size_t>(offsets_for_target.ptr2);
462  const auto i2 = read_int_from_buff(ptr2, offsets_for_target.compact_sz2);
463  return InternalTargetValue(i1, i2);
464  } else {
465  if (type_info.is_string() && type_info.get_compression() == kENCODING_NONE) {
466  CHECK(!agg_info.is_agg);
467  if (!result_set_->lazy_fetch_info_.empty()) {
468  CHECK_LT(target_logical_idx, result_set_->lazy_fetch_info_.size());
469  const auto& col_lazy_fetch = result_set_->lazy_fetch_info_[target_logical_idx];
470  if (col_lazy_fetch.is_lazily_fetched) {
471  return InternalTargetValue(reinterpret_cast<const std::string*>(i1));
472  }
473  }
474  if (result_set_->separate_varlen_storage_valid_) {
475  if (i1 < 0) {
476  CHECK_EQ(-1, i1);
477  return InternalTargetValue(static_cast<const std::string*>(nullptr));
478  }
479  CHECK_LT(storage_lookup_result.storage_idx,
480  result_set_->serialized_varlen_buffer_.size());
481  const auto& varlen_buffer_for_fragment =
482  result_set_->serialized_varlen_buffer_[storage_lookup_result.storage_idx];
483  CHECK_LT(static_cast<size_t>(i1), varlen_buffer_for_fragment.size());
484  return InternalTargetValue(&varlen_buffer_for_fragment[i1]);
485  }
486  CHECK(offsets_for_target.ptr2);
487  const auto ptr2 =
488  rowwise_target_ptr + reinterpret_cast<size_t>(offsets_for_target.ptr2);
489  const auto str_len = read_int_from_buff(ptr2, offsets_for_target.compact_sz2);
490  CHECK_GE(str_len, 0);
491  return result_set_->getVarlenOrderEntry(i1, str_len);
492  }
493  return InternalTargetValue(
494  type_info.is_fp() ? i1 : int_resize_cast(i1, type_info.get_logical_size()));
495  }
496 }
497 
499  // Compute offsets for base storage and all appended storage
500  const auto key_width = result_set_->query_mem_desc_.getEffectiveKeyWidth();
501  for (size_t storage_idx = 0; storage_idx < result_set_->appended_storage_.size() + 1;
502  ++storage_idx) {
503  offsets_for_storage_.emplace_back();
504 
505  const int8_t* buff = storage_idx == 0
506  ? result_set_->storage_->buff_
507  : result_set_->appended_storage_[storage_idx - 1]->buff_;
508  CHECK(buff);
509 
510  const auto& crt_query_mem_desc =
511  storage_idx == 0
512  ? result_set_->storage_->query_mem_desc_
513  : result_set_->appended_storage_[storage_idx - 1]->query_mem_desc_;
514  const int8_t* crt_col_ptr = get_cols_ptr(buff, crt_query_mem_desc);
515 
516  size_t agg_col_idx = 0;
517  for (size_t target_idx = 0; target_idx < result_set_->storage_->targets_.size();
518  ++target_idx) {
519  const auto& agg_info = result_set_->storage_->targets_[target_idx];
520 
521  const auto compact_sz1 =
522  crt_query_mem_desc.getPaddedSlotWidthBytes(agg_col_idx)
523  ? crt_query_mem_desc.getPaddedSlotWidthBytes(agg_col_idx)
524  : key_width;
525 
526  const auto next_col_ptr = advance_to_next_columnar_target_buff(
527  crt_col_ptr, crt_query_mem_desc, agg_col_idx);
528  const bool uses_two_slots = (agg_info.is_agg && agg_info.agg_kind == kAVG) ||
529  is_real_str_or_array(agg_info);
530  const auto col2_ptr = uses_two_slots ? next_col_ptr : nullptr;
531  const auto compact_sz2 =
532  (agg_info.is_agg && agg_info.agg_kind == kAVG) || is_real_str_or_array(agg_info)
533  ? crt_query_mem_desc.getPaddedSlotWidthBytes(agg_col_idx + 1)
534  : 0;
535 
536  offsets_for_storage_[storage_idx].push_back(
537  TargetOffsets{crt_col_ptr,
538  static_cast<size_t>(compact_sz1),
539  col2_ptr,
540  static_cast<size_t>(compact_sz2)});
541 
542  crt_col_ptr = next_col_ptr;
543  if (uses_two_slots) {
545  crt_col_ptr, crt_query_mem_desc, agg_col_idx + 1);
546  }
547  agg_col_idx = advance_slot(
548  agg_col_idx, agg_info, result_set_->separate_varlen_storage_valid_);
549  }
550  CHECK_EQ(offsets_for_storage_[storage_idx].size(),
551  result_set_->storage_->targets_.size());
552  }
553 }
554 
556  const int8_t* buff,
557  const size_t entry_idx,
558  const size_t target_logical_idx,
559  const StorageLookupResult& storage_lookup_result) const {
560  const size_t storage_idx = storage_lookup_result.storage_idx;
561 
562  CHECK_LT(storage_idx, offsets_for_storage_.size());
563  CHECK_LT(target_logical_idx, offsets_for_storage_[storage_idx].size());
564 
565  const auto& offsets_for_target = offsets_for_storage_[storage_idx][target_logical_idx];
566  const auto& agg_info = result_set_->storage_->targets_[target_logical_idx];
567  const auto& type_info = agg_info.sql_type;
568  auto ptr1 = offsets_for_target.ptr1;
569  if (result_set_->query_mem_desc_.targetGroupbyIndicesSize() > 0) {
570  if (result_set_->query_mem_desc_.getTargetGroupbyIndex(target_logical_idx) >= 0) {
571  ptr1 =
572  buff + result_set_->query_mem_desc_.getTargetGroupbyIndex(target_logical_idx) *
573  result_set_->query_mem_desc_.getEffectiveKeyWidth() *
574  result_set_->query_mem_desc_.entry_count_;
575  }
576  }
577 
578  const auto i1 = result_set_->lazyReadInt(
580  columnar_elem_ptr(entry_idx, ptr1, offsets_for_target.compact_sz1),
581  offsets_for_target.compact_sz1),
582  target_logical_idx,
583  storage_lookup_result);
584  if (agg_info.is_agg && agg_info.agg_kind == kAVG) {
585  CHECK(offsets_for_target.ptr2);
586  const auto i2 = read_int_from_buff(
588  entry_idx, offsets_for_target.ptr2, offsets_for_target.compact_sz2),
589  offsets_for_target.compact_sz2);
590  return InternalTargetValue(i1, i2);
591  } else {
592  // for TEXT ENCODING NONE:
593  if (type_info.is_string() && type_info.get_compression() == kENCODING_NONE) {
594  CHECK(!agg_info.is_agg);
595  if (!result_set_->lazy_fetch_info_.empty()) {
596  CHECK_LT(target_logical_idx, result_set_->lazy_fetch_info_.size());
597  const auto& col_lazy_fetch = result_set_->lazy_fetch_info_[target_logical_idx];
598  if (col_lazy_fetch.is_lazily_fetched) {
599  return InternalTargetValue(reinterpret_cast<const std::string*>(i1));
600  }
601  }
602  if (result_set_->separate_varlen_storage_valid_) {
603  if (i1 < 0) {
604  CHECK_EQ(-1, i1);
605  return InternalTargetValue(static_cast<const std::string*>(nullptr));
606  }
607  CHECK_LT(storage_lookup_result.storage_idx,
608  result_set_->serialized_varlen_buffer_.size());
609  const auto& varlen_buffer_for_fragment =
610  result_set_->serialized_varlen_buffer_[storage_lookup_result.storage_idx];
611  CHECK_LT(static_cast<size_t>(i1), varlen_buffer_for_fragment.size());
612  return InternalTargetValue(&varlen_buffer_for_fragment[i1]);
613  }
614  CHECK(offsets_for_target.ptr2);
615  const auto i2 = read_int_from_buff(
617  entry_idx, offsets_for_target.ptr2, offsets_for_target.compact_sz2),
618  offsets_for_target.compact_sz2);
619  CHECK_GE(i2, 0);
620  return result_set_->getVarlenOrderEntry(i1, i2);
621  }
622  return InternalTargetValue(
623  type_info.is_fp() ? i1 : int_resize_cast(i1, type_info.get_logical_size()));
624  }
625 }
626 
628  const size_t str_len) const {
629  char* host_str_ptr{nullptr};
630  std::vector<int8_t> cpu_buffer;
632  cpu_buffer.resize(str_len);
633  const auto executor = query_mem_desc_.getExecutor();
634  CHECK(executor);
635  auto& data_mgr = executor->catalog_->getDataMgr();
636  copy_from_gpu(&data_mgr,
637  &cpu_buffer[0],
638  static_cast<CUdeviceptr>(str_ptr),
639  str_len,
640  device_id_);
641  host_str_ptr = reinterpret_cast<char*>(&cpu_buffer[0]);
642  } else {
644  host_str_ptr = reinterpret_cast<char*>(str_ptr);
645  }
646  std::string str(host_str_ptr, str_len);
647  return InternalTargetValue(row_set_mem_owner_->addString(str));
648 }
649 
650 int64_t ResultSet::lazyReadInt(const int64_t ival,
651  const size_t target_logical_idx,
652  const StorageLookupResult& storage_lookup_result) const {
653  if (!lazy_fetch_info_.empty()) {
654  CHECK_LT(target_logical_idx, lazy_fetch_info_.size());
655  const auto& col_lazy_fetch = lazy_fetch_info_[target_logical_idx];
656  if (col_lazy_fetch.is_lazily_fetched) {
657  CHECK_LT(static_cast<size_t>(storage_lookup_result.storage_idx),
658  col_buffers_.size());
659  int64_t ival_copy = ival;
660  auto& frag_col_buffers =
661  getColumnFrag(static_cast<size_t>(storage_lookup_result.storage_idx),
662  target_logical_idx,
663  ival_copy);
664  auto& frag_col_buffer = frag_col_buffers[col_lazy_fetch.local_col_id];
665  CHECK_LT(target_logical_idx, targets_.size());
666  const TargetInfo& target_info = targets_[target_logical_idx];
667  CHECK(!target_info.is_agg);
668  if (target_info.sql_type.is_string() &&
669  target_info.sql_type.get_compression() == kENCODING_NONE) {
670  VarlenDatum vd;
671  bool is_end{false};
673  reinterpret_cast<ChunkIter*>(const_cast<int8_t*>(frag_col_buffer)),
674  storage_lookup_result.fixedup_entry_idx,
675  false,
676  &vd,
677  &is_end);
678  CHECK(!is_end);
679  if (vd.is_null) {
680  return 0;
681  }
682  std::string fetched_str(reinterpret_cast<char*>(vd.pointer), vd.length);
683  return reinterpret_cast<int64_t>(row_set_mem_owner_->addString(fetched_str));
684  }
685  return result_set::lazy_decode(col_lazy_fetch, frag_col_buffer, ival_copy);
686  }
687  }
688  return ival;
689 }
690 
691 // Not all entries in the buffer represent a valid row. Advance the internal cursor
692 // used for the getNextRow method to the next row which is valid.
695  iter.global_entry_idx_valid_ = false;
696  return;
697  }
698 
699  while (iter.crt_row_buff_idx_ < entryCount()) {
700  const auto entry_idx = permutation_.empty() ? iter.crt_row_buff_idx_
702  const auto storage_lookup_result = findStorage(entry_idx);
703  const auto storage = storage_lookup_result.storage_ptr;
704  const auto fixedup_entry_idx = storage_lookup_result.fixedup_entry_idx;
705  if (!storage->isEmptyEntry(fixedup_entry_idx)) {
706  if (iter.fetched_so_far_ < drop_first_) {
707  ++iter.fetched_so_far_;
708  } else {
709  break;
710  }
711  }
712  ++iter.crt_row_buff_idx_;
713  }
714  if (permutation_.empty()) {
716  } else {
718  iter.global_entry_idx_ = iter.crt_row_buff_idx_ == permutation_.size()
719  ? iter.crt_row_buff_idx_
721  }
722 
724 
725  if (iter.global_entry_idx_valid_) {
726  ++iter.crt_row_buff_idx_;
727  ++iter.fetched_so_far_;
728  }
729 }
730 
731 // Not all entries in the buffer represent a valid row. Advance the internal cursor
732 // used for the getNextRow method to the next row which is valid.
734  while (crt_row_buff_idx_ < entryCount()) {
735  const auto entry_idx =
737  const auto storage_lookup_result = findStorage(entry_idx);
738  const auto storage = storage_lookup_result.storage_ptr;
739  const auto fixedup_entry_idx = storage_lookup_result.fixedup_entry_idx;
740  if (!storage->isEmptyEntry(fixedup_entry_idx)) {
741  break;
742  }
744  }
745  if (permutation_.empty()) {
746  return crt_row_buff_idx_;
747  }
751 }
752 
753 size_t ResultSet::entryCount() const {
754  return permutation_.empty() ? query_mem_desc_.getEntryCount() : permutation_.size();
755 }
756 
757 size_t ResultSet::getBufferSizeBytes(const ExecutorDeviceType device_type) const {
758  CHECK(storage_);
759  return storage_->query_mem_desc_.getBufferSizeBytes(device_type);
760 }
761 
762 namespace {
763 
764 template <class T>
766  return ScalarTargetValue(static_cast<int64_t>(val));
767 }
768 
769 template <>
771  return ScalarTargetValue(val);
772 }
773 
774 template <>
776  return ScalarTargetValue(val);
777 }
778 
779 template <class T>
781  const int8_t* buff,
782  const size_t buff_sz,
783  std::shared_ptr<RowSetMemoryOwner> row_set_mem_owner) {
784  std::vector<ScalarTargetValue> values;
785  auto buff_elems = reinterpret_cast<const T*>(buff);
786  CHECK_EQ(size_t(0), buff_sz % sizeof(T));
787  const size_t num_elems = buff_sz / sizeof(T);
788  for (size_t i = 0; i < num_elems; ++i) {
789  values.push_back(make_scalar_tv<T>(buff_elems[i]));
790  }
791  return ArrayTargetValue(values);
792 }
793 
795  const int32_t* buff,
796  const size_t buff_sz,
797  const int dict_id,
798  const bool translate_strings,
799  std::shared_ptr<RowSetMemoryOwner> row_set_mem_owner,
800  const Catalog_Namespace::Catalog* catalog) {
801  std::vector<ScalarTargetValue> values;
802  CHECK_EQ(size_t(0), buff_sz % sizeof(int32_t));
803  const size_t num_elems = buff_sz / sizeof(int32_t);
804  if (translate_strings) {
805  for (size_t i = 0; i < num_elems; ++i) {
806  const auto string_id = buff[i];
807 
808  if (string_id == NULL_INT) {
809  values.emplace_back(NullableString(nullptr));
810  } else {
811  if (dict_id == 0) {
812  StringDictionaryProxy* sdp = row_set_mem_owner->getLiteralStringDictProxy();
813  values.emplace_back(sdp->getString(string_id));
814  } else {
815  values.emplace_back(NullableString(
816  row_set_mem_owner
817  ->getOrAddStringDictProxy(dict_id, /*with_generation=*/false, catalog)
818  ->getString(string_id)));
819  }
820  }
821  }
822  } else {
823  for (size_t i = 0; i < num_elems; i++) {
824  values.emplace_back(static_cast<int64_t>(buff[i]));
825  }
826  }
827  return ArrayTargetValue(values);
828 }
829 
831  const int8_t* buff,
832  const size_t buff_sz,
833  const bool translate_strings,
834  std::shared_ptr<RowSetMemoryOwner> row_set_mem_owner,
835  const Catalog_Namespace::Catalog* catalog) {
836  CHECK(array_ti.is_array());
837  const auto& elem_ti = array_ti.get_elem_type();
838  if (elem_ti.is_string()) {
839  return build_string_array_target_value(reinterpret_cast<const int32_t*>(buff),
840  buff_sz,
841  elem_ti.get_comp_param(),
842  translate_strings,
843  row_set_mem_owner,
844  catalog);
845  }
846  switch (elem_ti.get_size()) {
847  case 1:
848  return build_array_target_value<int8_t>(buff, buff_sz, row_set_mem_owner);
849  case 2:
850  return build_array_target_value<int16_t>(buff, buff_sz, row_set_mem_owner);
851  case 4:
852  if (elem_ti.is_fp()) {
853  return build_array_target_value<float>(buff, buff_sz, row_set_mem_owner);
854  } else {
855  return build_array_target_value<int32_t>(buff, buff_sz, row_set_mem_owner);
856  }
857  case 8:
858  if (elem_ti.is_fp()) {
859  return build_array_target_value<double>(buff, buff_sz, row_set_mem_owner);
860  } else {
861  return build_array_target_value<int64_t>(buff, buff_sz, row_set_mem_owner);
862  }
863  default:
864  CHECK(false);
865  }
866  CHECK(false);
867  return TargetValue(nullptr);
868 }
869 
870 template <class Tuple, size_t... indices>
871 inline std::vector<std::pair<const int8_t*, const int64_t>> make_vals_vector(
872  std::index_sequence<indices...>,
873  const Tuple& tuple) {
874  return std::vector<std::pair<const int8_t*, const int64_t>>{
875  std::make_pair(std::get<2 * indices>(tuple), std::get<2 * indices + 1>(tuple))...};
876 }
877 
878 inline std::unique_ptr<ArrayDatum> lazy_fetch_chunk(const int8_t* ptr,
879  const int64_t varlen_ptr) {
880  auto ad = std::make_unique<ArrayDatum>();
881  bool is_end;
882  ChunkIter_get_nth(reinterpret_cast<ChunkIter*>(const_cast<int8_t*>(ptr)),
883  varlen_ptr,
884  ad.get(),
885  &is_end);
886  CHECK(!is_end);
887  return ad;
888 }
889 
891  template <typename... T>
892  static inline auto fetch(const SQLTypeInfo& geo_ti,
893  const ResultSet::GeoReturnType return_type,
894  T&&... vals) {
895  constexpr int num_vals = sizeof...(vals);
896  static_assert(
897  num_vals % 2 == 0,
898  "Must have consistent pointer/size pairs for lazy fetch of geo target values.");
899  const auto vals_vector = make_vals_vector(std::make_index_sequence<num_vals / 2>{},
900  std::make_tuple(vals...));
901  std::array<VarlenDatumPtr, num_vals / 2> ad_arr;
902  size_t ctr = 0;
903  for (const auto& col_pair : vals_vector) {
904  ad_arr[ctr] = lazy_fetch_chunk(col_pair.first, col_pair.second);
905  // Regular chunk iterator used to fetch this datum sets the right nullness.
906  // That includes the fixlen bounds array.
907  // However it may incorrectly set it for the POINT coord array datum
908  // if 1st byte happened to hold NULL_ARRAY_TINYINT. One should either use
909  // the specialized iterator for POINT coords or rely on regular iterator +
910  // reset + recheck, which is what is done below.
911  auto is_point = (geo_ti.get_type() == kPOINT && ctr == 0);
912  if (is_point) {
913  // Resetting POINT coords array nullness here
914  ad_arr[ctr]->is_null = false;
915  }
916  if (!geo_ti.get_notnull()) {
917  // Recheck and set nullness
918  if (ad_arr[ctr]->length == 0 || ad_arr[ctr]->pointer == NULL ||
919  (is_point &&
920  is_null_point(geo_ti, ad_arr[ctr]->pointer, ad_arr[ctr]->length))) {
921  ad_arr[ctr]->is_null = true;
922  }
923  }
924  ctr++;
925  }
926  return ad_arr;
927  }
928 };
929 
930 inline std::unique_ptr<ArrayDatum> fetch_data_from_gpu(int64_t varlen_ptr,
931  const int64_t length,
932  Data_Namespace::DataMgr* data_mgr,
933  const int device_id) {
934  auto cpu_buf = std::shared_ptr<int8_t>(new int8_t[length], FreeDeleter());
936  data_mgr, cpu_buf.get(), static_cast<CUdeviceptr>(varlen_ptr), length, device_id);
937  // Just fetching the data from gpu, not checking geo nullness
938  return std::make_unique<ArrayDatum>(length, cpu_buf, false);
939 }
940 
942  static inline auto yieldGpuPtrFetcher() {
943  return [](const int64_t ptr, const int64_t length) -> VarlenDatumPtr {
944  // Just fetching the data from gpu, not checking geo nullness
945  return std::make_unique<VarlenDatum>(length, reinterpret_cast<int8_t*>(ptr), false);
946  };
947  }
948 
949  static inline auto yieldGpuDatumFetcher(Data_Namespace::DataMgr* data_mgr_ptr,
950  const int device_id) {
951  return [data_mgr_ptr, device_id](const int64_t ptr,
952  const int64_t length) -> VarlenDatumPtr {
953  return fetch_data_from_gpu(ptr, length, data_mgr_ptr, device_id);
954  };
955  }
956 
957  static inline auto yieldCpuDatumFetcher() {
958  return [](const int64_t ptr, const int64_t length) -> VarlenDatumPtr {
959  // Just fetching the data from gpu, not checking geo nullness
960  return std::make_unique<VarlenDatum>(length, reinterpret_cast<int8_t*>(ptr), false);
961  };
962  }
963 
964  template <typename... T>
965  static inline auto fetch(const SQLTypeInfo& geo_ti,
966  const ResultSet::GeoReturnType return_type,
967  Data_Namespace::DataMgr* data_mgr,
968  const bool fetch_data_from_gpu,
969  const int device_id,
970  T&&... vals) {
971  auto ad_arr_generator = [&](auto datum_fetcher) {
972  constexpr int num_vals = sizeof...(vals);
973  static_assert(
974  num_vals % 2 == 0,
975  "Must have consistent pointer/size pairs for lazy fetch of geo target values.");
976  const auto vals_vector = std::vector<int64_t>{vals...};
977 
978  std::array<VarlenDatumPtr, num_vals / 2> ad_arr;
979  size_t ctr = 0;
980  for (size_t i = 0; i < vals_vector.size(); i += 2) {
981  ad_arr[ctr] = datum_fetcher(vals_vector[i], vals_vector[i + 1]);
982  // All fetched datums come in with is_null set to false
983  if (!geo_ti.get_notnull()) {
984  bool is_null = false;
985  // Now need to set the nullness
986  if (ad_arr[ctr]->length == 0 || ad_arr[ctr]->pointer == NULL) {
987  is_null = true;
988  } else if (geo_ti.get_type() == kPOINT && ctr == 0 &&
989  is_null_point(geo_ti, ad_arr[ctr]->pointer, ad_arr[ctr]->length)) {
990  is_null = true; // recognizes compressed and uncompressed points
991  } else if (ad_arr[ctr]->length == 4 * sizeof(double)) {
992  // Bounds
993  auto dti = SQLTypeInfo(kARRAY, 0, 0, false, kENCODING_NONE, 0, kDOUBLE);
994  is_null = dti.is_null_fixlen_array(ad_arr[ctr]->pointer, ad_arr[ctr]->length);
995  }
996  ad_arr[ctr]->is_null = is_null;
997  }
998  ctr++;
999  }
1000  return ad_arr;
1001  };
1002 
1003  if (fetch_data_from_gpu) {
1005  return ad_arr_generator(yieldGpuPtrFetcher());
1006  } else {
1007  return ad_arr_generator(yieldGpuDatumFetcher(data_mgr, device_id));
1008  }
1009  } else {
1010  return ad_arr_generator(yieldCpuDatumFetcher());
1011  }
1012  }
1013 };
1014 
1015 template <SQLTypes GEO_SOURCE_TYPE, typename GeoTargetFetcher>
1017  template <typename... T>
1018  static inline TargetValue build(const SQLTypeInfo& geo_ti,
1019  const ResultSet::GeoReturnType return_type,
1020  T&&... vals) {
1021  auto ad_arr = GeoTargetFetcher::fetch(geo_ti, return_type, std::forward<T>(vals)...);
1022  static_assert(std::tuple_size<decltype(ad_arr)>::value > 0,
1023  "ArrayDatum array for Geo Target must contain at least one value.");
1024 
1025  // Fetcher sets the geo nullness based on geo typeinfo's notnull, type and
1026  // compression. Serializers will generate appropriate NULL geo where necessary.
1027  switch (return_type) {
1029  if (!geo_ti.get_notnull() && ad_arr[0]->is_null) {
1030  return GeoTargetValue();
1031  }
1033  GEO_SOURCE_TYPE>::GeoSerializerType::serialize(geo_ti,
1034  ad_arr);
1035  }
1037  if (!geo_ti.get_notnull() && ad_arr[0]->is_null) {
1038  // Generating NULL wkt string to represent NULL geo
1039  return NullableString(nullptr);
1040  }
1042  GEO_SOURCE_TYPE>::GeoSerializerType::serialize(geo_ti,
1043  ad_arr);
1044  }
1047  if (!geo_ti.get_notnull() && ad_arr[0]->is_null) {
1048  // NULL geo
1049  // Pass along null datum, instead of an empty/null GeoTargetValuePtr
1050  // return GeoTargetValuePtr();
1051  }
1053  GEO_SOURCE_TYPE>::GeoSerializerType::serialize(geo_ti,
1054  ad_arr);
1055  }
1056  default: {
1057  UNREACHABLE();
1058  return TargetValue(nullptr);
1059  }
1060  }
1061  }
1062 };
1063 
1064 template <typename T>
1065 inline std::pair<int64_t, int64_t> get_frag_id_and_local_idx(
1066  const std::vector<std::vector<T>>& frag_offsets,
1067  const size_t tab_or_col_idx,
1068  const int64_t global_idx) {
1069  CHECK_GE(global_idx, int64_t(0));
1070  for (int64_t frag_id = frag_offsets.size() - 1; frag_id > 0; --frag_id) {
1071  CHECK_LT(tab_or_col_idx, frag_offsets[frag_id].size());
1072  const auto frag_off = static_cast<int64_t>(frag_offsets[frag_id][tab_or_col_idx]);
1073  if (frag_off < global_idx) {
1074  return {frag_id, global_idx - frag_off};
1075  }
1076  }
1077  return {-1, -1};
1078 }
1079 
1080 } // namespace
1081 
1082 const std::vector<const int8_t*>& ResultSet::getColumnFrag(const size_t storage_idx,
1083  const size_t col_logical_idx,
1084  int64_t& global_idx) const {
1085  CHECK_LT(static_cast<size_t>(storage_idx), col_buffers_.size());
1086  if (col_buffers_[storage_idx].size() > 1) {
1087  int64_t frag_id = 0;
1088  int64_t local_idx = global_idx;
1089  if (consistent_frag_sizes_[storage_idx][col_logical_idx] != -1) {
1090  frag_id = global_idx / consistent_frag_sizes_[storage_idx][col_logical_idx];
1091  local_idx = global_idx % consistent_frag_sizes_[storage_idx][col_logical_idx];
1092  } else {
1093  std::tie(frag_id, local_idx) = get_frag_id_and_local_idx(
1094  frag_offsets_[storage_idx], col_logical_idx, global_idx);
1095  CHECK_LE(local_idx, global_idx);
1096  }
1097  CHECK_GE(frag_id, int64_t(0));
1098  CHECK_LT(static_cast<size_t>(frag_id), col_buffers_[storage_idx].size());
1099  global_idx = local_idx;
1100  return col_buffers_[storage_idx][frag_id];
1101  } else {
1102  CHECK_EQ(size_t(1), col_buffers_[storage_idx].size());
1103  return col_buffers_[storage_idx][0];
1104  }
1105 }
1106 
1111 void ResultSet::copyColumnIntoBuffer(const size_t column_idx,
1112  int8_t* output_buffer,
1113  const size_t output_buffer_size) const {
1115  CHECK_LT(column_idx, query_mem_desc_.getSlotCount());
1116  CHECK(output_buffer_size > 0);
1117  CHECK(output_buffer);
1118  const auto column_width_size = query_mem_desc_.getPaddedSlotWidthBytes(column_idx);
1119  size_t out_buff_offset = 0;
1120 
1121  // the main storage:
1122  const size_t crt_storage_row_count = storage_->query_mem_desc_.getEntryCount();
1123  const size_t crt_buffer_size = crt_storage_row_count * column_width_size;
1124  const size_t column_offset = storage_->query_mem_desc_.getColOffInBytes(column_idx);
1125  const int8_t* storage_buffer = storage_->getUnderlyingBuffer() + column_offset;
1126  CHECK(crt_buffer_size <= output_buffer_size);
1127  std::memcpy(output_buffer, storage_buffer, crt_buffer_size);
1128 
1129  out_buff_offset += crt_buffer_size;
1130 
1131  // the appended storages:
1132  for (size_t i = 0; i < appended_storage_.size(); i++) {
1133  const size_t crt_storage_row_count =
1134  appended_storage_[i]->query_mem_desc_.getEntryCount();
1135  if (crt_storage_row_count == 0) {
1136  // skip an empty appended storage
1137  continue;
1138  }
1139  CHECK_LT(out_buff_offset, output_buffer_size);
1140  const size_t crt_buffer_size = crt_storage_row_count * column_width_size;
1141  const size_t column_offset =
1142  appended_storage_[i]->query_mem_desc_.getColOffInBytes(column_idx);
1143  const int8_t* storage_buffer =
1144  appended_storage_[i]->getUnderlyingBuffer() + column_offset;
1145  CHECK(out_buff_offset + crt_buffer_size <= output_buffer_size);
1146  std::memcpy(output_buffer + out_buff_offset, storage_buffer, crt_buffer_size);
1147 
1148  out_buff_offset += crt_buffer_size;
1149  }
1150 }
1151 
1152 template <typename ENTRY_TYPE, QueryDescriptionType QUERY_TYPE, bool COLUMNAR_FORMAT>
1153 ENTRY_TYPE ResultSet::getEntryAt(const size_t row_idx,
1154  const size_t target_idx,
1155  const size_t slot_idx) const {
1156  if constexpr (QUERY_TYPE == QueryDescriptionType::GroupByPerfectHash) { // NOLINT
1157  if constexpr (COLUMNAR_FORMAT) { // NOLINT
1158  return getColumnarPerfectHashEntryAt<ENTRY_TYPE>(row_idx, target_idx, slot_idx);
1159  } else {
1160  return getRowWisePerfectHashEntryAt<ENTRY_TYPE>(row_idx, target_idx, slot_idx);
1161  }
1162  } else if constexpr (QUERY_TYPE == QueryDescriptionType::GroupByBaselineHash) {
1163  if constexpr (COLUMNAR_FORMAT) { // NOLINT
1164  return getColumnarBaselineEntryAt<ENTRY_TYPE>(row_idx, target_idx, slot_idx);
1165  } else {
1166  return getRowWiseBaselineEntryAt<ENTRY_TYPE>(row_idx, target_idx, slot_idx);
1167  }
1168  } else {
1169  UNREACHABLE() << "Invalid query type is used";
1170  return 0;
1171  }
1172 }
1173 
1174 #define DEF_GET_ENTRY_AT(query_type, columnar_output) \
1175  template DATA_T ResultSet::getEntryAt<DATA_T, query_type, columnar_output>( \
1176  const size_t row_idx, const size_t target_idx, const size_t slot_idx) const;
1177 
1178 #define DATA_T int64_t
1182 DEF_GET_ENTRY_AT(QueryDescriptionType::GroupByBaselineHash, false)
1183 #undef DATA_T
1184 
1185 #define DATA_T int32_t
1187 DEF_GET_ENTRY_AT(QueryDescriptionType::GroupByPerfectHash, false)
1188 DEF_GET_ENTRY_AT(QueryDescriptionType::GroupByBaselineHash, true)
1189 DEF_GET_ENTRY_AT(QueryDescriptionType::GroupByBaselineHash, false)
1190 #undef DATA_T
1191 
1192 #define DATA_T int16_t
1194 DEF_GET_ENTRY_AT(QueryDescriptionType::GroupByPerfectHash, false)
1195 DEF_GET_ENTRY_AT(QueryDescriptionType::GroupByBaselineHash, true)
1196 DEF_GET_ENTRY_AT(QueryDescriptionType::GroupByBaselineHash, false)
1197 #undef DATA_T
1198 
1199 #define DATA_T int8_t
1201 DEF_GET_ENTRY_AT(QueryDescriptionType::GroupByPerfectHash, false)
1202 DEF_GET_ENTRY_AT(QueryDescriptionType::GroupByBaselineHash, true)
1203 DEF_GET_ENTRY_AT(QueryDescriptionType::GroupByBaselineHash, false)
1204 #undef DATA_T
1205 
1206 #define DATA_T float
1208 DEF_GET_ENTRY_AT(QueryDescriptionType::GroupByPerfectHash, false)
1209 DEF_GET_ENTRY_AT(QueryDescriptionType::GroupByBaselineHash, true)
1210 DEF_GET_ENTRY_AT(QueryDescriptionType::GroupByBaselineHash, false)
1211 #undef DATA_T
1212 
1213 #define DATA_T double
1215 DEF_GET_ENTRY_AT(QueryDescriptionType::GroupByPerfectHash, false)
1216 DEF_GET_ENTRY_AT(QueryDescriptionType::GroupByBaselineHash, true)
1217 DEF_GET_ENTRY_AT(QueryDescriptionType::GroupByBaselineHash, false)
1218 #undef DATA_T
1219 
1220 #undef DEF_GET_ENTRY_AT
1221 
1228 template <typename ENTRY_TYPE>
1229 ENTRY_TYPE ResultSet::getColumnarPerfectHashEntryAt(const size_t row_idx,
1230  const size_t target_idx,
1231  const size_t slot_idx) const {
1232  const size_t column_offset = storage_->query_mem_desc_.getColOffInBytes(slot_idx);
1233  const int8_t* storage_buffer = storage_->getUnderlyingBuffer() + column_offset;
1234  return reinterpret_cast<const ENTRY_TYPE*>(storage_buffer)[row_idx];
1235 }
1236 
1243 template <typename ENTRY_TYPE>
1244 ENTRY_TYPE ResultSet::getRowWisePerfectHashEntryAt(const size_t row_idx,
1245  const size_t target_idx,
1246  const size_t slot_idx) const {
1247  const size_t row_offset = storage_->query_mem_desc_.getRowSize() * row_idx;
1248  const size_t column_offset = storage_->query_mem_desc_.getColOffInBytes(slot_idx);
1249  const int8_t* storage_buffer =
1250  storage_->getUnderlyingBuffer() + row_offset + column_offset;
1251  return *reinterpret_cast<const ENTRY_TYPE*>(storage_buffer);
1252 }
1253 
1260 template <typename ENTRY_TYPE>
1261 ENTRY_TYPE ResultSet::getRowWiseBaselineEntryAt(const size_t row_idx,
1262  const size_t target_idx,
1263  const size_t slot_idx) const {
1264  CHECK_NE(storage_->query_mem_desc_.targetGroupbyIndicesSize(), size_t(0));
1265  const auto key_width = storage_->query_mem_desc_.getEffectiveKeyWidth();
1266  auto keys_ptr = row_ptr_rowwise(
1267  storage_->getUnderlyingBuffer(), storage_->query_mem_desc_, row_idx);
1268  const auto column_offset =
1269  (storage_->query_mem_desc_.getTargetGroupbyIndex(target_idx) < 0)
1270  ? storage_->query_mem_desc_.getColOffInBytes(slot_idx)
1271  : storage_->query_mem_desc_.getTargetGroupbyIndex(target_idx) * key_width;
1272  const auto storage_buffer = keys_ptr + column_offset;
1273  return *reinterpret_cast<const ENTRY_TYPE*>(storage_buffer);
1274 }
1275 
1282 template <typename ENTRY_TYPE>
1283 ENTRY_TYPE ResultSet::getColumnarBaselineEntryAt(const size_t row_idx,
1284  const size_t target_idx,
1285  const size_t slot_idx) const {
1286  CHECK_NE(storage_->query_mem_desc_.targetGroupbyIndicesSize(), size_t(0));
1287  const auto key_width = storage_->query_mem_desc_.getEffectiveKeyWidth();
1288  const auto column_offset =
1289  (storage_->query_mem_desc_.getTargetGroupbyIndex(target_idx) < 0)
1290  ? storage_->query_mem_desc_.getColOffInBytes(slot_idx)
1291  : storage_->query_mem_desc_.getTargetGroupbyIndex(target_idx) * key_width *
1292  storage_->query_mem_desc_.getEntryCount();
1293  const auto column_buffer = storage_->getUnderlyingBuffer() + column_offset;
1294  return reinterpret_cast<const ENTRY_TYPE*>(column_buffer)[row_idx];
1295 }
1296 
1297 // Interprets ptr1, ptr2 as the ptr and len pair used for variable length data.
1299  const int8_t compact_sz1,
1300  const int8_t* ptr2,
1301  const int8_t compact_sz2,
1302  const TargetInfo& target_info,
1303  const size_t target_logical_idx,
1304  const bool translate_strings,
1305  const size_t entry_buff_idx) const {
1306  auto varlen_ptr = read_int_from_buff(ptr1, compact_sz1);
1307  if (separate_varlen_storage_valid_ && !target_info.is_agg) {
1308  if (varlen_ptr < 0) {
1309  CHECK_EQ(-1, varlen_ptr);
1310  if (target_info.sql_type.get_type() == kARRAY) {
1311  return ArrayTargetValue(boost::optional<std::vector<ScalarTargetValue>>{});
1312  }
1313  return TargetValue(nullptr);
1314  }
1315  const auto storage_idx = getStorageIndex(entry_buff_idx);
1316  if (target_info.sql_type.is_string()) {
1317  CHECK(target_info.sql_type.get_compression() == kENCODING_NONE);
1318  CHECK_LT(storage_idx.first, serialized_varlen_buffer_.size());
1319  const auto& varlen_buffer_for_storage =
1320  serialized_varlen_buffer_[storage_idx.first];
1321  CHECK_LT(static_cast<size_t>(varlen_ptr), varlen_buffer_for_storage.size());
1322  return varlen_buffer_for_storage[varlen_ptr];
1323  } else if (target_info.sql_type.get_type() == kARRAY) {
1324  CHECK_LT(storage_idx.first, serialized_varlen_buffer_.size());
1325  const auto& varlen_buffer = serialized_varlen_buffer_[storage_idx.first];
1326  CHECK_LT(static_cast<size_t>(varlen_ptr), varlen_buffer.size());
1327 
1328  return build_array_target_value(
1329  target_info.sql_type,
1330  reinterpret_cast<const int8_t*>(varlen_buffer[varlen_ptr].data()),
1331  varlen_buffer[varlen_ptr].size(),
1332  translate_strings,
1334  catalog_);
1335  } else {
1336  CHECK(false);
1337  }
1338  }
1339  if (!lazy_fetch_info_.empty()) {
1340  CHECK_LT(target_logical_idx, lazy_fetch_info_.size());
1341  const auto& col_lazy_fetch = lazy_fetch_info_[target_logical_idx];
1342  if (col_lazy_fetch.is_lazily_fetched) {
1343  const auto storage_idx = getStorageIndex(entry_buff_idx);
1344  CHECK_LT(storage_idx.first, col_buffers_.size());
1345  auto& frag_col_buffers =
1346  getColumnFrag(storage_idx.first, target_logical_idx, varlen_ptr);
1347  bool is_end{false};
1348  if (target_info.sql_type.is_string()) {
1349  VarlenDatum vd;
1350  ChunkIter_get_nth(reinterpret_cast<ChunkIter*>(const_cast<int8_t*>(
1351  frag_col_buffers[col_lazy_fetch.local_col_id])),
1352  varlen_ptr,
1353  false,
1354  &vd,
1355  &is_end);
1356  CHECK(!is_end);
1357  if (vd.is_null) {
1358  return TargetValue(nullptr);
1359  }
1360  CHECK(vd.pointer);
1361  CHECK_GT(vd.length, 0u);
1362  std::string fetched_str(reinterpret_cast<char*>(vd.pointer), vd.length);
1363  return fetched_str;
1364  } else {
1365  CHECK(target_info.sql_type.is_array());
1366  ArrayDatum ad;
1367  ChunkIter_get_nth(reinterpret_cast<ChunkIter*>(const_cast<int8_t*>(
1368  frag_col_buffers[col_lazy_fetch.local_col_id])),
1369  varlen_ptr,
1370  &ad,
1371  &is_end);
1372  CHECK(!is_end);
1373  if (ad.is_null) {
1374  return ArrayTargetValue(boost::optional<std::vector<ScalarTargetValue>>{});
1375  }
1376  CHECK_GE(ad.length, 0u);
1377  if (ad.length > 0) {
1378  CHECK(ad.pointer);
1379  }
1380  return build_array_target_value(target_info.sql_type,
1381  ad.pointer,
1382  ad.length,
1383  translate_strings,
1385  catalog_);
1386  }
1387  }
1388  }
1389  if (!varlen_ptr) {
1390  if (target_info.sql_type.is_array()) {
1391  return ArrayTargetValue(boost::optional<std::vector<ScalarTargetValue>>{});
1392  }
1393  return TargetValue(nullptr);
1394  }
1395  auto length = read_int_from_buff(ptr2, compact_sz2);
1396  if (target_info.sql_type.is_array()) {
1397  const auto& elem_ti = target_info.sql_type.get_elem_type();
1398  length *= elem_ti.get_array_context_logical_size();
1399  }
1400  std::vector<int8_t> cpu_buffer;
1401  if (varlen_ptr && device_type_ == ExecutorDeviceType::GPU) {
1402  cpu_buffer.resize(length);
1403  const auto executor = query_mem_desc_.getExecutor();
1404  CHECK(executor);
1405  auto& data_mgr = executor->catalog_->getDataMgr();
1406  copy_from_gpu(&data_mgr,
1407  &cpu_buffer[0],
1408  static_cast<CUdeviceptr>(varlen_ptr),
1409  length,
1410  device_id_);
1411  varlen_ptr = reinterpret_cast<int64_t>(&cpu_buffer[0]);
1412  }
1413  if (target_info.sql_type.is_array()) {
1414  return build_array_target_value(target_info.sql_type,
1415  reinterpret_cast<const int8_t*>(varlen_ptr),
1416  length,
1417  translate_strings,
1419  catalog_);
1420  }
1421  return std::string(reinterpret_cast<char*>(varlen_ptr), length);
1422 }
1423 
1424 bool ResultSet::isGeoColOnGpu(const size_t col_idx) const {
1425  // This should match the logic in makeGeoTargetValue which ultimately calls
1426  // fetch_data_from_gpu when the geo column is on the device.
1427  // TODO(croot): somehow find a way to refactor this and makeGeoTargetValue to use a
1428  // utility function that handles this logic in one place
1429  CHECK_LT(col_idx, targets_.size());
1430  if (!IS_GEO(targets_[col_idx].sql_type.get_type())) {
1431  throw std::runtime_error("Column target at index " + std::to_string(col_idx) +
1432  " is not a geo column. It is of type " +
1433  targets_[col_idx].sql_type.get_type_name() + ".");
1434  }
1435 
1436  const auto& target_info = targets_[col_idx];
1437  if (separate_varlen_storage_valid_ && !target_info.is_agg) {
1438  return false;
1439  }
1440 
1441  if (!lazy_fetch_info_.empty()) {
1442  CHECK_LT(col_idx, lazy_fetch_info_.size());
1443  if (lazy_fetch_info_[col_idx].is_lazily_fetched) {
1444  return false;
1445  }
1446  }
1447 
1449 }
1450 
1451 // Reads a geo value from a series of ptrs to var len types
1452 // In Columnar format, geo_target_ptr is the geo column ptr (a pointer to the beginning
1453 // of that specific geo column) and should be appropriately adjusted with the
1454 // entry_buff_idx
1455 TargetValue ResultSet::makeGeoTargetValue(const int8_t* geo_target_ptr,
1456  const size_t slot_idx,
1457  const TargetInfo& target_info,
1458  const size_t target_logical_idx,
1459  const size_t entry_buff_idx) const {
1460  CHECK(target_info.sql_type.is_geometry());
1461 
1462  auto getNextTargetBufferRowWise = [&](const size_t slot_idx, const size_t range) {
1463  return geo_target_ptr + query_mem_desc_.getPaddedColWidthForRange(slot_idx, range);
1464  };
1465 
1466  auto getNextTargetBufferColWise = [&](const size_t slot_idx, const size_t range) {
1467  const auto storage_info = findStorage(entry_buff_idx);
1468  auto crt_geo_col_ptr = geo_target_ptr;
1469  for (size_t i = slot_idx; i < slot_idx + range; i++) {
1470  crt_geo_col_ptr = advance_to_next_columnar_target_buff(
1471  crt_geo_col_ptr, storage_info.storage_ptr->query_mem_desc_, i);
1472  }
1473  // adjusting the column pointer to represent a pointer to the geo target value
1474  return crt_geo_col_ptr +
1475  storage_info.fixedup_entry_idx *
1476  storage_info.storage_ptr->query_mem_desc_.getPaddedSlotWidthBytes(
1477  slot_idx + range);
1478  };
1479 
1480  auto getNextTargetBuffer = [&](const size_t slot_idx, const size_t range) {
1482  ? getNextTargetBufferColWise(slot_idx, range)
1483  : getNextTargetBufferRowWise(slot_idx, range);
1484  };
1485 
1486  auto getCoordsDataPtr = [&](const int8_t* geo_target_ptr) {
1487  return read_int_from_buff(getNextTargetBuffer(slot_idx, 0),
1489  };
1490 
1491  auto getCoordsLength = [&](const int8_t* geo_target_ptr) {
1492  return read_int_from_buff(getNextTargetBuffer(slot_idx, 1),
1494  };
1495 
1496  auto getRingSizesPtr = [&](const int8_t* geo_target_ptr) {
1497  return read_int_from_buff(getNextTargetBuffer(slot_idx, 2),
1499  };
1500 
1501  auto getRingSizesLength = [&](const int8_t* geo_target_ptr) {
1502  return read_int_from_buff(getNextTargetBuffer(slot_idx, 3),
1504  };
1505 
1506  auto getPolyRingsPtr = [&](const int8_t* geo_target_ptr) {
1507  return read_int_from_buff(getNextTargetBuffer(slot_idx, 4),
1509  };
1510 
1511  auto getPolyRingsLength = [&](const int8_t* geo_target_ptr) {
1512  return read_int_from_buff(getNextTargetBuffer(slot_idx, 5),
1514  };
1515 
1516  auto getFragColBuffers = [&]() -> decltype(auto) {
1517  const auto storage_idx = getStorageIndex(entry_buff_idx);
1518  CHECK_LT(storage_idx.first, col_buffers_.size());
1519  auto global_idx = getCoordsDataPtr(geo_target_ptr);
1520  return getColumnFrag(storage_idx.first, target_logical_idx, global_idx);
1521  };
1522 
1523  const bool is_gpu_fetch = device_type_ == ExecutorDeviceType::GPU;
1524 
1525  auto getDataMgr = [&]() {
1526  auto executor = query_mem_desc_.getExecutor();
1527  CHECK(executor);
1528  auto& data_mgr = executor->catalog_->getDataMgr();
1529  return &data_mgr;
1530  };
1531 
1532  auto getSeparateVarlenStorage = [&]() -> decltype(auto) {
1533  const auto storage_idx = getStorageIndex(entry_buff_idx);
1534  CHECK_LT(storage_idx.first, serialized_varlen_buffer_.size());
1535  const auto& varlen_buffer = serialized_varlen_buffer_[storage_idx.first];
1536  return varlen_buffer;
1537  };
1538 
1539  if (separate_varlen_storage_valid_ && getCoordsDataPtr(geo_target_ptr) < 0) {
1540  CHECK_EQ(-1, getCoordsDataPtr(geo_target_ptr));
1541  return TargetValue(nullptr);
1542  }
1543 
1544  const ColumnLazyFetchInfo* col_lazy_fetch = nullptr;
1545  if (!lazy_fetch_info_.empty()) {
1546  CHECK_LT(target_logical_idx, lazy_fetch_info_.size());
1547  col_lazy_fetch = &lazy_fetch_info_[target_logical_idx];
1548  }
1549 
1550  switch (target_info.sql_type.get_type()) {
1551  case kPOINT: {
1552  if (separate_varlen_storage_valid_ && !target_info.is_agg) {
1553  const auto& varlen_buffer = getSeparateVarlenStorage();
1554  CHECK_LT(static_cast<size_t>(getCoordsDataPtr(geo_target_ptr)),
1555  varlen_buffer.size());
1556 
1557  return GeoTargetValueBuilder<kPOINT, GeoQueryOutputFetchHandler>::build(
1558  target_info.sql_type,
1560  nullptr,
1561  false,
1562  device_id_,
1563  reinterpret_cast<int64_t>(
1564  varlen_buffer[getCoordsDataPtr(geo_target_ptr)].data()),
1565  static_cast<int64_t>(varlen_buffer[getCoordsDataPtr(geo_target_ptr)].size()));
1566  } else if (col_lazy_fetch && col_lazy_fetch->is_lazily_fetched) {
1567  const auto& frag_col_buffers = getFragColBuffers();
1568  return GeoTargetValueBuilder<kPOINT, GeoLazyFetchHandler>::build(
1569  target_info.sql_type,
1571  frag_col_buffers[col_lazy_fetch->local_col_id],
1572  getCoordsDataPtr(geo_target_ptr));
1573  } else {
1574  return GeoTargetValueBuilder<kPOINT, GeoQueryOutputFetchHandler>::build(
1575  target_info.sql_type,
1577  is_gpu_fetch ? getDataMgr() : nullptr,
1578  is_gpu_fetch,
1579  device_id_,
1580  getCoordsDataPtr(geo_target_ptr),
1581  getCoordsLength(geo_target_ptr));
1582  }
1583  break;
1584  }
1585  case kLINESTRING: {
1586  if (separate_varlen_storage_valid_ && !target_info.is_agg) {
1587  const auto& varlen_buffer = getSeparateVarlenStorage();
1588  CHECK_LT(static_cast<size_t>(getCoordsDataPtr(geo_target_ptr)),
1589  varlen_buffer.size());
1590 
1591  return GeoTargetValueBuilder<kLINESTRING, GeoQueryOutputFetchHandler>::build(
1592  target_info.sql_type,
1594  nullptr,
1595  false,
1596  device_id_,
1597  reinterpret_cast<int64_t>(
1598  varlen_buffer[getCoordsDataPtr(geo_target_ptr)].data()),
1599  static_cast<int64_t>(varlen_buffer[getCoordsDataPtr(geo_target_ptr)].size()));
1600  } else if (col_lazy_fetch && col_lazy_fetch->is_lazily_fetched) {
1601  const auto& frag_col_buffers = getFragColBuffers();
1602  return GeoTargetValueBuilder<kLINESTRING, GeoLazyFetchHandler>::build(
1603  target_info.sql_type,
1605  frag_col_buffers[col_lazy_fetch->local_col_id],
1606  getCoordsDataPtr(geo_target_ptr));
1607  } else {
1608  return GeoTargetValueBuilder<kLINESTRING, GeoQueryOutputFetchHandler>::build(
1609  target_info.sql_type,
1611  is_gpu_fetch ? getDataMgr() : nullptr,
1612  is_gpu_fetch,
1613  device_id_,
1614  getCoordsDataPtr(geo_target_ptr),
1615  getCoordsLength(geo_target_ptr));
1616  }
1617  break;
1618  }
1619  case kPOLYGON: {
1620  if (separate_varlen_storage_valid_ && !target_info.is_agg) {
1621  const auto& varlen_buffer = getSeparateVarlenStorage();
1622  CHECK_LT(static_cast<size_t>(getCoordsDataPtr(geo_target_ptr) + 1),
1623  varlen_buffer.size());
1624 
1625  return GeoTargetValueBuilder<kPOLYGON, GeoQueryOutputFetchHandler>::build(
1626  target_info.sql_type,
1628  nullptr,
1629  false,
1630  device_id_,
1631  reinterpret_cast<int64_t>(
1632  varlen_buffer[getCoordsDataPtr(geo_target_ptr)].data()),
1633  static_cast<int64_t>(varlen_buffer[getCoordsDataPtr(geo_target_ptr)].size()),
1634  reinterpret_cast<int64_t>(
1635  varlen_buffer[getCoordsDataPtr(geo_target_ptr) + 1].data()),
1636  static_cast<int64_t>(
1637  varlen_buffer[getCoordsDataPtr(geo_target_ptr) + 1].size()));
1638  } else if (col_lazy_fetch && col_lazy_fetch->is_lazily_fetched) {
1639  const auto& frag_col_buffers = getFragColBuffers();
1640 
1641  return GeoTargetValueBuilder<kPOLYGON, GeoLazyFetchHandler>::build(
1642  target_info.sql_type,
1644  frag_col_buffers[col_lazy_fetch->local_col_id],
1645  getCoordsDataPtr(geo_target_ptr),
1646  frag_col_buffers[col_lazy_fetch->local_col_id + 1],
1647  getCoordsDataPtr(geo_target_ptr));
1648  } else {
1649  return GeoTargetValueBuilder<kPOLYGON, GeoQueryOutputFetchHandler>::build(
1650  target_info.sql_type,
1652  is_gpu_fetch ? getDataMgr() : nullptr,
1653  is_gpu_fetch,
1654  device_id_,
1655  getCoordsDataPtr(geo_target_ptr),
1656  getCoordsLength(geo_target_ptr),
1657  getRingSizesPtr(geo_target_ptr),
1658  getRingSizesLength(geo_target_ptr) * 4);
1659  }
1660  break;
1661  }
1662  case kMULTIPOLYGON: {
1663  if (separate_varlen_storage_valid_ && !target_info.is_agg) {
1664  const auto& varlen_buffer = getSeparateVarlenStorage();
1665  CHECK_LT(static_cast<size_t>(getCoordsDataPtr(geo_target_ptr) + 2),
1666  varlen_buffer.size());
1667 
1668  return GeoTargetValueBuilder<kMULTIPOLYGON, GeoQueryOutputFetchHandler>::build(
1669  target_info.sql_type,
1671  nullptr,
1672  false,
1673  device_id_,
1674  reinterpret_cast<int64_t>(
1675  varlen_buffer[getCoordsDataPtr(geo_target_ptr)].data()),
1676  static_cast<int64_t>(varlen_buffer[getCoordsDataPtr(geo_target_ptr)].size()),
1677  reinterpret_cast<int64_t>(
1678  varlen_buffer[getCoordsDataPtr(geo_target_ptr) + 1].data()),
1679  static_cast<int64_t>(
1680  varlen_buffer[getCoordsDataPtr(geo_target_ptr) + 1].size()),
1681  reinterpret_cast<int64_t>(
1682  varlen_buffer[getCoordsDataPtr(geo_target_ptr) + 2].data()),
1683  static_cast<int64_t>(
1684  varlen_buffer[getCoordsDataPtr(geo_target_ptr) + 2].size()));
1685  } else if (col_lazy_fetch && col_lazy_fetch->is_lazily_fetched) {
1686  const auto& frag_col_buffers = getFragColBuffers();
1687 
1688  return GeoTargetValueBuilder<kMULTIPOLYGON, GeoLazyFetchHandler>::build(
1689  target_info.sql_type,
1691  frag_col_buffers[col_lazy_fetch->local_col_id],
1692  getCoordsDataPtr(geo_target_ptr),
1693  frag_col_buffers[col_lazy_fetch->local_col_id + 1],
1694  getCoordsDataPtr(geo_target_ptr),
1695  frag_col_buffers[col_lazy_fetch->local_col_id + 2],
1696  getCoordsDataPtr(geo_target_ptr));
1697  } else {
1698  return GeoTargetValueBuilder<kMULTIPOLYGON, GeoQueryOutputFetchHandler>::build(
1699  target_info.sql_type,
1701  is_gpu_fetch ? getDataMgr() : nullptr,
1702  is_gpu_fetch,
1703  device_id_,
1704  getCoordsDataPtr(geo_target_ptr),
1705  getCoordsLength(geo_target_ptr),
1706  getRingSizesPtr(geo_target_ptr),
1707  getRingSizesLength(geo_target_ptr) * 4,
1708  getPolyRingsPtr(geo_target_ptr),
1709  getPolyRingsLength(geo_target_ptr) * 4);
1710  }
1711  break;
1712  }
1713  default:
1714  throw std::runtime_error("Unknown Geometry type encountered: " +
1715  target_info.sql_type.get_type_name());
1716  }
1717  UNREACHABLE();
1718  return TargetValue(nullptr);
1719 }
1720 
1721 // Reads an integer or a float from ptr based on the type and the byte width.
1723  const int8_t compact_sz,
1724  const TargetInfo& target_info,
1725  const size_t target_logical_idx,
1726  const bool translate_strings,
1727  const bool decimal_to_double,
1728  const size_t entry_buff_idx) const {
1729  auto actual_compact_sz = compact_sz;
1730  const auto& type_info = target_info.sql_type;
1731  if (type_info.get_type() == kFLOAT && !query_mem_desc_.forceFourByteFloat()) {
1733  actual_compact_sz = sizeof(float);
1734  } else {
1735  actual_compact_sz = sizeof(double);
1736  }
1737  if (target_info.is_agg &&
1738  (target_info.agg_kind == kAVG || target_info.agg_kind == kSUM ||
1739  target_info.agg_kind == kMIN || target_info.agg_kind == kMAX ||
1740  target_info.agg_kind == kSINGLE_VALUE)) {
1741  // The above listed aggregates use two floats in a single 8-byte slot. Set the
1742  // padded size to 4 bytes to properly read each value.
1743  actual_compact_sz = sizeof(float);
1744  }
1745  }
1746  if (get_compact_type(target_info).is_date_in_days()) {
1747  // Dates encoded in days are converted to 8 byte values on read.
1748  actual_compact_sz = sizeof(int64_t);
1749  }
1750 
1751  // String dictionary keys are read as 32-bit values regardless of encoding
1752  if (type_info.is_string() && type_info.get_compression() == kENCODING_DICT &&
1753  type_info.get_comp_param()) {
1754  actual_compact_sz = sizeof(int32_t);
1755  }
1756 
1757  auto ival = read_int_from_buff(ptr, actual_compact_sz);
1758  const auto& chosen_type = get_compact_type(target_info);
1759  if (!lazy_fetch_info_.empty()) {
1760  CHECK_LT(target_logical_idx, lazy_fetch_info_.size());
1761  const auto& col_lazy_fetch = lazy_fetch_info_[target_logical_idx];
1762  if (col_lazy_fetch.is_lazily_fetched) {
1763  CHECK_GE(ival, 0);
1764  const auto storage_idx = getStorageIndex(entry_buff_idx);
1765  CHECK_LT(storage_idx.first, col_buffers_.size());
1766  auto& frag_col_buffers = getColumnFrag(storage_idx.first, target_logical_idx, ival);
1767  CHECK_LT(size_t(col_lazy_fetch.local_col_id), frag_col_buffers.size());
1768  ival = result_set::lazy_decode(
1769  col_lazy_fetch, frag_col_buffers[col_lazy_fetch.local_col_id], ival);
1770  if (chosen_type.is_fp()) {
1771  const auto dval = *reinterpret_cast<const double*>(may_alias_ptr(&ival));
1772  if (chosen_type.get_type() == kFLOAT) {
1773  return ScalarTargetValue(static_cast<float>(dval));
1774  } else {
1775  return ScalarTargetValue(dval);
1776  }
1777  }
1778  }
1779  }
1780  if (chosen_type.is_fp()) {
1781  switch (actual_compact_sz) {
1782  case 8: {
1783  const auto dval = *reinterpret_cast<const double*>(ptr);
1784  return chosen_type.get_type() == kFLOAT
1785  ? ScalarTargetValue(static_cast<const float>(dval))
1786  : ScalarTargetValue(dval);
1787  }
1788  case 4: {
1789  CHECK_EQ(kFLOAT, chosen_type.get_type());
1790  return *reinterpret_cast<const float*>(ptr);
1791  }
1792  default:
1793  CHECK(false);
1794  }
1795  }
1796  if (chosen_type.is_integer() | chosen_type.is_boolean() || chosen_type.is_time() ||
1797  chosen_type.is_timeinterval()) {
1798  if (is_distinct_target(target_info)) {
1800  ival, query_mem_desc_.getCountDistinctDescriptor(target_logical_idx)));
1801  }
1802  // TODO(alex): remove int_resize_cast, make read_int_from_buff return the
1803  // right type instead
1804  if (inline_int_null_val(chosen_type) ==
1805  int_resize_cast(ival, chosen_type.get_logical_size())) {
1806  return inline_int_null_val(type_info);
1807  }
1808  return ival;
1809  }
1810  if (chosen_type.is_string() && chosen_type.get_compression() == kENCODING_DICT) {
1811  if (translate_strings) {
1812  if (static_cast<int32_t>(ival) ==
1813  NULL_INT) { // TODO(alex): this isn't nice, fix it
1814  return NullableString(nullptr);
1815  }
1816  StringDictionaryProxy* sdp{nullptr};
1817  if (!chosen_type.get_comp_param()) {
1818  sdp = row_set_mem_owner_->getLiteralStringDictProxy();
1819  } else {
1820  sdp = catalog_
1821  ? row_set_mem_owner_->getOrAddStringDictProxy(
1822  chosen_type.get_comp_param(), /*with_generation=*/false, catalog_)
1823  : row_set_mem_owner_->getStringDictProxy(
1824  chosen_type.get_comp_param()); // unit tests bypass the catalog
1825  }
1826  return NullableString(sdp->getString(ival));
1827  } else {
1828  return static_cast<int64_t>(static_cast<int32_t>(ival));
1829  }
1830  }
1831  if (chosen_type.is_decimal()) {
1832  if (decimal_to_double) {
1833  if (target_info.is_agg &&
1834  (target_info.agg_kind == kAVG || target_info.agg_kind == kSUM ||
1835  target_info.agg_kind == kMIN || target_info.agg_kind == kMAX) &&
1836  ival == inline_int_null_val(SQLTypeInfo(kBIGINT, false))) {
1837  return NULL_DOUBLE;
1838  }
1839  if (ival ==
1840  inline_int_null_val(SQLTypeInfo(decimal_to_int_type(chosen_type), false))) {
1841  return NULL_DOUBLE;
1842  }
1843  return static_cast<double>(ival) / exp_to_scale(chosen_type.get_scale());
1844  }
1845  return ival;
1846  }
1847  CHECK(false);
1848  return TargetValue(int64_t(0));
1849 }
1850 
1851 namespace {
1852 double calculate_quantile(int8_t const* ptr, double const q) {
1853  static_assert(sizeof(int64_t) == sizeof(quantile::TDigest*));
1854  auto* t_digest = *reinterpret_cast<quantile::TDigest* const*>(ptr);
1855  CHECK(t_digest) << "ptr=" << (void const*)ptr << ", q=" << q;
1856  t_digest->mergeBuffer();
1857  double const median = t_digest->quantile(q);
1858  return boost::math::isnan(median) ? NULL_DOUBLE : median;
1859 }
1860 } // namespace
1861 
1862 // Gets the TargetValue stored at position local_entry_idx in the col1_ptr and col2_ptr
1863 // column buffers. The second column is only used for AVG.
1864 // the global_entry_idx is passed to makeTargetValue to be used for
1865 // final lazy fetch (if there's any).
1867  const int8_t* col_ptr,
1868  const int8_t* keys_ptr,
1869  const QueryMemoryDescriptor& query_mem_desc,
1870  const size_t local_entry_idx,
1871  const size_t global_entry_idx,
1872  const TargetInfo& target_info,
1873  const size_t target_logical_idx,
1874  const size_t slot_idx,
1875  const bool translate_strings,
1876  const bool decimal_to_double) const {
1878  const auto col1_ptr = col_ptr;
1879  const auto compact_sz1 = query_mem_desc.getPaddedSlotWidthBytes(slot_idx);
1880  const auto next_col_ptr =
1881  advance_to_next_columnar_target_buff(col1_ptr, query_mem_desc, slot_idx);
1882  const auto col2_ptr = ((target_info.is_agg && target_info.agg_kind == kAVG) ||
1883  is_real_str_or_array(target_info))
1884  ? next_col_ptr
1885  : nullptr;
1886  const auto compact_sz2 = ((target_info.is_agg && target_info.agg_kind == kAVG) ||
1887  is_real_str_or_array(target_info))
1888  ? query_mem_desc.getPaddedSlotWidthBytes(slot_idx + 1)
1889  : 0;
1890 
1891  // TODO(Saman): add required logics for count distinct
1892  // geospatial target values:
1893  if (target_info.sql_type.is_geometry()) {
1894  return makeGeoTargetValue(
1895  col1_ptr, slot_idx, target_info, target_logical_idx, global_entry_idx);
1896  }
1897 
1898  const auto ptr1 = columnar_elem_ptr(local_entry_idx, col1_ptr, compact_sz1);
1899  if (target_info.agg_kind == kAVG || is_real_str_or_array(target_info)) {
1900  CHECK(col2_ptr);
1901  CHECK(compact_sz2);
1902  const auto ptr2 = columnar_elem_ptr(local_entry_idx, col2_ptr, compact_sz2);
1903  return target_info.agg_kind == kAVG
1904  ? make_avg_target_value(ptr1, compact_sz1, ptr2, compact_sz2, target_info)
1905  : makeVarlenTargetValue(ptr1,
1906  compact_sz1,
1907  ptr2,
1908  compact_sz2,
1909  target_info,
1910  target_logical_idx,
1911  translate_strings,
1912  global_entry_idx);
1913  } else if (target_info.agg_kind == kAPPROX_MEDIAN) {
1914  return calculate_quantile(ptr1, 0.5);
1915  }
1917  query_mem_desc_.getTargetGroupbyIndex(target_logical_idx) < 0) {
1918  return makeTargetValue(ptr1,
1919  compact_sz1,
1920  target_info,
1921  target_logical_idx,
1922  translate_strings,
1923  decimal_to_double,
1924  global_entry_idx);
1925  }
1926  const auto key_width = query_mem_desc_.getEffectiveKeyWidth();
1927  const auto key_idx = query_mem_desc_.getTargetGroupbyIndex(target_logical_idx);
1928  CHECK_GE(key_idx, 0);
1929  auto key_col_ptr = keys_ptr + key_idx * query_mem_desc_.getEntryCount() * key_width;
1930  return makeTargetValue(columnar_elem_ptr(local_entry_idx, key_col_ptr, key_width),
1931  key_width,
1932  target_info,
1933  target_logical_idx,
1934  translate_strings,
1935  decimal_to_double,
1936  global_entry_idx);
1937 }
1938 
1939 // Gets the TargetValue stored in slot_idx (and slot_idx for AVG) of
1940 // rowwise_target_ptr.
1942  int8_t* rowwise_target_ptr,
1943  int8_t* keys_ptr,
1944  const size_t entry_buff_idx,
1945  const TargetInfo& target_info,
1946  const size_t target_logical_idx,
1947  const size_t slot_idx,
1948  const bool translate_strings,
1949  const bool decimal_to_double,
1950  const bool fixup_count_distinct_pointers) const {
1951  if (UNLIKELY(fixup_count_distinct_pointers)) {
1952  if (is_distinct_target(target_info)) {
1953  auto count_distinct_ptr_ptr = reinterpret_cast<int64_t*>(rowwise_target_ptr);
1954  const auto remote_ptr = *count_distinct_ptr_ptr;
1955  if (remote_ptr) {
1956  const auto ptr = storage_->mappedPtr(remote_ptr);
1957  if (ptr) {
1958  *count_distinct_ptr_ptr = ptr;
1959  } else {
1960  // need to create a zero filled buffer for this remote_ptr
1961  const auto& count_distinct_desc =
1962  query_mem_desc_.count_distinct_descriptors_[target_logical_idx];
1963  const auto bitmap_byte_sz = count_distinct_desc.sub_bitmap_count == 1
1964  ? count_distinct_desc.bitmapSizeBytes()
1965  : count_distinct_desc.bitmapPaddedSizeBytes();
1966  auto count_distinct_buffer =
1967  row_set_mem_owner_->allocateCountDistinctBuffer(bitmap_byte_sz);
1968  *count_distinct_ptr_ptr = reinterpret_cast<int64_t>(count_distinct_buffer);
1969  }
1970  }
1971  }
1972  return int64_t(0);
1973  }
1974  if (target_info.sql_type.is_geometry()) {
1975  return makeGeoTargetValue(
1976  rowwise_target_ptr, slot_idx, target_info, target_logical_idx, entry_buff_idx);
1977  }
1978 
1979  auto ptr1 = rowwise_target_ptr;
1980  int8_t compact_sz1 = query_mem_desc_.getPaddedSlotWidthBytes(slot_idx);
1982  !query_mem_desc_.hasKeylessHash() && !target_info.is_agg) {
1983  // Single column perfect hash group by can utilize one slot for both the key and the
1984  // target value if both values fit in 8 bytes. Use the target value actual size for
1985  // this case. If they don't, the target value should be 8 bytes, so we can still use
1986  // the actual size rather than the compact size.
1987  compact_sz1 = query_mem_desc_.getLogicalSlotWidthBytes(slot_idx);
1988  }
1989 
1990  // logic for deciding width of column
1991  if (target_info.agg_kind == kAVG || is_real_str_or_array(target_info)) {
1992  const auto ptr2 =
1993  rowwise_target_ptr + query_mem_desc_.getPaddedSlotWidthBytes(slot_idx);
1994  int8_t compact_sz2 = 0;
1995  // Skip reading the second slot if we have a none encoded string and are using
1996  // the none encoded strings buffer attached to ResultSetStorage
1998  (target_info.sql_type.is_array() ||
1999  (target_info.sql_type.is_string() &&
2000  target_info.sql_type.get_compression() == kENCODING_NONE)))) {
2001  compact_sz2 = query_mem_desc_.getPaddedSlotWidthBytes(slot_idx + 1);
2002  }
2003  if (separate_varlen_storage_valid_ && target_info.is_agg) {
2004  compact_sz2 = 8; // TODO(adb): is there a better way to do this?
2005  }
2006  CHECK(ptr2);
2007  return target_info.agg_kind == kAVG
2008  ? make_avg_target_value(ptr1, compact_sz1, ptr2, compact_sz2, target_info)
2009  : makeVarlenTargetValue(ptr1,
2010  compact_sz1,
2011  ptr2,
2012  compact_sz2,
2013  target_info,
2014  target_logical_idx,
2015  translate_strings,
2016  entry_buff_idx);
2017  } else if (target_info.agg_kind == kAPPROX_MEDIAN) {
2018  return calculate_quantile(rowwise_target_ptr, 0.5);
2019  }
2021  query_mem_desc_.getTargetGroupbyIndex(target_logical_idx) < 0) {
2022  return makeTargetValue(ptr1,
2023  compact_sz1,
2024  target_info,
2025  target_logical_idx,
2026  translate_strings,
2027  decimal_to_double,
2028  entry_buff_idx);
2029  }
2030  const auto key_width = query_mem_desc_.getEffectiveKeyWidth();
2031  ptr1 = keys_ptr + query_mem_desc_.getTargetGroupbyIndex(target_logical_idx) * key_width;
2032  return makeTargetValue(ptr1,
2033  key_width,
2034  target_info,
2035  target_logical_idx,
2036  translate_strings,
2037  decimal_to_double,
2038  entry_buff_idx);
2039 }
2040 
2041 // Returns true iff the entry at position entry_idx in buff contains a valid row.
2042 bool ResultSetStorage::isEmptyEntry(const size_t entry_idx, const int8_t* buff) const {
2045  return false;
2046  }
2048  return isEmptyEntryColumnar(entry_idx, buff);
2049  }
2054  CHECK_LT(static_cast<size_t>(query_mem_desc_.getTargetIdxForKey()),
2055  target_init_vals_.size());
2056  const auto rowwise_target_ptr = row_ptr_rowwise(buff, query_mem_desc_, entry_idx);
2057  const auto target_slot_off = result_set::get_byteoff_of_slot(
2059  return read_int_from_buff(rowwise_target_ptr + target_slot_off,
2062  target_init_vals_[query_mem_desc_.getTargetIdxForKey()];
2063  } else {
2064  const auto keys_ptr = row_ptr_rowwise(buff, query_mem_desc_, entry_idx);
2066  case 4:
2069  return *reinterpret_cast<const int32_t*>(keys_ptr) == EMPTY_KEY_32;
2070  case 8:
2071  return *reinterpret_cast<const int64_t*>(keys_ptr) == EMPTY_KEY_64;
2072  default:
2073  CHECK(false);
2074  return true;
2075  }
2076  }
2077 }
2078 
2079 /*
2080  * Returns true if the entry contain empty keys
2081  * This function should only be used with columanr format.
2082  */
2083 bool ResultSetStorage::isEmptyEntryColumnar(const size_t entry_idx,
2084  const int8_t* buff) const {
2088  return false;
2089  }
2094  CHECK_LT(static_cast<size_t>(query_mem_desc_.getTargetIdxForKey()),
2095  target_init_vals_.size());
2096  const auto col_buff = advance_col_buff_to_slot(
2098  const auto entry_buff =
2099  col_buff + entry_idx * query_mem_desc_.getPaddedSlotWidthBytes(
2101  return read_int_from_buff(entry_buff,
2104  target_init_vals_[query_mem_desc_.getTargetIdxForKey()];
2105  } else {
2106  // it's enough to find the first group key which is empty
2108  return reinterpret_cast<const int64_t*>(buff)[entry_idx] == EMPTY_KEY_64;
2109  } else {
2111  const auto target_buff = buff + query_mem_desc_.getPrependedGroupColOffInBytes(0);
2112  switch (query_mem_desc_.groupColWidth(0)) {
2113  case 8:
2114  return reinterpret_cast<const int64_t*>(target_buff)[entry_idx] == EMPTY_KEY_64;
2115  case 4:
2116  return reinterpret_cast<const int32_t*>(target_buff)[entry_idx] == EMPTY_KEY_32;
2117  case 2:
2118  return reinterpret_cast<const int16_t*>(target_buff)[entry_idx] == EMPTY_KEY_16;
2119  case 1:
2120  return reinterpret_cast<const int8_t*>(target_buff)[entry_idx] == EMPTY_KEY_8;
2121  default:
2122  CHECK(false);
2123  }
2124  }
2125  return false;
2126  }
2127  return false;
2128 }
2129 
2130 namespace {
2131 
2132 template <typename T>
2133 inline size_t make_bin_search(size_t l, size_t r, T&& is_empty_fn) {
2134  // Avoid search if there are no empty keys.
2135  if (!is_empty_fn(r - 1)) {
2136  return r;
2137  }
2138 
2139  --r;
2140  while (l != r) {
2141  size_t c = (l + r) / 2;
2142  if (is_empty_fn(c)) {
2143  r = c;
2144  } else {
2145  l = c + 1;
2146  }
2147  }
2148 
2149  return r;
2150 }
2151 
2152 } // namespace
2153 
2157 
2158  if (!query_mem_desc_.getEntryCount()) {
2159  return 0;
2160  }
2161 
2163  return make_bin_search(0, query_mem_desc_.getEntryCount(), [this](size_t idx) {
2164  return reinterpret_cast<const int64_t*>(buff_)[idx] == EMPTY_KEY_64;
2165  });
2166  } else {
2167  return make_bin_search(0, query_mem_desc_.getEntryCount(), [this](size_t idx) {
2168  const auto keys_ptr = row_ptr_rowwise(buff_, query_mem_desc_, idx);
2169  return *reinterpret_cast<const int64_t*>(keys_ptr) == EMPTY_KEY_64;
2170  });
2171  }
2172 }
2173 
2174 bool ResultSetStorage::isEmptyEntry(const size_t entry_idx) const {
2175  return isEmptyEntry(entry_idx, buff_);
2176 }
2177 
2179  const InternalTargetValue& val,
2180  const bool float_argument_input) {
2181  if (ti.get_notnull()) {
2182  return false;
2183  }
2184  if (val.isInt()) {
2185  return val.i1 == null_val_bit_pattern(ti, float_argument_input);
2186  }
2187  if (val.isPair()) {
2188  return !val.i2 ||
2189  pair_to_double({val.i1, val.i2}, ti, float_argument_input) == NULL_DOUBLE;
2190  }
2191  if (val.isStr()) {
2192  return !val.i1;
2193  }
2194  CHECK(val.isNull());
2195  return true;
2196 }
static auto fetch(const SQLTypeInfo &geo_ti, const ResultSet::GeoReturnType return_type, T &&... vals)
#define CHECK_EQ(x, y)
Definition: Logger.h:205
std::vector< TargetValue > getNextRowImpl(const bool translate_strings, const bool decimal_to_double) const
bool isNull() const
Definition: TargetValue.h:69
#define NULL_DOUBLE
bool isPair() const
Definition: TargetValue.h:67
bool is_array() const
Definition: sqltypes.h:486
#define EMPTY_KEY_64
bool is_string() const
Definition: sqltypes.h:478
class for a per-database catalog. also includes metadata for the current database and the current use...
Definition: Catalog.h:101
double decimal_to_double(const SQLTypeInfo &otype, int64_t oval)
ENTRY_TYPE getRowWisePerfectHashEntryAt(const size_t row_idx, const size_t target_idx, const size_t slot_idx) const
AppendedStorage appended_storage_
Definition: ResultSet.h:708
const std::vector< const int8_t * > & getColumnFrag(const size_t storge_idx, const size_t col_logical_idx, int64_t &global_idx) const
GeoReturnType geo_return_type_
Definition: ResultSet.h:748
ExecutorDeviceType
bool is_null
Definition: sqltypes.h:144
boost::optional< boost::variant< GeoPointTargetValue, GeoLineStringTargetValue, GeoPolyTargetValue, GeoMultiPolyTargetValue > > GeoTargetValue
Definition: TargetValue.h:161
T advance_to_next_columnar_target_buff(T target_ptr, const QueryMemoryDescriptor &query_mem_desc, const size_t target_slot_idx)
size_t entryCount() const
SQLTypeInfo sql_type
Definition: TargetInfo.h:42
TargetValue build_string_array_target_value(const int32_t *buff, const size_t buff_sz, const int dict_id, const bool translate_strings, std::shared_ptr< RowSetMemoryOwner > row_set_mem_owner, const Catalog_Namespace::Catalog *catalog)
size_t make_bin_search(size_t l, size_t r, T &&is_empty_fn)
int get_array_context_logical_size() const
Definition: sqltypes.h:538
std::unique_ptr< ArrayDatum > lazy_fetch_chunk(const int8_t *ptr, const int64_t varlen_ptr)
const Catalog_Namespace::Catalog * catalog_
Definition: ResultSet.h:716
unsigned long long CUdeviceptr
Definition: nocuda.h:27
ENTRY_TYPE getRowWiseBaselineEntryAt(const size_t row_idx, const size_t target_idx, const size_t slot_idx) const
static bool isNull(const SQLTypeInfo &ti, const InternalTargetValue &val, const bool float_argument_input)
QueryMemoryDescriptor query_mem_desc_
Definition: ResultSet.h:706
#define UNREACHABLE()
Definition: Logger.h:241
#define CHECK_GE(x, y)
Definition: Logger.h:210
std::unique_ptr< ResultSetStorage > storage_
Definition: ResultSet.h:707
bool isDirectColumnarConversionPossible() const
Definition: ResultSet.cpp:973
bool is_null_point(const SQLTypeInfo &geo_ti, const int8_t *coords, const size_t coords_sz)
bool isGeoColOnGpu(const size_t col_idx) const
Constants for Builtin SQL Types supported by OmniSci.
size_t getBufferSizeBytes(const ExecutorDeviceType device_type) const
int64_t read_int_from_buff(const int8_t *ptr, const int8_t compact_sz)
size_t keep_first_
Definition: ResultSet.h:712
TargetValue make_avg_target_value(const int8_t *ptr1, const int8_t compact_sz1, const int8_t *ptr2, const int8_t compact_sz2, const TargetInfo &target_info)
double pair_to_double(const std::pair< int64_t, int64_t > &fp_pair, const SQLTypeInfo &ti, const bool float_argument_input)
bool takes_float_argument(const TargetInfo &target_info)
Definition: TargetInfo.h:134
std::vector< SerializedVarlenBufferStorage > serialized_varlen_buffer_
Definition: ResultSet.h:739
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:319
std::vector< std::pair< const int8_t *, const int64_t > > make_vals_vector(std::index_sequence< indices... >, const Tuple &tuple)
std::vector< TargetValue > getNextRowUnlocked(const bool translate_strings, const bool decimal_to_double) const
T advance_target_ptr_row_wise(T target_ptr, const TargetInfo &target_info, const size_t slot_idx, const QueryMemoryDescriptor &query_mem_desc, const bool separate_varlen_storage)
#define CHECK_GT(x, y)
Definition: Logger.h:209
int64_t null_val_bit_pattern(const SQLTypeInfo &ti, const bool float_argument_input)
DEVICE void ChunkIter_get_nth(ChunkIter *it, int n, bool uncompress, VarlenDatum *result, bool *is_end)
Definition: ChunkIter.cpp:181
static TargetValue build(const SQLTypeInfo &geo_ti, const ResultSet::GeoReturnType return_type, T &&... vals)
std::vector< TargetValue > getRowAt(const size_t index) const
std::string to_string(char const *&&v)
std::vector< uint32_t > permutation_
Definition: ResultSet.h:714
SQLTypeInfo agg_arg_type
Definition: TargetInfo.h:43
const int8_t getPaddedSlotWidthBytes(const size_t slot_idx) const
int8_t * pointer
Definition: sqltypes.h:143
#define NULL_INT
const size_t key_bytes_with_padding_
Definition: ResultSet.h:584
InternalTargetValue getColumnInternal(const int8_t *buff, const size_t entry_idx, const size_t target_logical_idx, const StorageLookupResult &storage_lookup_result) const
const Executor * getExecutor() const
bool isEmptyEntry(const size_t entry_idx, const int8_t *buff) const
const ResultSet * result_set_
Definition: ResultSet.h:579
bool isStr() const
Definition: TargetValue.h:71
const int8_t * advance_col_buff_to_slot(const int8_t *buff, const QueryMemoryDescriptor &query_mem_desc, const std::vector< TargetInfo > &targets, const size_t slot_idx, const bool separate_varlen_storage)
Definition: sqldefs.h:73
Serialization routines for geospatial types.
std::conditional_t< is_cuda_compiler(), DeviceArrayDatum, HostArrayDatum > ArrayDatum
Definition: sqltypes.h:199
const SQLTypeInfo get_compact_type(const TargetInfo &target)
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:318
OneIntegerColumnRow getOneColRow(const size_t index) const
bool isInt() const
Definition: TargetValue.h:65
size_t global_entry_idx_
Definition: ResultSet.h:125
const std::vector< TargetInfo > targets_
Definition: ResultSet.h:703
std::shared_ptr< RowSetMemoryOwner > row_set_mem_owner_
Definition: ResultSet.h:713
std::vector< TargetValue > getRowAtNoTranslations(const size_t index, const std::vector< bool > &targets_to_skip={}) const
size_t get_byteoff_of_slot(const size_t slot_idx, const QueryMemoryDescriptor &query_mem_desc)
size_t drop_first_
Definition: ResultSet.h:711
bool is_agg
Definition: TargetInfo.h:40
size_t advance_slot(const size_t j, const TargetInfo &target_info, const bool separate_varlen_storage)
CONSTEXPR DEVICE bool is_null(const T &value)
Classes representing a parse tree.
std::pair< size_t, size_t > getStorageIndex(const size_t entry_idx) const
Definition: ResultSet.cpp:635
int64_t count_distinct_set_size(const int64_t set_handle, const CountDistinctDescriptor &count_distinct_desc)
Definition: CountDistinct.h:75
InternalTargetValue getVarlenOrderEntry(const int64_t str_ptr, const size_t str_len) const
std::string getString(int32_t string_id) const
#define CHECK_NE(x, y)
Definition: Logger.h:206
TargetValue getTargetValueFromBufferColwise(const int8_t *col_ptr, const int8_t *keys_ptr, const QueryMemoryDescriptor &query_mem_desc, const size_t local_entry_idx, const size_t global_entry_idx, const TargetInfo &target_info, const size_t target_logical_idx, const size_t slot_idx, const bool translate_strings, const bool decimal_to_double) const
static auto fetch(const SQLTypeInfo &geo_ti, const ResultSet::GeoReturnType return_type, Data_Namespace::DataMgr *data_mgr, const bool fetch_data_from_gpu, const int device_id, T &&... vals)
void copy_from_gpu(Data_Namespace::DataMgr *data_mgr, void *dst, const CUdeviceptr src, const size_t num_bytes, const int device_id)
StorageLookupResult findStorage(const size_t entry_idx) const
Definition: ResultSet.cpp:660
int64_t lazy_decode(const ColumnLazyFetchInfo &col_lazy_fetch, const int8_t *byte_stream, const int64_t pos)
TargetValue build_array_target_value(const SQLTypeInfo &array_ti, const int8_t *buff, const size_t buff_sz, const bool translate_strings, std::shared_ptr< RowSetMemoryOwner > row_set_mem_owner, const Catalog_Namespace::Catalog *catalog)
CountDistinctDescriptors count_distinct_descriptors_
Definition: sqldefs.h:75
bool is_distinct_target(const TargetInfo &target_info)
Definition: TargetInfo.h:130
boost::optional< std::vector< ScalarTargetValue > > ArrayTargetValue
Definition: TargetValue.h:157
#define EMPTY_KEY_8
bool isRowAtEmpty(const size_t index) const
const std::vector< ColumnLazyFetchInfo > lazy_fetch_info_
Definition: ResultSet.h:726
size_t getPaddedColWidthForRange(const size_t offset, const size_t range) const
size_t targetGroupbyIndicesSize() const
T row_ptr_rowwise(T buff, const QueryMemoryDescriptor &query_mem_desc, const size_t entry_idx)
SQLAgg agg_kind
Definition: TargetInfo.h:41
SQLTypes decimal_to_int_type(const SQLTypeInfo &ti)
Definition: Datum.cpp:303
size_t binSearchRowCount() const
#define UNLIKELY(x)
Definition: likely.h:25
int8_t groupColWidth(const size_t key_idx) const
int32_t getTargetIdxForKey() const
std::vector< TargetValue > getNextRow(const bool translate_strings, const bool decimal_to_double) const
#define CHECK_LT(x, y)
Definition: Logger.h:207
bool is_geometry() const
Definition: sqltypes.h:490
bool is_real_str_or_array(const TargetInfo &target_info)
ENTRY_TYPE getColumnarPerfectHashEntryAt(const size_t row_idx, const size_t target_idx, const size_t slot_idx) const
TargetValue getTargetValueFromBufferRowwise(int8_t *rowwise_target_ptr, int8_t *keys_ptr, const size_t entry_buff_idx, const TargetInfo &target_info, const size_t target_logical_idx, const size_t slot_idx, const bool translate_strings, const bool decimal_to_double, const bool fixup_count_distinct_pointers) const
#define CHECK_LE(x, y)
Definition: Logger.h:208
std::string get_type_name() const
Definition: sqltypes.h:414
int64_t int_resize_cast(const int64_t ival, const size_t sz)
int64_t getTargetGroupbyIndex(const size_t target_idx) const
int64_t lazyReadInt(const int64_t ival, const size_t target_logical_idx, const StorageLookupResult &storage_lookup_result) const
InternalTargetValue getColumnInternal(const int8_t *buff, const size_t entry_idx, const size_t target_logical_idx, const StorageLookupResult &storage_lookup_result) const
#define EMPTY_KEY_16
std::vector< std::vector< std::vector< const int8_t * > > > col_buffers_
Definition: ResultSet.h:727
#define DEF_GET_ENTRY_AT(query_type, columnar_output)
boost::variant< std::string, void * > NullableString
Definition: TargetValue.h:155
TargetValue makeTargetValue(const int8_t *ptr, const int8_t compact_sz, const TargetInfo &target_info, const size_t target_logical_idx, const bool translate_strings, const bool decimal_to_double, const size_t entry_buff_idx) const
static auto yieldGpuDatumFetcher(Data_Namespace::DataMgr *data_mgr_ptr, const int device_id)
const bool is_lazily_fetched
std::vector< std::vector< int64_t > > consistent_frag_sizes_
Definition: ResultSet.h:729
TargetValue makeVarlenTargetValue(const int8_t *ptr1, const int8_t compact_sz1, const int8_t *ptr2, const int8_t compact_sz2, const TargetInfo &target_info, const size_t target_logical_idx, const bool translate_strings, const size_t entry_buff_idx) const
const ExecutorDeviceType device_type_
Definition: ResultSet.h:704
ENTRY_TYPE getColumnarBaselineEntryAt(const size_t row_idx, const size_t target_idx, const size_t slot_idx) const
SQLTypeInfo get_elem_type() const
Definition: sqltypes.h:697
const int8_t * get_rowwise_ptr(const int8_t *buff, const size_t entry_idx) const
Definition: ResultSet.h:572
#define CHECK(condition)
Definition: Logger.h:197
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:311
#define EMPTY_KEY_32
bool isEmptyEntryColumnar(const size_t entry_idx, const int8_t *buff) const
uint64_t exp_to_scale(const unsigned exp)
size_t crt_row_buff_idx_
Definition: ResultSet.h:709
void copyColumnIntoBuffer(const size_t column_idx, int8_t *output_buffer, const size_t output_buffer_size) const
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
QueryDescriptionType
Definition: Types.h:26
const int8_t getLogicalSlotWidthBytes(const size_t slot_idx) const
std::vector< std::vector< std::vector< int64_t > > > frag_offsets_
Definition: ResultSet.h:728
Basic constructors and methods of the row set interface.
bool separate_varlen_storage_valid_
Definition: ResultSet.h:740
boost::variant< ScalarTargetValue, ArrayTargetValue, GeoTargetValue, GeoTargetValuePtr > TargetValue
Definition: TargetValue.h:167
TargetValue makeGeoTargetValue(const int8_t *geo_target_ptr, const size_t slot_idx, const TargetInfo &target_info, const size_t target_logical_idx, const size_t entry_buff_idx) const
size_t advanceCursorToNextEntry() const
const CountDistinctDescriptor & getCountDistinctDescriptor(const size_t idx) const
ENTRY_TYPE getEntryAt(const size_t row_idx, const size_t target_idx, const size_t slot_idx) const
T advance_target_ptr_col_wise(T target_ptr, const TargetInfo &target_info, const size_t slot_idx, const QueryMemoryDescriptor &query_mem_desc, const bool separate_varlen_storage)
ScalarTargetValue make_scalar_tv(const double val)
double calculate_quantile(int8_t const *ptr, double const q)
QueryDescriptionType getQueryDescriptionType() const
Definition: sqldefs.h:74
size_t crt_row_buff_idx_
Definition: ResultSet.h:124
std::vector< std::vector< TargetOffsets > > offsets_for_storage_
Definition: ResultSet.h:577
T get_cols_ptr(T buff, const QueryMemoryDescriptor &query_mem_desc)
Definition: sqldefs.h:72
bool global_entry_idx_valid_
Definition: ResultSet.h:126
std::unique_ptr< VarlenDatum > VarlenDatumPtr
bool isSingleColumnGroupByWithPerfectHash() const
#define IS_GEO(T)
Definition: sqltypes.h:242
size_t get_key_bytes_rowwise(const QueryMemoryDescriptor &query_mem_desc)
const int8_t * columnar_elem_ptr(const size_t entry_idx, const int8_t *col1_ptr, const int8_t compact_sz1)
FORCE_INLINE HOST DEVICE T align_to_int64(T addr)
size_t getPrependedGroupColOffInBytes(const size_t group_idx) const
std::pair< int64_t, int64_t > get_frag_id_and_local_idx(const std::vector< std::vector< T >> &frag_offsets, const size_t tab_or_col_idx, const int64_t global_idx)
std::unique_ptr< ArrayDatum > fetch_data_from_gpu(int64_t varlen_ptr, const int64_t length, Data_Namespace::DataMgr *data_mgr, const int device_id)
size_t getEffectiveKeyWidth() const
bool is_date_in_days() const
Definition: sqltypes.h:705
boost::variant< int64_t, double, float, NullableString > ScalarTargetValue
Definition: TargetValue.h:156
size_t length
Definition: sqltypes.h:142
const int device_id_
Definition: ResultSet.h:705