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

Zhengqiang Duan commented on CALCITE-5229:
------------------------------------------

Recently I did some investigation on this exception. First of all, the direct 
cause of this problem is that the filed in PositionedCursor is 
`Baz$Record5_1.empid`, and current() returns an `Emplyee` object, which makes 
an exception occur during reflection.

Second, I investigated the source of the field, which is created in the 
CalcitePrepareImpl class with the following code.
{code:java}
Class resultClazz = null;
if (preparedResult instanceof Typed) {
  resultClazz = (Class) ((Typed) preparedResult).getElementType();
}
final Meta.CursorFactory cursorFactory =
    preparingStmt.resultConvention == BindableConvention.INSTANCE
        ? Meta.CursorFactory.ARRAY
        : Meta.CursorFactory.deduce(columns, resultClazz); {code}
resultClazz determines the type of field, and resultClazz is obtained through 
bindable#getElementType. I compared the code generation results of PR#2848 and 
the main branch and found that the Record5_1 class was included in the results 
of PR#2848.
 * main branch code generate result:

{code:java}
public static class Record1_0 implements java.io.Serializable {
  public int f0;
  public Record1_0() {}
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof Record1_0)) {
      return false;
    }
    return this.f0 == ((Record1_0) o).f0;
  }

  public int hashCode() {
    int h = 0;
    h = org.apache.calcite.runtime.Utilities.hash(h, this.f0);
    return h;
  }

  public int compareTo(Record1_0 that) {
    final int c;
    c = org.apache.calcite.runtime.Utilities.compare(this.f0, that.f0);
    if (c != 0) {
      return c;
    }
    return 0;
  }

  public String toString() {
    return "{f0=" + this.f0 + "}";
  }

}

public org.apache.calcite.linq4j.Enumerable bind(final 
org.apache.calcite.DataContext root) {
  java.util.List accumulatorAdders = new java.util.LinkedList();
  accumulatorAdders.add(new org.apache.calcite.linq4j.function.Function2() {
    public Record1_0 apply(Record1_0 acc, 
org.apache.calcite.test.schemata.hr.Employee in) {
      acc.f0 = org.apache.calcite.runtime.SqlFunctions.greater(acc.f0, 
in.deptno);
      return acc;
    }
    public Record1_0 apply(Object acc, Object in) {
      return apply(
        (Record1_0) acc,
        (org.apache.calcite.test.schemata.hr.Employee) in);
    }
  }
  );
  org.apache.calcite.adapter.enumerable.AggregateLambdaFactory lambdaFactory = 
new org.apache.calcite.adapter.enumerable.BasicAggregateLambdaFactory(
    new org.apache.calcite.linq4j.function.Function0() {
      public Object apply() {
        int a0s0;
        a0s0 = -2147483648;
        Record1_0 record0;
        record0 = new Record1_0();
        record0.f0 = a0s0;
        return record0;
      }
    }
,
    accumulatorAdders);
  final org.apache.calcite.linq4j.Enumerable _inputEnumerable = 
org.apache.calcite.linq4j.Linq4j.asEnumerable(((org.apache.calcite.test.schemata.hr.HrSchema)
 ((org.apache.calcite.adapter.java.ReflectiveSchema) 
root.getRootSchema().getSubSchema("hr").unwrap(org.apache.calcite.adapter.java.ReflectiveSchema.class)).getTarget()).emps).groupBy(new
 org.apache.calcite.linq4j.function.Function1() {
    public int apply(org.apache.calcite.test.schemata.hr.Employee a0) {
      return a0.empid;
    }
    public Object apply(Object a0) {
      return apply(
        (org.apache.calcite.test.schemata.hr.Employee) a0);
    }
  }
  , lambdaFactory.accumulatorInitializer(), lambdaFactory.accumulatorAdder(), 
lambdaFactory.resultSelector(new org.apache.calcite.linq4j.function.Function2() 
{
    public Object[] apply(int key, Record1_0 acc) {
      return new Object[] {
          key,
          acc.f0};
    }
    public Object[] apply(Integer key, Record1_0 acc) {
      return apply(
        key.intValue(),
        acc);
    }
    public Object[] apply(Object key, Object acc) {
      return apply(
        (Integer) key,
        (Record1_0) acc);
    }
  }
  
)).hashJoin(org.apache.calcite.linq4j.Linq4j.asEnumerable(((org.apache.calcite.test.schemata.hr.HrSchema)
 ((org.apache.calcite.adapter.java.ReflectiveSchema) 
root.getRootSchema().getSubSchema("hr").unwrap(org.apache.calcite.adapter.java.ReflectiveSchema.class)).getTarget()).emps),
 new org.apache.calcite.linq4j.function.Function1() {
    public java.util.List apply(Object[] v1) {
      return 
org.apache.calcite.runtime.FlatLists.of(org.apache.calcite.runtime.SqlFunctions.toInt(v1[0]),
 org.apache.calcite.runtime.SqlFunctions.toInt(v1[1]));
    }
    public Object apply(Object v1) {
      return apply(
        (Object[]) v1);
    }
  }
  , new org.apache.calcite.linq4j.function.Function1() {
    public java.util.List apply(org.apache.calcite.test.schemata.hr.Employee 
v1) {
      return org.apache.calcite.runtime.FlatLists.of(v1.empid, v1.deptno);
    }
    public Object apply(Object v1) {
      return apply(
        (org.apache.calcite.test.schemata.hr.Employee) v1);
    }
  }
  , new org.apache.calcite.linq4j.function.Function2() {
    public Object[] apply(Object[] left, 
org.apache.calcite.test.schemata.hr.Employee right) {
      return new Object[] {
          left[0],
          left[1],
          right.empid,
          right.deptno,
          right.name,
          right.salary,
          right.commission};
    }
    public Object[] apply(Object left, Object right) {
      return apply(
        (Object[]) left,
        (org.apache.calcite.test.schemata.hr.Employee) right);
    }
  }
  , null, false, false, null);
  final org.apache.calcite.linq4j.AbstractEnumerable child = 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() {
            final Object[] current = (Object[]) inputEnumerator.current();
            final Object input_value = current[2];
            final Object input_value0 = current[3];
            final Object input_value1 = current[4];
            final Object input_value2 = current[5];
            final Object input_value3 = current[6];
            return new Object[] {
                input_value,
                input_value0,
                input_value1,
                input_value2,
                input_value3};
          }

        };
    }

  };
  return child.orderBy(new org.apache.calcite.linq4j.function.Function1() {
      public float apply(Object[] v) {
        return org.apache.calcite.runtime.SqlFunctions.toFloat(v[3]);
      }
      public Object apply(Object v) {
        return apply(
          (Object[]) v);
      }
    }
    , org.apache.calcite.linq4j.function.Functions.nullsComparator(false, 
false)).skip((Integer) root.get("?1")).take((Integer) root.get("?0"));
}


public Class getElementType() {
  return java.lang.Object[].class;
}
{code}
 * PR#2848 code generate result:

{code:java}
public static class Record1_0 implements java.io.Serializable {
  public int f0;
  public Record1_0() {}
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof Record1_0)) {
      return false;
    }
    return this.f0 == ((Record1_0) o).f0;
  }

  public int hashCode() {
    int h = 0;
    h = org.apache.calcite.runtime.Utilities.hash(h, this.f0);
    return h;
  }

  public int compareTo(Record1_0 that) {
    final int c;
    c = org.apache.calcite.runtime.Utilities.compare(this.f0, that.f0);
    if (c != 0) {
      return c;
    }
    return 0;
  }

  public String toString() {
    return "{f0=" + this.f0 + "}";
  }

}

public static class Record5_1 implements java.io.Serializable {
  public int empid;
  public int deptno;
  public String name;
  public float salary;
  public Integer commission;
  public Record5_1() {}
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof Record5_1)) {
      return false;
    }
    return this.empid == ((Record5_1) o).empid && this.deptno == ((Record5_1) 
o).deptno && java.util.Objects.equals(this.name, ((Record5_1) o).name) && 
this.salary == ((Record5_1) o).salary && 
java.util.Objects.equals(this.commission, ((Record5_1) o).commission);
  }

  public int hashCode() {
    int h = 0;
    h = org.apache.calcite.runtime.Utilities.hash(h, this.empid);
    h = org.apache.calcite.runtime.Utilities.hash(h, this.deptno);
    h = org.apache.calcite.runtime.Utilities.hash(h, this.name);
    h = org.apache.calcite.runtime.Utilities.hash(h, this.salary);
    h = org.apache.calcite.runtime.Utilities.hash(h, this.commission);
    return h;
  }

  public int compareTo(Record5_1 that) {
    int c;
    c = org.apache.calcite.runtime.Utilities.compare(this.empid, that.empid);
    if (c != 0) {
      return c;
    }
    c = org.apache.calcite.runtime.Utilities.compare(this.deptno, that.deptno);
    if (c != 0) {
      return c;
    }
    c = org.apache.calcite.runtime.Utilities.compareNullsLast(this.name, 
that.name);
    if (c != 0) {
      return c;
    }
    c = org.apache.calcite.runtime.Utilities.compare(this.salary, that.salary);
    if (c != 0) {
      return c;
    }
    c = org.apache.calcite.runtime.Utilities.compareNullsLast(this.commission, 
that.commission);
    if (c != 0) {
      return c;
    }
    return 0;
  }

  public String toString() {
    return "{empid=" + this.empid + ", deptno=" + this.deptno + ", name=" + 
this.name + ", salary=" + this.salary + ", commission=" + this.commission + "}";
  }

}

public org.apache.calcite.linq4j.Enumerable bind(final 
org.apache.calcite.DataContext root) {
  java.util.List accumulatorAdders = new java.util.LinkedList();
  accumulatorAdders.add(new org.apache.calcite.linq4j.function.Function2() {
    public Record1_0 apply(Record1_0 acc, 
org.apache.calcite.test.schemata.hr.Employee in) {
      acc.f0 = org.apache.calcite.runtime.SqlFunctions.greater(acc.f0, 
in.deptno);
      return acc;
    }
    public Record1_0 apply(Object acc, Object in) {
      return apply(
        (Record1_0) acc,
        (org.apache.calcite.test.schemata.hr.Employee) in);
    }
  }
  );
  org.apache.calcite.adapter.enumerable.AggregateLambdaFactory lambdaFactory = 
new org.apache.calcite.adapter.enumerable.BasicAggregateLambdaFactory(
    new org.apache.calcite.linq4j.function.Function0() {
      public Object apply() {
        int a0s0;
        a0s0 = -2147483648;
        Record1_0 record0;
        record0 = new Record1_0();
        record0.f0 = a0s0;
        return record0;
      }
    }
,
    accumulatorAdders);
  final java.util.Comparator comparator = new java.util.Comparator(){
    public int compare(Object[] v0, Object[] v1) {
      int c;
      c = 
org.apache.calcite.runtime.Utilities.compare(org.apache.calcite.runtime.SqlFunctions.toInt(v0[0]),
 org.apache.calcite.runtime.SqlFunctions.toInt(v1[0]));
      if (c != 0) {
        return c;
      }
      c = 
org.apache.calcite.runtime.Utilities.compare(org.apache.calcite.runtime.SqlFunctions.toInt(v0[1]),
 org.apache.calcite.runtime.SqlFunctions.toInt(v1[1]));
      if (c != 0) {
        return c;
      }
      return 0;
    }

    public int compare(Object o0, Object o1) {
      return this.compare((Object[]) o0, (Object[]) o1);
    }

  };
  return 
org.apache.calcite.linq4j.EnumerableDefaults.semiJoin(org.apache.calcite.linq4j.Linq4j.asEnumerable(((org.apache.calcite.test.schemata.hr.HrSchema)
 ((org.apache.calcite.adapter.java.ReflectiveSchema) 
root.getRootSchema().getSubSchema("hr").unwrap(org.apache.calcite.adapter.java.ReflectiveSchema.class)).getTarget()).emps),
 
org.apache.calcite.linq4j.Linq4j.asEnumerable(((org.apache.calcite.test.schemata.hr.HrSchema)
 ((org.apache.calcite.adapter.java.ReflectiveSchema) 
root.getRootSchema().getSubSchema("hr").unwrap(org.apache.calcite.adapter.java.ReflectiveSchema.class)).getTarget()).emps).groupBy(new
 org.apache.calcite.linq4j.function.Function1() {
      public int apply(org.apache.calcite.test.schemata.hr.Employee a0) {
        return a0.empid;
      }
      public Object apply(Object a0) {
        return apply(
          (org.apache.calcite.test.schemata.hr.Employee) a0);
      }
    }
    , lambdaFactory.accumulatorInitializer(), lambdaFactory.accumulatorAdder(), 
lambdaFactory.resultSelector(new org.apache.calcite.linq4j.function.Function2() 
{
      public Object[] apply(int key, Record1_0 acc) {
        return new Object[] {
            key,
            acc.f0};
      }
      public Object[] apply(Integer key, Record1_0 acc) {
        return apply(
          key.intValue(),
          acc);
      }
      public Object[] apply(Object key, Object acc) {
        return apply(
          (Integer) key,
          (Record1_0) acc);
      }
    }
    )).orderBy(org.apache.calcite.linq4j.function.Functions.identitySelector(), 
comparator), new org.apache.calcite.linq4j.function.Function1() {
      public java.util.List apply(org.apache.calcite.test.schemata.hr.Employee 
v1) {
        return org.apache.calcite.runtime.FlatLists.of(v1.empid, v1.deptno);
      }
      public Object apply(Object v1) {
        return apply(
          (org.apache.calcite.test.schemata.hr.Employee) v1);
      }
    }
    , new org.apache.calcite.linq4j.function.Function1() {
      public java.util.List apply(Object[] v1) {
        return 
org.apache.calcite.runtime.FlatLists.of(org.apache.calcite.runtime.SqlFunctions.toInt(v1[0]),
 org.apache.calcite.runtime.SqlFunctions.toInt(v1[1]));
      }
      public Object apply(Object v1) {
        return apply(
          (Object[]) v1);
      }
    }
    , null, null).orderBy(new org.apache.calcite.linq4j.function.Function1() {
      public float apply(org.apache.calcite.test.schemata.hr.Employee v) {
        return v.salary;
      }
      public Object apply(Object v) {
        return apply(
          (org.apache.calcite.test.schemata.hr.Employee) v);
      }
    }
    , org.apache.calcite.linq4j.function.Functions.nullsComparator(false, 
false)).skip((Integer) root.get("?1")).take((Integer) root.get("?0"));
}


public Class getElementType() {
  return Record5_1.class;
}
{code}
I'll keep working on the code generation logic to try and fix this.

> JdbcTest#testDynamicParameterInLimitOffset throws IllegalArgumentException
> --------------------------------------------------------------------------
>
>                 Key: CALCITE-5229
>                 URL: https://issues.apache.org/jira/browse/CALCITE-5229
>             Project: Calcite
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 1.31.0
>            Reporter: Benchao Li
>            Assignee: Zhengqiang Duan
>            Priority: Major
>
> After CALCITE-5201, this test will fail because we can transform more cases 
> to semi join, and the physical type for some {{EnumerableRel}}s is wrong, we 
> should fix them.
> See https://github.com/apache/calcite/pull/2848/files#r913566595
> {code:java}
> java.lang.IllegalArgumentException: Can not set int field Baz$Record5_1.empid 
> to null value
> java.sql.SQLException: java.lang.IllegalArgumentException: Can not set int 
> field Baz$Record5_1.empid to null value
>       at 
> org.apache.calcite.avatica.util.PositionedCursor$FieldGetter.getObject(PositionedCursor.java:132)
>       at 
> org.apache.calcite.avatica.util.AbstractCursor$AccessorImpl.getObject(AbstractCursor.java:357)
>       at 
> org.apache.calcite.avatica.util.AbstractCursor$AccessorImpl.getString(AbstractCursor.java:300)
>       at 
> org.apache.calcite.avatica.AvaticaResultSet.getString(AvaticaResultSet.java:241)
>       at 
> org.apache.calcite.test.CalciteAssert$ResultSetFormatter.rowToString(CalciteAssert.java:1986)
>       at 
> org.apache.calcite.test.CalciteAssert$ResultSetFormatter.resultSet(CalciteAssert.java:1972)
>       at 
> org.apache.calcite.test.CalciteAssert.lambda$checkResult$2(CalciteAssert.java:310)
>       at 
> org.apache.calcite.test.CalciteAssert.assertPrepare(CalciteAssert.java:631)
>       at 
> org.apache.calcite.test.CalciteAssert.access$700(CalciteAssert.java:149)
>       at 
> org.apache.calcite.test.CalciteAssert$AssertQuery.lambda$returns$1(CalciteAssert.java:1448)
>       at 
> org.apache.calcite.test.CalciteAssert$AssertQuery.withConnection(CalciteAssert.java:1384)
>       at 
> org.apache.calcite.test.CalciteAssert$AssertQuery.returns(CalciteAssert.java:1443)
>       at 
> org.apache.calcite.test.CalciteAssert$AssertQuery.returns(CalciteAssert.java:1433)
>       at 
> org.apache.calcite.test.CalciteAssert$AssertQuery.returns(CalciteAssert.java:1396)
>       at 
> org.apache.calcite.test.JdbcTest.testDynamicParameterInLimitOffset(JdbcTest.java:5448){code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to