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

Vladimir Sitnikov commented on CALCITE-2223:
--------------------------------------------

A bit of a problem is {{RelBuilderFactory}} provides no clue on the convention 
of the generated of the generated relations.

I'm afraid below suggestions seem to break backward compatibility, however it 
looks like current implementation is not that very well defined.

For instance, consider
{code:java} public FilterSetOpTransposeRule(RelBuilderFactory 
relBuilderFactory) {
super(operand(Filter.class, operand(SetOp.class, ...)
{code}

It takes arbitrary Filter and arbitrary SetOp and converts them to none knows 
which relation via RelBuilderFactory.

The principle of least astonishment says that the rule should not match for 
JdbcFilter(EnumerableTableScan...) in case RelBuilderFactory comes from Drill :)

I think the rule should have "Convention" argument, so it can confine the 
proper relations.
Then we could use {{Filter.class}} and {{SetOp.class}} in rule definition and 
still get sane results (e.g. JdbcFilter(JdbcScan..)  or 
DrillFilter(DrillScan..) )

It think it would be OK.
The downside is we (and consumers) would have to add that argument all over the 
place.

An alternative approach would be to add 
{code:java}
public interface RelBuilderFactory {
  org.apache.calcite.plan.Convention getConvention();{code}

Then we won't have to add Convention argument to all the rules, however 
getConvention might sound a bit odd for RelBuilderFactory. <-- I like this 
approach better.


On top of that we might want to confine rules to a single convention by 
default. I guess cross-convention rules are much less desired and expected in 
practice, so we could make sure the default 
{{org.apache.calcite.plan.RelOptRule#operand}}) ensures all the children have 
the same convention. In other words {{operand(Filter.class, any())}} would 
ensure that Filter and its child have the same convention.

> ProjectMergeRule is infinitely matched when is applied after 
> ProjectReduceExpressionsRule
> -----------------------------------------------------------------------------------------
>
>                 Key: CALCITE-2223
>                 URL: https://issues.apache.org/jira/browse/CALCITE-2223
>             Project: Calcite
>          Issue Type: Bug
>            Reporter: Volodymyr Vysotskyi
>            Assignee: Julian Hyde
>            Priority: Critical
>         Attachments: 
> TestLimitWithExchanges_testPushLimitPastUnionExchange.png, heap_overview.png, 
> provenance_contents.png
>
>
> For queries like this:
> {code:sql}
> select t1.f from (select cast(f as int) f, f from (select cast(f as int) f 
> from (values('1')) t(f))) as t1
> {code}
> OOM is thrown when {{ProjectMergeRule}} is applied before applying 
> {{ProjectReduceExpressionsRule}} in VolcanoPlanner.
>  A simple test to reproduce this issue (in {{RelOptRulesTest}}):
> {code:java}
>   @Test public void testOomProjectMergeRule() {
>     RelBuilder relBuilder = 
> RelBuilder.create(RelBuilderTest.config().build());
>     RelNode relNode = relBuilder
>         .values(new String[]{"f"}, "1")
>         .project(
>             relBuilder.alias(
>                 relBuilder.cast(relBuilder.field(0), SqlTypeName.INTEGER),
>                 "f"))
>         .project(
>             relBuilder.alias(
>                 relBuilder.cast(relBuilder.field(0), SqlTypeName.INTEGER),
>                 "f0"),
>             relBuilder.alias(relBuilder.field(0), "f"))
>         .project(
>             relBuilder.alias(relBuilder.field(0), "f"))
>         .build();
>     RelOptPlanner planner = relNode.getCluster().getPlanner();
>     RuleSet ruleSet =
>         RuleSets.ofList(
>             ReduceExpressionsRule.PROJECT_INSTANCE,
>             new ProjectMergeRuleWithLongerName(),
>             EnumerableRules.ENUMERABLE_PROJECT_RULE,
>             EnumerableRules.ENUMERABLE_VALUES_RULE);
>     Program program = Programs.of(ruleSet);
>     RelTraitSet toTraits =
>         relNode.getCluster().traitSet()
>             .replace(0, EnumerableConvention.INSTANCE);
>     RelNode output = program.run(planner, relNode, toTraits,
>         ImmutableList.<RelOptMaterialization>of(), 
> ImmutableList.<RelOptLattice>of());
>     // check for output
>   }
>   /**
>    * ProjectMergeRule inheritor which has
>    * class name greater than ProjectReduceExpressionsRule class name 
> (String.compareTo()).
>    *
>    * It is needed for RuleQueue.popMatch() method
>    * to apply this rule before ProjectReduceExpressionsRule.
>    */
>   private static class ProjectMergeRuleWithLongerName extends 
> ProjectMergeRule {
>     public ProjectMergeRuleWithLongerName() {
>       super(true, RelFactories.LOGICAL_BUILDER);
>     }
>   }
> {code}



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to