use of org.apache.calcite.rel.logical.LogicalJoin in project drill by apache.
the class DrillJoinRelBase method estimateRowCount.
@Override
public double estimateRowCount(RelMetadataQuery mq) {
if (this.condition.isAlwaysTrue()) {
return joinRowFactor * this.getLeft().estimateRowCount(mq) * this.getRight().estimateRowCount(mq);
}
LogicalJoin jr = LogicalJoin.create(this.getLeft(), this.getRight(), this.getCondition(), this.getVariablesSet(), this.getJoinType());
if (// Statistics present for left and right side of the join
!DrillRelOptUtil.guessRows(this) && jr.getJoinType() == JoinRelType.INNER) {
List<Pair<Integer, Integer>> joinConditions = DrillRelOptUtil.analyzeSimpleEquiJoin((Join) jr);
if (joinConditions.size() > 0) {
List<Integer> leftSide = new ArrayList<>();
List<Integer> rightSide = new ArrayList<>();
for (Pair<Integer, Integer> condition : joinConditions) {
leftSide.add(condition.left);
rightSide.add(condition.right);
}
ImmutableBitSet leq = ImmutableBitSet.of(leftSide);
ImmutableBitSet req = ImmutableBitSet.of(rightSide);
Double ldrc = mq.getDistinctRowCount(this.getLeft(), leq, null);
Double rdrc = mq.getDistinctRowCount(this.getRight(), req, null);
Double lrc = mq.getRowCount(this.getLeft());
Double rrc = mq.getRowCount(this.getRight());
if (ldrc != null && rdrc != null && lrc != null && rrc != null) {
// Join cardinality = (lrc * rrc) / Math.max(ldrc, rdrc). Avoid overflow by dividing earlier
return (lrc / Math.max(ldrc, rdrc)) * rrc;
}
}
}
return joinRowFactor * Math.max(mq.getRowCount(this.getLeft()), mq.getRowCount(this.getRight()));
}
use of org.apache.calcite.rel.logical.LogicalJoin in project drill by apache.
the class DrillJoinRule method onMatch.
@Override
public void onMatch(RelOptRuleCall call) {
final LogicalJoin join = call.rel(0);
final RelNode left = join.getLeft();
final RelNode right = join.getRight();
final RelTraitSet traits = join.getTraitSet().plus(DrillRel.DRILL_LOGICAL);
final RelNode convertedLeft = convert(left, left.getTraitSet().plus(DrillRel.DRILL_LOGICAL).simplify());
final RelNode convertedRight = convert(right, right.getTraitSet().plus(DrillRel.DRILL_LOGICAL).simplify());
List<Integer> leftKeys = Lists.newArrayList();
List<Integer> rightKeys = Lists.newArrayList();
List<Boolean> filterNulls = Lists.newArrayList();
boolean addFilter = false;
RexNode origJoinCondition = join.getCondition();
RexNode newJoinCondition = origJoinCondition;
RexNode remaining = RelOptUtil.splitJoinCondition(convertedLeft, convertedRight, origJoinCondition, leftKeys, rightKeys, filterNulls);
boolean hasEquijoins = leftKeys.size() == rightKeys.size() && leftKeys.size() > 0;
// For OUTER join, pulling up a non-eqivjoin filter will lead to incorrectly discarding qualified rows.
if (!remaining.isAlwaysTrue()) {
if (hasEquijoins && join.getJoinType() == JoinRelType.INNER) {
addFilter = true;
newJoinCondition = buildJoinCondition(convertedLeft, convertedRight, leftKeys, rightKeys, filterNulls, join.getCluster().getRexBuilder());
}
} else {
newJoinCondition = buildJoinCondition(convertedLeft, convertedRight, leftKeys, rightKeys, filterNulls, join.getCluster().getRexBuilder());
}
try {
if (join.isSemiJoin()) {
RelNode joinRel = new DrillSemiJoinRel(join.getCluster(), traits, convertedLeft, convertedRight, newJoinCondition, leftKeys, rightKeys);
call.transformTo(joinRel);
return;
}
if (!addFilter) {
RelNode joinRel = new DrillJoinRel(join.getCluster(), traits, convertedLeft, convertedRight, newJoinCondition, join.getJoinType(), leftKeys, rightKeys);
call.transformTo(joinRel);
} else {
RelNode joinRel = new DrillJoinRel(join.getCluster(), traits, convertedLeft, convertedRight, newJoinCondition, join.getJoinType(), leftKeys, rightKeys);
call.transformTo(new DrillFilterRel(join.getCluster(), traits, joinRel, remaining));
}
} catch (InvalidRelException e) {
tracer.warn(e.toString());
}
}
Aggregations