private RelNode applyPostJoinOrderingTransform(RelNode basePlan, RelMetadataProvider mdProvider, RexExecutor executorProvider) {

      final HepProgramBuilder program = new HepProgramBuilder();

      double factor = conf.getFloatVar(ConfVars.HIVE_CARDINALITY_PRESERVING_JOIN_OPTIMIZATION_FACTOR);
      if (factor > 0.0) {
        generatePartialProgram(program, false, HepMatchOrder.TOP_DOWN,
            new HiveCardinalityPreservingJoinRule(factor));
      }

      // 1. Run other optimizations that do not need stats
      generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
          ProjectRemoveRule.Config.DEFAULT.toRule(),
          HiveUnionMergeRule.INSTANCE,
          new HiveUnionSimpleSelectsToInlineTableRule(dummyTableScan),
          HiveAggregateProjectMergeRule.INSTANCE,
          HiveProjectMergeRule.INSTANCE_NO_FORCE,
          HiveJoinCommuteRule.INSTANCE,
          new HiveAggregateSortLimitRule(conf.getBoolVar(ConfVars.HIVE_DEFAULT_NULLS_LAST)));

      // 2. Run aggregate-join transpose (cost based)
      //    If it failed because of missing stats, we continue with
      //    the rest of optimizations
      if (conf.getBoolVar(ConfVars.AGGR_JOIN_TRANSPOSE) || conf.getBoolVar(ConfVars.AGGR_JOIN_TRANSPOSE_UNIQUE)) {
        generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
            new HiveAggregateJoinTransposeRule(noColsMissingStats,
                conf.getBoolVar(ConfVars.AGGR_JOIN_TRANSPOSE),
                conf.getBoolVar(ConfVars.AGGR_JOIN_TRANSPOSE_UNIQUE)));
      }

      // 3. Convert Join + GBy to semijoin
      // Run this rule at later stages, since many calcite rules cant deal with semijoin
      if (conf.getBoolVar(ConfVars.SEMIJOIN_CONVERSION)) {
        generatePartialProgram(program, true, HepMatchOrder.DEPTH_FIRST,
            HiveSemiJoinRule.INSTANCE_PROJECT, HiveSemiJoinRule.INSTANCE_PROJECT_SWAPPED,
            HiveSemiJoinRule.INSTANCE_AGGREGATE, HiveSemiJoinRule.INSTANCE_AGGREGATE_SWAPPED);
      }

      // 4. convert SemiJoin + GBy to SemiJoin
      generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
          HiveRemoveGBYSemiJoinRule.INSTANCE);

      // 5. Run rule to fix windowing issue when it is done over
      // aggregation columns (HIVE-10627)
      if (profilesCBO.contains(ExtendedCBOProfile.WINDOWING_POSTPROCESSING)) {
        generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
            HiveWindowingFixRule.INSTANCE);
        generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
            HiveWindowingLastValueRewrite.INSTANCE);
      }

      // Expand SEARCH since JDBC (and potentially other federation rules) do not know how to handle it.
      generatePartialProgram(program,
          true,
          HepMatchOrder.DEPTH_FIRST,
          HiveSearchRules.PROJECT_SEARCH_EXPAND,
          HiveSearchRules.FILTER_SEARCH_EXPAND,
          HiveSearchRules.JOIN_SEARCH_EXPAND);

      // 7. Apply Druid transformation rules
      generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
          HiveDruidRules.FILTER_DATE_RANGE_RULE,
          HiveDruidRules.FILTER, HiveDruidRules.PROJECT_FILTER_TRANSPOSE,
          HiveDruidRules.AGGREGATE_FILTER_TRANSPOSE,
          HiveDruidRules.AGGREGATE_PROJECT,
          HiveDruidRules.PROJECT,
          HiveDruidRules.EXPAND_SINGLE_DISTINCT_AGGREGATES_DRUID_RULE,
          HiveDruidRules.AGGREGATE,
          HiveDruidRules.POST_AGGREGATION_PROJECT,
          HiveDruidRules.FILTER_AGGREGATE_TRANSPOSE,
          HiveDruidRules.FILTER_PROJECT_TRANSPOSE,
          HiveDruidRules.HAVING_FILTER_RULE,
          HiveDruidRules.SORT_PROJECT_TRANSPOSE,
          HiveDruidRules.SORT);

      // 8. Apply JDBC transformation rules
      if (conf.getBoolVar(ConfVars.HIVE_ENABLE_JDBC_PUSHDOWN)) {
        List<RelOptRule> rules = Lists.newArrayList();
        rules.add(JDBCExpandExpressionsRule.FILTER_INSTANCE);
        rules.add(JDBCExpandExpressionsRule.JOIN_INSTANCE);
        rules.add(JDBCExpandExpressionsRule.PROJECT_INSTANCE);
        rules.add(JDBCExtractJoinFilterRule.INSTANCE);
        rules.add(JDBCAbstractSplitFilterRule.SPLIT_FILTER_ABOVE_JOIN);
        rules.add(JDBCAbstractSplitFilterRule.SPLIT_FILTER_ABOVE_CONVERTER);
        rules.add(JDBCFilterJoinRule.INSTANCE);
        rules.add(JDBCFilterPushDownRule.INSTANCE);
        rules.add(JDBCProjectPushDownRule.INSTANCE);
        rules.add(JDBCAggregateProjectMergeRule.INSTANCE);
        if (!conf.getBoolVar(ConfVars.HIVE_ENABLE_JDBC_SAFE_PUSHDOWN)) {
          rules.add(JDBCJoinPushDownRule.INSTANCE);
          rules.add(JDBCUnionPushDownRule.INSTANCE);
          rules.add(JDBCAggregationPushDownRule.INSTANCE);
          rules.add(JDBCSortPushDownRule.INSTANCE);
        }
        generatePartialProgram(program, true, HepMatchOrder.TOP_DOWN,
            rules.toArray(new RelOptRule[rules.size()]));
      }

      // 9. Run rules to aid in translation from Calcite tree to Hive tree
      if (HiveConf.getBoolVar(conf, ConfVars.HIVE_CBO_RETPATH_HIVEOP)) {
        // 9.1. Merge join into multijoin operators (if possible)
        generatePartialProgram(program, true, HepMatchOrder.BOTTOM_UP,
            HiveJoinProjectTransposeRule.BOTH_PROJECT_INCLUDE_OUTER,
            HiveJoinProjectTransposeRule.LEFT_PROJECT_INCLUDE_OUTER,
            HiveJoinProjectTransposeRule.RIGHT_PROJECT_INCLUDE_OUTER,
            HiveJoinToMultiJoinRule.INSTANCE, HiveProjectMergeRule.INSTANCE);
        // The previous rules can pull up projections through join operators,
        // thus we run the field trimmer again to push them back down
        generatePartialProgram(program, false, HepMatchOrder.TOP_DOWN,
            new HiveFieldTrimmerRule(false));
        generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
            ProjectRemoveRule.Config.DEFAULT.toRule(), new ProjectMergeRule(false, HiveRelFactories.HIVE_BUILDER));
        generatePartialProgram(program, true, HepMatchOrder.TOP_DOWN,
            HiveFilterProjectTSTransposeRule.INSTANCE, HiveFilterProjectTSTransposeRule.INSTANCE_DRUID,
            HiveProjectFilterPullUpConstantsRule.INSTANCE);

        // 9.2.  Introduce exchange operators below join/multijoin operators
        generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
                new HiveInsertExchange4JoinRule(Join.class, NullOrdering.defaultNullOrder(conf).getDirection()),
                new HiveInsertExchange4JoinRule(
                        HiveMultiJoin.class, NullOrdering.defaultNullOrder(conf).getDirection()));
      } else {
        generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
                HiveProjectSortExchangeTransposeRule.INSTANCE, HiveProjectMergeRule.INSTANCE);
      }

      // 10. We need to expand IN/BETWEEN expressions when loading a materialized view
      // since otherwise this may prevent some rewritings from happening
      if (ctx.isLoadingMaterializedView()) {
        generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
            HiveInBetweenExpandRule.FILTER_INSTANCE,
            HiveInBetweenExpandRule.JOIN_INSTANCE,
            HiveInBetweenExpandRule.PROJECT_INSTANCE);
      }

      // Trigger program
      basePlan = executeProgram(basePlan, program.build(), mdProvider, executorProvider);

      return basePlan;
    }
Perform join reordering post-optimization.

@param basePlan
         original plan
@param mdProvider
         meta data provider
@param executorProvider
         executor
@return
ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java