public abstract class CalcRelSplitter extends Object
Calc with multiple RexCall
sub-expressions that cannot all be implemented by a single concrete
RelNode.
For example, the Java and Fennel calculator do not implement an identical set of operators. The Calc can be used to split a single Calc with mixed Java- and Fennel-only operators into a tree of Calc object that can each be individually implemented by either Java or Fennel.and splits it into several Calc instances.
Currently the splitter is only capable of handling two "rel types". That is, it can deal with Java vs. Fennel Calcs, but not Java vs. Fennel vs. some other type of Calc.
See ProjectToWindowRule
for an example of how this class is used.
| Modifier and Type | Class and Description |
|---|---|
private static class |
CalcRelSplitter.CannotImplement
Control exception for
CalcRelSplitter.ImplementTester. |
private static class |
CalcRelSplitter.HighestUsageFinder
Builds an array of the highest level which contains an expression which
uses each expression as an input.
|
private static class |
CalcRelSplitter.ImplementTester
Visitor which returns whether an expression can be implemented in a given
type of relational expression.
|
private static class |
CalcRelSplitter.InputToCommonExprConverter
Shuttle which converts every reference to an input field in an expression
to a reference to a common sub-expression.
|
private static class |
CalcRelSplitter.MaxInputFinder
Finds the highest level used by any of the inputs of a given expression.
|
static class |
CalcRelSplitter.RelType
Type of relational expression.
|
| Modifier and Type | Field and Description |
|---|---|
private RelNode |
child |
private RelOptCluster |
cluster |
protected RexProgram |
program |
protected RelBuilder |
relBuilder |
private CalcRelSplitter.RelType[] |
relTypes |
private static org.slf4j.Logger |
RULE_LOGGER |
private RelTraitSet |
traits |
private RelDataTypeFactory |
typeFactory |
| Constructor and Description |
|---|
CalcRelSplitter(Calc calc,
RelBuilder relBuilder,
CalcRelSplitter.RelType[] relTypes)
Constructs a CalcRelSplitter.
|
| Modifier and Type | Method and Description |
|---|---|
protected boolean |
canImplement(LogicalCalc rel,
String relTypeName)
Returns whether a relational expression can be implemented solely in a
given
CalcRelSplitter.RelType. |
private int |
chooseLevels(RexNode[] exprs,
int conditionOrdinal,
int[] exprLevels,
int[] levelTypeOrdinals)
Figures out which expressions to calculate at which level.
|
private List<Integer> |
computeTopologicalOrdering(RexNode[] exprs,
List<Set<Integer>> cohorts)
Computes the order in which to visit expressions, so that we decide the
level of an expression only after the levels of lower expressions have
been decided.
|
private static int |
count(boolean[] booleans)
Returns the number of bits set in an array.
|
private RexProgram |
createProgramForLevel(int level,
int levelCount,
RelDataType inputRowType,
RexNode[] allExprs,
int[] exprLevels,
int[] inputExprOrdinals,
int[] projectExprOrdinals,
int conditionExprOrdinal,
RelDataType outputRowType)
Creates a program containing the expressions for a given level.
|
private String |
deriveFieldName(RexNode expr,
int ordinal) |
(package private) RelNode |
execute() |
private static Set<Integer> |
findCohort(List<Set<Integer>> cohorts,
int ordinal)
Finds the cohort that contains the given integer, or returns null.
|
private static int |
firstSet(boolean[] booleans)
Returns the index of the first set bit in an array.
|
protected List<Set<Integer>> |
getCohorts()
Returns a list of sets of expressions that should be on the same level.
|
protected RelNode |
handle(RelNode rel)
Opportunity to further refine the relational expression created for a
given level.
|
private int[] |
identityArray(int length) |
private static int |
indexOf(int value,
int[] map)
Searches for a value in a map, and returns the position where it was
found, or -1.
|
private void |
traceLevelExpressions(RexNode[] exprs,
int[] exprLevels,
int[] levelTypeOrdinals,
int levelCount)
Traces the given array of level expression lists at the finer level.
|
private static final org.slf4j.Logger RULE_LOGGER
protected final RexProgram program
private final RelDataTypeFactory typeFactory
private final CalcRelSplitter.RelType[] relTypes
private final RelOptCluster cluster
private final RelTraitSet traits
private final RelNode child
protected final RelBuilder relBuilder
CalcRelSplitter(Calc calc, RelBuilder relBuilder, CalcRelSplitter.RelType[] relTypes)
calc - Calc to splitrelTypes - Array of rel types, e.g. {Java, Fennel}. Must be
distinct.RelNode execute()
protected RelNode handle(RelNode rel)
private int chooseLevels(RexNode[] exprs, int conditionOrdinal, int[] exprLevels, int[] levelTypeOrdinals)
exprs - Array of expressionsconditionOrdinal - Ordinal of the condition expression, or -1 if no
conditionexprLevels - Level ordinal for each expression (output)levelTypeOrdinals - The type of each level (output)private List<Integer> computeTopologicalOrdering(RexNode[] exprs, List<Set<Integer>> cohorts)
First, we need to ensure that an expression is visited after all of its inputs.
Further, if the expression is a member of a cohort, we need to visit it after the inputs of all other expressions in that cohort. With this condition, expressions in the same cohort will very likely end up in the same level.
Note that if there are no cohorts, the expressions from the
RexProgram are already in a suitable order. We perform the
topological sort just to ensure that the code path is well-trodden.
exprs - Expressionscohorts - List of cohorts, each of which is a set of expr ordinalsprivate static Set<Integer> findCohort(List<Set<Integer>> cohorts, int ordinal)
cohorts - List of cohorts, each a set of integersordinal - Integer to search forprivate int[] identityArray(int length)
private RexProgram createProgramForLevel(int level, int levelCount, RelDataType inputRowType, RexNode[] allExprs, int[] exprLevels, int[] inputExprOrdinals, int[] projectExprOrdinals, int conditionExprOrdinal, RelDataType outputRowType)
The expression list of the program will consist of all entries in the
expression list allExprs[i] for which the corresponding
level ordinal exprLevels[i] is equal to level.
Expressions are mapped according to inputExprOrdinals.
level - Level ordinallevelCount - Number of levelsinputRowType - Input row typeallExprs - Array of all expressionsexprLevels - Array of the level ordinal of each expressioninputExprOrdinals - Ordinals in the expression list of input
expressions. Input expression i
will be found at position
inputExprOrdinals[i].projectExprOrdinals - Ordinals of the expressions to be output this
level.conditionExprOrdinal - Ordinal of the expression to form the
condition for this level, or -1 if there is no
condition.outputRowType - Output row typeprivate void traceLevelExpressions(RexNode[] exprs, int[] exprLevels, int[] levelTypeOrdinals, int levelCount)
exprs - Array expressionsexprLevels - For each expression, the ordinal of its levellevelTypeOrdinals - For each level, the ordinal of its type in
the relTypes arraylevelCount - The number of levelsprivate static int count(boolean[] booleans)
private static int firstSet(boolean[] booleans)
private static int indexOf(int value,
int[] map)
value - Value to search formap - Map to search inprotected boolean canImplement(LogicalCalc rel, String relTypeName)
CalcRelSplitter.RelType.rel - Calculation relational expressionrelTypeName - Name of a CalcRelSplitter.RelTypeprotected List<Set<Integer>> getCohorts()
For example, if this method returns { {3, 5}, {4, 7} }, it means that expressions 3 and 5, should be on the same level, and expressions 4 and 7 should be on the same level. The two cohorts do not need to be on the same level.
The list is best effort. If it is not possible to arrange that the
expressions in a cohort are on the same level, the execute()
method will still succeed.
The default implementation of this method returns the empty list; expressions will be put on the most suitable level. This is generally the lowest possible level, except for literals, which are placed at the level where they are used.
Copyright © 2012–2018 The Apache Software Foundation. All rights reserved.