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