OmniSciDB  340b00dbf6
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JoinHashTableInterface.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019 MapD Technologies, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
18 
21 #include "QueryEngine/Execute.h"
27 
28 extern bool g_enable_overlaps_hashjoin;
29 
35  const Analyzer::ColumnVar* hash_col,
36  const std::vector<Fragmenter_Namespace::FragmentInfo>& fragment_info,
37  const Data_Namespace::MemoryLevel effective_memory_level,
38  const int device_id,
39  std::vector<std::shared_ptr<Chunk_NS::Chunk>>& chunks_owner,
40  DeviceAllocator* dev_buff_owner,
41  std::vector<std::shared_ptr<void>>& malloc_owner,
42  Executor* executor,
43  ColumnCacheMap* column_cache) {
44  static std::mutex fragment_fetch_mutex;
45  std::lock_guard<std::mutex> fragment_fetch_lock(fragment_fetch_mutex);
46  try {
47  JoinColumn join_column = ColumnFetcher::makeJoinColumn(executor,
48  *hash_col,
49  fragment_info,
50  effective_memory_level,
51  device_id,
52  dev_buff_owner,
53  chunks_owner,
54  malloc_owner,
55  *column_cache);
56  if (effective_memory_level == Data_Namespace::GPU_LEVEL) {
57  CHECK(dev_buff_owner);
58  auto device_col_chunks_buff = dev_buff_owner->alloc(join_column.col_chunks_buff_sz);
59  dev_buff_owner->copyToDevice(device_col_chunks_buff,
60  join_column.col_chunks_buff,
61  join_column.col_chunks_buff_sz);
62  join_column.col_chunks_buff = device_col_chunks_buff;
63  }
64  return join_column;
65  } catch (...) {
66  throw FailedToFetchColumn();
67  }
68 }
69 
70 namespace {
71 
72 template <typename T>
73 void innerToString(const int8_t* ptr1,
74  size_t entry_count,
75  size_t key_component_count,
76  bool raw,
77  std::string& txt) {
78  auto empty = get_empty_key<T>();
79  auto ptr = reinterpret_cast<const T*>(ptr1);
80  for (size_t e = 0; e < entry_count; ++e, ptr += key_component_count) {
81  if (e != 0) {
82  txt += " ";
83  }
84  if (*ptr == empty && !raw) {
85  txt += "*"; // null hash table entry
86  } else if (*ptr == empty - 1 && !raw) {
87  txt += "?"; // write_pending (should never happen here)
88  } else {
89  txt += "(";
90  for (size_t j = 0; j < key_component_count; ++j) {
91  if (j != 0) {
92  txt += ",";
93  }
94  txt += std::to_string(ptr[j]);
95  }
96  txt += ")";
97  }
98  }
99 }
100 
101 } // anonymous namespace
102 
105  const std::string& type, // perfect, keyed, or geo
106  const std::string& layout_type, // one-to-one, one-to-many, many-to-many
107  size_t key_component_count, // number of key parts
108  size_t key_component_width, // width of a key part
109  size_t entry_count, // number of hashable entries
110  const int8_t* ptr1, // keys
111  const int8_t* ptr2, // offsets
112  const int8_t* ptr3, // counts
113  const int8_t* ptr4, // payloads (rowids)
114  size_t buffer_size, // total memory size
115  bool raw) {
116  std::string txt;
117 
118  CHECK(ptr1 <= ptr2);
119  CHECK(ptr2 <= ptr3);
120  CHECK(ptr3 <= ptr4);
121  CHECK(ptr4 <= ptr1 + buffer_size);
122 
123  bool have_keys = ptr2 > ptr1;
124  bool have_offsets = ptr3 > ptr2;
125  bool have_counts = ptr4 > ptr3;
126  bool have_payloads = (ptr1 + buffer_size) > ptr4;
127 
128  // table heading
129  txt += "| " + type;
130  if (!have_offsets && !have_counts) {
131  txt += layout_type;
132  } else if (have_offsets && have_counts) {
133  txt += layout_type;
134  } else {
135  CHECK(false);
136  }
137 
138  // first section: keys
139  if (have_keys) {
140  CHECK(key_component_width == 8 || key_component_width == 4);
141 
142  if (!txt.empty()) {
143  txt += " ";
144  }
145  txt += "| keys ";
146 
147  if (key_component_width == 8) {
148  innerToString<int64_t>(ptr1, entry_count, key_component_count, raw, txt);
149  } else if (key_component_width == 4) {
150  innerToString<int32_t>(ptr1, entry_count, key_component_count, raw, txt);
151  }
152  }
153 
154  // second section: offsets
155  if (have_offsets) {
156  if (!txt.empty()) {
157  txt += " ";
158  }
159  txt += "| offsets ";
160 
161  auto i32ptr2 = reinterpret_cast<const int32_t*>(ptr2);
162  auto i32ptr3 = reinterpret_cast<const int32_t*>(ptr3);
163  for (size_t i = 0; &i32ptr2[i] < i32ptr3; ++i) {
164  if (i != 0) {
165  txt += " ";
166  }
167  if (i32ptr2[i] == -1 && !raw) {
168  txt += "*"; // null
169  } else {
170  txt += std::to_string(i32ptr2[i]);
171  }
172  }
173  }
174 
175  // third section: counts
176  if (have_counts) {
177  if (!txt.empty()) {
178  txt += " ";
179  }
180  txt += "| counts ";
181 
182  auto i32ptr3 = reinterpret_cast<const int32_t*>(ptr3);
183  auto i32ptr4 = reinterpret_cast<const int32_t*>(ptr4);
184  for (size_t i = 0; &i32ptr3[i] < i32ptr4; ++i) {
185  if (i != 0) {
186  txt += " ";
187  }
188  if (i32ptr3[i] == 0 && !raw) {
189  txt += "*"; // null
190  } else {
191  txt += std::to_string(i32ptr3[i]);
192  }
193  }
194  }
195 
196  // fourth section: payloads (rowids)
197  if (have_payloads) {
198  if (!txt.empty()) {
199  txt += " ";
200  }
201  txt += "| payloads ";
202 
203  auto i32ptr4 = reinterpret_cast<const int32_t*>(ptr4);
204  auto i32ptr5 = reinterpret_cast<const int32_t*>(ptr1 + buffer_size);
205  for (size_t i = 0; &i32ptr4[i] < i32ptr5; ++i) {
206  if (i != 0) {
207  txt += " ";
208  }
209  if (i32ptr4[i] == -1 && !raw) {
210  txt += "*"; // null
211  } else {
212  txt += std::to_string(i32ptr4[i]);
213  }
214  }
215  }
216 
217  if (!txt.empty()) {
218  txt += " |";
219  }
220  return txt;
221 }
222 
223 namespace {
224 
225 template <typename T>
226 std::string toStringFlat(const JoinHashTableInterface* hash_table,
227  const ExecutorDeviceType device_type,
228  const int device_id) {
229  auto mem =
230  reinterpret_cast<const T*>(hash_table->getJoinHashBuffer(device_type, device_id));
231  auto memsz = hash_table->getJoinHashBufferSize(device_type, device_id) / sizeof(T);
232  std::string txt;
233  for (size_t i = 0; i < memsz; ++i) {
234  if (i > 0) {
235  txt += ", ";
236  }
237  txt += std::to_string(mem[i]);
238  }
239  return txt;
240 }
241 
242 } // anonymous namespace
243 
245  const int device_id) const {
246  return toStringFlat<int64_t>(this, device_type, device_id);
247 }
248 
250  const int device_id) const {
251  return toStringFlat<int32_t>(this, device_type, device_id);
252 }
253 
254 std::ostream& operator<<(std::ostream& os, const DecodedJoinHashBufferEntry& e) {
255  os << " {{";
256  bool first = true;
257  for (auto k : e.key) {
258  if (!first) {
259  os << ",";
260  } else {
261  first = false;
262  }
263  os << k;
264  }
265  os << "}, ";
266  os << "{";
267  first = true;
268  for (auto p : e.payload) {
269  if (!first) {
270  os << ", ";
271  } else {
272  first = false;
273  }
274  os << p;
275  }
276  os << "}}";
277  return os;
278 }
279 
280 std::ostream& operator<<(std::ostream& os, const DecodedJoinHashBufferSet& s) {
281  os << "{\n";
282  bool first = true;
283  for (auto e : s) {
284  if (!first) {
285  os << ",\n";
286  } else {
287  first = false;
288  }
289  os << e;
290  }
291  if (!s.empty()) {
292  os << "\n";
293  }
294  os << "}\n";
295  return os;
296 }
297 
298 namespace {
299 
300 namespace perfect_hash {
301 
302 void to_set_one_to_one(const int32_t* const ptr4,
303  size_t entry_count,
305  const auto empty = -1;
306  auto ptr = ptr4;
307  for (size_t e = 0; e < entry_count; ++e, ++ptr) {
308  if (*ptr == empty) {
309  continue;
310  }
311 
312  decltype(DecodedJoinHashBufferEntry::key) key;
313  key.push_back(e);
314 
315  decltype(DecodedJoinHashBufferEntry::payload) payload;
316  payload.insert(*ptr);
317 
318  s.insert({std::move(key), std::move(payload)});
319  }
320 }
321 
322 void to_set_one_to_many(const int32_t* const ptr2,
323  const int32_t* const ptr3,
324  const int32_t* const ptr4,
325  size_t entry_count,
327  auto empty = -1;
328  auto ptr = ptr2;
329  for (size_t e = 0; e < entry_count; ++e, ++ptr) {
330  if (*ptr == empty) {
331  continue;
332  }
333 
334  decltype(DecodedJoinHashBufferEntry::key) key;
335  key.push_back(e);
336 
337  int32_t offset = ptr2[e];
338 
339  int32_t count = ptr3[e];
340 
341  decltype(DecodedJoinHashBufferEntry::payload) payload;
342  for (size_t j = 0; j < static_cast<size_t>(count); ++j) {
343  payload.insert(ptr4[offset + j]);
344  }
345 
346  s.insert({std::move(key), std::move(payload)});
347  }
348 }
349 
350 } // namespace perfect_hash
351 
352 namespace keyed_hash {
353 
354 template <typename T>
355 void to_set_one_to_one(const int8_t* ptr1,
356  size_t entry_count,
357  size_t key_component_count,
359  auto empty = get_empty_key<T>();
360  auto ptr = reinterpret_cast<const T*>(ptr1);
361  for (size_t e = 0; e < entry_count; ++e, ptr += key_component_count) {
362  if (*ptr == empty) {
363  continue;
364  }
365 
366  std::vector<int64_t> key;
367  size_t j = 0;
368  for (; j < key_component_count - 1; ++j) {
369  key.push_back(ptr[j]);
370  }
371 
372  std::set<int32_t> payload;
373  payload.insert(ptr[j]);
374 
375  s.insert({std::move(key), std::move(payload)});
376  }
377 }
378 
379 template <typename T>
380 void to_set_one_to_many(const int8_t* ptr1,
381  const int32_t* const ptr2,
382  const int32_t* const ptr3,
383  const int32_t* const ptr4,
384  size_t entry_count,
385  size_t key_component_count,
387  auto empty = get_empty_key<T>();
388  auto ptr = reinterpret_cast<const T*>(ptr1);
389  for (size_t e = 0; e < entry_count; ++e, ptr += key_component_count) {
390  if (*ptr == empty) {
391  continue;
392  }
393 
394  std::vector<int64_t> key;
395  size_t j = 0;
396  for (; j < key_component_count - 1; ++j) {
397  key.push_back(ptr[j]);
398  }
399 
400  int32_t offset = ptr2[e];
401 
402  int32_t count = ptr3[e];
403 
404  decltype(DecodedJoinHashBufferEntry::payload) payload;
405  for (size_t j = 0; j < static_cast<size_t>(count); ++j) {
406  payload.insert(ptr4[offset + j]);
407  }
408 
409  s.insert({std::move(key), std::move(payload)});
410  }
411 }
412 
413 } // namespace keyed_hash
414 
415 } // anonymous namespace
416 
419  size_t key_component_count, // number of key parts
420  size_t key_component_width, // width of a key part
421  size_t entry_count, // number of hashable entries
422  const int8_t* ptr1, // keys
423  const int8_t* ptr2, // offsets
424  const int8_t* ptr3, // counts
425  const int8_t* ptr4, // payloads (rowids)
426  size_t buffer_size) { // total memory size
428 
429  CHECK_LE(ptr1, ptr2);
430  CHECK_LE(ptr2, ptr3);
431  CHECK_LE(ptr3, ptr4);
432  CHECK_LE(ptr4, ptr1 + buffer_size);
433 
434  bool have_keys = ptr2 > ptr1;
435  bool have_offsets = ptr3 > ptr2;
436  bool have_counts = ptr4 > ptr3;
437  bool have_payloads = (ptr1 + buffer_size) > ptr4;
438 
439  auto i32ptr2 = reinterpret_cast<const int32_t*>(ptr2);
440  auto i32ptr3 = reinterpret_cast<const int32_t*>(ptr3);
441  auto i32ptr4 = reinterpret_cast<const int32_t*>(ptr4);
442 
443  if (have_keys) { // BaselineJoinHashTable or OverlapsJoinHashTable
444  CHECK(key_component_width == 8 || key_component_width == 4);
445  if (key_component_width == 8) {
446  if (!have_offsets && !have_counts) {
447  keyed_hash::to_set_one_to_one<int64_t>(ptr1, entry_count, key_component_count, s);
448  } else {
449  keyed_hash::to_set_one_to_many<int64_t>(
450  ptr1, i32ptr2, i32ptr3, i32ptr4, entry_count, key_component_count, s);
451  }
452  } else if (key_component_width == 4) {
453  if (!have_offsets && !have_counts) {
454  keyed_hash::to_set_one_to_one<int32_t>(ptr1, entry_count, key_component_count, s);
455  } else {
456  keyed_hash::to_set_one_to_many<int32_t>(
457  ptr1, i32ptr2, i32ptr3, i32ptr4, entry_count, key_component_count, s);
458  }
459  }
460  } else { // JoinHashTable
461  if (!have_offsets && !have_counts && have_payloads) {
462  perfect_hash::to_set_one_to_one(i32ptr4, entry_count, s);
463  } else {
464  perfect_hash::to_set_one_to_many(i32ptr2, i32ptr3, i32ptr4, entry_count, s);
465  }
466  }
467 
468  return s;
469 }
470 
472 std::shared_ptr<JoinHashTableInterface> JoinHashTableInterface::getInstance(
473  const std::shared_ptr<Analyzer::BinOper> qual_bin_oper,
474  const std::vector<InputTableInfo>& query_infos,
475  const Data_Namespace::MemoryLevel memory_level,
476  const HashType preferred_hash_type,
477  const int device_count,
478  ColumnCacheMap& column_cache,
479  Executor* executor) {
480  auto timer = DEBUG_TIMER(__func__);
481  std::shared_ptr<JoinHashTableInterface> join_hash_table;
482  CHECK_GT(device_count, 0);
483  if (!g_enable_overlaps_hashjoin && qual_bin_oper->is_overlaps_oper()) {
484  throw std::runtime_error(
485  "Overlaps hash join disabled, attempting to fall back to loop join");
486  }
487  if (qual_bin_oper->is_overlaps_oper()) {
488  VLOG(1) << "Trying to build geo hash table:";
489  join_hash_table = OverlapsJoinHashTable::getInstance(
490  qual_bin_oper, query_infos, memory_level, device_count, column_cache, executor);
491  } else if (dynamic_cast<const Analyzer::ExpressionTuple*>(
492  qual_bin_oper->get_left_operand())) {
493  VLOG(1) << "Trying to build keyed hash table:";
494  join_hash_table = BaselineJoinHashTable::getInstance(qual_bin_oper,
495  query_infos,
496  memory_level,
497  preferred_hash_type,
498  device_count,
499  column_cache,
500  executor);
501  } else {
502  try {
503  VLOG(1) << "Trying to build perfect hash table:";
504  join_hash_table = JoinHashTable::getInstance(qual_bin_oper,
505  query_infos,
506  memory_level,
507  preferred_hash_type,
508  device_count,
509  column_cache,
510  executor);
511  } catch (TooManyHashEntries&) {
512  const auto join_quals = coalesce_singleton_equi_join(qual_bin_oper);
513  CHECK_EQ(join_quals.size(), size_t(1));
514  const auto join_qual =
515  std::dynamic_pointer_cast<Analyzer::BinOper>(join_quals.front());
516  VLOG(1) << "Trying to build keyed hash table after perfect hash table:";
517  join_hash_table = BaselineJoinHashTable::getInstance(join_qual,
518  query_infos,
519  memory_level,
520  preferred_hash_type,
521  device_count,
522  column_cache,
523  executor);
524  }
525  }
526  CHECK(join_hash_table);
527  if (VLOGGING(2)) {
528  if (join_hash_table->getMemoryLevel() == Data_Namespace::MemoryLevel::GPU_LEVEL) {
529  for (int device_id = 0; device_id < join_hash_table->getDeviceCount();
530  ++device_id) {
531  if (join_hash_table->getJoinHashBufferSize(ExecutorDeviceType::GPU, device_id) <=
532  1000) {
533  VLOG(2) << "Built GPU hash table: "
534  << join_hash_table->toString(ExecutorDeviceType::GPU, device_id);
535  }
536  }
537  } else {
538  if (join_hash_table->getJoinHashBufferSize(ExecutorDeviceType::CPU) <= 1000) {
539  VLOG(2) << "Built CPU hash table: "
540  << join_hash_table->toString(ExecutorDeviceType::CPU);
541  }
542  }
543  }
544  return join_hash_table;
545 }
546 
547 std::shared_ptr<Analyzer::ColumnVar> getSyntheticColumnVar(std::string_view table,
548  std::string_view column,
549  int rte_idx,
550  Executor* executor) {
551  auto catalog = executor->getCatalog();
552  CHECK(catalog);
553 
554  auto tmeta = catalog->getMetadataForTable(std::string(table));
555  CHECK(tmeta);
556 
557  auto cmeta = catalog->getMetadataForColumn(tmeta->tableId, std::string(column));
558  CHECK(cmeta);
559 
560  auto ti = cmeta->columnType;
561 
562  if (ti.is_geometry() && ti.get_type() != kPOINT) {
563  int geoColumnId{0};
564  switch (ti.get_type()) {
565  case kLINESTRING: {
566  geoColumnId = cmeta->columnId + 2;
567  break;
568  }
569  case kPOLYGON: {
570  geoColumnId = cmeta->columnId + 3;
571  break;
572  }
573  case kMULTIPOLYGON: {
574  geoColumnId = cmeta->columnId + 4;
575  break;
576  }
577  default:
578  CHECK(false);
579  }
580  cmeta = catalog->getMetadataForColumn(tmeta->tableId, geoColumnId);
581  CHECK(cmeta);
582  ti = cmeta->columnType;
583  }
584 
585  auto cv =
586  std::make_shared<Analyzer::ColumnVar>(ti, tmeta->tableId, cmeta->columnId, rte_idx);
587  return cv;
588 }
589 
591  : public ScalarExprVisitor<std::set<const Analyzer::ColumnVar*>> {
592  protected:
593  std::set<const Analyzer::ColumnVar*> visitColumnVar(
594  const Analyzer::ColumnVar* column) const override {
595  return {column};
596  }
597 
598  std::set<const Analyzer::ColumnVar*> visitColumnVarTuple(
599  const Analyzer::ExpressionTuple* expr_tuple) const override {
600  AllColumnVarsVisitor visitor;
601  std::set<const Analyzer::ColumnVar*> result;
602  for (const auto& expr_component : expr_tuple->getTuple()) {
603  const auto component_rte_set = visitor.visit(expr_component.get());
604  result.insert(component_rte_set.begin(), component_rte_set.end());
605  }
606  return result;
607  }
608 
609  std::set<const Analyzer::ColumnVar*> aggregateResult(
610  const std::set<const Analyzer::ColumnVar*>& aggregate,
611  const std::set<const Analyzer::ColumnVar*>& next_result) const override {
612  auto result = aggregate;
613  result.insert(next_result.begin(), next_result.end());
614  return result;
615  }
616 };
617 
618 void setupSyntheticCaching(std::set<const Analyzer::ColumnVar*> cvs, Executor* executor) {
619  std::unordered_set<int> phys_table_ids;
620  for (auto cv : cvs) {
621  phys_table_ids.insert(cv->get_table_id());
622  }
623 
624  std::unordered_set<PhysicalInput> phys_inputs;
625  for (auto cv : cvs) {
626  phys_inputs.emplace(PhysicalInput{cv->get_column_id(), cv->get_table_id()});
627  }
628 
629  executor->setupCaching(phys_inputs, phys_table_ids);
630 }
631 
632 std::vector<InputTableInfo> getSyntheticInputTableInfo(
633  std::set<const Analyzer::ColumnVar*> cvs,
634  Executor* executor) {
635  auto catalog = executor->getCatalog();
636  CHECK(catalog);
637 
638  std::unordered_set<int> phys_table_ids;
639  for (auto cv : cvs) {
640  phys_table_ids.insert(cv->get_table_id());
641  }
642 
643  // NOTE(sy): This vector ordering seems to work for now, but maybe we need to
644  // review how rte_idx is assigned for ColumnVars. See for example Analyzer.h
645  // and RelAlgExecutor.cpp and rte_idx there.
646  std::vector<InputTableInfo> query_infos(phys_table_ids.size());
647  size_t i = 0;
648  for (auto id : phys_table_ids) {
649  auto tmeta = catalog->getMetadataForTable(id);
650  query_infos[i].table_id = id;
651  query_infos[i].info = tmeta->fragmenter->getFragmentsForQuery();
652  ++i;
653  }
654 
655  return query_infos;
656 }
657 
659 std::shared_ptr<JoinHashTableInterface> JoinHashTableInterface::getSyntheticInstance(
660  std::string_view table1,
661  std::string_view column1,
662  std::string_view table2,
663  std::string_view column2,
664  const Data_Namespace::MemoryLevel memory_level,
665  const HashType preferred_hash_type,
666  const int device_count,
667  ColumnCacheMap& column_cache,
668  Executor* executor) {
669  auto a1 = getSyntheticColumnVar(table1, column1, 0, executor);
670  auto a2 = getSyntheticColumnVar(table2, column2, 1, executor);
671 
672  auto qual_bin_oper = std::make_shared<Analyzer::BinOper>(kBOOLEAN, kEQ, kONE, a1, a2);
673 
674  std::set<const Analyzer::ColumnVar*> cvs =
675  AllColumnVarsVisitor().visit(qual_bin_oper.get());
676  auto query_infos = getSyntheticInputTableInfo(cvs, executor);
677  setupSyntheticCaching(cvs, executor);
678 
679  auto hash_table = JoinHashTableInterface::getInstance(qual_bin_oper,
680  query_infos,
681  memory_level,
682  preferred_hash_type,
683  device_count,
684  column_cache,
685  executor);
686  return hash_table;
687 }
688 
690 std::shared_ptr<JoinHashTableInterface> JoinHashTableInterface::getSyntheticInstance(
691  const std::shared_ptr<Analyzer::BinOper> qual_bin_oper,
692  const Data_Namespace::MemoryLevel memory_level,
693  const HashType preferred_hash_type,
694  const int device_count,
695  ColumnCacheMap& column_cache,
696  Executor* executor) {
697  std::set<const Analyzer::ColumnVar*> cvs =
698  AllColumnVarsVisitor().visit(qual_bin_oper.get());
699  auto query_infos = getSyntheticInputTableInfo(cvs, executor);
700  setupSyntheticCaching(cvs, executor);
701 
702  auto hash_table = JoinHashTableInterface::getInstance(qual_bin_oper,
703  query_infos,
704  memory_level,
705  preferred_hash_type,
706  device_count,
707  column_cache,
708  executor);
709  return hash_table;
710 }
std::vector< InputTableInfo > getSyntheticInputTableInfo(std::set< const Analyzer::ColumnVar * > cvs, Executor *executor)
std::string toStringFlat(const JoinHashTableInterface *hash_table, const ExecutorDeviceType device_type, const int device_id)
#define CHECK_EQ(x, y)
Definition: Logger.h:205
virtual int64_t getJoinHashBuffer(const ExecutorDeviceType device_type, const int device_id=0) const noexcept=0
void to_set_one_to_many(const int32_t *const ptr2, const int32_t *const ptr3, const int32_t *const ptr4, size_t entry_count, DecodedJoinHashBufferSet &s)
void to_set_one_to_one(const int32_t *const ptr4, size_t entry_count, DecodedJoinHashBufferSet &s)
std::shared_ptr< Analyzer::ColumnVar > getSyntheticColumnVar(std::string_view table, std::string_view column, int rte_idx, Executor *executor)
ExecutorDeviceType
static std::shared_ptr< JoinHashTableInterface > getSyntheticInstance(std::string_view table1, std::string_view column1, std::string_view table2, std::string_view column2, const Data_Namespace::MemoryLevel memory_level, const HashType preferred_hash_type, const int device_count, ColumnCacheMap &column_cache, Executor *executor)
Make hash table from named tables and columns (such as for testing).
std::list< std::shared_ptr< Analyzer::Expr > > coalesce_singleton_equi_join(const std::shared_ptr< Analyzer::BinOper > &join_qual)
static std::shared_ptr< OverlapsJoinHashTable > getInstance(const std::shared_ptr< Analyzer::BinOper > condition, const std::vector< InputTableInfo > &query_infos, const Data_Namespace::MemoryLevel memory_level, const int device_count, ColumnCacheMap &column_cache, Executor *executor)
Make hash table from an in-flight SQL query&#39;s parse tree etc.
std::ostream & operator<<(std::ostream &os, const SessionInfo &session_info)
Definition: SessionInfo.cpp:53
std::set< const Analyzer::ColumnVar * > aggregateResult(const std::set< const Analyzer::ColumnVar * > &aggregate, const std::set< const Analyzer::ColumnVar * > &next_result) const override
virtual void copyToDevice(int8_t *device_dst, const int8_t *host_src, const size_t num_bytes) const =0
Definition: sqldefs.h:30
virtual int8_t * alloc(const size_t num_bytes)=0
std::set< DecodedJoinHashBufferEntry > DecodedJoinHashBufferSet
T visit(const Analyzer::Expr *expr) const
#define CHECK_GT(x, y)
Definition: Logger.h:209
static std::shared_ptr< BaselineJoinHashTable > getInstance(const std::shared_ptr< Analyzer::BinOper > condition, const std::vector< InputTableInfo > &query_infos, const Data_Namespace::MemoryLevel memory_level, const HashType preferred_hash_type, const int device_count, ColumnCacheMap &column_cache, Executor *executor)
Make hash table from an in-flight SQL query&#39;s parse tree etc.
static JoinColumn makeJoinColumn(Executor *executor, const Analyzer::ColumnVar &hash_col, const std::vector< Fragmenter_Namespace::FragmentInfo > &fragments, const Data_Namespace::MemoryLevel effective_mem_lvl, const int device_id, DeviceAllocator *device_allocator, std::vector< std::shared_ptr< Chunk_NS::Chunk >> &chunks_owner, std::vector< std::shared_ptr< void >> &malloc_owner, ColumnCacheMap &column_cache)
Creates a JoinColumn struct containing an array of JoinChunk structs.
std::string to_string(char const *&&v)
bool g_enable_overlaps_hashjoin
Definition: Execute.cpp:91
size_t col_chunks_buff_sz
const std::vector< std::shared_ptr< Analyzer::Expr > > & getTuple() const
Definition: Analyzer.h:244
static std::shared_ptr< JoinHashTable > getInstance(const std::shared_ptr< Analyzer::BinOper > qual_bin_oper, const std::vector< InputTableInfo > &query_infos, const Data_Namespace::MemoryLevel memory_level, const HashType preferred_hash_type, const int device_count, ColumnCacheMap &column_cache, Executor *executor)
Make hash table from an in-flight SQL query&#39;s parse tree etc.
const int8_t * col_chunks_buff
std::unordered_map< int, std::unordered_map< int, std::shared_ptr< const ColumnarResults >>> ColumnCacheMap
#define VLOGGING(n)
Definition: Logger.h:195
static std::shared_ptr< JoinHashTableInterface > getInstance(const std::shared_ptr< Analyzer::BinOper > qual_bin_oper, const std::vector< InputTableInfo > &query_infos, const Data_Namespace::MemoryLevel memory_level, const HashType preferred_hash_type, const int device_count, ColumnCacheMap &column_cache, Executor *executor)
Make hash table from an in-flight SQL query&#39;s parse tree etc.
Definition: sqldefs.h:69
#define CHECK_LE(x, y)
Definition: Logger.h:208
std::set< const Analyzer::ColumnVar * > visitColumnVarTuple(const Analyzer::ExpressionTuple *expr_tuple) const override
JoinColumn fetchJoinColumn(const Analyzer::ColumnVar *hash_col, const std::vector< Fragmenter_Namespace::FragmentInfo > &fragment_info, const Data_Namespace::MemoryLevel effective_memory_level, const int device_id, std::vector< std::shared_ptr< Chunk_NS::Chunk >> &chunks_owner, DeviceAllocator *dev_buff_owner, std::vector< std::shared_ptr< void >> &malloc_owner, Executor *executor, ColumnCacheMap *column_cache)
void innerToString(const int8_t *ptr1, size_t entry_count, size_t key_component_count, bool raw, std::string &txt)
virtual DecodedJoinHashBufferSet toSet(const ExecutorDeviceType device_type, const int device_id) const =0
std::set< const Analyzer::ColumnVar * > visitColumnVar(const Analyzer::ColumnVar *column) const override
virtual std::string toStringFlat32(const ExecutorDeviceType device_type, const int device_id) const
virtual size_t getJoinHashBufferSize(const ExecutorDeviceType device_type, const int device_id=0) const noexcept=0
#define CHECK(condition)
Definition: Logger.h:197
std::set< int32_t > payload
#define DEBUG_TIMER(name)
Definition: Logger.h:313
void setupSyntheticCaching(std::set< const Analyzer::ColumnVar * > cvs, Executor *executor)
virtual std::string toStringFlat64(const ExecutorDeviceType device_type, const int device_id) const
std::vector< int64_t > key
virtual std::string toString(const ExecutorDeviceType device_type, const int device_id=0, bool raw=false) const =0
#define VLOG(n)
Definition: Logger.h:291