Uploaded image for project: 'Calcite'
  1. Calcite
  2. CALCITE-5948

Use explicit casting if element type in ARRAY/MAP does not equal derived component type

    XMLWordPrintableJSON

Details

    Description

      First, we need to reach a consensus to allow types of the same family to coexist in multiset such as array and map.

      It means the form like `array(1, cast(2 as tinyint))` is correct(the LeastRestrictiveType is Integer). However, this function validate success in calcite but it failed in runtime, exception stack is:

      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 

       

      And `map[1, 1, 2, cast(1 as tinyint)]` is correct but calcite throw exception:

      java.lang.AssertionError: Expected query to throw exception, but it did not; query [values (map[1, 1, 2, cast(1 as tinyint)])]; expected [Parameters must be of the same type]
      	at org.apache.calcite.sql.test.SqlTests.checkEx(SqlTests.java:240)	at org.apache.calcite.sql.test.AbstractSqlTester.assertExceptionIsThrown(AbstractSqlTester.java:111)	at org.apache.calcite.test.SqlOperatorFixtureImpl.checkQueryFails(SqlOperatorFixtureImpl.java:174) 

       

      std ArrayConstructor.

      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);
        }
      } 

      std map constructor:

      public class SqlMapValueConstructor extends SqlMultisetValueConstructor {
        public SqlMapValueConstructor() {
          super("MAP", SqlKind.MAP_VALUE_CONSTRUCTOR);
        }
      
        @Override public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
          Pair<@Nullable RelDataType, @Nullable RelDataType> type =
              getComponentTypes(
                  opBinding.getTypeFactory(), opBinding.collectOperandTypes());
           --> we need explicit cast here   
           return SqlTypeUtil.createMapType(
              opBinding.getTypeFactory(),
              requireNonNull(type.left, "inferred key type"),
              requireNonNull(type.right, "inferred value type"),
              false);
        }
      }

      Attachments

        Issue Links

          Activity

            People

              taoran Ran Tao
              taoran Ran Tao
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: