diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/QueryStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/QueryStmt.java index 43875f573e4981..4766562386cd4d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/QueryStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/QueryStmt.java @@ -433,6 +433,12 @@ public void getWithClauseTables(Analyzer analyzer, Map tableMap, Se } } + public void getWithClauseTableRefs(List tblRefs, Set parentViewNameSet) { + if (withClause_ != null) { + withClause_.getTableRefs(tblRefs, parentViewNameSet); + } + } + // get tables used by this query. // Set parentViewNameSet contain parent stmt view name // to make sure query like "with tmp as (select * from db1.table1) " + @@ -442,6 +448,10 @@ public void getWithClauseTables(Analyzer analyzer, Map tableMap, Se // so need to check is view name by parentViewNameSet. issue link: https://github.com/apache/incubator-doris/issues/4598 public abstract void getTables(Analyzer analyzer, Map tables, Set parentViewNameSet) throws AnalysisException; + // get TableRefs in this query, including physical TableRefs of this statement and + // nested statements of inline views and with_Clause. + public abstract void getTableRefs(List tblRefs, Set parentViewNameSet); + /** * UnionStmt and SelectStmt have different implementations. */ 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 af30850bb1a02f..3f6277a39196fa 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 @@ -40,7 +40,6 @@ import org.apache.doris.mysql.privilege.PrivPredicate; import org.apache.doris.qe.ConnectContext; import org.apache.doris.rewrite.ExprRewriter; - import com.google.common.base.Preconditions; import com.google.common.base.Predicates; import com.google.common.base.Strings; @@ -324,6 +323,22 @@ public void getTables(Analyzer analyzer, Map tableMap, Set } } + @Override + public void getTableRefs(List tblRefs, Set parentViewNameSet) { + getWithClauseTableRefs(tblRefs, parentViewNameSet); + for (TableRef tblRef : fromClause_) { + if (tblRef instanceof InlineViewRef) { + QueryStmt inlineStmt = ((InlineViewRef) tblRef).getViewStmt(); + inlineStmt.getTableRefs(tblRefs, parentViewNameSet); + } else { + if (isViewTableRef(tblRef.getName().toString(), parentViewNameSet)) { + continue; + } + tblRefs.add(tblRef); + } + } + } + // if tableName in parentViewNameSetor tableName in withClause views // means this tableref is inlineview, no need check dbname again private boolean isViewTableRef(String tblName, Set parentViewNameSet) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SetOperationStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SetOperationStmt.java index a1f2f4177621c4..194cc1e30292d4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SetOperationStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SetOperationStmt.java @@ -179,6 +179,14 @@ public void getTables(Analyzer analyzer, Map tableMap, Set } } + @Override + public void getTableRefs(List tblRefs, Set parentViewNameSet) { + getWithClauseTableRefs(tblRefs, parentViewNameSet); + for (SetOperand op : operands) { + op.getQueryStmt().getTableRefs(tblRefs, parentViewNameSet); + } + } + /** * Propagates DISTINCT from left to right, and checks that all * set operands are set compatible, adding implicit casts if necessary. diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowViewStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowViewStmt.java index 713b2f17cafbcb..e7acf6c2e445a8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowViewStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowViewStmt.java @@ -33,11 +33,9 @@ import org.apache.doris.qe.ShowResultSetMetaData; import com.google.common.base.Strings; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import com.google.common.collect.Sets; import java.util.List; -import java.util.Map; import java.util.Set; // Show view statement, used to show view information of one table. @@ -114,19 +112,22 @@ public void analyze(Analyzer analyzer) throws AnalysisException, UserException { for (Table table : database.getViews()) { View view = (View) table; - Map tableMap = Maps.newHashMap(); - // get tables from view sql - getTables(analyzer, view, tableMap); - if (tableMap.containsKey(showTable.getId())) { - matchViews.add(view); + List tblRefs = Lists.newArrayList(); + // get table refs instead of get tables because it don't need to check table's validity + getTableRefs(view, tblRefs); + for (TableRef tblRef : tblRefs) { + tblRef.analyze(analyzer); + if (tblRef.getName().equals(tbl)) { + matchViews.add(view); + } } } } - private void getTables(Analyzer analyzer, View view, Map tableMap) throws UserException { + private void getTableRefs(View view, List tblRefs) { Set parentViewNameSet = Sets.newHashSet(); QueryStmt queryStmt = view.getQueryStmt(); - queryStmt.getTables(analyzer, tableMap, parentViewNameSet); + queryStmt.getTableRefs(tblRefs, parentViewNameSet); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/WithClause.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/WithClause.java index 6ee877578d8a03..6e90b8eb284074 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/WithClause.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/WithClause.java @@ -17,20 +17,19 @@ package org.apache.doris.analysis; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.apache.doris.catalog.Table; import org.apache.doris.catalog.View; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.UserException; - import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * Representation of the WITH clause that may appear before a query statement or insert * statement. A WITH clause contains a list of named view definitions that may be @@ -114,6 +113,14 @@ public void getTables(Analyzer analyzer, Map tableMap, Set } } + public void getTableRefs(List tblRefs, Set parentViewNameSet) { + for (View view : views_) { + QueryStmt stmt = view.getQueryStmt(); + parentViewNameSet.add(view.getName()); + stmt.getTableRefs(tblRefs, parentViewNameSet); + } + } + @Override public WithClause clone() { return new WithClause(this); } diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/SelectStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/SelectStmtTest.java index fa850ca6016f18..0eeaee3b3d88f1 100755 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/SelectStmtTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/SelectStmtTest.java @@ -25,6 +25,8 @@ import org.apache.doris.qe.VariableMgr; import org.apache.doris.utframe.DorisAssert; import org.apache.doris.utframe.UtFrameUtils; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import org.junit.AfterClass; import org.junit.Assert; @@ -33,8 +35,9 @@ import org.junit.Test; import org.junit.rules.ExpectedException; +import java.util.List; +import java.util.Set; import java.util.UUID; - import mockit.Mock; import mockit.MockUp; @@ -562,4 +565,19 @@ public void testWithInNestedQueryStmt() throws Exception { String sql = "select 1 from (with w as (select 1 from db1.table1) select 1 from w) as tt"; dorisAssert.query(sql).explainQuery(); } + + @Test + public void testGetTableRefs() throws Exception { + ConnectContext ctx = UtFrameUtils.createDefaultCtx(); + String sql = "SELECT * FROM db1.table1 JOIN db1.table2 ON db1.table1.siteid = db1.table2.siteid;"; + dorisAssert.query(sql).explainQuery(); + QueryStmt stmt = (QueryStmt) UtFrameUtils.parseAndAnalyzeStmt(sql, ctx); + List tblRefs = Lists.newArrayList(); + Set parentViewNameSet = Sets.newHashSet(); + stmt.getTableRefs(tblRefs, parentViewNameSet); + + Assert.assertEquals(2, tblRefs.size()); + Assert.assertEquals("table1", tblRefs.get(0).getName().getTbl()); + Assert.assertEquals("table2", tblRefs.get(1).getName().getTbl()); + } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowViewStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowViewStmtTest.java index d26019576ca35b..3a521f6444c908 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowViewStmtTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowViewStmtTest.java @@ -2,14 +2,20 @@ import org.apache.doris.catalog.Catalog; import org.apache.doris.common.UserException; +import org.apache.doris.common.util.SqlParserUtils; import org.apache.doris.mysql.privilege.MockedAuth; import org.apache.doris.mysql.privilege.PaloAuth; import org.apache.doris.qe.ConnectContext; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import java.io.StringReader; +import java.util.List; +import java.util.Set; import mockit.Expectations; import mockit.Mocked; @@ -55,4 +61,24 @@ public void testNoDb() throws UserException { stmt.analyze(analyzer); Assert.fail(); } + + @Test + public void testGetTableRefs() throws Exception { + String sql = "with w as (select a from db1.test1) " + + "select b, c from db1.test2 " + + "left outer join " + + "(select d from db1.test3 join w on db1.test3.e = w.a) test4 " + + "on test1.f = test4.d"; + SqlScanner input = new SqlScanner(new StringReader(sql)); + SqlParser parser = new SqlParser(input); + QueryStmt queryStmt = (QueryStmt) SqlParserUtils.getFirstStmt(parser); + List tblRefs = Lists.newArrayList(); + Set parentViewNameSet = Sets.newHashSet(); + queryStmt.getTableRefs(tblRefs, parentViewNameSet); + + Assert.assertEquals(3, tblRefs.size()); + Assert.assertEquals("test1", tblRefs.get(0).getName().getTbl()); + Assert.assertEquals("test2", tblRefs.get(1).getName().getTbl()); + Assert.assertEquals("test3", tblRefs.get(2).getName().getTbl()); + } }