This is an automated email from the ASF dual-hosted git repository.

panxiaolei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new ce3afe7f13 [Enchancement](Materialized-View) forbiden some case in 
create mv with group by and fix select fail on g… (#16820)
ce3afe7f13 is described below

commit ce3afe7f13cb8bc00bae679b3e2f48d19e620c78
Author: Pxl <[email protected]>
AuthorDate: Mon Feb 20 13:04:50 2023 +0800

    [Enchancement](Materialized-View) forbiden some case in create mv with 
group by and fix select fail on g… (#16820)
    
    
       1. forbiden some case in create mv with group by
    
    select k1+1,sum(abs(k2+2)+k3+3) from d_table group by k1;
    
       2. fix select fail on grouping column have diffrent expr with select list
    
    create materialized view k1p2ap3psg as select k1+1,sum(abs(k2+2)+k3+3) from 
d_table group by k1+1;
    
    mysql [test]>explain select k1+1,sum(abs(k2+2)+k3+3) from d_table group by 
k1;
    ERROR 1105 (HY000): errCode = 2, detailMessage = select list expression not 
produced by aggregation output (missing from GROUP BY clause?): `k1` + 1
---
 .../doris/analysis/CreateMaterializedViewStmt.java | 42 ++++++++++++++++++++--
 .../java/org/apache/doris/analysis/SelectStmt.java | 17 +++++++--
 .../doris/rewrite/mvrewrite/ExprToSlotRefRule.java |  5 +++
 .../rewrite/mvrewrite/MVSelectFailedException.java |  4 +--
 .../analysis/CreateMaterializedViewStmtTest.java   | 14 ++++++++
 .../agg_have_dup_base/agg_have_dup_base.out        |  3 ++
 .../multi_slot_k1a2p2ap3ps.out                     |  5 +++
 .../agg_have_dup_base/agg_have_dup_base.groovy     |  6 ++++
 .../multi_slot_k1a2p2ap3ps.groovy                  | 14 ++++++++
 9 files changed, 103 insertions(+), 7 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateMaterializedViewStmt.java
 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateMaterializedViewStmt.java
index 76c86c62b3..e6c5a00793 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateMaterializedViewStmt.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateMaterializedViewStmt.java
@@ -158,6 +158,7 @@ public class CreateMaterializedViewStmt extends DdlStmt {
                     + selectStmt.getHavingPred().toSql());
         }
         analyzeOrderByClause();
+        analyzeGroupByClause();
         if (selectStmt.getLimit() != -1) {
             throw new AnalysisException("The limit clause is not supported in 
add materialized view clause, expr:"
                     + " limit " + selectStmt.getLimit());
@@ -239,6 +240,39 @@ public class CreateMaterializedViewStmt extends DdlStmt {
         dbName = tableName.getDb();
     }
 
+    private void analyzeGroupByClause() throws AnalysisException {
+        if (selectStmt.getGroupByClause() == null) {
+            return;
+        }
+        List<Expr> groupingExprs = 
selectStmt.getGroupByClause().getGroupingExprs();
+        List<FunctionCallExpr> aggregateExprs = 
selectStmt.getAggInfo().getAggregateExprs();
+        List<Expr> selectExprs = selectStmt.getSelectList().getExprs();
+        for (Expr expr : selectExprs) {
+            boolean match = false;
+            String lhs = 
selectStmt.getExprFromAliasSMap(expr).toSqlWithoutTbl();
+            for (Expr groupExpr : groupingExprs) {
+                String rhs = 
selectStmt.getExprFromAliasSMap(groupExpr).toSqlWithoutTbl();
+                if (lhs.equalsIgnoreCase(rhs)) {
+                    match = true;
+                    break;
+                }
+            }
+            if (!match) {
+                for (Expr groupExpr : aggregateExprs) {
+                    String rhs = 
selectStmt.getExprFromAliasSMap(groupExpr).toSqlWithoutTbl();
+                    if (lhs.equalsIgnoreCase(rhs)) {
+                        match = true;
+                        break;
+                    }
+                }
+            }
+
+            if (!match) {
+                throw new AnalysisException("The select expr " + lhs + " not 
in grouping or aggregate columns");
+            }
+        }
+    }
+
     private void analyzeOrderByClause() throws AnalysisException {
         if (selectStmt.getOrderByElements() == null) {
             supplyOrderColumn();
@@ -513,16 +547,20 @@ public class CreateMaterializedViewStmt extends DdlStmt {
         return name;
     }
 
+    private static boolean mvMatch(String name, String prefix) {
+        return MaterializedIndexMeta.normalizeName(name).startsWith(prefix);
+    }
+
     public static boolean isMVColumn(String name) {
         return isMVColumnAggregate(name) || isMVColumnNormal(name);
     }
 
     public static boolean isMVColumnAggregate(String name) {
-        return name.startsWith(MATERIALIZED_VIEW_AGGREGATE_NAME_PREFIX);
+        return mvMatch(name, MATERIALIZED_VIEW_AGGREGATE_NAME_PREFIX);
     }
 
     public static boolean isMVColumnNormal(String name) {
-        return name.startsWith(MATERIALIZED_VIEW_NAME_PREFIX);
+        return mvMatch(name, MATERIALIZED_VIEW_NAME_PREFIX);
     }
 
     @Override
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 091db335cd..9363abca26 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
@@ -46,6 +46,7 @@ import org.apache.doris.common.util.SqlUtils;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.rewrite.ExprRewriter;
+import org.apache.doris.rewrite.mvrewrite.MVSelectFailedException;
 import org.apache.doris.thrift.TExprOpcode;
 
 import com.google.common.base.Preconditions;
@@ -1491,9 +1492,19 @@ public class SelectStmt extends QueryStmt {
         // check that all post-agg exprs point to agg output
         for (int i = 0; i < selectList.getItems().size(); ++i) {
             if (!resultExprs.get(i).isBoundByTupleIds(groupingByTupleIds)) {
-                throw new AnalysisException(
-                        "select list expression not produced by aggregation 
output " + "(missing from "
-                                + "GROUP BY clause?): " + 
selectList.getItems().get(i).getExpr().toSql());
+                if 
(CreateMaterializedViewStmt.isMVColumn(resultExprs.get(i).toSqlWithoutTbl())) {
+                    List<TupleId> tupleIds = Lists.newArrayList();
+                    List<SlotId> slotIds = Lists.newArrayList();
+                    resultExprs.get(i).getIds(tupleIds, slotIds);
+                    for (TupleId id : tupleIds) {
+                        updateDisableTuplesMVRewriter(id);
+                    }
+                    throw new MVSelectFailedException("Materialized View 
rewrite invalid");
+                } else {
+                    throw new AnalysisException(
+                            "select list expression not produced by 
aggregation output " + "(missing from "
+                                    + "GROUP BY clause?): " + 
selectList.getItems().get(i).getExpr().toSql());
+                }
             }
         }
         if (orderByElements != null) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/rewrite/mvrewrite/ExprToSlotRefRule.java
 
b/fe/fe-core/src/main/java/org/apache/doris/rewrite/mvrewrite/ExprToSlotRefRule.java
index ea03d0af62..688600fbdc 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/rewrite/mvrewrite/ExprToSlotRefRule.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/rewrite/mvrewrite/ExprToSlotRefRule.java
@@ -259,6 +259,11 @@ public class ExprToSlotRefRule implements ExprRewriteRule {
 
         if (mvColumn == null) {
             return expr;
+        } else {
+            Expr rhs = mvColumn.getDefineExpr();
+            if (rhs == null || !rhs.getClass().equals(expr.getClass())) {
+                return expr;
+            }
         }
 
         return rewriteExpr(tableName, mvColumn, analyzer);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/rewrite/mvrewrite/MVSelectFailedException.java
 
b/fe/fe-core/src/main/java/org/apache/doris/rewrite/mvrewrite/MVSelectFailedException.java
index 286fc71067..4a355885a1 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/rewrite/mvrewrite/MVSelectFailedException.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/rewrite/mvrewrite/MVSelectFailedException.java
@@ -17,9 +17,9 @@
 
 package org.apache.doris.rewrite.mvrewrite;
 
-import org.apache.doris.common.UserException;
+import org.apache.doris.common.AnalysisException;
 
-public class MVSelectFailedException extends UserException {
+public class MVSelectFailedException extends AnalysisException {
 
     public MVSelectFailedException(String msg) {
         super(msg);
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateMaterializedViewStmtTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateMaterializedViewStmtTest.java
index 4762b3c9fe..9652fbd239 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateMaterializedViewStmtTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateMaterializedViewStmtTest.java
@@ -561,6 +561,8 @@ public class CreateMaterializedViewStmtTest {
                 result = columnName3;
                 slotRef4.toSql();
                 result = columnName4;
+                selectStmt.getGroupByClause();
+                result = null;
             }
         };
 
@@ -664,6 +666,8 @@ public class CreateMaterializedViewStmtTest {
                 result = 4;
                 selectStmt.getAggInfo(); // return null, so that the mv can be 
a duplicate mv
                 result = null;
+                selectStmt.getGroupByClause();
+                result = null;
             }
         };
 
@@ -762,6 +766,8 @@ public class CreateMaterializedViewStmtTest {
                 result = true;
                 selectStmt.getAggInfo(); // return null, so that the mv can be 
a duplicate mv
                 result = null;
+                selectStmt.getGroupByClause();
+                result = null;
             }
         };
 
@@ -860,6 +866,8 @@ public class CreateMaterializedViewStmtTest {
                 result = PrimitiveType.VARCHAR;
                 selectStmt.getAggInfo(); // return null, so that the mv can be 
a duplicate mv
                 result = null;
+                selectStmt.getGroupByClause();
+                result = null;
             }
         };
 
@@ -964,6 +972,8 @@ public class CreateMaterializedViewStmtTest {
                 result = columnName1;
                 slotRef1.getType().getPrimitiveType();
                 result = PrimitiveType.VARCHAR;
+                selectStmt.getGroupByClause();
+                result = null;
             }
         };
 
@@ -1040,6 +1050,8 @@ public class CreateMaterializedViewStmtTest {
                 result = columnName1;
                 slotRef2.getColumnName();
                 result = columnName2;
+                selectStmt.getGroupByClause();
+                result = null;
             }
         };
 
@@ -1095,6 +1107,8 @@ public class CreateMaterializedViewStmtTest {
                 result = null;
                 selectStmt.getHavingPred();
                 result = null;
+                selectStmt.getGroupByClause();
+                result = null;
                 selectStmt.getLimit();
                 result = -1;
                 slotRef1.toSql();
diff --git 
a/regression-test/data/materialized_view_p0/agg_have_dup_base/agg_have_dup_base.out
 
b/regression-test/data/materialized_view_p0/agg_have_dup_base/agg_have_dup_base.out
index 815c51b9c2..c59641f5cd 100644
--- 
a/regression-test/data/materialized_view_p0/agg_have_dup_base/agg_have_dup_base.out
+++ 
b/regression-test/data/materialized_view_p0/agg_have_dup_base/agg_have_dup_base.out
@@ -23,3 +23,6 @@
 2      2
 3      -3
 
+-- !select_mv --
+\N     -4
+
diff --git 
a/regression-test/data/materialized_view_p0/multi_slot_k1a2p2ap3ps/multi_slot_k1a2p2ap3ps.out
 
b/regression-test/data/materialized_view_p0/multi_slot_k1a2p2ap3ps/multi_slot_k1a2p2ap3ps.out
index 5df5415679..a3c0a07a99 100644
--- 
a/regression-test/data/materialized_view_p0/multi_slot_k1a2p2ap3ps/multi_slot_k1a2p2ap3ps.out
+++ 
b/regression-test/data/materialized_view_p0/multi_slot_k1a2p2ap3ps/multi_slot_k1a2p2ap3ps.out
@@ -10,3 +10,8 @@
 3      7
 5      9
 
+-- !select_base --
+1      1
+3      7
+5      9
+
diff --git 
a/regression-test/suites/materialized_view_p0/agg_have_dup_base/agg_have_dup_base.groovy
 
b/regression-test/suites/materialized_view_p0/agg_have_dup_base/agg_have_dup_base.groovy
index 452435a077..df0e50cac9 100644
--- 
a/regression-test/suites/materialized_view_p0/agg_have_dup_base/agg_have_dup_base.groovy
+++ 
b/regression-test/suites/materialized_view_p0/agg_have_dup_base/agg_have_dup_base.groovy
@@ -69,4 +69,10 @@ suite ("agg_have_dup_base") {
         contains "(k12s3m)"
     }
     qt_select_mv "select k1,max(k2) from d_table group by k1 order by k1;"
+
+    explain {
+        sql("select unix_timestamp(k1) tmp,sum(k2) from d_table group by tmp;")
+        contains "(k12s3m)"
+    }
+    qt_select_mv "select unix_timestamp(k1) tmp,sum(k2) from d_table group by 
tmp order by tmp;"
 }
diff --git 
a/regression-test/suites/materialized_view_p0/multi_slot_k1a2p2ap3ps/multi_slot_k1a2p2ap3ps.groovy
 
b/regression-test/suites/materialized_view_p0/multi_slot_k1a2p2ap3ps/multi_slot_k1a2p2ap3ps.groovy
index fb5f458f14..419ff5f42d 100644
--- 
a/regression-test/suites/materialized_view_p0/multi_slot_k1a2p2ap3ps/multi_slot_k1a2p2ap3ps.groovy
+++ 
b/regression-test/suites/materialized_view_p0/multi_slot_k1a2p2ap3ps/multi_slot_k1a2p2ap3ps.groovy
@@ -36,6 +36,14 @@ suite ("multi_slot_k1a2p2ap3ps") {
     sql "insert into d_table select 2,2,2,'b';"
     sql "insert into d_table select 3,-3,null,'c';"
 
+    boolean createFail = false;
+    try {
+        sql "create materialized view k1a2p2ap3ps as select 
abs(k1)+k2+1,sum(abs(k2+2)+k3+3) from d_table group by abs(k1)+k2;"
+    } catch (Exception e) {
+        createFail = true;
+    }
+    assertTrue(createFail);
+
     def result = "null"
     sql "create materialized view k1a2p2ap3ps as select 
abs(k1)+k2+1,sum(abs(k2+2)+k3+3) from d_table group by abs(k1)+k2+1;"
     while (!result.contains("FINISHED")){
@@ -57,4 +65,10 @@ suite ("multi_slot_k1a2p2ap3ps") {
         contains "(k1a2p2ap3ps)"
     }
     qt_select_mv "select abs(k1)+k2+1,sum(abs(k2+2)+k3+3) from d_table group 
by abs(k1)+k2+1 order by abs(k1)+k2+1;"
+
+    explain {
+        sql("select abs(k1)+k2+1,sum(abs(k2+2)+k3+3) from d_table group by 
abs(k1)+k2 order by abs(k1)+k2")
+        contains "(d_table)"
+    }
+    qt_select_base "select abs(k1)+k2+1,sum(abs(k2+2)+k3+3) from d_table group 
by abs(k1)+k2 order by abs(k1)+k2;"
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to