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

Rodrigo Setti updated CALCITE-7846:
-----------------------------------
    Description: 
A one-column user-defined table function and a one-column table can use 
different Enumerable row representations. Set operations between them can throw 
a {{ClassCastException}} or return incorrect rows.

Reproducer on Calcite 1.42.0:
 * Register {{numbers_fn()}} using {{{}TableFunctionImpl{}}}. It returns a 
{{ScannableTable }}with one {{INTEGER}} column, n, and {{Object[]}} rows [1] 
and [2].
 * Register numbers_table as a {{ScannableTable}} with the same row type and 
{{Object[]}} rows [2] and [3].
 * Compile and execute the following query with the Enumerable convention and 
{{{}EnumerableRel.Prefer.ARRAY{}}}:

 
{code:java}
SELECT n FROM TABLE(numbers_fn())
EXCEPT
SELECT n FROM numbers_table{code}
 

Expected: one row, n = 1.

Actual: execution throws
{code:java}
java.lang.ClassCastException: java.lang.Integer cannot be cast to
[Ljava.lang.Object; at
org.apache.calcite.linq4j.function.Functions$ArrayEqualityComparer.hashCode.{code}
 

The same mixed table/function shape should also yield correct results when the 
operand order is reversed, and with {{UNION}} and {{{}INTERSECT{}}}.

Suspected cause: {{EnumerableTableFunctionScan.defaultTableFunctionImplement 
retains JavaRowFormat.ARRAY}} for this non-QueryableTable function, while a 
one-column {{EnumerableTableScan}} uses scalar rows. The set-operation comparer 
then receives incompatible representations.

This is related to CALCITE-1907, which fixed a prior failure in the one-column 
table function that affected downstream operators. The set-operation reproducer 
above still fails on 1.42.0. As a downstream workaround, placing an identity 
{{EnumerableCalc}} immediately above the one-column 
{{EnumerableTableFunctionScan}} makes the query return the expected row.

A regression test should cover {{EXCEPT}} in both directions, {{{}UNION{}}}, 
and {{INTERSECT}} with the same one-column table and function.

Pull request was submitted: https://github.com/apache/calcite/pull/5319

  was:
A one-column user-defined table function and a one-column table can use 
different Enumerable row representations. Set operations between them can throw 
a {{ClassCastException}} or return incorrect rows.

Reproducer on Calcite 1.42.0:
 * Register {{numbers_fn()}} using {{{}TableFunctionImpl{}}}. It returns a 
{{ScannableTable }}with one {{INTEGER}} column, n, and {{Object[]}} rows [1] 
and [2].
 * Register numbers_table as a {{ScannableTable}} with the same row type and 
{{Object[]}} rows [2] and [3].
 * Compile and execute the following query with the Enumerable convention and 
{{{}EnumerableRel.Prefer.ARRAY{}}}:

 
{code:java}
SELECT n FROM TABLE(numbers_fn())
EXCEPT
SELECT n FROM numbers_table{code}
 

Expected: one row, n = 1.

Actual: execution throws
{code:java}
java.lang.ClassCastException: java.lang.Integer cannot be cast to
[Ljava.lang.Object; at
org.apache.calcite.linq4j.function.Functions$ArrayEqualityComparer.hashCode.{code}
 

The same mixed table/function shape should also yield correct results when the 
operand order is reversed, and with {{UNION}} and {{{}INTERSECT{}}}.

Suspected cause: {{EnumerableTableFunctionScan.defaultTableFunctionImplement 
retains JavaRowFormat.ARRAY}} for this non-QueryableTable function, while a 
one-column {{EnumerableTableScan}} uses scalar rows. The set-operation comparer 
then receives incompatible representations.

This is related to CALCITE-1907, which fixed a prior failure in the one-column 
table function that affected downstream operators. The set-operation reproducer 
above still fails on 1.42.0. As a downstream workaround, placing an identity 
{{EnumerableCalc}} immediately above the one-column 
{{EnumerableTableFunctionScan}} makes the query return the expected row.

A regression test should cover {{EXCEPT}} in both directions, {{{}UNION{}}}, 
and {{INTERSECT}} with the same one-column table and function.


> Set operations on one-column table functions can throw or return incorrect 
> rows
> -------------------------------------------------------------------------------
>
>                 Key: CALCITE-7846
>                 URL: https://issues.apache.org/jira/browse/CALCITE-7846
>             Project: Calcite
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 1.42.0
>         Environment: Calcite core and {{linq4j}} 1.42.0; Enumerable 
> convention; {{{}EnumerableRel.Prefer.ARRAY{}}}. Reproduced in a Java test on 
> macOS.
>            Reporter: Rodrigo Setti
>            Priority: Major
>              Labels: pull-requests-available, pull_request_available
>         Attachments: calcite-one-column-set-op-repro.zip
>
>
> A one-column user-defined table function and a one-column table can use 
> different Enumerable row representations. Set operations between them can 
> throw a {{ClassCastException}} or return incorrect rows.
> Reproducer on Calcite 1.42.0:
>  * Register {{numbers_fn()}} using {{{}TableFunctionImpl{}}}. It returns a 
> {{ScannableTable }}with one {{INTEGER}} column, n, and {{Object[]}} rows [1] 
> and [2].
>  * Register numbers_table as a {{ScannableTable}} with the same row type and 
> {{Object[]}} rows [2] and [3].
>  * Compile and execute the following query with the Enumerable convention and 
> {{{}EnumerableRel.Prefer.ARRAY{}}}:
>  
> {code:java}
> SELECT n FROM TABLE(numbers_fn())
> EXCEPT
> SELECT n FROM numbers_table{code}
>  
> Expected: one row, n = 1.
> Actual: execution throws
> {code:java}
> java.lang.ClassCastException: java.lang.Integer cannot be cast to
> [Ljava.lang.Object; at
> org.apache.calcite.linq4j.function.Functions$ArrayEqualityComparer.hashCode.{code}
>  
> The same mixed table/function shape should also yield correct results when 
> the operand order is reversed, and with {{UNION}} and {{{}INTERSECT{}}}.
> Suspected cause: {{EnumerableTableFunctionScan.defaultTableFunctionImplement 
> retains JavaRowFormat.ARRAY}} for this non-QueryableTable function, while a 
> one-column {{EnumerableTableScan}} uses scalar rows. The set-operation 
> comparer then receives incompatible representations.
> This is related to CALCITE-1907, which fixed a prior failure in the 
> one-column table function that affected downstream operators. The 
> set-operation reproducer above still fails on 1.42.0. As a downstream 
> workaround, placing an identity {{EnumerableCalc}} immediately above the 
> one-column {{EnumerableTableFunctionScan}} makes the query return the 
> expected row.
> A regression test should cover {{EXCEPT}} in both directions, {{{}UNION{}}}, 
> and {{INTERSECT}} with the same one-column table and function.
> Pull request was submitted: https://github.com/apache/calcite/pull/5319



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

Reply via email to