diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/AbstractMaterializedViewRule.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/AbstractMaterializedViewRule.java index 32e90a67efa586..66852444cc0e2f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/AbstractMaterializedViewRule.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/AbstractMaterializedViewRule.java @@ -58,7 +58,6 @@ import java.util.ArrayList; import java.util.Collection; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -69,8 +68,15 @@ * The abstract class for all materialized view rules */ public abstract class AbstractMaterializedViewRule implements ExplorationRuleFactory { - public static final HashSet SUPPORTED_JOIN_TYPE_SET = Sets.newHashSet(JoinType.INNER_JOIN, - JoinType.LEFT_OUTER_JOIN); + public static final Set SUPPORTED_JOIN_TYPE_SET = ImmutableSet.of( + JoinType.INNER_JOIN, + JoinType.LEFT_OUTER_JOIN, + JoinType.RIGHT_OUTER_JOIN, + JoinType.FULL_OUTER_JOIN, + JoinType.LEFT_SEMI_JOIN, + JoinType.RIGHT_SEMI_JOIN, + JoinType.LEFT_ANTI_JOIN, + JoinType.RIGHT_ANTI_JOIN); /** * The abstract template method for query rewrite, it contains the main logic, try to rewrite query by diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/ComparisonResult.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/ComparisonResult.java index c60eb9f94d3d0f..2ffdeb5718bff5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/ComparisonResult.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/ComparisonResult.java @@ -17,6 +17,7 @@ package org.apache.doris.nereids.rules.exploration.mv; +import org.apache.doris.common.Pair; import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.Slot; @@ -27,6 +28,7 @@ import java.util.Collection; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; /** * comparison result of view and query @@ -111,8 +113,14 @@ public Builder addViewExpressions(Collection expressions) return this; } - public Builder addViewNoNullableSlot(Set viewNoNullableSlot) { - viewNoNullableSlotBuilder.add(ImmutableSet.copyOf(viewNoNullableSlot)); + /**Add slots which should reject null slots in view*/ + public Builder addViewNoNullableSlot(Pair, Set> viewNoNullableSlotsPair) { + if (!viewNoNullableSlotsPair.first.isEmpty()) { + viewNoNullableSlotBuilder.add(viewNoNullableSlotsPair.first); + } + if (!viewNoNullableSlotsPair.second.isEmpty()) { + viewNoNullableSlotBuilder.add(viewNoNullableSlotsPair.second); + } return this; } @@ -127,7 +135,9 @@ public boolean isInvalid() { public ComparisonResult build() { Preconditions.checkArgument(valid, "Comparison result must be valid"); - return new ComparisonResult(queryBuilder.build(), queryAllPulledUpExpressionsBuilder.build(), + return new ComparisonResult(queryBuilder.build(), + queryAllPulledUpExpressionsBuilder.build().stream() + .filter(expr -> !expr.isInferred()).collect(Collectors.toList()), viewBuilder.build(), viewNoNullableSlotBuilder.build(), valid, ""); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/HyperGraphComparator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/HyperGraphComparator.java index 341caa88094118..956a974982ccec 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/HyperGraphComparator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/HyperGraphComparator.java @@ -73,7 +73,11 @@ public class HyperGraphComparator { private final Map> pullUpQueryExprWithEdge = new HashMap<>(); private final Map> pullUpViewExprWithEdge = new HashMap<>(); private final LogicalCompatibilityContext logicalCompatibilityContext; - private final Map>> inferredViewEdgeWithCond = new HashMap<>(); + // this records the slots which needs to reject null + // the key is the target join which should reject null, the value is a pair, the first value of the pair is the + // join type, the second value is also a pair which left represents the slots in the left of join that should + // reject null, right represents the slots in the right of join that should reject null. + private final Map, Set>>> inferredViewEdgeWithCond = new HashMap<>(); private List viewJoinEdgesAfterInferring; private List viewFilterEdgesAfterInferring; private final long eliminateViewNodesMap; @@ -263,7 +267,7 @@ private ComparisonResult buildComparisonRes() { } builder.addViewExpressions(rawFilter); } - for (Pair> inferredCond : inferredViewEdgeWithCond.values()) { + for (Pair, Set>> inferredCond : inferredViewEdgeWithCond.values()) { builder.addViewNoNullableSlot(inferredCond.second); } builder.addQueryAllPulledUpExpressions( @@ -485,11 +489,14 @@ private boolean tryInferEdge(JoinEdge query, JoinEdge view) { if (noNullableChild == null) { return false; } - Set noNullableSlot = Sets.union( - noNullableChild.first ? view.getJoin().left().getOutputSet() : ImmutableSet.of(), - noNullableChild.second ? view.getJoin().right().getOutputSet() : ImmutableSet.of() - ); - inferredViewEdgeWithCond.put(view, Pair.of(query.getJoinType(), noNullableSlot)); + Pair, Set> noNullableSlotSetPair = Pair.of(ImmutableSet.of(), ImmutableSet.of()); + if (noNullableChild.first) { + noNullableSlotSetPair.first = view.getJoin().left().getOutputSet(); + } + if (noNullableChild.second) { + noNullableSlotSetPair.second = view.getJoin().right().getOutputSet(); + } + inferredViewEdgeWithCond.put(view, Pair.of(query.getJoinType(), noNullableSlotSetPair)); } return true; } diff --git a/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_1.groovy b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_1.groovy index 2b81dfd8aead29..3a60f5e90e4159 100644 --- a/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_1.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_1.groovy @@ -135,6 +135,19 @@ suite("partition_mv_rewrite_dimension_1") { """ } + def create_mv_all = { mv_name, mv_sql -> + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + sql """DROP TABLE IF EXISTS ${mv_name}""" + sql""" + CREATE MATERIALIZED VIEW ${mv_name} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + ${mv_sql} + """ + } + def compare_res = { def stmt -> sql "SET enable_materialized_view_rewrite=false" def origin_res = sql stmt @@ -155,9 +168,9 @@ suite("partition_mv_rewrite_dimension_1") { // join direction def mv_name_1 = "mv_join_1" def join_direction_mv_1 = """ - select l_shipdate, o_orderdate, l_partkey, l_suppkey - from lineitem_1 - left join orders_1 + select l_shipdate, o_orderdate, l_partkey, l_suppkey + from lineitem_1 + left join orders_1 on lineitem_1.l_orderkey = orders_1.o_orderkey """ @@ -166,15 +179,15 @@ suite("partition_mv_rewrite_dimension_1") { waitingMTMVTaskFinished(job_name_1) def join_direction_sql_1 = """ - select l_shipdate - from lineitem_1 - left join orders_1 + select l_shipdate + from lineitem_1 + left join orders_1 on lineitem_1.l_orderkey = orders_1.o_orderkey """ def join_direction_sql_2 = """ - select l_shipdate - from orders_1 - left join lineitem_1 + select l_shipdate + from orders_1 + left join lineitem_1 on orders_1.o_orderkey = lineitem_1.l_orderkey """ explain { @@ -191,9 +204,9 @@ suite("partition_mv_rewrite_dimension_1") { def mv_name_2 = "mv_join_2" def join_direction_mv_2 = """ - select l_shipdate, o_orderdate, l_partkey, l_suppkey - from lineitem_1 - inner join orders_1 + select l_shipdate, o_orderdate, l_partkey, l_suppkey + from lineitem_1 + inner join orders_1 on lineitem_1.l_orderkey = orders_1.o_orderkey """ @@ -202,15 +215,15 @@ suite("partition_mv_rewrite_dimension_1") { waitingMTMVTaskFinished(job_name_2) def join_direction_sql_3 = """ - select l_shipdate - from lineitem_1 - inner join orders_1 + select l_shipdate + from lineitem_1 + inner join orders_1 on lineitem_1.l_orderkey = orders_1.o_orderkey """ def join_direction_sql_4 = """ - select l_shipdate - from orders_1 - inner join lineitem_1 + select l_shipdate + from orders_1 + inner join lineitem_1 on orders_1.o_orderkey = lineitem_1.l_orderkey """ explain { @@ -227,50 +240,50 @@ suite("partition_mv_rewrite_dimension_1") { // join filter position def join_filter_stmt_1 = """ - select l_shipdate, o_orderdate, l_partkey, l_suppkey, o_orderkey - from lineitem_1 - left join orders_1 + select l_shipdate, o_orderdate, l_partkey, l_suppkey, o_orderkey + from lineitem_1 + left join orders_1 on lineitem_1.l_orderkey = orders_1.o_orderkey""" def join_filter_stmt_2 = """ - select l_shipdate, o_orderdate, l_partkey, l_suppkey, o_orderkey - from (select * from lineitem_1 where l_shipdate = '2023-10-17' ) t1 - left join orders_1 + select l_shipdate, o_orderdate, l_partkey, l_suppkey, o_orderkey + from (select * from lineitem_1 where l_shipdate = '2023-10-17' ) t1 + left join orders_1 on t1.l_orderkey = orders_1.o_orderkey""" def join_filter_stmt_3 = """ - select l_shipdate, o_orderdate, l_partkey, l_suppkey, o_orderkey - from lineitem_1 - left join (select * from orders_1 where o_orderdate = '2023-10-17' ) t2 + select l_shipdate, o_orderdate, l_partkey, l_suppkey, o_orderkey + from lineitem_1 + left join (select * from orders_1 where o_orderdate = '2023-10-17' ) t2 on lineitem_1.l_orderkey = t2.o_orderkey""" def join_filter_stmt_4 = """ - select l_shipdate, o_orderdate, l_partkey, l_suppkey, o_orderkey - from lineitem_1 - left join orders_1 - on lineitem_1.l_orderkey = orders_1.o_orderkey + select l_shipdate, o_orderdate, l_partkey, l_suppkey, o_orderkey + from lineitem_1 + left join orders_1 + on lineitem_1.l_orderkey = orders_1.o_orderkey where l_shipdate = '2023-10-17' and o_orderdate = '2023-10-17'""" def join_filter_stmt_5 = """ - select l_shipdate, o_orderdate, l_partkey, l_suppkey, o_orderkey - from lineitem_1 - left join orders_1 - on lineitem_1.l_orderkey = orders_1.o_orderkey + select l_shipdate, o_orderdate, l_partkey, l_suppkey, o_orderkey + from lineitem_1 + left join orders_1 + on lineitem_1.l_orderkey = orders_1.o_orderkey where l_shipdate = '2023-10-17'""" def join_filter_stmt_6 = """ - select l_shipdate, o_orderdate, l_partkey, l_suppkey, o_orderkey - from lineitem_1 - left join orders_1 - on lineitem_1.l_orderkey = orders_1.o_orderkey + select l_shipdate, o_orderdate, l_partkey, l_suppkey, o_orderkey + from lineitem_1 + left join orders_1 + on lineitem_1.l_orderkey = orders_1.o_orderkey where o_orderdate = '2023-10-17'""" def join_filter_stmt_7 = """ - select l_shipdate, o_orderdate, l_partkey, l_suppkey, o_orderkey - from lineitem_1 - left join orders_1 - on lineitem_1.l_orderkey = orders_1.o_orderkey + select l_shipdate, o_orderdate, l_partkey, l_suppkey, o_orderkey + from lineitem_1 + left join orders_1 + on lineitem_1.l_orderkey = orders_1.o_orderkey where orders_1.o_orderkey=1""" def mv_list = [ join_filter_stmt_1, join_filter_stmt_2, join_filter_stmt_3, join_filter_stmt_4, join_filter_stmt_5, join_filter_stmt_6, join_filter_stmt_7] - for (int i = 0; i < mv_list.size(); i++) { + for (int i =0; i < mv_list.size(); i++) { logger.info("i:" + i) def join_filter_mv = """join_filter_mv_${i}""" create_mv_lineitem(join_filter_mv, mv_list[i]) @@ -403,39 +416,49 @@ suite("partition_mv_rewrite_dimension_1") { from lineitem_1 inner join orders_1 on lineitem_1.l_orderkey = orders_1.o_orderkey""" - - // Todo: right/cross/full/semi/anti join - // Currently, only left join and inner join are supported. -// def join_type_stmt_3 = """ -// select l_shipdate, o_orderdate, l_partkey, l_suppkey -// from lineitem_1 -// right join orders_1 -// on lineitem_1.l_orderkey = orders_1.o_orderkey""" + def join_type_stmt_3 = """ + select l_shipdate, o_orderdate, l_partkey, l_suppkey + from lineitem_1 + right join orders_1 + on lineitem_1.l_orderkey = orders_1.o_orderkey""" // def join_type_stmt_4 = """ // select l_shipdate, o_orderdate, l_partkey, l_suppkey // from lineitem_1 // cross join orders_1""" -// def join_type_stmt_5 = """ -// select l_shipdate, o_orderdate, l_partkey, l_suppkey -// from lineitem_1 -// full join orders_1 -// on lineitem_1.l_orderkey = orders_1.o_orderkey""" -// def join_type_stmt_6 = """ -// select l_shipdate, o_orderdate, l_partkey, l_suppkey -// from lineitem_1 -// semi join orders_1 -// on lineitem_1.l_orderkey = orders_1.o_orderkey""" -// def join_type_stmt_7 = """ -// select l_shipdate, o_orderdate, l_partkey, l_suppkey -// from lineitem_1 -// anti join orders_1 -// on lineitem_1.l_orderkey = orders_1.o_orderkey""" - def join_type_stmt_list = [join_type_stmt_1, join_type_stmt_2] + def join_type_stmt_5 = """ + select l_shipdate, o_orderdate, l_partkey, l_suppkey + from lineitem_1 + full join orders_1 + on lineitem_1.l_orderkey = orders_1.o_orderkey""" + def join_type_stmt_6 = """ + select l_shipdate, l_partkey, l_suppkey, l_linenumber + from lineitem_1 + left semi join orders_1 + on lineitem_1.l_orderkey = orders_1.o_orderkey""" + def join_type_stmt_7 = """ + select o_orderdate, o_orderkey, o_custkey, o_orderstatus + from lineitem_1 + right semi join orders_1 + on lineitem_1.l_orderkey = orders_1.o_orderkey""" + def join_type_stmt_8 = """ + select l_shipdate, l_partkey, l_suppkey, l_linenumber + from lineitem_1 + left anti join orders_1 + on lineitem_1.l_orderkey = orders_1.o_orderkey""" + def join_type_stmt_9 = """ + select o_orderdate, o_orderkey, o_custkey, o_orderstatus + from lineitem_1 + right anti join orders_1 + on lineitem_1.l_orderkey = orders_1.o_orderkey""" + def join_type_stmt_list = [join_type_stmt_1, join_type_stmt_2, join_type_stmt_3, join_type_stmt_5, + join_type_stmt_6, join_type_stmt_7, join_type_stmt_8, join_type_stmt_9] for (int i = 0; i < join_type_stmt_list.size(); i++) { logger.info("i:" + i) String join_type_mv = """join_type_mv_${i}""" - if (i == 2) { + if (i == 2 || i == 5 || i == 7) { create_mv_orders(join_type_mv, join_type_stmt_list[i]) + } else if (i == 3) { + create_mv_all(join_type_mv, join_type_stmt_list[i]) } else { create_mv_lineitem(join_type_mv, join_type_stmt_list[i]) } @@ -465,30 +488,30 @@ suite("partition_mv_rewrite_dimension_1") { sql """DROP MATERIALIZED VIEW IF EXISTS ${agg_mv_name_1};""" sql """DROP TABLE IF EXISTS ${agg_mv_name_1}""" sql """ - CREATE MATERIALIZED VIEW ${agg_mv_name_1} - BUILD IMMEDIATE REFRESH AUTO ON MANUAL - DISTRIBUTED BY RANDOM BUCKETS 2 - PROPERTIES ('replication_num' = '1') - AS + CREATE MATERIALIZED VIEW ${agg_mv_name_1} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS select - sum(o_totalprice) as sum_total, - max(o_totalprice) as max_total, - min(o_totalprice) as min_total, - count(*) as count_all, - bitmap_union(to_bitmap(case when o_shippriority > 1 and o_orderkey IN (1, 3) then o_custkey else null end)) cnt_1, - bitmap_union(to_bitmap(case when o_shippriority > 2 and o_orderkey IN (2) then o_custkey else null end)) as cnt_2 + sum(o_totalprice) as sum_total, + max(o_totalprice) as max_total, + min(o_totalprice) as min_total, + count(*) as count_all, + bitmap_union(to_bitmap(case when o_shippriority > 1 and o_orderkey IN (1, 3) then o_custkey else null end)) cnt_1, + bitmap_union(to_bitmap(case when o_shippriority > 2 and o_orderkey IN (2) then o_custkey else null end)) as cnt_2 from orders_1 """ def agg_job_name_1 = getJobName(db, agg_mv_name_1) waitingMTMVTaskFinished(agg_job_name_1) - def agg_sql_1 = """select - count(distinct case when o_shippriority > 1 and o_orderkey IN (1, 3) then o_custkey else null end) as cnt_1, - count(distinct case when O_SHIPPRIORITY > 2 and o_orderkey IN (2) then o_custkey else null end) as cnt_2, - sum(o_totalprice), - max(o_totalprice), - min(o_totalprice), - count(*) + def agg_sql_1 = """select + count(distinct case when o_shippriority > 1 and o_orderkey IN (1, 3) then o_custkey else null end) as cnt_1, + count(distinct case when O_SHIPPRIORITY > 2 and o_orderkey IN (2) then o_custkey else null end) as cnt_2, + sum(o_totalprice), + max(o_totalprice), + min(o_totalprice), + count(*) from orders_1 """ explain { @@ -501,23 +524,23 @@ suite("partition_mv_rewrite_dimension_1") { // agg + with group by + without agg function def agg_mv_name_2 = "agg_mv_name_2" def agg_mv_stmt_2 = """ - select o_orderdate, o_shippriority, o_comment - from orders_1 - group by - o_orderdate, - o_shippriority, - o_comment + select o_orderdate, o_shippriority, o_comment + from orders_1 + group by + o_orderdate, + o_shippriority, + o_comment """ create_mv_orders(agg_mv_name_2, agg_mv_stmt_2) def agg_job_name_2 = getJobName(db, agg_mv_name_2) waitingMTMVTaskFinished(agg_job_name_2) sql """analyze table ${agg_mv_name_2} with sync;""" - def agg_sql_2 = """select o_shippriority, o_comment - from orders_1 - group by - o_shippriority, - o_comment + def agg_sql_2 = """select o_shippriority, o_comment + from orders_1 + group by + o_shippriority, + o_comment """ def agg_sql_explain_2 = sql """explain ${agg_sql_2};""" def mv_index_1 = agg_sql_explain_2.toString().indexOf("MaterializedViewRewriteFail:") @@ -528,35 +551,35 @@ suite("partition_mv_rewrite_dimension_1") { // agg + with group by + with agg function def agg_mv_name_3 = "agg_mv_name_3" def agg_mv_stmt_3 = """ - select o_orderdate, o_shippriority, o_comment, - sum(o_totalprice) as sum_total, - max(o_totalprice) as max_total, - min(o_totalprice) as min_total, - count(*) as count_all, - bitmap_union(to_bitmap(case when o_shippriority > 1 and o_orderkey IN (1, 3) then o_custkey else null end)) cnt_1, - bitmap_union(to_bitmap(case when o_shippriority > 2 and o_orderkey IN (2) then o_custkey else null end)) as cnt_2 - from orders_1 - group by - o_orderdate, - o_shippriority, - o_comment + select o_orderdate, o_shippriority, o_comment, + sum(o_totalprice) as sum_total, + max(o_totalprice) as max_total, + min(o_totalprice) as min_total, + count(*) as count_all, + bitmap_union(to_bitmap(case when o_shippriority > 1 and o_orderkey IN (1, 3) then o_custkey else null end)) cnt_1, + bitmap_union(to_bitmap(case when o_shippriority > 2 and o_orderkey IN (2) then o_custkey else null end)) as cnt_2 + from orders_1 + group by + o_orderdate, + o_shippriority, + o_comment """ create_mv_orders(agg_mv_name_3, agg_mv_stmt_3) def agg_job_name_3 = getJobName(db, agg_mv_name_3) waitingMTMVTaskFinished(agg_job_name_3) sql """analyze table ${agg_mv_name_3} with sync;""" - def agg_sql_3 = """select o_shippriority, o_comment, + def agg_sql_3 = """select o_shippriority, o_comment, count(distinct case when o_shippriority > 1 and o_orderkey IN (1, 3) then o_custkey else null end) as cnt_1, - count(distinct case when O_SHIPPRIORITY > 2 and o_orderkey IN (2) then o_custkey else null end) as cnt_2, - sum(o_totalprice), - max(o_totalprice), - min(o_totalprice), - count(*) - from orders_1 - group by - o_shippriority, - o_comment + count(distinct case when O_SHIPPRIORITY > 2 and o_orderkey IN (2) then o_custkey else null end) as cnt_2, + sum(o_totalprice), + max(o_totalprice), + min(o_totalprice), + count(*) + from orders_1 + group by + o_shippriority, + o_comment """ def agg_sql_explain_3 = sql """explain ${agg_sql_3};""" def mv_index_2 = agg_sql_explain_3.toString().indexOf("MaterializedViewRewriteFail:") @@ -686,4 +709,5 @@ suite("partition_mv_rewrite_dimension_1") { // contains "${rewriting_mv_name_1}(${rewriting_mv_name_1})" // } // sql """DROP MATERIALIZED VIEW IF EXISTS ${rewriting_mv_name_1};""" + } diff --git a/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_full_join.groovy b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_full_join.groovy new file mode 100644 index 00000000000000..82f3c0b0de8719 --- /dev/null +++ b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_full_join.groovy @@ -0,0 +1,441 @@ +// 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. + +/* +This suite is a two dimensional test case file. +It mainly tests the full join and filter positions. + */ +suite("partition_mv_rewrite_dimension_2_full_join") { + String db = context.config.getDbNameByFile(context.file) + sql "use ${db}" + sql "SET enable_nereids_planner=true" + sql "SET enable_fallback_to_original_planner=false" + sql "SET enable_materialized_view_rewrite=true" + sql "SET enable_nereids_timeout = false" + + sql """ + drop table if exists orders_2_full_join + """ + + sql """CREATE TABLE `orders_2_full_join` ( + `o_orderkey` BIGINT NULL, + `o_custkey` INT NULL, + `o_orderstatus` VARCHAR(1) NULL, + `o_totalprice` DECIMAL(15, 2) NULL, + `o_orderpriority` VARCHAR(15) NULL, + `o_clerk` VARCHAR(15) NULL, + `o_shippriority` INT NULL, + `o_comment` VARCHAR(79) NULL, + `o_orderdate` DATE not NULL + ) ENGINE=OLAP + DUPLICATE KEY(`o_orderkey`, `o_custkey`) + COMMENT 'OLAP' + AUTO PARTITION BY range date_trunc(`o_orderdate`, 'day') () + DISTRIBUTED BY HASH(`o_orderkey`) BUCKETS 96 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + );""" + + sql """ + drop table if exists lineitem_2_full_join + """ + + sql """CREATE TABLE `lineitem_2_full_join` ( + `l_orderkey` BIGINT NULL, + `l_linenumber` INT NULL, + `l_partkey` INT NULL, + `l_suppkey` INT NULL, + `l_quantity` DECIMAL(15, 2) NULL, + `l_extendedprice` DECIMAL(15, 2) NULL, + `l_discount` DECIMAL(15, 2) NULL, + `l_tax` DECIMAL(15, 2) NULL, + `l_returnflag` VARCHAR(1) NULL, + `l_linestatus` VARCHAR(1) NULL, + `l_commitdate` DATE NULL, + `l_receiptdate` DATE NULL, + `l_shipinstruct` VARCHAR(25) NULL, + `l_shipmode` VARCHAR(10) NULL, + `l_comment` VARCHAR(44) NULL, + `l_shipdate` DATE not NULL + ) ENGINE=OLAP + DUPLICATE KEY(l_orderkey, l_linenumber, l_partkey, l_suppkey ) + COMMENT 'OLAP' + AUTO PARTITION BY range date_trunc(`l_shipdate`, 'day') () + DISTRIBUTED BY HASH(`l_orderkey`) BUCKETS 96 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + );""" + + sql """ + insert into orders_2_full_join values + (null, 1, 'o', 99.5, 'a', 'b', 1, 'yy', '2023-10-17'), + (1, null, 'k', 109.2, 'c','d',2, 'mm', '2023-10-17'), + (3, 3, null, 99.5, 'a', 'b', 1, 'yy', '2023-10-19'), + (1, 2, 'o', null, 'a', 'b', 1, 'yy', '2023-10-20'), + (2, 3, 'k', 109.2, null,'d',2, 'mm', '2023-10-21'), + (3, 1, 'o', 99.5, 'a', null, 1, 'yy', '2023-10-22'), + (1, 3, 'k', 99.5, 'a', 'b', null, 'yy', '2023-10-19'), + (2, 1, 'o', 109.2, 'c','d',2, null, '2023-10-18'), + (3, 2, 'k', 99.5, 'a', 'b', 1, 'yy', '2023-10-17'), + (4, 5, 'o', 99.5, 'a', 'b', 1, 'yy', '2023-10-19'); + """ + + sql """ + insert into lineitem_2_full_join values + (null, 1, 2, 3, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (1, null, 3, 1, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-18', '2023-10-18', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (3, 3, null, 2, 7.5, 8.5, 9.5, 10.5, 'k', 'o', '2023-10-19', '2023-10-19', 'c', 'd', 'xxxxxxxxx', '2023-10-19'), + (1, 2, 3, null, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (2, 3, 2, 1, 5.5, 6.5, 7.5, 8.5, 'o', 'k', null, '2023-10-18', 'a', 'b', 'yyyyyyyyy', '2023-10-18'), + (3, 1, 1, 2, 7.5, 8.5, 9.5, 10.5, 'k', 'o', '2023-10-19', null, 'c', 'd', 'xxxxxxxxx', '2023-10-19'), + (1, 3, 2, 2, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'); + """ + + sql """analyze table orders_2_full_join with sync;""" + sql """analyze table lineitem_2_full_join with sync;""" + + def create_mv_lineitem = { mv_name, mv_sql -> + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + sql """DROP TABLE IF EXISTS ${mv_name}""" + sql""" + CREATE MATERIALIZED VIEW ${mv_name} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + partition by(l_shipdate) + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + ${mv_sql} + """ + } + + def create_mv_orders = { mv_name, mv_sql -> + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + sql """DROP TABLE IF EXISTS ${mv_name}""" + sql""" + CREATE MATERIALIZED VIEW ${mv_name} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + partition by(o_orderdate) + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + ${mv_sql} + """ + } + + def create_mv_all = { mv_name, mv_sql -> + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + sql """DROP TABLE IF EXISTS ${mv_name}""" + sql""" + CREATE MATERIALIZED VIEW ${mv_name} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + ${mv_sql} + """ + } + + def compare_res = { def stmt -> + sql "SET enable_materialized_view_rewrite=false" + def origin_res = sql stmt + logger.info("origin_res: " + origin_res) + sql "SET enable_materialized_view_rewrite=true" + def mv_origin_res = sql stmt + logger.info("mv_origin_res: " + mv_origin_res) + assertTrue((mv_origin_res == [] && origin_res == []) || (mv_origin_res.size() == origin_res.size())) + for (int row = 0; row < mv_origin_res.size(); row++) { + assertTrue(mv_origin_res[row].size() == origin_res[row].size()) + for (int col = 0; col < mv_origin_res[row].size(); col++) { + assertTrue(mv_origin_res[row][col] == origin_res[row][col]) + } + } + } + + // full join + filter on different position + def mv_stmt_0 = """select t.l_shipdate, o_orderdate, t.l_partkey, t.l_suppkey, orders_2_full_join.o_orderkey + from (select l_shipdate, l_partkey, l_suppkey, l_orderkey from lineitem_2_full_join where l_shipdate = '2023-10-17') t + full join orders_2_full_join + on t.l_orderkey = orders_2_full_join.o_orderkey""" + + def mv_stmt_1 = """select l_shipdate, t.o_orderdate, l_partkey, l_suppkey, t.o_orderkey + from lineitem_2_full_join + full join (select o_orderdate,o_orderkey from orders_2_full_join where o_orderdate = '2023-10-17' ) t + on lineitem_2_full_join.l_orderkey = t.o_orderkey""" + + def mv_stmt_2 = """select l_shipdate, o_orderdate, l_partkey, l_suppkey, orders_2_full_join.o_orderkey + from lineitem_2_full_join + full join orders_2_full_join + on lineitem_2_full_join.l_orderkey = orders_2_full_join.o_orderkey + where l_shipdate = '2023-10-17'""" + + def mv_stmt_3 = """select l_shipdate, o_orderdate, l_partkey, l_suppkey, orders_2_full_join.o_orderkey + from lineitem_2_full_join + full join orders_2_full_join + on lineitem_2_full_join.l_orderkey = orders_2_full_join.o_orderkey + where o_orderdate = '2023-10-17'""" + + def mv_stmt_4 = """select l_shipdate, o_orderdate, l_partkey, l_suppkey, orders_2_full_join.o_orderkey + from lineitem_2_full_join + full join orders_2_full_join + on lineitem_2_full_join.l_orderkey = orders_2_full_join.o_orderkey + where l_shipdate = '2023-10-17' and o_orderdate = '2023-10-17'""" + + def mv_stmt_5 = """select l_shipdate, o_orderdate, l_partkey, l_suppkey, orders_2_full_join.o_orderkey + from lineitem_2_full_join + full join orders_2_full_join + on lineitem_2_full_join.l_orderkey = orders_2_full_join.o_orderkey + where l_shipdate = '2023-10-17' and o_orderdate = '2023-10-17' + and o_orderkey = 1""" + + def mv_stmt_6 = """select t.l_shipdate, o_orderdate, t.l_partkey, t.l_suppkey, orders_2_full_join.o_orderkey + from orders_2_full_join + full join (select l_shipdate, l_orderkey, l_partkey, l_suppkey from lineitem_2_full_join where l_shipdate = '2023-10-17') t + on t.l_orderkey = orders_2_full_join.o_orderkey""" + + def mv_stmt_7 = """select l_shipdate, t.o_orderdate, l_partkey, l_suppkey, t.o_orderkey + from (select o_orderdate, o_orderkey from orders_2_full_join where o_orderdate = '2023-10-17' ) t + full join lineitem_2_full_join + on lineitem_2_full_join.l_orderkey = t.o_orderkey""" + + def mv_stmt_8 = """select l_shipdate, o_orderdate, l_partkey, l_suppkey, orders_2_full_join.o_orderkey + from orders_2_full_join + full join lineitem_2_full_join + on lineitem_2_full_join.l_orderkey = orders_2_full_join.o_orderkey + where l_shipdate = '2023-10-17' """ + + def mv_stmt_9 = """select l_shipdate, o_orderdate, l_partkey, l_suppkey, orders_2_full_join.o_orderkey + from orders_2_full_join + full join lineitem_2_full_join + on lineitem_2_full_join.l_orderkey = orders_2_full_join.o_orderkey + where o_orderdate = '2023-10-17' """ + + def mv_stmt_10 = """select l_shipdate, o_orderdate, l_partkey, l_suppkey, orders_2_full_join.o_orderkey + from orders_2_full_join + full join lineitem_2_full_join + on lineitem_2_full_join.l_orderkey = orders_2_full_join.o_orderkey + where l_shipdate = '2023-10-17' and o_orderdate = '2023-10-17' """ + + def mv_stmt_11 = """select l_shipdate, o_orderdate, l_partkey, l_suppkey, orders_2_full_join.o_orderkey + from orders_2_full_join + full join lineitem_2_full_join + on lineitem_2_full_join.l_orderkey = orders_2_full_join.o_orderkey + where l_shipdate = '2023-10-17' and o_orderdate = '2023-10-17' + and o_orderkey = 1""" + def mv_list_1 = [mv_stmt_0, mv_stmt_1, mv_stmt_2, mv_stmt_3, mv_stmt_4, mv_stmt_5, mv_stmt_6, + mv_stmt_7, mv_stmt_8, mv_stmt_9, mv_stmt_10, mv_stmt_11] + for (int i = 0; i < mv_list_1.size(); i++) { + logger.info("i:" + i) + def mv_name = """mv_name_2_full_join_${i}""" + create_mv_all(mv_name, mv_list_1[i]) + def job_name = getJobName(db, mv_name) + waitingMTMVTaskFinished(job_name) + if (i == 0) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("current index j:" + j) + if (j in [0, 2, 4, 5, 6, 8, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 1) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [1, 3, 4, 5, 7, 9, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 2) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [2, 4, 5, 8, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 3) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [3, 4, 5, 9, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 4) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [4, 5, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 5) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [5, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 6) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [0, 2, 4, 5, 6, 8, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 7) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [1, 3, 4, 5, 7, 9, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 8) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [2, 4, 5, 8, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 9) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [3, 4, 5, 9, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 10) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [4, 5, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 11) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [5, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + } +} diff --git a/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_2.groovy b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_inner_join.groovy similarity index 100% rename from regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_2.groovy rename to regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_inner_join.groovy diff --git a/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_left_anti_join.groovy b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_left_anti_join.groovy new file mode 100644 index 00000000000000..13c6bc9c82c319 --- /dev/null +++ b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_left_anti_join.groovy @@ -0,0 +1,299 @@ +// 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. + +/* +This suite is a two dimensional test case file. +It mainly tests the left anti join and filter positions. + */ +suite("partition_mv_rewrite_dimension_2_left_anti_join") { + String db = context.config.getDbNameByFile(context.file) + sql "use ${db}" + sql "SET enable_nereids_planner=true" + sql "SET enable_fallback_to_original_planner=false" + sql "SET enable_materialized_view_rewrite=true" + sql "SET enable_nereids_timeout = false" + + sql """ + drop table if exists orders_2_left_anti_join + """ + + sql """CREATE TABLE `orders_2_left_anti_join` ( + `o_orderkey` BIGINT NULL, + `o_custkey` INT NULL, + `o_orderstatus` VARCHAR(1) NULL, + `o_totalprice` DECIMAL(15, 2) NULL, + `o_orderpriority` VARCHAR(15) NULL, + `o_clerk` VARCHAR(15) NULL, + `o_shippriority` INT NULL, + `o_comment` VARCHAR(79) NULL, + `o_orderdate` DATE not NULL + ) ENGINE=OLAP + DUPLICATE KEY(`o_orderkey`, `o_custkey`) + COMMENT 'OLAP' + AUTO PARTITION BY range date_trunc(`o_orderdate`, 'day') () + DISTRIBUTED BY HASH(`o_orderkey`) BUCKETS 96 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + );""" + + sql """ + drop table if exists lineitem_2_left_anti_join + """ + + sql """CREATE TABLE `lineitem_2_left_anti_join` ( + `l_orderkey` BIGINT NULL, + `l_linenumber` INT NULL, + `l_partkey` INT NULL, + `l_suppkey` INT NULL, + `l_quantity` DECIMAL(15, 2) NULL, + `l_extendedprice` DECIMAL(15, 2) NULL, + `l_discount` DECIMAL(15, 2) NULL, + `l_tax` DECIMAL(15, 2) NULL, + `l_returnflag` VARCHAR(1) NULL, + `l_linestatus` VARCHAR(1) NULL, + `l_commitdate` DATE NULL, + `l_receiptdate` DATE NULL, + `l_shipinstruct` VARCHAR(25) NULL, + `l_shipmode` VARCHAR(10) NULL, + `l_comment` VARCHAR(44) NULL, + `l_shipdate` DATE not NULL + ) ENGINE=OLAP + DUPLICATE KEY(l_orderkey, l_linenumber, l_partkey, l_suppkey ) + COMMENT 'OLAP' + AUTO PARTITION BY range date_trunc(`l_shipdate`, 'day') () + DISTRIBUTED BY HASH(`l_orderkey`) BUCKETS 96 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + );""" + + sql """ + insert into orders_2_left_anti_join values + (null, 1, 'o', 99.5, 'a', 'b', 1, 'yy', '2023-10-17'), + (1, null, 'k', 109.2, 'c','d',2, 'mm', '2023-10-17'), + (3, 3, null, 99.5, 'a', 'b', 1, 'yy', '2023-10-19'), + (1, 2, 'o', null, 'a', 'b', 1, 'yy', '2023-10-20'), + (2, 3, 'k', 109.2, null,'d',2, 'mm', '2023-10-21'), + (3, 1, 'o', 99.5, 'a', null, 1, 'yy', '2023-10-22'), + (1, 3, 'o', 99.5, 'a', 'b', null, 'yy', '2023-10-19'), + (2, 1, 'k', 109.2, 'c','d',2, null, '2023-10-18'), + (3, 2, 'k', 99.5, 'a', 'b', 1, 'yy', '2023-10-17'), + (4, 5, 'o', 99.5, 'a', 'b', 1, 'yy', '2023-10-19'); + """ + + sql """ + insert into lineitem_2_left_anti_join values + (null, 1, 2, 3, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (1, null, 3, 1, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-18', '2023-10-18', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (3, 3, null, 2, 7.5, 8.5, 9.5, 10.5, 'k', 'o', '2023-10-19', '2023-10-19', 'c', 'd', 'xxxxxxxxx', '2023-10-19'), + (1, 2, 3, null, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (2, 3, 2, 1, 5.5, 6.5, 7.5, 8.5, 'o', 'k', null, '2023-10-18', 'a', 'b', 'yyyyyyyyy', '2023-10-18'), + (3, 1, 1, 2, 7.5, 8.5, 9.5, 10.5, 'k', 'o', '2023-10-19', null, 'c', 'd', 'xxxxxxxxx', '2023-10-19'), + (1, 3, 2, 2, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'); + """ + + sql """analyze table orders_2_left_anti_join with sync;""" + sql """analyze table lineitem_2_left_anti_join with sync;""" + + def create_mv_lineitem = { mv_name, mv_sql -> + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + sql """DROP TABLE IF EXISTS ${mv_name}""" + sql""" + CREATE MATERIALIZED VIEW ${mv_name} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + partition by(l_shipdate) + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + ${mv_sql} + """ + } + + def create_mv_orders = { mv_name, mv_sql -> + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + sql """DROP TABLE IF EXISTS ${mv_name}""" + sql""" + CREATE MATERIALIZED VIEW ${mv_name} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + partition by(o_orderdate) + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + ${mv_sql} + """ + } + + def compare_res = { def stmt -> + sql "SET enable_materialized_view_rewrite=false" + def origin_res = sql stmt + logger.info("origin_res: " + origin_res) + sql "SET enable_materialized_view_rewrite=true" + def mv_origin_res = sql stmt + logger.info("mv_origin_res: " + mv_origin_res) + assertTrue((mv_origin_res == [] && origin_res == []) || (mv_origin_res.size() == origin_res.size())) + for (int row = 0; row < mv_origin_res.size(); row++) { + assertTrue(mv_origin_res[row].size() == origin_res[row].size()) + for (int col = 0; col < mv_origin_res[row].size(); col++) { + assertTrue(mv_origin_res[row][col] == origin_res[row][col]) + } + } + } + + // left anti join + filter on different position + def mv_stmt_0 = """select t.l_shipdate, t.l_partkey, t.l_suppkey + from (select l_shipdate, l_partkey, l_suppkey, l_orderkey from lineitem_2_left_anti_join where l_shipdate = '2023-10-17') t + left anti join orders_2_left_anti_join + on t.l_orderkey = orders_2_left_anti_join.o_orderkey""" + + def mv_stmt_1 = """select l_shipdate, l_partkey, l_suppkey + from lineitem_2_left_anti_join + left anti join (select o_orderdate,o_orderkey from orders_2_left_anti_join where o_orderdate = '2023-10-17' ) t + on lineitem_2_left_anti_join.l_orderkey = t.o_orderkey""" + + def mv_stmt_2 = """select l_shipdate, l_partkey, l_suppkey + from lineitem_2_left_anti_join + left anti join orders_2_left_anti_join + on lineitem_2_left_anti_join.l_orderkey = orders_2_left_anti_join.o_orderkey + where l_shipdate = '2023-10-17'""" + + def mv_stmt_3 = """select o_orderkey, o_orderdate, o_custkey + from orders_2_left_anti_join + left anti join (select l_shipdate, l_orderkey, l_partkey, l_suppkey from lineitem_2_left_anti_join where l_shipdate = '2023-10-17') t + on t.l_orderkey = orders_2_left_anti_join.o_orderkey""" + + def mv_stmt_4 = """select t.o_orderkey, t.o_orderdate, t.o_custkey + from (select o_orderkey, o_orderdate, o_custkey from orders_2_left_anti_join where o_orderdate = '2023-10-17' ) t + left anti join lineitem_2_left_anti_join + on lineitem_2_left_anti_join.l_orderkey = t.o_orderkey""" + + def mv_stmt_5 = """select o_orderkey, o_orderdate, o_custkey + from orders_2_left_anti_join + left anti join lineitem_2_left_anti_join + on lineitem_2_left_anti_join.l_orderkey = orders_2_left_anti_join.o_orderkey + where o_orderdate = '2023-10-17' """ + + def mv_list_1 = [mv_stmt_0, mv_stmt_1, mv_stmt_2, mv_stmt_3, mv_stmt_4, mv_stmt_5] + def order_by_stmt = " order by 1,2,3" + for (int i = 0; i < mv_list_1.size(); i++) { + logger.info("i:" + i) + def mv_name = """mv_name_2_left_anti_join_${i}""" + if (i < 3) { + create_mv_lineitem(mv_name, mv_list_1[i]) + } else { + create_mv_orders(mv_name, mv_list_1[i]) + } + def job_name = getJobName(db, mv_name) + waitingMTMVTaskFinished(job_name) + if (i == 0) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [ 0, 2]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 1) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [1]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 2) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [0, 2]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 3) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [3]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 4) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [4, 5]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 5) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [4, 5]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + } +} diff --git a/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_1.groovy b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_left_join.groovy similarity index 99% rename from regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_1.groovy rename to regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_left_join.groovy index 328bf7925d13d2..cc3591c6f44417 100644 --- a/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_1.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_left_join.groovy @@ -227,7 +227,7 @@ suite("partition_mv_rewrite_dimension_2_1") { for (int i = 0; i < mv_list_1.size(); i++) { logger.info("i:" + i) def mv_name = """mv_name_2_1_${i}""" - if (i < 6) { + if (i < 3) { create_mv_lineitem(mv_name, mv_list_1[i]) } else { create_mv_orders(mv_name, mv_list_1[i]) @@ -334,7 +334,7 @@ suite("partition_mv_rewrite_dimension_2_1") { for (int j = 0; j < mv_list_1.size(); j++) { logger.info("j:" + j) // 5, 11 should be success but not now, should support in the future by equivalence class - if (j in [4, 6, 8, 10]) { + if (j in [4, 5, 6, 8, 10, 11]) { explain { sql("${mv_list_1[j]}") contains "${mv_name}(${mv_name})" diff --git a/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_left_semi_join.groovy b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_left_semi_join.groovy new file mode 100644 index 00000000000000..e018aab7d799b5 --- /dev/null +++ b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_left_semi_join.groovy @@ -0,0 +1,299 @@ +// 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. + +/* +This suite is a two dimensional test case file. +It mainly tests the left semi join and filter positions. + */ +suite("partition_mv_rewrite_dimension_2_left_semi_join") { + String db = context.config.getDbNameByFile(context.file) + sql "use ${db}" + sql "SET enable_nereids_planner=true" + sql "SET enable_fallback_to_original_planner=false" + sql "SET enable_materialized_view_rewrite=true" + sql "SET enable_nereids_timeout = false" + + sql """ + drop table if exists orders_2_left_semi_join + """ + + sql """CREATE TABLE `orders_2_left_semi_join` ( + `o_orderkey` BIGINT NULL, + `o_custkey` INT NULL, + `o_orderstatus` VARCHAR(1) NULL, + `o_totalprice` DECIMAL(15, 2) NULL, + `o_orderpriority` VARCHAR(15) NULL, + `o_clerk` VARCHAR(15) NULL, + `o_shippriority` INT NULL, + `o_comment` VARCHAR(79) NULL, + `o_orderdate` DATE not NULL + ) ENGINE=OLAP + DUPLICATE KEY(`o_orderkey`, `o_custkey`) + COMMENT 'OLAP' + AUTO PARTITION BY range date_trunc(`o_orderdate`, 'day') () + DISTRIBUTED BY HASH(`o_orderkey`) BUCKETS 96 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + );""" + + sql """ + drop table if exists lineitem_2_left_semi_join + """ + + sql """CREATE TABLE `lineitem_2_left_semi_join` ( + `l_orderkey` BIGINT NULL, + `l_linenumber` INT NULL, + `l_partkey` INT NULL, + `l_suppkey` INT NULL, + `l_quantity` DECIMAL(15, 2) NULL, + `l_extendedprice` DECIMAL(15, 2) NULL, + `l_discount` DECIMAL(15, 2) NULL, + `l_tax` DECIMAL(15, 2) NULL, + `l_returnflag` VARCHAR(1) NULL, + `l_linestatus` VARCHAR(1) NULL, + `l_commitdate` DATE NULL, + `l_receiptdate` DATE NULL, + `l_shipinstruct` VARCHAR(25) NULL, + `l_shipmode` VARCHAR(10) NULL, + `l_comment` VARCHAR(44) NULL, + `l_shipdate` DATE not NULL + ) ENGINE=OLAP + DUPLICATE KEY(l_orderkey, l_linenumber, l_partkey, l_suppkey ) + COMMENT 'OLAP' + AUTO PARTITION BY range date_trunc(`l_shipdate`, 'day') () + DISTRIBUTED BY HASH(`l_orderkey`) BUCKETS 96 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + );""" + + sql """ + insert into orders_2_left_semi_join values + (null, 1, 'o', 99.5, 'a', 'b', 1, 'yy', '2023-10-17'), + (1, null, 'k', 109.2, 'c','d',2, 'mm', '2023-10-17'), + (3, 3, null, 99.5, 'a', 'b', 1, 'yy', '2023-10-19'), + (1, 2, 'o', null, 'a', 'b', 1, 'yy', '2023-10-20'), + (2, 3, 'k', 109.2, null,'d',2, 'mm', '2023-10-21'), + (3, 1, 'o', 99.5, 'a', null, 1, 'yy', '2023-10-22'), + (1, 3, 'o', 99.5, 'a', 'b', null, 'yy', '2023-10-19'), + (2, 1, 'k', 109.2, 'c','d',2, null, '2023-10-18'), + (3, 2, 'k', 99.5, 'a', 'b', 1, 'yy', '2023-10-17'), + (4, 5, 'o', 99.5, 'a', 'b', 1, 'yy', '2023-10-19'); + """ + + sql """ + insert into lineitem_2_left_semi_join values + (null, 1, 2, 3, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (1, null, 3, 1, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-18', '2023-10-18', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (3, 3, null, 2, 7.5, 8.5, 9.5, 10.5, 'k', 'o', '2023-10-19', '2023-10-19', 'c', 'd', 'xxxxxxxxx', '2023-10-19'), + (1, 2, 3, null, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (2, 3, 2, 1, 5.5, 6.5, 7.5, 8.5, 'o', 'k', null, '2023-10-18', 'a', 'b', 'yyyyyyyyy', '2023-10-18'), + (3, 1, 1, 2, 7.5, 8.5, 9.5, 10.5, 'k', 'o', '2023-10-19', null, 'c', 'd', 'xxxxxxxxx', '2023-10-19'), + (1, 3, 2, 2, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'); + """ + + sql """analyze table orders_2_left_semi_join with sync;""" + sql """analyze table lineitem_2_left_semi_join with sync;""" + + def create_mv_lineitem = { mv_name, mv_sql -> + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + sql """DROP TABLE IF EXISTS ${mv_name}""" + sql""" + CREATE MATERIALIZED VIEW ${mv_name} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + partition by(l_shipdate) + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + ${mv_sql} + """ + } + + def create_mv_orders = { mv_name, mv_sql -> + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + sql """DROP TABLE IF EXISTS ${mv_name}""" + sql""" + CREATE MATERIALIZED VIEW ${mv_name} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + partition by(o_orderdate) + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + ${mv_sql} + """ + } + + def compare_res = { def stmt -> + sql "SET enable_materialized_view_rewrite=false" + def origin_res = sql stmt + logger.info("origin_res: " + origin_res) + sql "SET enable_materialized_view_rewrite=true" + def mv_origin_res = sql stmt + logger.info("mv_origin_res: " + mv_origin_res) + assertTrue((mv_origin_res == [] && origin_res == []) || (mv_origin_res.size() == origin_res.size())) + for (int row = 0; row < mv_origin_res.size(); row++) { + assertTrue(mv_origin_res[row].size() == origin_res[row].size()) + for (int col = 0; col < mv_origin_res[row].size(); col++) { + assertTrue(mv_origin_res[row][col] == origin_res[row][col]) + } + } + } + + // left semi join + filter on different position + def mv_stmt_0 = """select t.l_shipdate, t.l_partkey, t.l_suppkey + from (select l_shipdate, l_partkey, l_suppkey, l_orderkey from lineitem_2_left_semi_join where l_shipdate = '2023-10-17') t + left semi join orders_2_left_semi_join + on t.l_orderkey = orders_2_left_semi_join.o_orderkey""" + + def mv_stmt_1 = """select l_shipdate, l_partkey, l_suppkey + from lineitem_2_left_semi_join + left semi join (select o_orderdate,o_orderkey from orders_2_left_semi_join where o_orderdate = '2023-10-17' ) t + on lineitem_2_left_semi_join.l_orderkey = t.o_orderkey""" + + def mv_stmt_2 = """select l_shipdate, l_partkey, l_suppkey + from lineitem_2_left_semi_join + left semi join orders_2_left_semi_join + on lineitem_2_left_semi_join.l_orderkey = orders_2_left_semi_join.o_orderkey + where l_shipdate = '2023-10-17'""" + + def mv_stmt_3 = """select o_orderkey, o_orderdate, o_custkey + from orders_2_left_semi_join + left semi join (select l_shipdate, l_orderkey, l_partkey, l_suppkey from lineitem_2_left_semi_join where l_shipdate = '2023-10-17') t + on t.l_orderkey = orders_2_left_semi_join.o_orderkey""" + + def mv_stmt_4 = """select t.o_orderkey, t.o_orderdate, t.o_custkey + from (select o_orderkey, o_orderdate, o_custkey from orders_2_left_semi_join where o_orderdate = '2023-10-17' ) t + left semi join lineitem_2_left_semi_join + on lineitem_2_left_semi_join.l_orderkey = t.o_orderkey""" + + def mv_stmt_5 = """select o_orderkey, o_orderdate, o_custkey + from orders_2_left_semi_join + left semi join lineitem_2_left_semi_join + on lineitem_2_left_semi_join.l_orderkey = orders_2_left_semi_join.o_orderkey + where o_orderdate = '2023-10-17' """ + + def mv_list_1 = [mv_stmt_0, mv_stmt_1, mv_stmt_2, mv_stmt_3, mv_stmt_4, mv_stmt_5] + def order_by_stmt = " order by 1,2,3" + for (int i = 0; i < mv_list_1.size(); i++) { + logger.info("i:" + i) + def mv_name = """mv_name_2_left_semi_join_${i}""" + if (i < 3) { + create_mv_lineitem(mv_name, mv_list_1[i]) + } else { + create_mv_orders(mv_name, mv_list_1[i]) + } + def job_name = getJobName(db, mv_name) + waitingMTMVTaskFinished(job_name) + if (i == 0) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [ 0, 2]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 1) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [1]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 2) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [0, 2]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 3) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [3]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 4) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [4, 5]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 5) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [4, 5]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + } +} diff --git a/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_right_anti_join.groovy b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_right_anti_join.groovy new file mode 100644 index 00000000000000..b6b576b1926ac9 --- /dev/null +++ b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_right_anti_join.groovy @@ -0,0 +1,299 @@ +// 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. + +/* +This suite is a two dimensional test case file. +It mainly tests the right anti join and filter positions. + */ +suite("partition_mv_rewrite_dimension_2_right_anti_join") { + String db = context.config.getDbNameByFile(context.file) + sql "use ${db}" + sql "SET enable_nereids_planner=true" + sql "SET enable_fallback_to_original_planner=false" + sql "SET enable_materialized_view_rewrite=true" + sql "SET enable_nereids_timeout = false" + + sql """ + drop table if exists orders_2_right_anti_join + """ + + sql """CREATE TABLE `orders_2_right_anti_join` ( + `o_orderkey` BIGINT NULL, + `o_custkey` INT NULL, + `o_orderstatus` VARCHAR(1) NULL, + `o_totalprice` DECIMAL(15, 2) NULL, + `o_orderpriority` VARCHAR(15) NULL, + `o_clerk` VARCHAR(15) NULL, + `o_shippriority` INT NULL, + `o_comment` VARCHAR(79) NULL, + `o_orderdate` DATE not NULL + ) ENGINE=OLAP + DUPLICATE KEY(`o_orderkey`, `o_custkey`) + COMMENT 'OLAP' + AUTO PARTITION BY range date_trunc(`o_orderdate`, 'day') () + DISTRIBUTED BY HASH(`o_orderkey`) BUCKETS 96 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + );""" + + sql """ + drop table if exists lineitem_2_right_anti_join + """ + + sql """CREATE TABLE `lineitem_2_right_anti_join` ( + `l_orderkey` BIGINT NULL, + `l_linenumber` INT NULL, + `l_partkey` INT NULL, + `l_suppkey` INT NULL, + `l_quantity` DECIMAL(15, 2) NULL, + `l_extendedprice` DECIMAL(15, 2) NULL, + `l_discount` DECIMAL(15, 2) NULL, + `l_tax` DECIMAL(15, 2) NULL, + `l_returnflag` VARCHAR(1) NULL, + `l_linestatus` VARCHAR(1) NULL, + `l_commitdate` DATE NULL, + `l_receiptdate` DATE NULL, + `l_shipinstruct` VARCHAR(25) NULL, + `l_shipmode` VARCHAR(10) NULL, + `l_comment` VARCHAR(44) NULL, + `l_shipdate` DATE not NULL + ) ENGINE=OLAP + DUPLICATE KEY(l_orderkey, l_linenumber, l_partkey, l_suppkey ) + COMMENT 'OLAP' + AUTO PARTITION BY range date_trunc(`l_shipdate`, 'day') () + DISTRIBUTED BY HASH(`l_orderkey`) BUCKETS 96 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + );""" + + sql """ + insert into orders_2_right_anti_join values + (null, 1, 'o', 99.5, 'a', 'b', 1, 'yy', '2023-10-17'), + (1, null, 'k', 109.2, 'c','d',2, 'mm', '2023-10-17'), + (3, 3, null, 99.5, 'a', 'b', 1, 'yy', '2023-10-19'), + (1, 2, 'o', null, 'a', 'b', 1, 'yy', '2023-10-20'), + (2, 3, 'k', 109.2, null,'d',2, 'mm', '2023-10-21'), + (3, 1, 'o', 99.5, 'a', null, 1, 'yy', '2023-10-22'), + (1, 3, 'o', 99.5, 'a', 'b', null, 'yy', '2023-10-19'), + (2, 1, 'k', 109.2, 'c','d',2, null, '2023-10-18'), + (3, 2, 'k', 99.5, 'a', 'b', 1, 'yy', '2023-10-17'), + (4, 5, 'o', 99.5, 'a', 'b', 1, 'yy', '2023-10-19'); + """ + + sql """ + insert into lineitem_2_right_anti_join values + (null, 1, 2, 3, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (1, null, 3, 1, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-18', '2023-10-18', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (3, 3, null, 2, 7.5, 8.5, 9.5, 10.5, 'k', 'o', '2023-10-19', '2023-10-19', 'c', 'd', 'xxxxxxxxx', '2023-10-19'), + (1, 2, 3, null, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (2, 3, 2, 1, 5.5, 6.5, 7.5, 8.5, 'o', 'k', null, '2023-10-18', 'a', 'b', 'yyyyyyyyy', '2023-10-18'), + (3, 1, 1, 2, 7.5, 8.5, 9.5, 10.5, 'k', 'o', '2023-10-19', null, 'c', 'd', 'xxxxxxxxx', '2023-10-19'), + (1, 3, 2, 2, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'); + """ + + sql """analyze table orders_2_right_anti_join with sync;""" + sql """analyze table lineitem_2_right_anti_join with sync;""" + + def create_mv_lineitem = { mv_name, mv_sql -> + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + sql """DROP TABLE IF EXISTS ${mv_name}""" + sql""" + CREATE MATERIALIZED VIEW ${mv_name} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + partition by(l_shipdate) + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + ${mv_sql} + """ + } + + def create_mv_orders = { mv_name, mv_sql -> + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + sql """DROP TABLE IF EXISTS ${mv_name}""" + sql""" + CREATE MATERIALIZED VIEW ${mv_name} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + partition by(o_orderdate) + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + ${mv_sql} + """ + } + + def compare_res = { def stmt -> + sql "SET enable_materialized_view_rewrite=false" + def origin_res = sql stmt + logger.info("origin_res: " + origin_res) + sql "SET enable_materialized_view_rewrite=true" + def mv_origin_res = sql stmt + logger.info("mv_origin_res: " + mv_origin_res) + assertTrue((mv_origin_res == [] && origin_res == []) || (mv_origin_res.size() == origin_res.size())) + for (int row = 0; row < mv_origin_res.size(); row++) { + assertTrue(mv_origin_res[row].size() == origin_res[row].size()) + for (int col = 0; col < mv_origin_res[row].size(); col++) { + assertTrue(mv_origin_res[row][col] == origin_res[row][col]) + } + } + } + + // right anti join + filter on different position + def mv_stmt_0 = """select o_orderkey, o_orderdate, o_custkey + from (select l_shipdate, l_partkey, l_suppkey, l_orderkey from lineitem_2_right_anti_join where l_shipdate = '2023-10-17') t + right anti join orders_2_right_anti_join + on t.l_orderkey = orders_2_right_anti_join.o_orderkey""" + + def mv_stmt_1 = """select t.o_orderkey, t.o_orderdate, t.o_custkey + from lineitem_2_right_anti_join + right anti join (select o_orderdate,o_orderkey, o_custkey from orders_2_right_anti_join where o_orderdate = '2023-10-17' ) t + on lineitem_2_right_anti_join.l_orderkey = t.o_orderkey""" + + def mv_stmt_2 = """select o_orderkey, o_orderdate, o_custkey + from lineitem_2_right_anti_join + right anti join orders_2_right_anti_join + on lineitem_2_right_anti_join.l_orderkey = orders_2_right_anti_join.o_orderkey + where o_orderdate = '2023-10-17'""" + + def mv_stmt_3 = """select t.l_shipdate, t.l_partkey, t.l_suppkey + from orders_2_right_anti_join + right anti join (select l_shipdate, l_orderkey, l_partkey, l_suppkey from lineitem_2_right_anti_join where l_shipdate = '2023-10-17') t + on t.l_orderkey = orders_2_right_anti_join.o_orderkey""" + + def mv_stmt_4 = """select l_shipdate, l_partkey, l_suppkey + from (select o_orderkey, o_orderdate, o_custkey from orders_2_right_anti_join where o_orderdate = '2023-10-17' ) t + right anti join lineitem_2_right_anti_join + on lineitem_2_right_anti_join.l_orderkey = t.o_orderkey""" + + def mv_stmt_5 = """select l_shipdate, l_partkey, l_suppkey + from orders_2_right_anti_join + right anti join lineitem_2_right_anti_join + on lineitem_2_right_anti_join.l_orderkey = orders_2_right_anti_join.o_orderkey + where l_shipdate = '2023-10-17' """ + + def mv_list_1 = [mv_stmt_0, mv_stmt_1, mv_stmt_2, mv_stmt_3, mv_stmt_4, mv_stmt_5] + def order_by_stmt = " order by 1,2,3" + for (int i = 0; i < mv_list_1.size(); i++) { + logger.info("i:" + i) + def mv_name = """mv_name_2_right_anti_join_${i}""" + if (i < 3) { + create_mv_orders(mv_name, mv_list_1[i]) + } else { + create_mv_lineitem(mv_name, mv_list_1[i]) + } + def job_name = getJobName(db, mv_name) + waitingMTMVTaskFinished(job_name) + if (i == 0) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [0]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 1) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [1, 2]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 2) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [1, 2]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 3) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [3, 5]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 4) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [4]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 5) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [3, 5]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + } +} diff --git a/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_right_join.groovy b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_right_join.groovy new file mode 100644 index 00000000000000..996ca5ae78b24f --- /dev/null +++ b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_right_join.groovy @@ -0,0 +1,434 @@ +// 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. + +/* +This suite is a two dimensional test case file. +It mainly tests the right join and filter positions. + */ +suite("partition_mv_rewrite_dimension_2_right_join") { + String db = context.config.getDbNameByFile(context.file) + sql "use ${db}" + sql "SET enable_nereids_planner=true" + sql "SET enable_fallback_to_original_planner=false" + sql "SET enable_materialized_view_rewrite=true" + sql "SET enable_nereids_timeout = false" + + sql """ + drop table if exists orders_2_right_join + """ + + sql """CREATE TABLE `orders_2_right_join` ( + `o_orderkey` BIGINT NULL, + `o_custkey` INT NULL, + `o_orderstatus` VARCHAR(1) NULL, + `o_totalprice` DECIMAL(15, 2) NULL, + `o_orderpriority` VARCHAR(15) NULL, + `o_clerk` VARCHAR(15) NULL, + `o_shippriority` INT NULL, + `o_comment` VARCHAR(79) NULL, + `o_orderdate` DATE not NULL + ) ENGINE=OLAP + DUPLICATE KEY(`o_orderkey`, `o_custkey`) + COMMENT 'OLAP' + AUTO PARTITION BY range date_trunc(`o_orderdate`, 'day') () + DISTRIBUTED BY HASH(`o_orderkey`) BUCKETS 96 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + );""" + + sql """ + drop table if exists lineitem_2_right_join + """ + + sql """CREATE TABLE `lineitem_2_right_join` ( + `l_orderkey` BIGINT NULL, + `l_linenumber` INT NULL, + `l_partkey` INT NULL, + `l_suppkey` INT NULL, + `l_quantity` DECIMAL(15, 2) NULL, + `l_extendedprice` DECIMAL(15, 2) NULL, + `l_discount` DECIMAL(15, 2) NULL, + `l_tax` DECIMAL(15, 2) NULL, + `l_returnflag` VARCHAR(1) NULL, + `l_linestatus` VARCHAR(1) NULL, + `l_commitdate` DATE NULL, + `l_receiptdate` DATE NULL, + `l_shipinstruct` VARCHAR(25) NULL, + `l_shipmode` VARCHAR(10) NULL, + `l_comment` VARCHAR(44) NULL, + `l_shipdate` DATE not NULL + ) ENGINE=OLAP + DUPLICATE KEY(l_orderkey, l_linenumber, l_partkey, l_suppkey ) + COMMENT 'OLAP' + AUTO PARTITION BY range date_trunc(`l_shipdate`, 'day') () + DISTRIBUTED BY HASH(`l_orderkey`) BUCKETS 96 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + );""" + + sql """ + insert into orders_2_right_join values + (null, 1, 'o', 99.5, 'a', 'b', 1, 'yy', '2023-10-17'), + (1, null, 'k', 109.2, 'c','d',2, 'mm', '2023-10-17'), + (3, 3, null, 99.5, 'a', 'b', 1, 'yy', '2023-10-19'), + (1, 2, 'o', null, 'a', 'b', 1, 'yy', '2023-10-20'), + (2, 3, 'k', 109.2, null,'d',2, 'mm', '2023-10-21'), + (3, 1, 'o', 99.5, 'a', null, 1, 'yy', '2023-10-22'), + (1, 3, 'o', 99.5, 'a', 'b', null, 'yy', '2023-10-19'), + (2, 1, 'k', 109.2, 'c','d',2, null, '2023-10-18'), + (3, 2, 'k', 99.5, 'a', 'b', 1, 'yy', '2023-10-17'), + (4, 5, 'o', 99.5, 'a', 'b', 1, 'yy', '2023-10-19'); + """ + + sql """ + insert into lineitem_2_right_join values + (null, 1, 2, 3, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (1, null, 3, 1, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-18', '2023-10-18', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (3, 3, null, 2, 7.5, 8.5, 9.5, 10.5, 'k', 'o', '2023-10-19', '2023-10-19', 'c', 'd', 'xxxxxxxxx', '2023-10-19'), + (1, 2, 3, null, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (2, 3, 2, 1, 5.5, 6.5, 7.5, 8.5, 'o', 'k', null, '2023-10-18', 'a', 'b', 'yyyyyyyyy', '2023-10-18'), + (3, 1, 1, 2, 7.5, 8.5, 9.5, 10.5, 'k', 'o', '2023-10-19', null, 'c', 'd', 'xxxxxxxxx', '2023-10-19'), + (1, 3, 2, 2, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'); + """ + + sql """analyze table orders_2_right_join with sync;""" + sql """analyze table lineitem_2_right_join with sync;""" + + def create_mv_lineitem = { mv_name, mv_sql -> + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + sql """DROP TABLE IF EXISTS ${mv_name}""" + sql""" + CREATE MATERIALIZED VIEW ${mv_name} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + partition by(l_shipdate) + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + ${mv_sql} + """ + } + + def create_mv_orders = { mv_name, mv_sql -> + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + sql """DROP TABLE IF EXISTS ${mv_name}""" + sql""" + CREATE MATERIALIZED VIEW ${mv_name} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + partition by(o_orderdate) + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + ${mv_sql} + """ + } + + def compare_res = { def stmt -> + sql "SET enable_materialized_view_rewrite=false" + def origin_res = sql stmt + logger.info("origin_res: " + origin_res) + sql "SET enable_materialized_view_rewrite=true" + def mv_origin_res = sql stmt + logger.info("mv_origin_res: " + mv_origin_res) + assertTrue((mv_origin_res == [] && origin_res == []) || (mv_origin_res.size() == origin_res.size())) + for (int row = 0; row < mv_origin_res.size(); row++) { + assertTrue(mv_origin_res[row].size() == origin_res[row].size()) + for (int col = 0; col < mv_origin_res[row].size(); col++) { + assertTrue(mv_origin_res[row][col] == origin_res[row][col]) + } + } + } + + def mv_stmt_0 = """select t.l_shipdate, o_orderdate, t.l_partkey, t.l_suppkey, orders_2_right_join.o_orderkey + from orders_2_right_join + right join (select l_shipdate, l_orderkey, l_partkey, l_suppkey from lineitem_2_right_join where l_shipdate = '2023-10-17') t + on t.l_orderkey = orders_2_right_join.o_orderkey""" + + def mv_stmt_1 = """select l_shipdate, t.o_orderdate, l_partkey, l_suppkey, t.o_orderkey + from (select o_orderdate, o_orderkey from orders_2_right_join where o_orderdate = '2023-10-17' ) t + right join lineitem_2_right_join + on lineitem_2_right_join.l_orderkey = t.o_orderkey""" + + def mv_stmt_2 = """select l_shipdate, o_orderdate, l_partkey, l_suppkey, orders_2_right_join.o_orderkey + from orders_2_right_join + right join lineitem_2_right_join + on lineitem_2_right_join.l_orderkey = orders_2_right_join.o_orderkey + where l_shipdate = '2023-10-17' """ + + def mv_stmt_3 = """select l_shipdate, o_orderdate, l_partkey, l_suppkey, orders_2_right_join.o_orderkey + from orders_2_right_join + right join lineitem_2_right_join + on lineitem_2_right_join.l_orderkey = orders_2_right_join.o_orderkey + where o_orderdate = '2023-10-17' """ + + def mv_stmt_4 = """select l_shipdate, o_orderdate, l_partkey, l_suppkey, orders_2_right_join.o_orderkey + from orders_2_right_join + right join lineitem_2_right_join + on lineitem_2_right_join.l_orderkey = orders_2_right_join.o_orderkey + where l_shipdate = '2023-10-17' and o_orderdate = '2023-10-17' """ + + def mv_stmt_5 = """select l_shipdate, o_orderdate, l_partkey, l_suppkey, orders_2_right_join.o_orderkey + from orders_2_right_join + right join lineitem_2_right_join + on lineitem_2_right_join.l_orderkey = orders_2_right_join.o_orderkey + where l_shipdate = '2023-10-17' and o_orderdate = '2023-10-17' + and o_orderkey = 1""" + + // right join + filter on different position + def mv_stmt_6 = """select t.l_shipdate, o_orderdate, t.l_partkey, t.l_suppkey, orders_2_right_join.o_orderkey + from (select l_shipdate, l_partkey, l_suppkey, l_orderkey from lineitem_2_right_join where l_shipdate = '2023-10-17') t + right join orders_2_right_join + on t.l_orderkey = orders_2_right_join.o_orderkey""" + + def mv_stmt_7 = """select l_shipdate, t.o_orderdate, l_partkey, l_suppkey, t.o_orderkey + from lineitem_2_right_join + right join (select o_orderdate,o_orderkey from orders_2_right_join where o_orderdate = '2023-10-17' ) t + on lineitem_2_right_join.l_orderkey = t.o_orderkey""" + + def mv_stmt_8 = """select l_shipdate, o_orderdate, l_partkey, l_suppkey, orders_2_right_join.o_orderkey + from lineitem_2_right_join + right join orders_2_right_join + on lineitem_2_right_join.l_orderkey = orders_2_right_join.o_orderkey + where l_shipdate = '2023-10-17'""" + + def mv_stmt_9 = """select l_shipdate, o_orderdate, l_partkey, l_suppkey, orders_2_right_join.o_orderkey + from lineitem_2_right_join + right join orders_2_right_join + on lineitem_2_right_join.l_orderkey = orders_2_right_join.o_orderkey + where o_orderdate = '2023-10-17'""" + + def mv_stmt_10 = """select l_shipdate, o_orderdate, l_partkey, l_suppkey, orders_2_right_join.o_orderkey + from lineitem_2_right_join + right join orders_2_right_join + on lineitem_2_right_join.l_orderkey = orders_2_right_join.o_orderkey + where l_shipdate = '2023-10-17' and o_orderdate = '2023-10-17'""" + + def mv_stmt_11 = """select l_shipdate, o_orderdate, l_partkey, l_suppkey, orders_2_right_join.o_orderkey + from lineitem_2_right_join + right join orders_2_right_join + on lineitem_2_right_join.l_orderkey = orders_2_right_join.o_orderkey + where l_shipdate = '2023-10-17' and o_orderdate = '2023-10-17' + and o_orderkey = 1""" + + def mv_list_1 = [mv_stmt_0, mv_stmt_1, mv_stmt_2, mv_stmt_3, mv_stmt_4, mv_stmt_5, mv_stmt_6, + mv_stmt_7, mv_stmt_8, mv_stmt_9, mv_stmt_10, mv_stmt_11] + for (int i = 0; i < mv_list_1.size(); i++) { + logger.info("i:" + i) + def mv_name = """mv_name_2_right_join_${i}""" + if (i < 6) { + create_mv_lineitem(mv_name, mv_list_1[i]) + } else { + create_mv_orders(mv_name, mv_list_1[i]) + } + def job_name = getJobName(db, mv_name) + waitingMTMVTaskFinished(job_name) + if (i == 0) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [ 0, 2, 4, 5, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 1) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [1, 3, 4, 5, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 2) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [0, 2, 4, 5, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 3) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [3, 4, 5, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 4) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [4, 5, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 5) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [5, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 6) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + // 5, 11 should be success but not now, should support in the future by equivalence class + if (j in [4, 5, 6, 8, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 7) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [4, 5, 7, 9, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 8) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [4, 5, 8, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 9) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [4, 5, 7, 9, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 10) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [4, 5, 10, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 11) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [5, 11]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + " order by 1,2,3,4,5") + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + } +} diff --git a/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_right_semi_join.groovy b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_right_semi_join.groovy new file mode 100644 index 00000000000000..39b9497610693c --- /dev/null +++ b/regression-test/suites/nereids_rules_p0/mv/dimension/dimension_2_right_semi_join.groovy @@ -0,0 +1,299 @@ +// 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. + +/* +This suite is a two dimensional test case file. +It mainly tests the right semi join and filter positions. + */ +suite("partition_mv_rewrite_dimension_2_right_semi_join") { + String db = context.config.getDbNameByFile(context.file) + sql "use ${db}" + sql "SET enable_nereids_planner=true" + sql "SET enable_fallback_to_original_planner=false" + sql "SET enable_materialized_view_rewrite=true" + sql "SET enable_nereids_timeout = false" + + sql """ + drop table if exists orders_2_right_semi_join + """ + + sql """CREATE TABLE `orders_2_right_semi_join` ( + `o_orderkey` BIGINT NULL, + `o_custkey` INT NULL, + `o_orderstatus` VARCHAR(1) NULL, + `o_totalprice` DECIMAL(15, 2) NULL, + `o_orderpriority` VARCHAR(15) NULL, + `o_clerk` VARCHAR(15) NULL, + `o_shippriority` INT NULL, + `o_comment` VARCHAR(79) NULL, + `o_orderdate` DATE not NULL + ) ENGINE=OLAP + DUPLICATE KEY(`o_orderkey`, `o_custkey`) + COMMENT 'OLAP' + AUTO PARTITION BY range date_trunc(`o_orderdate`, 'day') () + DISTRIBUTED BY HASH(`o_orderkey`) BUCKETS 96 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + );""" + + sql """ + drop table if exists lineitem_2_right_semi_join + """ + + sql """CREATE TABLE `lineitem_2_right_semi_join` ( + `l_orderkey` BIGINT NULL, + `l_linenumber` INT NULL, + `l_partkey` INT NULL, + `l_suppkey` INT NULL, + `l_quantity` DECIMAL(15, 2) NULL, + `l_extendedprice` DECIMAL(15, 2) NULL, + `l_discount` DECIMAL(15, 2) NULL, + `l_tax` DECIMAL(15, 2) NULL, + `l_returnflag` VARCHAR(1) NULL, + `l_linestatus` VARCHAR(1) NULL, + `l_commitdate` DATE NULL, + `l_receiptdate` DATE NULL, + `l_shipinstruct` VARCHAR(25) NULL, + `l_shipmode` VARCHAR(10) NULL, + `l_comment` VARCHAR(44) NULL, + `l_shipdate` DATE not NULL + ) ENGINE=OLAP + DUPLICATE KEY(l_orderkey, l_linenumber, l_partkey, l_suppkey ) + COMMENT 'OLAP' + AUTO PARTITION BY range date_trunc(`l_shipdate`, 'day') () + DISTRIBUTED BY HASH(`l_orderkey`) BUCKETS 96 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + );""" + + sql """ + insert into orders_2_right_semi_join values + (null, 1, 'o', 99.5, 'a', 'b', 1, 'yy', '2023-10-17'), + (1, null, 'k', 109.2, 'c','d',2, 'mm', '2023-10-17'), + (3, 3, null, 99.5, 'a', 'b', 1, 'yy', '2023-10-19'), + (1, 2, 'o', null, 'a', 'b', 1, 'yy', '2023-10-20'), + (2, 3, 'k', 109.2, null,'d',2, 'mm', '2023-10-21'), + (3, 1, 'o', 99.5, 'a', null, 1, 'yy', '2023-10-22'), + (1, 3, 'o', 99.5, 'a', 'b', null, 'yy', '2023-10-19'), + (2, 1, 'k', 109.2, 'c','d',2, null, '2023-10-18'), + (3, 2, 'k', 99.5, 'a', 'b', 1, 'yy', '2023-10-17'), + (4, 5, 'o', 99.5, 'a', 'b', 1, 'yy', '2023-10-19'); + """ + + sql """ + insert into lineitem_2_right_semi_join values + (null, 1, 2, 3, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (1, null, 3, 1, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-18', '2023-10-18', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (3, 3, null, 2, 7.5, 8.5, 9.5, 10.5, 'k', 'o', '2023-10-19', '2023-10-19', 'c', 'd', 'xxxxxxxxx', '2023-10-19'), + (1, 2, 3, null, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'), + (2, 3, 2, 1, 5.5, 6.5, 7.5, 8.5, 'o', 'k', null, '2023-10-18', 'a', 'b', 'yyyyyyyyy', '2023-10-18'), + (3, 1, 1, 2, 7.5, 8.5, 9.5, 10.5, 'k', 'o', '2023-10-19', null, 'c', 'd', 'xxxxxxxxx', '2023-10-19'), + (1, 3, 2, 2, 5.5, 6.5, 7.5, 8.5, 'o', 'k', '2023-10-17', '2023-10-17', 'a', 'b', 'yyyyyyyyy', '2023-10-17'); + """ + + sql """analyze table orders_2_right_semi_join with sync;""" + sql """analyze table lineitem_2_right_semi_join with sync;""" + + def create_mv_lineitem = { mv_name, mv_sql -> + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + sql """DROP TABLE IF EXISTS ${mv_name}""" + sql""" + CREATE MATERIALIZED VIEW ${mv_name} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + partition by(l_shipdate) + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + ${mv_sql} + """ + } + + def create_mv_orders = { mv_name, mv_sql -> + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + sql """DROP TABLE IF EXISTS ${mv_name}""" + sql""" + CREATE MATERIALIZED VIEW ${mv_name} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + partition by(o_orderdate) + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + ${mv_sql} + """ + } + + def compare_res = { def stmt -> + sql "SET enable_materialized_view_rewrite=false" + def origin_res = sql stmt + logger.info("origin_res: " + origin_res) + sql "SET enable_materialized_view_rewrite=true" + def mv_origin_res = sql stmt + logger.info("mv_origin_res: " + mv_origin_res) + assertTrue((mv_origin_res == [] && origin_res == []) || (mv_origin_res.size() == origin_res.size())) + for (int row = 0; row < mv_origin_res.size(); row++) { + assertTrue(mv_origin_res[row].size() == origin_res[row].size()) + for (int col = 0; col < mv_origin_res[row].size(); col++) { + assertTrue(mv_origin_res[row][col] == origin_res[row][col]) + } + } + } + + // right semi join + filter on different position + def mv_stmt_0 = """select o_orderkey, o_orderdate, o_custkey + from (select l_shipdate, l_partkey, l_suppkey, l_orderkey from lineitem_2_right_semi_join where l_shipdate = '2023-10-17') t + right semi join orders_2_right_semi_join + on t.l_orderkey = orders_2_right_semi_join.o_orderkey""" + + def mv_stmt_1 = """select t.o_orderkey, t.o_orderdate, t.o_custkey + from lineitem_2_right_semi_join + right semi join (select o_orderdate, o_orderkey, o_custkey from orders_2_right_semi_join where o_orderdate = '2023-10-17' ) t + on lineitem_2_right_semi_join.l_orderkey = t.o_orderkey""" + + def mv_stmt_2 = """select o_orderkey, o_orderdate, o_custkey + from lineitem_2_right_semi_join + right semi join orders_2_right_semi_join + on lineitem_2_right_semi_join.l_orderkey = orders_2_right_semi_join.o_orderkey + where o_orderdate = '2023-10-17'""" + + def mv_stmt_3 = """select t.l_shipdate, t.l_partkey, t.l_suppkey + from orders_2_right_semi_join + right semi join (select l_shipdate, l_orderkey, l_partkey, l_suppkey from lineitem_2_right_semi_join where l_shipdate = '2023-10-17') t + on t.l_orderkey = orders_2_right_semi_join.o_orderkey""" + + def mv_stmt_4 = """select l_shipdate, l_partkey, l_suppkey + from (select o_orderkey, o_orderdate, o_custkey from orders_2_right_semi_join where o_orderdate = '2023-10-17' ) t + right semi join lineitem_2_right_semi_join + on lineitem_2_right_semi_join.l_orderkey = t.o_orderkey""" + + def mv_stmt_5 = """select l_shipdate, l_partkey, l_suppkey + from orders_2_right_semi_join + right semi join lineitem_2_right_semi_join + on lineitem_2_right_semi_join.l_orderkey = orders_2_right_semi_join.o_orderkey + where l_shipdate = '2023-10-17' """ + + def mv_list_1 = [mv_stmt_0, mv_stmt_1, mv_stmt_2, mv_stmt_3, mv_stmt_4, mv_stmt_5] + def order_by_stmt = " order by 1,2,3" + for (int i = 0; i < mv_list_1.size(); i++) { + logger.info("i:" + i) + def mv_name = """mv_name_2_right_semi_join_${i}""" + if (i < 3) { + create_mv_orders(mv_name, mv_list_1[i]) + } else { + create_mv_lineitem(mv_name, mv_list_1[i]) + } + def job_name = getJobName(db, mv_name) + waitingMTMVTaskFinished(job_name) + if (i == 0) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [0]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 1) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [1, 2]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 2) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [1, 2]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 3) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [3, 5]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 4) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [4]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } else if (i == 5) { + for (int j = 0; j < mv_list_1.size(); j++) { + logger.info("j:" + j) + if (j in [3, 5]) { + explain { + sql("${mv_list_1[j]}") + contains "${mv_name}(${mv_name})" + } + compare_res(mv_list_1[j] + order_by_stmt) + } else { + explain { + sql("${mv_list_1[j]}") + notContains "${mv_name}(${mv_name})" + } + } + } + } + sql """DROP MATERIALIZED VIEW IF EXISTS ${mv_name};""" + } +} diff --git a/regression-test/suites/nereids_rules_p0/mv/dimension_2_join_agg/dimension_2_join_agg.groovy b/regression-test/suites/nereids_rules_p0/mv/dimension_2_join_agg/dimension_2_join_agg.groovy index a6702710a14016..055861fd344b7d 100644 --- a/regression-test/suites/nereids_rules_p0/mv/dimension_2_join_agg/dimension_2_join_agg.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/dimension_2_join_agg/dimension_2_join_agg.groovy @@ -883,17 +883,21 @@ suite("dimension_2_join_agg_replenish") { t1.sum_total, col3, count_all """ - def sql_list = [left_mv_stmt_1,left_mv_stmt_2,left_mv_stmt_3,left_mv_stmt_4,left_mv_stmt_5,left_mv_stmt_6,left_mv_stmt_7,left_mv_stmt_8,left_mv_stmt_9,left_mv_stmt_10, - right_mv_stmt_1,right_mv_stmt_2,right_mv_stmt_3,right_mv_stmt_4,right_mv_stmt_5,right_mv_stmt_6,right_mv_stmt_7,right_mv_stmt_8,right_mv_stmt_9,right_mv_stmt_10, - inner_mv_stmt_1,inner_mv_stmt_2,inner_mv_stmt_3,inner_mv_stmt_4,inner_mv_stmt_5,inner_mv_stmt_6,inner_mv_stmt_7,inner_mv_stmt_8,inner_mv_stmt_9,inner_mv_stmt_10] -// query rewrite by materialzied view only support inner join, left outer join and right outer join(which can be converted to left outer join) -// full_mv_stmt_1,full_mv_stmt_2,full_mv_stmt_3,full_mv_stmt_4,full_mv_stmt_5,full_mv_stmt_6,full_mv_stmt_7,full_mv_stmt_8,full_mv_stmt_9,full_mv_stmt_10, -// cross_mv_stmt_1,cross_mv_stmt_2,cross_mv_stmt_3,cross_mv_stmt_4,cross_mv_stmt_5,cross_mv_stmt_6,cross_mv_stmt_7,cross_mv_stmt_8,cross_mv_stmt_9,cross_mv_stmt_10, -// left_semi_mv_stmt_1,left_semi_mv_stmt_2,left_semi_mv_stmt_3,left_semi_mv_stmt_4,left_semi_mv_stmt_5,left_semi_mv_stmt_6,left_semi_mv_stmt_7,left_semi_mv_stmt_8,left_semi_mv_stmt_9,left_semi_mv_stmt_10, -// left_anti_mv_stmt_1,left_anti_mv_stmt_2,left_anti_mv_stmt_3,left_anti_mv_stmt_4,left_anti_mv_stmt_5,left_anti_mv_stmt_6,left_anti_mv_stmt_7,left_anti_mv_stmt_8,left_anti_mv_stmt_9,left_anti_mv_stmt_10, -// right_semi_mv_stmt_1,right_semi_mv_stmt_2,right_semi_mv_stmt_3,right_semi_mv_stmt_4,right_semi_mv_stmt_5,right_semi_mv_stmt_6,right_semi_mv_stmt_7,right_semi_mv_stmt_8,right_semi_mv_stmt_9,right_semi_mv_stmt_10, -// right_anti_mv_stmt_1,right_anti_mv_stmt_2,right_anti_mv_stmt_3,right_anti_mv_stmt_4,right_anti_mv_stmt_5,right_anti_mv_stmt_6,right_anti_mv_stmt_7,right_anti_mv_stmt_8,right_anti_mv_stmt_9,right_anti_mv_stmt_10] - + def sql_list = [ + left_mv_stmt_1,left_mv_stmt_2,left_mv_stmt_3,left_mv_stmt_4,left_mv_stmt_5,left_mv_stmt_6,left_mv_stmt_7,left_mv_stmt_8,left_mv_stmt_9,left_mv_stmt_10, + right_mv_stmt_1,right_mv_stmt_2,right_mv_stmt_3,right_mv_stmt_4,right_mv_stmt_5,right_mv_stmt_6,right_mv_stmt_7,right_mv_stmt_8,right_mv_stmt_9,right_mv_stmt_10, + inner_mv_stmt_1,inner_mv_stmt_2,inner_mv_stmt_3,inner_mv_stmt_4,inner_mv_stmt_5,inner_mv_stmt_6,inner_mv_stmt_7,inner_mv_stmt_8,inner_mv_stmt_9,inner_mv_stmt_10, + full_mv_stmt_1,full_mv_stmt_2,full_mv_stmt_3,full_mv_stmt_4,full_mv_stmt_5,full_mv_stmt_6,full_mv_stmt_7,full_mv_stmt_8,full_mv_stmt_9,full_mv_stmt_10, + + // agg pulled up, and the struct info is invalid. need to support aggregate merge then support following query rewriting + // left_semi_mv_stmt_1,left_semi_mv_stmt_2,left_semi_mv_stmt_3,left_semi_mv_stmt_4,left_semi_mv_stmt_5,left_semi_mv_stmt_6,left_semi_mv_stmt_7,left_semi_mv_stmt_8,left_semi_mv_stmt_9,left_semi_mv_stmt_10, + // left_anti_mv_stmt_1,left_anti_mv_stmt_2,left_anti_mv_stmt_3,left_anti_mv_stmt_4,left_anti_mv_stmt_5,left_anti_mv_stmt_6,left_anti_mv_stmt_7,left_anti_mv_stmt_8,left_anti_mv_stmt_9,left_anti_mv_stmt_10, + // right_semi_mv_stmt_1,right_semi_mv_stmt_2,right_semi_mv_stmt_3,right_semi_mv_stmt_4,right_semi_mv_stmt_5,right_semi_mv_stmt_6,right_semi_mv_stmt_7,right_semi_mv_stmt_8,right_semi_mv_stmt_9,right_semi_mv_stmt_10, + // right_anti_mv_stmt_1,right_anti_mv_stmt_2,right_anti_mv_stmt_3,right_anti_mv_stmt_4,right_anti_mv_stmt_5,right_anti_mv_stmt_6,right_anti_mv_stmt_7,right_anti_mv_stmt_8,right_anti_mv_stmt_9,right_anti_mv_stmt_10 + + // query rewrite by materialized view doesn't support cross join currently + // cross_mv_stmt_1,cross_mv_stmt_2,cross_mv_stmt_3,cross_mv_stmt_4,cross_mv_stmt_5,cross_mv_stmt_6,cross_mv_stmt_7,cross_mv_stmt_8,cross_mv_stmt_9,cross_mv_stmt_10, + ] for (int i = 0; i < sql_list.size(); i++) { def origin_res = sql sql_list[i] assert (origin_res.size() > 0) diff --git a/regression-test/suites/nereids_rules_p0/mv/tpch/mv_tpch_test.groovy b/regression-test/suites/nereids_rules_p0/mv/tpch/mv_tpch_test.groovy index 2956654a6250a2..15b9ebf9f23f3a 100644 --- a/regression-test/suites/nereids_rules_p0/mv/tpch/mv_tpch_test.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/tpch/mv_tpch_test.groovy @@ -336,7 +336,7 @@ suite("mv_tpch_test") { """ // contains subquery, doesn't support now order_qt_query4_before "${query4}" - check_mv_rewrite_fail(db, mv4, query4, "mv4") + check_mv_rewrite_success(db, mv4, query4, "mv4") order_qt_query4_after "${query4}" sql """ DROP MATERIALIZED VIEW IF EXISTS mv4""" @@ -1070,7 +1070,7 @@ suite("mv_tpch_test") { """ // contains subquery, doesn't support now order_qt_query16_before "${query16}" - check_mv_rewrite_fail(db, mv16, query16, "mv16") + check_mv_rewrite_success(db, mv16, query16, "mv16") order_qt_query16_after "${query16}" sql """ DROP MATERIALIZED VIEW IF EXISTS mv16"""