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