org.eigenbase.rex
Class RexProgramBuilder

java.lang.Object
  extended by org.eigenbase.rex.RexProgramBuilder

public class RexProgramBuilder
extends Object

Workspace for constructing a RexProgram.

RexProgramBuilder is necessary because a RexProgram is immutable. (The String class has the same problem: it is immutable, so they introduced StringBuffer.)

Since:
Aug 18, 2005
Version:
$Id: //open/dev/farrago/src/org/eigenbase/rex/RexProgramBuilder.java#15 $
Author:
jhyde
See Also:
RexProgramBuilder

Nested Class Summary
private  class RexProgramBuilder.RegisterInputShuttle
          Shuttle which walks over an expression, registering each sub-expression.
private  class RexProgramBuilder.RegisterMidputShuttle
          Extension to RexProgramBuilder.RegisterInputShuttle which allows expressions to be in terms of inputs or previous common sub-expressions.
private  class RexProgramBuilder.RegisterOutputShuttle
          Shuttle which walks over an expression, registering each sub-expression.
private  class RexProgramBuilder.RegisterShuttle
           
private  class RexProgramBuilder.UpdateRefShuttle
          Shuttle which rewires RexLocalRef using a list of updated references
private  class RexProgramBuilder.UsageVisitor
          Visitor which marks which expressions are used.
 
Field Summary
private  RexLocalRef conditionRef
           
private  List<RexNode> exprList
           
private  Map<String,RexLocalRef> exprMap
           
private  RelDataType inputRowType
           
private  List<RexLocalRef> localRefList
           
private  List<String> projectNameList
           
private  List<RexLocalRef> projectRefList
           
private  RexBuilder rexBuilder
           
private  boolean validating
           
 
Constructor Summary
  RexProgramBuilder(RelDataType inputRowType, RexBuilder rexBuilder)
          Creates a program-builder.
private RexProgramBuilder(RexBuilder rexBuilder, RelDataType inputRowType, List<RexNode> exprList, List<RexLocalRef> projectRefList, RexLocalRef conditionRef, RelDataType outputRowType)
          Creates a program builder with the same contents as a program.
 
Method Summary
private  void add(List<RexNode> exprList, List<RexLocalRef> projectRefList, RexLocalRef conditionRef, RelDataType outputRowType, RexShuttle shuttle, boolean updateRefs)
          Adds a set of expressions, projections and filters, applying a shuttle first.
 void addCondition(RexNode expr)
          Sets the condition of the program.
 RexLocalRef addExpr(RexNode expr)
          Adds an expression to the list of common expressions, and returns a reference to the expression.
 void addIdentity()
          Adds a project item for every input field.
 RexLocalRef addProject(int at, int ordinal, String name)
          Adds a projection based upon the indexth expression at a given position.
 RexLocalRef addProject(int at, RexNode expr, String name)
          Adds a project expression to the program at a given position.
 RexLocalRef addProject(int ordinal, String name)
          Adds a projection based upon the indexth expression.
 RexLocalRef addProject(RexNode expr, String name)
          Adds a project expression to the program.
private static boolean assertionsAreEnabled()
          Returns whether assertions are enabled in this class.
 void clearProjects()
          Removes all project items.
static RexProgramBuilder create(RexBuilder rexBuilder, RelDataType inputRowType, List<RexNode> exprList, List<RexLocalRef> projectRefList, RexLocalRef conditionRef, RelDataType outputRowType)
          Creates a program builder with the same contents as a program.
static RexProgramBuilder create(RexBuilder rexBuilder, RelDataType inputRowType, List<RexNode> exprList, List<RexLocalRef> projectRefList, RexLocalRef conditionRef, RelDataType outputRowType, RexShuttle shuttle, boolean updateRefs)
          Creates a program builder with the same contents as a program, applying a shuttle first.
 void eliminateUnused()
          Eliminate unused expressions.
static RexProgramBuilder forProgram(RexProgram program, RexBuilder rexBuilder)
          Creates a program builder and initializes it from an existing program.
private  void generateMissingNames()
           
 RelDataType getInputRowType()
          Returns the rowtype of the input to the program
 RexProgram getProgram()
          Converts the state of the program builder to an immutable program.
 List<RexLocalRef> getProjectList()
          Returns the list of project expressions.
 RexLocalRef makeInputRef(int index)
          Creates a reference to a given input field
static RexProgram mergePrograms(RexProgram topProgram, RexProgram bottomProgram, RexBuilder rexBuilder)
          Merges two programs together.
 RexLocalRef registerInput(RexNode expr)
          Registers an expression in the list of common sub-expressions, and returns a reference to that expression.
private  RexLocalRef registerInternal(RexNode expr, boolean force)
          Registers an expression in the list of common sub-expressions, and returns a reference to that expression.
 RexLocalRef registerOutput(RexNode expr)
          Converts an expression expressed in terms of the outputs of this program into an expression expressed in terms of the inputs, registers it in the list of common sub-expressions, and returns a reference to that expression.
private  List<RexLocalRef> registerProjectsAndCondition(RexProgram program)
           
private  void validate(RexNode expr, int fieldOrdinal)
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

rexBuilder

private final RexBuilder rexBuilder

inputRowType

private final RelDataType inputRowType

exprList

private final List<RexNode> exprList

exprMap

private final Map<String,RexLocalRef> exprMap

localRefList

private final List<RexLocalRef> localRefList

projectRefList

private final List<RexLocalRef> projectRefList

projectNameList

private final List<String> projectNameList

conditionRef

private RexLocalRef conditionRef

validating

private boolean validating
Constructor Detail

RexProgramBuilder

public RexProgramBuilder(RelDataType inputRowType,
                         RexBuilder rexBuilder)
Creates a program-builder.


RexProgramBuilder

private RexProgramBuilder(RexBuilder rexBuilder,
                          RelDataType inputRowType,
                          List<RexNode> exprList,
                          List<RexLocalRef> projectRefList,
                          RexLocalRef conditionRef,
                          RelDataType outputRowType)
Creates a program builder with the same contents as a program.

Parameters:
rexBuilder - Rex builder
inputRowType - Input row type
exprList - Common expressions
projectRefList - Projections
conditionRef - Condition, or null
outputRowType - Output row type
Method Detail

assertionsAreEnabled

private static boolean assertionsAreEnabled()
Returns whether assertions are enabled in this class.


validate

private void validate(RexNode expr,
                      int fieldOrdinal)

addProject

public RexLocalRef addProject(RexNode expr,
                              String name)
Adds a project expression to the program.

The expression specified in terms of the input fields. If not, call registerOutput(RexNode) first.

Parameters:
expr - Expression to add
name - Name of field in output row type; if null, a unique name will be generated when the program is created
Returns:
the ref created

addProject

public RexLocalRef addProject(int ordinal,
                              String name)
Adds a projection based upon the indexth expression.

Parameters:
ordinal - Index of expression to project
name -
Returns:
the ref created

addProject

public RexLocalRef addProject(int at,
                              RexNode expr,
                              String name)
Adds a project expression to the program at a given position.

The expression specified in terms of the input fields. If not, call registerOutput(RexNode) first.

Parameters:
at - Position in project list to add expression
expr - Expression to add
name - Name of field in output row type; if null, a unique name will be generated when the program is created
Returns:
the ref created

addProject

public RexLocalRef addProject(int at,
                              int ordinal,
                              String name)
Adds a projection based upon the indexth expression at a given position.

Parameters:
at - Position in project list to add expression
ordinal - Index of expression to project
name -
Returns:
the ref created

addCondition

public void addCondition(RexNode expr)
Sets the condition of the program.

The expression must be specified in terms of the input fields. If not, call registerOutput(RexNode) first.


registerInput

public RexLocalRef registerInput(RexNode expr)
Registers an expression in the list of common sub-expressions, and returns a reference to that expression.

The expression must be expressed in terms of the inputs of this program.


registerOutput

public RexLocalRef registerOutput(RexNode expr)
Converts an expression expressed in terms of the outputs of this program into an expression expressed in terms of the inputs, registers it in the list of common sub-expressions, and returns a reference to that expression.

Parameters:
expr - Expression to register

registerInternal

private RexLocalRef registerInternal(RexNode expr,
                                     boolean force)
Registers an expression in the list of common sub-expressions, and returns a reference to that expression.

If an equivalent sub-expression already exists, creates another expression only if force is true.

Parameters:
expr - Expression to register
force - Whether to create a new sub-expression if an equivalent sub-expression exists.

addExpr

public RexLocalRef addExpr(RexNode expr)
Adds an expression to the list of common expressions, and returns a reference to the expression. DOES NOT CHECK WHETHER THE EXPRESSION ALREADY EXISTS.

Parameters:
expr - Expression
Returns:
Reference to expression

getProgram

public RexProgram getProgram()
Converts the state of the program builder to an immutable program.

It is OK to call this method, modify the program specification (by adding projections, and so forth), and call this method again.


generateMissingNames

private void generateMissingNames()

forProgram

public static RexProgramBuilder forProgram(RexProgram program,
                                           RexBuilder rexBuilder)
Creates a program builder and initializes it from an existing program.

Calling getProgram() immediately after creation will return a program equivalent (in terms of external behavior) to the existing program.

The existing program will not be changed. (It cannot: programs are immutable.)

Parameters:
program - Existing program
rexBuilder - Rex builder
Returns:
A program builder initialized with an equivalent program

create

public static RexProgramBuilder create(RexBuilder rexBuilder,
                                       RelDataType inputRowType,
                                       List<RexNode> exprList,
                                       List<RexLocalRef> projectRefList,
                                       RexLocalRef conditionRef,
                                       RelDataType outputRowType)
Creates a program builder with the same contents as a program.

Parameters:
rexBuilder - Rex builder
inputRowType - Input row type
exprList - Common expressions
projectRefList - Projections
conditionRef - Condition, or null
outputRowType - Output row type
Returns:
A program builder

create

public static RexProgramBuilder create(RexBuilder rexBuilder,
                                       RelDataType inputRowType,
                                       List<RexNode> exprList,
                                       List<RexLocalRef> projectRefList,
                                       RexLocalRef conditionRef,
                                       RelDataType outputRowType,
                                       RexShuttle shuttle,
                                       boolean updateRefs)
Creates a program builder with the same contents as a program, applying a shuttle first.

TODO: Refactor the above create method in terms of this one.

Parameters:
rexBuilder - Rex builder
inputRowType - Input row type
exprList - Common expressions
projectRefList - Projections
conditionRef - Condition, or null
outputRowType - Output row type
shuttle - Shuttle to apply to each expression before adding it to the program builder
updateRefs - Whether to update references that changes as a result of rewrites made by the shuttle
Returns:
A program builder

add

private void add(List<RexNode> exprList,
                 List<RexLocalRef> projectRefList,
                 RexLocalRef conditionRef,
                 RelDataType outputRowType,
                 RexShuttle shuttle,
                 boolean updateRefs)
Adds a set of expressions, projections and filters, applying a shuttle first.

Parameters:
exprList - Common expressions
projectRefList - Projections
conditionRef - Condition, or null
outputRowType - Output row type
shuttle - Shuttle to apply to each expression before adding it to the program builder
updateRefs - Whether to update references that changes as a result of rewrites made by the shuttle

eliminateUnused

public void eliminateUnused()
Eliminate unused expressions.


mergePrograms

public static RexProgram mergePrograms(RexProgram topProgram,
                                       RexProgram bottomProgram,
                                       RexBuilder rexBuilder)
Merges two programs together.

All expressions become common sub-expressions. For example, the query

SELECT x + 1 AS p, x + y AS q FROM (
   SELECT a + b AS x, c AS y
   FROM t
   WHERE c = 6)
would be represented as the programs
   Calc:
       Projects={$2, $3},
       Condition=null,
       Exprs={$0, $1, $0 + 1, $0 + $1})
   Calc(
       Projects={$3, $2},
       Condition={$4}
       Exprs={$0, $1, $2, $0 + $1, $2 = 6}
 

The merged program is

   Calc(
      Projects={$4, $5}
      Condition=$6
      Exprs={0: $0       // a
             1: $1        // b
             2: $2        // c
             3: ($0 + $1) // x = a + b
             4: ($3 + 1)  // p = x + 1
             5: ($3 + $2) // q = x + y
             6: ($2 = 6)  // c = 6
 

Another example:

SELECT *
 FROM (
   SELECT a + b AS x, c AS y
   FROM t
   WHERE c = 6)
 WHERE x = 5
becomes
SELECT a + b AS x, c AS y
 FROM t
 WHERE c = 6 AND (a + b) = 5

Parameters:
topProgram - Top program. Its expressions are in terms of the outputs of the bottom program.
bottomProgram - Bottom program. Its expressions are in terms of the result fields of the relational expression's input
rexBuilder -
Returns:
Merged program

registerProjectsAndCondition

private List<RexLocalRef> registerProjectsAndCondition(RexProgram program)

clearProjects

public void clearProjects()
Removes all project items.


addIdentity

public void addIdentity()
Adds a project item for every input field.

You cannot call this method if there are other project items.

"Precondition:"
projectRefList.isEmpty()

makeInputRef

public RexLocalRef makeInputRef(int index)
Creates a reference to a given input field

Parameters:
index - Ordinal of input field, must be less than the number of fields in the input type
Returns:
Reference to input field

getInputRowType

public RelDataType getInputRowType()
Returns the rowtype of the input to the program


getProjectList

public List<RexLocalRef> getProjectList()
Returns the list of project expressions.