That method is intended if you have a class MyTableScan and a generic rule that 
can handle any instance of MyTableScan. 

If you have (say) five instances of MyTableScan and five rule instances, one 
for each scan, then you should register each rule instance individually in the 
planner. 

There are a couple of pitfalls with your approach. Suppose you have a self join 
query “select * from t as t1, t as t2”, and t is of type MyTable. There is only 
one table but two scans, so you will need to register two rule instances. 

Those rule instances contain state, and therefore hold memory and other 
resources, you won’t want to keep them for a long time (e.g. in a cache). 

For these reasons, the recommended policy is to include the state in the table 
instance (not in the scan, and not in the rule) and therefore you can write 
generic rules that can be safely cached and reused. 

This approach makes it possible to write more complex rules - e.g. a rule that 
matches two scans of MyTable under a Join. In your model, if there are N scans 
of a MyTable in a query you would have to create and register N^2 rule 
instances. 

Julian 


> On Feb 2, 2024, at 5:45 AM, Austin Richardson 
> <austin.richard...@teampicnic.com> wrote:
> 
> Hello Calcite devs,
> 
> Our team currently has a setup in which we have a single TableScan
> implementation (e.g. MyTableScan) serving multiple Calcite tables. Each
> MyTableScan handles the registration of rules tailored to its respective
> Calcite table. I've included an example of the code structure at the end of
> my email.
> 
> What we’ve run into is the class-based deduplication behaviour here
> <https://github.com/apache/calcite/blob/351ddeb47b8dfb5c196c563920290a79575e9864/core/src/main/java/org/apache/calcite/plan/AbstractRelOptPlanner.java#L235>,
> meaning only one instance of MyTableScan can successfully register its
> rules.
> 
> We’re exploring solutions to split these such that each table has a unique
> TableScan implementation, but also wanted to check first: is there any
> alternate way we could keep the single class approach, but still have
> Calcite register each MyTableScan?
> 
> Best,
> Austin
> 
> 
> ---
> 
> 
> Example code structure:
> 
> 
> abstract class MyTable {
>    abstract RelOptRule getRule();
> 
>    @Override
>    public RelNode toRel(...) {
>        return new MyTableScan(getRule());
>    }
> }
> 
> ...
> 
> class Table1 extends MyTable {
>    @Override
>    RelOptRule getRule() { ... }
> }
> 
> ...
> 
> class Table2 extends MyTable {
>    @Override
>    RelOptRule getRule() { ... }
> }
> 
> ...
> 
> class MyTableScan {
>    RelOptRule rule;
> 
>    // ... constructor where rule is injected ...
> 
>    @Override
>    public void register(RelOptPlanner planner) {
>        planner.addRule(rule);
>    }
> }

Reply via email to