This is an automated email from the ASF dual-hosted git repository.
tkalkirill pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 798eb3e064b IGNITE-28971 SQL Calcite: Introduce value resolver for
FETCH, OFFSET, and LIMIT (#13467)
798eb3e064b is described below
commit 798eb3e064be0b980df596fd27f8c41cfef541cc
Author: Kirill Tkalenko <[email protected]>
AuthorDate: Thu Aug 20 22:52:42 2026 +0300
IGNITE-28971 SQL Calcite: Introduce value resolver for FETCH, OFFSET, and
LIMIT (#13467)
---
.../query/calcite/exec/LogicalRelImplementor.java | 5 ++--
.../calcite/prepare/AbstractQueryContext.java | 3 ++-
.../query/calcite/prepare/IgnitePlanner.java | 21 +++++++++++++--
...Context.java => IgniteSqlPaginationPolicy.java} | 30 ++++++++++------------
.../query/calcite/prepare/IgniteSqlValidator.java | 21 +++++++++------
.../query/calcite/prepare/PlanningContext.java | 2 +-
.../query/calcite/rule/SortConverterRule.java | 14 +++++++++-
.../DynamicParametersIntegrationTest.java | 9 +++----
.../integration/LimitOffsetIntegrationTest.java | 14 +++++-----
.../OperatorsExtensionIntegrationTest.java | 20 +++++++++++++++
.../query/calcite/planner/AbstractPlannerTest.java | 21 ++++++++++++---
.../calcite/planner/LimitOffsetPlannerTest.java | 16 +++++++++++-
modules/calcite/src/test/sql/order/test_limit.test | 4 +++
13 files changed, 132 insertions(+), 48 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 a828c607417..5b7d70934ab 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
@@ -18,7 +18,6 @@
package org.apache.ignite.internal.processors.query.calcite.exec;
import java.math.BigDecimal;
-import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
@@ -86,6 +85,7 @@ import
org.apache.ignite.internal.processors.query.calcite.exec.rel.UnionAllNode
import org.apache.ignite.internal.processors.query.calcite.exec.rel.WindowNode;
import
org.apache.ignite.internal.processors.query.calcite.metadata.AffinityService;
import
org.apache.ignite.internal.processors.query.calcite.metadata.ColocationGroup;
+import
org.apache.ignite.internal.processors.query.calcite.prepare.IgniteSqlPaginationPolicy;
import
org.apache.ignite.internal.processors.query.calcite.prepare.bounds.SearchBounds;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteCollect;
import
org.apache.ignite.internal.processors.query.calcite.rel.IgniteCorrelatedNestedLoopJoin;
@@ -1094,7 +1094,8 @@ 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);
+ return
IgniteSqlPaginationPolicy.convertToLongExact(paramAsDecimal, pagPlc);
}
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/AbstractQueryContext.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/AbstractQueryContext.java
index 7fd4d73efc7..b892136f5b7 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/AbstractQueryContext.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/AbstractQueryContext.java
@@ -18,6 +18,7 @@
package org.apache.ignite.internal.processors.query.calcite.prepare;
import org.apache.calcite.plan.Context;
+import org.jetbrains.annotations.Nullable;
/**
* Abstract query context.
@@ -32,7 +33,7 @@ public class AbstractQueryContext implements Context {
}
/** {@inheritDoc} */
- @Override public <C> C unwrap(Class<C> aCls) {
+ @Override public <C> @Nullable C unwrap(Class<C> aCls) {
if (aCls == getClass())
return aCls.cast(this);
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 92e9764839e..2ed2fe2ce42 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
@@ -365,7 +365,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));
@@ -435,7 +435,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();
return validator;
}
@@ -807,4 +807,21 @@ 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)
+ );
+ }
+
+ /** */
+ private SqlValidator createSqlValidator() {
+ return createSqlValidator(catalogReader);
+ }
}
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/AbstractQueryContext.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlPaginationPolicy.java
similarity index 51%
copy from
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/AbstractQueryContext.java
copy to
modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlPaginationPolicy.java
index 7fd4d73efc7..e7f81e9456e 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/AbstractQueryContext.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteSqlPaginationPolicy.java
@@ -14,28 +14,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.ignite.internal.processors.query.calcite.prepare;
+import java.math.RoundingMode;
import org.apache.calcite.plan.Context;
+import org.apache.calcite.tools.Frameworks;
+import org.apache.ignite.internal.processors.query.calcite.util.IgniteMath;
+import org.jetbrains.annotations.Nullable;
/**
- * Abstract query context.
+ * 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>
*/
-public class AbstractQueryContext implements Context {
- /** */
- private final Context parentCtx;
-
- /** */
- public AbstractQueryContext(Context parentCtx) {
- this.parentCtx = parentCtx;
- }
-
- /** {@inheritDoc} */
- @Override public <C> C unwrap(Class<C> aCls) {
- if (aCls == getClass())
- return aCls.cast(this);
+@FunctionalInterface
+public interface IgniteSqlPaginationPolicy {
+ /** Returns the rounding mode for FETCH, LIMIT and OFFSET values. */
+ RoundingMode roundingMode();
- return parentCtx.unwrap(aCls);
+ /** Rounds the given value according to the specified policy and converts
it to {@code long}. */
+ static long convertToLongExact(Number value, @Nullable
IgniteSqlPaginationPolicy policy) {
+ return policy == null ? IgniteMath.convertToLongExact(value) :
IgniteMath.convertToLongExact(value, policy.roundingMode());
}
}
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 ac03d696d1f..b3c643b7b9b 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
@@ -18,7 +18,6 @@
package org.apache.ignite.internal.processors.query.calcite.prepare;
import java.math.BigDecimal;
-import java.math.RoundingMode;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
@@ -115,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);
}
@@ -385,7 +390,7 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
if (val.signum() < 0)
throw new IllegalArgumentException("Negative value for " +
nodeName);
- IgniteMath.convertToLongExact(val, RoundingMode.DOWN);
+ IgniteSqlPaginationPolicy.convertToLongExact(val, pagPlc);
}
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/prepare/PlanningContext.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/PlanningContext.java
index 4b401dabfad..b522f1a0db3 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/PlanningContext.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/PlanningContext.java
@@ -161,7 +161,7 @@ public final class PlanningContext implements Context {
}
/** {@inheritDoc} */
- @Override public <C> C unwrap(Class<C> aCls) {
+ @Override public <C> @Nullable C unwrap(Class<C> aCls) {
if (aCls == getClass())
return aCls.cast(this);
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/SortConverterRule.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/SortConverterRule.java
index 6025930981e..9cd4c23cc3f 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/SortConverterRule.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/SortConverterRule.java
@@ -35,6 +35,7 @@ import org.apache.calcite.rex.RexDynamicParam;
import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.rex.RexUtil;
+import
org.apache.ignite.internal.processors.query.calcite.prepare.IgniteSqlPaginationPolicy;
import
org.apache.ignite.internal.processors.query.calcite.rel.IgniteConvention;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteLimit;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSort;
@@ -139,8 +140,19 @@ public class SortConverterRule extends
RelRule<SortConverterRule.Config> {
BigDecimal fetchVal =
((RexLiteral)reducedFetch.get(0)).getValueAs(BigDecimal.class);
+ if (fetchVal == null)
+ return false;
+
// SortNode does not accept zero FETCH; the outer IgniteLimit handles
it.
- return fetchVal != null && fetchVal.compareTo(BigDecimal.ONE) >= 0;
+ IgniteSqlPaginationPolicy pagPlc =
sort.getCluster().getPlanner().getContext().unwrap(IgniteSqlPaginationPolicy.class);
+
+ try {
+ return IgniteSqlPaginationPolicy.convertToLongExact(fetchVal,
pagPlc) > 0;
+ }
+ catch (ArithmeticException ignored) {
+ // The outer IgniteLimit will report invalid FETCH during
execution.
+ return false;
+ }
}
/** Returns {@code true} if the expression contains a dynamic parameter. */
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 6e5d0a4b845..8a130f5a2e1 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
@@ -193,15 +193,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))
@@ -210,13 +210,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)
@@ -230,7 +230,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 72053f73429..ac0f38e46cc 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
@@ -149,18 +149,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();
}
/**
@@ -352,7 +352,7 @@ public class LimitOffsetIntegrationTest extends
AbstractBasicIntegrationTransact
assertQuery("SELECT id FROM TEST_REPL ORDER BY id OFFSET 1 ROWS "
+ "FETCH FIRST (ABS(0.5)) ROWS ONLY")
- .resultSize(0)
+ .returns(1)
.check();
assertQuery("SELECT id FROM TEST_REPL ORDER BY id OFFSET 1 ROWS "
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 68ada8d64ce..8825c2b4eb3 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;
@@ -66,6 +67,7 @@ import
org.apache.ignite.internal.processors.query.calcite.exec.exp.agg.Accumula
import
org.apache.ignite.internal.processors.query.calcite.exec.exp.agg.Accumulators;
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.IgniteSqlPaginationPolicy;
import
org.apache.ignite.internal.processors.query.calcite.prepare.IgniteSqlValidator;
import
org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
import org.apache.ignite.plugin.AbstractTestPluginProvider;
@@ -96,6 +98,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();
@@ -216,6 +219,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/java/org/apache/ignite/internal/processors/query/calcite/planner/AbstractPlannerTest.java
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AbstractPlannerTest.java
index 3da09de1218..6c29252f6bd 100644
---
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AbstractPlannerTest.java
+++
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AbstractPlannerTest.java
@@ -28,6 +28,7 @@ import java.util.UUID;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import com.google.common.collect.ImmutableSet;
+import org.apache.calcite.plan.Context;
import org.apache.calcite.plan.Contexts;
import org.apache.calcite.plan.RelOptListener;
import org.apache.calcite.plan.RelOptUtil;
@@ -220,7 +221,7 @@ public abstract class AbstractPlannerTest extends
GridCommonAbstractTest {
@Nullable RelOptListener planLsnr,
String... disabledRules
) {
- return plannerCtx(sql, Collections.singleton(publicSchema), planLsnr,
null, ImmutableSet.copyOf(disabledRules));
+ return plannerCtx(sql, Collections.singleton(publicSchema), planLsnr,
null, ImmutableSet.copyOf(disabledRules), null);
}
/** */
@@ -229,10 +230,13 @@ public abstract class AbstractPlannerTest extends
GridCommonAbstractTest {
Collection<IgniteSchema> schemas,
@Nullable RelOptListener planLsnr,
Collection<Object> params,
- Collection<String> disabledRules
+ Collection<String> disabledRules,
+ @Nullable Context additionalCtx
) {
+ Context parentCtx = Contexts.of(baseQueryContext(schemas), planLsnr);
+
PlanningContext.Builder ctxBuilder = PlanningContext.builder()
- .parentContext(Contexts.of(baseQueryContext(schemas), planLsnr))
+ .parentContext(additionalCtx == null ? parentCtx :
Contexts.chain(parentCtx, additionalCtx))
.query(sql);
if (params != null)
@@ -842,6 +846,9 @@ public abstract class AbstractPlannerTest extends
GridCommonAbstractTest {
/** */
@Nullable private RelOptListener planListener;
+ /** */
+ @Nullable private Context additionalCtx;
+
/** */
public TestPlanningContextBuilder query(String qry) {
query = qry;
@@ -884,9 +891,15 @@ public abstract class AbstractPlannerTest extends
GridCommonAbstractTest {
return this;
}
+ /** */
+ public TestPlanningContextBuilder additionalCtx(Context additionalCtx)
{
+ this.additionalCtx = additionalCtx;
+ return this;
+ }
+
/** */
PlanningContext build() {
- return plannerCtx(query, schemas, planListener, params,
disabledRules);
+ return plannerCtx(query, schemas, planListener, params,
disabledRules, additionalCtx);
}
}
diff --git
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/LimitOffsetPlannerTest.java
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/LimitOffsetPlannerTest.java
index 65514db6ea4..dc876471513 100644
---
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/LimitOffsetPlannerTest.java
+++
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/LimitOffsetPlannerTest.java
@@ -17,6 +17,8 @@
package org.apache.ignite.internal.processors.query.calcite.planner;
+import java.math.RoundingMode;
+import org.apache.calcite.plan.Contexts;
import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.rel.core.Sort;
import org.apache.calcite.rel.type.RelDataType;
@@ -25,6 +27,7 @@ import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.util.ImmutableIntList;
import
org.apache.ignite.internal.processors.query.calcite.prepare.IgnitePlanner;
+import
org.apache.ignite.internal.processors.query.calcite.prepare.IgniteSqlPaginationPolicy;
import
org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteExchange;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteIndexScan;
@@ -88,7 +91,18 @@ public class LimitOffsetPlannerTest extends
AbstractPlannerTest {
.and(sort -> sort.fetch != null))))));
assertPlan("SELECT * FROM TEST ORDER BY ID OFFSET 1 ROWS "
- + "FETCH FIRST (ABS(0.5)) ROWS ONLY", publicSchema,
+ + "FETCH FIRST (ABS(0.6)) ROWS ONLY", publicSchema,
+ isInstanceOf(IgniteLimit.class)
+ .and(limit -> limit.offset() != null && limit.fetch() != null)
+ .and(input(isInstanceOf(IgniteExchange.class)
+ .and(input(isInstanceOf(IgniteSort.class)
+ .and(sort -> sort.offset != null && sort.fetch !=
null))))));
+
+ assertPlan(contextBuilder()
+ .query("SELECT * FROM TEST ORDER BY ID OFFSET 1 ROWS "
+ + "FETCH FIRST (ABS(0.6)) ROWS ONLY")
+ .schema(publicSchema)
+ .additionalCtx(Contexts.of((IgniteSqlPaginationPolicy)() ->
RoundingMode.DOWN)),
isInstanceOf(IgniteLimit.class)
.and(limit -> limit.offset() != null && limit.fetch() != null)
.and(input(isInstanceOf(IgniteExchange.class)
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