This is an automated email from the ASF dual-hosted git repository.
BiteTheDDDDt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 85767429400 [Chore](be) Reject right anti hash mark join plans (#63482)
85767429400 is described below
commit 8576742940065ccc8e979159bccb2be822efbde4
Author: Pxl <[email protected]>
AuthorDate: Fri May 22 15:20:13 2026 +0800
[Chore](be) Reject right anti hash mark join plans (#63482)
Problem Summary: Hash mark join currently supports left semi/anti,
null-aware left semi/anti, and right semi plans. Current FE rules do not
generate right anti mark hash join from SQL, but a malformed or future
plan could still reach BE hash join operators. The right anti mark path
is not a supported hash mark join shape, so reject it during hash join
build/probe operator initialization instead of allowing the unsupported
plan to proceed.
---
be/src/exec/operator/hashjoin_build_sink.cpp | 5 +++++
be/src/exec/operator/join_build_sink_operator.cpp | 6 +++---
be/test/exec/operator/hashjoin_build_sink_test.cpp | 21 +++++++++++++++++++++
3 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/be/src/exec/operator/hashjoin_build_sink.cpp
b/be/src/exec/operator/hashjoin_build_sink.cpp
index 1d5d4e84261..4c5815c71ab 100644
--- a/be/src/exec/operator/hashjoin_build_sink.cpp
+++ b/be/src/exec/operator/hashjoin_build_sink.cpp
@@ -700,6 +700,11 @@
HashJoinBuildSinkOperatorX::HashJoinBuildSinkOperatorX(ObjectPool* pool, int ope
Status HashJoinBuildSinkOperatorX::init(const TPlanNode& tnode, RuntimeState*
state) {
RETURN_IF_ERROR(JoinBuildSinkOperatorX::init(tnode, state));
DCHECK(tnode.__isset.hash_join_node);
+ if (_is_mark_join && _join_op == TJoinOp::RIGHT_ANTI_JOIN) {
+ return Status::InternalError(
+ "Hash join does not support right anti mark join, query={},
node={}, join_op={}",
+ print_id(state->query_id()), node_id(), to_string(_join_op));
+ }
if (tnode.hash_join_node.__isset.hash_output_slot_ids) {
_hash_output_slot_ids = tnode.hash_join_node.hash_output_slot_ids;
diff --git a/be/src/exec/operator/join_build_sink_operator.cpp
b/be/src/exec/operator/join_build_sink_operator.cpp
index 01b61ae1e81..719b33fab2e 100644
--- a/be/src/exec/operator/join_build_sink_operator.cpp
+++ b/be/src/exec/operator/join_build_sink_operator.cpp
@@ -77,9 +77,9 @@
JoinBuildSinkOperatorX<LocalStateType>::JoinBuildSinkOperatorX(ObjectPool* pool,
DCHECK(_join_op == TJoinOp::LEFT_ANTI_JOIN || _join_op ==
TJoinOp::LEFT_SEMI_JOIN ||
_join_op == TJoinOp::CROSS_JOIN || _join_op ==
TJoinOp::NULL_AWARE_LEFT_ANTI_JOIN ||
_join_op == TJoinOp::NULL_AWARE_LEFT_SEMI_JOIN ||
- _join_op == TJoinOp::RIGHT_SEMI_JOIN)
- << "Mark join is only supported for null aware left semi/anti
join and right semi "
- "join and cross join "
+ _join_op == TJoinOp::RIGHT_SEMI_JOIN || _join_op ==
TJoinOp::RIGHT_ANTI_JOIN)
+ << "Mark join is only supported for null aware left semi/anti
join, right "
+ "semi/anti join and cross join "
"but this is "
<< _join_op;
}
diff --git a/be/test/exec/operator/hashjoin_build_sink_test.cpp
b/be/test/exec/operator/hashjoin_build_sink_test.cpp
index 20b66132949..26dcbcc65e4 100644
--- a/be/test/exec/operator/hashjoin_build_sink_test.cpp
+++ b/be/test/exec/operator/hashjoin_build_sink_test.cpp
@@ -208,6 +208,27 @@ TEST_F(HashJoinBuildSinkTest,
RejectBroadcastJoinThatRequiresBuildSideFinalize)
}
}
+TEST_F(HashJoinBuildSinkTest, RightAntiMarkJoinRejected) {
+ auto tnode = _helper.create_test_plan_node(TJoinOp::RIGHT_ANTI_JOIN,
+ {TPrimitiveType::INT,
TPrimitiveType::STRING},
+ {false, false}, {false, false},
true, 1);
+ auto [probe_operator, sink_operator] = _helper.create_operators(tnode);
+ ASSERT_TRUE(probe_operator);
+ ASSERT_TRUE(sink_operator);
+
+ auto runtime_state = std::make_unique<MockRuntimeState>();
+ runtime_state->_query_ctx = _helper.query_ctx.get();
+ runtime_state->_query_id = _helper.query_ctx->query_id();
+ runtime_state->resize_op_id_to_local_state(-100);
+ runtime_state->set_max_operator_id(-100);
+ runtime_state->set_desc_tbl(_helper.desc_tbl);
+
+ auto st = sink_operator->init(tnode, runtime_state.get());
+ ASSERT_FALSE(st.ok());
+ EXPECT_THAT(st.to_string(), testing::HasSubstr("right anti mark join"));
+ EXPECT_THAT(st.to_string(), testing::HasSubstr("node=0"));
+}
+
TEST_F(HashJoinBuildSinkTest, Sink) {
auto test_block = [&](TJoinOp::type op_type, const
std::vector<TPrimitiveType::type>& key_types,
const std::vector<bool>& left_nullables,
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]