From 382703328348448a7adc5b412f4e5e0bda1f9833 Mon Sep 17 00:00:00 2001 From: foxtail463 Date: Sat, 1 Aug 2026 11:58:18 +0800 Subject: [PATCH 1/2] [fix](mtmv) Check agg/window partition keys only for tracked partition outputs (#65393) Problem Summary: MV partition tracking could reject valid partitioned MVs when an aggregate, window, or rewritten PartitionTopN exists on a branch that does not carry the MV partition column. A typical case is a left join where the MV partitions by the left table column, while the right subquery has row_number() or group by on unrelated keys. Solution: Gate aggregate/window/partition-topn partition-key validation by whether the current plan output contains a tracked MV partition slot. Add LogicalPartitionTopN handling for rewritten row_number ... rn = 1 --------- Co-authored-by: yangtao555 --- .../mv/PartitionIncrementMaintainer.java | 90 ++++++++++-- .../mv/MaterializedViewUtilsTest.java | 82 ++++++++++- ...ross_join_list_str_increment_create.groovy | 8 +- ...ss_join_range_date_increment_create.groovy | 137 +++++++++++++++++- ..._join_range_number_increment_create.groovy | 6 +- ...nner_join_list_str_increment_create.groovy | 8 +- ...er_join_range_date_increment_create.groovy | 6 +- ..._join_range_number_increment_create.groovy | 8 +- ...anti_join_list_str_increment_create.groovy | 8 +- ...ti_join_range_date_increment_create.groovy | 6 +- ..._join_range_number_increment_create.groovy | 8 +- ...left_join_list_str_increment_create.groovy | 8 +- ...ft_join_range_date_increment_create.groovy | 8 +- ..._join_range_number_increment_create.groovy | 6 +- ...semi_join_list_str_increment_create.groovy | 8 +- ...mi_join_range_date_increment_create.groovy | 8 +- ..._join_range_number_increment_create.groovy | 8 +- 17 files changed, 335 insertions(+), 78 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/PartitionIncrementMaintainer.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/PartitionIncrementMaintainer.java index 21d6c4f0eb44c9..9f5b2c5f1200bc 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/PartitionIncrementMaintainer.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/PartitionIncrementMaintainer.java @@ -49,6 +49,7 @@ import org.apache.doris.nereids.trees.plans.logical.LogicalFilter; import org.apache.doris.nereids.trees.plans.logical.LogicalJoin; import org.apache.doris.nereids.trees.plans.logical.LogicalLimit; +import org.apache.doris.nereids.trees.plans.logical.LogicalPartitionTopN; import org.apache.doris.nereids.trees.plans.logical.LogicalProject; import org.apache.doris.nereids.trees.plans.logical.LogicalRelation; import org.apache.doris.nereids.trees.plans.logical.LogicalResultSink; @@ -61,6 +62,7 @@ import org.apache.doris.nereids.trees.plans.visitor.DefaultPlanVisitor; import org.apache.doris.nereids.trees.plans.visitor.ExpressionLineageReplacer; import org.apache.doris.nereids.types.DataType; +import org.apache.doris.nereids.util.ImmutableEqualSet; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -430,6 +432,9 @@ && new BaseTableInfo(((LogicalCatalogRelation) relation).getTable()) @Override public Void visitLogicalAggregate(LogicalAggregate aggregate, PartitionIncrementCheckContext context) { + if (!planOutputContainsPartitionColumnToCheck(aggregate, context)) { + return super.visitLogicalAggregate(aggregate, context); + } Set groupByExprSet = new HashSet<>(aggregate.getGroupByExpressions()); if (groupByExprSet.isEmpty()) { context.addFailReason("group by sets is empty, doesn't contain the target partition"); @@ -446,6 +451,9 @@ public Void visitLogicalAggregate(LogicalAggregate aggregate, @Override public Void visitLogicalWindow(LogicalWindow window, PartitionIncrementCheckContext context) { + if (!planOutputContainsPartitionColumnToCheck(window, context)) { + return super.visitLogicalWindow(window, context); + } List windowExpressions = window.getWindowExpressions(); if (windowExpressions.isEmpty()) { context.addFailReason("window expression is empty, doesn't contain the target partition"); @@ -454,7 +462,7 @@ public Void visitLogicalWindow(LogicalWindow window, PartitionIn return visit(window, context); } for (NamedExpression namedExpression : windowExpressions) { - if (!checkWindowPartition(namedExpression, context)) { + if (!checkWindowPartition(namedExpression, window, context)) { context.addFailReason("window partition sets doesn't contain the target partition"); context.collectFailedTableSet(window); context.setFailFast(true); @@ -464,6 +472,29 @@ public Void visitLogicalWindow(LogicalWindow window, PartitionIn return super.visitLogicalWindow(window, context); } + @Override + public Void visitLogicalPartitionTopN(LogicalPartitionTopN partitionTopN, + PartitionIncrementCheckContext context) { + if (!planOutputContainsPartitionColumnToCheck(partitionTopN, context)) { + return super.visitLogicalPartitionTopN(partitionTopN, context); + } + if (partitionTopN.hasGlobalLimit()) { + // A global limit/topN selects the top rows across all partitions rather than within + // each partition, so a change in one source partition can move the global winner and + // affect multiple MV partitions. That breaks partition-local maintenance, so reject it. + context.addFailReason("partition topN has global limit, which is not partition local"); + context.collectFailedTableSet(partitionTopN); + context.setFailFast(true); + return super.visitLogicalPartitionTopN(partitionTopN, context); + } + if (!checkPartitionKeysContainPartitionToCheck(partitionTopN.getPartitionKeys(), partitionTopN, context)) { + context.addFailReason("partition topN partition keys doesn't contain the target partition"); + context.collectFailedTableSet(partitionTopN); + context.setFailFast(true); + } + return super.visitLogicalPartitionTopN(partitionTopN, context); + } + @Override public Void visit(Plan plan, PartitionIncrementCheckContext context) { if (plan instanceof LogicalProject @@ -476,6 +507,7 @@ public Void visit(Plan plan, PartitionIncrementCheckContext context) { || plan instanceof LogicalWindow || (plan instanceof LogicalUnion && ((LogicalUnion) plan).getQualifier() == SetOperation.Qualifier.ALL) + || plan instanceof LogicalPartitionTopN || plan instanceof LogicalCTEAnchor || plan instanceof LogicalCTEConsumer || plan instanceof LogicalCTEProducer @@ -491,30 +523,58 @@ public Void visit(Plan plan, PartitionIncrementCheckContext context) { return super.visit(plan, context); } - private boolean checkWindowPartition(Expression expression, PartitionIncrementCheckContext context) { + private boolean checkWindowPartition(Expression expression, Plan currentPlan, + PartitionIncrementCheckContext context) { List windowExpressions = expression.collectToList(expressionTreeNode -> expressionTreeNode instanceof WindowExpression); for (Object windowExpressionObj : windowExpressions) { WindowExpression windowExpression = (WindowExpression) windowExpressionObj; - List partitionKeys = windowExpression.getPartitionKeys(); - Set originalPartitionbyExprSet = new HashSet<>(); - partitionKeys.forEach(groupExpr -> { - if (groupExpr instanceof SlotReference && groupExpr.isColumnFromTable()) { - originalPartitionbyExprSet.add(((SlotReference) groupExpr).getOriginalColumn().get()); - } - }); - Set contextPartitionColumnSet = getPartitionColumnsToCheck(context); - if (contextPartitionColumnSet.isEmpty()) { - return false; - } - if (contextPartitionColumnSet.stream().noneMatch( - partition -> originalPartitionbyExprSet.contains(partition.getOriginalColumn().get()))) { + if (!checkPartitionKeysContainPartitionToCheck(windowExpression.getPartitionKeys(), + currentPlan, context)) { return false; } } return true; } + private boolean checkPartitionKeysContainPartitionToCheck(List partitionKeys, + Plan currentPlan, PartitionIncrementCheckContext context) { + // Match by slot exprId, not catalog Column: Column.equals ignores the owning table, so an + // unrelated same-schema column (e.g. l.p vs r.p) would be wrongly accepted as the tracked key. + Set partitionKeySlotSet = new HashSet<>(); + partitionKeys.forEach(partitionKey -> { + if (partitionKey instanceof SlotReference && partitionKey.isColumnFromTable()) { + partitionKeySlotSet.add((SlotReference) partitionKey); + } + }); + Set contextPartitionColumnSet = getPartitionColumnsToCheck(context); + if (contextPartitionColumnSet.isEmpty()) { + return false; + } + if (contextPartitionColumnSet.stream().anyMatch(partitionKeySlotSet::contains)) { + return true; + } + // Also accept a key that is a different slot but proven equal to the tracked column, e.g. + // window over (partition by r.p) on an inner join l.p = r.p, or a forwarding alias p AS p_alias. + // currentPlan's DataTrait carries these equalities (bottom-up) even though this top-down check + // runs before the join equalities reach the context. + ImmutableEqualSet equalSet = currentPlan.getLogicalProperties().getTrait().getEqualSet(); + return contextPartitionColumnSet.stream().anyMatch(contextSlot -> + partitionKeySlotSet.stream().anyMatch(keySlot -> equalSet.isEqual(contextSlot, keySlot))); + } + + private boolean planOutputContainsPartitionColumnToCheck(Plan plan, PartitionIncrementCheckContext context) { + Set outputSet = plan.getOutputSet(); + for (NamedExpression namedExpression : context.getPartitionAndRefExpressionMap().keySet()) { + // Plan outputs are slots, so only tracked partition expressions already resolved + // to slots can match here. + if (namedExpression instanceof Slot && outputSet.contains(namedExpression)) { + return true; + } + } + return false; + } + private Set getPartitionColumnsToCheck(PartitionIncrementCheckContext context) { Set partitionExpressionSet = context.getPartitionAndRefExpressionMap().keySet(); Set partitionSlotSet = new HashSet<>(); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/mv/MaterializedViewUtilsTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/mv/MaterializedViewUtilsTest.java index 3bc6c736c274e4..afba719aa6d466 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/mv/MaterializedViewUtilsTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/mv/MaterializedViewUtilsTest.java @@ -644,6 +644,80 @@ public void getRelatedTableInfoTestWithWindowButNotPartitionTest() { }); } + @Test + public void getRelatedTableInfoTestWithUnrelatedRightWindowTest() { + PlanChecker.from(connectContext) + .checkExplain("SELECT l.L_SHIPDATE, l.L_ORDERKEY, o.O_ORDERDATE " + + "FROM lineitem as l " + + "LEFT JOIN (" + + "SELECT O_ORDERKEY, O_ORDERDATE, " + + "ROW_NUMBER() OVER (PARTITION BY O_ORDERKEY ORDER BY O_ORDERDATE DESC) AS rn " + + "FROM orders" + + ") as o " + + "ON l.L_ORDERKEY = o.O_ORDERKEY AND o.rn = 1", + nereidsPlanner -> { + Plan rewrittenPlan = nereidsPlanner.getRewrittenPlan(); + RelatedTableInfo relatedTableInfo = + MaterializedViewUtils.getRelatedTableInfo("L_SHIPDATE", null, + rewrittenPlan, nereidsPlanner.getCascadesContext()); + Assertions.assertTrue(relatedTableInfo.isPctPossible(), relatedTableInfo.getFailReason()); + checkRelatedTableInfo(relatedTableInfo, + "lineitem", + "L_SHIPDATE", + true); + }); + } + + @Test + public void getRelatedTableInfoTestWithUnrelatedSameSchemaWindowTest() { + // t1 and t2 come from the same table, so t1.L_SHIPDATE and t2.L_SHIPDATE share an identical + // catalog Column definition but belong to different table instances. The MV partitions by + // t1.L_SHIPDATE while the row_number() partitions by the unrelated t2.L_SHIPDATE, and the join + // condition is on L_ORDERKEY so the two shipdate slots are NOT in the same equal set. Partition + // tracking must reject this: matching by bare Column would wrongly treat t2.L_SHIPDATE as the + // tracked partition key and allow stale rows after a partition-only refresh. + PlanChecker.from(connectContext) + .checkExplain("SELECT t1.L_SHIPDATE, t1.L_ORDERKEY " + + "FROM lineitem t1 " + + "LEFT JOIN (" + + "SELECT L_ORDERKEY, L_SHIPDATE, " + + "ROW_NUMBER() OVER (PARTITION BY L_SHIPDATE ORDER BY L_PARTKEY DESC) AS rn " + + "FROM lineitem" + + ") as t2 " + + "ON t1.L_ORDERKEY = t2.L_ORDERKEY AND t2.rn = 1", + nereidsPlanner -> { + Plan rewrittenPlan = nereidsPlanner.getRewrittenPlan(); + RelatedTableInfo relatedTableInfo = + MaterializedViewUtils.getRelatedTableInfo("L_SHIPDATE", null, + rewrittenPlan, nereidsPlanner.getCascadesContext()); + Assertions.assertFalse(relatedTableInfo.isPctPossible()); + }); + } + + @Test + public void getRelatedTableInfoTestWithUnrelatedRightAggregateTest() { + PlanChecker.from(connectContext) + .checkExplain("SELECT l.L_SHIPDATE, l.L_ORDERKEY, o.max_orderdate " + + "FROM lineitem as l " + + "LEFT JOIN (" + + "SELECT O_ORDERKEY, max(O_ORDERDATE) AS max_orderdate " + + "FROM orders " + + "GROUP BY O_ORDERKEY" + + ") as o " + + "ON l.L_ORDERKEY = o.O_ORDERKEY", + nereidsPlanner -> { + Plan rewrittenPlan = nereidsPlanner.getRewrittenPlan(); + RelatedTableInfo relatedTableInfo = + MaterializedViewUtils.getRelatedTableInfo("L_SHIPDATE", null, + rewrittenPlan, nereidsPlanner.getCascadesContext()); + Assertions.assertTrue(relatedTableInfo.isPctPossible(), relatedTableInfo.getFailReason()); + checkRelatedTableInfo(relatedTableInfo, + "lineitem", + "L_SHIPDATE", + true); + }); + } + @Test public void getRelatedTableInfoTestWithLimitTest() { PlanChecker.from(connectContext) @@ -882,9 +956,11 @@ public void getRelatedTableInfoWhenMultiBaseTablePartition() { RelatedTableInfo relatedTableInfo = MaterializedViewUtils.getRelatedTableInfo("upgrade_day", null, rewrittenPlan, nereidsPlanner.getCascadesContext()); - Assertions.assertTrue(relatedTableInfo.getFailReason().contains( - "partition column is not in group by or window partition by")); - Assertions.assertFalse(relatedTableInfo.isPctPossible()); + Assertions.assertTrue(relatedTableInfo.isPctPossible(), relatedTableInfo.getFailReason()); + checkRelatedTableInfo(relatedTableInfo, + "test1", + "upgrade_day", + true); }); } diff --git a/regression-test/suites/nereids_rules_p0/mv/increment_create/cross_join_list_str_increment_create.groovy b/regression-test/suites/nereids_rules_p0/mv/increment_create/cross_join_list_str_increment_create.groovy index 0e24889c007f0a..afaa1a39818bbb 100644 --- a/regression-test/suites/nereids_rules_p0/mv/increment_create/cross_join_list_str_increment_create.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/increment_create/cross_join_list_str_increment_create.groovy @@ -345,12 +345,12 @@ suite("cross_join_list_str_increment_create") { def sql_all_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] - def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8] + def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8, mv_sql_14] def sql_complete_list = [] // change left table data // create mv base on left table with partition col - def sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] + def sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, primary_tb_change, is_complete_change) @@ -375,9 +375,9 @@ suite("cross_join_list_str_increment_create") { // change right table data // create mv base on left table with partition col - sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] sql_increment_list = [] - sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8] + sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8, mv_sql_14] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, slave_tb_change, is_complete_change) // create mv base on left table with no partition col diff --git a/regression-test/suites/nereids_rules_p0/mv/increment_create/cross_join_range_date_increment_create.groovy b/regression-test/suites/nereids_rules_p0/mv/increment_create/cross_join_range_date_increment_create.groovy index 90c8a9447b2118..2336a559bb8914 100644 --- a/regression-test/suites/nereids_rules_p0/mv/increment_create/cross_join_range_date_increment_create.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/increment_create/cross_join_range_date_increment_create.groovy @@ -175,17 +175,23 @@ suite("cross_join_range_date_increment_create") { assert (refresh_info[0][5] == "100.00% (6/6)") } + // use a fresh l_orderkey each call so the change is a new group, not a group-by-folded duplicate + def primary_change_counter = 100 def primary_tb_change = { sql """ - insert into lineitem_cross_2 values - (2, 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'); + insert into lineitem_cross_2 values + (${primary_change_counter}, 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'); """ + primary_change_counter++ } + // use a fresh o_orderkey each call so the change is a new group, not a group-by-folded duplicate + def slave_change_counter = 100 def slave_tb_change = { sql""" - insert into orders_cross_2 values - (2, 5, 'ok', 99.5, 'a', 'b', 1, 'yy', '2023-10-17'); + insert into orders_cross_2 values + (${slave_change_counter}, 5, 'ok', 99.5, 'a', 'b', 1, 'yy', '2023-10-17'); """ + slave_change_counter++ } // no window func + on partition col @@ -336,12 +342,12 @@ suite("cross_join_range_date_increment_create") { def sql_all_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] - def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7] + def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_13] def sql_complete_list = [] // change left table data // create mv base on left table with partition col - def sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] + def sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, primary_tb_change, is_complete_change) @@ -366,9 +372,9 @@ suite("cross_join_range_date_increment_create") { // change right table data // create mv base on left table with partition col - sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] + sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] sql_increment_list = [] - sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7] + sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_13] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, slave_tb_change, is_complete_change) @@ -393,4 +399,119 @@ suite("cross_join_range_date_increment_create") { list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_not_part_col_right, slave_tb_change, is_complete_change) + // Focused cases the cross-join matrix above cannot express: identity/equality-class partition-key + // matching and the global-limit guard. Dedicated tables keep them isolated from the matrix state. + sql "drop table if exists identity_left" + sql "drop table if exists identity_right" + sql """CREATE TABLE identity_left ( + id BIGINT NULL, + score BIGINT NULL, + p DATE NOT NULL + ) ENGINE=OLAP DUPLICATE KEY(id) + auto partition by range (date_trunc(`p`, 'day')) () + DISTRIBUTED BY HASH(id) BUCKETS 1 + PROPERTIES ("replication_allocation" = "tag.location.default: 1");""" + // identity_right is defined identically to identity_left so only slot/exprId identity, not + // catalog Column.equals, can distinguish identity_left.p from identity_right.p + sql """CREATE TABLE identity_right ( + id BIGINT NULL, + score BIGINT NULL, + p DATE NOT NULL + ) ENGINE=OLAP DUPLICATE KEY(id) + auto partition by range (date_trunc(`p`, 'day')) () + DISTRIBUTED BY HASH(id) BUCKETS 1 + PROPERTIES ("replication_allocation" = "tag.location.default: 1");""" + sql """insert into identity_left values (1,10,'2023-10-17'),(2,20,'2023-10-18');""" + sql """insert into identity_right values (1,5,'2023-10-17'),(2,50,'2023-10-18');""" + sql """analyze table identity_left with sync;""" + sql """analyze table identity_right with sync;""" + + def identity_mv = "mv_identity_focus" + def drop_identity_mv = { + sql """DROP MATERIALIZED VIEW IF EXISTS ${identity_mv};""" + sql """DROP TABLE IF EXISTS ${identity_mv};""" + } + + // negative: unrelated same-schema column (window partition by identity_right.p, no equality) must be rejected + drop_identity_mv() + test { + sql """ + CREATE MATERIALIZED VIEW ${identity_mv} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + partition by(p) + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + select identity_left.p, identity_left.id, + count(identity_right.score) over (partition by identity_right.p order by identity_right.id) as wc + from identity_left cross join identity_right + """ + exception "Unable to find a suitable base table for partitioning" + } + + // negative: global-limit PartitionTopN (order by rn limit N over a window) is not partition-local + drop_identity_mv() + test { + sql """ + CREATE MATERIALIZED VIEW ${identity_mv} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + partition by(p) + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + select p, id, rn from ( + select identity_left.p as p, identity_left.id as id, + row_number() over (partition by identity_left.p order by identity_left.score desc) as rn + from identity_left + ) v order by rn limit 5 + """ + exception "Unable to find a suitable base table for partitioning" + } + + // positive: inner-join equality identity_left.p = identity_right.p accepts window partition by identity_right.p; expect PARTIAL refresh + drop_identity_mv() + sql """ + CREATE MATERIALIZED VIEW ${identity_mv} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + partition by(p) + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + select identity_left.p, identity_left.id, + count(identity_right.score) over (partition by identity_right.p order by identity_right.id) as wc + from identity_left inner join identity_right on identity_left.p = identity_right.p + """ + def identity_job = getJobName(db, identity_mv) + waitingMTMVTaskFinishedWithoutAnalyze(identity_job) + sql """insert into identity_left values (100, 999, '2023-10-17');""" + sql """refresh MATERIALIZED VIEW ${identity_mv} AUTO""" + waitingMTMVTaskFinishedWithoutAnalyze(identity_job) + def identity_refresh = sql """select Status, RefreshMode, NeedRefreshPartitions, Progress + from tasks("type"="mv") where JobName="${identity_job}" order by CreateTime desc limit 1;""" + assert (identity_refresh[0][0] == "SUCCESS") + assert (identity_refresh[0][1] == "PARTIAL") + assert (identity_refresh[0][2] == "[\"p_20231017_20231018\"]") + assert (identity_refresh[0][3] == "100.00% (1/1)") + + // positive: forwarding alias p_alias equals the window key identity_left.p despite a different ExprId + drop_identity_mv() + sql """ + CREATE MATERIALIZED VIEW ${identity_mv} + BUILD IMMEDIATE REFRESH AUTO ON MANUAL + partition by(p_alias) + DISTRIBUTED BY RANDOM BUCKETS 2 + PROPERTIES ('replication_num' = '1') + AS + select p_alias, id, wc from ( + select identity_left.p as p_alias, identity_left.id as id, + count(identity_left.score) over (partition by identity_left.p order by identity_left.id) as wc + from identity_left + ) v + """ + def alias_job = getJobName(db, identity_mv) + waitingMTMVTaskFinishedWithoutAnalyze(alias_job) + def alias_built = sql """select Status from tasks("type"="mv") where JobName="${alias_job}" order by CreateTime desc limit 1;""" + assert (alias_built[0][0] == "SUCCESS") + drop_identity_mv() + } diff --git a/regression-test/suites/nereids_rules_p0/mv/increment_create/cross_join_range_number_increment_create.groovy b/regression-test/suites/nereids_rules_p0/mv/increment_create/cross_join_range_number_increment_create.groovy index 0bf234131836a2..3b7a44ce9d1dfd 100644 --- a/regression-test/suites/nereids_rules_p0/mv/increment_create/cross_join_range_number_increment_create.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/increment_create/cross_join_range_number_increment_create.groovy @@ -351,7 +351,7 @@ suite("cross_join_range_number_increment_create") { // change left table data // create mv base on left table with partition col - sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, primary_tb_change, is_complete_change) @@ -376,9 +376,9 @@ suite("cross_join_range_number_increment_create") { // change right table data // create mv base on left table with partition col - sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] sql_increment_list = [] - sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8] + sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8, mv_sql_14] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, slave_tb_change, is_complete_change) diff --git a/regression-test/suites/nereids_rules_p0/mv/increment_create/inner_join_list_str_increment_create.groovy b/regression-test/suites/nereids_rules_p0/mv/increment_create/inner_join_list_str_increment_create.groovy index 789959e4ccccfd..33b9d5654f7c33 100644 --- a/regression-test/suites/nereids_rules_p0/mv/increment_create/inner_join_list_str_increment_create.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/increment_create/inner_join_list_str_increment_create.groovy @@ -370,7 +370,7 @@ suite("inner_join_list_str_increment_create") { // change left table data // create mv base on left table with partition col - sql_error_list = [mv_sql_7, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12, mv_sql_13, mv_sql_15, mv_sql_16, mv_sql_18] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, primary_tb_change, is_complete_change) @@ -382,7 +382,7 @@ suite("inner_join_list_str_increment_create") { partition_by_not_part_col, primary_tb_change, is_complete_change) // create mv base on right table with partition col - sql_error_list = [mv_sql_7, mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_12, mv_sql_13, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_18] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12, mv_sql_13, mv_sql_15, mv_sql_16, mv_sql_18] sql_increment_list = [] sql_complete_list = [mv_sql_1, mv_sql_3] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, @@ -396,7 +396,7 @@ suite("inner_join_list_str_increment_create") { // change right table data // create mv base on left table with partition col - sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12, mv_sql_13, mv_sql_15, mv_sql_16, mv_sql_18] sql_increment_list = [mv_sql_4, mv_sql_6, mv_sql_8, mv_sql_14] sql_complete_list = [mv_sql_1, mv_sql_3] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, @@ -411,7 +411,7 @@ suite("inner_join_list_str_increment_create") { partition_by_not_part_col, slave_tb_change, is_complete_change) // create mv base on right table with partition col - sql_error_list = [mv_sql_7, mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_12, mv_sql_13, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_18] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12, mv_sql_13, mv_sql_15, mv_sql_16, mv_sql_18] sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_11, mv_sql_17] sql_complete_list = [] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, diff --git a/regression-test/suites/nereids_rules_p0/mv/increment_create/inner_join_range_date_increment_create.groovy b/regression-test/suites/nereids_rules_p0/mv/increment_create/inner_join_range_date_increment_create.groovy index 36288e1d7f7fb6..39e1b1beaba36e 100644 --- a/regression-test/suites/nereids_rules_p0/mv/increment_create/inner_join_range_date_increment_create.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/increment_create/inner_join_range_date_increment_create.groovy @@ -361,7 +361,7 @@ suite("inner_join_range_date_increment_create") { // change left table data // create mv base on left table with partition col - sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] + sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, primary_tb_change, is_complete_change) @@ -386,9 +386,9 @@ suite("inner_join_range_date_increment_create") { // change right table data // create mv base on left table with partition col - sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] + sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] sql_increment_list = [mv_sql_1, mv_sql_3] - sql_complete_list = [mv_sql_4, mv_sql_6, mv_sql_7] + sql_complete_list = [mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_13] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, slave_tb_change, is_complete_change) diff --git a/regression-test/suites/nereids_rules_p0/mv/increment_create/inner_join_range_number_increment_create.groovy b/regression-test/suites/nereids_rules_p0/mv/increment_create/inner_join_range_number_increment_create.groovy index 89be330e2b0ad1..811badb85ba024 100644 --- a/regression-test/suites/nereids_rules_p0/mv/increment_create/inner_join_range_number_increment_create.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/increment_create/inner_join_range_number_increment_create.groovy @@ -371,7 +371,7 @@ suite("inner_join_range_number_increment_create") { // change left table data // create mv base on left table with partition col - sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12, mv_sql_13, mv_sql_15, mv_sql_16, mv_sql_18] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, primary_tb_change, is_complete_change) @@ -382,7 +382,7 @@ suite("inner_join_range_number_increment_create") { partition_by_not_part_col, primary_tb_change, is_complete_change) // create mv base on right table with partition col - sql_error_list = [mv_sql_7, mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_12, mv_sql_13, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_18] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12, mv_sql_13, mv_sql_15, mv_sql_16, mv_sql_18] sql_increment_list = [] sql_complete_list = [mv_sql_1, mv_sql_3] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, @@ -396,7 +396,7 @@ suite("inner_join_range_number_increment_create") { // change right table data // create mv base on left table with partition col - sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12, mv_sql_13, mv_sql_15, mv_sql_16, mv_sql_17, mv_sql_18] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12, mv_sql_13, mv_sql_15, mv_sql_16, mv_sql_18] sql_increment_list = [mv_sql_4, mv_sql_6, mv_sql_8, mv_sql_14] sql_complete_list = [mv_sql_1, mv_sql_3] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, @@ -411,7 +411,7 @@ suite("inner_join_range_number_increment_create") { partition_by_not_part_col, slave_tb_change, is_complete_change) // create mv base on right table with partition col - sql_error_list = [mv_sql_7, mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_12, mv_sql_13, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_18] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12, mv_sql_13, mv_sql_15, mv_sql_16, mv_sql_18] sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_11, mv_sql_17] sql_complete_list = [] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, diff --git a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_anti_join_list_str_increment_create.groovy b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_anti_join_list_str_increment_create.groovy index aeefdb8ad1ddcd..62117c298b8fa2 100644 --- a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_anti_join_list_str_increment_create.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_anti_join_list_str_increment_create.groovy @@ -302,12 +302,12 @@ suite("left_anti_join_list_str_increment_create") { } def sql_all_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] - def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8] + def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8, mv_sql_11] def sql_complete_list = [] // change left table data // create mv base on left table with partition col - def sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + def sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, primary_tb_change, is_complete_change) @@ -328,9 +328,9 @@ suite("left_anti_join_list_str_increment_create") { // change right table data // create mv base on left table with partition col - sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12] sql_increment_list = [] - sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8] + sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8, mv_sql_11] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, slave_tb_change, is_complete_change) diff --git a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_anti_join_range_date_increment_create.groovy b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_anti_join_range_date_increment_create.groovy index f443406831ce71..c6e1b907193477 100644 --- a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_anti_join_range_date_increment_create.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_anti_join_range_date_increment_create.groovy @@ -298,7 +298,7 @@ suite("left_anti_join_range_date_increment_create") { // change left table data // create mv base on left table with partition col - def sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + def sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_11, mv_sql_12] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, primary_tb_change, is_complete_change) @@ -319,9 +319,9 @@ suite("left_anti_join_range_date_increment_create") { // change right table data // create mv base on left table with partition col - sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_11, mv_sql_12] sql_increment_list = [] - sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7] + sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_10] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, slave_tb_change, is_complete_change) diff --git a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_anti_join_range_number_increment_create.groovy b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_anti_join_range_number_increment_create.groovy index 9ab74e04f9e881..8fcb3713e11863 100644 --- a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_anti_join_range_number_increment_create.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_anti_join_range_number_increment_create.groovy @@ -301,13 +301,13 @@ suite("left_anti_join_range_number_increment_create") { } def sql_all_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] - def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8] + def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8, mv_sql_11] def sql_complete_list = [] def sql_error_list = [] // change left table data // create mv base on left table with partition col - sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, primary_tb_change, is_complete_change) @@ -328,9 +328,9 @@ suite("left_anti_join_range_number_increment_create") { // change right table data // create mv base on left table with partition col - sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12] sql_increment_list = [] - sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8] + sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8, mv_sql_11] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, slave_tb_change, is_complete_change) diff --git a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_join_list_str_increment_create.groovy b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_join_list_str_increment_create.groovy index 4fc907f7ed7a86..19b17201d29fc8 100644 --- a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_join_list_str_increment_create.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_join_list_str_increment_create.groovy @@ -302,12 +302,12 @@ suite("left_join_list_str_increment_create") { } def sql_all_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] - def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8] + def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8, mv_sql_11] def sql_complete_list = [] // change left table data // create mv base on left table with partition col - def sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + def sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, primary_tb_change, is_complete_change) @@ -328,9 +328,9 @@ suite("left_join_list_str_increment_create") { // change right table data // create mv base on left table with partition col - sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12] sql_increment_list = [] - sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8] + sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8, mv_sql_11] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, slave_tb_change, is_complete_change) diff --git a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_join_range_date_increment_create.groovy b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_join_range_date_increment_create.groovy index 51ea3c0f621555..621bc6fa032dcf 100644 --- a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_join_range_date_increment_create.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_join_range_date_increment_create.groovy @@ -293,12 +293,12 @@ suite("left_join_range_date_increment_create") { } def sql_all_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] - def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7] + def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_10] def sql_complete_list = [] // change left table data // create mv base on left table with partition col - def sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + def sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_11, mv_sql_12] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, primary_tb_change, is_complete_change) @@ -319,9 +319,9 @@ suite("left_join_range_date_increment_create") { // change right table data // create mv base on left table with partition col - sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_11, mv_sql_12] sql_increment_list = [] - sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7] + sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_10] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, slave_tb_change, is_complete_change) diff --git a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_join_range_number_increment_create.groovy b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_join_range_number_increment_create.groovy index 91360b733e10db..ab149544ad9dfe 100644 --- a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_join_range_number_increment_create.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_join_range_number_increment_create.groovy @@ -306,7 +306,7 @@ suite("left_join_range_number_increment_create") { // change left table data // create mv base on left table with partition col - def sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + def sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, primary_tb_change, is_complete_change) @@ -327,9 +327,9 @@ suite("left_join_range_number_increment_create") { // change right table data // create mv base on left table with partition col - sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12] sql_increment_list = [] - sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8] + sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8, mv_sql_11] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, slave_tb_change, is_complete_change) diff --git a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_semi_join_list_str_increment_create.groovy b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_semi_join_list_str_increment_create.groovy index 69067e65719a6a..58c2b1c843c189 100644 --- a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_semi_join_list_str_increment_create.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_semi_join_list_str_increment_create.groovy @@ -302,12 +302,12 @@ suite("left_semi_join_list_str_increment_create") { } def sql_all_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] - def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8] + def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8, mv_sql_11] def sql_complete_list = [] // change left table data // create mv base on left table with partition col - def sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + def sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, primary_tb_change, is_complete_change) @@ -328,9 +328,9 @@ suite("left_semi_join_list_str_increment_create") { // change right table data // create mv base on left table with partition col - sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12] sql_increment_list = [] - sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8] + sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8, mv_sql_11] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, slave_tb_change, is_complete_change) diff --git a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_semi_join_range_date_increment_create.groovy b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_semi_join_range_date_increment_create.groovy index 789c4aadca7966..6601ef5ea3a40e 100644 --- a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_semi_join_range_date_increment_create.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_semi_join_range_date_increment_create.groovy @@ -293,12 +293,12 @@ suite("left_semi_join_range_date_increment_create") { } def sql_all_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] - def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7] + def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_10] def sql_complete_list = [] // change left table data // create mv base on left table with partition col - def sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + def sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_11, mv_sql_12] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, primary_tb_change, is_complete_change) @@ -319,9 +319,9 @@ suite("left_semi_join_range_date_increment_create") { // change right table data // create mv base on left table with partition col - sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + sql_error_list = [mv_sql_8, mv_sql_9, mv_sql_11, mv_sql_12] sql_increment_list = [] - sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7] + sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_10] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, slave_tb_change, is_complete_change) diff --git a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_semi_join_range_number_increment_create.groovy b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_semi_join_range_number_increment_create.groovy index 7f872ae2a9e470..6ceb6b5b05d4dc 100644 --- a/regression-test/suites/nereids_rules_p0/mv/increment_create/left_semi_join_range_number_increment_create.groovy +++ b/regression-test/suites/nereids_rules_p0/mv/increment_create/left_semi_join_range_number_increment_create.groovy @@ -301,13 +301,13 @@ suite("left_semi_join_range_number_increment_create") { } def sql_all_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] - def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8] + def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8, mv_sql_11] def sql_complete_list = [] def sql_error_list = [] // change left table data // create mv base on left table with partition col - sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, primary_tb_change, is_complete_change) @@ -328,9 +328,9 @@ suite("left_semi_join_range_number_increment_create") { // change right table data // create mv base on left table with partition col - sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12] + sql_error_list = [mv_sql_7, mv_sql_9, mv_sql_10, mv_sql_12] sql_increment_list = [] - sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8] + sql_complete_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_8, mv_sql_11] list_judgement(sql_all_list, sql_increment_list, sql_complete_list, sql_error_list, partition_by_part_col, slave_tb_change, is_complete_change) From bf9f70e46823352f6e8c762b2c54366ca8fb8361 Mon Sep 17 00:00:00 2001 From: yujun Date: Tue, 22 Sep 2026 17:26:55 +0800 Subject: [PATCH 2/2] [test](regression) Add waitingMTMVTaskFinishedWithoutAnalyze helper to Suite.groovy The branch-4.2 pick of the mtmv partition-key check adds focus cases to cross_join_range_date_increment_create that call waitingMTMVTaskFinishedWithoutAnalyze, but the helper was introduced on master by #61290 which is not picked to branch-4.2, so the suite fails with MissingMethodException. Key changes: - Port waitingMTMVTaskFinishedWithoutAnalyze from master Suite.groovy: wait for the MTMV task to reach SUCCESS without the analyze step. Unit Test: - Focus cases of cross_join_range_date_increment_create extracted into a standalone suite and run locally: passed. --- .../apache/doris/regression/suite/Suite.groovy | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy b/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy index d894e961e85aef..cf94aa3c32bce2 100644 --- a/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy +++ b/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy @@ -2232,6 +2232,21 @@ class Suite implements GroovyInterceptable { logger.info("index stats: " + stats.toString()) } + void waitingMTMVTaskFinishedWithoutAnalyze(String jobName) { + // Wait for the newly submitted MTMV task to become visible in tasks(). + Thread.sleep(2000); + String showTasks = """ + select TaskId, Status from tasks('type'='mv') + where JobName = '${jobName}' order by CreateTime DESC limit 1 + """ + List taskRow = waitMTMVTaskTerminal(showTasks, "waitingMTMVTaskFinishedWithoutAnalyze") + String status = taskRow == null ? "NULL" : taskRow.get(1).toString() + if (status != "SUCCESS") { + logger.info("status is not success") + } + Assert.assertEquals("SUCCESS", status) + } + void waitingMTMVTaskFinishedNotNeedSuccess(String jobName) { // Wait for the newly submitted MTMV task to become visible in tasks(). Thread.sleep(2000);