use of org.apache.calcite.rex.RexLocalRef in project calcite by apache.
the class JoinProjectTransposeRule method onMatch.
// ~ Methods ----------------------------------------------------------------
// implement RelOptRule
public void onMatch(RelOptRuleCall call) {
Join joinRel = call.rel(0);
JoinRelType joinType = joinRel.getJoinType();
Project leftProj;
Project rightProj;
RelNode leftJoinChild;
RelNode rightJoinChild;
// 2) input's projection doesn't generate nulls
if (hasLeftChild(call) && (includeOuter || !joinType.generatesNullsOnLeft())) {
leftProj = call.rel(1);
leftJoinChild = getProjectChild(call, leftProj, true);
} else {
leftProj = null;
leftJoinChild = call.rel(1);
}
if (hasRightChild(call) && (includeOuter || !joinType.generatesNullsOnRight())) {
rightProj = getRightChild(call);
rightJoinChild = getProjectChild(call, rightProj, false);
} else {
rightProj = null;
rightJoinChild = joinRel.getRight();
}
if ((leftProj == null) && (rightProj == null)) {
return;
}
// Construct two RexPrograms and combine them. The bottom program
// is a join of the projection expressions from the left and/or
// right projects that feed into the join. The top program contains
// the join condition.
// Create a row type representing a concatenation of the inputs
// underneath the projects that feed into the join. This is the input
// into the bottom RexProgram. Note that the join type is an inner
// join because the inputs haven't actually been joined yet.
RelDataType joinChildrenRowType = SqlValidatorUtil.deriveJoinRowType(leftJoinChild.getRowType(), rightJoinChild.getRowType(), JoinRelType.INNER, joinRel.getCluster().getTypeFactory(), null, Collections.<RelDataTypeField>emptyList());
// Create projection expressions, combining the projection expressions
// from the projects that feed into the join. For the RHS projection
// expressions, shift them to the right by the number of fields on
// the LHS. If the join input was not a projection, simply create
// references to the inputs.
int nProjExprs = joinRel.getRowType().getFieldCount();
final List<Pair<RexNode, String>> projects = new ArrayList<>();
final RexBuilder rexBuilder = joinRel.getCluster().getRexBuilder();
createProjectExprs(leftProj, leftJoinChild, 0, rexBuilder, joinChildrenRowType.getFieldList(), projects);
List<RelDataTypeField> leftFields = leftJoinChild.getRowType().getFieldList();
int nFieldsLeft = leftFields.size();
createProjectExprs(rightProj, rightJoinChild, nFieldsLeft, rexBuilder, joinChildrenRowType.getFieldList(), projects);
final List<RelDataType> projTypes = new ArrayList<>();
for (int i = 0; i < nProjExprs; i++) {
projTypes.add(projects.get(i).left.getType());
}
RelDataType projRowType = rexBuilder.getTypeFactory().createStructType(projTypes, Pair.right(projects));
// create the RexPrograms and merge them
RexProgram bottomProgram = RexProgram.create(joinChildrenRowType, Pair.left(projects), null, projRowType, rexBuilder);
RexProgramBuilder topProgramBuilder = new RexProgramBuilder(projRowType, rexBuilder);
topProgramBuilder.addIdentity();
topProgramBuilder.addCondition(joinRel.getCondition());
RexProgram topProgram = topProgramBuilder.getProgram();
RexProgram mergedProgram = RexProgramBuilder.mergePrograms(topProgram, bottomProgram, rexBuilder);
// expand out the join condition and construct a new LogicalJoin that
// directly references the join children without the intervening
// ProjectRels
RexNode newCondition = mergedProgram.expandLocalRef(mergedProgram.getCondition());
Join newJoinRel = joinRel.copy(joinRel.getTraitSet(), newCondition, leftJoinChild, rightJoinChild, joinRel.getJoinType(), joinRel.isSemiJoinDone());
// expand out the new projection expressions; if the join is an
// outer join, modify the expressions to reference the join output
final List<RexNode> newProjExprs = new ArrayList<>();
List<RexLocalRef> projList = mergedProgram.getProjectList();
List<RelDataTypeField> newJoinFields = newJoinRel.getRowType().getFieldList();
int nJoinFields = newJoinFields.size();
int[] adjustments = new int[nJoinFields];
for (int i = 0; i < nProjExprs; i++) {
RexNode newExpr = mergedProgram.expandLocalRef(projList.get(i));
if (joinType != JoinRelType.INNER) {
newExpr = newExpr.accept(new RelOptUtil.RexInputConverter(rexBuilder, joinChildrenRowType.getFieldList(), newJoinFields, adjustments));
}
newProjExprs.add(newExpr);
}
// finally, create the projection on top of the join
final RelBuilder relBuilder = call.builder();
relBuilder.push(newJoinRel);
relBuilder.project(newProjExprs, joinRel.getRowType().getFieldNames());
// projection to fix differences wrt nullability of fields
if (joinType != JoinRelType.INNER) {
relBuilder.convert(joinRel.getRowType(), false);
}
call.transformTo(relBuilder.build());
}
use of org.apache.calcite.rex.RexLocalRef 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.RexLocalRef in project storm by apache.
the class StreamsCalcRel method streamsPlan.
@Override
public void streamsPlan(StreamsPlanCreator planCreator) throws Exception {
// SingleRel
RelNode input = getInput();
StormRelUtils.getStormRelInput(input).streamsPlan(planCreator);
RelDataType inputRowType = getInput(0).getRowType();
// filter
ExecutableExpression filterInstance = null;
RexLocalRef condition = program.getCondition();
if (condition != null) {
RexNode conditionNode = program.expandLocalRef(condition);
filterInstance = planCreator.createScalarInstance(Lists.newArrayList(conditionNode), inputRowType, StormRelUtils.getClassName(this));
}
// projection
ExecutableExpression projectionInstance = null;
List<RexLocalRef> projectList = program.getProjectList();
if (projectList != null && !projectList.isEmpty()) {
List<RexNode> expandedNodes = new ArrayList<>();
for (RexLocalRef project : projectList) {
expandedNodes.add(program.expandLocalRef(project));
}
projectionInstance = planCreator.createScalarInstance(expandedNodes, inputRowType, StormRelUtils.getClassName(this));
}
if (projectionInstance == null && filterInstance == null) {
// it shouldn't be happen
throw new IllegalStateException("Either projection or condition, or both should be provided.");
}
List<String> outputFieldNames = getRowType().getFieldNames();
int outputCount = outputFieldNames.size();
EvaluationCalc evalCalc = new EvaluationCalc(filterInstance, projectionInstance, outputCount, planCreator.getDataContext());
final Stream<Values> inputStream = planCreator.pop();
final Stream finalStream = inputStream.flatMap(evalCalc);
planCreator.addStream(finalStream);
}
use of org.apache.calcite.rex.RexLocalRef in project flink by apache.
the class WatermarkAssignerChangelogNormalizeTransposeRule method buildMapping.
private Mappings.TargetMapping buildMapping(RexProgram program) {
final Map<Integer, Integer> mapInToOutPos = new HashMap<>();
final List<RexLocalRef> projects = program.getProjectList();
for (int idx = 0; idx < projects.size(); idx++) {
RexNode rexNode = program.expandLocalRef(projects.get(idx));
if (rexNode instanceof RexInputRef) {
mapInToOutPos.put(((RexInputRef) rexNode).getIndex(), idx);
}
}
return Mappings.target(mapInToOutPos, program.getInputRowType().getFieldCount(), program.getOutputRowType().getFieldCount());
}
use of org.apache.calcite.rex.RexLocalRef in project beam by apache.
the class BeamCalcRelType method canImplement.
@Override
protected boolean canImplement(RexCall call) {
final SqlOperator operator = call.getOperator();
RexImpTable.RexCallImplementor implementor = RexImpTable.INSTANCE.get(operator);
if (implementor == null) {
// Reject methods with no implementation
return false;
}
if (operator instanceof SqlUserDefinedFunction) {
SqlUserDefinedFunction udf = (SqlUserDefinedFunction) call.op;
if (udf.function instanceof ZetaSqlScalarFunctionImpl) {
ZetaSqlScalarFunctionImpl scalarFunction = (ZetaSqlScalarFunctionImpl) udf.function;
if (!scalarFunction.functionGroup.equals(BeamZetaSqlCatalog.USER_DEFINED_JAVA_SCALAR_FUNCTIONS)) {
// Reject ZetaSQL Builtin Scalar Functions
return false;
}
for (RexNode operand : call.getOperands()) {
if (operand instanceof RexLocalRef) {
if (!supportsType(operand.getType())) {
LOG.error("User-defined function {} received unsupported operand type {}.", call.op.getName(), ((RexLocalRef) operand).getType());
return false;
}
} else {
LOG.error("User-defined function {} received unrecognized operand kind {}.", call.op.getName(), operand.getKind());
return false;
}
}
} else {
// Reject other UDFs
return false;
}
} else {
// Reject Calcite implementations
return false;
}
return true;
}
Aggregations