use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexNode in project calcite by apache.
the class FilterTableScanRule method apply.
// ~ Methods ----------------------------------------------------------------
protected void apply(RelOptRuleCall call, Filter filter, TableScan scan) {
final ImmutableIntList projects;
final ImmutableList.Builder<RexNode> filters = ImmutableList.builder();
if (scan instanceof Bindables.BindableTableScan) {
final Bindables.BindableTableScan bindableScan = (Bindables.BindableTableScan) scan;
filters.addAll(bindableScan.filters);
projects = bindableScan.projects;
} else {
projects = scan.identity();
}
final Mapping mapping = Mappings.target(projects, scan.getTable().getRowType().getFieldCount());
filters.add(RexUtil.apply(mapping, filter.getCondition()));
call.transformTo(Bindables.BindableTableScan.create(scan.getCluster(), scan.getTable(), filters.build(), projects));
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexNode in project calcite by apache.
the class JoinAssociateRule method onMatch.
// ~ Methods ----------------------------------------------------------------
public void onMatch(final RelOptRuleCall call) {
final Join topJoin = call.rel(0);
final Join bottomJoin = call.rel(1);
final RelNode relA = bottomJoin.getLeft();
final RelNode relB = bottomJoin.getRight();
final RelSubset relC = call.rel(2);
final RelOptCluster cluster = topJoin.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
if (relC.getConvention() != relA.getConvention()) {
// EnumerableConvention, we're only interested in enumerable subsets.
return;
}
// topJoin
// / \
// bottomJoin C
// / \
// A B
final int aCount = relA.getRowType().getFieldCount();
final int bCount = relB.getRowType().getFieldCount();
final int cCount = relC.getRowType().getFieldCount();
final ImmutableBitSet aBitSet = ImmutableBitSet.range(0, aCount);
final ImmutableBitSet bBitSet = ImmutableBitSet.range(aCount, aCount + bCount);
if (!topJoin.getSystemFieldList().isEmpty()) {
// FIXME Enable this rule for joins with system fields
return;
}
// (Is this too strict?)
if (topJoin.getJoinType() != JoinRelType.INNER || bottomJoin.getJoinType() != JoinRelType.INNER) {
return;
}
// Goal is to transform to
//
// newTopJoin
// / \
// A newBottomJoin
// / \
// B C
// Split the condition of topJoin and bottomJoin into a conjunctions. A
// condition can be pushed down if it does not use columns from A.
final List<RexNode> top = Lists.newArrayList();
final List<RexNode> bottom = Lists.newArrayList();
JoinPushThroughJoinRule.split(topJoin.getCondition(), aBitSet, top, bottom);
JoinPushThroughJoinRule.split(bottomJoin.getCondition(), aBitSet, top, bottom);
// Mapping for moving conditions from topJoin or bottomJoin to
// newBottomJoin.
// target: | B | C |
// source: | A | B | C |
final Mappings.TargetMapping bottomMapping = Mappings.createShiftMapping(aCount + bCount + cCount, 0, aCount, bCount, bCount, aCount + bCount, cCount);
final List<RexNode> newBottomList = Lists.newArrayList();
new RexPermuteInputsShuttle(bottomMapping, relB, relC).visitList(bottom, newBottomList);
RexNode newBottomCondition = RexUtil.composeConjunction(rexBuilder, newBottomList, false);
final Join newBottomJoin = bottomJoin.copy(bottomJoin.getTraitSet(), newBottomCondition, relB, relC, JoinRelType.INNER, false);
// Condition for newTopJoin consists of pieces from bottomJoin and topJoin.
// Field ordinals do not need to be changed.
RexNode newTopCondition = RexUtil.composeConjunction(rexBuilder, top, false);
final Join newTopJoin = topJoin.copy(topJoin.getTraitSet(), newTopCondition, relA, newBottomJoin, JoinRelType.INNER, false);
call.transformTo(newTopJoin);
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexNode 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.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexNode in project calcite by apache.
the class JoinPushExpressionsRule method onMatch.
@Override
public void onMatch(RelOptRuleCall call) {
Join join = call.rel(0);
// Push expression in join condition into Project below Join.
RelNode newJoin = RelOptUtil.pushDownJoinConditions(join, call.builder());
// If the join is the same, we bail out
if (newJoin instanceof Join) {
final RexNode newCondition = ((Join) newJoin).getCondition();
if (join.getCondition().toString().equals(newCondition.toString())) {
return;
}
}
call.transformTo(newJoin);
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rex.RexNode in project calcite by apache.
the class LoptSemiJoinOptimizer method findSemiJoinIndexByCost.
/**
* Given a list of possible filters on a fact table, determine if there is
* an index that can be used, provided all the fact table keys originate
* from the same underlying table.
*
* @param multiJoin join factors being optimized
* @param joinFilters filters to be used on the fact table
* @param factIdx index in join factors corresponding to the fact table
* @param dimIdx index in join factors corresponding to the dimension table
*
* @return SemiJoin containing information regarding the semijoin that
* can be used to filter the fact table
*/
private SemiJoin findSemiJoinIndexByCost(LoptMultiJoin multiJoin, List<RexNode> joinFilters, int factIdx, int dimIdx) {
// create a SemiJoin with the semi-join condition and keys
RexNode semiJoinCondition = RexUtil.composeConjunction(rexBuilder, joinFilters, true);
int leftAdjustment = 0;
for (int i = 0; i < factIdx; i++) {
leftAdjustment -= multiJoin.getNumFieldsInJoinFactor(i);
}
semiJoinCondition = adjustSemiJoinCondition(multiJoin, leftAdjustment, semiJoinCondition, factIdx, dimIdx);
RelNode factRel = multiJoin.getJoinFactor(factIdx);
RelNode dimRel = multiJoin.getJoinFactor(dimIdx);
final JoinInfo joinInfo = JoinInfo.of(factRel, dimRel, semiJoinCondition);
assert joinInfo.leftKeys.size() > 0;
// mutable copies
final List<Integer> leftKeys = Lists.newArrayList(joinInfo.leftKeys);
final List<Integer> rightKeys = Lists.newArrayList(joinInfo.rightKeys);
// make sure all the fact table keys originate from the same table
// and are simple column references
final List<Integer> actualLeftKeys = new ArrayList<>();
LcsTable factTable = validateKeys(factRel, leftKeys, rightKeys, actualLeftKeys);
if (factTable == null) {
return null;
}
// find the best index
final List<Integer> bestKeyOrder = new ArrayList<>();
LcsTableScan tmpFactRel = (LcsTableScan) factTable.toRel(RelOptUtil.getContext(factRel.getCluster()));
LcsIndexOptimizer indexOptimizer = new LcsIndexOptimizer(tmpFactRel);
FemLocalIndex bestIndex = indexOptimizer.findSemiJoinIndexByCost(dimRel, actualLeftKeys, rightKeys, bestKeyOrder);
if (bestIndex == null) {
return null;
}
// if necessary, truncate the keys to reflect the ones that match
// the index and remove the corresponding, unnecessary filters from
// the condition; note that we don't save the actual keys here because
// later when the semijoin is pushed past other RelNodes, the keys will
// be converted
final List<Integer> truncatedLeftKeys;
final List<Integer> truncatedRightKeys;
if (actualLeftKeys.size() == bestKeyOrder.size()) {
truncatedLeftKeys = leftKeys;
truncatedRightKeys = rightKeys;
} else {
truncatedLeftKeys = new ArrayList<>();
truncatedRightKeys = new ArrayList<>();
for (int key : bestKeyOrder) {
truncatedLeftKeys.add(leftKeys.get(key));
truncatedRightKeys.add(rightKeys.get(key));
}
semiJoinCondition = removeExtraFilters(truncatedLeftKeys, multiJoin.getNumFieldsInJoinFactor(factIdx), semiJoinCondition);
}
return SemiJoin.create(factRel, dimRel, semiJoinCondition, ImmutableIntList.copyOf(truncatedLeftKeys), ImmutableIntList.copyOf(truncatedRightKeys));
}
Aggregations