@@ -66,46 +66,83 @@ HashBuild::HashBuild(
6666      joinBridge_ (operatorCtx_->task ()->getHashJoinBridgeLocked(
6767          operatorCtx_->driverCtx ()->splitGroupId,
6868          planNodeId())),
69-       keyChannelMap_(joinNode_->rightKeys ().size()) {
69+       keyChannelMap_(joinNode_->rightKeys ().size()),
70+       reusedHashTableAddress_(joinNode_->reusedHashTableAddress ()) {
7071  VELOX_CHECK (pool ()->trackUsage ());
7172  VELOX_CHECK_NOT_NULL (joinBridge_);
7273
7374  joinBridge_->addBuilder ();
7475
75-   const  auto & inputType = joinNode_->sources ()[1 ]->outputType ();
76- 
77-   const  auto  numKeys = joinNode_->rightKeys ().size ();
78-   keyChannels_.reserve (numKeys);
79- 
80-   for  (int  i = 0 ; i < numKeys; ++i) {
81-     auto & key = joinNode_->rightKeys ()[i];
82-     auto  channel = exprToChannel (key.get (), inputType);
83-     keyChannelMap_[channel] = i;
84-     keyChannels_.emplace_back (channel);
85-   }
86- 
87-   //  Identify the non-key build side columns and make a decoder for each.
88-   const  int32_t  numDependents = inputType->size () - numKeys;
89-   if  (numDependents > 0 ) {
90-     //  Number of join keys (numKeys) may be less then number of input columns
91-     //  (inputType->size()). In this case numDependents is negative and cannot be
92-     //  used to call 'reserve'. This happens when we join different probe side
93-     //  keys with the same build side key: SELECT * FROM t LEFT JOIN u ON t.k1 =
94-     //  u.k AND t.k2 = u.k.
95-     dependentChannels_.reserve (numDependents);
96-     decoders_.reserve (numDependents);
97-   }
98-   for  (auto  i = 0 ; i < inputType->size (); ++i) {
99-     if  (keyChannelMap_.find (i) == keyChannelMap_.end ()) {
100-       dependentChannels_.emplace_back (i);
101-       decoders_.emplace_back (std::make_unique<DecodedVector>());
76+   if  (reusedHashTableAddress_ != nullptr ) {
77+     auto  baseHashTable =
78+         reinterpret_cast <exec::BaseHashTable*>(reusedHashTableAddress_);
79+ 
80+     VELOX_CHECK_NOT_NULL (joinBridge_);
81+     joinBridge_->start ();
82+ 
83+     if  (baseHashTable->joinHasNullKeys () && isAntiJoin (joinType_) &&
84+         nullAware_ && !joinNode_->filter ()) {
85+       joinBridge_->setAntiJoinHasNullKeys ();
86+     } else  {
87+       baseHashTable->prepareJoinTable (
88+           {}, BaseHashTable::kNoSpillInputStartPartitionBit );
89+ 
90+       VELOX_CHECK_NOT_NULL (joinBridge_);
91+       std::unique_ptr<
92+           exec::BaseHashTable,
93+           std::function<void (exec::BaseHashTable*)>>
94+           hashTable (nullptr , [](exec::BaseHashTable* ptr) { /*  Do nothing */   });
95+ 
96+       if  (auto  hasheTableWithNullKeys =
97+               dynamic_cast <exec::HashTable<true >*>(baseHashTable)) {
98+         hashTable.reset (hasheTableWithNullKeys);
99+       } else  if  (
100+           auto  hasheTableWithoutNullKeys =
101+               dynamic_cast <exec::HashTable<false >*>(baseHashTable)) {
102+         hashTable.reset (hasheTableWithoutNullKeys);
103+       } else  {
104+         VELOX_UNREACHABLE (" Unexpected HashTable {}"  , baseHashTable->toString ());
105+       }
106+       joinBridge_->setHashTable (
107+           std::move (hashTable), hashTable->joinHasNullKeys ());
102108    }
103-   }
104109
105-   tableType_ = hashJoinTableType (joinNode_);
106-   setupTable ();
107-   setupSpiller ();
108-   stateCleared_ = false ;
110+   } else  {
111+     const  auto & inputType = joinNode_->sources ()[1 ]->outputType ();
112+ 
113+     const  auto  numKeys = joinNode_->rightKeys ().size ();
114+     keyChannels_.reserve (numKeys);
115+ 
116+     for  (int  i = 0 ; i < numKeys; ++i) {
117+       auto & key = joinNode_->rightKeys ()[i];
118+       auto  channel = exprToChannel (key.get (), inputType);
119+       keyChannelMap_[channel] = i;
120+       keyChannels_.emplace_back (channel);
121+     }
122+ 
123+     //  Identify the non-key build side columns and make a decoder for each.
124+     const  int32_t  numDependents = inputType->size () - numKeys;
125+     if  (numDependents > 0 ) {
126+       //  Number of join keys (numKeys) may be less then number of input columns
127+       //  (inputType->size()). In this case numDependents is negative and cannot
128+       //  be used to call 'reserve'. This happens when we join different probe
129+       //  side keys with the same build side key: SELECT * FROM t LEFT JOIN u ON
130+       //  t.k1 = u.k AND t.k2 = u.k.
131+       dependentChannels_.reserve (numDependents);
132+       decoders_.reserve (numDependents);
133+     }
134+     for  (auto  i = 0 ; i < inputType->size (); ++i) {
135+       if  (keyChannelMap_.find (i) == keyChannelMap_.end ()) {
136+         dependentChannels_.emplace_back (i);
137+         decoders_.emplace_back (std::make_unique<DecodedVector>());
138+       }
139+     }
140+ 
141+     tableType_ = hashJoinTableType (joinNode_);
142+     setupTable ();
143+     setupSpiller ();
144+     stateCleared_ = false ;
145+   }
109146}
110147
111148void  HashBuild::initialize () {
@@ -622,6 +659,10 @@ void HashBuild::spillPartition(
622659}
623660
624661void  HashBuild::noMoreInput () {
662+   if  (reusedHashTableAddress_ != nullptr ) {
663+     return ;
664+   }
665+ 
625666  checkRunning ();
626667
627668  if  (noMoreInput_) {
@@ -995,6 +1036,9 @@ BlockingReason HashBuild::isBlocked(ContinueFuture* future) {
9951036}
9961037
9971038bool  HashBuild::isFinished () {
1039+   if  (reusedHashTableAddress_ != nullptr ) {
1040+     return  true ;
1041+   }
9981042  return  state_ == State::kFinish ;
9991043}
10001044
0 commit comments