[
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 one-column table function
failure affecting 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.
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 one-column table function
failure affecting 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
>
> 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 one-column table
> function failure affecting 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.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)