This is an automated email from the ASF dual-hosted git repository.
zstan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new 65fd2caf88 IGNITE-19976: Sql. ClassCastException when trying to select
from indexed smallint column (#3377)
65fd2caf88 is described below
commit 65fd2caf88e486bc53e9d01aaf3b2a74c1ec134b
Author: Max Zhuravkov <[email protected]>
AuthorDate: Thu Mar 14 09:26:53 2024 +0200
IGNITE-19976: Sql. ClassCastException when trying to select from indexed
smallint column (#3377)
---
.../internal/sql/engine/ItSecondaryIndexTest.java | 41 ++++
.../ignite/internal/sql/engine/util/RexUtils.java | 34 ++--
.../planner/IndexSearchBoundsPlannerTest.java | 223 ++++++++++++++++-----
3 files changed, 240 insertions(+), 58 deletions(-)
diff --git
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItSecondaryIndexTest.java
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItSecondaryIndexTest.java
index 1e40ffc988..2a69a53ab1 100644
---
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItSecondaryIndexTest.java
+++
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItSecondaryIndexTest.java
@@ -17,6 +17,7 @@
package org.apache.ignite.internal.sql.engine;
+import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
import static
org.apache.ignite.internal.sql.engine.util.QueryChecker.containsAnyProject;
import static
org.apache.ignite.internal.sql.engine.util.QueryChecker.containsAnyScan;
import static
org.apache.ignite.internal.sql.engine.util.QueryChecker.containsIndexScan;
@@ -28,12 +29,15 @@ import static org.hamcrest.Matchers.not;
import java.time.LocalDate;
import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
import org.apache.ignite.internal.sql.BaseSqlIntegrationTest;
import org.apache.ignite.internal.sql.engine.rel.IgniteKeyValueGet;
import org.apache.ignite.internal.sql.engine.util.QueryChecker;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
/**
* Basic index tests.
@@ -47,6 +51,8 @@ public class ItSecondaryIndexTest extends
BaseSqlIntegrationTest {
private static final String NAME_DATE_IDX = "NAME_DATE_IDX";
+ private static final AtomicInteger TABLE_IDX = new AtomicInteger();
+
/**
* Before all.
*/
@@ -1113,4 +1119,39 @@ public class ItSecondaryIndexTest extends
BaseSqlIntegrationTest {
.returns(1)
.check();
}
+
+ @ParameterizedTest
+ @CsvSource(value = {
+ // type, literal
+ "TINYINT;50",
+ "TINYINT;50::BIGINT",
+ "TINYINT;50::DECIMAL(10)",
+ "TINYINT;50::REAL",
+
+ "REAL;50.00",
+ "REAL;50.00::REAL",
+ "REAL;50.00::DOUBLE",
+ "REAL;50",
+
+ "DOUBLE;50.00",
+ "DOUBLE;50.00::REAL",
+ "DOUBLE;50.00::DECIMAL(10,2)",
+ "DOUBLE;50",
+
+ "DECIMAL(10, 2);50.00", // DECIMAL(10,2)
+ "DECIMAL(10, 2);50.00::REAL",
+ "DECIMAL(10, 2);50.00::DOUBLE",
+ "DECIMAL(10, 2);50",
+ }, delimiter = ';')
+ public void testTypeCastsIndexBounds(String type, String val) {
+ int id = TABLE_IDX.getAndIncrement();
+
+ sql(format("create table tt_{}(id INTEGER PRIMARY KEY, field_1 {})",
id, type, val));
+
+ sql(format("SELECT * FROM tt_{} WHERE field_1 = {}", id, val));
+
+ sql(format("CREATE INDEX tt_idx_{} ON tt_{} (field_1)", id, id));
+
+ sql(format("SELECT * FROM tt_{} WHERE field_1 = {}", id, val));
+ }
}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/RexUtils.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/RexUtils.java
index d54920f62a..6dffd47ec0 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/RexUtils.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/RexUtils.java
@@ -947,9 +947,13 @@ public class RexUtils {
}
/**
- * If the given node is a numeric literal, checks whether it the cast to
{@code type} overflows
- * and in that case performs {@code saturated cast}, converting a value of
that literal to the largest value of that type.
- * If overflow does can not occur, returns the same node.
+ * If the given node is a numeric literal, checks whether its cast to
{@code type} overflows and in that case
+ * performs {@code saturated cast}, converting a value of that literal to
the largest value of that type.
+ *
+ * <p>If overflow does can not occur, returns a literal wrapped in a cast
to {@code type}, because values search bounds
+ * in index lookups/scans should exactly match to types of database
columns.
+ *
+ * <p>Otherwise returns {@code null}.
*/
@Nullable
private static RexLiteral toSaturatedValue(RexBuilder builder, RexNode
node, RelDataType type) {
@@ -982,21 +986,25 @@ public class RexUtils {
exact = true;
}
+ BigDecimal newVal;
+
if (lower.compareTo(val) > 0) {
- if (exact) {
- return builder.makeExactLiteral(lower, type);
- } else {
- return builder.makeApproxLiteral(lower, type);
- }
+ newVal = lower;
} else if (val.compareTo(upper) > 0) {
- if (exact) {
- return builder.makeExactLiteral(upper, type);
- } else {
- return builder.makeApproxLiteral(upper, type);
- }
+ newVal = upper;
+ } else if (!SqlTypeUtil.equalSansNullability(node.getType(), type)) {
+ newVal = val;
} else {
+ // If literal types and required type, match ignoring nullability,
+ // then return a literal as is.
return lit;
}
+
+ if (exact) {
+ return builder.makeExactLiteral(newVal, type);
+ } else {
+ return builder.makeApproxLiteral(newVal, type);
+ }
}
/** Visitor for replacing scan local refs to input refs. */
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/IndexSearchBoundsPlannerTest.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/IndexSearchBoundsPlannerTest.java
index 5d35473d5f..ed3349185b 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/IndexSearchBoundsPlannerTest.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/IndexSearchBoundsPlannerTest.java
@@ -18,11 +18,13 @@
package org.apache.ignite.internal.sql.engine.planner;
import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
+import static org.junit.jupiter.params.provider.Arguments.arguments;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
@@ -33,8 +35,10 @@ import java.util.stream.Stream;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.rex.RexUtil;
import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.sql.type.SqlTypeUtil;
+import org.apache.ignite.internal.logger.IgniteLogger;
+import org.apache.ignite.internal.logger.Loggers;
import
org.apache.ignite.internal.sql.engine.framework.TestBuilders.TableBuilder;
import org.apache.ignite.internal.sql.engine.prepare.bounds.ExactBounds;
import org.apache.ignite.internal.sql.engine.prepare.bounds.MultiBounds;
@@ -42,6 +46,7 @@ import
org.apache.ignite.internal.sql.engine.prepare.bounds.RangeBounds;
import org.apache.ignite.internal.sql.engine.prepare.bounds.SearchBounds;
import org.apache.ignite.internal.sql.engine.rel.IgniteIndexScan;
import org.apache.ignite.internal.sql.engine.schema.IgniteIndex.Collation;
+import org.apache.ignite.internal.sql.engine.schema.IgniteIndex.Type;
import org.apache.ignite.internal.sql.engine.schema.IgniteSchema;
import org.apache.ignite.internal.sql.engine.trait.IgniteDistributions;
import org.apache.ignite.internal.sql.engine.type.IgniteTypeFactory;
@@ -59,6 +64,8 @@ import org.junit.jupiter.params.provider.MethodSource;
* Index bounds check tests.
*/
public class IndexSearchBoundsPlannerTest extends AbstractPlannerTest {
+ private static final IgniteLogger LOG =
Loggers.forClass(IndexSearchBoundsPlannerTest.class);
+
private static List<String> NODES = new ArrayList<>(4);
private IgniteSchema publicSchema;
@@ -452,62 +459,177 @@ public class IndexSearchBoundsPlannerTest extends
AbstractPlannerTest {
assertBounds("SELECT * FROM test2 WHERE C2 = " + value, List.of(),
schema, bounds);
}
- private static Stream<Arguments> boundsTypeLimits() {
- RelDataType tinyintType =
TYPE_FACTORY.createSqlType(SqlTypeName.TINYINT);
- byte[] tinyIntTypeLimits = {Byte.MIN_VALUE, Byte.MAX_VALUE};
+ @ParameterizedTest
+ @MethodSource("indexTypeAndNumericsInBounds")
+ public void testCorrectNumericIndexInBounds(
+ Type indexType,
+ RelDataType columnType,
+ String valueExpr,
+ String boundExpr,
+ RelDataType boundExprType) throws Exception {
+
+ UnaryOperator<TableBuilder> tableB = tableB("TEST2", "C2", columnType);
+
+ IgniteSchema schema;
+ if (indexType == Type.HASH) {
+ schema = createSchemaFrom(tableB.andThen(addHashIndex("C2")));
+ } else {
+ schema = createSchemaFrom(tableB.andThen(addSortIndex("C2")));
+ }
- RelDataType smallIntType =
TYPE_FACTORY.createSqlType(SqlTypeName.SMALLINT);
- short[] smallIntLimits = {Short.MIN_VALUE, Short.MAX_VALUE};
+ assertBounds("SELECT * FROM test2 WHERE C2 = " + valueExpr, List.of(),
schema, searchBounds -> {
+ if (!(searchBounds instanceof ExactBounds)) {
+ log.info("SearchBound type does not match. Expected {} but got
{}", ExactBounds.class, searchBounds);
+ return false;
+ }
- RelDataType intType = TYPE_FACTORY.createSqlType(SqlTypeName.INTEGER);
- int[] intLimits = {Integer.MIN_VALUE, Integer.MAX_VALUE};
+ ExactBounds exactBounds = (ExactBounds) searchBounds;
+ RexNode rexNode = exactBounds.bound();
- RelDataType bigIntType =
TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT);
- BigDecimal[] bigIntTypeLimits = {BigDecimal.valueOf(Long.MIN_VALUE),
BigDecimal.valueOf(Long.MAX_VALUE)};
+ if (!SqlTypeUtil.equalSansNullability(boundExprType,
rexNode.getType())) {
+ log.info("Bound type does not match. Expected {} but got {}",
boundExprType, rexNode.getType());
+ return false;
+ }
- RelDataType decimal3Type =
TYPE_FACTORY.createSqlType(SqlTypeName.DECIMAL, 3);
- BigDecimal[] decimal3TypeLimits = {BigDecimal.valueOf(-999),
BigDecimal.valueOf(999)};
- RelDataType decimal53Type =
TYPE_FACTORY.createSqlType(SqlTypeName.DECIMAL, 5, 3);
- BigDecimal[] decimal53TypeLimits = {new BigDecimal("-99.999"), new
BigDecimal("99.999")};
+ if (!boundExpr.equals(rexNode.toString())) {
+ log.info("Bound expr does not match. Expected {} but got {}",
boundExpr, rexNode);
+ return false;
+ }
+
+ return true;
+ });
+ }
+
+ private static Stream<Arguments> indexTypeAndNumericsInBounds() {
+ Stream<Arguments> result = Stream.of();
+
+ for (Type type : Type.values()) {
+ Stream<Arguments> idx = numericsInBounds().map(a -> {
+ Object[] v = a.get();
+
+ Object[] newArgs = new Object[v.length + 1];
+ newArgs[0] = type;
+ System.arraycopy(v, 0, newArgs, 1, v.length);
+
+ return arguments(newArgs);
+ });
+ result = Stream.concat(result, idx);
+ }
+
+ return result;
+ }
+ private static Stream<Arguments> numericsInBounds() {
return Stream.of(
- Arguments.arguments(tinyintType, -129,
exact(tinyIntTypeLimits[0])),
- Arguments.arguments(tinyintType, -128,
exact(tinyIntTypeLimits[0])),
- Arguments.arguments(tinyintType, 127,
exact(tinyIntTypeLimits[1])),
- Arguments.arguments(tinyintType, 128,
exact(tinyIntTypeLimits[1])),
+ // Column type, expr to use in search condition, expected
expression in search bounds as RexNode::toString, its type.
+
+ arguments(sqlType(SqlTypeName.TINYINT), "42", "42:TINYINT",
sqlType(SqlTypeName.TINYINT)),
+ arguments(sqlType(SqlTypeName.TINYINT), "CAST(42 AS TINYINT)",
"42:TINYINT", sqlType(SqlTypeName.TINYINT)),
+ arguments(sqlType(SqlTypeName.TINYINT), "CAST(42 AS SMALLINT)",
"42:TINYINT", sqlType(SqlTypeName.TINYINT)),
+ arguments(sqlType(SqlTypeName.TINYINT), "CAST(42 AS INTEGER)",
"42:TINYINT", sqlType(SqlTypeName.TINYINT)),
+ arguments(sqlType(SqlTypeName.TINYINT), "CAST(42 AS BIGINT)",
"42:TINYINT", sqlType(SqlTypeName.TINYINT)),
+
+ arguments(sqlType(SqlTypeName.SMALLINT), "42", "42:SMALLINT",
sqlType(SqlTypeName.SMALLINT)),
+ arguments(sqlType(SqlTypeName.SMALLINT), "CAST(42 AS TINYINT)",
"42:SMALLINT", sqlType(SqlTypeName.SMALLINT)),
+ arguments(sqlType(SqlTypeName.SMALLINT), "CAST(42 AS SMALLINT)",
"42:SMALLINT", sqlType(SqlTypeName.SMALLINT)),
+ arguments(sqlType(SqlTypeName.SMALLINT), "CAST(42 AS INTEGER)",
"42:SMALLINT", sqlType(SqlTypeName.SMALLINT)),
+ arguments(sqlType(SqlTypeName.SMALLINT), "CAST(42 AS BIGINT)",
"42:SMALLINT", sqlType(SqlTypeName.SMALLINT)),
+
+ arguments(sqlType(SqlTypeName.INTEGER), "42", "42",
sqlType(SqlTypeName.INTEGER)),
+ arguments(sqlType(SqlTypeName.INTEGER), "CAST(42 AS TINYINT)",
"42", sqlType(SqlTypeName.INTEGER)),
+ arguments(sqlType(SqlTypeName.INTEGER), "CAST(42 AS SMALLINT)",
"42", sqlType(SqlTypeName.INTEGER)),
+ arguments(sqlType(SqlTypeName.INTEGER), "CAST(42 AS INTEGER)",
"42", sqlType(SqlTypeName.INTEGER)),
+ arguments(sqlType(SqlTypeName.INTEGER), "CAST(42 AS BIGINT)",
"42", sqlType(SqlTypeName.INTEGER)),
+
+ arguments(sqlType(SqlTypeName.BIGINT), "42", "42:BIGINT",
sqlType(SqlTypeName.BIGINT)),
+ arguments(sqlType(SqlTypeName.BIGINT), "CAST(42 AS TINYINT)",
"42:BIGINT", sqlType(SqlTypeName.BIGINT)),
+ arguments(sqlType(SqlTypeName.BIGINT), "CAST(42 AS SMALLINT)",
"42:BIGINT", sqlType(SqlTypeName.BIGINT)),
+ arguments(sqlType(SqlTypeName.BIGINT), "CAST(42 AS INTEGER)",
"42:BIGINT", sqlType(SqlTypeName.BIGINT)),
+ arguments(sqlType(SqlTypeName.BIGINT), "CAST(42 AS BIGINT)",
"42:BIGINT", sqlType(SqlTypeName.BIGINT)),
+
+ arguments(sqlType(SqlTypeName.REAL), "42", "42:REAL",
sqlType(SqlTypeName.REAL)),
+ arguments(sqlType(SqlTypeName.DOUBLE), "42", "42:DOUBLE",
sqlType(SqlTypeName.DOUBLE))
+
+ // TODO https://issues.apache.org/jira/browse/IGNITE-19881 uncomment
after this issue is fixed
+ // The optimizer selects TableScan instead of a IndexScan
(Real/double columns)
+ // arguments(sqlType(SqlTypeName.REAL), "CAST(42 AS DOUBLE)",
"42:REAL", sqlType(SqlTypeName.REAL)),
+ // arguments(sqlType(SqlTypeName.DOUBLE), "CAST(42 AS REAL)",
"42:DOUBLE", sqlType(SqlTypeName.DOUBLE)),
+ // TODO https://issues.apache.org/jira/browse/IGNITE-19882 uncomment
after this issue is fixed
+ // The optimizer selects TableScan instead of a IndexScan (Decimal
columns)
+ // arguments(sqlType(SqlTypeName.DECIMAL, 5), "42", "42:DECIMAL(10,
0)", sqlType(SqlTypeName.DECIMAL, 5, 0)),
+ // arguments(sqlType(SqlTypeName.DECIMAL, 10, 2), "42",
"42:DECIMAL(10, 2)", sqlType(SqlTypeName.DECIMAL, 10, 2)),
+ // arguments(sqlType(SqlTypeName.INTEGER), "CAST(42 AS DECIMAL(10))",
"42", sqlType(SqlTypeName.INTEGER)),
+ );
+ }
- Arguments.arguments(smallIntType, (-(int) Math.pow(2, 15) -
1), exact(smallIntLimits[0])),
- Arguments.arguments(smallIntType, (-(int) Math.pow(2, 15)),
exact(smallIntLimits[0])),
- Arguments.arguments(smallIntType, ((int) Math.pow(2, 15)),
exact(smallIntLimits[1])),
- Arguments.arguments(smallIntType, ((int) Math.pow(2, 15) + 1),
exact(smallIntLimits[1])),
+ private static Stream<Arguments> boundsTypeLimits() {
+ RelDataType tinyintType = sqlType(SqlTypeName.TINYINT);
+ byte[] tinyIntTypeLimits = {Byte.MIN_VALUE, Byte.MAX_VALUE};
+ List<Arguments> tinyInts = List.of(
+ arguments(tinyintType, -129, exact(tinyIntTypeLimits[0])),
+ arguments(tinyintType, -128, exact(tinyIntTypeLimits[0])),
+ arguments(tinyintType, 127, exact(tinyIntTypeLimits[1])),
+ arguments(tinyintType, 128, exact(tinyIntTypeLimits[1]))
+ );
- Arguments.arguments(intType, (-(long) Math.pow(2, 31) - 1),
exact(intLimits[0])),
- Arguments.arguments(intType, (-(long) Math.pow(2, 31)),
exact(intLimits[0])),
- Arguments.arguments(intType, ((long) Math.pow(2, 31)),
exact(intLimits[1])),
- Arguments.arguments(intType, ((long) Math.pow(2, 31) + 1),
exact(intLimits[1])),
+ RelDataType smallIntType = sqlType(SqlTypeName.SMALLINT);
+ short[] smallIntLimits = {Short.MIN_VALUE, Short.MAX_VALUE};
+ List<Arguments> smallInts = List.of(
+ arguments(smallIntType, (-(int) Math.pow(2, 15) - 1),
exact(smallIntLimits[0])),
+ arguments(smallIntType, (-(int) Math.pow(2, 15)),
exact(smallIntLimits[0])),
+ arguments(smallIntType, ((int) Math.pow(2, 15)),
exact(smallIntLimits[1])),
+ arguments(smallIntType, ((int) Math.pow(2, 15) + 1),
exact(smallIntLimits[1]))
+ );
- Arguments.arguments(decimal3Type, "(-1000)::DECIMAL(3)",
exact(decimal3TypeLimits[0])),
- Arguments.arguments(decimal3Type, "(-999)::DECIMAL(3)",
exact(decimal3TypeLimits[0])),
- Arguments.arguments(decimal3Type, "999::DECIMAL(3)",
exact(decimal3TypeLimits[1])),
- Arguments.arguments(decimal3Type, "1000::DECIMAL(3)",
exact(decimal3TypeLimits[1])),
+ RelDataType intType = sqlType(SqlTypeName.INTEGER);
+ int[] intLimits = {Integer.MIN_VALUE, Integer.MAX_VALUE};
+ List<Arguments> ints = List.of(
+ arguments(intType, (-(long) Math.pow(2, 31) - 1),
exact(intLimits[0])),
+ arguments(intType, (-(long) Math.pow(2, 31)),
exact(intLimits[0])),
+ arguments(intType, ((long) Math.pow(2, 31)),
exact(intLimits[1])),
+ arguments(intType, ((long) Math.pow(2, 31) + 1),
exact(intLimits[1]))
+ );
- Arguments.arguments(decimal53Type, "(-100.000)::DECIMAL(5,
3)", exact(decimal53TypeLimits[0])),
- Arguments.arguments(decimal53Type, "(100.000)::DECIMAL(5, 3)",
exact(decimal53TypeLimits[1])),
+ RelDataType bigIntType = sqlType(SqlTypeName.BIGINT);
+ BigDecimal[] bigIntTypeLimits = {BigDecimal.valueOf(Long.MIN_VALUE),
BigDecimal.valueOf(Long.MAX_VALUE)};
+ List<Arguments> bigints = List.of(
+ arguments(bigIntType, BigInteger.TWO.pow(63).negate(),
exact(bigIntTypeLimits[0]))
+ );
- // TODO https://issues.apache.org/jira/browse/IGNITE-19858
- // Cause serialization/deserialization mismatch in
AbstractPlannerTest::checkSplitAndSerialization
- // Arguments.arguments(bigIntType,
BigInteger.TWO.pow(63).add(BigInteger.ONE).negate(),
- // exact(bigIntTypeLimits[0])),
- // Arguments.arguments(bigIntType, BigInteger.TWO.pow(63),
exact(bigIntTypeLimits[1])),
- // Arguments.arguments(bigIntType,
BigInteger.TWO.pow(63).add(BigInteger.ONE), exact(bigIntTypeLimits[1])),
+ RelDataType decimal3Type = sqlType(SqlTypeName.DECIMAL, 3);
+ BigDecimal[] decimal3TypeLimits = {BigDecimal.valueOf(-999),
BigDecimal.valueOf(999)};
+ List<Arguments> decimal3s = List.of(
+ arguments(decimal3Type, "(-1000)::DECIMAL(3)",
exact(decimal3TypeLimits[0])),
+ arguments(decimal3Type, "(-999)::DECIMAL(3)",
exact(decimal3TypeLimits[0])),
+ arguments(decimal3Type, "999::DECIMAL(3)",
exact(decimal3TypeLimits[1])),
+ arguments(decimal3Type, "1000::DECIMAL(3)",
exact(decimal3TypeLimits[1]))
+ );
- // Arguments.arguments(realType,
BigDecimal.valueOf(Float.MAX_VALUE).add(BigDecimal.ONE) + "::REAL",
- // exact(Float.MAX_VALUE)),
+ RelDataType decimal53Type = sqlType(SqlTypeName.DECIMAL, 5, 3);
+ BigDecimal[] decimal53TypeLimits = {new BigDecimal("-99.999"), new
BigDecimal("99.999")};
- // Arguments.arguments(realType,
BigDecimal.valueOf(Double.MAX_VALUE).add(BigDecimal.ONE),
- // exact(Double.MAX_VALUE)),
- Arguments.arguments(bigIntType,
BigInteger.TWO.pow(63).negate(), exact(bigIntTypeLimits[0]))
+ List<Arguments> decimal35s = List.of(
+ arguments(decimal53Type, "(-100.000)::DECIMAL(5, 3)",
exact(decimal53TypeLimits[0])),
+ arguments(decimal53Type, "(100.000)::DECIMAL(5, 3)",
exact(decimal53TypeLimits[1]))
);
+
+ // TODO https://issues.apache.org/jira/browse/IGNITE-19858
+ // Cause serialization/deserialization mismatch in
AbstractPlannerTest::checkSplitAndSerialization
+ //
+ // RelDataType realType =
TYPE_FACTORY.createSqlType(SqlTypeName.REAL);
+ // List<Arguments> reals = List.of(
+ // arguments(realType,
BigDecimal.valueOf(Float.MAX_VALUE).add(BigDecimal.ONE) + "::REAL",
exact(Float.MAX_VALUE)),
+ // arguments(realType,
BigDecimal.valueOf(Double.MAX_VALUE).add(BigDecimal.ONE),
exact(Double.MAX_VALUE))
+ // );
+
+ return Stream.of(
+ tinyInts,
+ smallInts,
+ ints,
+ bigints,
+ decimal3s,
+ decimal35s
+ ).flatMap(Collection::stream);
}
private static Predicate<SearchBounds> exact(Object val) {
@@ -540,6 +662,7 @@ public class IndexSearchBoundsPlannerTest extends
AbstractPlannerTest {
private static boolean matchBounds(List<SearchBounds> searchBounds,
Predicate<SearchBounds>... predicates) {
for (int i = 0; i < predicates.length; i++) {
if (!predicates[i].test(searchBounds.get(i))) {
+ LOG.info("{} bounds do not not match: {}",
searchBounds.get(i), predicates[i]);
return false;
}
}
@@ -565,13 +688,23 @@ public class IndexSearchBoundsPlannerTest extends
AbstractPlannerTest {
return named(range, format("{}{}, {}{}", lc, lower, upper, uc));
}
+ private static RelDataType sqlType(SqlTypeName typeName) {
+ return TYPE_FACTORY.createSqlType(typeName);
+ }
+
+ private static RelDataType sqlType(SqlTypeName typeName, int precision) {
+ return TYPE_FACTORY.createSqlType(typeName, precision);
+ }
+
+ private static RelDataType sqlType(SqlTypeName typeName, int precision,
int scale) {
+ return TYPE_FACTORY.createSqlType(typeName, precision, scale);
+ }
+
private static boolean matchValue(@Nullable Object val, RexNode bound) {
if (val == null || bound == null) {
return val == bound;
}
- bound = RexUtil.removeCast(bound);
-
String actual = Objects.toString(bound instanceof RexLiteral ?
((RexLiteral) bound).getValueAs(val.getClass()) : bound);
String expected = Objects.toString(val);
return expected.equals(actual);