Yes, to repeat: don’t call RelNode.getInput(int), or RelNode.getInputs(), or 
Join.getLeft() or Join.getRight(), or SingleRelNode.getInput(). If you do, you 
will get the wrapped input, a HepRelVertex or a RelSubset.

Instead call RelOptRuleCall.rel(int).

Julian



> On Aug 2, 2017, at 1:34 PM, Muhammad Gelbana <[email protected]> wrote:
> 
> Of course! You are correct. I got used to single input nodes and I didn't
> deal with the Join properly.
> 
> I get the inputs of the join using *join.getInputs()*.
> 
> 
> 
> Thanks,
> Gelbana
> 
> On Wed, Aug 2, 2017 at 8:10 PM, Julian Hyde <[email protected]> wrote:
> 
>> Join has two inputs but you have only one “any()”. I am surprised that it
>> is matching a Join at all (an operand with one input should not match a
>> RelNode with two inputs). But given that it does… you have two operands, so
>> call.rel(0) and call.rel(1) will be valid but call.rel(2) will not.
>> 
>> So, how are you getting the right input to the join? Are you calling
>> Join.getInput(1) or Join.getRight()? Yes, those will be HepRelVertex or
>> RelSubset, as you are seeing.
>> 
>> You should add another “, any()”, then call call.rel(2) when the rule
>> matches.
>> 
>> Julian
>> 
>> 
>> 
>>> On Aug 2, 2017, at 3:15 AM, Muhammad Gelbana <[email protected]>
>> wrote:
>>> 
>>> Here it is
>>> 
>>>> public GelbanaJoinRule(JdbcConvention out) {
>>>>   super(operand(LogicalJoin.class, Convention.NONE, any()),
>>>> "GelbanaJoinRule");
>>>>   this.outConvention = out;
>>>> }
>>> 
>>> 
>>> The nodes appearing as *HepRelVertex* are the *LogicalJoin*'s input
>> nodes,
>>> not the operands passed to the rule using the
>>> *org.apache.calcite.plan.RelOptRule.matches(RelOptRuleCall)* method.
>>> 
>>> 
>>> 
>>> - Gelbana
>>> 
>>> On Tue, Aug 1, 2017 at 6:13 PM, Jess Balint <[email protected]> wrote:
>>> 
>>>> Can you share your operand constraints? Where did you see HepRelVertex?
>> As
>>>> Julian described, the rel nodes are of the correct type when matched
>> with
>>>> operand constraints.
>>>> 
>>>> Jess
>>>> 
>>>> On Tue, Aug 1, 2017 at 7:25 AM, Muhammad Gelbana <[email protected]>
>>>> wrote:
>>>> 
>>>>> I'm facing a similar problem but with Join inputs. Is there a way to
>>>>> control the type of nodes returned as inputs to a join ? I wrote a rule
>>>> for
>>>>> a join but it failed to match it because I expect the join inputs to be
>>>>> *JdbcRel* nodes while the inputs were actually *HepRelVertex*. I'm
>> using
>>>>> Drill.
>>>>> 
>>>>> 
>>>>> 
>>>>> - Gelbana
>>>>> 
>>>>> On Fri, Jun 30, 2017 at 4:35 PM, Muhammad Gelbana <[email protected]
>>> 
>>>>> wrote:
>>>>> 
>>>>>> Thanks a lot Julian. That was very helpful.
>>>>>> 
>>>>>> *---------------------*
>>>>>> *Muhammad Gelbana*
>>>>>> 
>>>>>> On Thu, Jun 29, 2017 at 8:04 PM, Julian Hyde <[email protected]>
>> wrote:
>>>>>> 
>>>>>>> Consider ProjectFilterTransposeRule, a simple rule that matches a
>>>>> Project
>>>>>>> on top of a Filter. But how to get that Project and Filter?
>>>>>>> 
>>>>>>> Run RelOptRulesTest.testPushProjectPastFilter in the debugger, and
>>>> put
>>>>> a
>>>>>>> breakpoint in ProjectFilterTransposeRule.onMatch [1]. Look at the
>>>>>>> Project “origProj” in the debugger. Its input is a HepRelVertex
>>>>> containing
>>>>>>> a Filter. But Filter “filter” is, sure enough, a Filter.
>>>>>>> 
>>>>>>> So, to get the filter, don’t call origProj.getInput(), instead call
>>>>>>> call.rel(1). The RelOptRuleCall will have ensured that this is the
>>>>> correct
>>>>>>> type, and removed any wrappers.
>>>>>>> 
>>>>>>> Julian
>>>>>>> 
>>>>>>> 
>>>>>>> [1] https://insight.io/github.com/apache/calcite/blob/master/cor
>>>>>>> e/src/main/java/org/apache/calcite/rel/rules/ProjectFilterTr
>>>>>>> ansposeRule.java?line=78 <https://insight.io/github.com
>>>>>>> /apache/calcite/blob/master/core/src/main/java/org/apache/
>>>>>>> calcite/rel/rules/ProjectFilterTransposeRule.java?line=78>
>>>>>>>> On Jun 29, 2017, at 8:47 AM, Muhammad Gelbana <[email protected]>
>>>>>>> wrote:
>>>>>>>> 
>>>>>>>> ​But how can I handle the unexpected variation of the input class
>>>>> type ?
>>>>>>>> For example, please consider the following *RelOptRule* constructor​
>>>>>>>> 
>>>>>>>> public IncortaLimitRule() {
>>>>>>>>>  super(operand(*DrillLimitRel*.class,
>>>>> operand(*IncortaJdbcDrel*.clas
>>>>>>> s,
>>>>>>>>> operand(*JdbcRel*.class, any()))), "TestRule");
>>>>>>>>> }
>>>>>>>> 
>>>>>>>> 
>>>>>>>> I'm trying to be precise so I specified the RelNode
>>>> (*DrillLimitRel*),
>>>>>>> it's
>>>>>>>> input (*IncortaJdbcDrel*) and it's input's input (*JdbcRel*, this is
>>>>> an
>>>>>>>> interface but I understand that the planner should match relnodes if
>>>>> the
>>>>>>>> rule's operand is a parent of examined operand, so for instance,
>>>>>>>> *JdbcTableScan* should match).
>>>>>>>> 
>>>>>>>> Is there a way to guarantee the relnode's input type ? Looking into
>>>>>>> other
>>>>>>>> rules, I don't remember seeing type checking for input relnodes. Is
>>>>> it a
>>>>>>>> good sign that I have to do multiple checks for the input relnode
>>>>> type ?
>>>>>>>> 
>>>>>>>> *---------------------*
>>>>>>>> *Muhammad Gelbana*
>>>>>>>> 
>>>>>>>> On Tue, Jun 27, 2017 at 1:36 AM, Julian Hyde <[email protected]>
>>>>> wrote:
>>>>>>>> 
>>>>>>>>> RelSubset provides a level of indirection that allows Calcite to
>>>>>>> optimize
>>>>>>>>> queries. If the input to a relational operator is an equivalence
>>>>>>> class, not
>>>>>>>>> a particular relational expression, then Calcite has the freedom to
>>>>>>> choose
>>>>>>>>> the member of the equivalence class that has the cheapest cost.
>>>>>>>>> 
>>>>>>>>> Calcite uses the Volcano algorithm, a form of dynamic programming,
>>>> to
>>>>>>> do
>>>>>>>>> this.
>>>>>>>>> 
>>>>>>>>> As you have discovered it means that you cannot simply tree-walk
>>>>> over a
>>>>>>>>> relational expression, looking for, say, a Project on top of a
>>>>> Filter.
>>>>>>> You
>>>>>>>>> need to write a RelOptRule that declares that it wants to see a
>>>>>>> Project on
>>>>>>>>> top of a Filter, and Volcano will fire that rule whenever that
>>>>>>> combination
>>>>>>>>> arises.
>>>>>>>>> 
>>>>>>>>> Julian
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>>> On Jun 26, 2017, at 4:00 PM, Muhammad Gelbana <
>>>> [email protected]>
>>>>>>>>> wrote:
>>>>>>>>>> 
>>>>>>>>>> While debugging through some of the rules I'm trying to get to
>>>>> work, I
>>>>>>>>> find
>>>>>>>>>> that the matched relnode's input is *HepRelVertex* or a
>>>> *RelSubset*.
>>>>>>>>>> 
>>>>>>>>>> Why wouldn't I be getting a descendant of the following types:
>>>>>>>>>> 
>>>>>>>>>> - BiRel
>>>>>>>>>> - MultiJoin
>>>>>>>>>> - SetOp
>>>>>>>>>> - SingleRel
>>>>>>>>>> - TableScan
>>>>>>>>>> 
>>>>>>>>>> There are other types too but I can assume how to handle the
>>>> types I
>>>>>>>>> listed.
>>>>>>>>>> 
>>>>>>>>>> *RelSubset* is really confusing because, as far as I understand,
>>>>> it's
>>>>>>> a
>>>>>>>>>> group of relnodes. So how can I decide which node to get from this
>>>>>>> group
>>>>>>>>> so
>>>>>>>>>> I can use it as an input to the new relnode I'm creating ?! Or
>>>>> should
>>>>>>> I
>>>>>>>>>> pass the *RelSubset* itself ? Why am I getting it in the first
>>>> place
>>>>>>> and
>>>>>>>>>> not a single relnode ?
>>>>>>>>>> 
>>>>>>>>>> *---------------------*
>>>>>>>>>> *Muhammad Gelbana*
>>>>>>>>> 
>>>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>> 
>>>>> 
>>>> 
>> 
>> 

Reply via email to