This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.0
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.0 by this push:
new a41f4099814 branch-4.0: [fix](nereids) partition topn optimization
requires all window expressions are in the same order #56622 (#56976)
a41f4099814 is described below
commit a41f40998149192d62a911dde2800bc3d88c97fd
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Oct 16 10:02:49 2025 +0800
branch-4.0: [fix](nereids) partition topn optimization requires all window
expressions are in the same order #56622 (#56976)
Cherry-picked from #56622
Co-authored-by: minghong <[email protected]>
---
.../nereids/trees/plans/logical/LogicalWindow.java | 16 ++++++
.../GeneratePartitionTopnFromWindowTest.java | 40 ++++++++++++++
.../nereids_p0/partition_topn/check_orderkey.out | 4 ++
.../partition_topn/check_orderkey.groovy | 61 ++++++++++++++++++++++
4 files changed, 121 insertions(+)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalWindow.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalWindow.java
index ab14f543041..fde80a4d5b6 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalWindow.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalWindow.java
@@ -23,6 +23,7 @@ import org.apache.doris.nereids.properties.DataTrait;
import org.apache.doris.nereids.properties.DataTrait.Builder;
import org.apache.doris.nereids.properties.FdItem;
import org.apache.doris.nereids.properties.LogicalProperties;
+import org.apache.doris.nereids.trees.expressions.Alias;
import org.apache.doris.nereids.trees.expressions.BinaryOperator;
import org.apache.doris.nereids.trees.expressions.EqualTo;
import org.apache.doris.nereids.trees.expressions.ExprId;
@@ -212,6 +213,7 @@ public class LogicalWindow<CHILD_TYPE extends Plan> extends
LogicalUnary<CHILD_T
// 1. The window function should be one of the 'row_number()',
'rank()', 'dense_rank()'.
// 2. The window frame should be 'UNBOUNDED' to 'CURRENT'.
// 3. The 'PARTITION' key and 'ORDER' key can not be empty at the same
time.
+ // 4. order of window expressions should be compatible.
WindowExpression chosenWindowFunc = null;
long chosenPartitionLimit = Long.MAX_VALUE;
long chosenRowNumberPartitionLimit = Long.MAX_VALUE;
@@ -304,10 +306,24 @@ public class LogicalWindow<CHILD_TYPE extends Plan>
extends LogicalUnary<CHILD_T
}
}
}
+
if (chosenWindowFunc == null || (chosenPartitionLimit == Long.MAX_VALUE
&& chosenRowNumberPartitionLimit == Long.MAX_VALUE)) {
return null;
} else {
+ // 4. check all windowExpression's order key is empty or is the
same as chosenWindowFunc's order key
+ for (NamedExpression windowExpr : windowExpressions) {
+ if (windowExpr != null && windowExpr instanceof Alias
+ && windowExpr.child(0) instanceof WindowExpression) {
+ WindowExpression windowFunc = (WindowExpression)
windowExpr.child(0);
+ if (windowFunc.getOrderKeys().isEmpty()
+ ||
windowFunc.getOrderKeys().equals(chosenWindowFunc.getOrderKeys())) {
+ continue;
+ } else {
+ return null;
+ }
+ }
+ }
return Pair.of(chosenWindowFunc, hasRowNumber ?
chosenRowNumberPartitionLimit : chosenPartitionLimit);
}
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/GeneratePartitionTopnFromWindowTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/GeneratePartitionTopnFromWindowTest.java
index e5f7efd38de..00d47bb8b78 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/GeneratePartitionTopnFromWindowTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/GeneratePartitionTopnFromWindowTest.java
@@ -117,4 +117,44 @@ public class GeneratePartitionTopnFromWindowTest
implements MemoPatternMatchSupp
)
);
}
+
+ @Test
+ public void testMultipleWindowsWithDifferentOrders() {
+ ConnectContext context = MemoTestUtils.createConnectContext();
+ context.getSessionVariable().setEnablePartitionTopN(true);
+ NamedExpression gender = scan.getOutput().get(1).toSlot();
+ NamedExpression age = scan.getOutput().get(3).toSlot();
+
+ List<Expression> partitionKeyList = ImmutableList.of(gender);
+ List<OrderExpression> orderKeyList = ImmutableList.of(new
OrderExpression(
+ new OrderKey(age, true, true)));
+ WindowFrame windowFrame = new
WindowFrame(WindowFrame.FrameUnitsType.ROWS,
+ WindowFrame.FrameBoundary.newPrecedingBoundary(),
+ WindowFrame.FrameBoundary.newCurrentRowBoundary());
+ WindowExpression window1 = new WindowExpression(new RowNumber(),
partitionKeyList, orderKeyList, windowFrame);
+ Alias windowAlias1 = new Alias(window1, window1.toSql());
+
+ List<OrderExpression> orderKeyList2 = ImmutableList.of(new
OrderExpression(
+ new OrderKey(age, false, true)));
+ WindowExpression window2 = new WindowExpression(new RowNumber(),
partitionKeyList, orderKeyList2, windowFrame);
+ Alias windowAlias2 = new Alias(window2, window2.toSql());
+
+ List<NamedExpression> expressions = Lists.newArrayList(windowAlias1,
windowAlias2);
+ LogicalWindow<LogicalOlapScan> window = new
LogicalWindow<>(expressions, scan);
+ Expression filterPredicate = new
LessThanEqual(window.getOutput().get(4).toSlot(), Literal.of(100));
+
+ LogicalPlan plan = new LogicalPlanBuilder(window)
+ .filter(filterPredicate)
+ .project(ImmutableList.of(0))
+ .build();
+
+ PlanChecker.from(context, plan)
+ .applyTopDown(new CreatePartitionTopNFromWindow())
+ .matches(
+ logicalProject(
+ logicalFilter(
+ logicalWindow(
+ logicalOlapScan()
+ ))));
+ }
}
diff --git a/regression-test/data/nereids_p0/partition_topn/check_orderkey.out
b/regression-test/data/nereids_p0/partition_topn/check_orderkey.out
new file mode 100644
index 00000000000..4266d3efbea
--- /dev/null
+++ b/regression-test/data/nereids_p0/partition_topn/check_orderkey.out
@@ -0,0 +1,4 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !exe --
+1 c 3 1
+
diff --git
a/regression-test/suites/nereids_p0/partition_topn/check_orderkey.groovy
b/regression-test/suites/nereids_p0/partition_topn/check_orderkey.groovy
new file mode 100644
index 00000000000..62e853495c6
--- /dev/null
+++ b/regression-test/suites/nereids_p0/partition_topn/check_orderkey.groovy
@@ -0,0 +1,61 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite("check_orderkey") {
+ sql """
+ create table students02 (
+ id int, age int, name varchar
+ )properties ('replication_num'='1');
+
+ insert into students02 values (1, 1, 'a'), (1, 2, 'b'), (1, 3, 'c');
+ """
+ //"ORDER BY age desc" and "ORDER BY age" is different, do not use
partition topn
+ explain {
+ sql """
+ select
+ t.id,
+ t.name,
+ t.age,
+ t.desc_age
+ from (
+ SELECT
+ ROW_NUMBER() OVER (partition by id ORDER BY age desc) AS
desc_age,
+ ROW_NUMBER() OVER (partition by id ORDER BY age) AS age,
+ id,
+ name
+ FROM students02) t
+ where t.desc_age=1;
+ """
+ notContains("VPartitionTopN")
+ }
+
+ qt_exe """
+ select
+ t.id,
+ t.name,
+ t.age,
+ t.desc_age
+ from (
+ SELECT
+ ROW_NUMBER() OVER (partition by id ORDER BY age desc) AS desc_age,
+ ROW_NUMBER() OVER (partition by id ORDER BY age) AS age,
+ id,
+ name
+ FROM students02) t
+ where t.desc_age=1;
+ """
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]