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