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]