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

starocean999 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 24e34d3d021 [fix](sync mv) fix rewrite wrongly with sync mv (#39284)
24e34d3d021 is described below

commit 24e34d3d021c642e9ef2d6dddc937a89c021a5dd
Author: zhangyuan <ayuanzh...@tencent.com>
AuthorDate: Mon Nov 25 09:56:38 2024 +0800

    [fix](sync mv) fix rewrite wrongly with sync mv (#39284)
    
    Aggregate table rewrite wrongly with sync mv:
    
    drop table if  exists t1;
    CREATE TABLE IF NOT EXISTS t1 (
                    k int,
                    a int,
                    int_value int sum,
                    char_value char(10) max,
                    date_value date max
                )
                ENGINE=OLAP
                aggregate KEY(k,a)
    DISTRIBUTED BY HASH(k) BUCKETS 2 properties("replication_num" = "1");
    insert into t1 values
        (1,1,1,'a', '2020-12-01'),
        (2,2,2,'b', '2021-12-01'),
        (3,2,2,'c', '2022-12-01'),
        (4,2,4,'c', '2023-12-01');
    
    mysql> select a from t1;
    +------+
    | a    |
    +------+
    |    2 |
    |    1 |
    |    2 |
    |    2 |
    +------+
    4 rows in set (0.01 sec)
    
    CREATE MATERIALIZED VIEW v_t1
            AS
         select k%2 as kk,a,max(date_value) from t1 group by kk, a;
    select JobName from mv_infos('database'='test') where Name = 'v_t1';
    select sleep(2);
    
    // after rewire with v_t1, the result only have 3 rows
    mysql> select a from t1;
    +------+
    | a    |
    +------+
    |    2 |
    |    2 |
    |    1 |
    +------+
    3 rows in set (0.01 sec)
    
    ## solution
    When rewriting query with aggregate table's sync mv, it is not only
    necessary to check the key size, but also to check all key columns;
---
 .../mv/AbstractSelectMaterializedIndexRule.java    |  12 ++
 .../SelectMaterializedIndexWithoutAggregate.java   |   1 +
 .../mv/join/inner/inner_join_x.out                 |  25 ++++
 .../mv/join/inner/inner_join_x.groovy              | 128 +++++++++++++++++++++
 4 files changed, 166 insertions(+)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/AbstractSelectMaterializedIndexRule.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/AbstractSelectMaterializedIndexRule.java
index f17ab1c96bd..357883d1f71 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/AbstractSelectMaterializedIndexRule.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/AbstractSelectMaterializedIndexRule.java
@@ -144,6 +144,18 @@ public abstract class AbstractSelectMaterializedIndexRule {
         return prunedExpr;
     }
 
+    protected static boolean containAllKeyColumns(OlapTable table, 
MaterializedIndex index) {
+        Set<String> mvColNames = 
table.getKeyColumnsByIndexId(index.getId()).stream()
+                .map(c -> 
normalizeName(parseMvColumnToSql(c.getNameWithoutMvPrefix())))
+                .collect(Collectors.toCollection(() -> new 
TreeSet<String>(String.CASE_INSENSITIVE_ORDER)));
+
+        Set<String> keyColNames = table.getBaseSchemaKeyColumns().stream()
+                .map(c -> 
normalizeName(parseMvColumnToSql(c.getNameWithoutMvPrefix())))
+                .collect(Collectors.toCollection(() -> new 
TreeSet<String>(String.CASE_INSENSITIVE_ORDER)));
+
+        return keyColNames.containsAll(mvColNames);
+    }
+
     protected static boolean containAllRequiredColumns(MaterializedIndex 
index, LogicalOlapScan scan,
             Set<Slot> requiredScanOutput, Set<? extends Expression> 
requiredExpr, Set<Expression> predicateExpr) {
         OlapTable table = scan.getTable();
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/SelectMaterializedIndexWithoutAggregate.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/SelectMaterializedIndexWithoutAggregate.java
index 76278fe48ee..3a589108a09 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/SelectMaterializedIndexWithoutAggregate.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/mv/SelectMaterializedIndexWithoutAggregate.java
@@ -234,6 +234,7 @@ public class SelectMaterializedIndexWithoutAggregate 
extends AbstractSelectMater
             // So only base index and indexes that have all the keys could be 
used.
             List<MaterializedIndex> candidates = 
table.getVisibleIndex().stream()
                     .filter(index -> 
table.getKeyColumnsByIndexId(index.getId()).size() == baseIndexKeySize)
+                    .filter(index -> containAllKeyColumns(table, index))
                     .filter(index -> containAllRequiredColumns(index, scan, 
requiredScanOutputSupplier.get(),
                             requiredExpr.get(), predicatesSupplier.get()))
                     .collect(Collectors.toList());
diff --git 
a/regression-test/data/nereids_rules_p0/mv/join/inner/inner_join_x.out 
b/regression-test/data/nereids_rules_p0/mv/join/inner/inner_join_x.out
new file mode 100644
index 00000000000..201aca1c08f
--- /dev/null
+++ b/regression-test/data/nereids_rules_p0/mv/join/inner/inner_join_x.out
@@ -0,0 +1,25 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !query_before --
+1
+2
+2
+2
+
+-- !query_after --
+1
+2
+2
+2
+
+-- !query_before --
+1
+2
+2
+2
+
+-- !query_after --
+1
+2
+2
+2
+
diff --git 
a/regression-test/suites/nereids_rules_p0/mv/join/inner/inner_join_x.groovy 
b/regression-test/suites/nereids_rules_p0/mv/join/inner/inner_join_x.groovy
new file mode 100644
index 00000000000..5f8e150385a
--- /dev/null
+++ b/regression-test/suites/nereids_rules_p0/mv/join/inner/inner_join_x.groovy
@@ -0,0 +1,128 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite("inner_join_x") {
+    String db = context.config.getDbNameByFile(context.file)
+    sql "use ${db}"
+    sql "set runtime_filter_mode=OFF"
+    sql "set enable_sync_mv_cost_based_rewrite=false"
+
+
+    // =======================  test table with aggregate key 
============================
+    sql """
+    drop table if  exists t1;
+    """
+
+    sql """
+    CREATE TABLE IF NOT EXISTS t1 (
+                k int,
+                a int,
+                int_value int sum,
+                char_value char(10) max,
+                date_value date max
+            )
+            ENGINE=OLAP
+            aggregate KEY(k,a)
+            DISTRIBUTED BY HASH(k) BUCKETS 2 properties("replication_num" = 
"1")
+
+    """
+
+    def mv_name="v_t1"
+    createMV ( """
+     create materialized view ${mv_name} as select k%2 as kk,a, 
sum(int_value), max(date_value) from t1 group by kk, a;
+    """)
+
+    sql """
+    insert into t1 values
+    (1,1,1,'a', '2020-12-01'),
+    (2,2,2,'b', '2021-12-01'),
+    (3,2,2,'c', '2022-12-01'),
+    (4,2,4,'c', '2023-12-01');
+    """
+
+    def query =  """
+    select a from t1
+    """
+    
+    explain {
+        sql("${query}")
+        notContains("${mv_name}(${mv_name})")
+    }
+
+    order_qt_query_before "${query}"
+    
+
+    sql """ DROP MATERIALIZED VIEW IF EXISTS  ${mv_name} on t1"""
+
+    order_qt_query_after "${query}"
+
+    sql """
+    drop table if exists t1 
+    """
+
+    // =======================  test table with duplicate key 
============================
+    sql """
+    drop table if  exists t1;
+    """
+
+    sql """
+    CREATE TABLE IF NOT EXISTS t1 (
+                k int,
+                a int,
+                int_value int,
+                char_value char(10),
+                date_value date
+            )
+            ENGINE=OLAP
+            duplicate KEY(k,a)
+            DISTRIBUTED BY HASH(k) BUCKETS 2 properties("replication_num" = 
"1")
+
+    """
+
+    mv_name="v_t1"
+    createMV ( """
+     create materialized view ${mv_name} as select k%2 as kk,a, 
sum(int_value), max(date_value) from t1 group by kk, a;
+    """)
+
+    sql """
+    insert into t1 values
+    (1,1,1,'a', '2020-12-01'),
+    (2,2,2,'b', '2021-12-01'),
+    (3,2,2,'c', '2022-12-01'),
+    (4,2,4,'c', '2023-12-01');
+    """
+
+    query =  """
+    select a from t1
+    """
+    
+    explain {
+        sql("${query}")
+        notContains("t1(${mv_name})")
+    }
+
+    order_qt_query_before "${query}"
+    
+
+    sql """ DROP MATERIALIZED VIEW IF EXISTS  ${mv_name} on t1"""
+
+    order_qt_query_after "${query}"
+
+    sql """
+    drop table if exists t1 
+    """
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to