21
21
#include < Interpreters/JoinUtils.h>
22
22
#include < Interpreters/JoinV2/HashJoin.h>
23
23
#include < Interpreters/JoinV2/HashJoinProbe.h>
24
+ #include < Interpreters/JoinV2/SemiJoinProbe.h>
24
25
#include < Interpreters/NullableUtils.h>
25
26
#include < Parsers/ASTTablesInSelectQuery.h>
26
27
@@ -39,7 +40,9 @@ bool JoinProbeContext::isProbeFinished() const
39
40
{
40
41
return current_row_idx >= rows
41
42
// For prefetching
42
- && prefetch_active_states == 0 ;
43
+ && prefetch_active_states == 0
44
+ // For (left outer) (anti) semi join with other conditions
45
+ && (semi_join_probe_list == nullptr || semi_join_probe_list->activeSlots () == 0 );
43
46
}
44
47
45
48
bool JoinProbeContext::isAllFinished () const
@@ -71,6 +74,7 @@ void JoinProbeContext::prepareForHashProbe(
71
74
HashJoinKeyMethod method,
72
75
ASTTableJoin::Kind kind,
73
76
bool has_other_condition,
77
+ bool has_other_eq_cond_from_in,
74
78
const Names & key_names,
75
79
const String & filter_column,
76
80
const NameSet & probe_output_name_set,
@@ -123,6 +127,23 @@ void JoinProbeContext::prepareForHashProbe(
123
127
{
124
128
left_semi_match_res.clear ();
125
129
left_semi_match_res.resize_fill_zero (rows);
130
+ if (has_other_eq_cond_from_in)
131
+ {
132
+ left_semi_match_null_res.clear ();
133
+ left_semi_match_null_res.resize_fill_zero (rows);
134
+ }
135
+ }
136
+ if ((kind == Semi || kind == Anti) && has_other_condition)
137
+ {
138
+ semi_selective_offsets.clear ();
139
+ semi_selective_offsets.reserve (rows);
140
+ }
141
+
142
+ if (SemiJoinProbeHelper::isSupported (kind, has_other_condition))
143
+ {
144
+ if unlikely (!semi_join_probe_list)
145
+ semi_join_probe_list = createSemiJoinProbeList (method);
146
+ semi_join_probe_list->reset (rows);
126
147
}
127
148
128
149
is_prepared = true ;
@@ -634,16 +655,17 @@ void JoinProbeHelper::probeFillColumns(JoinProbeContext & ctx, JoinProbeWorkerDa
634
655
using Adder = JoinProbeAdder<kind, has_other_condition, late_materialization>;
635
656
636
657
auto & key_getter = *static_cast <KeyGetterType *>(ctx.key_getter .get ());
658
+ // Some columns in wd.result_block may remain empty due to late materialization for join with other conditions.
659
+ // But since all columns are cleared after handling other conditions, wd.result_block.rows() is always 0.
637
660
size_t current_offset = wd.result_block .rows ();
661
+ if constexpr (has_other_condition)
662
+ RUNTIME_CHECK (current_offset == 0 );
638
663
size_t idx = ctx.current_row_idx ;
639
664
RowPtr ptr = ctx.current_build_row_ptr ;
640
665
bool is_matched = ctx.current_row_is_matched ;
641
666
size_t collision = 0 ;
642
- size_t key_offset = sizeof (RowPtr);
643
- if constexpr (KeyGetterType::joinKeyCompareHashFirst ())
644
- {
645
- key_offset += sizeof (HashValueType);
646
- }
667
+ constexpr size_t key_offset
668
+ = sizeof (RowPtr) + (KeyGetterType::joinKeyCompareHashFirst () ? sizeof (HashValueType) : 0 );
647
669
648
670
#define NOT_MATCHED (not_matched ) \
649
671
if constexpr (Adder::need_not_matched) \
@@ -782,8 +804,10 @@ struct ProbePrefetchState
782
804
KeyType key{};
783
805
union
784
806
{
785
- RowPtr ptr = nullptr ;
786
- std::atomic<RowPtr> * pointer_ptr;
807
+ // / Used when stage is FindHeader
808
+ std::atomic<RowPtr> * pointer_ptr = nullptr ;
809
+ // / Used when stage is FindNext
810
+ RowPtr ptr;
787
811
};
788
812
};
789
813
@@ -801,24 +825,26 @@ void JoinProbeHelper::probeFillColumnsPrefetch(
801
825
using Adder = JoinProbeAdder<kind, has_other_condition, late_materialization>;
802
826
803
827
auto & key_getter = *static_cast <KeyGetterType *>(ctx.key_getter .get ());
804
- if (!ctx.prefetch_states )
828
+ const size_t probe_prefetch_step = settings.probe_prefetch_step ;
829
+ if unlikely (!ctx.prefetch_states )
805
830
{
806
831
ctx.prefetch_states = decltype (ctx.prefetch_states )(
807
- static_cast <void *>(new ProbePrefetchState<KeyGetter>[settings. probe_prefetch_step ]),
832
+ static_cast <void *>(new ProbePrefetchState<KeyGetter>[probe_prefetch_step]),
808
833
[](void * ptr) { delete[] static_cast <ProbePrefetchState<KeyGetter> *>(ptr); });
809
834
}
810
835
auto * states = static_cast <ProbePrefetchState<KeyGetter> *>(ctx.prefetch_states .get ());
811
836
812
837
size_t idx = ctx.current_row_idx ;
813
838
size_t active_states = ctx.prefetch_active_states ;
814
839
size_t k = ctx.prefetch_iter ;
840
+ // Some columns in wd.result_block may remain empty due to late materialization for join with other conditions.
841
+ // But since all columns are cleared after handling other conditions, wd.result_block.rows() is always 0.
815
842
size_t current_offset = wd.result_block .rows ();
843
+ if constexpr (has_other_condition)
844
+ RUNTIME_CHECK (current_offset == 0 );
816
845
size_t collision = 0 ;
817
- size_t key_offset = sizeof (RowPtr);
818
- if constexpr (KeyGetterType::joinKeyCompareHashFirst ())
819
- {
820
- key_offset += sizeof (HashValueType);
821
- }
846
+ constexpr size_t key_offset
847
+ = sizeof (RowPtr) + (KeyGetterType::joinKeyCompareHashFirst () ? sizeof (HashValueType) : 0 );
822
848
823
849
#define NOT_MATCHED (not_matched, idx ) \
824
850
if constexpr (Adder::need_not_matched) \
@@ -831,7 +857,6 @@ void JoinProbeHelper::probeFillColumnsPrefetch(
831
857
} \
832
858
}
833
859
834
- const size_t probe_prefetch_step = settings.probe_prefetch_step ;
835
860
while (idx < ctx.rows || active_states > 0 )
836
861
{
837
862
k = k == probe_prefetch_step ? 0 : k;
@@ -845,11 +870,10 @@ void JoinProbeHelper::probeFillColumnsPrefetch(
845
870
const auto & key2 = key_getter.deserializeJoinKey (ptr + key_offset);
846
871
bool key_is_equal = joinKeyIsEqual (key_getter, state->key , key2, state->hash , ptr);
847
872
collision += !key_is_equal;
873
+ if constexpr (Adder::need_not_matched)
874
+ state->is_matched |= key_is_equal;
848
875
if (key_is_equal)
849
876
{
850
- if constexpr (Adder::need_not_matched)
851
- state->is_matched = true ;
852
-
853
877
if constexpr (Adder::need_matched)
854
878
{
855
879
bool is_end = Adder::addMatched (
@@ -1026,6 +1050,17 @@ Block JoinProbeHelper::handleOtherConditions(
1026
1050
1027
1051
non_equal_conditions.other_cond_expr ->execute (exec_block);
1028
1052
1053
+ SCOPE_EXIT ({
1054
+ RUNTIME_CHECK (wd.result_block .columns () == left_columns + right_columns);
1055
+ // / Clear the data in result_block.
1056
+ for (size_t i = 0 ; i < left_columns + right_columns; ++i)
1057
+ {
1058
+ auto column = wd.result_block .getByPosition (i).column ->assumeMutable ();
1059
+ column->popBack (column->size ());
1060
+ wd.result_block .getByPosition (i).column = std::move (column);
1061
+ }
1062
+ });
1063
+
1029
1064
size_t rows = exec_block.rows ();
1030
1065
// Ensure BASE_OFFSETS is accessed within bound.
1031
1066
// It must be true because max_block_size <= BASE_OFFSETS.size(HASH_JOIN_MAX_BLOCK_SIZE_UPPER_BOUND).
@@ -1212,17 +1247,6 @@ Block JoinProbeHelper::handleOtherConditions(
1212
1247
}
1213
1248
};
1214
1249
1215
- SCOPE_EXIT ({
1216
- RUNTIME_CHECK (wd.result_block .columns () == left_columns + right_columns);
1217
- // / Clear the data in result_block.
1218
- for (size_t i = 0 ; i < left_columns + right_columns; ++i)
1219
- {
1220
- auto column = wd.result_block .getByPosition (i).column ->assumeMutable ();
1221
- column->popBack (column->size ());
1222
- wd.result_block .getByPosition (i).column = std::move (column);
1223
- }
1224
- });
1225
-
1226
1250
size_t length = std::min (result_size, remaining_insert_size);
1227
1251
fill_matched (0 , length);
1228
1252
if (result_size >= remaining_insert_size)
0 commit comments