use of org.apache.calcite.rex.RexProgramBuilder in project calcite by apache.
the class RexProgramTest method createProg.
/**
* Creates a program, depending on variant:
*
* <ol>
* <li><code>select (x + y) + (x + 1) as a, (x + x) as b from t(x, y)</code>
* <li><code>select (x + y) + (x + 1) as a, (x + (x + 1)) as b
* from t(x, y)</code>
* <li><code>select (x + y) + (x + 1) as a, (x + x) as b from t(x, y)
* where ((x + y) > 1) and ((x + y) > 1)</code>
* <li><code>select (x + y) + (x + 1) as a, (x + x) as b from t(x, y)
* where not case
* when x + 1 > 5 then true
* when y is null then null
* else false
* end</code>
* </ol>
*/
private RexProgramBuilder createProg(int variant) {
assert variant >= 0 && variant <= 4;
List<RelDataType> types = Arrays.asList(typeFactory.createSqlType(SqlTypeName.INTEGER), typeFactory.createSqlType(SqlTypeName.INTEGER));
List<String> names = Arrays.asList("x", "y");
RelDataType inputRowType = typeFactory.createStructType(types, names);
final RexProgramBuilder builder = new RexProgramBuilder(inputRowType, rexBuilder);
// $t0 = x
// $t1 = y
// $t2 = $t0 + 1 (i.e. x + 1)
final RexNode i0 = rexBuilder.makeInputRef(types.get(0), 0);
final RexLiteral c1 = rexBuilder.makeExactLiteral(BigDecimal.ONE);
final RexLiteral c5 = rexBuilder.makeExactLiteral(BigDecimal.valueOf(5L));
RexLocalRef t2 = builder.addExpr(rexBuilder.makeCall(SqlStdOperatorTable.PLUS, i0, c1));
// $t3 = 77 (not used)
final RexLiteral c77 = rexBuilder.makeExactLiteral(BigDecimal.valueOf(77));
RexLocalRef t3 = builder.addExpr(c77);
Util.discard(t3);
// $t4 = $t0 + $t1 (i.e. x + y)
final RexNode i1 = rexBuilder.makeInputRef(types.get(1), 1);
RexLocalRef t4 = builder.addExpr(rexBuilder.makeCall(SqlStdOperatorTable.PLUS, i0, i1));
RexLocalRef t5;
final RexLocalRef t1;
switch(variant) {
case 0:
case 2:
// $t5 = $t0 + $t0 (i.e. x + x)
t5 = builder.addExpr(rexBuilder.makeCall(SqlStdOperatorTable.PLUS, i0, i0));
t1 = null;
break;
case 1:
case 3:
case 4:
// $tx = $t0 + 1
t1 = builder.addExpr(rexBuilder.makeCall(SqlStdOperatorTable.PLUS, i0, c1));
// $t5 = $t0 + $tx (i.e. x + (x + 1))
t5 = builder.addExpr(rexBuilder.makeCall(SqlStdOperatorTable.PLUS, i0, t1));
break;
default:
throw new AssertionError("unexpected variant " + variant);
}
// $t6 = $t4 + $t2 (i.e. (x + y) + (x + 1))
RexLocalRef t6 = builder.addExpr(rexBuilder.makeCall(SqlStdOperatorTable.PLUS, t4, t2));
builder.addProject(t6.getIndex(), "a");
builder.addProject(t5.getIndex(), "b");
final RexLocalRef t7;
final RexLocalRef t8;
switch(variant) {
case 2:
// $t7 = $t4 > $i0 (i.e. (x + y) > 0)
t7 = builder.addExpr(rexBuilder.makeCall(SqlStdOperatorTable.GREATER_THAN, t4, i0));
// $t8 = $t7 AND $t7
t8 = builder.addExpr(and(t7, t7));
builder.addCondition(t8);
builder.addCondition(t7);
break;
case 3:
case 4:
// $t7 = 5
t7 = builder.addExpr(c5);
// $t8 = $t2 > $t7 (i.e. (x + 1) > 5)
t8 = builder.addExpr(gt(t2, t7));
// $t9 = true
final RexLocalRef t9 = builder.addExpr(trueLiteral);
// $t10 = $t1 is not null (i.e. y is not null)
assert t1 != null;
final RexLocalRef t10 = builder.addExpr(rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, t1));
// $t11 = false
final RexLocalRef t11 = builder.addExpr(falseLiteral);
// $t12 = unknown
final RexLocalRef t12 = builder.addExpr(unknownLiteral);
// $t13 = case when $t8 then $t9 when $t10 then $t11 else $t12 end
final RexLocalRef t13 = builder.addExpr(case_(t8, t9, t10, t11, t12));
// $t14 = not $t13 (i.e. not case ... end)
final RexLocalRef t14 = builder.addExpr(not(t13));
// don't add 't14 is true' - that is implicit
if (variant == 3) {
builder.addCondition(t14);
} else {
// $t15 = $14 is true
final RexLocalRef t15 = builder.addExpr(rexBuilder.makeCall(SqlStdOperatorTable.IS_TRUE, t14));
builder.addCondition(t15);
}
}
return builder;
}
use of org.apache.calcite.rex.RexProgramBuilder in project flink by apache.
the class PushFilterPastChangelogNormalizeRule method projectIdentityWithConditions.
/**
* Returns a {@link StreamPhysicalCalc} with the given {@param conditions} and an identity
* projection.
*/
private StreamPhysicalCalc projectIdentityWithConditions(RelBuilder relBuilder, RelNode newInput, List<RexNode> conditions) {
final RexProgramBuilder programBuilder = new RexProgramBuilder(newInput.getRowType(), relBuilder.getRexBuilder());
programBuilder.addIdentity();
final RexNode condition = relBuilder.and(conditions);
if (!condition.isAlwaysTrue()) {
programBuilder.addCondition(condition);
}
final RexProgram newProgram = programBuilder.getProgram();
return new StreamPhysicalCalc(newInput.getCluster(), newInput.getTraitSet(), newInput, newProgram, newProgram.getOutputRowType());
}
use of org.apache.calcite.rex.RexProgramBuilder in project flink by apache.
the class PushFilterPastChangelogNormalizeRule method projectWith.
/**
* Returns a {@link StreamPhysicalCalc} which is a copy of {@param calc}, but with the
* projections applied from {@param projectFromCalc}.
*/
private StreamPhysicalCalc projectWith(RelBuilder relBuilder, StreamPhysicalCalc projectFromCalc, StreamPhysicalCalc calc) {
final RexProgramBuilder programBuilder = new RexProgramBuilder(calc.getRowType(), relBuilder.getRexBuilder());
if (calc.getProgram().getCondition() != null) {
programBuilder.addCondition(calc.getProgram().expandLocalRef(calc.getProgram().getCondition()));
}
for (Pair<RexLocalRef, String> projectRef : projectFromCalc.getProgram().getNamedProjects()) {
final RexNode project = projectFromCalc.getProgram().expandLocalRef(projectRef.left);
programBuilder.addProject(project, projectRef.right);
}
final RexProgram newProgram = programBuilder.getProgram();
return (StreamPhysicalCalc) calc.copy(calc.getTraitSet(), calc.getInput(), newProgram);
}
use of org.apache.calcite.rex.RexProgramBuilder in project flink by apache.
the class FlinkSemiAntiJoinProjectTransposeRule method adjustCondition.
/**
* 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);
// 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());
}
use of org.apache.calcite.rex.RexProgramBuilder in project flink by apache.
the class RelTimeIndicatorConverter method mergeCalcToMaterializeTimeIndicators.
private RelNode mergeCalcToMaterializeTimeIndicators(FlinkLogicalCalc calc, Set<Integer> refIndices) {
RexProgram program = calc.getProgram();
RexProgramBuilder newProgramBuilder = new RexProgramBuilder(program.getInputRowType(), rexBuilder);
for (int idx = 0; idx < program.getNamedProjects().size(); idx++) {
Pair<RexLocalRef, String> pair = program.getNamedProjects().get(idx);
RexNode project = program.expandLocalRef(pair.left);
if (refIndices.contains(idx)) {
project = materializeTimeIndicators(project);
}
newProgramBuilder.addProject(project, pair.right);
}
if (program.getCondition() != null) {
newProgramBuilder.addCondition(program.expandLocalRef(program.getCondition()));
}
RexProgram newProgram = newProgramBuilder.getProgram();
return FlinkLogicalCalc.create(calc.getInput(), newProgram);
}
Aggregations