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

Xuyang Zhong updated CALCITE-7431:
----------------------------------
    Description: 
Below is my test and an exception will be thrown:

 
{code:java}
RelBuilder b = RelBuilder.create(RelBuilderTest.config().build());

RelNode in = b
    .scan("EMP")
    .sort(3) // MGR asc
    .project(b.field(3), b.alias(b.field(3), "MGR2")) // MGR, MGR as MGR2
    .build();

// the following 3 lines will all fail
System.err.println(in.getTraitSet().getCollation());
System.err.println(in.getTraitSet().getCollations());
System.err.println((RelCollation) 
in.getTraitSet().getTrait(RelCollationTraitDef.INSTANCE)); 

// the exception:
java.lang.ClassCastException: org.apache.calcite.plan.RelCompositeTrait cannot 
be cast to org.apache.calcite.rel.RelCollation{code}
The reason is that at `{{{}return (T) getTrait(index);{}}}` in 
`RelTraitSet#getTrait`, the trait we actually get is a 
`{{{}RelCompositeTrait`{}}}, but it is cast to `{{{}RelCollation`{}}}, which 
leads to a Java cast error.

I’m not sure whether this is by design: Callers of 
`{{{}RelTraitSet#getTrait`{}}} have to be aware that the input trait may have 
multiple values (`{{{}RelMultipleTrait`{}}}), and therefore should use 
`{{{}#getTraits`{}}} instead. From my perspective, relying on callers to be 
aware of this is not ideal. At the very least, `{{{}#getTrait{}}}` should 
validate whether the trait is a `{{{}RelMultipleTrait{}}}` and explicitly 
indicate that `{{{}#getTraits`{}}} should be used instead.

I encountered this issue because for the SQL below, in older versions, 
`{{{}FilterProjectTransposeRule#Line187`{}}} would throw this error. Although 
it was fixed in 
[https://github.com/apache/calcite/pull/4704/changes#r2644415395], I found that 
there still seem to be many places that call `{{{}#getTrait`{}}} 
incorrectly—for example, `{{{}#getCollation()`{}}}, `{{{}#getCollations()`{}}}, 
and the handling of `{{{}RelDistribution`{}}}.
{code:java}
SELECT
    *
FROM (
    SELECT
        task_status, task_status + 1
    FROM ods_htg__prod_shop_govern_task__task
    WHERE
        task_date >= '2026-02-01' AND task_date < '2026-02-01'
        -- this will convert the source to empty value source,
        -- and empty value source will output multi collations
)
WHERE
    task_status  > 10 {code}

  was:
Below is my test and an exception will be thrown:

 
{code:java}
RelBuilder b = RelBuilder.create(RelBuilderTest.config().build());

RelNode in = b
    .scan("EMP")
    .sort(3) // MGR asc
    .project(b.field(3), b.alias(b.field(3), "MGR2")) // MGR, MGR as MGR2
    .build();

// the following 3 line will all fail
System.err.println(in.getTraitSet().getCollation());
System.err.println(in.getTraitSet().getCollations());
System.err.println((RelCollation) 
in.getTraitSet().getTrait(RelCollationTraitDef.INSTANCE)); 

// the exception:
java.lang.ClassCastException: org.apache.calcite.plan.RelCompositeTrait cannot 
be cast to org.apache.calcite.rel.RelCollation{code}
 

 

The reason is that at `{{{}return (T) getTrait(index);{}}}` in 
`RelTraitSet#getTrait`. The trait we actually get is a 
`{{{}RelCompositeTrait`{}}}, but it is cast to `{{{}RelCollation`{}}}, which 
leads to a Java cast error.

I’m not sure whether this is by design: Callers of 
`{{{}RelTraitSet#getTrait`{}}} have to be aware that the input trait may have 
multiple values (`{{{}RelMultipleTrait`{}}}), and therefore should use 
`{{{}#getTraits`{}}} instead. From my perspective, relying on callers to be 
aware of this is not ideal. At the very least, `{{{}#getTrait{}}}` should 
validate whether the trait is a `{{{}RelMultipleTrait{}}}` and explicitly 
indicate that `{{{}#getTraits`{}}} should be used instead.

I encountered this issue because for the SQL below, in older versions, 
`{{{}FilterProjectTransposeRule#Line187`{}}} would throw this error. Although 
it was fixed in 
[https://github.com/apache/calcite/pull/4704/changes#r2644415395], I found that 
there still seem to be many places that call `{{{}#getTrait`{}}} 
incorrectly—for example, `{{{}#getCollation()`{}}}, `{{{}#getCollations()`{}}}, 
and the handling of `{{{}RelDistribution`{}}}.
{code:java}
SELECT
    *
FROM (
    SELECT
        task_status, task_status + 1
    FROM ods_htg__prod_shop_govern_task__task
    WHERE
        task_date >= '2026-02-01' AND task_date < '2026-02-01'
        -- this will convert the source to empty value source,
        -- and empty value source will output multi collations
)
WHERE
    task_status  > 10 {code}


> RelTraitSet#getTrait seems to mishandle RelCompositeTrait
> ---------------------------------------------------------
>
>                 Key: CALCITE-7431
>                 URL: https://issues.apache.org/jira/browse/CALCITE-7431
>             Project: Calcite
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 1.41.0
>            Reporter: Xuyang Zhong
>            Priority: Major
>
> Below is my test and an exception will be thrown:
>  
> {code:java}
> RelBuilder b = RelBuilder.create(RelBuilderTest.config().build());
> RelNode in = b
>     .scan("EMP")
>     .sort(3) // MGR asc
>     .project(b.field(3), b.alias(b.field(3), "MGR2")) // MGR, MGR as MGR2
>     .build();
> // the following 3 lines will all fail
> System.err.println(in.getTraitSet().getCollation());
> System.err.println(in.getTraitSet().getCollations());
> System.err.println((RelCollation) 
> in.getTraitSet().getTrait(RelCollationTraitDef.INSTANCE)); 
> // the exception:
> java.lang.ClassCastException: org.apache.calcite.plan.RelCompositeTrait 
> cannot be cast to org.apache.calcite.rel.RelCollation{code}
> The reason is that at `{{{}return (T) getTrait(index);{}}}` in 
> `RelTraitSet#getTrait`, the trait we actually get is a 
> `{{{}RelCompositeTrait`{}}}, but it is cast to `{{{}RelCollation`{}}}, which 
> leads to a Java cast error.
> I’m not sure whether this is by design: Callers of 
> `{{{}RelTraitSet#getTrait`{}}} have to be aware that the input trait may have 
> multiple values (`{{{}RelMultipleTrait`{}}}), and therefore should use 
> `{{{}#getTraits`{}}} instead. From my perspective, relying on callers to be 
> aware of this is not ideal. At the very least, `{{{}#getTrait{}}}` should 
> validate whether the trait is a `{{{}RelMultipleTrait{}}}` and explicitly 
> indicate that `{{{}#getTraits`{}}} should be used instead.
> I encountered this issue because for the SQL below, in older versions, 
> `{{{}FilterProjectTransposeRule#Line187`{}}} would throw this error. Although 
> it was fixed in 
> [https://github.com/apache/calcite/pull/4704/changes#r2644415395], I found 
> that there still seem to be many places that call `{{{}#getTrait`{}}} 
> incorrectly—for example, `{{{}#getCollation()`{}}}, 
> `{{{}#getCollations()`{}}}, and the handling of `{{{}RelDistribution`{}}}.
> {code:java}
> SELECT
>     *
> FROM (
>     SELECT
>         task_status, task_status + 1
>     FROM ods_htg__prod_shop_govern_task__task
>     WHERE
>         task_date >= '2026-02-01' AND task_date < '2026-02-01'
>         -- this will convert the source to empty value source,
>         -- and empty value source will output multi collations
> )
> WHERE
>     task_status  > 10 {code}



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

Reply via email to