Java源码示例:org.apache.calcite.rex.RexProgramBuilder
示例1
@Override
public void onMatch(RelOptRuleCall call) {
LogicalCalc calc = call.rel(0);
// Expand decimals in every expression in this program. If no
// expression changes, don't apply the rule.
final RexProgram program = calc.getProgram();
if (!RexUtil.requiresDecimalExpansion(program, true)) {
return;
}
final RexBuilder rexBuilder = calc.getCluster().getRexBuilder();
final RexShuttle shuttle = new DecimalShuttle(rexBuilder);
RexProgramBuilder programBuilder = RexProgramBuilder.create(rexBuilder, calc.getInput().getRowType(),
program.getExprList(), program.getProjectList(), program.getCondition(), program.getOutputRowType(),
shuttle, true);
final RexProgram newProgram = programBuilder.getProgram();
LogicalCalc newCalc = LogicalCalc.create(calc.getInput(), newProgram);
call.transformTo(newCalc);
}
示例2
public void onMatch(RelOptRuleCall call) {
final Filter topFilter = call.rel(0);
final Filter bottomFilter = call.rel(1);
// use RexPrograms to merge the two FilterRels into a single program
// so we can convert the two LogicalFilter conditions to directly
// reference the bottom LogicalFilter's child
RexBuilder rexBuilder = topFilter.getCluster().getRexBuilder();
RexProgram bottomProgram = createProgram(bottomFilter);
RexProgram topProgram = createProgram(topFilter);
RexProgram mergedProgram = RexProgramBuilder.mergePrograms(topProgram, bottomProgram, rexBuilder);
RexNode newCondition = mergedProgram.expandLocalRef(mergedProgram.getCondition());
final RelBuilder relBuilder = call.builder();
relBuilder.push(bottomFilter.getInput()).filter(newCondition);
call.transformTo(relBuilder.build());
}
示例3
public void onMatch(RelOptRuleCall call) {
final EnumerableFilter filter = call.rel(0);
final RelNode input = filter.getInput();
// Create a program containing a filter.
final RexBuilder rexBuilder = filter.getCluster().getRexBuilder();
final RelDataType inputRowType = input.getRowType();
final RexProgramBuilder programBuilder =
new RexProgramBuilder(inputRowType, rexBuilder);
programBuilder.addIdentity();
programBuilder.addCondition(filter.getCondition());
final RexProgram program = programBuilder.getProgram();
final EnumerableCalc calc = EnumerableCalc.create(input, program);
call.transformTo(calc);
}
示例4
public void onMatch(RelOptRuleCall call) {
final Filter topFilter = call.rel(0);
final Filter bottomFilter = call.rel(1);
// use RexPrograms to merge the two FilterRels into a single program
// so we can convert the two LogicalFilter conditions to directly
// reference the bottom LogicalFilter's child
RexBuilder rexBuilder = topFilter.getCluster().getRexBuilder();
RexProgram bottomProgram = createProgram(bottomFilter);
RexProgram topProgram = createProgram(topFilter);
RexProgram mergedProgram =
RexProgramBuilder.mergePrograms(
topProgram,
bottomProgram,
rexBuilder);
RexNode newCondition =
mergedProgram.expandLocalRef(
mergedProgram.getCondition());
final RelBuilder relBuilder = call.builder();
relBuilder.push(bottomFilter.getInput())
.filter(newCondition);
call.transformTo(relBuilder.build());
}
示例5
/**
* Creates a RexProgram corresponding to a LogicalFilter
*
* @param filterRel the LogicalFilter
* @return created RexProgram
*/
private RexProgram createProgram(Filter filterRel) {
RexProgramBuilder programBuilder =
new RexProgramBuilder(
filterRel.getRowType(),
filterRel.getCluster().getRexBuilder());
programBuilder.addIdentity();
programBuilder.addCondition(filterRel.getCondition());
return programBuilder.getProgram();
}
示例6
public void onMatch(RelOptRuleCall call) {
final LogicalFilter filter = call.rel(0);
final LogicalCalc calc = call.rel(1);
// Don't merge a filter onto a calc which contains windowed aggregates.
// That would effectively be pushing a multiset down through a filter.
// We'll have chance to merge later, when the over is expanded.
if (calc.getProgram().containsAggs()) {
return;
}
// Create a program containing the filter.
final RexBuilder rexBuilder = filter.getCluster().getRexBuilder();
final RexProgramBuilder progBuilder =
new RexProgramBuilder(
calc.getRowType(),
rexBuilder);
progBuilder.addIdentity();
progBuilder.addCondition(filter.getCondition());
RexProgram topProgram = progBuilder.getProgram();
RexProgram bottomProgram = calc.getProgram();
// Merge the programs together.
RexProgram mergedProgram =
RexProgramBuilder.mergePrograms(
topProgram,
bottomProgram,
rexBuilder);
final LogicalCalc newCalc =
LogicalCalc.create(calc.getInput(), mergedProgram);
call.transformTo(newCalc);
}
示例7
public void rewriteRel(LogicalCalc rel) {
// Translate the child.
final RelNode newInput = getNewForOldRel(rel.getInput());
final RelOptCluster cluster = rel.getCluster();
RexProgramBuilder programBuilder = new RexProgramBuilder(newInput.getRowType(), cluster.getRexBuilder());
// Convert the common expressions.
final RexProgram program = rel.getProgram();
final RewriteRexShuttle shuttle = new RewriteRexShuttle();
for (RexNode expr : program.getExprList()) {
programBuilder.registerInput(expr.accept(shuttle));
}
// Convert the projections.
final List<Pair<RexNode, String>> flattenedExpList = new ArrayList<>();
List<String> fieldNames = rel.getRowType().getFieldNames();
flattenProjections(new RewriteRexShuttle(), program.getProjectList(), fieldNames, "", flattenedExpList);
// Register each of the new projections.
for (Pair<RexNode, String> flattenedExp : flattenedExpList) {
programBuilder.addProject(flattenedExp.left, flattenedExp.right);
}
// Translate the condition.
final RexLocalRef conditionRef = program.getCondition();
if (conditionRef != null) {
final Ord<RelDataType> newField = getNewFieldForOldInput(conditionRef.getIndex());
programBuilder.addCondition(RexBuilder.getRexFactory().makeInputRef(newField.i, newField.e));
}
RexProgram newProgram = programBuilder.getProgram();
// Create a new calc relational expression.
LogicalCalc newRel = LogicalCalc.create(newInput, newProgram);
setNewForOldRel(rel, newRel);
}
示例8
public void onMatch(RelOptRuleCall call) {
Filter topFilter = call.rel(0);
Filter bottomFilter = call.rel(1);
// use RexPrograms to merge the two FilterRels into a single program
// so we can convert the two FilterRel conditions to directly
// reference the bottom FilterRel's child
RexBuilder rexBuilder = topFilter.getCluster().getRexBuilder();
RexProgram bottomProgram = createProgram(bottomFilter);
RexProgram topProgram = createProgram(topFilter);
RexProgram mergedProgram =
RexProgramBuilder.mergePrograms(
topProgram,
bottomProgram,
rexBuilder);
RexNode newCondition =
mergedProgram.expandLocalRef(
mergedProgram.getCondition());
// if(!RexUtil.isFlat(newCondition)){
// RexCall newCall = (RexCall) newCondition;
// newCondition = rexBuilder.makeFlatCall( newCall.getOperator(), newCall.getOperands());
// }
Filter newFilterRel =
(Filter) filterFactory.createFilter(
bottomFilter.getInput(),
RexUtil.flatten(rexBuilder, newCondition));
call.transformTo(newFilterRel);
}
示例9
/**
* Creates a RexProgram corresponding to a LogicalFilter
*
* @param filterRel the LogicalFilter
* @return created RexProgram
*/
private RexProgram createProgram(Filter filterRel) {
RexProgramBuilder programBuilder =
new RexProgramBuilder(
filterRel.getRowType(),
filterRel.getCluster().getRexBuilder());
programBuilder.addIdentity();
programBuilder.addCondition(filterRel.getCondition());
return programBuilder.getProgram();
}
示例10
private String compile(RexBuilder rexBuilder, List<RexNode> constExps,
RexToLixTranslator.InputGetter getter, RelDataType rowType) {
final RexProgramBuilder programBuilder =
new RexProgramBuilder(rowType, rexBuilder);
for (RexNode node : constExps) {
programBuilder.addProject(
node, "c" + programBuilder.getProjectList().size());
}
final JavaTypeFactoryImpl javaTypeFactory =
new JavaTypeFactoryImpl(rexBuilder.getTypeFactory().getTypeSystem());
final BlockBuilder blockBuilder = new BlockBuilder();
final ParameterExpression root0_ =
Expressions.parameter(Object.class, "root0");
final ParameterExpression root_ = DataContext.ROOT;
blockBuilder.add(
Expressions.declare(
Modifier.FINAL, root_,
Expressions.convert_(root0_, DataContext.class)));
final SqlConformance conformance = SqlConformanceEnum.HIVE;
final RexProgram program = programBuilder.getProgram();
final List<Expression> expressions =
RexToLixTranslator.translateProjects(program, javaTypeFactory,
conformance, blockBuilder, null, root_, getter, null);
blockBuilder.add(
Expressions.return_(null,
Expressions.newArrayInit(Object[].class, expressions)));
final MethodDeclaration methodDecl =
Expressions.methodDecl(Modifier.PUBLIC, Object[].class,
BuiltInMethod.FUNCTION1_APPLY.method.getName(),
ImmutableList.of(root0_), blockBuilder.toBlock());
String code = Expressions.toString(methodDecl);
if (CalcitePrepareImpl.DEBUG) {
Util.debugCode(System.out, code);
}
return code;
}
示例11
@Override
public EnumerableRel implementEnumerable(List<EnumerableRel> inputs) {
// keep it for having clause
RexBuilder rexBuilder = getCluster().getRexBuilder();
RelDataType inputRowType = getInput().getRowType();
RexProgramBuilder programBuilder = new RexProgramBuilder(inputRowType, rexBuilder);
programBuilder.addIdentity();
programBuilder.addCondition(this.condition);
RexProgram program = programBuilder.getProgram();
return new EnumerableCalc(getCluster(), getCluster().traitSetOf(EnumerableConvention.INSTANCE), //
sole(inputs), program);
}
示例12
/**
* Creates a RexProgram corresponding to a LogicalFilter
*
* @param filterRel
* the LogicalFilter
* @return created RexProgram
*/
private RexProgram createProgram(Filter filterRel) {
RexProgramBuilder programBuilder = new RexProgramBuilder(filterRel.getRowType(),
filterRel.getCluster().getRexBuilder());
programBuilder.addIdentity();
programBuilder.addCondition(filterRel.getCondition());
return programBuilder.getProgram();
}
示例13
/**
* Create quasi-Java expression from given {@link RexNode}
*
* @param node Expression in the form of {@link RexNode}
* @param inputRowType Input Data type to expression in the form of {@link RelDataType}
* @param outputRowType Output data type of expression in the form of {@link RelDataType}
*
* @return Returns quasi-Java expression
*/
public String getExpression(RexNode node, RelDataType inputRowType, RelDataType outputRowType)
{
final RexProgramBuilder programBuilder = new RexProgramBuilder(inputRowType, rexBuilder);
programBuilder.addProject(node, null);
final RexProgram program = programBuilder.getProgram();
final BlockBuilder builder = new BlockBuilder();
final JavaTypeFactory javaTypeFactory = (JavaTypeFactory)rexBuilder.getTypeFactory();
final RexToLixTranslator.InputGetter inputGetter = new RexToLixTranslator.InputGetterImpl(ImmutableList
.of(Pair.<Expression, PhysType>of(Expressions.variable(Object[].class, "inputValues"),
PhysTypeImpl.of(javaTypeFactory, inputRowType, JavaRowFormat.ARRAY, false))));
final Function1<String, RexToLixTranslator.InputGetter> correlates =
new Function1<String, RexToLixTranslator.InputGetter>()
{
public RexToLixTranslator.InputGetter apply(String a0)
{
throw new UnsupportedOperationException();
}
};
final List<Expression> list = RexToLixTranslator.translateProjects(program, javaTypeFactory, builder,
PhysTypeImpl.of(javaTypeFactory, outputRowType, JavaRowFormat.ARRAY, false), null, inputGetter, correlates);
for (int i = 0; i < list.size(); i++) {
Statement statement = Expressions.statement(list.get(i));
builder.add(statement);
}
return finalizeExpression(builder.toBlock(), inputRowType);
}
示例14
public BlockStatement compileToBlock(List<RexNode> nodes, RelDataType inputRowType) {
final RexProgramBuilder programBuilder =
new RexProgramBuilder(inputRowType, rexBuilder);
for (RexNode node : nodes) {
programBuilder.addProject(node, null);
}
return compileToBlock(programBuilder.getProgram());
}
示例15
public String compile(List<RexNode> nodes, RelDataType inputRowType, String className) {
final RexProgramBuilder programBuilder =
new RexProgramBuilder(inputRowType, rexBuilder);
for (RexNode node : nodes) {
programBuilder.addProject(node, null);
}
return compile(programBuilder.getProgram(), className);
}
示例16
@Override
public EnumerableRel implementEnumerable(List<EnumerableRel> inputs) {
// keep it for having clause
RexBuilder rexBuilder = getCluster().getRexBuilder();
RelDataType inputRowType = getInput().getRowType();
RexProgramBuilder programBuilder = new RexProgramBuilder(inputRowType, rexBuilder);
programBuilder.addIdentity();
programBuilder.addCondition(this.condition);
RexProgram program = programBuilder.getProgram();
return new EnumerableCalc(getCluster(), getCluster().traitSetOf(EnumerableConvention.INSTANCE), //
sole(inputs), program);
}
示例17
private FlinkLogicalCalc createTopCalc(
int primitiveLeftFieldCount,
RexBuilder rexBuilder,
ArrayBuffer<RexNode> extractedRexNodes,
RelDataType calcRowType,
FlinkLogicalCorrelate newCorrelate) {
RexProgram rexProgram = new RexProgramBuilder(newCorrelate.getRowType(), rexBuilder).getProgram();
int offset = extractedRexNodes.size() + primitiveLeftFieldCount;
// extract correlate output RexNode.
List<RexNode> newTopCalcProjects = rexProgram
.getExprList()
.stream()
.filter(x -> x instanceof RexInputRef)
.filter(x -> {
int index = ((RexInputRef) x).getIndex();
return index < primitiveLeftFieldCount || index >= offset;
})
.collect(Collectors.toList());
return new FlinkLogicalCalc(
newCorrelate.getCluster(),
newCorrelate.getTraitSet(),
newCorrelate,
RexProgram.create(
newCorrelate.getRowType(),
newTopCalcProjects,
null,
calcRowType,
rexBuilder));
}
示例18
private FlinkLogicalCalc createTopCalc(
int primitiveLeftFieldCount,
RexBuilder rexBuilder,
ArrayBuffer<RexNode> extractedRexNodes,
RelDataType calcRowType,
FlinkLogicalCorrelate newCorrelate) {
RexProgram rexProgram = new RexProgramBuilder(newCorrelate.getRowType(), rexBuilder).getProgram();
int offset = extractedRexNodes.size() + primitiveLeftFieldCount;
// extract correlate output RexNode.
List<RexNode> newTopCalcProjects = rexProgram
.getExprList()
.stream()
.filter(x -> x instanceof RexInputRef)
.filter(x -> {
int index = ((RexInputRef) x).getIndex();
return index < primitiveLeftFieldCount || index >= offset;
})
.collect(Collectors.toList());
return new FlinkLogicalCalc(
newCorrelate.getCluster(),
newCorrelate.getTraitSet(),
newCorrelate,
RexProgram.create(
newCorrelate.getRowType(),
newTopCalcProjects,
null,
calcRowType,
rexBuilder));
}
示例19
public void onMatch(RelOptRuleCall call) {
final LogicalFilter filter = call.rel(0);
final LogicalCalc calc = call.rel(1);
// Don't merge a filter onto a calc which contains windowed aggregates.
// That would effectively be pushing a multiset down through a filter.
// We'll have chance to merge later, when the over is expanded.
if (calc.getProgram().containsAggs()) {
return;
}
// Create a program containing the filter.
final RexBuilder rexBuilder = filter.getCluster().getRexBuilder();
final RexProgramBuilder progBuilder =
new RexProgramBuilder(
calc.getRowType(),
rexBuilder);
progBuilder.addIdentity();
progBuilder.addCondition(filter.getCondition());
RexProgram topProgram = progBuilder.getProgram();
RexProgram bottomProgram = calc.getProgram();
// Merge the programs together.
RexProgram mergedProgram =
RexProgramBuilder.mergePrograms(
topProgram,
bottomProgram,
rexBuilder);
final LogicalCalc newCalc =
LogicalCalc.create(calc.getInput(), mergedProgram);
call.transformTo(newCalc);
}
示例20
public void onMatch(RelOptRuleCall call) {
LogicalCalc calc = call.rel(0);
// Expand decimals in every expression in this program. If no
// expression changes, don't apply the rule.
final RexProgram program = calc.getProgram();
if (!RexUtil.requiresDecimalExpansion(program, true)) {
return;
}
final RexBuilder rexBuilder = calc.getCluster().getRexBuilder();
final RexShuttle shuttle = new DecimalShuttle(rexBuilder);
RexProgramBuilder programBuilder =
RexProgramBuilder.create(
rexBuilder,
calc.getInput().getRowType(),
program.getExprList(),
program.getProjectList(),
program.getCondition(),
program.getOutputRowType(),
shuttle,
true);
final RexProgram newProgram = programBuilder.getProgram();
LogicalCalc newCalc = LogicalCalc.create(calc.getInput(), newProgram);
call.transformTo(newCalc);
}
示例21
/** Returns a predicate expression based on a join condition. **/
static Expression generatePredicate(
EnumerableRelImplementor implementor,
RexBuilder rexBuilder,
RelNode left,
RelNode right,
PhysType leftPhysType,
PhysType rightPhysType,
RexNode condition) {
final BlockBuilder builder = new BlockBuilder();
final ParameterExpression left_ =
Expressions.parameter(leftPhysType.getJavaRowType(), "left");
final ParameterExpression right_ =
Expressions.parameter(rightPhysType.getJavaRowType(), "right");
final RexProgramBuilder program =
new RexProgramBuilder(
implementor.getTypeFactory().builder()
.addAll(left.getRowType().getFieldList())
.addAll(right.getRowType().getFieldList())
.build(),
rexBuilder);
program.addCondition(condition);
builder.add(
Expressions.return_(null,
RexToLixTranslator.translateCondition(program.getProgram(),
implementor.getTypeFactory(),
builder,
new RexToLixTranslator.InputGetterImpl(
ImmutableList.of(Pair.of(left_, leftPhysType),
Pair.of(right_, rightPhysType))),
implementor.allCorrelateVariables,
implementor.getConformance())));
return Expressions.lambda(Predicate2.class, builder.toBlock(), left_, right_);
}
示例22
@Test void testCalc() {
final FrameworkConfig config = RelBuilderTest.config().build();
final RelBuilder builder = RelBuilder.create(config);
final RexBuilder rexBuilder = builder.getRexBuilder();
final LogicalTableScan scan = (LogicalTableScan) builder.scan("EMP").build();
final RexProgramBuilder programBuilder =
new RexProgramBuilder(scan.getRowType(), rexBuilder);
final RelDataTypeField field = scan.getRowType().getField("SAL", false, false);
programBuilder.addIdentity();
programBuilder.addCondition(
rexBuilder.makeCall(SqlStdOperatorTable.GREATER_THAN,
new RexInputRef(field.getIndex(), field.getType()),
builder.literal(10)));
final LogicalCalc calc = LogicalCalc.create(scan, programBuilder.getProgram());
String relJson = RelOptUtil.dumpPlan("", calc,
SqlExplainFormat.JSON, SqlExplainLevel.EXPPLAN_ATTRIBUTES);
String s =
Frameworks.withPlanner((cluster, relOptSchema, rootSchema) -> {
final RelJsonReader reader = new RelJsonReader(
cluster, getSchema(calc), rootSchema);
RelNode node;
try {
node = reader.read(relJson);
} catch (IOException e) {
throw TestUtil.rethrow(e);
}
return RelOptUtil.dumpPlan("", node, SqlExplainFormat.TEXT,
SqlExplainLevel.EXPPLAN_ATTRIBUTES);
});
final String expected =
"LogicalCalc(expr#0..7=[{inputs}], expr#8=[10], expr#9=[>($t5, $t8)],"
+ " proj#0..7=[{exprs}], $condition=[$t9])\n"
+ " LogicalTableScan(table=[[scott, EMP]])\n";
assertThat(s, isLinux(expected));
}
示例23
public void onMatch(RelOptRuleCall call) {
final LogicalProject project = call.rel(0);
final LogicalCalc calc = call.rel(1);
// Don't merge a project which contains windowed aggregates onto a
// calc. That would effectively be pushing a windowed aggregate down
// through a filter. Transform the project into an identical calc,
// which we'll have chance to merge later, after the over is
// expanded.
final RelOptCluster cluster = project.getCluster();
RexProgram program =
RexProgram.create(
calc.getRowType(),
project.getProjects(),
null,
project.getRowType(),
cluster.getRexBuilder());
if (RexOver.containsOver(program)) {
LogicalCalc projectAsCalc = LogicalCalc.create(calc, program);
call.transformTo(projectAsCalc);
return;
}
// Create a program containing the project node's expressions.
final RexBuilder rexBuilder = cluster.getRexBuilder();
final RexProgramBuilder progBuilder =
new RexProgramBuilder(
calc.getRowType(),
rexBuilder);
for (Pair<RexNode, String> field : project.getNamedProjects()) {
progBuilder.addProject(field.left, field.right);
}
RexProgram topProgram = progBuilder.getProgram();
RexProgram bottomProgram = calc.getProgram();
// Merge the programs together.
RexProgram mergedProgram =
RexProgramBuilder.mergePrograms(
topProgram,
bottomProgram,
rexBuilder);
final LogicalCalc newCalc =
LogicalCalc.create(calc.getInput(), mergedProgram);
call.transformTo(newCalc);
}
示例24
/**
* Pulls the project above the semijoin and returns the resulting semijoin
* condition. As a result, the semijoin condition should be modified such
* that references to the LHS of a semijoin should now reference the
* children of the project that's on the LHS.
*
* @param project LogicalProject on the LHS of the semijoin
* @param semiJoin the semijoin
* @return the modified semijoin condition
*/
private RexNode adjustCondition(LogicalProject project, SemiJoin semiJoin) {
// create two RexPrograms -- the bottom one representing a
// concatenation of the project and the RHS of the semijoin and the
// top one representing the semijoin condition
RexBuilder rexBuilder = project.getCluster().getRexBuilder();
RelDataTypeFactory typeFactory = rexBuilder.getTypeFactory();
RelNode rightChild = semiJoin.getRight();
// for the bottom RexProgram, the input is a concatenation of the
// child of the project and the RHS of the semijoin
RelDataType bottomInputRowType =
SqlValidatorUtil.deriveJoinRowType(
project.getInput().getRowType(),
rightChild.getRowType(),
JoinRelType.INNER,
typeFactory,
null,
semiJoin.getSystemFieldList());
RexProgramBuilder bottomProgramBuilder =
new RexProgramBuilder(bottomInputRowType, rexBuilder);
// add the project expressions, then add input references for the RHS
// of the semijoin
for (Pair<RexNode, String> pair : project.getNamedProjects()) {
bottomProgramBuilder.addProject(pair.left, pair.right);
}
int nLeftFields = project.getInput().getRowType().getFieldCount();
List<RelDataTypeField> rightFields =
rightChild.getRowType().getFieldList();
int nRightFields = rightFields.size();
for (int i = 0; i < nRightFields; i++) {
final RelDataTypeField field = rightFields.get(i);
RexNode inputRef =
rexBuilder.makeInputRef(
field.getType(), i + nLeftFields);
bottomProgramBuilder.addProject(inputRef, field.getName());
}
RexProgram bottomProgram = bottomProgramBuilder.getProgram();
// input rowtype into the top program is the concatenation of the
// project and the RHS of the semijoin
RelDataType topInputRowType =
SqlValidatorUtil.deriveJoinRowType(
project.getRowType(),
rightChild.getRowType(),
JoinRelType.INNER,
typeFactory,
null,
semiJoin.getSystemFieldList());
RexProgramBuilder topProgramBuilder =
new RexProgramBuilder(
topInputRowType,
rexBuilder);
topProgramBuilder.addIdentity();
topProgramBuilder.addCondition(semiJoin.getCondition());
RexProgram topProgram = topProgramBuilder.getProgram();
// merge the programs and expand out the local references to form
// the new semijoin condition; it now references a concatenation of
// the project's child and the RHS of the semijoin
RexProgram mergedProgram =
RexProgramBuilder.mergePrograms(
topProgram,
bottomProgram,
rexBuilder);
return mergedProgram.expandLocalRef(
mergedProgram.getCondition());
}
示例25
/**
* Pulls the project above the semi/anti join and returns the resulting semi/anti join
* condition. As a result, the semi/anti join condition should be modified such
* that references to the LHS of a semi/anti join should now reference the
* children of the project that's on the LHS.
*
* @param project LogicalProject on the LHS of the semi/anti join
* @param join the semi/anti join
* @return the modified semi/anti join condition
*/
private RexNode adjustCondition(LogicalProject project, Join join) {
// create two RexPrograms -- the bottom one representing a
// concatenation of the project and the RHS of the semi/anti join and the
// top one representing the semi/anti join condition
RexBuilder rexBuilder = project.getCluster().getRexBuilder();
RelDataTypeFactory typeFactory = rexBuilder.getTypeFactory();
RelNode rightChild = join.getRight();
// for the bottom RexProgram, the input is a concatenation of the
// child of the project and the RHS of the semi/anti join
RelDataType bottomInputRowType =
SqlValidatorUtil.deriveJoinRowType(
project.getInput().getRowType(),
rightChild.getRowType(),
JoinRelType.INNER,
typeFactory,
null,
join.getSystemFieldList());
RexProgramBuilder bottomProgramBuilder =
new RexProgramBuilder(bottomInputRowType, rexBuilder);
// add the project expressions, then add input references for the RHS
// of the semi/anti join
for (Pair<RexNode, String> pair : project.getNamedProjects()) {
bottomProgramBuilder.addProject(pair.left, pair.right);
}
int nLeftFields = project.getInput().getRowType().getFieldCount();
List<RelDataTypeField> rightFields =
rightChild.getRowType().getFieldList();
int nRightFields = rightFields.size();
for (int i = 0; i < nRightFields; i++) {
final RelDataTypeField field = rightFields.get(i);
RexNode inputRef =
rexBuilder.makeInputRef(
field.getType(), i + nLeftFields);
bottomProgramBuilder.addProject(inputRef, field.getName());
}
RexProgram bottomProgram = bottomProgramBuilder.getProgram();
// input rowtype into the top program is the concatenation of the
// project and the RHS of the semi/anti join
RelDataType topInputRowType =
SqlValidatorUtil.deriveJoinRowType(
project.getRowType(),
rightChild.getRowType(),
JoinRelType.INNER,
typeFactory,
null,
join.getSystemFieldList());
RexProgramBuilder topProgramBuilder =
new RexProgramBuilder(
topInputRowType,
rexBuilder);
topProgramBuilder.addIdentity();
topProgramBuilder.addCondition(join.getCondition());
RexProgram topProgram = topProgramBuilder.getProgram();
// merge the programs and expand out the local references to form
// the new semi/anti join condition; it now references a concatenation of
// the project's child and the RHS of the semi/anti join
RexProgram mergedProgram =
RexProgramBuilder.mergePrograms(
topProgram,
bottomProgram,
rexBuilder);
return mergedProgram.expandLocalRef(
mergedProgram.getCondition());
}
示例26
public void onMatch(RelOptRuleCall call) {
final Join joinRel = call.rel(0);
final RelNode otherNode;
final Calc calc;
final RelNode leftJoinChild;
final RelNode rightJoinChild;
if (call.rel(1) instanceof Calc) {
otherNode = call.rel(2);
calc = call.rel(1);
rightJoinChild = otherNode;
leftJoinChild = calc.getInput();
} else {
otherNode = call.rel(1);
calc = call.rel(2);
rightJoinChild = calc.getInput();
leftJoinChild = otherNode;
}
/**
* Currently not supporting calc which doesnot
* project star (all the columns of input)
* or has aggregates.
*/
if (!isStar(calc.getProgram())
|| calc.getProgram().containsAggs()) {
return;
}
final List<RelDataTypeField> origFields =
calc.getRowType().getFieldList();
final int[] adjustments = new int[calc.getProgram().getExprCount()];
if (rightJoinChild == calc.getInput()) {
int offset = leftJoinChild.getRowType().getFieldList().size();
for (int i = 0; i < origFields.size(); i++) {
adjustments[i] = offset;
}
}
Join newJoinRel =
joinRel.copy(joinRel.getTraitSet(), joinRel.getCondition(),
leftJoinChild, rightJoinChild, joinRel.getJoinType(),
joinRel.isSemiJoinDone());
RexProgramBuilder topProgramBuilder =
new RexProgramBuilder(
joinRel.getRowType(),
joinRel.getCluster().getRexBuilder());
topProgramBuilder.addIdentity();
final RelOptUtil.RexInputConverter rexInputConverter =
new RelOptUtil.RexInputConverter(calc.getCluster().getRexBuilder(),
origFields,
joinRel.getRowType().getFieldList(),
adjustments);
if (calc.getProgram().getCondition() != null) {
RexNode cond =
calc.getProgram().expandLocalRef(calc.getProgram().getCondition());
final RexLocalRef rexLocalRef =
topProgramBuilder.addExpr(cond.accept(rexInputConverter));
topProgramBuilder.addCondition(rexLocalRef);
}
Calc newCalcRel =
calc.copy(calc.getTraitSet(), newJoinRel, topProgramBuilder.getProgram());
call.transformTo(newCalcRel);
}
示例27
@Override
public void onMatch(RelOptRuleCall call) {
FlinkLogicalCorrelate correlate = call.rel(0);
FlinkLogicalCalc right = call.rel(2);
RexBuilder rexBuilder = call.builder().getRexBuilder();
FlinkLogicalCalc mergedCalc = CorrelateUtil.getMergedCalc(right);
FlinkLogicalTableFunctionScan tableScan = CorrelateUtil.getTableFunctionScan(mergedCalc).get();
RexProgram mergedCalcProgram = mergedCalc.getProgram();
InputRefRewriter inputRefRewriter = new InputRefRewriter(
correlate.getRowType().getFieldCount() - mergedCalc.getRowType().getFieldCount());
List<RexNode> correlateFilters = RelOptUtil
.conjunctions(mergedCalcProgram.expandLocalRef(mergedCalcProgram.getCondition()))
.stream()
.map(x -> x.accept(inputRefRewriter))
.collect(Collectors.toList());
FlinkLogicalCorrelate newCorrelate = new FlinkLogicalCorrelate(
correlate.getCluster(),
correlate.getTraitSet(),
correlate.getLeft(),
tableScan,
correlate.getCorrelationId(),
correlate.getRequiredColumns(),
correlate.getJoinType());
RexNode topCalcCondition = RexUtil.composeConjunction(rexBuilder, correlateFilters);
RexProgram rexProgram = new RexProgramBuilder(
newCorrelate.getRowType(), rexBuilder).getProgram();
FlinkLogicalCalc newTopCalc = new FlinkLogicalCalc(
newCorrelate.getCluster(),
newCorrelate.getTraitSet(),
newCorrelate,
RexProgram.create(
newCorrelate.getRowType(),
rexProgram.getExprList(),
topCalcCondition,
newCorrelate.getRowType(),
rexBuilder));
call.transformTo(newTopCalc);
}
示例28
@Override
public void onMatch(RelOptRuleCall call) {
FlinkLogicalCorrelate correlate = call.rel(0);
FlinkLogicalCalc right = call.rel(2);
RexBuilder rexBuilder = call.builder().getRexBuilder();
FlinkLogicalCalc mergedCalc = StreamExecCorrelateRule.getMergedCalc(right);
FlinkLogicalTableFunctionScan tableScan = StreamExecCorrelateRule.getTableScan(mergedCalc);
RexProgram mergedCalcProgram = mergedCalc.getProgram();
InputRefRewriter inputRefRewriter = new InputRefRewriter(
correlate.getRowType().getFieldCount() - mergedCalc.getRowType().getFieldCount());
List<RexNode> correlateFilters = RelOptUtil
.conjunctions(mergedCalcProgram.expandLocalRef(mergedCalcProgram.getCondition()))
.stream()
.map(x -> x.accept(inputRefRewriter))
.collect(Collectors.toList());
FlinkLogicalCorrelate newCorrelate = new FlinkLogicalCorrelate(
correlate.getCluster(),
correlate.getTraitSet(),
correlate.getLeft(),
tableScan,
correlate.getCorrelationId(),
correlate.getRequiredColumns(),
correlate.getJoinType());
RexNode topCalcCondition = RexUtil.composeConjunction(rexBuilder, correlateFilters);
RexProgram rexProgram = new RexProgramBuilder(
newCorrelate.getRowType(), rexBuilder).getProgram();
FlinkLogicalCalc newTopCalc = new FlinkLogicalCalc(
newCorrelate.getCluster(),
newCorrelate.getTraitSet(),
newCorrelate,
RexProgram.create(
newCorrelate.getRowType(),
rexProgram.getExprList(),
topCalcCondition,
newCorrelate.getRowType(),
rexBuilder));
call.transformTo(newTopCalc);
}
示例29
/**
* Pulls the project above the semi/anti join and returns the resulting semi/anti join
* condition. As a result, the semi/anti join condition should be modified such
* that references to the LHS of a semi/anti join should now reference the
* children of the project that's on the LHS.
*
* @param project LogicalProject on the LHS of the semi/anti join
* @param join the semi/anti join
* @return the modified semi/anti join condition
*/
private RexNode adjustCondition(LogicalProject project, Join join) {
// create two RexPrograms -- the bottom one representing a
// concatenation of the project and the RHS of the semi/anti join and the
// top one representing the semi/anti join condition
RexBuilder rexBuilder = project.getCluster().getRexBuilder();
RelDataTypeFactory typeFactory = rexBuilder.getTypeFactory();
RelNode rightChild = join.getRight();
// for the bottom RexProgram, the input is a concatenation of the
// child of the project and the RHS of the semi/anti join
RelDataType bottomInputRowType =
SqlValidatorUtil.deriveJoinRowType(
project.getInput().getRowType(),
rightChild.getRowType(),
JoinRelType.INNER,
typeFactory,
null,
join.getSystemFieldList());
RexProgramBuilder bottomProgramBuilder =
new RexProgramBuilder(bottomInputRowType, rexBuilder);
// add the project expressions, then add input references for the RHS
// of the semi/anti join
for (Pair<RexNode, String> pair : project.getNamedProjects()) {
bottomProgramBuilder.addProject(pair.left, pair.right);
}
int nLeftFields = project.getInput().getRowType().getFieldCount();
List<RelDataTypeField> rightFields =
rightChild.getRowType().getFieldList();
int nRightFields = rightFields.size();
for (int i = 0; i < nRightFields; i++) {
final RelDataTypeField field = rightFields.get(i);
RexNode inputRef =
rexBuilder.makeInputRef(
field.getType(), i + nLeftFields);
bottomProgramBuilder.addProject(inputRef, field.getName());
}
RexProgram bottomProgram = bottomProgramBuilder.getProgram();
// input rowtype into the top program is the concatenation of the
// project and the RHS of the semi/anti join
RelDataType topInputRowType =
SqlValidatorUtil.deriveJoinRowType(
project.getRowType(),
rightChild.getRowType(),
JoinRelType.INNER,
typeFactory,
null,
join.getSystemFieldList());
RexProgramBuilder topProgramBuilder =
new RexProgramBuilder(
topInputRowType,
rexBuilder);
topProgramBuilder.addIdentity();
topProgramBuilder.addCondition(join.getCondition());
RexProgram topProgram = topProgramBuilder.getProgram();
// merge the programs and expand out the local references to form
// the new semi/anti join condition; it now references a concatenation of
// the project's child and the RHS of the semi/anti join
RexProgram mergedProgram =
RexProgramBuilder.mergePrograms(
topProgram,
bottomProgram,
rexBuilder);
return mergedProgram.expandLocalRef(
mergedProgram.getCondition());
}
示例30
public void onMatch(RelOptRuleCall call) {
final LogicalProject project = call.rel(0);
final LogicalCalc calc = call.rel(1);
// Don't merge a project which contains windowed aggregates onto a
// calc. That would effectively be pushing a windowed aggregate down
// through a filter. Transform the project into an identical calc,
// which we'll have chance to merge later, after the over is
// expanded.
final RelOptCluster cluster = project.getCluster();
RexProgram program =
RexProgram.create(
calc.getRowType(),
project.getProjects(),
null,
project.getRowType(),
cluster.getRexBuilder());
if (RexOver.containsOver(program)) {
LogicalCalc projectAsCalc = LogicalCalc.create(calc, program);
call.transformTo(projectAsCalc);
return;
}
// Create a program containing the project node's expressions.
final RexBuilder rexBuilder = cluster.getRexBuilder();
final RexProgramBuilder progBuilder =
new RexProgramBuilder(
calc.getRowType(),
rexBuilder);
for (Pair<RexNode, String> field : project.getNamedProjects()) {
progBuilder.addProject(field.left, field.right);
}
RexProgram topProgram = progBuilder.getProgram();
RexProgram bottomProgram = calc.getProgram();
// Merge the programs together.
RexProgram mergedProgram =
RexProgramBuilder.mergePrograms(
topProgram,
bottomProgram,
rexBuilder);
final LogicalCalc newCalc =
LogicalCalc.create(calc.getInput(), mergedProgram);
call.transformTo(newCalc);
}