[ https://issues.apache.org/jira/browse/CALCITE-6244?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Wegdan Ghazi updated CALCITE-6244: ---------------------------------- Summary: Improve `Expressions#constant` to allow Java records (was: Improve `Expressions#constant` to allow passing models with non-public fields) > Improve `Expressions#constant` to allow Java records > ---------------------------------------------------- > > Key: CALCITE-6244 > URL: https://issues.apache.org/jira/browse/CALCITE-6244 > Project: Calcite > Issue Type: Improvement > Components: linq4j > Reporter: Wegdan Ghazi > Assignee: Wegdan Ghazi > Priority: Minor > Fix For: 1.38.0 > > > 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)