[jira] [Created] (CALCITE-6245) Permute operands of SqlCall everywhere when validating and Converting to Rel

2024-02-05 Thread Feng Jin (Jira)
Feng Jin created CALCITE-6245:
-

 Summary: Permute operands of SqlCall everywhere when validating 
and Converting to Rel
 Key: CALCITE-6245
 URL: https://issues.apache.org/jira/browse/CALCITE-6245
 Project: Calcite
  Issue Type: Bug
Reporter: Feng Jin


Currently, when using named parameters, there may be some issues due to the 
incorrect expansion of named parameters during validation. Specifically, 
several unit tests can be added to reproduce this.


add a test case org.apache.calcite.test.UdfTest#testScalarFunctionWithParameter
{code:java}
  @Test void testScalarFunctionWithParameter() {
final String sql = "select \"adhoc\".my_det_plus(X => \"deptno\", Y => 100) 
as p\n"
+ "from \"adhoc\".EMPLOYEES";
final AtomicInteger c = 
Smalls.MyDeterministicPlusFunction.INSTANCE_COUNT.get();
final int before = c.get();
withUdf().query(sql).returnsUnordered("P=110",
"P=120",
"P=110",
"P=110");
final int after = c.get();
assertThat(after, is(before + 1));
  }
{code}

And we will get the following error:


{code:shell}
java.sql.SQLException: Error while executing SQL "select "adhoc".my_det_plus(x 
=> "deptno", y => 100) as p
from "adhoc".EMPLOYEES": At line 1, column 28: Column 'X' not found in any table
at org.apache.calcite.avatica.Helper.createException(Helper.java:56)
at org.apache.calcite.avatica.Helper.createException(Helper.java:41)
at 
org.apache.calcite.avatica.AvaticaStatement.executeInternal(AvaticaStatement.java:164)
at 
org.apache.calcite.avatica.AvaticaStatement.executeQuery(AvaticaStatement.java:228)
at 
org.apache.calcite.test.CalciteAssert.assertQuery(CalciteAssert.java:543)
at 
org.apache.calcite.test.CalciteAssert$AssertQuery.lambda$returns$1(CalciteAssert.java:1455)
at 
org.apache.calcite.test.CalciteAssert$AssertQuery.withConnection(CalciteAssert.java:1394)
at 
org.apache.calcite.test.CalciteAssert$AssertQuery.returns(CalciteAssert.java:1453)
at 
org.apache.calcite.test.CalciteAssert$AssertQuery.returns(CalciteAssert.java:1443)
at 
org.apache.calcite.test.CalciteAssert$AssertQuery.returnsUnordered(CalciteAssert.java:1465)
at 
org.apache.calcite.test.UdfTest.testScalarFunctionWithParameter(UdfTest.java:227)
{code}


another test case:

org.apache.calcite.test.UdfTest#testAggFunctionWithParameter
{code:java}
  @Test void testAggFunctionWithParameter() {
final String empDept = JdbcTest.EmpDeptTableFactory.class.getName();
final String sum = Smalls.MyStaticSumFunction.class.getName();
final String sum2 = Smalls.MySumFunction.class.getName();
final CalciteAssert.AssertThat with = CalciteAssert.model("{\n"
+ "  version: '1.0',\n"
+ "   schemas: [\n"
+ " {\n"
+ "   name: 'adhoc',\n"
+ "   tables: [\n"
+ " {\n"
+ "   name: 'EMPLOYEES',\n"
+ "   type: 'custom',\n"
+ "   factory: '" + empDept + "',\n"
+ "   operand: {'foo': true, 'bar': 345}\n"
+ " }\n"
+ "   ],\n"
+ "   functions: [\n"
+ " {\n"
+ "   name: 'MY_SUM',\n"
+ "   className: '" + sum + "'\n"
+ " },\n"
+ " {\n"
+ "   name: 'MY_SUM2',\n"
+ "   className: '" + sum2 + "'\n"
+ " }\n"
+ "   ]\n"
+ " }\n"
+ "   ]\n"
+ "}")
.withDefaultSchema("adhoc")
.with("caseSensitive", false);
with.withDefaultSchema(null)
.query(
"select \"adhoc\".my_sum(arg1  => \"deptno\") as p from 
\"adhoc\".EMPLOYEES\n")
.returns("P=50\n");
  }
{code}

And we will get the following error:


{code:shell}
// Some comments here
Caused by: org.apache.calcite.runtime.CalciteContextException: From line 1, 
column 23 to line 1, column 26: Column 'ARG1' not found in any table
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at 
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at 
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at 
org.apache.calcite.runtime.Resources$ExInstWithCause.ex(Resources.java:505)
at org.apache.calcite.sql.SqlUtil.newContextException(SqlUtil.java:945)
at org.apache.calcite.sql.SqlUtil.newContextException(SqlUtil.java:930)
at 
org.apache.calcite.sql.validate.SqlValidatorImpl.newValidationError(SqlValidatorImpl.java:5470)
at 

[jira] [Updated] (CALCITE-6238) Exception while evaluating ROUND function

2024-02-05 Thread ASF GitHub Bot (Jira)


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

ASF GitHub Bot updated CALCITE-6238:

Labels: pull-request-available  (was: )

> Exception while evaluating ROUND function
> -
>
> Key: CALCITE-6238
> URL: https://issues.apache.org/jira/browse/CALCITE-6238
> Project: Calcite
>  Issue Type: Bug
>  Components: core
>Affects Versions: 1.36.0
>Reporter: Mihai Budiu
>Priority: Minor
>  Labels: pull-request-available
>
> The following test in CalciteSqlOperatorTest:
> {code:java}
>  @Test void testRoundFunc() {
> final SqlOperatorFixture f = fixture();
> f.checkScalar("round(42, CAST(2 as BIGINT))", 42, "INTEGER NOT NULL");
>   }
> {code}
> causes an exception; here is the relevant part of the stack trace:
> {code}
> java.sql.SQLException: Error while executing SQL "values (round(42, CAST(2 as 
> BIGINT)))": Unable to implement EnumerableCalc(expr#0=[{inputs}], 
> expr#1=[42], expr#2=[2:BIGINT], expr#3=[ROUND($t1, $t2)], EXPR$0=[$t3]): 
> rowcount = 1.0, cumulative cost = {2.0 rows, 6.0 cpu, 0.0 io}, id = 20
>   EnumerableValues(tuples=[[{ 0 }]]): rowcount = 1.0, cumulative cost = {1.0 
> rows, 1.0 cpu, 0.0 io}, id = 13
> ...
>   Suppressed: java.lang.RuntimeException: while resolving method 
> 'sround[int, long]' in class class org.apache.calcite.runtime.SqlFunctions
>   at 
> org.apache.calcite.adapter.enumerable.EnumUtils.call(EnumUtils.java:679)
>   at 
> org.apache.calcite.adapter.enumerable.RexImpTable$MethodImplementor.call(RexImpTable.java:2818)
>   at 
> org.apache.calcite.adapter.enumerable.RexImpTable$MethodImplementor.implementSafe(RexImpTable.java:2799)
>   at 
> org.apache.calcite.adapter.enumerable.RexImpTable$AbstractRexCallImplementor.genValueStatement(RexImpTable.java:3857)
>   at 
> org.apache.calcite.adapter.enumerable.RexImpTable$AbstractRexCallImplementor.implement(RexImpTable.java:3819)
> {code}
> And indeed, SqlFunctions does not have a function sround with this signature.
> There are several possible fixes:
> - reject calls to ROUND that have a BIGINT second argument
> - have the validator insert an implicit cast for the second argument to 
> INTEGER
> - implement more Java versions of the SROUND function in SqlFunctions. 
> Probably many more.
> Which one of these is the right one? I suspect this problem applies to other 
> SQL functions as well.



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


[jira] [Commented] (CALCITE-6240) Remove ROW_NUMBER if OVER PARTITION BY unique key

2024-02-05 Thread Julian Hyde (Jira)


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

Julian Hyde commented on CALCITE-6240:
--

Also related to CALCITE-5406, because
{code:java}
SELECT DISTINCT ON (x)
  x, y, z
FROM t{code}
is equivalent to
{code:java}
SELECT x, y, z
FROM (
SELECT x, y, z, ROW_NUMBER() OVER (PARTITION BY x) AS r
FROM t)
WHERE r = 1{code}

> Remove ROW_NUMBER if OVER PARTITION BY unique key
> -
>
> Key: CALCITE-6240
> URL: https://issues.apache.org/jira/browse/CALCITE-6240
> Project: Calcite
>  Issue Type: Improvement
>  Components: core
>Reporter: Jiajun Xie
>Assignee: Jiajun Xie
>Priority: Minor
>
> The SQL Only have ROW_NUMBER function.
> {code:java}
> SELECT empno, ename FROM ( 
>    SELECT ROW_NUMBER() OVER (PARTITION BY empno) rn, empno, ename
>    FROM emp
> ) WHERE rn <= 5{code}
> to 
> {code:java}
> SELECT empno, ename FROM emp{code}
>  
> If we know every partition count is less than filter count, we can optimize
> {code:java}
> SELECT deptno, ename FROM ( 
>    SELECT ROW_NUMBER() OVER (PARTITION BY deptno) rn, deptno, ename
>    FROM emp
> ) WHERE rn <= N 
> -- Statistic let we know every department count is less than N{code}
> to
> {code:java}
> SELECT empno, ename FROM emp {code}



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


[jira] [Commented] (CALCITE-6237) Using fractions in LOG function does not return correct results

2024-02-05 Thread Julian Hyde (Jira)


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

Julian Hyde commented on CALCITE-6237:
--

+1 [~asolimando]

[~caicancai], Often the hardest problem is to describe the problem correctly. 
This is why we do a lot of our work in jira (and why creating a PR too early 
can create confusion).

You will notice that I asked a question above, "Do you understand why I closed 
CALCITE-6232 as invalid?", and also "Why would you expect fractions to have a 
special behavior in Log functions?" in CALCITE-6232. Those questions are my 
invitation to start a discussion. The main thing I think you can do better is 
to engage in discussion.

> Using fractions in LOG function does not return correct results
> ---
>
> Key: CALCITE-6237
> URL: https://issues.apache.org/jira/browse/CALCITE-6237
> Project: Calcite
>  Issue Type: Bug
>  Components: core
>Affects Versions: 1.36.0
>Reporter: Caican Cai
>Priority: Major
> Fix For: 1.37.0
>
>
> {code:java}
> mysql> SELECT LOG10(2/3) AS result;
> +-+
> | result              |
> +-+
> | -0.1760912594899757 |
> +-+
> 1 row in set (0.00 sec)
> mysql> SELECT LOG2(0) AS result;
> ++
> | result |
> ++
> |   NULL |
> ++
> 1 row in set, 1 warning (0.01 sec)
> mysql> SELECT LOG2(2/3) AS result;
> +-+
> | result              |
> +-+
> | -0.5849625021638512 |
> +-+
> 1 row in set (0.00 sec)
>   {code}
> When using Calcite's Log2 and Log10 functions, if the parameter is a 
> fraction, the integer digits will be retained by default. I think this is 
> wrong. Several decimal places (such as tens) should be retained by default.



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


[jira] [Comment Edited] (CALCITE-6240) Remove ROW_NUMBER if OVER PARTITION BY unique key

2024-02-05 Thread Julian Hyde (Jira)


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

Julian Hyde edited comment on CALCITE-6240 at 2/5/24 8:02 PM:
--

Regarding the first rewrite - converting ROW_NUMBER on a unique key to 1. Can 
this behavior be described by an algebraic property? E.g. ROW_NUMBER applied to 
one row always returns 1?

The second rewrite is also desirable, but I think it will require a different 
mechanism. (It is related to CALCITE-3181, CALCITE-4687.) Maybe this case 
should focus only on the first rewrite. 

Related: {{ROW_NUMBER() OVER (PARTITION BY w, x ORDER BY x, y)}} can be 
simplified to {{ROW_NUMBER() OVER (PARTITION BY w, x ORDER BY y)}} because 
{{x}} has a unique value within any group. This could be applied to any 
aggregate function that sorts, e.g. {{LISTAGG()}}.


was (Author: julianhyde):
Can this behavior be described by an algebraic property? E.g. ROW_NUMBER 
applied to one row always returns 1?

Related: {{ROW_NUMBER() OVER (PARTITION BY w, x ORDER BY x, y)}} can be 
simplified to {{ROW_NUMBER() OVER (PARTITION BY w, x ORDER BY y)}} because 
{{x}} has a unique value within any group. This could be applied to any 
aggregate function that sorts, e.g. {{LISTAGG()}}.

> Remove ROW_NUMBER if OVER PARTITION BY unique key
> -
>
> Key: CALCITE-6240
> URL: https://issues.apache.org/jira/browse/CALCITE-6240
> Project: Calcite
>  Issue Type: Improvement
>  Components: core
>Reporter: Jiajun Xie
>Assignee: Jiajun Xie
>Priority: Minor
>
> The SQL Only have ROW_NUMBER function.
> {code:java}
> SELECT empno, ename FROM ( 
>    SELECT ROW_NUMBER() OVER (PARTITION BY empno) rn, empno, ename
>    FROM emp
> ) WHERE rn <= 5{code}
> to 
> {code:java}
> SELECT empno, ename FROM emp{code}
>  
> If we know every partition count is less than filter count, we can optimize
> {code:java}
> SELECT deptno, ename FROM ( 
>    SELECT ROW_NUMBER() OVER (PARTITION BY deptno) rn, deptno, ename
>    FROM emp
> ) WHERE rn <= N 
> -- Statistic let we know every department count is less than N{code}
> to
> {code:java}
> SELECT empno, ename FROM emp {code}



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


[jira] [Commented] (CALCITE-6240) Remove ROW_NUMBER if OVER PARTITION BY unique key

2024-02-05 Thread Julian Hyde (Jira)


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

Julian Hyde commented on CALCITE-6240:
--

Can this behavior be described by an algebraic property? E.g. ROW_NUMBER 
applied to one row always returns 1?

Related: {{ROW_NUMBER() OVER (PARTITION BY w, x ORDER BY x, y)}} can be 
simplified to {{ROW_NUMBER() OVER (PARTITION BY w, x ORDER BY y)}} because 
{{x}} has a unique value within any group. This could be applied to any 
aggregate function that sorts, e.g. {{LISTAGG()}}.

> Remove ROW_NUMBER if OVER PARTITION BY unique key
> -
>
> Key: CALCITE-6240
> URL: https://issues.apache.org/jira/browse/CALCITE-6240
> Project: Calcite
>  Issue Type: Improvement
>  Components: core
>Reporter: Jiajun Xie
>Assignee: Jiajun Xie
>Priority: Minor
>
> The SQL Only have ROW_NUMBER function.
> {code:java}
> SELECT empno, ename FROM ( 
>    SELECT ROW_NUMBER() OVER (PARTITION BY empno) rn, empno, ename
>    FROM emp
> ) WHERE rn <= 5{code}
> to 
> {code:java}
> SELECT empno, ename FROM emp{code}
>  
> If we know every partition count is less than filter count, we can optimize
> {code:java}
> SELECT deptno, ename FROM ( 
>    SELECT ROW_NUMBER() OVER (PARTITION BY deptno) rn, deptno, ename
>    FROM emp
> ) WHERE rn <= N 
> -- Statistic let we know every department count is less than N{code}
> to
> {code:java}
> SELECT empno, ename FROM emp {code}



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


[jira] [Commented] (CALCITE-6244) Improve `Expressions#constant` to allow passing models with non-public fields

2024-02-05 Thread Julian Hyde (Jira)


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

Julian Hyde commented on CALCITE-6244:
--

Do you propose to allow any class with public fields? I’d be happier if you 
supported some particular models, such as records, that we can verify are 
immutable. And add tests for each model. 

You say “use reflection”, and using reflection when building the AST is fine, 
but maybe not fine if the generated code uses reflection. I want the generated 
code to be such that Javac can do constant reduction. 

> 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: linq4j
>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)


[jira] [Updated] (CALCITE-6244) Improve `Expressions#constant` to allow passing models with non-public fields

2024-02-05 Thread Julian Hyde (Jira)


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

Julian Hyde updated CALCITE-6244:
-
Component/s: linq4j
 (was: avatica)

> 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: linq4j
>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)


[jira] [Created] (CALCITE-6244) Improve `Expressions#constant` to allow passing models with non-public fields

2024-02-05 Thread Wegdan Ghazi (Jira)
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)


[jira] [Updated] (CALCITE-6244) Improve `Expressions#constant` to allow passing models with non-public fields

2024-02-05 Thread Wegdan Ghazi (Jira)


 [ 
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 

[jira] [Commented] (CALCITE-5647) RelMdPopulationSize should use mq.getRowCount(rel) instead of rel.estimateRowCount(mq)

2024-02-05 Thread Ruben Q L (Jira)


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

Ruben Q L commented on CALCITE-5647:


[~jduong] done.

> RelMdPopulationSize should use mq.getRowCount(rel) instead of 
> rel.estimateRowCount(mq)
> --
>
> Key: CALCITE-5647
> URL: https://issues.apache.org/jira/browse/CALCITE-5647
> Project: Calcite
>  Issue Type: Bug
>  Components: core
>Affects Versions: 1.34.0
>Reporter: Adam Kennedy
>Assignee: Adam Kennedy
>Priority: Minor
>  Labels: pull-request-available
>   Original Estimate: 1h
>  Time Spent: 20m
>  Remaining Estimate: 40m
>
> A few locations in Calcite call rel.estimateRowCount(mq) when they should 
> instead call mq.getRowCount(red).
> We detected this because we implemented row count estimation entirely within 
> an alternative handle instead of RelMdRowCount, and then override 
> estimateRowCount to ensure the custom handler is user, by throwing an 
> unreachable code exception.
> A few places in Calcite trigger these unreachable exceptions because they do 
> not use mq.getRowCount.
> The most easily triggered on is in RelMdPopulationSize for the Values 
> parameter.



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


[jira] [Updated] (CALCITE-5647) RelMdPopulationSize should use mq.getRowCount(rel) instead of rel.estimateRowCount(mq)

2024-02-05 Thread Ruben Q L (Jira)


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

Ruben Q L updated CALCITE-5647:
---
Summary: RelMdPopulationSize should use mq.getRowCount(rel) instead of 
rel.estimateRowCount(mq)  (was: RelMdPopulationSize calls rel.estimateRowCount 
instead of mq.getRowCount)

> RelMdPopulationSize should use mq.getRowCount(rel) instead of 
> rel.estimateRowCount(mq)
> --
>
> Key: CALCITE-5647
> URL: https://issues.apache.org/jira/browse/CALCITE-5647
> Project: Calcite
>  Issue Type: Bug
>  Components: core
>Affects Versions: 1.34.0
>Reporter: Adam Kennedy
>Assignee: Adam Kennedy
>Priority: Minor
>  Labels: pull-request-available
>   Original Estimate: 1h
>  Time Spent: 20m
>  Remaining Estimate: 40m
>
> A few locations in Calcite call rel.estimateRowCount(mq) when they should 
> instead call mq.getRowCount(red).
> We detected this because we implemented row count estimation entirely within 
> an alternative handle instead of RelMdRowCount, and then override 
> estimateRowCount to ensure the custom handler is user, by throwing an 
> unreachable code exception.
> A few places in Calcite trigger these unreachable exceptions because they do 
> not use mq.getRowCount.
> The most easily triggered on is in RelMdPopulationSize for the Values 
> parameter.



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