@@ -34,7 +34,7 @@ Status HashJoinProbeLocalState::init(RuntimeState* state, LocalStateInfo& info)
3434 SCOPED_TIMER (profile ()->total_time_counter ());
3535 SCOPED_TIMER (_open_timer);
3636 auto & p = _parent->cast <HashJoinProbeOperatorX>();
37- _probe_ignore_null = p._probe_ignore_null ;
37+ _shared_state-> probe_ignore_null = p._probe_ignore_null ;
3838 _probe_expr_ctxs.resize (p._probe_expr_ctxs .size ());
3939 for (size_t i = 0 ; i < _probe_expr_ctxs.size (); i++) {
4040 RETURN_IF_ERROR (p._probe_expr_ctxs [i]->clone (state, _probe_expr_ctxs[i]));
@@ -43,11 +43,6 @@ Status HashJoinProbeLocalState::init(RuntimeState* state, LocalStateInfo& info)
4343 for (size_t i = 0 ; i < _other_join_conjuncts.size (); i++) {
4444 RETURN_IF_ERROR (p._other_join_conjuncts [i]->clone (state, _other_join_conjuncts[i]));
4545 }
46- // Since the comparison of null values is meaningless, null aware left anti join should not output null
47- // when the build side is not empty.
48- if (!_shared_state->build_blocks ->empty () && p._join_op == TJoinOp::NULL_AWARE_LEFT_ANTI_JOIN ) {
49- _probe_ignore_null = true ;
50- }
5146 _construct_mutable_join_block ();
5247 _probe_column_disguise_null.reserve (_probe_expr_ctxs.size ());
5348 _probe_arena_memory_usage =
@@ -189,6 +184,42 @@ Status HashJoinProbeOperatorX::pull(doris::RuntimeState* state, vectorized::Bloc
189184 local_state.init_for_probe (state);
190185 SCOPED_TIMER (local_state._probe_timer );
191186 if (local_state._shared_state ->short_circuit_for_probe ) {
187+ // / If `_short_circuit_for_probe` is true, this indicates no rows
188+ // / match the join condition, and this is 'mark join', so we need to create a column as mark
189+ // / with all rows set to 0.
190+ if (_is_mark_join) {
191+ auto block_rows = local_state._probe_block .rows ();
192+ if (block_rows == 0 ) {
193+ if (local_state._probe_eos ) {
194+ source_state = SourceState::FINISHED ;
195+ }
196+ return Status::OK ();
197+ }
198+
199+ vectorized::Block temp_block;
200+ // get probe side output column
201+ for (int i = 0 ; i < _left_output_slot_flags.size (); ++i) {
202+ if (_left_output_slot_flags[i]) {
203+ temp_block.insert (local_state._probe_block .get_by_position (i));
204+ }
205+ }
206+ auto mark_column = vectorized::ColumnUInt8::create (block_rows, 0 );
207+ temp_block.insert (
208+ {std::move (mark_column), std::make_shared<vectorized::DataTypeUInt8>(), " " });
209+
210+ {
211+ SCOPED_TIMER (local_state._join_filter_timer );
212+ RETURN_IF_ERROR (vectorized::VExprContext::filter_block (
213+ local_state._conjuncts , &temp_block, temp_block.columns ()));
214+ }
215+
216+ RETURN_IF_ERROR (local_state._build_output_block (&temp_block, output_block, false ));
217+ temp_block.clear ();
218+ local_state._probe_block .clear_column_data (
219+ _child_x->row_desc ().num_materialized_slots ());
220+ local_state.reached_limit (output_block, source_state);
221+ return Status::OK ();
222+ }
192223 // If we use a short-circuit strategy, should return empty block directly.
193224 source_state = SourceState::FINISHED ;
194225 return Status::OK ();
@@ -241,7 +272,7 @@ Status HashJoinProbeOperatorX::pull(doris::RuntimeState* state, vectorized::Bloc
241272 *local_state._shared_state ->hash_table_variants ,
242273 *local_state._process_hashtable_ctx_variants ,
243274 vectorized::make_bool_variant (local_state._need_null_map_for_probe ),
244- vectorized::make_bool_variant (local_state._probe_ignore_null ));
275+ vectorized::make_bool_variant (local_state._shared_state -> probe_ignore_null ));
245276 });
246277 } else if (local_state._probe_eos ) {
247278 if (_is_right_semi_anti || (_is_outer_join && _join_op != TJoinOp::LEFT_OUTER_JOIN )) {
@@ -299,7 +330,8 @@ bool HashJoinProbeOperatorX::need_more_input_data(RuntimeState* state) const {
299330 auto & local_state = state->get_local_state (id ())->cast <HashJoinProbeLocalState>();
300331 return (local_state._probe_block .rows () == 0 ||
301332 local_state._probe_index == local_state._probe_block .rows ()) &&
302- !local_state._probe_eos && !local_state._shared_state ->short_circuit_for_probe ;
333+ !local_state._probe_eos &&
334+ (!local_state._shared_state ->short_circuit_for_probe || _is_mark_join);
303335}
304336
305337Status HashJoinProbeOperatorX::_do_evaluate (vectorized::Block& block,
0 commit comments