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

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

commit d8fcc4077ddf74f05994f24edc8997f8889dd7b5
Author: Zhen Chen <[email protected]>
AuthorDate: Sat Sep 20 18:12:31 2025 +0800

    [CALCITE-7190] FETCH and OFFSET in SortMergeRule only supports BIGINT
---
 .../org/apache/calcite/rel/rules/MeasureRules.java |  4 ++--
 .../apache/calcite/rel/rules/SortMergeRule.java    | 14 ++++++------
 .../java/org/apache/calcite/tools/RelBuilder.java  | 25 +++++++++++++++-------
 3 files changed, 27 insertions(+), 16 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/rel/rules/MeasureRules.java 
b/core/src/main/java/org/apache/calcite/rel/rules/MeasureRules.java
index 707c7b2f5f..037a4d6054 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/MeasureRules.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/MeasureRules.java
@@ -508,8 +508,8 @@ protected 
ProjectSortMeasureRule(ProjectSortMeasureRuleConfig config) {
 
       relBuilder.push(sort.getInput())
           .projectPlus(map.keySet())
-          .sortLimit(sort.offset == null ? 0 : 
RexLiteral.longValue(sort.offset),
-              sort.fetch == null ? -1 : RexLiteral.longValue(sort.fetch),
+          .sortLimit(sort.offset == null ? 0 : 
RexLiteral.numberValue(sort.offset),
+              sort.fetch == null ? -1 : RexLiteral.numberValue(sort.fetch),
               sort.getSortExps())
           .project(newProjects);
       call.transformTo(relBuilder.build());
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/SortMergeRule.java 
b/core/src/main/java/org/apache/calcite/rel/rules/SortMergeRule.java
index 797b7e354a..1622864329 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/SortMergeRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/SortMergeRule.java
@@ -28,6 +28,8 @@
 
 import org.immutables.value.Value;
 
+import java.math.BigDecimal;
+
 /**
  * This rule try to merge the double {@link Sort},one is Limit semantics,
  * another sort is Limit or TOPN semantics.
@@ -92,18 +94,18 @@ private static void limitMerge(SortMergeRule rule,
 
     final RelBuilder builder = call.builder();
 
-    final long topFetch = topSort.fetch instanceof RexLiteral
-        ? RexLiteral.longValue(topSort.fetch) : -1;
+    final Number topFetch = topSort.fetch instanceof RexLiteral
+        ? RexLiteral.numberValue(topSort.fetch) : null;
 
-    final long bottomFetch = bottomSort.fetch instanceof RexLiteral
-        ? RexLiteral.longValue(bottomSort.fetch) : -1;
+    final Number bottomFetch = bottomSort.fetch instanceof RexLiteral
+        ? RexLiteral.numberValue(bottomSort.fetch) : null;
 
-    if (topFetch == -1 || bottomFetch == -1) {
+    if (topFetch == null || bottomFetch == null) {
       return;
     }
 
     // Get the minimum limit value from parent and child sort RelNode
-    final long minFetch = Math.min(topFetch, bottomFetch);
+    final Number minFetch = ((BigDecimal) topFetch).min((BigDecimal) 
bottomFetch);
 
     builder.push(bottomSort.getInput());
 
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 b9b9c25a42..e653d72d54 100644
--- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
+++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
@@ -3674,7 +3674,7 @@ private static <E> ImmutableList<ImmutableList<E>> copy(
    * @param offset Number of rows to skip; non-positive means don't skip any
    * @param fetch Maximum number of rows to fetch; negative means no limit
    */
-  public RelBuilder limit(int offset, int fetch) {
+  public RelBuilder limit(Number offset, Number fetch) {
     return sortLimit(offset, fetch, ImmutableList.of());
   }
 
@@ -3720,7 +3720,7 @@ public RelBuilder sort(Iterable<? extends RexNode> nodes) 
{
   }
 
   /** Creates a {@link Sort} by expressions, with limit and offset. */
-  public RelBuilder sortLimit(long offset, long fetch, RexNode... nodes) {
+  public RelBuilder sortLimit(Number offset, Number fetch, RexNode... nodes) {
     return sortLimit(offset, fetch, ImmutableList.copyOf(nodes));
   }
 
@@ -3739,10 +3739,16 @@ public RelBuilder sort(RelCollation collation) {
    * @param fetch Maximum number of rows to fetch; negative means no limit
    * @param nodes Sort expressions
    */
-  public RelBuilder sortLimit(long offset, long fetch,
+  public RelBuilder sortLimit(Number offset, Number fetch,
       Iterable<? extends RexNode> nodes) {
-    final @Nullable RexNode offsetNode = offset <= 0 ? null : literal(offset);
-    final @Nullable RexNode fetchNode = fetch < 0 ? null : literal(fetch);
+    final @Nullable RexNode offsetNode =
+        new BigDecimal(offset.toString()).compareTo(BigDecimal.ZERO) <= 0
+            ? null
+            : literal(offset);
+    final @Nullable RexNode fetchNode =
+        new BigDecimal(fetch.toString()).compareTo(BigDecimal.ZERO) < 0
+            ? null
+            : literal(fetch);
     return sortLimit(offsetNode, fetchNode, nodes);
   }
 
@@ -3770,9 +3776,12 @@ public RelBuilder sortLimit(@Nullable RexNode 
offsetNode, @Nullable RexNode fetc
     final Registrar registrar = new Registrar(fields(), ImmutableList.of());
     final List<RelFieldCollation> fieldCollations =
         registrar.registerFieldCollations(nodes);
-    final long fetch = fetchNode instanceof RexLiteral
-        ? RexLiteral.longValue(fetchNode) : -1;
-    if (offsetNode == null && fetch == 0 && config.simplifyLimit()) {
+    final Number fetch = fetchNode instanceof RexLiteral
+        ? RexLiteral.numberValue(fetchNode) : null;
+    if (offsetNode == null
+        && fetch != null
+        && ((BigDecimal) fetch).compareTo(BigDecimal.ZERO) == 0
+        && config.simplifyLimit()) {
       return empty();
     }
     if (offsetNode == null && fetchNode == null && fieldCollations.isEmpty()) {

Reply via email to