Hello,
We have defined some extra comparison functions for our users.
However, we’ve noticed that filter push-down (using ` 
CoreRules.FILTER_INTO_JOIN`) does not occur when the operands to the functions 
come from the opposite side of an outer join (i.e. from the right side of a 
left outer join, or from the left side of a right outer join).

Here is a demonstration of this with SQL, the logical plan, and the physical 
plan post optimization: https://pastebin.com/raw/KjE40z5X
In this example, I’ve defined a simple function called “test” which takes a 
BigInt and returns Boolean.
In the first query, the operand to `test` comes from the left side of the left 
join, and the tree before planning has the filter node above the join, and 
after planning the filter is below the join.
In the second query, the operand to `test` comes from the left side of the 
right join, and the tree before planning has the filter node above the join, 
but after planning the filter is still above the join.
(I was hoping to get the output from the RuleEventLogger, but I haven’t been 
able to get it working.)

I figure the push down is not happening because we are not properly 
communicating how these functions handles null (which is to return null, which 
would be false-y, and therefore allow the join to be converted to an inner join 
and the filter pushed down below the join).
We are not providing these functions as SqlOperator instances in a 
SqlOperatorTable; instead we use `ScalarFunctionImpl.create` on native methods, 
and provide those Function instances through the Schema, via 
`AbstractSchema.getFunctionMultimap` (which eventually make it to the 
CatalogReader)
I’m guessing that if we were providing these via a SqlOperatorTable (which 
we’re hoping to do sometime soon) that having the return type of the operator 
be nullable, or have the nullability be inferred from the operands, would allow 
the planner to push the filter below the join.

Am I right?
In the meantime, is there a way to provide this nullability information through 
`ScalarFunctionImpl.create` pathway we’re currently using?

Thanks!
-Ian J. Bertolacci

Reply via email to