You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@calcite.apache.org by "Soumyakanti Das (Jira)" <ji...@apache.org> on 2022/12/19 19:14:00 UTC

[jira] [Updated] (CALCITE-5444) Error when trying to cast 0:DECIMAL(1,0) to 0:DECIMAL(1,1)

     [ https://issues.apache.org/jira/browse/CALCITE-5444?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Soumyakanti Das updated CALCITE-5444:
-------------------------------------
    Description: 
The java {{BigDecimal.valueOf(0)}} method returns 0:DECIMAL(1,0). While trying to convert it to {{{}0.0: DECIMAL(1,1){}}}, we encounter an error:
{code:java}
Cannot convert 0 to DECIMAL(1, 1) due to overflow
java.lang.IllegalArgumentException: Cannot convert 0 to DECIMAL(1, 1) due to overflow
    at org.apache.calcite.rex.RexBuilder.makeLiteral(RexBuilder.java:1015)
    at org.apache.calcite.rex.RexProgramTest.testDecimalWithZero(RexProgramTest.java:2662) {code}
This is because {{intDigits > maxIntDigits}} [here|https://github.com/apache/calcite/blob/013f034dee3e24083760b4695e2eacfbf592c2cb/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java#L1812], which causes an exception [here|https://github.com/apache/calcite/blob/013f034dee3e24083760b4695e2eacfbf592c2cb/core/src/main/java/org/apache/calcite/rex/RexBuilder.java#L1015].

This can be reproduced by calling makeLiteral directly with a test in {{RexProgramTest}} like:
{code:java}
@Test void testDecimalWithZero() {
  RexLiteral literal = rexBuilder.makeLiteral(BigDecimal.valueOf(0),
      typeFactory.createSqlType(SqlTypeName.DECIMAL, 1, 1),
      SqlTypeName.DECIMAL);
  assertEquals(1, literal.getType().getPrecision());
  assertEquals(1, literal.getType().getScale());{code}
This doesn't fail if we add a test to {{{}SqlToRelConverterTest.java{}}}, like,
{code:java}
@Test void testDecimal() {
  final String sql = "select cast(cast(0 as decimal(1,0)) as decimal(1, 1))";
  sql(sql).ok();
} {code}
because the exception is caught and handled in [RexExecutable.java|https://github.com/apache/calcite/blob/013f034dee3e24083760b4695e2eacfbf592c2cb/core/src/main/java/org/apache/calcite/rex/RexExecutable.java#L96]. However, we see the exception if we directly call {{makeLiteral}} as shown above.

Ideally, this is fine, but I think ZERO should be a special case as 1 != 1.0 but 0 == 0.0

The simplest solution could be to modify the {{if}} block [here|https://github.com/apache/calcite/blob/013f034dee3e24083760b4695e2eacfbf592c2cb/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java#L1805] to 
{code:java}
if (value == null || value.equals(new BigDecimal("0")) {
      return true;
} {code}
 

  was:
The java {{BigDecimal.valueOf(0)}} method returns 0:DECIMAL(1,0). While trying to convert it to {{{}0.0: DECIMAL(1,1){}}}, we encounter an error:
{code:java}
Cannot convert 0 to DECIMAL(1, 1) due to overflow
java.lang.IllegalArgumentException: Cannot convert 0 to DECIMAL(1, 1) due to overflow
    at org.apache.calcite.rex.RexBuilder.makeLiteral(RexBuilder.java:1015)
    at org.apache.calcite.rex.RexProgramTest.testDecimalWithZero(RexProgramTest.java:2662) {code}
This is because {{intDigits > maxIntDigits}} [here|https://github.com/apache/calcite/blob/013f034dee3e24083760b4695e2eacfbf592c2cb/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java#L1812], which causes an exception [here|https://github.com/apache/calcite/blob/013f034dee3e24083760b4695e2eacfbf592c2cb/core/src/main/java/org/apache/calcite/rex/RexBuilder.java#L1015].

This can be reproduced by calling makeLiteral directly like:
{code:java}
@Test void testDecimalWithZero() {
  rexBuilder.makeLiteral(BigDecimal.valueOf(0),
      typeFactory.createSqlType(SqlTypeName.DECIMAL, 1, 1),
      SqlTypeName.DECIMAL);
} {code}
This doesn't fail if we add a test to {{{}SqlToRelConverterTest.java{}}}, like,
{code:java}
@Test void testDecimal() {
  final String sql = "select cast(cast(0 as decimal(1,0)) as decimal(1, 1))";
  sql(sql).ok();
} {code}
because the exception is caught and handled in [RexExecutable.java|https://github.com/apache/calcite/blob/013f034dee3e24083760b4695e2eacfbf592c2cb/core/src/main/java/org/apache/calcite/rex/RexExecutable.java#L96]. However, we see the exception if we directly call {{makeLiteral}} as shown above.

Ideally, this is fine, but I think ZERO should be a special case as 1 != 1.0 but 0 == 0.0

The simplest solution could be to modify the {{if}} block [here|https://github.com/apache/calcite/blob/013f034dee3e24083760b4695e2eacfbf592c2cb/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java#L1805] to 
{code:java}
if (value == null || value.equals(new BigDecimal("0")) {
      return true;
} {code}
 


> Error when trying to cast 0:DECIMAL(1,0) to 0:DECIMAL(1,1)
> ----------------------------------------------------------
>
>                 Key: CALCITE-5444
>                 URL: https://issues.apache.org/jira/browse/CALCITE-5444
>             Project: Calcite
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 1.33.0
>            Reporter: Soumyakanti Das
>            Assignee: Soumyakanti Das
>            Priority: Major
>
> The java {{BigDecimal.valueOf(0)}} method returns 0:DECIMAL(1,0). While trying to convert it to {{{}0.0: DECIMAL(1,1){}}}, we encounter an error:
> {code:java}
> Cannot convert 0 to DECIMAL(1, 1) due to overflow
> java.lang.IllegalArgumentException: Cannot convert 0 to DECIMAL(1, 1) due to overflow
>     at org.apache.calcite.rex.RexBuilder.makeLiteral(RexBuilder.java:1015)
>     at org.apache.calcite.rex.RexProgramTest.testDecimalWithZero(RexProgramTest.java:2662) {code}
> This is because {{intDigits > maxIntDigits}} [here|https://github.com/apache/calcite/blob/013f034dee3e24083760b4695e2eacfbf592c2cb/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java#L1812], which causes an exception [here|https://github.com/apache/calcite/blob/013f034dee3e24083760b4695e2eacfbf592c2cb/core/src/main/java/org/apache/calcite/rex/RexBuilder.java#L1015].
> This can be reproduced by calling makeLiteral directly with a test in {{RexProgramTest}} like:
> {code:java}
> @Test void testDecimalWithZero() {
>   RexLiteral literal = rexBuilder.makeLiteral(BigDecimal.valueOf(0),
>       typeFactory.createSqlType(SqlTypeName.DECIMAL, 1, 1),
>       SqlTypeName.DECIMAL);
>   assertEquals(1, literal.getType().getPrecision());
>   assertEquals(1, literal.getType().getScale());{code}
> This doesn't fail if we add a test to {{{}SqlToRelConverterTest.java{}}}, like,
> {code:java}
> @Test void testDecimal() {
>   final String sql = "select cast(cast(0 as decimal(1,0)) as decimal(1, 1))";
>   sql(sql).ok();
> } {code}
> because the exception is caught and handled in [RexExecutable.java|https://github.com/apache/calcite/blob/013f034dee3e24083760b4695e2eacfbf592c2cb/core/src/main/java/org/apache/calcite/rex/RexExecutable.java#L96]. However, we see the exception if we directly call {{makeLiteral}} as shown above.
> Ideally, this is fine, but I think ZERO should be a special case as 1 != 1.0 but 0 == 0.0
> The simplest solution could be to modify the {{if}} block [here|https://github.com/apache/calcite/blob/013f034dee3e24083760b4695e2eacfbf592c2cb/core/src/main/java/org/apache/calcite/sql/type/SqlTypeUtil.java#L1805] to 
> {code:java}
> if (value == null || value.equals(new BigDecimal("0")) {
>       return true;
> } {code}
>  



--
This message was sent by Atlassian Jira
(v8.20.10#820010)