From eeee036cba7ec4325f0f097eacf9e2b26b4d7fa8 Mon Sep 17 00:00:00 2001 From: yinzhijian <373141588@qq.com> Date: Fri, 8 Jul 2022 17:28:32 +0800 Subject: [PATCH] [fix](optimizer) join reorder may cause column non-existence problem (#10670) for example: select * from t1 inner join t2 on t1.a = t2.b inner join t3 on t3.c = t2.b; If t3 is a large table, it will be placed first after the reorderTable, and the problem that t2.b does not exist will occur in reanalyzing. --- .../org/apache/doris/analysis/SelectStmt.java | 13 ++++++++++++- .../apache/doris/planner/QueryPlanTest.java | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SelectStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SelectStmt.java index 881e7a2947..05ffa486c5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SelectStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SelectStmt.java @@ -820,7 +820,18 @@ public class SelectStmt extends QueryStmt { List candidateEqJoinPredicates = analyzer.getEqJoinConjunctsExcludeAuxPredicates(tid); for (Expr candidateEqJoinPredicate : candidateEqJoinPredicates) { List candidateTupleList = Lists.newArrayList(); - Expr.getIds(Lists.newArrayList(candidateEqJoinPredicate), candidateTupleList, null); + List candidateEqJoinPredicateList = Lists.newArrayList(candidateEqJoinPredicate); + // If a large table or view has joinClause is ranked first, + // and the joinClause is not judged here, + // the column in joinClause may not be found during reanalyzing. + // for example: + // select * from t1 inner join t2 on t1.a = t2.b inner join t3 on t3.c = t2.b; + // If t3 is a large table, it will be placed first after the reorderTable, + // and the problem that t2.b does not exist will occur in reanalyzing + if (candidateTableRef.getOnClause() != null) { + candidateEqJoinPredicateList.add(candidateTableRef.getOnClause()); + } + Expr.getIds(candidateEqJoinPredicateList, candidateTupleList, null); int count = candidateTupleList.size(); for (TupleId tupleId : candidateTupleList) { if (validTupleId.contains(tupleId) || tid.equals(tupleId)) { diff --git a/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java b/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java index 4163112aa7..b8499836df 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java @@ -2169,4 +2169,22 @@ public class QueryPlanTest extends TestWithFeService { Assert.assertFalse(explainString.contains("CROSS JOIN")); } + + @Test + public void testDefaultJoinReorderWithView() throws Exception { + connectContext.setDatabase("default_cluster:test"); + createTable("CREATE TABLE t_1 (col1 varchar, col2 varchar, col3 int)\n" + "DISTRIBUTED BY HASH(col3)\n" + + "BUCKETS 3\n" + "PROPERTIES(\n" + " \"replication_num\"=\"1\"\n" + ");"); + createTable("CREATE TABLE t_2 (col1 varchar, col2 varchar, col3 int)\n" + "DISTRIBUTED BY HASH(col3)\n" + + "BUCKETS 3\n" + "PROPERTIES(\n" + " \"replication_num\"=\"1\"\n" + ");"); + createView("CREATE VIEW v_1 as select col1 from t_1;"); + createView("CREATE VIEW v_2 as select x.col2 from (select t_2.col2, 1 + 1 from t_2) x;"); + + String sql = "explain select t_1.col2, v_1.col1 from t_1 inner join t_2 on t_1.col1 = t_2.col1 inner join v_1 " + + "on v_1.col1 = t_2.col2 inner join v_2 on v_2.col2 = t_2.col1"; + String explainString = getSQLPlanOrErrorMsg(sql); + System.out.println(explainString); + // errCode = 2, detailMessage = Unknown column 'col2' in 't_2' + Assert.assertFalse(explainString.contains("errCode")); + } }