net.sf.farrago.fennel.rel
Class FarragoMultisetSplitterRule

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

public class FarragoMultisetSplitterRule
extends RelOptRule

FarragoMultisetSplitterRule is a planner rule which removes multiset operations from an expression.

It works in three ways:

  1. It works on relational expressions consisting of a mix between multiset and non-multisets calls, splitting them up. For example, CARDINALITY(ms) != 632
  2. It works on relational expressions consisting of nested multiset calls, splitting them up. For example, CARDINALITY(ms1 MULTISET UNION ms2)
  3. It also transforms a multiset call to an equivalent RelNode tree.

It uses the CalcRelSplitter for its splitting. Example: The expression CARDINALITY(ms) = 5 begins its life as: CalcRel=[=(CARD(ms),5)] After the split it, looks in principle like:

CalcRel=[=($in_ms,5]
   CalcRel=[CARD(ms)]
See CalcRelSplitter on details of the split.

CalcRel=[CARD(ms)] is intercepted in this very same rule and an equivalent RelNode tree is injected in its place.

Since:
Mar 10, 2005
Version:
$Id: //open/dev/farrago/src/net/sf/farrago/fennel/rel/FarragoMultisetSplitterRule.java#4 $
Author:
Wael Chatila

Nested Class Summary
private  class FarragoMultisetSplitterRule.MultisetRelSplitter
          Unmix mixing between multisets and non-multisets
private  class FarragoMultisetSplitterRule.NestedRelSplitter
          Unnest nested multiset calls
 
Field Summary
static FarragoMultisetSplitterRule instance
           
 
Fields inherited from class org.eigenbase.relopt.RelOptRule
ANY, description, operands
 
Constructor Summary
private FarragoMultisetSplitterRule()
          Creates a FarragoMultisetSplitterRule.
 
Method Summary
private  boolean containsNestedMultiset(RexNode node, boolean deep)
          Returns true if node contains a multiset call directly under another multiset call.
private  boolean containsNestedMultiset(RexProgram program)
          Returns true if any expression in a program contains a multiset call directly under another multiset call.
 RelNode createExistsPlanSingleRow(RelNode child, boolean neg)
           
private static RelNode createLimitRel(RelNode child)
          Creates a relational expression which ensures that a given expression only returns one row, and throws a runtime error otherwise.
private static RelNode createProject(CalcRel calc, RexLocalRef local, List<CorrelatorRel.Correlation> correlationList)
           
private static UncollectRel createUncollect(CalcRel calc, RexLocalRef local, List<CorrelatorRel.Correlation> correlationList)
           
private  int findMultiset(List<RexNode> exprs)
           
private  CorrelatorRel insertRels(CalcRel calc, int offset)
          Injects an equivalent RelNode tree to a RexCall's multiset operator.
 void onMatch(RelOptRuleCall call)
          Receives notification about a rule match.
 
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 FarragoMultisetSplitterRule instance
Constructor Detail

FarragoMultisetSplitterRule

private FarragoMultisetSplitterRule()
Creates a FarragoMultisetSplitterRule.

Method Detail

findMultiset

private int findMultiset(List<RexNode> exprs)

onMatch

public void onMatch(RelOptRuleCall call)
Description copied from class: RelOptRule
Receives notification about a rule match. At the time that this method is called, call.rels holds the set of relational expressions which match the operands to the rule; call.rels[0] is the root expression.

Typically a rule would check that the nodes are valid matches, creates a new expression, then calls back RelOptRuleCall.transformTo(org.eigenbase.rel.RelNode) to register the expression.

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

insertRels

private CorrelatorRel insertRels(CalcRel calc,
                                 int offset)
Injects an equivalent RelNode tree to a RexCall's multiset operator.

If the expression is a multiset of scslar values (say an INTEGER MULTISET) then the relation's type will be a row with a single field, and that field will need to be dereferenced.

Parameters:
calc - The CalcRel that the multiset call belongs to
offset - Ordinal of the expression to transform.

createUncollect

private static UncollectRel createUncollect(CalcRel calc,
                                            RexLocalRef local,
                                            List<CorrelatorRel.Correlation> correlationList)

createProject

private static RelNode createProject(CalcRel calc,
                                     RexLocalRef local,
                                     List<CorrelatorRel.Correlation> correlationList)

createLimitRel

private static RelNode createLimitRel(RelNode child)
Creates a relational expression which ensures that a given expression only returns one row, and throws a runtime error otherwise. The result is
 ProjectRel($0)
   FilterRel[condition=CASE WHEN $0==1 THEN true ELSE throw("21000") END]
     AggregateRel[count(*), $0]

 
where 21000 is the standard CARDINALITY VIOLATION error code.

Parameters:
child - Child relational expression
Returns:
A relational expression of the same type
"Postcondition:"
return.getRowType() == child.getRowType()

containsNestedMultiset

private boolean containsNestedMultiset(RexProgram program)
Returns true if any expression in a program contains a multiset call directly under another multiset call.


containsNestedMultiset

private boolean containsNestedMultiset(RexNode node,
                                       boolean deep)
Returns true if node contains a multiset call directly under another multiset call.


createExistsPlanSingleRow

public RelNode createExistsPlanSingleRow(RelNode child,
                                         boolean neg)