suibianwanwank commented on code in PR #4023:
URL: https://github.com/apache/calcite/pull/4023#discussion_r1821391222


##########
core/src/main/java/org/apache/calcite/sql/validate/implicit/AbstractTypeCoercion.java:
##########
@@ -280,6 +280,13 @@ protected boolean needToCast(SqlValidatorScope scope, 
SqlNode node,
       return false;
     }
 
+    if (node.getKind() == SqlKind.LITERAL

Review Comment:
   I'm not particularly familiar with the parts of validator. Thanks for any 
advice. 
   Here's what I understand:
   In [CALCITE-5156], this part of the code is removed here to implement the 
implicit conversion of In. 
   ```  
    if (romType.getPrecedenceList().containsType(toType)
           && SqlTypeUtil.isIntType(fromType)
           && SqlTypeUtil.isIntType(toType)) {
         return false;
       }
   ```
   But for Literal, In will be converted to Value at ToRel, Value allows the 
type of Literal in Tuple to be not exactly the same as the type of Value 
(because for Literal, the type often depends on the external call). So the type 
takes precedence over Value. Therefore, the conversion of Literal is not 
necessary here, and is described in the code comment as follows
   ```
   private RexLiteral convertLiteral(SqlLiteral sqlLiteral,
       Blackboard bb, RelDataType type) {
     RexNode literalExpr = exprConverter.convertLiteral(bb, sqlLiteral);
   
     if (!(literalExpr instanceof RexLiteral)) {
       assert literalExpr.isA(SqlKind.CAST);
       RexNode child = ((RexCall) literalExpr).getOperands().get(0);
       assert RexLiteral.isNullLiteral(child);
   
       // NOTE jvs 22-Nov-2006:  we preserve type info
       // in LogicalValues digest, so it's OK to lose it here
       return (RexLiteral) child;
     }
   }
   ```
   And Literal will not be inferred as a smallint. 
   ```
     @Override public RelDataType createSqlType(RelDataTypeFactory typeFactory) 
{
       if (exact) {
         int scaleValue = requireNonNull(scale, "scale");
         if (0 == scaleValue) {
           try {
             BigDecimal bd = getValueNonNull();
             SqlTypeName result;
             // Will throw if the number cannot be represented as a long.
             long l = bd.longValueExact();
             if ((l >= Integer.MIN_VALUE) && (l <= Integer.MAX_VALUE)) {
               result = SqlTypeName.INTEGER;
             } else {
               result = SqlTypeName.BIGINT;
             }
             return typeFactory.createSqlType(result);
           } catch (ArithmeticException ex) {
             // This indicates that the value does not fit in any integer type.
             // Fallback to DECIMAL.
           }
         }
         // else we have a decimal
         return typeFactory.createSqlType(
             SqlTypeName.DECIMAL,
             requireNonNull(prec, "prec"),
             scaleValue);
       }
   ```
   Therefore, for an integer number that is always < Interger.MAX_VALUE, CAST 
is always added here if the function was originally inferred to not be an 
Integer.  This leads to the Bad Plan described in Jira.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to