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()) {
