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

rubenql pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new 34ae30c7c6 [CALCITE-7222] SortRemoveDuplicateKeysRule miss fetch and 
offset information
34ae30c7c6 is described below

commit 34ae30c7c6db7cf2172e1dd81a6023e6866ae215
Author: Zhen Chen <[email protected]>
AuthorDate: Sat Oct 11 17:36:58 2025 +0800

    [CALCITE-7222] SortRemoveDuplicateKeysRule miss fetch and offset information
---
 .../calcite/rel/metadata/RelMetadataQuery.java     |  6 ++--
 .../rel/rules/SortRemoveDuplicateKeysRule.java     |  4 +--
 .../java/org/apache/calcite/tools/RelBuilder.java  |  8 ++++-
 .../org/apache/calcite/test/RelOptRulesTest.java   | 22 +++++++++++++
 .../org/apache/calcite/test/RelOptRulesTest.xml    | 38 ++++++++++++++++++++++
 5 files changed, 72 insertions(+), 6 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java 
b/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
index 4a5d8ddff0..8044846254 100644
--- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
+++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java
@@ -994,12 +994,12 @@ public Boolean isVisibleInExplain(RelNode rel,
   }
 
   /**
-   * Determines whether key is functionally dependent on column.
+   * Determines whether one column functionally determines another.
    */
-  public @Nullable Boolean determines(RelNode rel, int key, int column) {
+  public @Nullable Boolean determines(RelNode rel, int determinant, int 
dependent) {
     for (;;) {
       try {
-        return functionalDependencyHandler.determines(rel, this, key, column);
+        return functionalDependencyHandler.determines(rel, this, determinant, 
dependent);
       } catch (MetadataHandlerProvider.NoHandler e) {
         functionalDependencyHandler = 
revise(BuiltInMetadata.FunctionalDependency.Handler.class);
       }
diff --git 
a/core/src/main/java/org/apache/calcite/rel/rules/SortRemoveDuplicateKeysRule.java
 
b/core/src/main/java/org/apache/calcite/rel/rules/SortRemoveDuplicateKeysRule.java
index 525bece4c8..6574aa9f59 100644
--- 
a/core/src/main/java/org/apache/calcite/rel/rules/SortRemoveDuplicateKeysRule.java
+++ 
b/core/src/main/java/org/apache/calcite/rel/rules/SortRemoveDuplicateKeysRule.java
@@ -78,7 +78,7 @@ protected SortRemoveDuplicateKeysRule(Config config) {
       boolean dup = false;
       for (RelFieldCollation existed : newCollations) {
         if (Boolean.TRUE.equals(
-            mq.determines(sort, field.getFieldIndex(), 
existed.getFieldIndex()))) {
+            mq.determines(sort, existed.getFieldIndex(), 
field.getFieldIndex()))) {
           dup = true;
           break;
         }
@@ -93,7 +93,7 @@ protected SortRemoveDuplicateKeysRule(Config config) {
     }
 
     relBuilder.push(sort.getInput())
-        .sort(RelCollations.of(newCollations));
+        .sortLimit(sort.offset, sort.fetch, RelCollations.of(newCollations));
     call.transformTo(relBuilder.build());
   }
 
diff --git a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java 
b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
index d84c031458..90df447ebc 100644
--- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
+++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
@@ -3727,8 +3727,14 @@ public RelBuilder sortLimit(long offset, long fetch, 
RexNode... nodes) {
   /** Creates a {@link Sort} by specifying collations.
    */
   public RelBuilder sort(RelCollation collation) {
+    return sortLimit(null, null, collation);
+  }
+
+  /** Creates a {@link Sort} by specifying collations, with offset node and 
fetch node. */
+  public RelBuilder sortLimit(@Nullable RexNode offsetNode, @Nullable RexNode 
fetchNode,
+      RelCollation collation) {
     final RelNode sort =
-        struct.sortFactory.createSort(peek(), collation, null, null);
+        struct.sortFactory.createSort(peek(), collation, offsetNode, 
fetchNode);
     replaceTop(sort);
     return this;
   }
diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java 
b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
index 32225bf803..3a4fb184c5 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -11334,6 +11334,28 @@ private void 
checkLoptOptimizeJoinRule(LoptOptimizeJoinRule rule) {
         .check();
   }
 
+  /** Test case of
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-7222";>[CALCITE-7222]
+   * SortRemoveDuplicateKeysRule miss fetch and offset infomation</a>. */
+  @Test void testSortRemoveDuplicateKeysWithPK() {
+    final String query = "select * from (select empno as a, deptno as b from 
emp) t"
+        + " order by a, b limit 1 offset 2";
+    sql(query)
+        .withRule(CoreRules.SORT_REMOVE_DUPLICATE_KEYS)
+        .check();
+  }
+
+  /** Test case of
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-7222";>[CALCITE-7222]
+   * SortRemoveDuplicateKeysRule miss fetch and offset infomation</a>. */
+  @Test void testSortRemoveDuplicateKeysWithLimit() {
+    final String query = "select * from (select empno as a, empno as b from 
emp) t"
+        + " order by a, b limit 1 offset 2";
+    sql(query)
+        .withRule(CoreRules.SORT_REMOVE_DUPLICATE_KEYS)
+        .check();
+  }
+
   /** Test case of
    * <a 
href="https://issues.apache.org/jira/browse/CALCITE-7116";>[CALCITE-7116]
    * Optimize queries with GROUPING SETS by converting them
diff --git 
a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml 
b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
index 3c85ef747a..ac3a626d81 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -18259,6 +18259,44 @@ LogicalSort(sort0=[$0], dir0=[ASC])
       LogicalProject(D1=[$7], D2=[$7])
         LogicalTableScan(table=[[CATALOG, SALES, EMP]])
       LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testSortRemoveDuplicateKeysWithLimit">
+    <Resource name="sql">
+      <![CDATA[select * from (select empno as a, empno as b from emp) t order 
by a, b limit 1 offset 2]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalSort(sort0=[$0], sort1=[$1], dir0=[ASC], dir1=[ASC], offset=[2], 
fetch=[1])
+  LogicalProject(A=[$0], B=[$0])
+    LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+LogicalSort(sort0=[$0], dir0=[ASC], offset=[2], fetch=[1])
+  LogicalProject(A=[$0], B=[$0])
+    LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testSortRemoveDuplicateKeysWithPK">
+    <Resource name="sql">
+      <![CDATA[select * from (select empno as a, deptno as b from emp) t order 
by a, b limit 1 offset 2]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalSort(sort0=[$0], sort1=[$1], dir0=[ASC], dir1=[ASC], offset=[2], 
fetch=[1])
+  LogicalProject(A=[$0], B=[$7])
+    LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+LogicalSort(sort0=[$0], dir0=[ASC], offset=[2], fetch=[1])
+  LogicalProject(A=[$0], B=[$7])
+    LogicalTableScan(table=[[CATALOG, SALES, EMP]])
 ]]>
     </Resource>
   </TestCase>

Reply via email to