[ 
https://issues.apache.org/jira/browse/CALCITE-3216?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16893969#comment-16893969
 ] 

Laurent Goujon edited comment on CALCITE-3216 at 7/26/19 4:32 PM:
------------------------------------------------------------------

The problem is likely to be common to any set operator: if the children of the 
operator are compatible but not exactly the same, the operator row type is the 
least restrictive of all the input types. But as far as I can tell, during 
execution, Calcite execution engine doesn't coerce the the records generated by 
the operator to match the row type, causing issues for parent operators as 
their physical representation do not match the expected type.

It's easy to spot in the generated source code:
{code:java}
/*   1 */ public org.apache.calcite.linq4j.Enumerable bind(final 
org.apache.calcite.DataContext root) {
/*   2 */   final org.apache.calcite.linq4j.Enumerable _inputEnumerable = 
org.apache.calcite.linq4j.Linq4j.asEnumerable(new Integer[] {
/*   3 */     0});
/*   4 */   final org.apache.calcite.linq4j.AbstractEnumerable child0 = new 
org.apache.calcite.linq4j.AbstractEnumerable(){
/*   5 */     public org.apache.calcite.linq4j.Enumerator enumerator() {
/*   6 */       return new org.apache.calcite.linq4j.Enumerator(){
/*   7 */           public final org.apache.calcite.linq4j.Enumerator 
inputEnumerator = _inputEnumerable.enumerator();
/*   8 */           public void reset() {
/*   9 */             inputEnumerator.reset();
/*  10 */           }
/*  11 */ 
/*  12 */           public boolean moveNext() {
/*  13 */             return inputEnumerator.moveNext();
/*  14 */           }
/*  15 */ 
/*  16 */           public void close() {
/*  17 */             inputEnumerator.close();
/*  18 */           }
/*  19 */ 
/*  20 */           public Object current() {
/*  21 */             return (byte)1;
/*  22 */           }
/*  23 */ 
/*  24 */         };
/*  25 */     }
/*  26 */ 
/*  27 */   };
/*  28 */   int prevStart;
/*  29 */   int prevEnd;
/*  30 */   final java.util.Comparator comparator = new java.util.Comparator(){
/*  31 */     public int compare(Integer v0, Integer v1) {
/*  32 */       int c;
/*  33 */       return 0;
/*  34 */     }
/*  35 */ 
/*  36 */     public int compare(Object o0, Object o1) {
/*  37 */       return this.compare((Integer) o0, (Integer) o1);
/*  38 */     }
/*  39 */ 
/*  40 */   };
/*  41 */   final org.apache.calcite.runtime.SortedMultiMap multiMap = new 
org.apache.calcite.runtime.SortedMultiMap();
/*  42 */   child0.union(org.apache.calcite.linq4j.Linq4j.asEnumerable(new 
Integer[] {
/*  43 */     2})).foreach(new org.apache.calcite.linq4j.function.Function1() {
/*  44 */     public Object apply(int v) {
/*  45 */       int key = v;
/*  46 */       multiMap.putMulti(key, v);
/*  47 */       return null;
/*  48 */     }
/*  49 */     public Object apply(Integer v) {
/*  50 */       return apply(
/*  51 */         v.intValue());
/*  52 */     }
/*  53 */     public Object apply(Object v) {
/*  54 */       return apply(
/*  55 */         (Integer) v);
/*  56 */     }
/*  57 */   }
/*  58 */   );
/*  59 */   final java.util.Iterator iterator = multiMap.arrays(comparator);
/*  60 */   final java.util.ArrayList _list = new java.util.ArrayList(
/*  61 */     multiMap.size());
/*  62 */   Long COUNTa0w0 = (Long) null;
/*  63 */   while (iterator.hasNext()) {
/*  64 */     final Object[] _rows = (Object[]) iterator.next();
/*  65 */     prevStart = -1;
/*  66 */     prevEnd = 2147483647;
/*  67 */     final int maxX = _rows.length - 1;
/*  68 */     for (int i = 0; i < _rows.length; ++i) {
/*  69 */       if (maxX != prevEnd) {
/*  70 */         int actualStart = maxX < prevEnd ? 0 : prevEnd + 1;
/*  71 */         prevEnd = maxX;
/*  72 */         COUNTa0w0 = Long.valueOf(maxX + 1);
/*  73 */       }
/*  74 */       _list.add(new Object[] {
/*  75 */         org.apache.calcite.runtime.SqlFunctions.toInt(_rows[i]),
/*  76 */         COUNTa0w0});
/*  77 */     }
/*  78 */   }
/*  79 */   multiMap.clear();
/*  80 */   return org.apache.calcite.linq4j.Linq4j.asEnumerable(_list);
/*  81 */ }
/*  82 */ 
/*  83 */ 
/*  84 */ public Class getElementType() {
/*  85 */   return java.lang.Object[].class;
/*  86 */ }
{code}

Alas, I'm not familiar at all with the execution engine, and have no idea what 
the fix should look like.


was (Author: laurentgo):
The problem is likely to be common to any set operator: if the children of the 
operator are compatible but not exactly the same, the operator row type is the 
least restrictive of all the input types. But as far as I can tell, during 
execution, Calcite execution engine doesn't coerce the the records generated by 
the operator to match the row type, causing issues for parent operators as 
their physical representation do not match the expected type.

It's easy to spot in the generated source code:
{code:java}
 public org.apache.calcite.linq4j.Enumerable bind(final 
org.apache.calcite.DataContext root) {
   final org.apache.calcite.linq4j.Enumerable _inputEnumerable = 
org.apache.calcite.linq4j.Linq4j.asEnumerable(new Integer[] {
     0});
   final org.apache.calcite.linq4j.AbstractEnumerable child0 = new 
org.apache.calcite.linq4j.AbstractEnumerable(){
     public org.apache.calcite.linq4j.Enumerator enumerator() {
       return new org.apache.calcite.linq4j.Enumerator(){
           public final org.apache.calcite.linq4j.Enumerator inputEnumerator = 
_inputEnumerable.enumerator();
           public void reset() { 
             inputEnumerator.reset();
           }         
 
           public boolean moveNext() {
             return inputEnumerator.moveNext();
           }         
 
           public void close() { 
             inputEnumerator.close();
           }         
 
           public Object current() {
             return (byte)1;
           }         
 
         };        
     }
 
   };
   final org.apache.calcite.linq4j.Enumerable _inputEnumerable0 = 
child0.union(org.apache.calcite.linq4j.Linq4j.asEnumerable(new Integer[] {
     2}));
   return new org.apache.calcite.linq4j.AbstractEnumerable(){
       public org.apache.calcite.linq4j.Enumerator enumerator() {
         return new org.apache.calcite.linq4j.Enumerator(){
             public final org.apache.calcite.linq4j.Enumerator inputEnumerator 
= _inputEnumerable0.enumerator();
             public void reset() { 
               inputEnumerator.reset();
             }         
 
             public boolean moveNext() {
               return inputEnumerator.moveNext();
             }         
 
             public void close() { 
               inputEnumerator.close();
             }         
 
             public Object current() {
               return 
org.apache.calcite.runtime.SqlFunctions.toInt(inputEnumerator.current()) * 2;
             }         
 
           };        
       }
 
     };
 }
 
 
 public Class getElementType() {
   return int.class;
 }
{code}

Alas, I'm not familiar at all with the execution engine, and have no idea what 
the fix should look like.

> ClassCastException when running window function over union
> ----------------------------------------------------------
>
>                 Key: CALCITE-3216
>                 URL: https://issues.apache.org/jira/browse/CALCITE-3216
>             Project: Calcite
>          Issue Type: Bug
>          Components: core
>            Reporter: Laurent Goujon
>            Priority: Major
>
> I discovered an issue in Calcite execution engine which can be captured by 
> this simple query:
> {code:sql}
> select *, count(*) over (partition by "id") from (
> select "id" from (VALUES(CAST(1 AS TINYINT))) "foo"("id")
> union
> select "id" from (VALUES(2)) "foo"("id"))
> {code}
> When running this query using JdbcTest for example, I got the following 
> stacktrace:
> {noformat}
> Caused by: java.lang.ClassCastException: java.lang.Byte cannot be cast to 
> java.lang.Integer
>       at Baz$3.apply(ANONYMOUS.java:55)
>       at 
> org.apache.calcite.linq4j.DefaultEnumerable.foreach(DefaultEnumerable.java:77)
>       at Baz.bind(Baz.java:43)
>       at 
> org.apache.calcite.jdbc.CalcitePrepare$CalciteSignature.enumerable(CalcitePrepare.java:355)
>       at 
> org.apache.calcite.jdbc.CalciteConnectionImpl.enumerable(CalciteConnectionImpl.java:316)
>       at 
> org.apache.calcite.jdbc.CalciteMetaImpl._createIterable(CalciteMetaImpl.java:506)
>       at 
> org.apache.calcite.jdbc.CalciteMetaImpl.createIterable(CalciteMetaImpl.java:497)
>       at 
> org.apache.calcite.avatica.AvaticaResultSet.execute(AvaticaResultSet.java:182)
>       at 
> org.apache.calcite.jdbc.CalciteResultSet.execute(CalciteResultSet.java:64)
>       at 
> org.apache.calcite.jdbc.CalciteResultSet.execute(CalciteResultSet.java:1)
>       at 
> org.apache.calcite.avatica.AvaticaConnection$1.execute(AvaticaConnection.java:667)
>       at 
> org.apache.calcite.jdbc.CalciteMetaImpl.prepareAndExecute(CalciteMetaImpl.java:566)
>       at 
> org.apache.calcite.avatica.AvaticaConnection.prepareAndExecuteInternal(AvaticaConnection.java:675)
>       at 
> org.apache.calcite.avatica.AvaticaStatement.executeInternal(AvaticaStatement.java:156)
> {noformat}



--
This message was sent by Atlassian JIRA
(v7.6.14#76016)

Reply via email to