use of org.apache.calcite.rex.RexProgram in project calcite by apache.
the class RelOptUtil method permute.
/**
* Creates a relational expression which permutes the output fields of a
* relational expression according to a permutation.
*
* <p>Optimizations:</p>
*
* <ul>
* <li>If the relational expression is a
* {@link org.apache.calcite.rel.logical.LogicalCalc} or
* {@link org.apache.calcite.rel.logical.LogicalProject} that is already
* acting as a permutation, combines the new permutation with the old;</li>
*
* <li>If the permutation is the identity, returns the original relational
* expression.</li>
* </ul>
*
* <p>If a permutation is combined with its inverse, these optimizations
* would combine to remove them both.
*
* @param rel Relational expression
* @param permutation Permutation to apply to fields
* @param fieldNames Field names; if null, or if a particular entry is null,
* the name of the permuted field is used
* @return relational expression which permutes its input fields
*/
public static RelNode permute(RelNode rel, Permutation permutation, List<String> fieldNames) {
if (permutation.isIdentity()) {
return rel;
}
if (rel instanceof LogicalCalc) {
LogicalCalc calc = (LogicalCalc) rel;
Permutation permutation1 = calc.getProgram().getPermutation();
if (permutation1 != null) {
Permutation permutation2 = permutation.product(permutation1);
return permute(rel, permutation2, null);
}
}
if (rel instanceof LogicalProject) {
Permutation permutation1 = ((LogicalProject) rel).getPermutation();
if (permutation1 != null) {
Permutation permutation2 = permutation.product(permutation1);
return permute(rel, permutation2, null);
}
}
final List<RelDataType> outputTypeList = new ArrayList<>();
final List<String> outputNameList = new ArrayList<>();
final List<RexNode> exprList = new ArrayList<>();
final List<RexLocalRef> projectRefList = new ArrayList<>();
final List<RelDataTypeField> fields = rel.getRowType().getFieldList();
final RelOptCluster cluster = rel.getCluster();
for (int i = 0; i < permutation.getTargetCount(); i++) {
int target = permutation.getTarget(i);
final RelDataTypeField targetField = fields.get(target);
outputTypeList.add(targetField.getType());
outputNameList.add(((fieldNames == null) || (fieldNames.size() <= i) || (fieldNames.get(i) == null)) ? targetField.getName() : fieldNames.get(i));
exprList.add(cluster.getRexBuilder().makeInputRef(fields.get(i).getType(), i));
final int source = permutation.getSource(i);
projectRefList.add(new RexLocalRef(source, fields.get(source).getType()));
}
final RelDataTypeFactory typeFactory = cluster.getTypeFactory();
final RexProgram program = new RexProgram(rel.getRowType(), exprList, projectRefList, null, typeFactory.createStructType(outputTypeList, outputNameList));
return LogicalCalc.create(rel, program);
}
use of org.apache.calcite.rex.RexProgram in project calcite by apache.
the class RexProgramTest method testSimplifyCondition2.
/**
* Tests how the condition is simplified.
*/
@Test
public void testSimplifyCondition2() {
final RexProgram program = createProg(4).getProgram(false);
assertThat(program.toString(), is("(expr#0..1=[{inputs}], expr#2=[+($0, 1)], expr#3=[77], " + "expr#4=[+($0, $1)], expr#5=[+($0, 1)], expr#6=[+($0, $t5)], " + "expr#7=[+($t4, $t2)], expr#8=[5], expr#9=[>($t2, $t8)], " + "expr#10=[true], expr#11=[IS NOT NULL($t5)], expr#12=[false], " + "expr#13=[null], expr#14=[CASE($t9, $t10, $t11, $t12, $t13)], " + "expr#15=[NOT($t14)], expr#16=[IS TRUE($t15)], a=[$t7], b=[$t6], " + "$condition=[$t16])"));
assertThat(program.normalize(rexBuilder, simplify).toString(), is("(expr#0..1=[{inputs}], expr#2=[+($t0, $t1)], expr#3=[1], " + "expr#4=[+($t0, $t3)], expr#5=[+($t2, $t4)], " + "expr#6=[+($t0, $t4)], expr#7=[5], expr#8=[>($t4, $t7)], " + "expr#9=[CAST($t8):BOOLEAN], expr#10=[IS FALSE($t9)], " + "a=[$t5], b=[$t6], $condition=[$t10])"));
}
use of org.apache.calcite.rex.RexProgram in project calcite by apache.
the class ReduceDecimalsRule method onMatch.
// implement RelOptRule
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);
}
use of org.apache.calcite.rex.RexProgram in project drill by axbaretto.
the class DrillMergeFilterRule method onMatch.
// ~ Methods ----------------------------------------------------------------
// implement RelOptRule
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);
}
use of org.apache.calcite.rex.RexProgram in project samza by apache.
the class RexToJavaCompiler method compile.
/**
* Compiles a relational expression to a instance of {@link Expression}
*
* for e.g.
* Query : select id from profile
* where profile table has relational schema with id(NUMBER) and name(VARCHAR) columns.
* This query will result in the following relational plan
* LogicalProject(id=[$1])
* LogicalTableScan(table=[[profile]])
*
* And the corresponding expressions are
* inputs : EnumerableTableScan (Which is the output of LogicalTableScan)
* nodes : [$1] Which essentially means take pick the first column from the input
*
* This function converts the LogicalProject expression "[$1]" with input RexNode which is an output of TableScan
* to a java code that implements the interface {@link Expression}
*
* @param inputs Input relations/time-varying relations for this row expression
* @param nodes relational expressions that needs to be converted to java code.
* @return compiled expression of type {@link org.apache.samza.sql.data.Expression}
*/
public org.apache.samza.sql.data.Expression compile(List<RelNode> inputs, List<RexNode> nodes) {
/*
* In case there are multiple input relations, we build a single input row type combining types of all the inputs.
*/
final RelDataTypeFactory.FieldInfoBuilder fieldBuilder = rexBuilder.getTypeFactory().builder();
for (RelNode input : inputs) {
fieldBuilder.addAll(input.getRowType().getFieldList());
}
final RelDataType inputRowType = fieldBuilder.build();
final RexProgramBuilder programBuilder = new RexProgramBuilder(inputRowType, rexBuilder);
for (RexNode node : nodes) {
programBuilder.addProject(node, null);
}
final RexProgram program = programBuilder.getProgram();
final BlockBuilder builder = new BlockBuilder();
final ParameterExpression sqlContext = Expressions.parameter(SamzaSqlExecutionContext.class, "sqlContext");
final ParameterExpression context = Expressions.parameter(Context.class, "context");
final ParameterExpression root = DataContext.ROOT;
final ParameterExpression inputValues = Expressions.parameter(Object[].class, "inputValues");
final ParameterExpression outputValues = Expressions.parameter(Object[].class, "outputValues");
final JavaTypeFactoryImpl javaTypeFactory = new SamzaSqlJavaTypeFactoryImpl(rexBuilder.getTypeFactory().getTypeSystem());
// public void execute(Object[] inputValues, Object[] outputValues)
final RexToLixTranslator.InputGetter inputGetter = new RexToLixTranslator.InputGetterImpl(ImmutableList.of(Pair.of(Expressions.variable(Object[].class, "inputValues"), PhysTypeImpl.of(javaTypeFactory, inputRowType, JavaRowFormat.ARRAY, false))));
final List<org.apache.calcite.linq4j.tree.Expression> list = RexToLixTranslator.translateProjects(program, javaTypeFactory, SqlConformanceEnum.DEFAULT, builder, null, DataContext.ROOT, inputGetter, null);
for (int i = 0; i < list.size(); i++) {
builder.add(Expressions.statement(Expressions.assign(Expressions.arrayIndex(outputValues, Expressions.constant(i)), list.get(i))));
}
return createSamzaExpressionFromCalcite(sqlContext, context, root, inputValues, outputValues, builder.toBlock());
}
Aggregations