You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@calcite.apache.org by "ASF GitHub Bot (Jira)" <ji...@apache.org> on 2020/01/10 11:22:00 UTC

[jira] [Updated] (CALCITE-3364) Can't group table function result due to a type cast error if table function returns a row with a single value

     [ https://issues.apache.org/jira/browse/CALCITE-3364?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

ASF GitHub Bot updated CALCITE-3364:
------------------------------------
    Labels: pull-request-available  (was: )

> Can't group table function result due to a type cast error if table function returns a row with a single value
> --------------------------------------------------------------------------------------------------------------
>
>                 Key: CALCITE-3364
>                 URL: https://issues.apache.org/jira/browse/CALCITE-3364
>             Project: Calcite
>          Issue Type: Bug
>    Affects Versions: 1.21.0
>            Reporter: Anton Haidai
>            Priority: Major
>              Labels: pull-request-available
>
> I was not able to find a suitable test, so I'll describe the issue using a custom minimal table function returning a row with a single value as an example. I believe, that it should be reproducible against any table function.
> There is a simple table function my_dummy() that just prints numbers 1 to 5. Simple select works as expected:
> {code}
> SQL:
> select val from table(my_dummy())
> Result:
> val : INTEGER
> 5
> 4
> 3
> 2
> 1
> {code}
> However, when trying to make an aggregation on top of it, there is a class cast error:
> {code}
> SQL:
> select val from table(my_dummy())
> group by val
> Error:
> java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to java.lang.Integer
> 	at org.apache.calcite.avatica.util.AbstractCursor$IntAccessor.getInt(AbstractCursor.java:541)
> 	at org.apache.calcite.avatica.AvaticaSite.get(AvaticaSite.java:340)
> 	at org.apache.calcite.avatica.AvaticaResultSet.getObject(AvaticaResultSet.java:393)
> {code}
> Actually, this array Object[] contains a single integer produced by the table function. Also I faced similar class cast errors in a generated code making hashJoin (in a complex production code), I believe, the cause should be the same as in this minimal example.
> Here is this my_dummy() table function implementation (single file):
> {code}
> package com.myapp.tf;
> import org.apache.calcite.DataContext;
> import org.apache.calcite.linq4j.AbstractEnumerable;
> import org.apache.calcite.linq4j.Enumerable;
> import org.apache.calcite.linq4j.Enumerator;
> import org.apache.calcite.linq4j.tree.Types;
> import org.apache.calcite.rel.type.RelDataType;
> import org.apache.calcite.rel.type.RelDataTypeFactory;
> import org.apache.calcite.schema.ScannableTable;
> import org.apache.calcite.schema.TableFunction;
> import org.apache.calcite.schema.impl.AbstractTable;
> import org.apache.calcite.schema.impl.TableFunctionImpl;
> import org.apache.calcite.sql.SqlIdentifier;
> import org.apache.calcite.sql.SqlOperatorBinding;
> import org.apache.calcite.sql.parser.SqlParserPos;
> import org.apache.calcite.sql.type.SqlTypeName;
> import org.apache.calcite.sql.validate.SqlUserDefinedTableFunction;
> import java.util.Collections;
> import java.util.concurrent.atomic.AtomicInteger;
> import static org.apache.calcite.sql.type.OperandTypes.family;
> public class DummyFunction extends SqlUserDefinedTableFunction {
>     public static String DUMMY_FUNCTION_NAME = "my_dummy";
>     public static final TableFunction DUMMY_TABLE_FUNCTION = TableFunctionImpl.create(Types.lookupMethod(
>         DummyFunction.class,
>         "createDummyTable"
>     ));
>     public static DummyTable createDummyTable() {
>         return new DummyTable();
>     }
>     public DummyFunction() {
>         super(new SqlIdentifier(DUMMY_FUNCTION_NAME, SqlParserPos.ZERO),
>             null,
>             null,
>             family(),
>             Collections.emptyList(),
>             DUMMY_TABLE_FUNCTION
>         );
>     }
>     @Override
>     public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
>         RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
>         return typeFactory.builder()
>             .add("val", SqlTypeName.INTEGER)
>             .build();
>     }
> }
> class DummyTable extends AbstractTable implements ScannableTable {
>     private final AtomicInteger cnt = new AtomicInteger(6);
>     @Override
>     public Enumerable<Object[]> scan(DataContext root) {
>         return new AbstractEnumerable<Object[]>() {
>             public Enumerator<Object[]> enumerator() {
>                 return new Enumerator<Object[]> () {
>                     @Override
>                     public Object[] current() {
>                         return new Object[] { cnt.intValue() };
>                     }
>                     @Override
>                     public boolean moveNext() {
>                         return cnt.decrementAndGet() > 0;
>                     }
>                     @Override
>                     public void reset() {
>                     }
>                     @Override
>                     public void close() {
>                     }
>                 };
>             }
>         };
>     }
>     @Override
>     public RelDataType getRowType(RelDataTypeFactory typeFactory) {
>         return typeFactory.builder()
>             .add("val", SqlTypeName.INTEGER)
>             .build();
>     }
> }
> {code}
> And adding it into a schema:
> {code}
> mySchemaPlus.add(DUMMY_FUNCTION_NAME, DummyFunction.DUMMY_TABLE_FUNCTION);
> {code}



--
This message was sent by Atlassian Jira
(v8.3.4#803005)