From 74f1037836d01391102312f6cca7fadd9f9d8848 Mon Sep 17 00:00:00 2001 From: shuke <37901441+shuke987@users.noreply.github.com> Date: Mon, 20 Jul 2026 11:46:24 +0800 Subject: [PATCH 1/5] [test](fe) Remove flaky DistributeHintTest.testLeading --- .../joinorder/joinhint/DistributeHintTest.java | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/joinhint/DistributeHintTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/joinhint/DistributeHintTest.java index 7f3b6aa12c5338..c9761e2a531677 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/joinhint/DistributeHintTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/joinhint/DistributeHintTest.java @@ -50,23 +50,6 @@ public class DistributeHintTest extends TPCHTestBase { private List failCases = new ArrayList<>(); - @Test - public void testLeading() { - for (int t = 3; t < 10; t++) { - for (int e = t - 1; e <= (t * (t - 1)) / 2; e++) { - for (int i = 0; i < 10; i++) { - System.out.println("TableNumber: " + String.valueOf(t) + " EdgeNumber: " + e + " Iteration: " + i); - randomTest(t, e, false, true); - } - } - } - int totalCases = successCases + unsuccessCases; - System.out.println("TotalCases: " + totalCases + "\tSuccessCases: " + successCases + unsuccessCases + "\tUnSuccessCases: " + 0); - for (String treePlan : failCases) { - System.out.println(treePlan); - } - } - @Test public void testHintJoin() { for (int t = 3; t < 10; t++) { From 350131233177c09eefc7cbc2d1dbae1683f24b9c Mon Sep 17 00:00:00 2001 From: shuke <37901441+shuke987@users.noreply.github.com> Date: Wed, 22 Jul 2026 10:48:41 +0800 Subject: [PATCH 2/5] [fix](fe) Reject invalid semi/anti leading constraints --- .../doris/nereids/hint/LeadingHint.java | 16 ++--- .../doris/nereids/hint/LeadingHintTest.java | 66 +++++++++++++++++++ 2 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 fe/fe-core/src/test/java/org/apache/doris/nereids/hint/LeadingHintTest.java diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/hint/LeadingHint.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/hint/LeadingHint.java index 7f67311204d349..633ae1c7604f38 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/hint/LeadingHint.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/hint/LeadingHint.java @@ -416,14 +416,14 @@ public Pair getJoinConstraint(Long joinTableBitmap, Lon continue; } - if (joinConstraint.getJoinType().isSemiJoin()) { - if (LongBitmap.isSubset(joinConstraint.getRightHand(), leftTableBitmap) - && !LongBitmap.isSubset(joinConstraint.getRightHand(), leftTableBitmap)) { - continue; - } - if (LongBitmap.isSubset(joinConstraint.getRightHand(), rightTableBitmap) - && !joinConstraint.getRightHand().equals(rightTableBitmap)) { - continue; + if (joinConstraint.getJoinType().isSemiOrAntiJoin()) { + Long constrainedSide = joinConstraint.getJoinType().isRightSemiOrAntiJoin() + ? joinConstraint.getLeftHand() : joinConstraint.getRightHand(); + if ((LongBitmap.isSubset(constrainedSide, leftTableBitmap) + && !constrainedSide.equals(leftTableBitmap)) + || (LongBitmap.isSubset(constrainedSide, rightTableBitmap) + && !constrainedSide.equals(rightTableBitmap))) { + return Pair.of(null, false); } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/hint/LeadingHintTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/hint/LeadingHintTest.java new file mode 100644 index 00000000000000..c47c13fd1cbb22 --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/hint/LeadingHintTest.java @@ -0,0 +1,66 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.hint; + +import org.apache.doris.common.Pair; +import org.apache.doris.nereids.jobs.joinorder.hypergraph.bitmap.LongBitmap; +import org.apache.doris.nereids.trees.plans.JoinType; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class LeadingHintTest { + + @Test + public void testRejectExtraTableOnSemiOrAntiJoinConstrainedSide() { + assertRejectedWithExtraTable(JoinType.LEFT_SEMI_JOIN); + assertRejectedWithExtraTable(JoinType.LEFT_ANTI_JOIN); + assertRejectedWithExtraTable(JoinType.RIGHT_SEMI_JOIN); + assertRejectedWithExtraTable(JoinType.RIGHT_ANTI_JOIN); + } + + private void assertRejectedWithExtraTable(JoinType joinType) { + LeadingHint leading = new LeadingHint("Leading"); + long leftHand = LongBitmap.newBitmap(0); + long rightHand = LongBitmap.newBitmap(1); + long extraTable = LongBitmap.newBitmap(2); + JoinConstraint joinConstraint = new JoinConstraint( + leftHand, rightHand, leftHand, rightHand, joinType, true); + leading.getJoinConstraintList().add(joinConstraint); + + Pair exactMatch = leading.getJoinConstraint( + LongBitmap.or(leftHand, rightHand), leftHand, rightHand); + Assertions.assertSame(joinConstraint, exactMatch.first); + Assertions.assertTrue(exactMatch.second); + + long leftTableBitmap; + long rightTableBitmap; + if (joinType.isRightSemiOrAntiJoin()) { + leftTableBitmap = LongBitmap.newBitmapUnion(leftHand, extraTable); + rightTableBitmap = rightHand; + } else { + leftTableBitmap = LongBitmap.newBitmapUnion(rightHand, extraTable); + rightTableBitmap = leftHand; + } + + Pair result = leading.getJoinConstraint( + LongBitmap.or(leftTableBitmap, rightTableBitmap), leftTableBitmap, rightTableBitmap); + Assertions.assertNull(result.first); + Assertions.assertFalse(result.second); + } +} From 1e8da631ce8ed2b532786e19355cd5e65cc56813 Mon Sep 17 00:00:00 2001 From: shuke <37901441+shuke987@users.noreply.github.com> Date: Wed, 22 Jul 2026 10:54:19 +0800 Subject: [PATCH 3/5] [fix](fe) Delay semi/anti constraints until both sides exist --- .../java/org/apache/doris/nereids/hint/LeadingHint.java | 4 ++++ .../java/org/apache/doris/nereids/hint/LeadingHintTest.java | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/hint/LeadingHint.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/hint/LeadingHint.java index 633ae1c7604f38..8dcc41e0aeb0d8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/hint/LeadingHint.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/hint/LeadingHint.java @@ -417,6 +417,10 @@ public Pair getJoinConstraint(Long joinTableBitmap, Lon } if (joinConstraint.getJoinType().isSemiOrAntiJoin()) { + if (!LongBitmap.isSubset(joinConstraint.getMinLeftHand(), joinTableBitmap) + || !LongBitmap.isSubset(joinConstraint.getMinRightHand(), joinTableBitmap)) { + continue; + } Long constrainedSide = joinConstraint.getJoinType().isRightSemiOrAntiJoin() ? joinConstraint.getLeftHand() : joinConstraint.getRightHand(); if ((LongBitmap.isSubset(constrainedSide, leftTableBitmap) diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/hint/LeadingHintTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/hint/LeadingHintTest.java index c47c13fd1cbb22..a65611605b6d09 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/hint/LeadingHintTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/hint/LeadingHintTest.java @@ -48,6 +48,12 @@ private void assertRejectedWithExtraTable(JoinType joinType) { Assertions.assertSame(joinConstraint, exactMatch.first); Assertions.assertTrue(exactMatch.second); + long constrainedSide = joinType.isRightSemiOrAntiJoin() ? leftHand : rightHand; + Pair withoutRetainedSide = leading.getJoinConstraint( + LongBitmap.or(constrainedSide, extraTable), constrainedSide, extraTable); + Assertions.assertNull(withoutRetainedSide.first); + Assertions.assertTrue(withoutRetainedSide.second); + long leftTableBitmap; long rightTableBitmap; if (joinType.isRightSemiOrAntiJoin()) { From 1efd508e33b9e936cb3c7280fb52043f37048876 Mon Sep 17 00:00:00 2001 From: shuke <37901441+shuke987@users.noreply.github.com> Date: Wed, 22 Jul 2026 11:52:56 +0800 Subject: [PATCH 4/5] Revert "[fix](fe) Delay semi/anti constraints until both sides exist" This reverts commit 1e8da631ce8ed2b532786e19355cd5e65cc56813. --- .../java/org/apache/doris/nereids/hint/LeadingHint.java | 4 ---- .../java/org/apache/doris/nereids/hint/LeadingHintTest.java | 6 ------ 2 files changed, 10 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/hint/LeadingHint.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/hint/LeadingHint.java index 8dcc41e0aeb0d8..633ae1c7604f38 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/hint/LeadingHint.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/hint/LeadingHint.java @@ -417,10 +417,6 @@ public Pair getJoinConstraint(Long joinTableBitmap, Lon } if (joinConstraint.getJoinType().isSemiOrAntiJoin()) { - if (!LongBitmap.isSubset(joinConstraint.getMinLeftHand(), joinTableBitmap) - || !LongBitmap.isSubset(joinConstraint.getMinRightHand(), joinTableBitmap)) { - continue; - } Long constrainedSide = joinConstraint.getJoinType().isRightSemiOrAntiJoin() ? joinConstraint.getLeftHand() : joinConstraint.getRightHand(); if ((LongBitmap.isSubset(constrainedSide, leftTableBitmap) diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/hint/LeadingHintTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/hint/LeadingHintTest.java index a65611605b6d09..c47c13fd1cbb22 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/hint/LeadingHintTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/hint/LeadingHintTest.java @@ -48,12 +48,6 @@ private void assertRejectedWithExtraTable(JoinType joinType) { Assertions.assertSame(joinConstraint, exactMatch.first); Assertions.assertTrue(exactMatch.second); - long constrainedSide = joinType.isRightSemiOrAntiJoin() ? leftHand : rightHand; - Pair withoutRetainedSide = leading.getJoinConstraint( - LongBitmap.or(constrainedSide, extraTable), constrainedSide, extraTable); - Assertions.assertNull(withoutRetainedSide.first); - Assertions.assertTrue(withoutRetainedSide.second); - long leftTableBitmap; long rightTableBitmap; if (joinType.isRightSemiOrAntiJoin()) { From f9b67e8c3c32e348771ef1df9dc88f319f2b3dea Mon Sep 17 00:00:00 2001 From: shuke <37901441+shuke987@users.noreply.github.com> Date: Wed, 22 Jul 2026 11:53:02 +0800 Subject: [PATCH 5/5] Revert "[fix](fe) Reject invalid semi/anti leading constraints" This reverts commit 350131233177c09eefc7cbc2d1dbae1683f24b9c. --- .../doris/nereids/hint/LeadingHint.java | 16 ++--- .../doris/nereids/hint/LeadingHintTest.java | 66 ------------------- 2 files changed, 8 insertions(+), 74 deletions(-) delete mode 100644 fe/fe-core/src/test/java/org/apache/doris/nereids/hint/LeadingHintTest.java diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/hint/LeadingHint.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/hint/LeadingHint.java index 633ae1c7604f38..7f67311204d349 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/hint/LeadingHint.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/hint/LeadingHint.java @@ -416,14 +416,14 @@ public Pair getJoinConstraint(Long joinTableBitmap, Lon continue; } - if (joinConstraint.getJoinType().isSemiOrAntiJoin()) { - Long constrainedSide = joinConstraint.getJoinType().isRightSemiOrAntiJoin() - ? joinConstraint.getLeftHand() : joinConstraint.getRightHand(); - if ((LongBitmap.isSubset(constrainedSide, leftTableBitmap) - && !constrainedSide.equals(leftTableBitmap)) - || (LongBitmap.isSubset(constrainedSide, rightTableBitmap) - && !constrainedSide.equals(rightTableBitmap))) { - return Pair.of(null, false); + if (joinConstraint.getJoinType().isSemiJoin()) { + if (LongBitmap.isSubset(joinConstraint.getRightHand(), leftTableBitmap) + && !LongBitmap.isSubset(joinConstraint.getRightHand(), leftTableBitmap)) { + continue; + } + if (LongBitmap.isSubset(joinConstraint.getRightHand(), rightTableBitmap) + && !joinConstraint.getRightHand().equals(rightTableBitmap)) { + continue; } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/hint/LeadingHintTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/hint/LeadingHintTest.java deleted file mode 100644 index c47c13fd1cbb22..00000000000000 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/hint/LeadingHintTest.java +++ /dev/null @@ -1,66 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -package org.apache.doris.nereids.hint; - -import org.apache.doris.common.Pair; -import org.apache.doris.nereids.jobs.joinorder.hypergraph.bitmap.LongBitmap; -import org.apache.doris.nereids.trees.plans.JoinType; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class LeadingHintTest { - - @Test - public void testRejectExtraTableOnSemiOrAntiJoinConstrainedSide() { - assertRejectedWithExtraTable(JoinType.LEFT_SEMI_JOIN); - assertRejectedWithExtraTable(JoinType.LEFT_ANTI_JOIN); - assertRejectedWithExtraTable(JoinType.RIGHT_SEMI_JOIN); - assertRejectedWithExtraTable(JoinType.RIGHT_ANTI_JOIN); - } - - private void assertRejectedWithExtraTable(JoinType joinType) { - LeadingHint leading = new LeadingHint("Leading"); - long leftHand = LongBitmap.newBitmap(0); - long rightHand = LongBitmap.newBitmap(1); - long extraTable = LongBitmap.newBitmap(2); - JoinConstraint joinConstraint = new JoinConstraint( - leftHand, rightHand, leftHand, rightHand, joinType, true); - leading.getJoinConstraintList().add(joinConstraint); - - Pair exactMatch = leading.getJoinConstraint( - LongBitmap.or(leftHand, rightHand), leftHand, rightHand); - Assertions.assertSame(joinConstraint, exactMatch.first); - Assertions.assertTrue(exactMatch.second); - - long leftTableBitmap; - long rightTableBitmap; - if (joinType.isRightSemiOrAntiJoin()) { - leftTableBitmap = LongBitmap.newBitmapUnion(leftHand, extraTable); - rightTableBitmap = rightHand; - } else { - leftTableBitmap = LongBitmap.newBitmapUnion(rightHand, extraTable); - rightTableBitmap = leftHand; - } - - Pair result = leading.getJoinConstraint( - LongBitmap.or(leftTableBitmap, rightTableBitmap), leftTableBitmap, rightTableBitmap); - Assertions.assertNull(result.first); - Assertions.assertFalse(result.second); - } -}