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

ASF GitHub Bot updated CALCITE-7854:
------------------------------------
    Labels: pull-request-available  (was: )

> FilterProjectTransposeRule throws NullPointerException when the Filter has a 
> distribution trait and the Project's input has none
> --------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CALCITE-7854
>                 URL: https://issues.apache.org/jira/browse/CALCITE-7854
>             Project: Calcite
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 1.42.0
>            Reporter: Vladimir Sitnikov
>            Priority: Major
>              Labels: pull-request-available
>
> Applying {{FilterProjectTransposeRule}} (for example 
> {{CoreRules.FILTER_PROJECT_TRANSPOSE}}, which copies the Filter) throws 
> {{NullPointerException}} when the Filter's trait set contains a distribution 
> trait and the trait set of the Project's input does not. Trait sets differ in 
> this way when the planner does not register {{RelDistributionTraitDef}} and a 
> distribution is added to the Filter with {{RelTraitSet#plus}}, as a 
> user-defined rule or Filter subclass can do.
> Reproducer (for {{RelOptRulesTest}}; {{RelBuilderTest.config()}} uses a 
> planner that does not register {{RelDistributionTraitDef}}):
> {code:java}
> @Test void testFilterProjectTransposeRuleInputWithoutDistribution() {
>   final RelBuilder b = RelBuilder.create(RelBuilderTest.config().build());
>   final Filter filter = (Filter) b
>       .scan("EMP")
>       .project(b.field("SAL"))
>       .filter(b.equals(b.field(0), b.literal(11500)))
>       .build();
>   final RelNode in =
>       filter.copy(filter.getTraitSet().plus(RelDistributions.SINGLETON),
>           filter.getInput(), filter.getCondition());
>   final HepProgram program = new HepProgramBuilder()
>       .addRuleInstance(CoreRules.FILTER_PROJECT_TRANSPOSE)
>       .build();
>   final HepPlanner hepPlanner = new HepPlanner(program);
>   hepPlanner.setRoot(in);
>   final RelNode result = hepPlanner.findBestExp();
>   final RelNode pushedFilter = result.getInput(0);
>   assertThat(
>       pushedFilter.getTraitSet().getTrait(RelDistributionTraitDef.INSTANCE),
>       is(RelDistributions.ANY));
> }
> {code}
> Actual result on main (commit 8f27e24a02; 1.42.0 has the same code):
> {noformat}
> java.lang.NullPointerException: Cannot invoke 
> "org.apache.calcite.plan.RelTrait.getClass()" because "trait" is null
>     at org.apache.calcite.plan.RelTraitDef.canonize(RelTraitDef.java:105)
>     at org.apache.calcite.plan.RelCompositeTrait.of(RelCompositeTrait.java:64)
>     at org.apache.calcite.plan.RelTraitSet.replaceIfs(RelTraitSet.java:264)
>     at 
> org.apache.calcite.rel.rules.FilterProjectTransposeRule.onMatch(FilterProjectTransposeRule.java:188)
>     at 
> org.apache.calcite.plan.AbstractRelOptPlanner.fireRule(AbstractRelOptPlanner.java:380)
>     at org.apache.calcite.plan.hep.HepPlanner.applyRule(HepPlanner.java:697)
> {noformat}
> Expected result: the rule pushes the Filter below the Project, and the pushed 
> Filter has the default distribution, {{RelDistributions.ANY}}. That is what 
> {{RelTraitSet#replaceIf}} and {{RelTraitSet#replaceIfs}} produce when their 
> supplier returns null, and the rule already relies on that fallback for the 
> collation trait.
> Cause: when {{copyFilter}} is true, the rule copies the input's distribution 
> with {{replaceIfs(RelDistributionTraitDef.INSTANCE, () -> 
> Collections.singletonList(input.getTraitSet().getTrait(RelDistributionTraitDef.INSTANCE)))}}.
>  {{getTrait}} returns null when the input's trait set has no distribution 
> trait, so the supplier returns a list that holds null rather than null 
> itself, and {{RelCompositeTrait.of}} fails on the null element. Calling 
> {{replaceIf}}, which falls back to the default when the supplier returns 
> null, fixes it.
> Found while reviewing CALCITE-7736 ([PR 
> #5213|https://github.com/apache/calcite/pull/5213]), which carries this fix 
> inside the nullness migration.



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

Reply via email to