// implement RelOptRule
  public void onMatch(RelOptRuleCall call) {
    ProjectRel origProj = call.rel(0);
    JoinRel joinRel = call.rel(1);

    // locate all fields referenced in the projection and join condition;
    // determine which inputs are referenced in the projection and
    // join condition; if all fields are being referenced and there are no
    // special expressions, no point in proceeding any further
    PushProjector pushProject =
        new PushProjector(origProj, joinRel.getCondition(), joinRel, preserveExprCondition);
    if (pushProject.locateAllRefs()) {
      return;
    }

    // create left and right projections, projecting only those
    // fields referenced on each side
    RelNode leftProjRel = pushProject.createProjectRefsAndExprs(joinRel.getLeft(), true, false);
    RelNode rightProjRel = pushProject.createProjectRefsAndExprs(joinRel.getRight(), true, true);

    // convert the join condition to reference the projected columns
    RexNode newJoinFilter = null;
    int[] adjustments = pushProject.getAdjustments();
    if (joinRel.getCondition() != null) {
      List<RelDataTypeField> projJoinFieldList = new ArrayList<RelDataTypeField>();
      projJoinFieldList.addAll(joinRel.getSystemFieldList());
      projJoinFieldList.addAll(leftProjRel.getRowType().getFieldList());
      projJoinFieldList.addAll(rightProjRel.getRowType().getFieldList());
      newJoinFilter =
          pushProject.convertRefsAndExprs(joinRel.getCondition(), projJoinFieldList, adjustments);
    }

    // create a new joinrel with the projected children
    JoinRel newJoinRel =
        new JoinRel(
            joinRel.getCluster(),
            leftProjRel,
            rightProjRel,
            newJoinFilter,
            joinRel.getJoinType(),
            Collections.<String>emptySet(),
            joinRel.isSemiJoinDone(),
            joinRel.getSystemFieldList());

    // put the original project on top of the join, converting it to
    // reference the modified projection list
    ProjectRel topProject = pushProject.createNewProject(newJoinRel, adjustments);

    call.transformTo(topProject);
  }
        public void onMatch(RelOptRuleCall call) {
          JoinRel join = (JoinRel) call.rels[0];
          List<RexNode> expList = new ArrayList<RexNode>(Arrays.asList(join.getChildExps()));
          if (reduceExpressions(join, expList)) {
            call.transformTo(
                new JoinRel(
                    join.getCluster(),
                    join.getLeft(),
                    join.getRight(),
                    expList.get(0),
                    join.getJoinType(),
                    join.getVariablesStopped()));

            // New plan is absolutely better than old plan.
            call.getPlanner().setImportance(join, 0.0);
          }
        }