You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by tk...@apache.org on 2026/08/12 10:33:20 UTC
(ignite) branch ignite-28971 created (now ef714001968)
This is an automated email from the ASF dual-hosted git repository.
tkalkirill pushed a change to branch ignite-28971
in repository https://gitbox.apache.org/repos/asf/ignite.git
at ef714001968 IGNITE-28971 Wip
This branch includes the following new commits:
new ef714001968 IGNITE-28971 Wip
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(ignite) 01/01: IGNITE-28971 Wip
Posted by tk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
tkalkirill pushed a commit to branch ignite-28971
in repository https://gitbox.apache.org/repos/asf/ignite.git
commit ef7140019687d987205af07cb32198e5b6a9b201
Author: Kirill Tkalenko <tk...@yandex.ru>
AuthorDate: Wed Aug 12 13:31:53 2026 +0300
IGNITE-28971 Wip
---
.../query/calcite/exec/LogicalRelImplementor.java | 6 +++-
.../query/calcite/prepare/IgnitePlanner.java | 17 ++++++++++--
.../query/calcite/prepare/IgniteSqlValidator.java | 22 ++++++++++-----
.../calcite/sql/IgniteSqlPaginationPolicy.java | 32 ++++++++++++++++++++++
.../DynamicParametersIntegrationTest.java | 9 +++---
.../integration/LimitOffsetIntegrationTest.java | 12 ++++----
.../OperatorsExtensionIntegrationTest.java | 20 ++++++++++++++
modules/calcite/src/test/sql/order/test_limit.test | 4 +++
8 files changed, 101 insertions(+), 21 deletions(-)
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java
index b5c1c06f1ce..71af0b907d2 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java
@@ -125,6 +125,7 @@ import org.apache.ignite.internal.processors.query.calcite.rule.LogicalScanConve
import org.apache.ignite.internal.processors.query.calcite.schema.CacheTableDescriptor;
import org.apache.ignite.internal.processors.query.calcite.schema.IgniteIndex;
import org.apache.ignite.internal.processors.query.calcite.schema.IgniteTable;
+import org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlPaginationPolicy;
import org.apache.ignite.internal.processors.query.calcite.trait.Destination;
import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistribution;
import org.apache.ignite.internal.processors.query.calcite.trait.TraitUtils;
@@ -1084,7 +1085,10 @@ public class LogicalRelImplementor<Row> implements IgniteRelVisitor<Node<Row>> {
if (paramAsDecimal.signum() < 0)
throw new IllegalArgumentException("Negative value for " + op);
- return IgniteMath.convertToLongExact(paramAsDecimal, RoundingMode.DOWN);
+ IgniteSqlPaginationPolicy pagPlc = ctx.unwrap(IgniteSqlPaginationPolicy.class);
+ RoundingMode roundingMode = pagPlc == null ? IgniteMath.NUMERIC_ROUNDING_MODE : pagPlc.roundingMode();
+
+ return IgniteMath.convertToLongExact(paramAsDecimal, roundingMode);
}
catch (RuntimeException ex) {
throw new IgniteSQLException(IgniteResource.INSTANCE.illegalFetchLimit(op).str(),
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgnitePlanner.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgnitePlanner.java
index 553ca3ba89a..2a73046f941 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgnitePlanner.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgnitePlanner.java
@@ -91,6 +91,7 @@ import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
import org.apache.ignite.internal.processors.query.IgniteSQLException;
import org.apache.ignite.internal.processors.query.calcite.metadata.IgniteMetadata;
import org.apache.ignite.internal.processors.query.calcite.metadata.RelMetadataQueryEx;
+import org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlPaginationPolicy;
import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
import org.apache.ignite.internal.processors.query.calcite.util.Commons;
import org.apache.ignite.internal.util.typedef.F;
@@ -365,7 +366,7 @@ public class IgnitePlanner implements Planner, RelOptTable.ViewExpander {
}
CalciteCatalogReader catalogReader = this.catalogReader.withSchemaPath(schemaPath);
- SqlValidator validator = new IgniteSqlValidator(operatorTbl, catalogReader, typeFactory, validatorCfg, ctx.parameters());
+ SqlValidator validator = createSqlValidator(catalogReader);
SqlToRelConverter sqlToRelConverter = sqlToRelConverter(validator, catalogReader, sqlToRelConverterCfg);
RelRoot root = sqlToRelConverter.convertQuery(sqlNode, true, false);
root = root.withRel(sqlToRelConverter.decorrelate(sqlNode, root.rel));
@@ -426,7 +427,7 @@ public class IgnitePlanner implements Planner, RelOptTable.ViewExpander {
/** */
private SqlValidator validator() {
if (validator == null)
- validator = new IgniteSqlValidator(operatorTbl, catalogReader, typeFactory, validatorCfg, ctx.parameters());
+ validator = createSqlValidator(catalogReader);
return validator;
}
@@ -798,4 +799,16 @@ public class IgnitePlanner implements Planner, RelOptTable.ViewExpander {
super.checkCancel();
}
}
+
+ /** */
+ private SqlValidator createSqlValidator(CalciteCatalogReader catalogReader) {
+ return new IgniteSqlValidator(
+ operatorTbl,
+ catalogReader,
+ typeFactory,
+ validatorCfg,
+ ctx.parameters(),
+ ctx.unwrap(IgniteSqlPaginationPolicy.class)
+ );
+ }
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlValidator.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlValidator.java
index 22d9be1f083..57ceb927de0 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlValidator.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlValidator.java
@@ -75,6 +75,7 @@ import org.apache.ignite.internal.processors.query.calcite.schema.CacheTableDesc
import org.apache.ignite.internal.processors.query.calcite.schema.IgniteCacheTable;
import org.apache.ignite.internal.processors.query.calcite.schema.IgniteTable;
import org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlDecimalLiteral;
+import org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlPaginationPolicy;
import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
import org.apache.ignite.internal.processors.query.calcite.type.OtherType;
import org.apache.ignite.internal.processors.query.calcite.util.IgniteMath;
@@ -113,25 +114,31 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
/** */
private final RelDataType nullType;
+ /** */
+ private final @Nullable IgniteSqlPaginationPolicy pagPlc;
+
/**
* Creates a validator.
*
- * @param opTab Operator table
- * @param catalogReader Catalog reader
- * @param typeFactory Type factory
- * @param cfg Config
- * @param parameters Dynamic parameters
+ * @param opTab Operator table.
+ * @param catalogReader Catalog reader.
+ * @param typeFactory Type factory.
+ * @param cfg Config.
+ * @param parameters Dynamic parameters.
+ * @param pagPlc Pagination policy.
*/
public IgniteSqlValidator(
SqlOperatorTable opTab,
CalciteCatalogReader catalogReader,
IgniteTypeFactory typeFactory,
SqlValidator.Config cfg,
- @Nullable Object[] parameters
+ @Nullable Object[] parameters,
+ @Nullable IgniteSqlPaginationPolicy pagPlc
) {
super(opTab, catalogReader, typeFactory, cfg);
this.parameters = parameters;
+ this.pagPlc = pagPlc;
nullType = typeFactory.createSqlType(SqlTypeName.NULL);
}
@@ -306,7 +313,8 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
if (val.signum() < 0)
throw new IllegalArgumentException("Negative value for " + nodeName);
- IgniteMath.convertToLongExact(val, RoundingMode.DOWN);
+ RoundingMode roundingMode = pagPlc == null ? IgniteMath.NUMERIC_ROUNDING_MODE : pagPlc.roundingMode();
+ IgniteMath.convertToLongExact(val, roundingMode);
}
catch (RuntimeException e) {
throw newValidationError(n, IgniteResource.INSTANCE.illegalFetchLimit(nodeName));
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/sql/IgniteSqlPaginationPolicy.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/sql/IgniteSqlPaginationPolicy.java
new file mode 100644
index 00000000000..47eb4d15393
--- /dev/null
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/sql/IgniteSqlPaginationPolicy.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+package org.apache.ignite.internal.processors.query.calcite.sql;
+
+import java.math.RoundingMode;
+import org.apache.calcite.plan.Context;
+import org.apache.calcite.tools.Frameworks;
+
+/**
+ * Defines a policy for processing values of SQL pagination clauses: LIMIT, FETCH, and OFFSET.
+ *
+ * <p>Custom instance can be supplied through {@link Frameworks.ConfigBuilder#context(Context)}.</p>
+ */
+@FunctionalInterface
+public interface IgniteSqlPaginationPolicy {
+ /** Returns the rounding mode for FETCH, LIMIT and OFFSET values. */
+ RoundingMode roundingMode();
+}
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/DynamicParametersIntegrationTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/DynamicParametersIntegrationTest.java
index 45f6db66f08..cea49a96c10 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/DynamicParametersIntegrationTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/DynamicParametersIntegrationTest.java
@@ -171,15 +171,15 @@ public class DynamicParametersIntegrationTest extends AbstractBasicIntegrationTe
public void testFractionalLimitOffset() {
createAndPopulateTable();
- assertQuery("SELECT id FROM person ORDER BY id LIMIT ?").withParams(0.5).resultSize(0).check();
+ assertQuery("SELECT id FROM person ORDER BY id LIMIT ?").withParams(0.5).returns(0).check();
assertQuery("SELECT id FROM person ORDER BY id LIMIT ?").withParams(1.4).returns(0).check();
- assertQuery("SELECT id FROM person ORDER BY id LIMIT ?").withParams(1.6).returns(0).check();
+ assertQuery("SELECT id FROM person ORDER BY id LIMIT ?").withParams(1.6).returns(0).returns(1).check();
assertThrowsSqlException("SELECT id FROM person ORDER BY id LIMIT ?", null, BigDecimal.valueOf(-1.5));
assertThrowsSqlException("SELECT id FROM person ORDER BY id LIMIT ?", null, BigDecimal.valueOf(-0.5));
assertQuery("SELECT id FROM person ORDER BY id FETCH FIRST ? ROWS ONLY")
.withParams(BigDecimal.valueOf(0.5))
- .resultSize(0)
+ .returns(0)
.check();
assertQuery("SELECT id FROM person ORDER BY id FETCH FIRST ? ROWS ONLY")
.withParams(BigDecimal.valueOf(1.3))
@@ -188,13 +188,13 @@ public class DynamicParametersIntegrationTest extends AbstractBasicIntegrationTe
assertQuery("SELECT id FROM person ORDER BY id FETCH FIRST ? ROWS ONLY")
.withParams(BigDecimal.valueOf(1.6))
.returns(0)
+ .returns(1)
.check();
assertThrowsSqlException("SELECT id FROM person ORDER BY id FETCH FIRST ? ROWS ONLY", null, BigDecimal.valueOf(-1.5));
assertThrowsSqlException("SELECT id FROM person ORDER BY id FETCH FIRST ? ROWS ONLY", null, BigDecimal.valueOf(-0.5));
assertQuery("SELECT id FROM person ORDER BY id OFFSET ? ROWS")
.withParams(BigDecimal.valueOf(0.5))
- .returns(0)
.returns(1)
.returns(2)
.returns(3)
@@ -208,7 +208,6 @@ public class DynamicParametersIntegrationTest extends AbstractBasicIntegrationTe
.check();
assertQuery("SELECT id FROM person ORDER BY id OFFSET ? ROWS")
.withParams(BigDecimal.valueOf(2.6))
- .returns(2)
.returns(3)
.returns(4)
.check();
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/LimitOffsetIntegrationTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/LimitOffsetIntegrationTest.java
index 04eeb5e543e..74b15d6e476 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/LimitOffsetIntegrationTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/LimitOffsetIntegrationTest.java
@@ -134,18 +134,18 @@ public class LimitOffsetIntegrationTest extends AbstractBasicIntegrationTransact
public void testFractionalLimitOffset() throws Exception {
fillCache(cacheRepl, 4);
- assertQuery("SELECT id FROM TEST_REPL ORDER BY id LIMIT 0.5").check();
+ assertQuery("SELECT id FROM TEST_REPL ORDER BY id LIMIT 0.5").returns(0).check();
assertQuery("SELECT id FROM TEST_REPL ORDER BY id LIMIT 1.2").returns(0).check();
- assertQuery("SELECT id FROM TEST_REPL ORDER BY id LIMIT 1.5").returns(0).check();
+ assertQuery("SELECT id FROM TEST_REPL ORDER BY id LIMIT 1.5").returns(0).returns(1).check();
- assertQuery("SELECT id FROM TEST_REPL ORDER BY id FETCH FIRST 0.5 ROWS ONLY").check();
+ assertQuery("SELECT id FROM TEST_REPL ORDER BY id FETCH FIRST 0.5 ROWS ONLY").returns(0).check();
assertQuery("SELECT id FROM TEST_REPL ORDER BY id FETCH FIRST 1.3 ROWS ONLY").returns(0).check();
- assertQuery("SELECT id FROM TEST_REPL ORDER BY id FETCH FIRST 1.6 ROWS ONLY").returns(0).check();
+ assertQuery("SELECT id FROM TEST_REPL ORDER BY id FETCH FIRST 1.6 ROWS ONLY").returns(0).returns(1).check();
assertQuery("SELECT id FROM TEST_REPL ORDER BY id OFFSET 0.5 ROWS")
- .returns(0).returns(1).returns(2).returns(3).check();
+ .returns(1).returns(2).returns(3).check();
assertQuery("SELECT id FROM TEST_REPL ORDER BY id OFFSET 2.3 ROWS").returns(2).returns(3).check();
- assertQuery("SELECT id FROM TEST_REPL ORDER BY id OFFSET 2.6 ROWS").returns(2).returns(3).check();
+ assertQuery("SELECT id FROM TEST_REPL ORDER BY id OFFSET 2.6 ROWS").returns(3).check();
}
/**
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/OperatorsExtensionIntegrationTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/OperatorsExtensionIntegrationTest.java
index 4d4e402f1e5..0ad8cd90e5c 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/OperatorsExtensionIntegrationTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/OperatorsExtensionIntegrationTest.java
@@ -17,6 +17,7 @@
package org.apache.ignite.internal.processors.query.calcite.integration;
import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.List;
@@ -64,6 +65,7 @@ import org.apache.ignite.internal.processors.query.calcite.exec.exp.agg.Accumula
import org.apache.ignite.internal.processors.query.calcite.prepare.IgniteConvertletTable;
import org.apache.ignite.internal.processors.query.calcite.prepare.IgniteSqlNodeRewriter;
import org.apache.ignite.internal.processors.query.calcite.prepare.IgniteSqlValidator;
+import org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlPaginationPolicy;
import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
import org.apache.ignite.plugin.AbstractTestPluginProvider;
import org.apache.ignite.plugin.PluginContext;
@@ -93,6 +95,7 @@ public class OperatorsExtensionIntegrationTest extends AbstractBasicIntegrationT
.withSqlNodeRewriter(new SqlRewriter()))
.context(Contexts.chain(
CalciteQueryProcessor.FRAMEWORK_CONFIG.getContext(),
+ Contexts.of((IgniteSqlPaginationPolicy)() -> RoundingMode.DOWN),
Contexts.of(new AccumulatorFactoryProviderImpl())))
.build();
@@ -178,6 +181,23 @@ public class OperatorsExtensionIntegrationTest extends AbstractBasicIntegrationT
.check();
}
+ /** */
+ @Test
+ public void testPaginationRoundingPolicy() {
+ assertQuery("SELECT x FROM (VALUES (0), (1), (2)) t(x) ORDER BY x LIMIT 1.9")
+ .returns(0)
+ .check();
+
+ assertQuery("SELECT x FROM (VALUES (0), (1), (2)) t(x) ORDER BY x FETCH FIRST 1.9 ROWS ONLY")
+ .returns(0)
+ .check();
+
+ assertQuery("SELECT x FROM (VALUES (0), (1), (2)) t(x) ORDER BY x OFFSET 1.9 ROWS")
+ .returns(1)
+ .returns(2)
+ .check();
+ }
+
/** Rewrites LTRIM with 2 parameters. */
public static SqlCall rewriteLtrim(SqlValidator validator, SqlCall call) {
if (call.operandCount() != 2)
diff --git a/modules/calcite/src/test/sql/order/test_limit.test b/modules/calcite/src/test/sql/order/test_limit.test
index 00ce8f9822d..f7fa98caf70 100644
--- a/modules/calcite/src/test/sql/order/test_limit.test
+++ b/modules/calcite/src/test/sql/order/test_limit.test
@@ -28,12 +28,14 @@ query I
SELECT a FROM test ORDER BY a LIMIT 1.5
----
11
+12
# decimal limit
query I
SELECT a FROM test ORDER BY a LIMIT 1.6
----
11
+12
# decimal limit
query I
@@ -57,12 +59,14 @@ query I
SELECT a FROM test ORDER BY a FETCH FIRST 1.5 ROWS ONLY
----
11
+12
# decimal limit
query I
SELECT a FROM test ORDER BY a FETCH FIRST 1.6 ROWS ONLY
----
11
+12
# decimal offset/limit
query I