net.sf.farrago.fennel.rel
Class FarragoAutoCalcRule

java.lang.Object
  extended by org.eigenbase.relopt.RelOptRule
      extended by net.sf.farrago.fennel.rel.FarragoAutoCalcRule

public class FarragoAutoCalcRule
extends RelOptRule

FarragoAutoCalcRule is a rule for implementing CalcRel via a combination of the Fennel Calculator (FennelCalcRel) and the Java Calculator (IterCalcRel).

This rule does not attempt to transform the matching RelOptRuleCall if the entire CalcRel can be implemented entirely via one calculator or the other. A future optimization might be to use a costing mechanism to determine where expressions that can be implemented by both calculators should be executed.

Strategy: Each CalcRel can be considered a forest (e.g. a group of trees). The forest is comprised of the RexNode trees contained in the project and conditional expressions in the CalcRel. The rule's basic strategy is to stratify the forest into levels, such that each level can be implemented entirely by a single calc. Having divided the forest into levels, the rule creates new CalcRel instances which each contain all of the RexNodes associated with a given level and then connects RexNodes across the levels by adding RexInputRef instances as needed. The planner will then evaluate each CalcRel and should find that either IterCalcRel or FennelCalcRel is able to implement each of the CalcRels this rule creates. The planner will then automatically place the necessary plumbing between IterCalcRel and FennelCalcRel instances to convert between the two types of calculator. This strategy depends the rules that generate IterCalcRel and FennelCalcRel not performing their transformations if a portion of an expression cannot be implemented in the corresponding calculator. It also depends on accurate implementability information regarding RexCalls.

Potential improvements: Currently, the rule does not exploit redundancy between trees in the forest. For example, consider a table T with columns C1 and C2 and calculator functions F1, F2 and J where F1 and F2 are Fennel-only and J is Java-only. The query

     select F1(C1), F2(C1), J(C2) from T
begins life as
     CalcRel Project: "F1($0), F2($0), J($1)"
After applying FarragoAutoCalcRule we get
     CalcRel Project: "F1($0), F2($1), $2"
     CalcRel Project: "$0, $0, J($1)"
Notice that although the calls to F1 and F2 refer to the same base column, the rule treats them separately. A better result would be
     CalcRel Project: "F1($0), F2($0), $1"
     CalcRel Project: "$0, J($1)"

Another improvement relates to handling conditional expressions. The current implementation of the FarragoAutoCalc rule only treats the conditional expression specially in the top-most post-transformation CalcRel. For example, consider a table T with columns C1 and C2 and calculator functions F and J where F is Fennel-only and J is Java-only. The query

     select F(C1) from T where J(C2)
begins life as
     CalcRel Project: "F($0)"    Conditional: "J($1)"
After applying FarragoAutoCalcRule we get
     CalcRel Project: "F($0)"    Conditional: "$1"
     CalcRel Project: "$0 J($1)" Conditional:     
Notice that even though the conditional expression could be evaluated and used for filtering in the lower CalcRel, it's not. This means that all rows are sent to the Fennel calculator. A better result would be
     CalcRel Project: "F($0)"    Contidional:
     CalcRel Project: "$0"       Conditional: "J($1)"
In this case, rows that don't match the conditional expression would not reach the Fennel calculator.


Nested Class Summary
private static class FarragoAutoCalcRule.AutoCalcRelSplitter
           
private static class FarragoAutoCalcRule.FennelRelType
           
private static class FarragoAutoCalcRule.JavaRelType
           
 
Field Summary
static FarragoAutoCalcRule instance
          The singleton instance.
 
Fields inherited from class org.eigenbase.relopt.RelOptRule
ANY, description, operands
 
Constructor Summary
private FarragoAutoCalcRule()
          Creates a new FarragoAutoCalcRule object.
 
Method Summary
 boolean canImplementInFennel(CalcRel calc)
          Returns whether an expression can be implemented in Fennel convention.
 void onMatch(RelOptRuleCall call)
          Called when this rule matches a rel.
 
Methods inherited from class org.eigenbase.relopt.RelOptRule
convert, equals, equals, getOperand, getOperands, getOutConvention, getOutTrait, hashCode, matches, mergeTraitsAndConvert, mergeTraitsAndConvert, toString
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

instance

public static final FarragoAutoCalcRule instance
The singleton instance.

Constructor Detail

FarragoAutoCalcRule

private FarragoAutoCalcRule()
Creates a new FarragoAutoCalcRule object.

Method Detail

onMatch

public void onMatch(RelOptRuleCall call)
Called when this rule matches a rel. First uses RexToCalcTranslator to determine if the rel can be implemented in the Fennel calc. If so, this method returns without performing any transformation. Next uses JavaRelImplementor to perform the same test for the Java calc. Also returns with no transformation if the Java calc can implement the rel. Finally, transforms the given CalcRel into a stack of CalcRels that can each individually be implemented in the Fennel or Java calcs.

Specified by:
onMatch in class RelOptRule
Parameters:
call - Rule call
See Also:
RelOptRule.matches(RelOptRuleCall)

canImplementInFennel

public boolean canImplementInFennel(CalcRel calc)
Returns whether an expression can be implemented in Fennel convention.