[CALCITE-2684] RexBuilder gives AssertionError when creating integer literal larger than 2^63 (Ruben Quesada Lopez)
Close apache/calcite#928 For [CALCITE-2701]: Close apache/calcite#935 Project: http://git-wip-us.apache.org/repos/asf/calcite/repo Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/0ad68c31 Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/0ad68c31 Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/0ad68c31 Branch: refs/heads/master Commit: 0ad68c3194c7bca24dfd21302418636730274312 Parents: dfb29f7 Author: rubenada <[email protected]> Authored: Mon Nov 19 16:46:02 2018 +0100 Committer: Julian Hyde <[email protected]> Committed: Mon Dec 3 19:16:15 2018 -0800 ---------------------------------------------------------------------- .../java/org/apache/calcite/rex/RexBuilder.java | 12 +++++++--- .../org/apache/calcite/rex/RexBuilderTest.java | 24 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/calcite/blob/0ad68c31/core/src/main/java/org/apache/calcite/rex/RexBuilder.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rex/RexBuilder.java b/core/src/main/java/org/apache/calcite/rex/RexBuilder.java index d346ec7..696b63b 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexBuilder.java +++ b/core/src/main/java/org/apache/calcite/rex/RexBuilder.java @@ -78,6 +78,14 @@ public class RexBuilder { public static final SqlSpecialOperator GET_OPERATOR = new SqlSpecialOperator("_get", SqlKind.OTHER_FUNCTION); + /** The smallest valid {@code int} value, as a {@link BigDecimal}. */ + private static final BigDecimal INT_MIN = + BigDecimal.valueOf(Integer.MIN_VALUE); + + /** The largest valid {@code int} value, as a {@link BigDecimal}. */ + private static final BigDecimal INT_MAX = + BigDecimal.valueOf(Integer.MAX_VALUE); + //~ Instance fields -------------------------------------------------------- protected final RelDataTypeFactory typeFactory; @@ -928,12 +936,10 @@ public class RexBuilder { public RexLiteral makeExactLiteral(BigDecimal bd) { RelDataType relType; int scale = bd.scale(); - long l = bd.unscaledValue().longValue(); assert scale >= 0; assert scale <= typeFactory.getTypeSystem().getMaxNumericScale() : scale; - assert BigDecimal.valueOf(l, scale).equals(bd); if (scale == 0) { - if ((l >= Integer.MIN_VALUE) && (l <= Integer.MAX_VALUE)) { + if (bd.compareTo(INT_MIN) >= 0 && bd.compareTo(INT_MAX) <= 0) { relType = typeFactory.createSqlType(SqlTypeName.INTEGER); } else { relType = typeFactory.createSqlType(SqlTypeName.BIGINT); http://git-wip-us.apache.org/repos/asf/calcite/blob/0ad68c31/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java b/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java index 1445e95..7475044 100644 --- a/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java +++ b/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java @@ -32,6 +32,7 @@ import org.apache.calcite.util.Util; import org.junit.Test; +import java.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.util.Calendar; import java.util.TimeZone; @@ -539,6 +540,29 @@ public class RexBuilderTest { assertEquals("_UTF8'foobar'", literal.toString()); } + /** Tests {@link RexBuilder#makeExactLiteral(java.math.BigDecimal)}. */ + @Test public void testBigDecimalLiteral() { + final RelDataTypeFactory typeFactory = + new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT); + final RexBuilder builder = new RexBuilder(typeFactory); + checkBigDecimalLiteral(builder, "25"); + checkBigDecimalLiteral(builder, "9.9"); + checkBigDecimalLiteral(builder, "0"); + checkBigDecimalLiteral(builder, "-75.5"); + checkBigDecimalLiteral(builder, "10000000"); + checkBigDecimalLiteral(builder, "100000.111111111111111111"); + checkBigDecimalLiteral(builder, "-100000.111111111111111111"); + checkBigDecimalLiteral(builder, "73786976294838206464"); // 2^66 + checkBigDecimalLiteral(builder, "-73786976294838206464"); + } + + private void checkBigDecimalLiteral(RexBuilder builder, String val) { + final RexLiteral literal = builder.makeExactLiteral(new BigDecimal(val)); + assertThat("builder.makeExactLiteral(new BigDecimal(" + val + + ")).getValueAs(BigDecimal.class).toString()", + literal.getValueAs(BigDecimal.class).toString(), is(val)); + } + } // End RexBuilderTest.java
