This is an automated email from the ASF dual-hosted git repository. yiguolei pushed a commit to branch branch-2.1 in repository https://gitbox.apache.org/repos/asf/doris.git
commit 90c69b020ad4cf1b7456c5bdfdbcaae3dbec7969 Author: LiBinfeng <46676950+libinfeng...@users.noreply.github.com> AuthorDate: Fri Apr 12 15:06:02 2024 +0800 [Fix](Nereids) fix leading hint should have all tables in one query block (#33517) --- .../org/apache/doris/nereids/hint/LeadingHint.java | 59 +++++++++++----------- .../doris/nereids/rules/analysis/LeadingJoin.java | 2 +- .../data/nereids_p0/hint/fix_leading.out | 25 +++++++++ .../data/nereids_p0/hint/multi_leading.out | 4 +- .../suites/nereids_p0/hint/fix_leading.groovy | 4 ++ .../suites/nereids_p0/hint/multi_leading.groovy | 8 +-- 6 files changed, 65 insertions(+), 37 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 1f48e4873cb..3ef5217566a 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 @@ -17,7 +17,6 @@ package org.apache.doris.nereids.hint; -import org.apache.doris.catalog.TableIf; import org.apache.doris.common.Pair; import org.apache.doris.nereids.jobs.joinorder.hypergraph.bitmap.LongBitmap; import org.apache.doris.nereids.trees.expressions.ExprId; @@ -226,14 +225,14 @@ public class LeadingHint extends Hint { return null; } - private boolean hasSameName() { + private Optional<String> hasSameName() { Set<String> tableSet = Sets.newHashSet(); for (String table : tablelist) { if (!tableSet.add(table)) { - return true; + return Optional.of(table); } } - return false; + return Optional.empty(); } public Map<ExprId, String> getExprIdToTableNameMap() { @@ -287,12 +286,14 @@ public class LeadingHint extends Hint { /** * set total bitmap used in leading before we get into leading join */ - public void setTotalBitmap() { + public void setTotalBitmap(Set<RelationId> inputRelationSets) { Long totalBitmap = 0L; - if (hasSameName()) { + Optional<String> duplicateTableName = hasSameName(); + if (duplicateTableName.isPresent()) { this.setStatus(HintStatus.SYNTAX_ERROR); - this.setErrorMessage("duplicated table"); + this.setErrorMessage("duplicated table:" + duplicateTableName.get()); } + Set<RelationId> existRelationSets = new HashSet<>(); for (int index = 0; index < getTablelist().size(); index++) { RelationId id = findRelationIdAndTableName(getTablelist().get(index)); if (id == null) { @@ -300,11 +301,32 @@ public class LeadingHint extends Hint { this.setErrorMessage("can not find table: " + getTablelist().get(index)); return; } + existRelationSets.add(id); totalBitmap = LongBitmap.set(totalBitmap, id.asInt()); } + if (getTablelist().size() < inputRelationSets.size()) { + Set<RelationId> missRelationIds = new HashSet<>(); + missRelationIds.addAll(inputRelationSets); + missRelationIds.removeAll(existRelationSets); + String missingTablenames = getMissingTableNames(missRelationIds); + this.setStatus(HintStatus.SYNTAX_ERROR); + this.setErrorMessage("leading should have all tables in query block, missing tables: " + missingTablenames); + } this.totalBitmap = totalBitmap; } + private String getMissingTableNames(Set<RelationId> missRelationIds) { + String missTableNames = ""; + for (RelationId id : missRelationIds) { + for (Pair<RelationId, String> pair : relationIdAndTableName) { + if (pair.first.equals(id)) { + missTableNames += pair.second + " "; + } + } + } + return missTableNames; + } + /** * try to get join constraint, if can not get, it means join is inner join, * @param joinTableBitmap table bitmap below this join @@ -612,27 +634,4 @@ public class LeadingHint extends Hint { return null; } } - - /** - * get leading containing tables which means leading wants to combine tables into joins - * @return long value represent tables we included - */ - public Long getLeadingTableBitmap(List<TableIf> tables) { - Long totalBitmap = 0L; - if (hasSameName()) { - this.setStatus(HintStatus.SYNTAX_ERROR); - this.setErrorMessage("duplicated table"); - return totalBitmap; - } - for (int index = 0; index < getTablelist().size(); index++) { - RelationId id = findRelationIdAndTableName(getTablelist().get(index)); - if (id == null) { - this.setStatus(HintStatus.SYNTAX_ERROR); - this.setErrorMessage("can not find table: " + getTablelist().get(index)); - return totalBitmap; - } - totalBitmap = LongBitmap.set(totalBitmap, id.asInt()); - } - return totalBitmap; - } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/LeadingJoin.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/LeadingJoin.java index c8b19a1e9d5..9e94c745f77 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/LeadingJoin.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/LeadingJoin.java @@ -43,7 +43,7 @@ public class LeadingJoin implements RewriteRuleFactory { return ctx.root; } Hint leadingHint = ctx.cascadesContext.getHintMap().get("Leading"); - ((LeadingHint) leadingHint).setTotalBitmap(); + ((LeadingHint) leadingHint).setTotalBitmap(ctx.root.getInputRelations()); Long currentBitMap = LongBitmap.computeTableBitmap(ctx.root.getInputRelations()); if (((LeadingHint) leadingHint).getTotalBitmap().equals(currentBitMap) && leadingHint.isSuccess()) { diff --git a/regression-test/data/nereids_p0/hint/fix_leading.out b/regression-test/data/nereids_p0/hint/fix_leading.out index 2a83ff6eafe..c7bfec92f2d 100644 --- a/regression-test/data/nereids_p0/hint/fix_leading.out +++ b/regression-test/data/nereids_p0/hint/fix_leading.out @@ -256,3 +256,28 @@ Used: leading(t1 t2 t3 ) UnUsed: SyntaxError: +-- !select5_1 -- +PhysicalResultSink +--hashAgg[GLOBAL] +----PhysicalDistribute[DistributionSpecGather] +------hashAgg[LOCAL] +--------PhysicalProject +----------NestedLoopJoin[LEFT_OUTER_JOIN](t3.c3 > 500) +------------PhysicalProject +--------------PhysicalOlapScan[t3] +------------PhysicalDistribute[DistributionSpecReplicated] +--------------PhysicalProject +----------------NestedLoopJoin[LEFT_OUTER_JOIN](t1.c1 > 500) +------------------PhysicalProject +--------------------filter((t1.c1 < 200)) +----------------------PhysicalOlapScan[t1] +------------------PhysicalDistribute[DistributionSpecReplicated] +--------------------PhysicalProject +----------------------filter((t2.c2 > 500)) +------------------------PhysicalOlapScan[t2] + +Hint log: +Used: +UnUsed: +SyntaxError: leading(t1 t2) Msg:leading should have all tables in query block, missing tables: t3 + diff --git a/regression-test/data/nereids_p0/hint/multi_leading.out b/regression-test/data/nereids_p0/hint/multi_leading.out index 0efabe2002e..b602e97bcb9 100644 --- a/regression-test/data/nereids_p0/hint/multi_leading.out +++ b/regression-test/data/nereids_p0/hint/multi_leading.out @@ -264,7 +264,7 @@ PhysicalResultSink ----------------------PhysicalOlapScan[t1] Hint log: -Used: leading(t2 t1 ) leading(t3 alias1 ) +Used: leading(t2 t1 ) leading(t3 alias1 cte ) UnUsed: SyntaxError: @@ -330,7 +330,7 @@ PhysicalResultSink ----------------------PhysicalOlapScan[t1] Hint log: -Used: leading(t2 t1 ) leading(t2 t1 ) leading(t2 t1 ) leading(t3 alias1 ) +Used: leading(t2 t1 ) leading(t2 t1 ) leading(t2 t1 ) leading(t3 alias1 cte ) UnUsed: SyntaxError: diff --git a/regression-test/suites/nereids_p0/hint/fix_leading.groovy b/regression-test/suites/nereids_p0/hint/fix_leading.groovy index 6185789d2ba..49823e97698 100644 --- a/regression-test/suites/nereids_p0/hint/fix_leading.groovy +++ b/regression-test/suites/nereids_p0/hint/fix_leading.groovy @@ -170,4 +170,8 @@ suite("fix_leading") { qt_select4_1 """select count(*) from t1 left join t2 on c1 > 500 and c2 >500 right join t3 on c3 > 500 and c1 < 200;""" qt_select4_2 """select /*+ leading(t1 t2 t3)*/ count(*) from t1 left join t2 on c1 > 500 and c2 >500 right join t3 on c3 > 500 and c1 < 200;""" qt_select4_3 """explain shape plan select /*+ leading(t1 t2 t3)*/ count(*) from t1 left join t2 on c1 > 500 and c2 >500 right join t3 on c3 > 500 and c1 < 200;""" + + // check whether we have all tables + qt_select5_1 """explain shape plan select /*+ leading(t1 t2)*/ count(*) from t1 left join t2 on c1 > 500 and c2 >500 right join t3 on c3 > 500 and c1 < 200;""" + } diff --git a/regression-test/suites/nereids_p0/hint/multi_leading.groovy b/regression-test/suites/nereids_p0/hint/multi_leading.groovy index d1f83d15ebb..bd567ecdefa 100644 --- a/regression-test/suites/nereids_p0/hint/multi_leading.groovy +++ b/regression-test/suites/nereids_p0/hint/multi_leading.groovy @@ -98,14 +98,14 @@ suite("multi_leading") { // test subquery + cte qt_sql3_1 """explain shape plan with cte as (select c11, c1 from t1 join t2 on c1 = c2) select count(*) from (select c1, c11 from t1 join t2 on c1 = c2) as alias1 join t3 on alias1.c1 = t3.c3 join cte on alias1.c1 = cte.c11;""" - qt_sql3_2 """explain shape plan with cte as (select /*+ leading(t2 t1) */ c11, c1 from t1 join t2 on c1 = c2) select /*+ leading(t3 alias1) */ count(*) from (select c1, c11 from t1 join t2 on c1 = c2) as alias1 join t3 on alias1.c1 = t3.c3 join cte on alias1.c1 = cte.c11;;""" + qt_sql3_2 """explain shape plan with cte as (select /*+ leading(t2 t1) */ c11, c1 from t1 join t2 on c1 = c2) select /*+ leading(t3 alias1 cte) */ count(*) from (select c1, c11 from t1 join t2 on c1 = c2) as alias1 join t3 on alias1.c1 = t3.c3 join cte on alias1.c1 = cte.c11;;""" qt_sql3_3 """explain shape plan with cte as (select c11, c1 from t1 join t2 on c1 = c2) select count(*) from (select /*+ leading(t2 t1) */ c1, c11 from t1 join t2 on c1 = c2) as alias1 join t3 on alias1.c1 = t3.c3 join cte on alias1.c1 = cte.c11;;""" - qt_sql3_4 """explain shape plan with cte as (select /*+ leading(t2 t1) */ c11, c1 from t1 join t2 on c1 = c2) select /*+ leading(t3 alias1) */ count(*) from (select /*+ leading(t2 t1) */ c1, c11 from t1 join t2 on c1 = c2) as alias1 join t3 on alias1.c1 = t3.c3 join cte on alias1.c1 = cte.c11;;""" + qt_sql3_4 """explain shape plan with cte as (select /*+ leading(t2 t1) */ c11, c1 from t1 join t2 on c1 = c2) select /*+ leading(t3 alias1 cte) */ count(*) from (select /*+ leading(t2 t1) */ c1, c11 from t1 join t2 on c1 = c2) as alias1 join t3 on alias1.c1 = t3.c3 join cte on alias1.c1 = cte.c11;;""" qt_sql3_res_1 """with cte as (select c11, c1 from t1 join t2 on c1 = c2) select count(*) from (select c1, c11 from t1 join t2 on c1 = c2) as alias1 join t3 on alias1.c1 = t3.c3 join cte on alias1.c1 = cte.c11;;""" - qt_sql3_res_2 """with cte as (select /*+ leading(t2 t1) */ c11, c1 from t1 join t2 on c1 = c2) select /*+ leading(t3 alias1) */ count(*) from (select c1, c11 from t1 join t2 on c1 = c2) as alias1 join t3 on alias1.c1 = t3.c3 join cte on alias1.c1 = cte.c11;;""" + qt_sql3_res_2 """with cte as (select /*+ leading(t2 t1) */ c11, c1 from t1 join t2 on c1 = c2) select /*+ leading(t3 alias1 cte) */ count(*) from (select c1, c11 from t1 join t2 on c1 = c2) as alias1 join t3 on alias1.c1 = t3.c3 join cte on alias1.c1 = cte.c11;;""" qt_sql3_res_3 """with cte as (select c11, c1 from t1 join t2 on c1 = c2) select count(*) from (select /*+ leading(t2 t1) */ c1, c11 from t1 join t2 on c1 = c2) as alias1 join t3 on alias1.c1 = t3.c3 join cte on alias1.c1 = cte.c11;;""" - qt_sql3_res_4 """with cte as (select /*+ leading(t2 t1) */ c11, c1 from t1 join t2 on c1 = c2) select /*+ leading(t3 alias1) */ count(*) from (select /*+ leading(t2 t1) */ c1, c11 from t1 join t2 on c1 = c2) as alias1 join t3 on alias1.c1 = t3.c3 join cte on alias1.c1 = cte.c11;;""" + qt_sql3_res_4 """with cte as (select /*+ leading(t2 t1) */ c11, c1 from t1 join t2 on c1 = c2) select /*+ leading(t3 alias1 cte) */ count(*) from (select /*+ leading(t2 t1) */ c1, c11 from t1 join t2 on c1 = c2) as alias1 join t3 on alias1.c1 = t3.c3 join cte on alias1.c1 = cte.c11;;""" // test multi level subqueries qt_sql4_0 """explain shape plan select count(*) from (select c1, c11 from t1 join (select c2, c22 from t2 join t4 on c2 = c4) as alias2 on c1 = alias2.c2) as alias1 join t3 on alias1.c1 = t3.c3;""" --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org