[
https://issues.apache.org/jira/browse/CALCITE-5948?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Ran Tao updated CALCITE-5948:
-----------------------------
Description:
First, we need to reach a consensus to allow types of the same family to
coexist in array functions (calcite use SameOperandTypeChecker or
LeastRestrictiveType to support and implement this semantics).
It means the form like `{*}array(1, cast(2 as tinyint)){*}` is correct(the
LeastRestrictiveType is Integer).In fact, the most of mature engines such as
spark/hive/flink just also support this behavior. However, this function
validate success in calcite but it failed in runtime, exception stack is:
{code:java}
java.lang.ClassCastException: class java.lang.Byte cannot be cast to class
java.lang.Integer
at
org.apache.calcite.avatica.util.AbstractCursor$IntAccessor.getInt(AbstractCursor.java:522)
at
org.apache.calcite.avatica.util.AbstractCursor$ArrayAccessor.convertValue(AbstractCursor.java:1396)
at
org.apache.calcite.avatica.util.AbstractCursor$ArrayAccessor.getObject(AbstractCursor.java:1377)
at
org.apache.calcite.avatica.util.AbstractCursor$ArrayAccessor.getArray(AbstractCursor.java:1432)
at
org.apache.calcite.avatica.util.AbstractCursor$ArrayAccessor.getString(AbstractCursor.java:1444)
at
org.apache.calcite.avatica.AvaticaResultSet.getString(AvaticaResultSet.java:241)
at org.apache.calcite.util.JdbcTypeImpl$10.get(JdbcTypeImpl.java:112)
at org.apache.calcite.util.JdbcTypeImpl$10.get(JdbcTypeImpl.java:109)
at
org.apache.calcite.sql.test.ResultCheckers.compareResultSetWithMatcher(ResultCheckers.java:248)
at
org.apache.calcite.sql.test.ResultCheckers$MatcherResultChecker.checkResult(ResultCheckers
{code}
e.g. and more array functions failed in runtime when use element cast.
{code:java}
//java.lang.ClassCastException: java.lang.Byte cannot be cast to
java.lang.Integer
select array(1, cast(2 as tinyint))
// java.lang.ClassCastException: java.lang.Integer cannot be cast to
java.lang.Long
select array_prepend(array[1, cast(2 as bigint)], 3)
select array_prepend(array[1, 2], cast(3 as bigint))
// java.lang.ClassCastException: java.lang.Short cannot be cast to
java.lang.Integer
select array_append(array[1, cast(2 as smallint)], 3)
select array_append(array[1, 2], cast(3 as smallint))
// java.lang.ClassCastException: java.lang.Integer cannot be cast to
java.lang.Long
select array_reverse(array[1, cast(2 as bigint)])
// java.lang.ClassCastException: java.lang.Short cannot be cast to
java.lang.Integer
array_distinct(array[1, 2, cast(2 as smallint), 1])
more functions failed... {code}
std ArrayConstructor.
{code:java}
public class SqlArrayValueConstructor extends SqlMultisetValueConstructor {
public SqlArrayValueConstructor() {
super("ARRAY", SqlKind.ARRAY_VALUE_CONSTRUCTOR);
}
@Override public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
RelDataType type =
getComponentType(
opBinding.getTypeFactory(),
opBinding.collectOperandTypes());
--> we need explicit cast here
requireNonNull(type, "inferred array element type");
return SqlTypeUtil.createArrayType(
opBinding.getTypeFactory(), type, false);
}
} {code}
spark library array
{code:java}
private static RelDataType arrayReturnType(SqlOperatorBinding opBinding) {
RelDataType type =
opBinding.getOperandCount() > 0
? ReturnTypes.LEAST_RESTRICTIVE.inferReturnType(opBinding)
: opBinding.getTypeFactory().createUnknownType();
--> we need explicit cast here
requireNonNull(type, "inferred array element type");
return SqlTypeUtil.createArrayType(opBinding.getTypeFactory(), type, false);
} {code}
was:
First, we need to reach a consensus to allow types of the same family to
coexist in array functions (calcite use SameOperandTypeChecker or
LeastRestrictiveType to support and implement this semantics).
It means the form like `{*}array(1, cast(2 as tinyint)){*}` is correct(the
LeastRestrictiveType is Integer).In fact, the most of mature engines such as
spark/hive/flink just also support this behavior. However, this function
validate success in calcite but it failed in runtime, exception stack is:
{code:java}
java.lang.ClassCastException: class java.lang.Byte cannot be cast to class
java.lang.Integer
at
org.apache.calcite.avatica.util.AbstractCursor$IntAccessor.getInt(AbstractCursor.java:522)
at
org.apache.calcite.avatica.util.AbstractCursor$ArrayAccessor.convertValue(AbstractCursor.java:1396)
at
org.apache.calcite.avatica.util.AbstractCursor$ArrayAccessor.getObject(AbstractCursor.java:1377)
at
org.apache.calcite.avatica.util.AbstractCursor$ArrayAccessor.getArray(AbstractCursor.java:1432)
at
org.apache.calcite.avatica.util.AbstractCursor$ArrayAccessor.getString(AbstractCursor.java:1444)
at
org.apache.calcite.avatica.AvaticaResultSet.getString(AvaticaResultSet.java:241)
at org.apache.calcite.util.JdbcTypeImpl$10.get(JdbcTypeImpl.java:112)
at org.apache.calcite.util.JdbcTypeImpl$10.get(JdbcTypeImpl.java:109)
at
org.apache.calcite.sql.test.ResultCheckers.compareResultSetWithMatcher(ResultCheckers.java:248)
at
org.apache.calcite.sql.test.ResultCheckers$MatcherResultChecker.checkResult(ResultCheckers
{code}
e.g. and more array functions failed in runtime when use element cast.
{code:java}
//java.lang.ClassCastException: java.lang.Byte cannot be cast to
java.lang.Integer
select array(1, cast(2 as tinyint))
// java.lang.ClassCastException: java.lang.Short cannot be cast to
java.lang.Integer
select array(1, cast(2 as smallint))
// java.lang.ClassCastException: java.lang.Integer cannot be cast to
java.lang.Long
select array(1, cast(2 as bigint))
// java.lang.ClassCastException: java.lang.Integer cannot be cast to
java.lang.Long
select array_prepend(array[1, cast(2 as bigint)], 3)
select array_prepend(array[1, 2], cast(3 as bigint))
// java.lang.ClassCastException: java.lang.Short cannot be cast to
java.lang.Integer
select array_append(array[1, cast(2 as smallint)], 3)
select array_append(array[1, 2], cast(3 as smallint))
// java.lang.ClassCastException: java.lang.Integer cannot be cast to
java.lang.Long
select array_reverse(array[1, cast(2 as bigint)])
// java.lang.ClassCastException: java.lang.Short cannot be cast to
java.lang.Integer
array_distinct(array[1, 2, cast(2 as smallint), 1])
more functions failed... {code}
the error code path(a part of them):
{code:java}
private static class IntAccessor extends ExactNumericAccessor {
private IntAccessor(Getter getter) {
super(getter);
}
public int getInt() throws SQLException {
Integer o = (Integer) super.getObject(); --> error logic
return o == null ? 0 : o;
}
public long getLong() throws SQLException {
return getInt();
}
}{code}
we may should fix it in calcite-avatica. and add more test cases to cover it in
calcite-main.
> Explicit casting should be made if the type of an element in ARRAY not equals
> with the derived component type
> -------------------------------------------------------------------------------------------------------------
>
> Key: CALCITE-5948
> URL: https://issues.apache.org/jira/browse/CALCITE-5948
> Project: Calcite
> Issue Type: Bug
> Components: avatica
> Affects Versions: 1.35.0
> Reporter: Ran Tao
> Assignee: Ran Tao
> Priority: Major
>
> First, we need to reach a consensus to allow types of the same family to
> coexist in array functions (calcite use SameOperandTypeChecker or
> LeastRestrictiveType to support and implement this semantics).
> It means the form like `{*}array(1, cast(2 as tinyint)){*}` is correct(the
> LeastRestrictiveType is Integer).In fact, the most of mature engines such as
> spark/hive/flink just also support this behavior. However, this function
> validate success in calcite but it failed in runtime, exception stack is:
> {code:java}
> java.lang.ClassCastException: class java.lang.Byte cannot be cast to class
> java.lang.Integer
> at
> org.apache.calcite.avatica.util.AbstractCursor$IntAccessor.getInt(AbstractCursor.java:522)
> at
> org.apache.calcite.avatica.util.AbstractCursor$ArrayAccessor.convertValue(AbstractCursor.java:1396)
> at
> org.apache.calcite.avatica.util.AbstractCursor$ArrayAccessor.getObject(AbstractCursor.java:1377)
> at
> org.apache.calcite.avatica.util.AbstractCursor$ArrayAccessor.getArray(AbstractCursor.java:1432)
> at
> org.apache.calcite.avatica.util.AbstractCursor$ArrayAccessor.getString(AbstractCursor.java:1444)
> at
> org.apache.calcite.avatica.AvaticaResultSet.getString(AvaticaResultSet.java:241)
> at org.apache.calcite.util.JdbcTypeImpl$10.get(JdbcTypeImpl.java:112)
> at org.apache.calcite.util.JdbcTypeImpl$10.get(JdbcTypeImpl.java:109)
> at
> org.apache.calcite.sql.test.ResultCheckers.compareResultSetWithMatcher(ResultCheckers.java:248)
> at
> org.apache.calcite.sql.test.ResultCheckers$MatcherResultChecker.checkResult(ResultCheckers
> {code}
> e.g. and more array functions failed in runtime when use element cast.
> {code:java}
> //java.lang.ClassCastException: java.lang.Byte cannot be cast to
> java.lang.Integer
> select array(1, cast(2 as tinyint))
> // java.lang.ClassCastException: java.lang.Integer cannot be cast to
> java.lang.Long
> select array_prepend(array[1, cast(2 as bigint)], 3)
> select array_prepend(array[1, 2], cast(3 as bigint))
> // java.lang.ClassCastException: java.lang.Short cannot be cast to
> java.lang.Integer
> select array_append(array[1, cast(2 as smallint)], 3)
> select array_append(array[1, 2], cast(3 as smallint))
> // java.lang.ClassCastException: java.lang.Integer cannot be cast to
> java.lang.Long
> select array_reverse(array[1, cast(2 as bigint)])
> // java.lang.ClassCastException: java.lang.Short cannot be cast to
> java.lang.Integer
> array_distinct(array[1, 2, cast(2 as smallint), 1])
> more functions failed... {code}
>
> std ArrayConstructor.
> {code:java}
> public class SqlArrayValueConstructor extends SqlMultisetValueConstructor {
> public SqlArrayValueConstructor() {
> super("ARRAY", SqlKind.ARRAY_VALUE_CONSTRUCTOR);
> }
> @Override public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
> RelDataType type =
> getComponentType(
> opBinding.getTypeFactory(),
> opBinding.collectOperandTypes());
> --> we need explicit cast here
> requireNonNull(type, "inferred array element type");
> return SqlTypeUtil.createArrayType(
> opBinding.getTypeFactory(), type, false);
> }
> } {code}
>
>
> spark library array
> {code:java}
> private static RelDataType arrayReturnType(SqlOperatorBinding opBinding) {
> RelDataType type =
> opBinding.getOperandCount() > 0
> ? ReturnTypes.LEAST_RESTRICTIVE.inferReturnType(opBinding)
> : opBinding.getTypeFactory().createUnknownType();
> --> we need explicit cast here
> requireNonNull(type, "inferred array element type");
> return SqlTypeUtil.createArrayType(opBinding.getTypeFactory(), type, false);
> } {code}
>
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)