OmniSciDB  c1a53651b2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RangeJoinHashTable Class Referencefinal

#include <RangeJoinHashTable.h>

+ Inheritance diagram for RangeJoinHashTable:
+ Collaboration diagram for RangeJoinHashTable:

Public Member Functions

 RangeJoinHashTable (const std::shared_ptr< Analyzer::BinOper > condition, const JoinType join_type, const Analyzer::RangeOper *range_expr, std::shared_ptr< Analyzer::ColumnVar > inner_col_expr, const std::vector< InputTableInfo > &query_infos, const Data_Namespace::MemoryLevel memory_level, ColumnCacheMap &column_cache, Executor *executor, const std::vector< InnerOuter > &inner_outer_pairs, const int device_count, const RegisteredQueryHint &query_hints, const HashTableBuildDagMap &hashtable_build_dag_map, const TableIdToNodeMap &table_id_to_node_map)
 
 ~RangeJoinHashTable () override=default
 
llvm::Value * codegenKey (const CompilationOptions &co, llvm::Value *offset)
 
HashJoinMatchingSet codegenMatchingSetWithOffset (const CompilationOptions &, const size_t, llvm::Value *)
 
- Public Member Functions inherited from OverlapsJoinHashTable
 OverlapsJoinHashTable (const std::shared_ptr< Analyzer::BinOper > condition, const JoinType join_type, const std::vector< InputTableInfo > &query_infos, const Data_Namespace::MemoryLevel memory_level, ColumnCacheMap &column_cache, Executor *executor, const std::vector< InnerOuter > &inner_outer_pairs, const int device_count, const RegisteredQueryHint &query_hints, const HashTableBuildDagMap &hashtable_build_dag_map, const TableIdToNodeMap &table_id_to_node_map)
 
virtual ~OverlapsJoinHashTable ()
 
- Public Member Functions inherited from HashJoin
virtual std::string toStringFlat64 (const ExecutorDeviceType device_type, const int device_id) const
 
virtual std::string toStringFlat32 (const ExecutorDeviceType device_type, const int device_id) const
 
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)
 
HashTablegetHashTableForDevice (const size_t device_id) const
 
size_t getJoinHashBufferSize (const ExecutorDeviceType device_type)
 
size_t getJoinHashBufferSize (const ExecutorDeviceType device_type, const int device_id) const
 
int8_t * getJoinHashBuffer (const ExecutorDeviceType device_type, const int device_id) const
 
void freeHashBufferMemory ()
 

Static Public Member Functions

static std::shared_ptr
< RangeJoinHashTable
getInstance (const std::shared_ptr< Analyzer::BinOper > condition, const Analyzer::RangeOper *range_expr, const std::vector< InputTableInfo > &query_infos, const Data_Namespace::MemoryLevel memory_level, const JoinType join_type, const int device_count, ColumnCacheMap &column_cache, Executor *executor, const HashTableBuildDagMap &hashtable_build_dag_map, const RegisteredQueryHint &query_hints, const TableIdToNodeMap &table_id_to_node_map)
 
- Static Public Member Functions inherited from OverlapsJoinHashTable
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 JoinType join_type, const int device_count, ColumnCacheMap &column_cache, Executor *executor, const HashTableBuildDagMap &hashtable_build_dag_map, const RegisteredQueryHint &query_hint, const TableIdToNodeMap &table_id_to_node_map)
 Make hash table from an in-flight SQL query's parse tree etc. More...
 
static void invalidateCache ()
 
static void markCachedItemAsDirty (size_t table_key)
 
static HashtableRecyclergetHashTableCache ()
 
static
OverlapsTuningParamRecycler
getOverlapsTuningParamCache ()
 
- Static Public Member Functions inherited from HashJoin
static bool layoutRequiresAdditionalBuffers (HashType layout) noexcept
 
static std::string getHashTypeString (HashType ht) noexcept
 
static HashJoinMatchingSet codegenMatchingSet (const std::vector< llvm::Value * > &hash_join_idx_args_in, const bool is_sharded, const bool col_is_nullable, const bool is_bw_eq, const int64_t sub_buff_size, Executor *executor, const bool is_bucketized=false)
 
static llvm::Value * codegenHashTableLoad (const size_t table_idx, Executor *executor)
 
static std::shared_ptr< HashJoingetInstance (const std::shared_ptr< Analyzer::BinOper > qual_bin_oper, const std::vector< InputTableInfo > &query_infos, const Data_Namespace::MemoryLevel memory_level, const JoinType join_type, const HashType preferred_hash_type, const int device_count, ColumnCacheMap &column_cache, Executor *executor, const HashTableBuildDagMap &hashtable_build_dag_map, const RegisteredQueryHint &query_hint, const TableIdToNodeMap &table_id_to_node_map)
 Make hash table from an in-flight SQL query's parse tree etc. More...
 
static std::shared_ptr< HashJoingetSyntheticInstance (std::string_view table1, std::string_view column1, const Catalog_Namespace::Catalog &catalog1, std::string_view table2, std::string_view column2, const Catalog_Namespace::Catalog &catalog2, 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). More...
 
static std::shared_ptr< HashJoingetSyntheticInstance (const std::shared_ptr< Analyzer::BinOper > qual_bin_oper, 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). More...
 
static std::pair< std::string,
std::shared_ptr< HashJoin > > 
getSyntheticInstance (std::vector< std::shared_ptr< Analyzer::BinOper >>, const Data_Namespace::MemoryLevel memory_level, const HashType preferred_hash_type, const int device_count, ColumnCacheMap &column_cache, Executor *executor)
 
static shared::TableKey getInnerTableId (const std::vector< InnerOuter > &inner_outer_pairs)
 
static bool canAccessHashTable (bool allow_hash_table_recycling, bool invalid_cache_key, JoinType join_type)
 
static void checkHashJoinReplicationConstraint (const shared::TableKey &table_key, const size_t shard_count, const Executor *executor)
 
static std::pair< InnerOuter,
InnerOuterStringOpInfos
normalizeColumnPair (const Analyzer::Expr *lhs, const Analyzer::Expr *rhs, const TemporaryTables *temporary_tables, const bool is_overlaps_join=false)
 
template<typename T >
static const T * getHashJoinColumn (const Analyzer::Expr *expr)
 
static std::pair< std::vector
< InnerOuter >, std::vector
< InnerOuterStringOpInfos > > 
normalizeColumnPairs (const Analyzer::BinOper *condition, const TemporaryTables *temporary_tables)
 
static std::vector< int > collectFragmentIds (const std::vector< Fragmenter_Namespace::FragmentInfo > &fragments)
 
static CompositeKeyInfo getCompositeKeyInfo (const std::vector< InnerOuter > &inner_outer_pairs, const Executor *executor, const std::vector< InnerOuterStringOpInfos > &inner_outer_string_op_infos_pairs={})
 
static std::vector< const
StringDictionaryProxy::IdMap * > 
translateCompositeStrDictProxies (const CompositeKeyInfo &composite_key_info, const std::vector< InnerOuterStringOpInfos > &string_op_infos_for_keys, const Executor *executor)
 
static std::pair< const
StringDictionaryProxy
*, StringDictionaryProxy * > 
getStrDictProxies (const InnerOuter &cols, const Executor *executor, const bool has_string_ops)
 
static const
StringDictionaryProxy::IdMap
translateInnerToOuterStrDictProxies (const InnerOuter &cols, const InnerOuterStringOpInfos &inner_outer_string_op_infos, ExpressionRange &old_col_range, const Executor *executor)
 

Protected Member Functions

void reifyWithLayout (const HashType layout) override
 
void reifyForDevice (const ColumnsForDevice &columns_for_device, const HashType layout, const size_t entry_count, const size_t emitted_keys_count, const int device_id, const logger::ThreadLocalIds parent_thread_local_ids)
 
std::shared_ptr
< BaselineHashTable
initHashTableOnCpu (const std::vector< JoinColumn > &join_columns, const std::vector< JoinColumnTypeInfo > &join_column_types, const std::vector< JoinBucketInfo > &join_bucket_info, const HashType layout, const size_t entry_count, const size_t emitted_keys_count)
 
HashType getHashType () const noexceptoverride
 
std::pair< size_t, size_t > approximateTupleCount (const std::vector< double > &inverse_bucket_sizes_for_dimension, std::vector< ColumnsForDevice > &columns_per_device, const size_t chosen_max_hashtable_size, const double chosen_bucket_threshold) override
 
std::pair< size_t, size_t > computeRangeHashTableCounts (const size_t shard_count, std::vector< ColumnsForDevice > &columns_per_device)
 
- Protected Member Functions inherited from OverlapsJoinHashTable
void reify (const HashType preferred_layout)
 
virtual void reifyImpl (std::vector< ColumnsForDevice > &columns_per_device, const Fragmenter_Namespace::TableInfo &query_info, const HashType layout, const size_t shard_count, const size_t entry_count, const size_t emitted_keys_count, const bool skip_hashtable_caching, const size_t chosen_max_hashtable_size, const double chosen_bucket_threshold)
 
void reifyForDevice (const ColumnsForDevice &columns_for_device, const HashType layout, const size_t entry_count, const size_t emitted_keys_count, const bool skip_hashtable_caching, const int device_id, const logger::ThreadLocalIds parent_thread_local_ids)
 
size_t calculateHashTableSize (size_t number_of_dimensions, size_t emitted_keys_count, size_t entry_count) const
 
ColumnsForDevice fetchColumnsForDevice (const std::vector< Fragmenter_Namespace::FragmentInfo > &fragments, const int device_id, DeviceAllocator *dev_buff_owner)
 
virtual std::pair< size_t, size_t > computeHashTableCounts (const size_t shard_count, const std::vector< double > &inverse_bucket_sizes_for_dimension, std::vector< ColumnsForDevice > &columns_per_device, const size_t chosen_max_hashtable_size, const double chosen_bucket_threshold)
 
void setInverseBucketSizeInfo (const std::vector< double > &inverse_bucket_sizes, std::vector< ColumnsForDevice > &columns_per_device, const size_t device_count)
 
size_t getKeyComponentWidth () const
 
size_t getKeyComponentCount () const
 
Data_Namespace::MemoryLevel getMemoryLevel () const noexceptoverride
 
int getDeviceCount () const noexceptoverride
 
std::shared_ptr
< BaselineHashTable
initHashTableOnCpu (const std::vector< JoinColumn > &join_columns, const std::vector< JoinColumnTypeInfo > &join_column_types, const std::vector< JoinBucketInfo > &join_bucket_info, const HashType layout, const size_t entry_count, const size_t emitted_keys_count, const bool skip_hashtable_caching)
 
HashJoinMatchingSet codegenMatchingSet (const CompilationOptions &, const size_t) override
 
std::string toString (const ExecutorDeviceType device_type, const int device_id=0, bool raw=false) const override
 
DecodedJoinHashBufferSet toSet (const ExecutorDeviceType device_type, const int device_id) const override
 
llvm::Value * codegenSlot (const CompilationOptions &, const size_t) override
 
const RegisteredQueryHintgetRegisteredQueryHint ()
 
size_t getEntryCount () const
 
size_t getEmittedKeysCount () const
 
size_t getComponentBufferSize () const noexceptoverride
 
size_t shardCount () const
 
Data_Namespace::MemoryLevel getEffectiveMemoryLevel (const std::vector< InnerOuter > &inner_outer_pairs) const
 
shared::TableKey getInnerTableId () const noexceptoverride
 
int getInnerTableRteIdx () const noexceptoverride
 
size_t getKeyBufferSize () const noexcept
 
size_t offsetBufferOff () const noexceptoverride
 
size_t countBufferOff () const noexceptoverride
 
size_t payloadBufferOff () const noexceptoverride
 
std::string getHashJoinType () const final
 
bool isBitwiseEq () const override
 
std::shared_ptr< HashTableinitHashTableOnCpuFromCache (QueryPlanHash key, CacheItemType item_type, DeviceIdentifier device_identifier)
 
std::optional< std::pair
< size_t, size_t > > 
getApproximateTupleCountFromCache (QueryPlanHash key, CacheItemType item_type, DeviceIdentifier device_identifier)
 
void putHashTableOnCpuToCache (QueryPlanHash key, CacheItemType item_type, std::shared_ptr< HashTable > hashtable_ptr, DeviceIdentifier device_identifier, size_t hashtable_building_time)
 
llvm::Value * codegenKey (const CompilationOptions &)
 
std::vector< llvm::Value * > codegenManyKey (const CompilationOptions &)
 
std::optional
< OverlapsHashTableMetaInfo
getOverlapsHashTableMetaInfo ()
 
QueryPlanHash getAlternativeCacheKey (AlternativeCacheKeyForOverlapsHashJoin &info)
 
void generateCacheKey (const size_t max_hashtable_size, const double bucket_threshold, const std::vector< double > &bucket_sizes, std::vector< std::vector< Fragmenter_Namespace::FragmentInfo >> &fragments_per_device, int device_count)
 
QueryPlanHash getCacheKey (int device_id) const
 
const std::vector< InnerOuter > & getInnerOuterPairs () const
 
void setOverlapsHashtableMetaInfo (size_t max_table_size_bytes, double bucket_threshold, std::vector< double > &bucket_sizes)
 

Private Member Functions

bool isInnerColCompressed () const
 
bool isProbeCompressed () const
 

Private Attributes

const Analyzer::RangeOperrange_expr_
 
std::shared_ptr
< Analyzer::ColumnVar
inner_col_expr_
 
Data_Namespace::MemoryLevel effective_memory_level_
 
const double bucket_threshold_ {std::numeric_limits<double>::max()}
 
const size_t max_hashtable_size_ {std::numeric_limits<size_t>::max()}
 

Additional Inherited Members

- Static Protected Member Functions inherited from HashJoin
static llvm::Value * codegenColOrStringOper (const Analyzer::Expr *col_or_string_oper, const std::vector< StringOps_Namespace::StringOpInfo > &string_op_infos, CodeGenerator &code_generator, const CompilationOptions &co)
 
- Protected Attributes inherited from OverlapsJoinHashTable
const std::shared_ptr
< Analyzer::BinOper
condition_
 
const JoinType join_type_
 
const std::vector
< InputTableInfo > & 
query_infos_
 
const Data_Namespace::MemoryLevel memory_level_
 
Executorexecutor_
 
ColumnCacheMapcolumn_cache_
 
std::vector< InnerOuterinner_outer_pairs_
 
const int device_count_
 
RegisteredQueryHint query_hints_
 
std::vector< double > inverse_bucket_sizes_for_dimension_
 
double chosen_overlaps_bucket_threshold_
 
size_t chosen_overlaps_max_table_size_bytes_
 
CompositeKeyInfo composite_key_info_
 
std::optional< HashTypelayout_override_
 
std::mutex cpu_hash_table_buff_mutex_
 
HashTableBuildDagMap hashtable_build_dag_map_
 
QueryPlanDAG query_plan_dag_
 
std::vector< QueryPlanHashhashtable_cache_key_
 
HashtableCacheMetaInfo hashtable_cache_meta_info_
 
std::unordered_set< size_t > table_keys_
 
const TableIdToNodeMap table_id_to_node_map_
 
- Protected Attributes inherited from HashJoin
std::vector< std::shared_ptr
< HashTable > > 
hash_tables_for_device_
 
- Static Protected Attributes inherited from OverlapsJoinHashTable
static std::unique_ptr
< HashtableRecycler
hash_table_cache_
 
static std::unique_ptr
< OverlapsTuningParamRecycler
auto_tuner_cache_
 

Detailed Description

Definition at line 21 of file RangeJoinHashTable.h.

Constructor & Destructor Documentation

RangeJoinHashTable::RangeJoinHashTable ( const std::shared_ptr< Analyzer::BinOper condition,
const JoinType  join_type,
const Analyzer::RangeOper range_expr,
std::shared_ptr< Analyzer::ColumnVar inner_col_expr,
const std::vector< InputTableInfo > &  query_infos,
const Data_Namespace::MemoryLevel  memory_level,
ColumnCacheMap column_cache,
Executor executor,
const std::vector< InnerOuter > &  inner_outer_pairs,
const int  device_count,
const RegisteredQueryHint query_hints,
const HashTableBuildDagMap hashtable_build_dag_map,
const TableIdToNodeMap table_id_to_node_map 
)
inline

Definition at line 23 of file RangeJoinHashTable.h.

36  : OverlapsJoinHashTable(condition,
37  join_type,
38  query_infos,
39  memory_level,
40  column_cache,
41  executor,
42  inner_outer_pairs,
43  device_count,
44  query_hints,
45  hashtable_build_dag_map,
46  table_id_to_node_map)
47  , range_expr_(range_expr)
48  , inner_col_expr_(std::move(inner_col_expr)) {}
std::shared_ptr< Analyzer::ColumnVar > inner_col_expr_
OverlapsJoinHashTable(const std::shared_ptr< Analyzer::BinOper > condition, const JoinType join_type, const std::vector< InputTableInfo > &query_infos, const Data_Namespace::MemoryLevel memory_level, ColumnCacheMap &column_cache, Executor *executor, const std::vector< InnerOuter > &inner_outer_pairs, const int device_count, const RegisteredQueryHint &query_hints, const HashTableBuildDagMap &hashtable_build_dag_map, const TableIdToNodeMap &table_id_to_node_map)
const Analyzer::RangeOper * range_expr_
RangeJoinHashTable::~RangeJoinHashTable ( )
overridedefault

Member Function Documentation

std::pair< size_t, size_t > RangeJoinHashTable::approximateTupleCount ( const std::vector< double > &  inverse_bucket_sizes_for_dimension,
std::vector< ColumnsForDevice > &  columns_per_device,
const size_t  chosen_max_hashtable_size,
const double  chosen_bucket_threshold 
)
overrideprotectedvirtual

Reimplemented from OverlapsJoinHashTable.

Definition at line 532 of file RangeJoinHashTable.cpp.

References approximate_distinct_tuples_on_device_range(), approximate_distinct_tuples_range(), threading_serial::async(), Bitmap, CHECK, CHECK_EQ, CHECK_GT, CPU, Data_Namespace::CPU_LEVEL, cpu_threads(), OverlapsJoinHashTable::device_count_, effective_memory_level_, OverlapsJoinHashTable::executor_, HashJoin::getCompositeKeyInfo(), getQueryEngineCudaStreamForDevice(), GPU, Data_Namespace::GPU_LEVEL, hll_size(), hll_unify(), CountDistinctDescriptor::impl_type_, OverlapsJoinHashTable::inner_outer_pairs_, isInnerColCompressed(), transfer_flat_object_to_gpu(), transfer_vector_of_flat_objects_to_gpu(), and UNREACHABLE.

Referenced by computeRangeHashTableCounts().

536  {
537 #ifdef _WIN32
538  // WIN32 needs have C++20 set for designated initialisation to work
539  CountDistinctDescriptor count_distinct_desc{
541  0,
542  11,
543  true,
547  1,
548  };
549 #else
550  CountDistinctDescriptor count_distinct_desc{
552  .min_val = 0,
553  .bitmap_sz_bits = 11,
554  .approximate = true,
558  .sub_bitmap_count = 1,
559  };
560 #endif
561  const auto padded_size_bytes = count_distinct_desc.bitmapPaddedSizeBytes();
562 
563  CHECK(!columns_per_device.empty() && !columns_per_device.front().join_columns.empty());
564  if (columns_per_device.front().join_columns.front().num_elems == 0) {
565  return std::make_pair(0, 0);
566  }
567 
568  for (auto& columns_for_device : columns_per_device) {
569  columns_for_device.setBucketInfo(inverse_bucket_sizes_for_dimension,
571  }
572 
573  // Number of keys must match dimension of buckets
574  CHECK_EQ(columns_per_device.front().join_columns.size(),
575  columns_per_device.front().join_buckets.size());
577  const auto composite_key_info =
579  int thread_count = cpu_threads();
580  std::vector<uint8_t> hll_buffer_all_cpus(thread_count * padded_size_bytes);
581  auto hll_result = &hll_buffer_all_cpus[0];
582 
583  std::vector<int32_t> num_keys_for_row;
584  num_keys_for_row.resize(columns_per_device.front().join_columns[0].num_elems);
585 
587  num_keys_for_row,
588  count_distinct_desc.bitmap_sz_bits,
589  padded_size_bytes,
590  columns_per_device.front().join_columns,
591  columns_per_device.front().join_column_types,
592  columns_per_device.front().join_buckets,
594  thread_count);
595 
596  for (int i = 1; i < thread_count; ++i) {
597  hll_unify(hll_result,
598  hll_result + i * padded_size_bytes,
599  1 << count_distinct_desc.bitmap_sz_bits);
600  }
601  return std::make_pair(hll_size(hll_result, count_distinct_desc.bitmap_sz_bits),
602  num_keys_for_row.size() > 0 ? num_keys_for_row.back() : 0);
603  }
604 #ifdef HAVE_CUDA
605  auto& data_mgr = *executor_->getDataMgr();
606  std::vector<std::vector<uint8_t>> host_hll_buffers(device_count_);
607  for (auto& host_hll_buffer : host_hll_buffers) {
608  host_hll_buffer.resize(count_distinct_desc.bitmapPaddedSizeBytes());
609  }
610  std::vector<size_t> emitted_keys_count_device_threads(device_count_, 0);
611  std::vector<std::future<void>> approximate_distinct_device_threads;
612  for (int device_id = 0; device_id < device_count_; ++device_id) {
613  approximate_distinct_device_threads.emplace_back(std::async(
615  [device_id,
616  &columns_per_device,
617  &count_distinct_desc,
618  &data_mgr,
619  &host_hll_buffers,
620  &emitted_keys_count_device_threads,
621  this] {
622  auto allocator = std::make_unique<CudaAllocator>(
623  &data_mgr, device_id, getQueryEngineCudaStreamForDevice(device_id));
624  auto device_hll_buffer =
625  allocator->alloc(count_distinct_desc.bitmapPaddedSizeBytes());
626  data_mgr.getCudaMgr()->zeroDeviceMem(
627  device_hll_buffer,
628  count_distinct_desc.bitmapPaddedSizeBytes(),
629  device_id,
631  const auto& columns_for_device = columns_per_device[device_id];
632  auto join_columns_gpu = transfer_vector_of_flat_objects_to_gpu(
633  columns_for_device.join_columns, *allocator);
634 
635  CHECK_GT(columns_for_device.join_buckets.size(), 0u);
636  const auto& bucket_sizes_for_dimension =
637  columns_for_device.join_buckets[0].inverse_bucket_sizes_for_dimension;
638  auto bucket_sizes_gpu =
639  allocator->alloc(bucket_sizes_for_dimension.size() * sizeof(double));
640  allocator->copyToDevice(bucket_sizes_gpu,
641  bucket_sizes_for_dimension.data(),
642  bucket_sizes_for_dimension.size() * sizeof(double));
643  const size_t row_counts_buffer_sz =
644  columns_per_device.front().join_columns[0].num_elems * sizeof(int32_t);
645  auto row_counts_buffer = allocator->alloc(row_counts_buffer_sz);
646  data_mgr.getCudaMgr()->zeroDeviceMem(
647  row_counts_buffer,
648  row_counts_buffer_sz,
649  device_id,
651  const auto key_handler =
653  bucket_sizes_for_dimension.size(),
654  join_columns_gpu,
655  reinterpret_cast<double*>(bucket_sizes_gpu));
656  const auto key_handler_gpu =
657  transfer_flat_object_to_gpu(key_handler, *allocator);
659  reinterpret_cast<uint8_t*>(device_hll_buffer),
660  count_distinct_desc.bitmap_sz_bits,
661  reinterpret_cast<int32_t*>(row_counts_buffer),
662  key_handler_gpu,
663  columns_for_device.join_columns[0].num_elems,
664  executor_->blockSize(),
665  executor_->gridSize());
666 
667  auto& host_emitted_keys_count = emitted_keys_count_device_threads[device_id];
668  allocator->copyFromDevice(
669  &host_emitted_keys_count,
670  row_counts_buffer +
671  (columns_per_device.front().join_columns[0].num_elems - 1) *
672  sizeof(int32_t),
673  sizeof(int32_t));
674 
675  auto& host_hll_buffer = host_hll_buffers[device_id];
676  allocator->copyFromDevice(&host_hll_buffer[0],
677  device_hll_buffer,
678  count_distinct_desc.bitmapPaddedSizeBytes());
679  }));
680  }
681  for (auto& child : approximate_distinct_device_threads) {
682  child.get();
683  }
685  auto& result_hll_buffer = host_hll_buffers.front();
686  auto hll_result = reinterpret_cast<int32_t*>(&result_hll_buffer[0]);
687  for (int device_id = 1; device_id < device_count_; ++device_id) {
688  auto& host_hll_buffer = host_hll_buffers[device_id];
689  hll_unify(hll_result,
690  reinterpret_cast<int32_t*>(&host_hll_buffer[0]),
691  1 << count_distinct_desc.bitmap_sz_bits);
692  }
693  size_t emitted_keys_count = 0;
694  for (auto& emitted_keys_count_device : emitted_keys_count_device_threads) {
695  emitted_keys_count += emitted_keys_count_device;
696  }
697  return std::make_pair(hll_size(hll_result, count_distinct_desc.bitmap_sz_bits),
698  emitted_keys_count);
699 #else
700  UNREACHABLE();
701  return {0, 0};
702 #endif // HAVE_CUDA
703 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
T * transfer_flat_object_to_gpu(const T &object, DeviceAllocator &allocator)
void hll_unify(T1 *lhs, T2 *rhs, const size_t m)
Definition: HyperLogLog.h:107
#define UNREACHABLE()
Definition: Logger.h:337
CountDistinctImplType impl_type_
size_t hll_size(const T *M, const size_t bitmap_sz_bits)
Definition: HyperLogLog.h:88
#define CHECK_GT(x, y)
Definition: Logger.h:305
void approximate_distinct_tuples_on_device_range(uint8_t *hll_buffer, const uint32_t b, int32_t *row_counts_buffer, const RangeKeyHandler *key_handler, const size_t num_elems, const size_t block_size_x, const size_t grid_size_x)
future< Result > async(Fn &&fn, Args &&...args)
CUstream getQueryEngineCudaStreamForDevice(int device_num)
Definition: QueryEngine.cpp:7
bool isInnerColCompressed() const
void approximate_distinct_tuples_range(uint8_t *hll_buffer_all_cpus, std::vector< int32_t > &row_counts, const uint32_t b, const size_t padded_size_bytes, const std::vector< JoinColumn > &join_column_per_key, const std::vector< JoinColumnTypeInfo > &type_info_per_key, const std::vector< JoinBucketInfo > &join_buckets_per_key, const bool is_compressed, const int thread_count)
#define CHECK(condition)
Definition: Logger.h:291
std::vector< InnerOuter > inner_outer_pairs_
Data_Namespace::MemoryLevel effective_memory_level_
T * transfer_vector_of_flat_objects_to_gpu(const std::vector< T > &vec, DeviceAllocator &allocator)
int cpu_threads()
Definition: thread_count.h:25
static CompositeKeyInfo getCompositeKeyInfo(const std::vector< InnerOuter > &inner_outer_pairs, const Executor *executor, const std::vector< InnerOuterStringOpInfos > &inner_outer_string_op_infos_pairs={})
Definition: HashJoin.cpp:461

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

llvm::Value * RangeJoinHashTable::codegenKey ( const CompilationOptions co,
llvm::Value *  offset 
)

Definition at line 711 of file RangeJoinHashTable.cpp.

References CodeGenerator::castArrayPointer(), CHECK, CHECK_EQ, CodeGenerator::codegen(), OverlapsJoinHashTable::executor_, func_resolve, get_int_type(), Catalog_Namespace::get_metadata_for_column(), OverlapsJoinHashTable::getKeyComponentCount(), OverlapsJoinHashTable::getKeyComponentWidth(), OverlapsJoinHashTable::inner_outer_pairs_, OverlapsJoinHashTable::inverse_bucket_sizes_for_dimension_, isProbeCompressed(), kPOINT, kTINYINT, LL_BUILDER, LL_CONTEXT, LL_FP, LL_INT, and CodeGenerator::posArg().

Referenced by codegenMatchingSetWithOffset().

712  {
713  const auto key_component_width = getKeyComponentWidth();
714  CHECK(key_component_width == 4 || key_component_width == 8);
715  const auto key_size_lv = LL_INT(getKeyComponentCount() * key_component_width);
716  llvm::Value* key_buff_lv{nullptr};
717  switch (key_component_width) {
718  case 4:
719  key_buff_lv =
720  LL_BUILDER.CreateAlloca(llvm::Type::getInt32Ty(LL_CONTEXT), key_size_lv);
721  break;
722  case 8:
723  key_buff_lv =
724  LL_BUILDER.CreateAlloca(llvm::Type::getInt64Ty(LL_CONTEXT), key_size_lv);
725  break;
726  default:
727  CHECK(false);
728  }
729 
730  const auto& inner_outer_pair = inner_outer_pairs_[0];
731  const auto outer_col = inner_outer_pair.second;
732  const auto outer_col_ti = outer_col->get_type_info();
733 
734  if (outer_col_ti.is_geometry()) {
735  CodeGenerator code_generator(executor_);
736  // TODO(adb): for points we will use the coords array, but for other
737  // geometries we will need to use the bounding box. For now only support
738  // points.
739  CHECK_EQ(outer_col_ti.get_type(), kPOINT);
740  CHECK_EQ(inverse_bucket_sizes_for_dimension_.size(), static_cast<size_t>(2));
741 
742  llvm::Value* arr_ptr{nullptr};
743  // prepare point column (arr) ptr to generate code for hash table key
744  if (auto outer_col_var = dynamic_cast<const Analyzer::ColumnVar*>(outer_col)) {
745  const auto col_lvs = code_generator.codegen(outer_col, true, co);
746  CHECK_EQ(col_lvs.size(), size_t(1));
747  auto column_key = outer_col_var->getColumnKey();
748  column_key.column_id = column_key.column_id + 1;
749  const auto coords_cd = Catalog_Namespace::get_metadata_for_column(column_key);
750  CHECK(coords_cd);
751  const auto coords_ti = coords_cd->columnType;
752 
753  const auto array_buff_ptr = executor_->cgen_state_->emitExternalCall(
754  "array_buff",
755  llvm::Type::getInt8PtrTy(executor_->cgen_state_->context_),
756  {col_lvs.front(), code_generator.posArg(outer_col)});
757  CHECK(array_buff_ptr);
758  CHECK(coords_ti.get_elem_type().get_type() == kTINYINT)
759  << "Only TINYINT coordinates columns are supported in geo overlaps "
760  "hash join.";
761  arr_ptr =
762  code_generator.castArrayPointer(array_buff_ptr, coords_ti.get_elem_type());
763  } else if (auto geo_expr_outer_col =
764  dynamic_cast<const Analyzer::GeoOperator*>(outer_col)) {
765  const auto geo_expr_name = geo_expr_outer_col->getName();
766  if (func_resolve(geo_expr_name, "ST_Point"sv, "ST_Transform"sv, "ST_Centroid"sv)) {
767  // note that ST_SetSRID changes type info of the column, and is handled by
768  // translation phase, so when we use ST_SETSRID(ST_POINT(x, y), 4326)
769  // as a join column expression, we recognize it as ST_POINT (with SRID as 4326)
770  const auto col_lvs = code_generator.codegen(outer_col, true, co);
771  // listed functions keep point coordinates in the local variable (let say S)
772  // which is corresponding to the pointer that col_lvs[0] holds
773  // thus, all we need is to retrieve necessary coordinate from the S by varying
774  // its offset (i.e., i == 0 means x coordinate)
775  arr_ptr = LL_BUILDER.CreatePointerCast(
776  col_lvs[0], llvm::Type::getInt8PtrTy(executor_->cgen_state_->context_));
777  } else {
778  throw std::runtime_error(
779  "RHS key of the range join operator has a geospatial function which is not "
780  "supported yet: " +
781  geo_expr_name);
782  }
783  } else {
784  throw std::runtime_error("Range join operator has an invalid rhs key: " +
785  outer_col->toString());
786  }
787 
788  // load and unpack offsets
789  const auto offset =
790  LL_BUILDER.CreateLoad(offset_ptr->getType()->getPointerElementType(),
791  offset_ptr,
792  "packed_bucket_offset");
793  const auto x_offset =
794  LL_BUILDER.CreateTrunc(offset, llvm::Type::getInt32Ty(LL_CONTEXT));
795 
796  const auto y_offset_shifted =
797  LL_BUILDER.CreateLShr(offset, LL_INT(static_cast<int64_t>(32)));
798  const auto y_offset =
799  LL_BUILDER.CreateTrunc(y_offset_shifted, llvm::Type::getInt32Ty(LL_CONTEXT));
800 
801  const auto x_bucket_offset =
802  LL_BUILDER.CreateSExt(x_offset, llvm::Type::getInt64Ty(LL_CONTEXT));
803  const auto y_bucket_offset =
804  LL_BUILDER.CreateSExt(y_offset, llvm::Type::getInt64Ty(LL_CONTEXT));
805 
806  for (size_t i = 0; i < 2; i++) {
807  const auto key_comp_dest_lv = LL_BUILDER.CreateGEP(
808  key_buff_lv->getType()->getScalarType()->getPointerElementType(),
809  key_buff_lv,
810  LL_INT(i));
811 
812  const auto funcName = isProbeCompressed() ? "get_bucket_key_for_range_compressed"
813  : "get_bucket_key_for_range_double";
814 
815  // Note that get_bucket_key_for_range_compressed will need to be
816  // specialized for future compression schemes
817  auto bucket_key = executor_->cgen_state_->emitExternalCall(
818  funcName,
821 
822  auto bucket_key_shifted = i == 0
823  ? LL_BUILDER.CreateAdd(x_bucket_offset, bucket_key)
824  : LL_BUILDER.CreateAdd(y_bucket_offset, bucket_key);
825 
826  const auto col_lv = LL_BUILDER.CreateSExt(
827  bucket_key_shifted, get_int_type(key_component_width * 8, LL_CONTEXT));
828  LL_BUILDER.CreateStore(col_lv, key_comp_dest_lv);
829  }
830  } else {
831  LOG(FATAL) << "Range join key currently only supported for geospatial types.";
832  }
833  return key_buff_lv;
834 }
#define LL_INT(v)
#define CHECK_EQ(x, y)
Definition: Logger.h:301
auto func_resolve
#define LOG(tag)
Definition: Logger.h:285
const ColumnDescriptor * get_metadata_for_column(const ::shared::ColumnKey &column_key)
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
#define LL_CONTEXT
#define LL_FP(v)
#define LL_BUILDER
std::vector< double > inverse_bucket_sizes_for_dimension_
bool isProbeCompressed() const
#define CHECK(condition)
Definition: Logger.h:291
std::vector< InnerOuter > inner_outer_pairs_

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

HashJoinMatchingSet RangeJoinHashTable::codegenMatchingSetWithOffset ( const CompilationOptions co,
const size_t  index,
llvm::Value *  range_offset 
)

Definition at line 836 of file RangeJoinHashTable.cpp.

References CHECK, HashJoin::codegenHashTableLoad(), codegenKey(), HashJoin::codegenMatchingSet(), OverlapsJoinHashTable::executor_, get_int_type(), OverlapsJoinHashTable::getComponentBufferSize(), OverlapsJoinHashTable::getEntryCount(), getHashType(), OverlapsJoinHashTable::getKeyComponentCount(), OverlapsJoinHashTable::getKeyComponentWidth(), LL_BUILDER, LL_CONTEXT, LL_INT, OverlapsJoinHashTable::offsetBufferOff(), OneToMany, and to_string().

839  {
840  const auto key_component_width = getKeyComponentWidth();
841  CHECK(key_component_width == 4 || key_component_width == 8);
842 
843  auto key_buff_lv = codegenKey(co, range_offset);
845 
846  auto hash_ptr = codegenHashTableLoad(index, executor_);
847  const auto composite_dict_ptr_type =
848  llvm::Type::getIntNPtrTy(LL_CONTEXT, key_component_width * 8);
849 
850  const auto composite_key_dict =
851  hash_ptr->getType()->isPointerTy()
852  ? LL_BUILDER.CreatePointerCast(hash_ptr, composite_dict_ptr_type)
853  : LL_BUILDER.CreateIntToPtr(hash_ptr, composite_dict_ptr_type);
854 
855  const auto key_component_count = getKeyComponentCount();
856 
857  const auto funcName =
858  "get_composite_key_index_" + std::to_string(key_component_width * 8);
859 
860  const auto key = executor_->cgen_state_->emitExternalCall(funcName,
862  {key_buff_lv,
863  LL_INT(key_component_count),
864  composite_key_dict,
865  LL_INT(getEntryCount())});
866 
867  auto one_to_many_ptr = hash_ptr;
868  if (one_to_many_ptr->getType()->isPointerTy()) {
869  one_to_many_ptr =
870  LL_BUILDER.CreatePtrToInt(hash_ptr, llvm::Type::getInt64Ty(LL_CONTEXT));
871  } else {
872  CHECK(one_to_many_ptr->getType()->isIntegerTy(64));
873  }
874  const auto composite_key_dict_size = offsetBufferOff();
875  one_to_many_ptr =
876  LL_BUILDER.CreateAdd(one_to_many_ptr, LL_INT(composite_key_dict_size));
877 
879  /* hash_join_idx_args_in */ {one_to_many_ptr,
880  key,
881  LL_INT(int64_t(0)),
882  LL_INT(getEntryCount() - 1)},
883  /* is_sharded */ false,
884  /* is_nullable */ false,
885  /* is_bw_eq */ false,
886  /* sub_buff_size */ getComponentBufferSize(),
887  /* executor */ executor_);
888 }
#define LL_INT(v)
virtual HashJoinMatchingSet codegenMatchingSet(const CompilationOptions &, const size_t)=0
llvm::Value * codegenKey(const CompilationOptions &co, llvm::Value *offset)
static llvm::Value * codegenHashTableLoad(const size_t table_idx, Executor *executor)
Definition: HashJoin.cpp:257
HashType getHashType() const noexceptoverride
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
#define LL_CONTEXT
std::string to_string(char const *&&v)
#define LL_BUILDER
size_t offsetBufferOff() const noexceptoverride
#define CHECK(condition)
Definition: Logger.h:291
size_t getComponentBufferSize() const noexceptoverride

+ Here is the call graph for this function:

std::pair< size_t, size_t > RangeJoinHashTable::computeRangeHashTableCounts ( const size_t  shard_count,
std::vector< ColumnsForDevice > &  columns_per_device 
)
protected

Definition at line 516 of file RangeJoinHashTable.cpp.

References approximateTupleCount(), bucket_threshold_, CHECK, OverlapsJoinHashTable::device_count_, get_entries_per_device(), OverlapsJoinHashTable::inverse_bucket_sizes_for_dimension_, max_hashtable_size_, and OverlapsJoinHashTable::memory_level_.

Referenced by reifyWithLayout().

518  {
520  const auto [tuple_count, emitted_keys_count] =
522  columns_per_device,
525  const auto entry_count = 2 * std::max(tuple_count, size_t(1));
526 
527  return std::make_pair(
528  get_entries_per_device(entry_count, shard_count, device_count_, memory_level_),
529  emitted_keys_count);
530 }
std::pair< size_t, size_t > approximateTupleCount(const std::vector< double > &inverse_bucket_sizes_for_dimension, std::vector< ColumnsForDevice > &columns_per_device, const size_t chosen_max_hashtable_size, const double chosen_bucket_threshold) override
const double bucket_threshold_
std::vector< double > inverse_bucket_sizes_for_dimension_
size_t get_entries_per_device(const size_t total_entries, const size_t shard_count, const size_t device_count, const Data_Namespace::MemoryLevel memory_level)
#define CHECK(condition)
Definition: Logger.h:291
const Data_Namespace::MemoryLevel memory_level_
const size_t max_hashtable_size_

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

HashType RangeJoinHashTable::getHashType ( ) const
inlineoverrideprotectedvirtualnoexcept

Reimplemented from OverlapsJoinHashTable.

Definition at line 94 of file RangeJoinHashTable.h.

References OneToMany.

Referenced by codegenMatchingSetWithOffset().

+ Here is the caller graph for this function:

std::shared_ptr< RangeJoinHashTable > RangeJoinHashTable::getInstance ( const std::shared_ptr< Analyzer::BinOper condition,
const Analyzer::RangeOper range_expr,
const std::vector< InputTableInfo > &  query_infos,
const Data_Namespace::MemoryLevel  memory_level,
const JoinType  join_type,
const int  device_count,
ColumnCacheMap column_cache,
Executor executor,
const HashTableBuildDagMap hashtable_build_dag_map,
const RegisteredQueryHint query_hints,
const TableIdToNodeMap table_id_to_node_map 
)
static

NOTE(jclay): Handling Range Joins With Mixed Compression:

First, let's take a concrete example of a query that is rewritten as a range join. Notice in the first code block, that the condition operator is an Overlaps operator. The LHS is a column, and the RHS is the range operator. In order to have the hash table build and probe work properly, we need to ensure that the approriate runtime functions are selected. The following breakdown is provided to help document how the appropriate runtime funditon is selected.

  • The LHS of the RangeOper is used to build the hash table
  • The LHS of the OverlapsOper + the RHS of the RangeOper is used as probe

SELECT count(*) FROM t1, t2 where ST_Distance(t1.p1_comp32, t2.p1) <= 6.3;

BinOper condition

((OVERLAPS) (ColumnVar table: (t1) column: (p1_comp32) GEOMETRY(POINT, 4326) ENCODING COMPRESSED(32)) (RangeOper) (ColumnVar table: (t2) column: (p1) GEOMETRY(POINT, 4326) ENCODING NONE), (Const 6.330000))

RangeOper condition

[(ColumnVar table: 5 (t2) column: 1 rte: 1 GEOMETRY(POINT, 4326) ENCODING NONE), (Const 6.330000)]

Same example as above, annotated:

SELECT count(*) FROM t1, t2 where ST_Distance( t1.p1_comp32, << Overlaps Condition LHS t2.p1 << RangeOper LHS ) <= 6.3; << RangeOper RHS

In this case, we select the uncompressed runtime functions when building the hash table over t2.p1. When performing the probe, we must select the compressed runtime functions.

Definition at line 71 of file RangeJoinHashTable.cpp.

References CHECK, HashJoin::checkHashJoinReplicationConstraint(), logger::FATAL, get_inner_query_info(), Analyzer::RangeOper::get_left_operand(), Catalog_Namespace::get_metadata_for_column(), HashJoin::getInnerTableId(), Fragmenter_Namespace::TableInfo::getNumTuplesUpperBound(), BaselineJoinHashTable::getShardCountForCondition(), Data_Namespace::GPU_LEVEL, InputTableInfo::info, LOG, OneToMany, and Analyzer::RangeOper::toString().

Referenced by OverlapsJoinHashTable::getInstance().

82  {
83  // the hash table is built over the LHS of the range oper. we then use the lhs
84  // of the bin oper + the rhs of the range oper for the probe
85  auto range_expr_col_var =
86  dynamic_cast<const Analyzer::ColumnVar*>(range_expr->get_left_operand());
87  if (!range_expr_col_var || !range_expr_col_var->get_type_info().is_geometry()) {
88  throw HashJoinFail("Could not build hash tables for range join | " +
89  range_expr->toString());
90  }
91 
92  CHECK(range_expr_col_var->get_type_info().is_geometry());
93 
94  auto coords_column_key = range_expr_col_var->getColumnKey();
95  coords_column_key.column_id = coords_column_key.column_id + 1;
96  const auto coords_cd = Catalog_Namespace::get_metadata_for_column(coords_column_key);
97  CHECK(coords_cd);
98 
99  auto range_join_inner_col_expr = makeExpr<Analyzer::ColumnVar>(
100  coords_cd->columnType, coords_column_key, range_expr_col_var->get_rte_idx());
101 
102  std::vector<InnerOuter> inner_outer_pairs;
103  inner_outer_pairs.emplace_back(
104  InnerOuter{dynamic_cast<Analyzer::ColumnVar*>(range_join_inner_col_expr.get()),
105  condition->get_left_operand()});
106 
107  const auto& query_info =
108  get_inner_query_info(HashJoin::getInnerTableId(inner_outer_pairs), query_infos)
109  .info;
110 
111  const auto total_entries = 2 * query_info.getNumTuplesUpperBound();
112  if (total_entries > static_cast<size_t>(std::numeric_limits<int32_t>::max())) {
113  throw TooManyHashEntries();
114  }
115 
116  const auto shard_count = memory_level == Data_Namespace::GPU_LEVEL
118  condition.get(), executor, inner_outer_pairs)
119  : 0;
120 
121  auto join_hash_table = std::make_shared<RangeJoinHashTable>(condition,
122  join_type,
123  range_expr,
124  range_join_inner_col_expr,
125  query_infos,
126  memory_level,
127  column_cache,
128  executor,
129  inner_outer_pairs,
130  device_count,
131  query_hints,
132  hashtable_build_dag_map,
133  table_id_to_node_map);
135  HashJoin::getInnerTableId(inner_outer_pairs), shard_count, executor);
136  try {
137  join_hash_table->reifyWithLayout(HashType::OneToMany);
138  } catch (const HashJoinFail& e) {
139  throw HashJoinFail(std::string("Could not build a 1-to-1 correspondence for columns "
140  "involved in equijoin | ") +
141  e.what());
142  } catch (const ColumnarConversionNotSupported& e) {
143  throw HashJoinFail(std::string("Could not build hash tables for equijoin | ") +
144  e.what());
145  } catch (const JoinHashTableTooBig& e) {
146  throw e;
147  } catch (const std::exception& e) {
148  LOG(FATAL) << "Fatal error while attempting to build hash tables for join: "
149  << e.what();
150  }
151 
152  return join_hash_table;
153 }
Fragmenter_Namespace::TableInfo info
Definition: InputMetadata.h:35
std::pair< const Analyzer::ColumnVar *, const Analyzer::Expr * > InnerOuter
Definition: HashJoin.h:106
#define LOG(tag)
Definition: Logger.h:285
static void checkHashJoinReplicationConstraint(const shared::TableKey &table_key, const size_t shard_count, const Executor *executor)
Definition: HashJoin.cpp:779
const ColumnDescriptor * get_metadata_for_column(const ::shared::ColumnKey &column_key)
const InputTableInfo & get_inner_query_info(const shared::TableKey &inner_table_key, const std::vector< InputTableInfo > &query_infos)
const Expr * get_left_operand() const
Definition: Analyzer.h:552
std::string toString() const override
Definition: Analyzer.cpp:2747
virtual shared::TableKey getInnerTableId() const noexcept=0
#define CHECK(condition)
Definition: Logger.h:291
static size_t getShardCountForCondition(const Analyzer::BinOper *condition, const Executor *executor, const std::vector< InnerOuter > &inner_outer_pairs)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::shared_ptr< BaselineHashTable > RangeJoinHashTable::initHashTableOnCpu ( const std::vector< JoinColumn > &  join_columns,
const std::vector< JoinColumnTypeInfo > &  join_column_types,
const std::vector< JoinBucketInfo > &  join_bucket_info,
const HashType  layout,
const size_t  entry_count,
const size_t  emitted_keys_count 
)
protected

Definition at line 457 of file RangeJoinHashTable.cpp.

References CHECK, DataRecyclerUtil::CPU_DEVICE_IDENTIFIER, DEBUG_TIMER, OverlapsJoinHashTable::executor_, HashJoin::getCompositeKeyInfo(), OverlapsJoinHashTable::getKeyComponentCount(), OverlapsJoinHashTable::getKeyComponentWidth(), OverlapsJoinHashTable::hashtable_cache_key_, OverlapsJoinHashTable::inner_outer_pairs_, isInnerColCompressed(), OverlapsJoinHashTable::join_type_, HashJoin::layoutRequiresAdditionalBuffers(), OVERLAPS_HT, OverlapsJoinHashTable::putHashTableOnCpuToCache(), OverlapsJoinHashTable::query_hints_, and to_string().

Referenced by reifyForDevice().

463  {
464  auto timer = DEBUG_TIMER(__func__);
465  decltype(std::chrono::steady_clock::now()) ts1, ts2;
466  ts1 = std::chrono::steady_clock::now();
467  const auto composite_key_info =
469  CHECK(!join_columns.empty());
470  CHECK(!join_bucket_info.empty());
471 
473  const auto key_component_count =
474  join_bucket_info[0].inverse_bucket_sizes_for_dimension.size();
475 
476  auto key_handler =
478  key_component_count,
479  &join_columns[0],
480  join_bucket_info[0].inverse_bucket_sizes_for_dimension.data());
481 
484  dummy_str_proxy_translation_maps_ptrs_and_offsets;
485  const auto err =
486  builder.initHashTableOnCpu(&key_handler,
487  composite_key_info,
488  join_columns,
489  join_column_types,
490  join_bucket_info,
491  dummy_str_proxy_translation_maps_ptrs_and_offsets,
492  entry_count,
493  emitted_keys_count,
494  layout,
495  join_type_,
498  query_hints_);
499  ts2 = std::chrono::steady_clock::now();
500  if (err) {
501  throw HashJoinFail(std::string("Unrecognized error when initializing CPU "
502  "range join hash table (") +
503  std::to_string(err) + std::string(")"));
504  }
505  std::shared_ptr<BaselineHashTable> hash_table = builder.getHashTable();
506  auto hashtable_build_time =
507  std::chrono::duration_cast<std::chrono::milliseconds>(ts2 - ts1).count();
510  hash_table,
512  hashtable_build_time);
513  return hash_table;
514 }
void putHashTableOnCpuToCache(QueryPlanHash key, CacheItemType item_type, std::shared_ptr< HashTable > hashtable_ptr, DeviceIdentifier device_identifier, size_t hashtable_building_time)
std::string to_string(char const *&&v)
std::shared_ptr< BaselineHashTable > initHashTableOnCpu(const std::vector< JoinColumn > &join_columns, const std::vector< JoinColumnTypeInfo > &join_column_types, const std::vector< JoinBucketInfo > &join_bucket_info, const HashType layout, const size_t entry_count, const size_t emitted_keys_count)
RegisteredQueryHint query_hints_
std::vector< QueryPlanHash > hashtable_cache_key_
std::pair< std::vector< const int32_t * >, std::vector< int32_t >> StrProxyTranslationMapsPtrsAndOffsets
std::unique_ptr< BaselineHashTable > getHashTable()
bool isInnerColCompressed() const
#define CHECK(condition)
Definition: Logger.h:291
#define DEBUG_TIMER(name)
Definition: Logger.h:411
std::vector< InnerOuter > inner_outer_pairs_
static constexpr DeviceIdentifier CPU_DEVICE_IDENTIFIER
Definition: DataRecycler.h:136
static bool layoutRequiresAdditionalBuffers(HashType layout) noexcept
Definition: HashJoin.h:161
static CompositeKeyInfo getCompositeKeyInfo(const std::vector< InnerOuter > &inner_outer_pairs, const Executor *executor, const std::vector< InnerOuterStringOpInfos > &inner_outer_string_op_infos_pairs={})
Definition: HashJoin.cpp:461

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool RangeJoinHashTable::isInnerColCompressed ( ) const
inlineprivate

Definition at line 114 of file RangeJoinHashTable.h.

References SQLTypeInfo::get_compression(), Analyzer::RangeOper::get_left_operand(), Analyzer::Expr::get_type_info(), kENCODING_GEOINT, and range_expr_.

Referenced by approximateTupleCount(), and initHashTableOnCpu().

114  {
117  }
const Expr * get_left_operand() const
Definition: Analyzer.h:552
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:389
const Analyzer::RangeOper * range_expr_

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool RangeJoinHashTable::isProbeCompressed ( ) const
inlineprivate

Definition at line 119 of file RangeJoinHashTable.h.

References OverlapsJoinHashTable::getInnerOuterPairs(), and kENCODING_GEOINT.

Referenced by codegenKey().

119  {
120  const auto& inner_outer_pair = getInnerOuterPairs()[0];
121  const auto outer_col = inner_outer_pair.second;
122  const auto outer_col_ti = outer_col->get_type_info();
123 
124  return outer_col_ti.get_compression() == kENCODING_GEOINT;
125  }
const std::vector< InnerOuter > & getInnerOuterPairs() const

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void RangeJoinHashTable::reifyForDevice ( const ColumnsForDevice columns_for_device,
const HashType  layout,
const size_t  entry_count,
const size_t  emitted_keys_count,
const int  device_id,
const logger::ThreadLocalIds  parent_thread_local_ids 
)
protected

Definition at line 350 of file RangeJoinHashTable.cpp.

References CHECK, CHECK_EQ, CHECK_LT, Data_Namespace::CPU_LEVEL, DEBUG_TIMER_NEW_THREAD, effective_memory_level_, OverlapsJoinHashTable::getKeyComponentWidth(), Data_Namespace::GPU_LEVEL, HashJoin::hash_tables_for_device_, initHashTableOnCpu(), ColumnsForDevice::join_buckets, ColumnsForDevice::join_column_types, ColumnsForDevice::join_columns, HashJoin::layoutRequiresAdditionalBuffers(), OverlapsJoinHashTable::memory_level_, logger::ThreadLocalIds::setNewThreadId(), logger::ThreadLocalIds::thread_id_, UNREACHABLE, and VLOG.

Referenced by reifyWithLayout().

356  {
357  logger::LocalIdsScopeGuard lisg = parent_thread_local_ids.setNewThreadId();
358  DEBUG_TIMER_NEW_THREAD(parent_thread_local_ids.thread_id_);
359  CHECK_EQ(getKeyComponentWidth(), size_t(8));
361 
363  VLOG(1) << "Building range join hash table on CPU.";
364  auto hash_table = initHashTableOnCpu(columns_for_device.join_columns,
365  columns_for_device.join_column_types,
366  columns_for_device.join_buckets,
367  layout,
368  entry_count,
369  emitted_keys_count);
370  CHECK(hash_table);
371 
372 #ifdef HAVE_CUDA
374  auto gpu_hash_table = copyCpuHashTableToGpu(
375  hash_table, layout, entry_count, emitted_keys_count, device_id);
376  CHECK_LT(size_t(device_id), hash_tables_for_device_.size());
377  hash_tables_for_device_[device_id] = std::move(gpu_hash_table);
378  } else {
379 #else
381 #endif
382  CHECK_EQ(hash_tables_for_device_.size(), size_t(1));
383  hash_tables_for_device_[0] = std::move(hash_table);
384 #ifdef HAVE_CUDA
385  }
386 #endif
387  } else {
388 #ifdef HAVE_CUDA
389  auto hash_table = initHashTableOnGpu(columns_for_device.join_columns,
390  columns_for_device.join_column_types,
391  columns_for_device.join_buckets,
392  layout,
393  entry_count,
394  emitted_keys_count,
395  device_id);
396  CHECK_LT(size_t(device_id), hash_tables_for_device_.size());
397  hash_tables_for_device_[device_id] = std::move(hash_table);
398 #else
399  UNREACHABLE();
400 #endif
401  }
402 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
std::vector< std::shared_ptr< HashTable > > hash_tables_for_device_
Definition: HashJoin.h:363
#define UNREACHABLE()
Definition: Logger.h:337
#define DEBUG_TIMER_NEW_THREAD(parent_thread_id)
Definition: Logger.h:416
const std::vector< JoinColumnTypeInfo > join_column_types
Definition: HashJoin.h:112
std::shared_ptr< BaselineHashTable > initHashTableOnCpu(const std::vector< JoinColumn > &join_columns, const std::vector< JoinColumnTypeInfo > &join_column_types, const std::vector< JoinBucketInfo > &join_bucket_info, const HashType layout, const size_t entry_count, const size_t emitted_keys_count)
#define CHECK_LT(x, y)
Definition: Logger.h:303
LocalIdsScopeGuard setNewThreadId() const
Definition: Logger.cpp:532
#define CHECK(condition)
Definition: Logger.h:291
const Data_Namespace::MemoryLevel memory_level_
Data_Namespace::MemoryLevel effective_memory_level_
ThreadId thread_id_
Definition: Logger.h:138
std::vector< JoinBucketInfo > join_buckets
Definition: HashJoin.h:114
const std::vector< JoinColumn > join_columns
Definition: HashJoin.h:111
#define VLOG(n)
Definition: Logger.h:387
static bool layoutRequiresAdditionalBuffers(HashType layout) noexcept
Definition: HashJoin.h:161

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void RangeJoinHashTable::reifyWithLayout ( const HashType  layout)
overrideprotectedvirtual

Reimplemented from OverlapsJoinHashTable.

Definition at line 155 of file RangeJoinHashTable.cpp.

References threading_serial::async(), bucket_threshold_, CompositeKeyInfo::cache_key_chunks, OverlapsJoinHashTable::calculateHashTableSize(), CHECK, CHECK_EQ, CHECK_LT, HashJoin::collectFragmentIds(), OverlapsJoinHashTable::composite_key_info_, computeRangeHashTableCounts(), OverlapsJoinHashTable::condition_, DataRecyclerUtil::CPU_DEVICE_IDENTIFIER, OverlapsJoinHashTable::cpu_hash_table_buff_mutex_, Data_Namespace::CPU_LEVEL, DEBUG_TIMER, OverlapsJoinHashTable::device_count_, effective_memory_level_, OverlapsJoinHashTable::executor_, OverlapsJoinHashTable::fetchColumnsForDevice(), OverlapsJoinHashTable::generateCacheKey(), get_inner_query_info(), Analyzer::RangeOper::get_left_operand(), Analyzer::RangeOper::get_right_operand(), OverlapsJoinHashTable::getAlternativeCacheKey(), DataRecyclerUtil::getAlternativeTableKeys(), OverlapsJoinHashTable::getEffectiveMemoryLevel(), HashtableRecycler::getHashtableAccessPathInfo(), HashJoin::getHashTypeString(), HashJoin::getInnerTableId(), OverlapsJoinHashTable::getInnerTableId(), getQueryEngineCudaStreamForDevice(), Data_Namespace::GPU_LEVEL, OverlapsJoinHashTable::hash_table_cache_, HashJoin::hash_tables_for_device_, OverlapsJoinHashTable::hashtable_build_dag_map_, OverlapsJoinHashTable::hashtable_cache_key_, InputTableInfo::info, OverlapsJoinHashTable::initHashTableOnCpuFromCache(), OverlapsJoinHashTable::inner_outer_pairs_, OverlapsJoinHashTable::inverse_bucket_sizes_for_dimension_, HashtableRecycler::isInvalidHashTableCacheKey(), OverlapsJoinHashTable::join_type_, OverlapsJoinHashTable::layout_override_, ManyToMany, max_hashtable_size_, OverlapsJoinHashTable::memory_level_, OneToMany, only_shards_for_device(), OVERLAPS_HT, OverlapsJoinHashTable::query_infos_, range_expr_, reifyForDevice(), OverlapsJoinHashTable::setInverseBucketSizeInfo(), OverlapsJoinHashTable::setOverlapsHashtableMetaInfo(), OverlapsJoinHashTable::shardCount(), OverlapsJoinHashTable::table_keys_, logger::thread_local_ids(), UNREACHABLE, and VLOG.

155  {
156  auto timer = DEBUG_TIMER(__func__);
157  CHECK(layout == HashType::OneToMany);
158 
159  const auto& query_info =
161  .info;
162 
163  if (query_info.fragments.empty()) {
164  return;
165  }
166 
167  const auto& table_key = getInnerTableId();
168  VLOG(1) << "Reify with layout " << getHashTypeString(layout) << "for " << table_key;
169 
170  std::vector<ColumnsForDevice> columns_per_device;
171 
172  auto data_mgr = executor_->getDataMgr();
173  std::vector<std::vector<Fragmenter_Namespace::FragmentInfo>> fragments_per_device;
174  std::vector<std::unique_ptr<CudaAllocator>> dev_buff_owners;
175  const auto shard_count = shardCount();
176  for (int device_id = 0; device_id < device_count_; ++device_id) {
177  fragments_per_device.emplace_back(
178  shard_count
179  ? only_shards_for_device(query_info.fragments, device_id, device_count_)
180  : query_info.fragments);
182  dev_buff_owners.emplace_back(std::make_unique<CudaAllocator>(
183  data_mgr, device_id, getQueryEngineCudaStreamForDevice(device_id)));
184  }
185  // for overlaps join, we need to fetch columns regardless of the availability of
186  // cached hash table to calculate various params, i.e., bucket size info todo
187  // (yoonmin) : relax this
188  const auto columns_for_device =
189  fetchColumnsForDevice(fragments_per_device[device_id],
190  device_id,
192  ? dev_buff_owners[device_id].get()
193  : nullptr);
194  columns_per_device.push_back(columns_for_device);
195  }
196 
198 
199  const auto bucket_range =
200  dynamic_cast<const Analyzer::Constant*>(range_expr_->get_right_operand());
201 
202  CHECK(bucket_range);
203  CHECK(bucket_range->get_type_info().is_fp() &&
204  bucket_range->get_type_info().get_size() == 8); // TODO
205 
206  const auto bucket_range_datum = bucket_range->get_constval();
207 
208  inverse_bucket_sizes_for_dimension_.emplace_back(1. / bucket_range_datum.doubleval);
209  inverse_bucket_sizes_for_dimension_.emplace_back(1. / bucket_range_datum.doubleval);
210 
212  inverse_bucket_sizes_for_dimension_, columns_per_device, device_count_);
213 
215 
216  // to properly lookup cached hash table, we need to use join columns listed as lhs and
217  // rhs of the overlaps op instead of physical (and hidden) column tailored to range join
218  // expr in other words, we need to use geometry column (point) instead of its hidden
219  // array column i.e., see `get_physical_cols` function
220  std::vector<InnerOuter> inner_outer_pairs_for_cache_lookup;
221  inner_outer_pairs_for_cache_lookup.emplace_back(InnerOuter{
222  dynamic_cast<const Analyzer::ColumnVar*>(range_expr_->get_left_operand()),
223  condition_->get_left_operand()});
224  auto hashtable_access_path_info =
225  HashtableRecycler::getHashtableAccessPathInfo(inner_outer_pairs_for_cache_lookup,
226  {},
227  condition_->get_optype(),
228  join_type_,
231  shard_count,
232  fragments_per_device,
233  executor_);
234  hashtable_cache_key_ = hashtable_access_path_info.hashed_query_plan_dag;
235  table_keys_ = hashtable_access_path_info.table_keys;
236 
237  auto get_inner_table_key = [&inner_outer_pairs_for_cache_lookup]() {
238  auto col_var = inner_outer_pairs_for_cache_lookup.front().first;
239  return col_var->getTableKey();
240  };
241 
242  if (table_keys_.empty()) {
243  const auto& inner_table_key = get_inner_table_key();
245  composite_key_info_.cache_key_chunks, inner_table_key);
246  }
247  CHECK(!table_keys_.empty());
248 
254  fragments_per_device,
255  device_count_);
256 
257  if (HashtableRecycler::isInvalidHashTableCacheKey(hashtable_cache_key_) &&
258  get_inner_table_key().table_id > 0) {
259  std::vector<size_t> per_device_chunk_key;
260  for (int device_id = 0; device_id < device_count_; ++device_id) {
261  auto chunk_key_hash = boost::hash_value(composite_key_info_.cache_key_chunks);
262  boost::hash_combine(chunk_key_hash,
263  HashJoin::collectFragmentIds(fragments_per_device[device_id]));
264  per_device_chunk_key.push_back(chunk_key_hash);
265  AlternativeCacheKeyForOverlapsHashJoin cache_key{
266  inner_outer_pairs_for_cache_lookup,
267  columns_per_device.front().join_columns.front().num_elems,
268  chunk_key_hash,
269  condition_->get_optype(),
272  {}};
273  hashtable_cache_key_[device_id] = getAlternativeCacheKey(cache_key);
274  hash_table_cache_->addQueryPlanDagForTableKeys(hashtable_cache_key_[device_id],
275  table_keys_);
276  }
277  }
278 
280  std::lock_guard<std::mutex> cpu_hash_table_buff_lock(cpu_hash_table_buff_mutex_);
281  if (auto generic_hash_table =
282  initHashTableOnCpuFromCache(hashtable_cache_key_.front(),
285  if (auto hash_table =
286  std::dynamic_pointer_cast<BaselineHashTable>(generic_hash_table)) {
287  // See if a hash table of a different layout was returned.
288  // If it was OneToMany, we can reuse it on ManyToMany.
289  if (layout == HashType::ManyToMany &&
290  hash_table->getLayout() == HashType::OneToMany) {
291  // use the cached hash table
293  }
294 
296 #ifdef HAVE_CUDA
297  for (int device_id = 0; device_id < device_count_; ++device_id) {
298  auto gpu_hash_table = copyCpuHashTableToGpu(hash_table,
299  layout,
300  hash_table->getEntryCount(),
301  hash_table->getEmittedKeysCount(),
302  device_id);
303  CHECK_LT(size_t(device_id), hash_tables_for_device_.size());
304  hash_tables_for_device_[device_id] = std::move(gpu_hash_table);
305  }
306 #else
307  UNREACHABLE();
308 #endif
309  } else {
311  CHECK_EQ(hash_tables_for_device_.size(), size_t(1));
312  // do not move hash_table to keep valid ptr of it within the hash table recycler
313  hash_tables_for_device_[0] = hash_table;
314  }
315  return;
316  }
317  }
318  }
319 
320  auto [entry_count, emitted_keys_count] =
321  computeRangeHashTableCounts(shard_count, columns_per_device);
322 
323  size_t hash_table_size = OverlapsJoinHashTable::calculateHashTableSize(
324  inverse_bucket_sizes_for_dimension_.size(), emitted_keys_count, entry_count);
325 
326  VLOG(1) << "Finalized range join hash table: entry count " << entry_count
327  << " hash table size " << hash_table_size;
328 
329  std::vector<std::future<void>> init_threads;
330  for (int device_id = 0; device_id < device_count_; ++device_id) {
331  init_threads.push_back(
334  this,
335  /* columns_for_device */ columns_per_device[device_id],
336  /* layout_type */ layout,
337  /* entry_count */ entry_count,
338  /* emitted_keys_count */ emitted_keys_count,
339  /* device_id */ device_id,
340  /* parent_thread_local_ids */ logger::thread_local_ids()));
341  }
342  for (auto& init_thread : init_threads) {
343  init_thread.wait();
344  }
345  for (auto& init_thread : init_threads) {
346  init_thread.get();
347  }
348 }
static std::vector< int > collectFragmentIds(const std::vector< Fragmenter_Namespace::FragmentInfo > &fragments)
Definition: HashJoin.cpp:452
#define CHECK_EQ(x, y)
Definition: Logger.h:301
Fragmenter_Namespace::TableInfo info
Definition: InputMetadata.h:35
std::shared_ptr< HashTable > initHashTableOnCpuFromCache(QueryPlanHash key, CacheItemType item_type, DeviceIdentifier device_identifier)
shared::TableKey getInnerTableId() const noexceptoverride
static bool isInvalidHashTableCacheKey(const std::vector< QueryPlanHash > &cache_keys)
std::pair< const Analyzer::ColumnVar *, const Analyzer::Expr * > InnerOuter
Definition: HashJoin.h:106
std::vector< ChunkKey > cache_key_chunks
Definition: HashJoin.h:130
std::vector< std::shared_ptr< HashTable > > hash_tables_for_device_
Definition: HashJoin.h:363
#define UNREACHABLE()
Definition: Logger.h:337
const InputTableInfo & get_inner_query_info(const shared::TableKey &inner_table_key, const std::vector< InputTableInfo > &query_infos)
const Expr * get_left_operand() const
Definition: Analyzer.h:552
size_t calculateHashTableSize(size_t number_of_dimensions, size_t emitted_keys_count, size_t entry_count) const
const std::shared_ptr< Analyzer::BinOper > condition_
future< Result > async(Fn &&fn, Args &&...args)
QueryPlanHash getAlternativeCacheKey(AlternativeCacheKeyForOverlapsHashJoin &info)
const std::vector< InputTableInfo > & query_infos_
std::vector< Fragmenter_Namespace::FragmentInfo > only_shards_for_device(const std::vector< Fragmenter_Namespace::FragmentInfo > &fragments, const int device_id, const int device_count)
HashTableBuildDagMap hashtable_build_dag_map_
static std::unordered_set< size_t > getAlternativeTableKeys(const std::vector< ChunkKey > &chunk_keys, const shared::TableKey &inner_table_key)
Definition: DataRecycler.h:154
std::pair< size_t, size_t > computeRangeHashTableCounts(const size_t shard_count, std::vector< ColumnsForDevice > &columns_per_device)
std::vector< QueryPlanHash > hashtable_cache_key_
const double bucket_threshold_
const Expr * get_right_operand() const
Definition: Analyzer.h:553
void setOverlapsHashtableMetaInfo(size_t max_table_size_bytes, double bucket_threshold, std::vector< double > &bucket_sizes)
virtual shared::TableKey getInnerTableId() const noexcept=0
std::vector< double > inverse_bucket_sizes_for_dimension_
#define CHECK_LT(x, y)
Definition: Logger.h:303
std::optional< HashType > layout_override_
static std::string getHashTypeString(HashType ht) noexcept
Definition: HashJoin.h:165
void setInverseBucketSizeInfo(const std::vector< double > &inverse_bucket_sizes, std::vector< ColumnsForDevice > &columns_per_device, const size_t device_count)
ColumnsForDevice fetchColumnsForDevice(const std::vector< Fragmenter_Namespace::FragmentInfo > &fragments, const int device_id, DeviceAllocator *dev_buff_owner)
CUstream getQueryEngineCudaStreamForDevice(int device_num)
Definition: QueryEngine.cpp:7
#define CHECK(condition)
Definition: Logger.h:291
#define DEBUG_TIMER(name)
Definition: Logger.h:411
const Data_Namespace::MemoryLevel memory_level_
void generateCacheKey(const size_t max_hashtable_size, const double bucket_threshold, const std::vector< double > &bucket_sizes, std::vector< std::vector< Fragmenter_Namespace::FragmentInfo >> &fragments_per_device, int device_count)
static std::unique_ptr< HashtableRecycler > hash_table_cache_
std::vector< InnerOuter > inner_outer_pairs_
std::unordered_set< size_t > table_keys_
void reifyForDevice(const ColumnsForDevice &columns_for_device, const HashType layout, const size_t entry_count, const size_t emitted_keys_count, const int device_id, const logger::ThreadLocalIds parent_thread_local_ids)
Data_Namespace::MemoryLevel effective_memory_level_
Data_Namespace::MemoryLevel getEffectiveMemoryLevel(const std::vector< InnerOuter > &inner_outer_pairs) const
const Analyzer::RangeOper * range_expr_
static constexpr DeviceIdentifier CPU_DEVICE_IDENTIFIER
Definition: DataRecycler.h:136
static HashtableAccessPathInfo getHashtableAccessPathInfo(const std::vector< InnerOuter > &inner_outer_pairs, const std::vector< InnerOuterStringOpInfos > &inner_outer_string_op_infos_pairs, const SQLOps op_type, const JoinType join_type, const HashTableBuildDagMap &hashtable_build_dag_map, int device_count, int shard_count, const std::vector< std::vector< Fragmenter_Namespace::FragmentInfo >> &frags_for_device, Executor *executor)
CompositeKeyInfo composite_key_info_
ThreadLocalIds thread_local_ids()
Definition: Logger.cpp:874
#define VLOG(n)
Definition: Logger.h:387
const size_t max_hashtable_size_

+ Here is the call graph for this function:

Member Data Documentation

const double RangeJoinHashTable::bucket_threshold_ {std::numeric_limits<double>::max()}
private

Definition at line 130 of file RangeJoinHashTable.h.

Referenced by computeRangeHashTableCounts(), and reifyWithLayout().

Data_Namespace::MemoryLevel RangeJoinHashTable::effective_memory_level_
private

Definition at line 129 of file RangeJoinHashTable.h.

Referenced by approximateTupleCount(), reifyForDevice(), and reifyWithLayout().

std::shared_ptr<Analyzer::ColumnVar> RangeJoinHashTable::inner_col_expr_
private

Definition at line 128 of file RangeJoinHashTable.h.

const size_t RangeJoinHashTable::max_hashtable_size_ {std::numeric_limits<size_t>::max()}
private

Definition at line 131 of file RangeJoinHashTable.h.

Referenced by computeRangeHashTableCounts(), and reifyWithLayout().

const Analyzer::RangeOper* RangeJoinHashTable::range_expr_
private

Definition at line 127 of file RangeJoinHashTable.h.

Referenced by isInnerColCompressed(), and reifyWithLayout().


The documentation for this class was generated from the following files: