Wegdan Ghazi created CALCITE-6244:
-------------------------------------

             Summary: Improve `Expressions#constant` to allow passing models 
with non-public fields
                 Key: CALCITE-6244
                 URL: https://issues.apache.org/jira/browse/CALCITE-6244
             Project: Calcite
          Issue Type: Improvement
          Components: avatica
            Reporter: Wegdan Ghazi
            Assignee: Wegdan Ghazi


To use 
[Expressions#constant|https://github.com/apache/calcite/blob/e17098d47f3c31e4d90cc17e6e1da1175bf49ae4/linq4j/src/main/java/org/apache/calcite/linq4j/tree/Expressions.java#L540]
 with complex models, it's required to pass a model with public fields, as can 
be seen in this 
[test|https://github.com/apache/calcite/blob/e17098d47f3c31e4d90cc17e6e1da1175bf49ae4/linq4j/src/test/java/org/apache/calcite/linq4j/test/ExpressionTest.java#L865].

i.e. to successfully pass an instance of `Employee`, it must be defined as 
follows:

 
{code:java}
public static class Employee {
    public final int empno;
    public final String name;
    public final int deptno;    public Employee(int empno, String name, int 
deptno) {
      this.empno = empno;
      this.name = name;
      this.deptno = deptno;
    }    public String toString() {
      return "Employee(name: " + name + ", deptno:" + deptno + ")";
    }    @Override public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + deptno;
      result = prime * result + empno;
      result = prime * result + ((name == null) ? 0 : name.hashCode());
      return result;
    }    @Override public boolean equals(Object obj) {
      if (this == obj) {
        return true;
      }
      if (obj == null) {
        return false;
      }
      if (getClass() != obj.getClass()) {
        return false;
      }
      Employee other = (Employee) obj;
      if (deptno != other.deptno) {
        return false;
      }
      if (empno != other.empno) {
        return false;
      }
      if (name == null) {
        if (other.name != null) {
          return false;
        }
      } else if (!name.equals(other.name)) {
        return false;
      }
      return true;
    }
  } {code}
This makes it difficult to use generated classes e.g. Java records or 
immutables, or even encapsulated POJOs to pass through Linq4j.

 

This is caused by the logic to 
[explore|https://github.com/apache/calcite/blob/e17098d47f3c31e4d90cc17e6e1da1175bf49ae4/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstantExpression.java#L299]
 and 
[create|https://github.com/apache/calcite/blob/e17098d47f3c31e4d90cc17e6e1da1175bf49ae4/linq4j/src/main/java/org/apache/calcite/linq4j/tree/ConstantExpression.java#L216]
 the model constructor; which depends on:

 
{code:java}
value.getClass().getFields() {code}
which only accesses public fields.

{*}Proposed solution{*}: Access fields using reflection, by accessing their 
getter methods.

 

 



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

Reply via email to