[
https://issues.apache.org/jira/browse/CALCITE-4777?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17415431#comment-17415431
]
Ruben Q L commented on CALCITE-4777:
------------------------------------
Is casting decimal to boolean something standard? I just tried a similar query
in PostgreSQL and it did not work either (it failed more gracefully with a
message "ERROR: cannot cast type numeric to boolean"). Perhaps the proper way
to deal with this situation is using a {{CASE WHEN ...}} ?
> Casting from decimal to boolean throws an exception
> ---------------------------------------------------
>
> Key: CALCITE-4777
> URL: https://issues.apache.org/jira/browse/CALCITE-4777
> Project: Calcite
> Issue Type: Bug
> Reporter: xuyangzhong
> Priority: Major
>
> My sql is the following:
> {code:java}
> // code placeholder
> select * from test where cast (0.10915913549909961 as boolean){code}
>
> I want to simplify the cast. An exception is thrown:
>
> {code:java}
> // code placeholder
> Exception in thread "main" java.lang.RuntimeException: while resolving method
> 'booleanValue' in class class java.math.BigDecimal at
> org.apache.calcite.linq4j.tree.Expressions.call(Expressions.java:424) at
> org.apache.calcite.linq4j.tree.Expressions.call(Expressions.java:435) at
> org.apache.calcite.linq4j.tree.Expressions.unbox(Expressions.java:1453) at
> org.apache.calcite.adapter.enumerable.EnumUtils.convert(EnumUtils.java:398)
> at
> org.apache.calcite.adapter.enumerable.EnumUtils.convert(EnumUtils.java:326)
> at
> org.apache.calcite.adapter.enumerable.RexToLixTranslator.translateCast(RexToLixTranslator.java:543)
> at
> org.apache.calcite.adapter.enumerable.RexImpTable$CastImplementor.implementSafe(RexImpTable.java:2450)
> at
> org.apache.calcite.adapter.enumerable.RexImpTable$AbstractRexCallImplementor.genValueStatement(RexImpTable.java:2894)
> at
> org.apache.calcite.adapter.enumerable.RexImpTable$AbstractRexCallImplementor.implement(RexImpTable.java:2859)
> at
> org.apache.calcite.adapter.enumerable.RexToLixTranslator.visitCall(RexToLixTranslator.java:1089)
> at
> org.apache.calcite.adapter.enumerable.RexToLixTranslator.visitCall(RexToLixTranslator.java:90)
> at org.apache.calcite.rex.RexCall.accept(RexCall.java:174) at
> org.apache.calcite.adapter.enumerable.RexToLixTranslator.visitLocalRef(RexToLixTranslator.java:975)
> at
> org.apache.calcite.adapter.enumerable.RexToLixTranslator.visitLocalRef(RexToLixTranslator.java:90)
> at org.apache.calcite.rex.RexLocalRef.accept(RexLocalRef.java:75) at
> org.apache.calcite.adapter.enumerable.RexToLixTranslator.translate(RexToLixTranslator.java:237)
> at
> org.apache.calcite.adapter.enumerable.RexToLixTranslator.translate(RexToLixTranslator.java:231)
> at
> org.apache.calcite.adapter.enumerable.RexToLixTranslator.translateList(RexToLixTranslator.java:823)
> at
> org.apache.calcite.adapter.enumerable.RexToLixTranslator.translateProjects(RexToLixTranslator.java:198)
> at org.apache.calcite.rex.RexExecutorImpl.compile(RexExecutorImpl.java:90)
> at org.apache.calcite.rex.RexExecutorImpl.compile(RexExecutorImpl.java:66) at
> org.apache.calcite.rex.RexExecutorImpl.reduce(RexExecutorImpl.java:128) at
> org.apache.calcite.rex.RexSimplify.simplifyCast(RexSimplify.java:2101) at
> org.apache.calcite.rex.RexSimplify.simplify(RexSimplify.java:326) at
> org.apache.calcite.rex.RexSimplify.simplifyUnknownAs(RexSimplify.java:287) at
> org.apache.flink.table.examples.java.tests.CalciteTest.main(CalciteTest.java:47)
> Caused by: java.lang.NoSuchMethodException:
> java.math.BigDecimal.booleanValue() at
> java.lang.Class.getMethod(Class.java:1786) at
> org.apache.calcite.linq4j.tree.Expressions.call(Expressions.java:421) ... 25
> more
> {code}
> In order to avoid that I used the wrong rule or it caused by my bad coding, i
> write the test case following:
>
> {code:java}
> // code placeholder
> JavaTypeFactory typeFactory = new
> JavaTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
> RexBuilder rexBuilder = new RexBuilder(typeFactory);
> final RexSimplify simplify = new RexSimplify(rexBuilder,
> RelOptPredicateList.EMPTY, RexUtil.EXECUTOR);
> RelDataType type = new BasicSqlType(typeFactory.getTypeSystem(),
> SqlTypeName.BOOLEAN);
> RelDataType bb = new
> BasicSqlType(typeFactory.getTypeSystem(),SqlTypeName.DECIMAL,18,17);
> SqlOperator op = new SqlCastFunction();
> RexLiteral lt =
> rexBuilder.makeExactLiteral(BigDecimal.valueOf(0.10915913549909961),bb);
> List<RexNode> list = new ArrayList<>();
> list.add(lt);
> RexNode rexNode = rexBuilder.makeCall(type,op,list);
> simplify.simplifyUnknownAs(rexNode, RexUnknownAs.UNKNOWN);
> {code}
> and it throws the same exception.
>
> Actually, the cast simplify operation will enter the function _translateCast_
> in _RexToLixTranslator_.It misses the "case BOOLEAN" and uses the convert in
> EnumUtils. However, because the Decimal's Primitive is null and fromNumber is
> true, the Expression's function named "call" calls the "booleanValue"
> function in "java.math.BigDecimal", which does not actually exist. So the
> exception is thrown.
> I find in SqFunctions, we have a function "toBoolean(Number number)" (which
> seems never to be used?). This function may very fit dealing with this
> question, right?
>
--
This message was sent by Atlassian Jira
(v8.3.4#803005)