diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterMaterializedViewStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterMaterializedViewStmt.java index a59ed5b74dc1d0..b0ecc5261a65e4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterMaterializedViewStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/AlterMaterializedViewStmt.java @@ -21,6 +21,7 @@ import org.apache.doris.common.AnalysisException; import org.apache.doris.common.ErrorCode; import org.apache.doris.common.ErrorReport; +import org.apache.doris.common.UserException; import org.apache.doris.mysql.privilege.PrivPredicate; import org.apache.doris.qe.ConnectContext; @@ -42,7 +43,8 @@ public MVRefreshInfo getRefreshInfo() { } @Override - public void analyze(Analyzer analyzer) throws AnalysisException { + public void analyze(Analyzer analyzer) throws AnalysisException, UserException { + super.analyze(analyzer); mvName.analyze(analyzer); if (!Env.getCurrentEnv().getAccessManager().checkTblPriv(ConnectContext.get(), mvName.getDb(), mvName.getTbl(), PrivPredicate.ALTER)) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java index 37a1fa0c5393e1..e3e81963797097 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java @@ -320,6 +320,10 @@ private static class GlobalState { // analysis. public boolean isExplain; + // Record the statement clazz that the analyzer would to analyze, + // this give an opportunity to control analyzing behavior according to the statement type. + public Class rootStatementClazz; + // Indicates whether the query has plan hints. public boolean hasPlanHints = false; @@ -568,6 +572,14 @@ public boolean isExplain() { return globalState.isExplain; } + public void setRootStatementClazz(Class statementClazz) { + globalState.rootStatementClazz = statementClazz; + } + + public Class getRootStatementClazz() { + return globalState.rootStatementClazz; + } + public int incrementCallDepth() { return ++callDepth; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableAsSelectStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableAsSelectStmt.java index 3019117942ac92..f2bca083b3b7db 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableAsSelectStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateTableAsSelectStmt.java @@ -72,6 +72,7 @@ public void analyze(Analyzer analyzer) throws UserException { // To avoid duplicate registrations of table/colRefs, // create a new root analyzer and clone the query statement for this initial pass. Analyzer dummyRootAnalyzer = new Analyzer(analyzer.getEnv(), analyzer.getContext()); + super.analyze(dummyRootAnalyzer); QueryStmt tmpStmt = queryStmt.clone(); tmpStmt.analyze(dummyRootAnalyzer); this.queryStmt = tmpStmt; diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateViewStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateViewStmt.java index 528b882f848991..befbe8a9dc94da 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateViewStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateViewStmt.java @@ -55,6 +55,7 @@ public String getComment() { @Override public void analyze(Analyzer analyzer) throws UserException { + super.analyze(analyzer); tableName.analyze(analyzer); FeNameFormat.checkTableName(tableName.getTbl()); viewDefStmt.setNeedToSql(true); diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SelectListItem.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SelectListItem.java index 8fc99e29673d89..34368c7b17eaf7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SelectListItem.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SelectListItem.java @@ -120,7 +120,6 @@ public String toDigest() { * Return a column label for the select list item. Without generate column name * automatically. */ - @Deprecated public String toColumnLabel() { Preconditions.checkState(!isStar()); if (alias != null) { 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 47478ba3d7f688..8c40f5230ac116 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 @@ -543,7 +543,17 @@ public void analyze(Analyzer analyzer) throws UserException { throw new AnalysisException("Subquery is not supported in the select list."); } resultExprs.add(rewriteQueryExprByMvColumnExpr(item.getExpr(), analyzer)); - String columnLabel = item.toColumnLabel(i); + String columnLabel = null; + Class statementClazz = analyzer.getRootStatementClazz(); + if (statementClazz != null && !QueryStmt.class.isAssignableFrom(statementClazz)) { + // Infer column name when item is expr + columnLabel = item.toColumnLabel(i); + } + if (columnLabel == null) { + // column label without position is applicative for query and do not infer + // column name when item is expr + columnLabel = item.toColumnLabel(); + } SlotRef aliasRef = new SlotRef(null, columnLabel); Expr existingAliasExpr = aliasSMap.get(aliasRef); if (existingAliasExpr != null && !existingAliasExpr.equals(item.getExpr())) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/StatementBase.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/StatementBase.java index 015edb2fe50307..13895f5695bbd9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/StatementBase.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/StatementBase.java @@ -78,12 +78,17 @@ protected StatementBase(StatementBase other) { * were missing from the catalog. * It is up to the analysis() implementation to ensure the maximum number of missing * tables/views get collected in the Analyzer before failing analyze(). + * Should call the method firstly when override the method, the analyzer param should be + * the one which statement would use. */ public void analyze(Analyzer analyzer) throws AnalysisException, UserException { if (isAnalyzed()) { return; } this.analyzer = analyzer; + if (analyzer.getRootStatementClazz() == null) { + analyzer.setRootStatementClazz(this.getClass()); + } if (Strings.isNullOrEmpty(analyzer.getClusterName())) { ErrorReport.reportAnalysisException(ErrorCode.ERR_CLUSTER_NO_SELECT_CLUSTER); } diff --git a/fe/fe-core/src/test/java/org/apache/doris/qe/OlapQueryCacheTest.java b/fe/fe-core/src/test/java/org/apache/doris/qe/OlapQueryCacheTest.java index 934521a094ba59..5e2d13003f2da5 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/qe/OlapQueryCacheTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/qe/OlapQueryCacheTest.java @@ -18,7 +18,9 @@ package org.apache.doris.qe; import org.apache.doris.analysis.Analyzer; +import org.apache.doris.analysis.CreateViewStmt; import org.apache.doris.analysis.PartitionValue; +import org.apache.doris.analysis.QueryStmt; import org.apache.doris.analysis.SqlParser; import org.apache.doris.analysis.SqlScanner; import org.apache.doris.analysis.StatementBase; @@ -165,22 +167,6 @@ public SystemInfoService getCurrentSystemInfo() { }; db = new Database(1L, fullDbName); - OlapTable tbl1 = createOrderTable(); - OlapTable tbl2 = createProfileTable(); - OlapTable tbl3 = createEventTable(); - db.createTable(tbl1); - db.createTable(tbl2); - db.createTable(tbl3); - - View view1 = createEventView1(); - View view2 = createEventView2(); - View view3 = createEventView3(); - View view4 = createEventNestedView(); - db.createTable(view1); - db.createTable(view2); - db.createTable(view3); - db.createTable(view4); - new Expectations(catalog) { { catalog.getDbNullable(fullDbName); @@ -334,6 +320,25 @@ public SystemInfoService getCurrentSystemInfo() { analyzer = new Analyzer(env, ctx); newRangeList = Lists.newArrayList(); + + // table and view init use analyzer, should init after analyzer build + OlapTable tbl1 = createOrderTable(); + db.createTable(tbl1); + OlapTable tbl2 = createProfileTable(); + db.createTable(tbl2); + OlapTable tbl3 = createEventTable(); + db.createTable(tbl3); + + // build view meta inline sql and create view directly, the originStmt from inline sql + // should be analyzed by create view statement analyzer and then to sql + View view1 = createEventView1(); + db.createTable(view1); + View view2 = createEventView2(); + db.createTable(view2); + View view3 = createEventView3(); + db.createTable(view3); + View view4 = createEventNestedView(); + db.createTable(view4); } private OlapTable createOrderTable() { @@ -509,14 +514,18 @@ private View createEventView1() { String originStmt = "select eventdate, COUNT(userid) FROM appevent WHERE " + "eventdate>=\"2020-01-12\" and eventdate<=\"2020-01-14\" GROUP BY eventdate"; View view = new View(30000L, "view1", null); - view.setInlineViewDefWithSqlMode(originStmt, 0L); + Analyzer createViewAnalyzer = new Analyzer(env, ctx); + createViewAnalyzer.setRootStatementClazz(CreateViewStmt.class); + view.setInlineViewDefWithSqlMode(parseSql(originStmt, createViewAnalyzer, true).toSql(), 0L); return view; } private View createEventView2() { String originStmt = "select eventdate, userid FROM appevent"; View view = new View(30001L, "view2", null); - view.setInlineViewDefWithSqlMode(originStmt, 0L); + Analyzer createViewAnalyzer = new Analyzer(env, ctx); + createViewAnalyzer.setRootStatementClazz(CreateViewStmt.class); + view.setInlineViewDefWithSqlMode(parseSql(originStmt, createViewAnalyzer, true).toSql(), 0L); return view; } @@ -524,7 +533,9 @@ private View createEventView3() { String originStmt = "select eventdate, COUNT(userid) FROM appevent WHERE " + "eventdate>=\"2020-01-12\" and eventdate<=\"2020-01-15\" GROUP BY eventdate"; View view = new View(30002L, "view3", null); - view.setInlineViewDefWithSqlMode(originStmt, 0L); + Analyzer createViewAnalyzer = new Analyzer(env, ctx); + createViewAnalyzer.setRootStatementClazz(CreateViewStmt.class); + view.setInlineViewDefWithSqlMode(parseSql(originStmt, createViewAnalyzer, true).toSql(), 0L); return view; } @@ -532,7 +543,10 @@ private View createEventNestedView() { String originStmt = "select eventdate, COUNT(userid) FROM view2 WHERE " + "eventdate>=\"2020-01-12\" and eventdate<=\"2020-01-14\" GROUP BY eventdate"; View view = new View(30003L, "view4", null); - view.setInlineViewDefWithSqlMode(originStmt, 0L); + Analyzer createViewAnalyzer = new Analyzer(env, ctx); + createViewAnalyzer.setRootStatementClazz(CreateViewStmt.class); + view.setInlineViewDefWithSqlMode( + parseSql(originStmt, createViewAnalyzer, true).toSql(), 0L); return view; } @@ -564,11 +578,18 @@ private StatementBase parseSqlByNereids(String sql) { } private StatementBase parseSql(String sql) { + return parseSql(sql, null, false); + } + + private StatementBase parseSql(String sql, Analyzer analyzer, boolean needToSql) { SqlParser parser = new SqlParser(new SqlScanner(new StringReader(sql))); StatementBase parseStmt = null; try { parseStmt = SqlParserUtils.getFirstStmt(parser); - parseStmt.analyze(analyzer); + if (parseStmt instanceof QueryStmt) { + ((QueryStmt) parseStmt).setNeedToSql(needToSql); + } + parseStmt.analyze(analyzer == null ? this.analyzer : analyzer); } catch (AnalysisException e) { LOG.warn("Part,an_ex={}", e); Assert.fail(e.getMessage()); @@ -1023,7 +1044,7 @@ public void testSubSelect() throws Exception { cache.rewriteSelectStmt(null); LOG.warn("Sub nokey={}", cache.getNokeyStmt().toSql()); Assert.assertEquals(cache.getNokeyStmt().toSql(), - "SELECT `eventdate` AS `eventdate`, sum(`pv`) AS `__sum_1` FROM (" + "SELECT `eventdate` AS `eventdate`, sum(`pv`) AS `sum(``pv``)` FROM (" + "SELECT `eventdate` AS `eventdate`, count(`userid`) AS `pv` FROM " + "`testCluster:testDb`.`appevent` WHERE `eventid` = 1" + " GROUP BY `eventdate`) tbl GROUP BY `eventdate`"); @@ -1045,7 +1066,7 @@ public void testSubSelect() throws Exception { sql = ca.getRewriteStmt().toSql(); LOG.warn("Sub rewrite={}", sql); Assert.assertEquals(sql, - "SELECT `eventdate` AS `eventdate`, sum(`pv`) AS `__sum_1` FROM (" + "SELECT `eventdate` AS `eventdate`, sum(`pv`) AS `sum(``pv``)` FROM (" + "SELECT `eventdate` AS `eventdate`, count(`userid`) AS `pv` FROM " + "`testCluster:testDb`.`appevent` WHERE " + "`eventdate` > '2020-01-13' AND `eventdate` < '2020-01-16' AND `eventid` = 1 GROUP BY " @@ -1102,7 +1123,7 @@ public void testSqlCacheKey() { SqlCache sqlCache = (SqlCache) ca.getCache(); String cacheKey = sqlCache.getSqlWithViewStmt(); Assert.assertEquals(cacheKey, "SELECT `eventdate` AS `eventdate`, count(`userid`) AS " - + "`__count_1` FROM `testCluster:testDb`.`appevent` WHERE `eventdate` >= '2020-01-12' AND " + + "`count(``userid``)` FROM `testCluster:testDb`.`appevent` WHERE `eventdate` >= '2020-01-12' AND " + "`eventdate` <= '2020-01-14' GROUP BY `eventdate`|"); Assert.assertEquals(selectedPartitionIds.size(), sqlCache.getSumOfPartitionNum()); } @@ -1140,9 +1161,11 @@ public void testSqlCacheKeyWithView() { SqlCache sqlCache = (SqlCache) ca.getCache(); String cacheKey = sqlCache.getSqlWithViewStmt(); - Assert.assertEquals(cacheKey, "SELECT `testCluster:testDb`.`view1`.`eventdate` AS `eventdate`, `testCluster:testDb`.`view1`." - + "`__count_1` AS `__count_1` FROM `testCluster:testDb`.`view1`|select eventdate, COUNT(userid) " - + "FROM appevent WHERE eventdate>=\"2020-01-12\" and eventdate<=\"2020-01-14\" GROUP BY eventdate"); + Assert.assertEquals(cacheKey, "SELECT `testCluster:testDb`.`view1`.`eventdate` AS `eventdate`, " + + "`testCluster:testDb`.`view1`.`__count_1` AS `__count_1` FROM `testCluster:testDb`.`view1`|" + + "SELECT `eventdate` AS `eventdate`, count(`userid`) AS `__count_1` FROM " + + "`testCluster:testDb`.`appevent` WHERE `eventdate` >= '2020-01-12' AND " + + "`eventdate` <= '2020-01-14' GROUP BY `eventdate`"); Assert.assertEquals(selectedPartitionIds.size(), sqlCache.getSumOfPartitionNum()); } @@ -1159,9 +1182,9 @@ public void testSqlCacheKeyWithViewForNereids() { SqlCache sqlCache = (SqlCache) ca.getCache(); String cacheKey = sqlCache.getSqlWithViewStmt(); - Assert.assertEquals(cacheKey, "SELECT * from testDb.view1" - + "|select eventdate, COUNT(userid) FROM appevent " - + "WHERE eventdate>=\"2020-01-12\" and eventdate<=\"2020-01-14\" GROUP BY eventdate"); + Assert.assertEquals(cacheKey, "SELECT * from testDb.view1|SELECT `eventdate` AS `eventdate`, " + + "count(`userid`) AS `__count_1` FROM `testCluster:testDb`.`appevent` " + + "WHERE `eventdate` >= '2020-01-12' AND `eventdate` <= '2020-01-14' GROUP BY `eventdate`"); Assert.assertEquals(selectedPartitionIds.size(), sqlCache.getSumOfPartitionNum()); } @@ -1185,10 +1208,11 @@ public void testSqlCacheKeyWithSubSelectView() { SqlCache sqlCache = (SqlCache) ca.getCache(); String cacheKey = sqlCache.getSqlWithViewStmt(); - Assert.assertEquals(cacheKey, "SELECT `origin`.`eventdate` AS `eventdate`, `origin`.`userid` AS " - + "`userid` FROM (SELECT `view2`.`eventdate` AS `eventdate`, `view2`.`userid` AS `userid` FROM " - + "`testCluster:testDb`.`view2` view2 WHERE `view2`.`eventdate` >= '2020-01-12' AND `view2`.`eventdate` " - + "<= '2020-01-14') origin|select eventdate, userid FROM appevent"); + Assert.assertEquals(cacheKey, "SELECT `origin`.`eventdate` AS `eventdate`, " + + "`origin`.`userid` AS `userid` FROM (SELECT `view2`.`eventdate` AS `eventdate`, " + + "`view2`.`userid` AS `userid` FROM `testCluster:testDb`.`view2` view2 " + + "WHERE `view2`.`eventdate` >= '2020-01-12' AND `view2`.`eventdate` <= '2020-01-14') origin|" + + "SELECT `eventdate` AS `eventdate`, `userid` AS `userid` FROM `testCluster:testDb`.`appevent`"); Assert.assertEquals(selectedPartitionIds.size(), sqlCache.getSumOfPartitionNum()); } @@ -1214,11 +1238,11 @@ public void testSqlCacheKeyWithSubSelectViewForNereids() { SqlCache sqlCache = (SqlCache) ca.getCache(); String cacheKey = sqlCache.getSqlWithViewStmt(); Assert.assertEquals(cacheKey, "select origin.eventdate as eventdate, origin.userid as userid\n" - + "from (\n" - + " select view2.eventdate as eventdate, view2.userid as userid \n" - + " from testDb.view2 view2 \n" - + " where view2.eventdate >=\"2020-01-12\" and view2.eventdate <= \"2020-01-14\"\n" - + ") origin" + "|select eventdate, userid FROM appevent"); + + "from (\n" + + " select view2.eventdate as eventdate, view2.userid as userid \n" + + " from testDb.view2 view2 \n" + + " where view2.eventdate >=\"2020-01-12\" and view2.eventdate <= \"2020-01-14\"\n" + + ") origin|SELECT `eventdate` AS `eventdate`, `userid` AS `userid` FROM `testCluster:testDb`.`appevent`"); Assert.assertEquals(selectedPartitionIds.size(), sqlCache.getSumOfPartitionNum()); } @@ -1238,10 +1262,11 @@ public void testPartitionCacheKeyWithView() { cache.rewriteSelectStmt(null); Assert.assertEquals(cache.getNokeyStmt().getWhereClause(), null); - Assert.assertEquals(cache.getSqlWithViewStmt(), "SELECT `testCluster:testDb`.`view3`.`eventdate` AS " - + "`eventdate`, `testCluster:testDb`.`view3`.`__count_1` AS `__count_1` FROM " - + "`testCluster:testDb`.`view3`|select eventdate, COUNT(userid) FROM appevent WHERE eventdate>=" - + "\"2020-01-12\" and eventdate<=\"2020-01-15\" GROUP BY eventdate"); + Assert.assertEquals(cache.getSqlWithViewStmt(), "SELECT `testCluster:testDb`.`view3`.`eventdate` " + + "AS `eventdate`, `testCluster:testDb`.`view3`.`__count_1` AS `__count_1` " + + "FROM `testCluster:testDb`.`view3`|SELECT `eventdate` AS `eventdate`, count(`userid`) " + + "AS `__count_1` FROM `testCluster:testDb`.`appevent` WHERE `eventdate` >= '2020-01-12' " + + "AND `eventdate` <= '2020-01-15' GROUP BY `eventdate`"); } catch (Exception e) { LOG.warn("ex={}", e); Assert.fail(e.getMessage()); @@ -1272,9 +1297,10 @@ public void testPartitionCacheKeyWithSubSelectView() { cache.rewriteSelectStmt(null); Assert.assertEquals(cache.getNokeyStmt().getWhereClause(), null); Assert.assertEquals(cache.getSqlWithViewStmt(), - "SELECT `origin`.`eventdate` AS `eventdate`, `origin`.`cnt` AS `cnt` FROM (SELECT " - + " `eventdate` AS `eventdate`, count(`userid`) AS `cnt` FROM " - + "`testDb`.`view2` GROUP BY `eventdate`) origin|select eventdate, userid FROM appevent"); + "SELECT `origin`.`eventdate` AS `eventdate`, `origin`.`cnt` AS `cnt` " + + "FROM (SELECT `eventdate` AS `eventdate`, count(`userid`) AS `cnt` " + + "FROM `testDb`.`view2` GROUP BY `eventdate`) origin|SELECT `eventdate` AS `eventdate`, " + + "`userid` AS `userid` FROM `testCluster:testDb`.`appevent`"); } catch (Exception e) { LOG.warn("ex={}", e); Assert.fail(e.getMessage()); @@ -1295,9 +1321,10 @@ public void testSqlCacheKeyWithNestedView() { SqlCache sqlCache = (SqlCache) ca.getCache(); String cacheKey = sqlCache.getSqlWithViewStmt(); Assert.assertEquals(cacheKey, "SELECT `testCluster:testDb`.`view4`.`eventdate` AS `eventdate`, " - + "`testCluster:testDb`.`view4`.`__count_1` AS `__count_1` FROM `testCluster:testDb`.`view4`|select " - + "eventdate, COUNT(userid) FROM view2 WHERE eventdate>=\"2020-01-12\" and " - + "eventdate<=\"2020-01-14\" GROUP BY eventdate|select eventdate, userid FROM appevent"); + + "`testCluster:testDb`.`view4`.`__count_1` AS `__count_1` FROM `testCluster:testDb`.`view4`|" + + "SELECT `eventdate` AS `eventdate`, count(`userid`) AS `__count_1` FROM `testDb`.`view2` " + + "WHERE `eventdate` >= '2020-01-12' AND `eventdate` <= '2020-01-14' GROUP BY `eventdate`|" + + "SELECT `eventdate` AS `eventdate`, `userid` AS `userid` FROM `testCluster:testDb`.`appevent`"); Assert.assertEquals(selectedPartitionIds.size(), sqlCache.getSumOfPartitionNum()); } @@ -1314,10 +1341,10 @@ public void testSqlCacheKeyWithNestedViewForNereids() { SqlCache sqlCache = (SqlCache) ca.getCache(); String cacheKey = sqlCache.getSqlWithViewStmt(); - Assert.assertEquals(cacheKey, "SELECT * from testDb.view4" - + "|select eventdate, COUNT(userid) FROM view2 " - + "WHERE eventdate>=\"2020-01-12\" and eventdate<=\"2020-01-14\" GROUP BY eventdate" - + "|select eventdate, userid FROM appevent"); + Assert.assertEquals(cacheKey, "SELECT * from testDb.view4|SELECT `eventdate` AS `eventdate`, " + + "count(`userid`) AS `__count_1` FROM `testDb`.`view2` WHERE `eventdate` >= '2020-01-12' AND " + + "`eventdate` <= '2020-01-14' GROUP BY `eventdate`|SELECT `eventdate` AS `eventdate`, " + + "`userid` AS `userid` FROM `testCluster:testDb`.`appevent`"); Assert.assertEquals(selectedPartitionIds.size(), sqlCache.getSumOfPartitionNum()); }