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

Wegdan Ghazi updated CALCITE-6244:
----------------------------------
    Description: 
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.

  was:
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.

 

 


> 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
>            Priority: Minor
>
> 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