Lana, that makes perfect sense. The rule engine does not descent into RexSubQuery. (We can debate whether it should.)
Julian > On Feb 12, 2021, at 23:00, Lana Ramjit <[email protected]> wrote: > > I am not sure if this helps and one of the dev team will probably know > better than me, but I think I ran into a similar issue. > The withOperandSupplier matches LogicalTableScan nodes, but the subquery is > a RexSubQuery contained in a LogicalFilter; so it skips the LogicalFilter > and does not descend into the expression tree to start firing rules. > > I believe that it works in the full planner because the full planner uses a > SubqueryRemoveRule that lifts the subquery out of an expression in the > LogicalFilter and into a set of first-class logical operators. So I did > manage to fix a similar issue by making sure that SubqueryRemoveRule is > fired first. > > Hope this helps; I am interested to know if my fix is right since I ran > into a similar issue! > -Lana > >> On Fri, Feb 12, 2021 at 10:33 PM Michael Thomson <[email protected]> >> wrote: >> >> Julian >> >> Thanks for your comment, I am using Calcite 1.25 currently by the way. >> Here is a simplified version of the code that runs the rule >> >> >> @Override >> public RelRoot rel(SqlNode sql) { >> RelRoot root = super.rel(sql); >> root = applyInjectFilterRule(root, restriction); >> return root; >> } >> >> private RelRoot applyInjectFilterRule(RelRoot root, Restriction >> restriction) { >> final InjectFilterRule injectFilterRule = >> InjectFilterRule.Config.DEFAULT.toRule(restriction); >> >> final HepProgram program = >> HepProgram.builder().addRuleInstance(injectFilterRule).build(); >> HepPlanner prePlanner = new HepPlanner(program); >> prePlanner.setRoot(root.rel); >> final RelNode rootRelNode = prePlanner.findBestExp(); >> return root.withRel(rootRelNode); >> } >> >> Does this look reasonable? >> >> I can produce a complete test program to try to reproduce in isolation if >> nothing in this code jumps out. >> >> thanks >> Michael. >> >> On Fri, Feb 12, 2021 at 3:43 PM Julian Hyde <[email protected]> >> wrote: >> >>> It looks like you’ve defined it right. It should fire once for each >>> LogicalTableScan in the plan. >>> >>> Make sure that you have registered a rule instance in the planner. >>> >>>> On Feb 11, 2021, at 11:19 PM, Michael Thomson <[email protected] >>> >>> wrote: >>>> >>>> Hi, >>>> >>>> I suspect I am doing something wrong but it's not obvious to me and >>> hoping >>>> someone can spot what my issue is. >>>> >>>> I am trying to add a simple filter after detection of LogicalTableScans >>> on >>>> particular tables >>>> >>>> I have a rule that looks like this >>>> >>>> public interface Config extends RelRule.Config { >>>> Config DEFAULT = >>>> EMPTY.withOperandSupplier(b0 -> >>>> b0.operand(LogicalTableScan.class).anyInputs()) >>>> .as(Config.class); >>>> >>>> @Override >>>> default InjectFilterRule toRule() { >>>> return new InjectFilterRule(this, null); >>>> } >>>> } >>>> >>>> Everything works as expected with most sql >>>> >>>> but when using a subqueries like this >>>> >>>> select * from t6 where t6.t1 in (select t1 from t6); >>>> >>>> The result I see is >>>> >>>> LogicalProject(t1=[$0], i1=[$1]) >>>> LogicalFilter(condition=[IN($0, { >>>> LogicalProject(t1=[$0]) >>>> LogicalTableScan(table=[[database, t6]]) >>>> })]) >>>> LogicalFilter(condition=[OR(=($0, 'a'), =($0, 'b'), =($0, 'c'))]) >>>> LogicalTableScan(table=[[database, t6]]) >>>> >>>> You will note the bogus FILTER added to the first LogicalTableScan >>>> >>>> LogicalFilter(condition=[OR(=($0, 'a'), =($0, 'b'), =($0, 'c'))]) >>>> >>>> but nothing was added to the one in the IN subquery >>>> >>>> When I look in the debug it seems the onMatch code never receives an >>>> invocation for the subquery Scan. >>>> >>>> The rules are run as part of the planner.rel() call. >>>> >>>> Any ideas of what I am overlooking or misunderstanding would be much >>>> appreciated >>>> >>>> thanks >>>> Michael. >>> >>> >>
