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. > > > > >
