protected RelNode applyPreJoinOrderingTransforms(RelNode basePlan, RelMetadataProvider mdProvider, RexExecutor executorProvider) {
      // TODO: Decorelation of subquery should be done before attempting
      // Partition Pruning; otherwise Expression evaluation may try to execute
      // corelated sub query.
      final int maxCNFNodeCount = conf.getIntVar(HiveConf.ConfVars.HIVE_CBO_CNF_NODES_LIMIT);
      final int minNumORClauses = conf.getIntVar(HiveConf.ConfVars.HIVE_POINT_LOOKUP_OPTIMIZER_MIN);

      final HepProgramBuilder program = new HepProgramBuilder();

      //0. SetOp rewrite
      generatePartialProgram(program, true, HepMatchOrder.BOTTOM_UP,
          HiveProjectOverIntersectRemoveRule.INSTANCE, HiveIntersectMergeRule.INSTANCE,
          HiveUnionMergeRule.INSTANCE);
      generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
          HiveIntersectRewriteRule.INSTANCE);
      generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
          HiveExceptRewriteRule.INSTANCE);

      //1. Distinct aggregate rewrite
      if (!isMaterializedViewMaintenance() && conf.getBoolVar(ConfVars.HIVE_OPTIMIZE_BI_ENABLED)) {
        // Rewrite to datasketches if enabled
        if (conf.getBoolVar(ConfVars.HIVE_OPTIMIZE_BI_REWRITE_COUNTDISTINCT_ENABLED)) {
          String sketchType = conf.getVar(ConfVars.HIVE_OPTIMIZE_BI_REWRITE_COUNT_DISTINCT_SKETCH);
          RelOptRule rule = new HiveRewriteToDataSketchesRules.CountDistinctRewrite(sketchType);
          generatePartialProgram(program, true, HepMatchOrder.TOP_DOWN, rule);
        }
        if (conf.getBoolVar(ConfVars.HIVE_OPTIMIZE_BI_REWRITE_PERCENTILE_DISC_ENABLED)) {
          String sketchType = conf.getVar(ConfVars.HIVE_OPTIMIZE_BI_REWRITE_PERCENTILE_DISC_SKETCH);
          RelOptRule rule = new HiveRewriteToDataSketchesRules.PercentileDiscRewrite(sketchType);
          generatePartialProgram(program, true, HepMatchOrder.TOP_DOWN, rule);
        }
        if (conf.getBoolVar(ConfVars.HIVE_OPTIMIZE_BI_REWRITE_CUME_DIST_ENABLED)) {
          String sketchType = conf.getVar(ConfVars.HIVE_OPTIMIZE_BI_REWRITE_CUME_DIST_SKETCH);
          RelOptRule rule = new HiveRewriteToDataSketchesRules.CumeDistRewriteRule(sketchType);
          generatePartialProgram(program, true, HepMatchOrder.TOP_DOWN, rule);
        }
        if (conf.getBoolVar(ConfVars.HIVE_OPTIMIZE_BI_REWRITE_NTILE_ENABLED)) {
          String sketchType = conf.getVar(ConfVars.HIVE_OPTIMIZE_BI_REWRITE_NTILE_SKETCH);
          RelOptRule rule = new HiveRewriteToDataSketchesRules.NTileRewrite(sketchType);
          generatePartialProgram(program, true, HepMatchOrder.TOP_DOWN, rule);
        }
        if (conf.getBoolVar(ConfVars.HIVE_OPTIMIZE_BI_REWRITE_RANK_ENABLED)) {
          String sketchType = conf.getVar(ConfVars.HIVE_OPTIMIZE_BI_REWRITE_RANK_SKETCH);
          RelOptRule rule = new HiveRewriteToDataSketchesRules.RankRewriteRule(sketchType);
          generatePartialProgram(program, true, HepMatchOrder.TOP_DOWN, rule);
        }
      }
      // Run this optimization early, since it is expanding the operator pipeline.
      if (!conf.getVar(HiveConf.ConfVars.HIVE_EXECUTION_ENGINE).equals("mr") &&
          conf.getBoolVar(HiveConf.ConfVars.HIVE_OPTIMIZE_DISTINCT_REWRITE)) {
        // Its not clear, if this rewrite is always performant on MR, since extra map phase
        // introduced for 2nd MR job may offset gains of this multi-stage aggregation.
        // We need a cost model for MR to enable this on MR.
        generatePartialProgram(program, true, HepMatchOrder.TOP_DOWN,
            HiveExpandDistinctAggregatesRule.INSTANCE);
      }

      // 2. Try factoring out common filter elements & separating deterministic
      // vs non-deterministic UDF. This needs to run before PPD so that PPD can
      // add on-clauses for old style Join Syntax
      // Ex: select * from R1 join R2 where ((R1.x=R2.x) and R1.y<10) or
      // ((R1.x=R2.x) and R1.z=10)) and rand(1) < 0.1
      generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
          new HivePreFilteringRule(maxCNFNodeCount));

      // 3. Run exhaustive PPD, add not null filters, transitive inference,
      // constant propagation, constant folding
      List<RelOptRule> rules = Lists.newArrayList();
      if (conf.getBoolVar(HiveConf.ConfVars.HIVE_OPT_PPD_WINDOWING)) {
        rules.add(HiveFilterProjectTransposeRule.DETERMINISTIC_WINDOWING);
      } else {
        rules.add(HiveFilterProjectTransposeRule.DETERMINISTIC);
      }
      rules.add(HiveFilterTableFunctionTransposeRule.INSTANCE);
      rules.add(HiveOptimizeInlineArrayTableFunctionRule.INSTANCE);
      rules.add(HiveFilterSetOpTransposeRule.INSTANCE);
      rules.add(HiveFilterSortTransposeRule.SORT_LIMIT_INSTANCE);
      rules.add(HiveFilterSortTransposeRule.SORT_EXCHANGE_INSTANCE);
      rules.add(HiveFilterJoinRule.JOIN);
      rules.add(HiveFilterJoinRule.FILTER_ON_JOIN);
      rules.add(new HiveFilterAggregateTransposeRule(Filter.class, HiveRelFactories.HIVE_BUILDER,
          Aggregate.class));
      rules.add(FilterMergeRule.Config.DEFAULT
          .withOperandFor(HiveFilter.class)
          .withRelBuilderFactory(HiveRelFactories.HIVE_BUILDER)
          .toRule());
      if (conf.getBoolVar(HiveConf.ConfVars.HIVE_OPTIMIZE_REDUCE_WITH_STATS)) {
        rules.add(HiveReduceExpressionsWithStatsRule.INSTANCE);
      }
      rules.add(HiveProjectFilterPullUpConstantsRule.INSTANCE);
      rules.add(HiveReduceExpressionsRule.PROJECT_INSTANCE);
      rules.add(HiveReduceExpressionsRule.FILTER_INSTANCE);
      rules.add(HiveReduceExpressionsRule.JOIN_INSTANCE);
      rules.add(HiveReduceExpressionsRule.SEMIJOIN_INSTANCE);
      rules.add(HiveAggregateReduceFunctionsRule.INSTANCE);
      rules.add(HiveAggregateReduceRule.INSTANCE);
      if (conf.getBoolVar(HiveConf.ConfVars.HIVE_POINT_LOOKUP_OPTIMIZER)) {
        rules.add(new HivePointLookupOptimizerRule.FilterCondition(minNumORClauses));
        rules.add(new HivePointLookupOptimizerRule.JoinCondition(minNumORClauses));
        rules.add(new HivePointLookupOptimizerRule.ProjectionExpressions(minNumORClauses));
      }
      rules.add(HiveProjectJoinTransposeRule.INSTANCE);
      if (conf.getBoolVar(HiveConf.ConfVars.HIVE_OPTIMIZE_CONSTRAINTS_JOIN) &&
          profilesCBO.contains(ExtendedCBOProfile.REFERENTIAL_CONSTRAINTS)) {
        rules.add(HiveJoinConstraintsRule.INSTANCE);
      }
      rules.add(HiveJoinAddNotNullRule.INSTANCE_JOIN);
      rules.add(HiveJoinAddNotNullRule.INSTANCE_SEMIJOIN);
      rules.add(HiveJoinAddNotNullRule.INSTANCE_ANTIJOIN);
      rules.add(new HiveJoinPushTransitivePredicatesRule(HiveJoin.class));
      rules.add(new HiveJoinPushTransitivePredicatesRule(HiveSemiJoin.class));
      rules.add(new HiveJoinPushTransitivePredicatesRule(HiveAntiJoin.class));
      rules.add(HiveSortMergeRule.INSTANCE);
      rules.add(HiveSortPullUpConstantsRule.SORT_LIMIT_INSTANCE);
      rules.add(HiveSortPullUpConstantsRule.SORT_EXCHANGE_INSTANCE);
      rules.add(HiveUnionPullUpConstantsRule.INSTANCE);
      rules.add(HiveAggregatePullUpConstantsRule.INSTANCE);
      generatePartialProgram(program, true, HepMatchOrder.BOTTOM_UP,
          rules.toArray(new RelOptRule[0]));

      // 4. Push down limit through outer join
      // NOTE: We run this after PPD to support old style join syntax.
      // Ex: select * from R1 left outer join R2 where ((R1.x=R2.x) and R1.y<10) or
      // ((R1.x=R2.x) and R1.z=10)) and rand(1) < 0.1 order by R1.x limit 10
      if (conf.getBoolVar(HiveConf.ConfVars.HIVE_OPTIMIZE_LIMIT_TRANSPOSE)) {
        // This should be a cost based decision, but till we enable the extended cost
        // model, we will use the given value for the variable
        final float reductionProportion = HiveConf.getFloatVar(conf,
            HiveConf.ConfVars.HIVE_OPTIMIZE_LIMIT_TRANSPOSE_REDUCTION_PERCENTAGE);
        final long reductionTuples = HiveConf.getLongVar(conf,
            HiveConf.ConfVars.HIVE_OPTIMIZE_LIMIT_TRANSPOSE_REDUCTION_TUPLES);
        generatePartialProgram(program, true, HepMatchOrder.TOP_DOWN,
            HiveSortMergeRule.INSTANCE, HiveSortProjectTransposeRule.INSTANCE,
            HiveSortJoinReduceRule.INSTANCE, HiveSortUnionReduceRule.INSTANCE);
        generatePartialProgram(program, true, HepMatchOrder.BOTTOM_UP,
            new HiveSortRemoveRule(reductionProportion, reductionTuples),
            HiveProjectSortTransposeRule.INSTANCE);
      }

      // Push Down Semi Joins
      //TODO: Enable this later
      /*perfLogger.PerfLogBegin(this.getClass().getName(), PerfLogger.OPTIMIZER);
      basePlan = hepPlan(basePlan, true, mdProvider, executorProvider, SemiJoinJoinTransposeRule.INSTANCE,
          SemiJoinFilterTransposeRule.INSTANCE, SemiJoinProjectTransposeRule.INSTANCE);
      perfLogger.PerfLogEnd(this.getClass().getName(), PerfLogger.OPTIMIZER,
        "Calcite: Prejoin ordering transformation, Push Down Semi Joins"); */

      // 5. Try to remove limit and order by
      generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
          HiveSortLimitRemoveRule.INSTANCE);

      // 6. Apply Partition Pruning
      generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
          new HivePartitionPruneRule(conf));

      // 7. Projection Pruning (this introduces select above TS & hence needs to be run last due to PP)
      generatePartialProgram(program, false, HepMatchOrder.TOP_DOWN,
          new HiveFieldTrimmerRule(true));

      // 8. Rerun PPD through Project as column pruning would have introduced
      // DT above scans; By pushing filter just above TS, Hive can push it into
      // storage (in case there are filters on non partition cols). This only
      // matches FIL-PROJ-TS
      // Also merge, remove and reduce Project if possible
      generatePartialProgram(program, true, HepMatchOrder.TOP_DOWN,
          HiveFilterProjectTSTransposeRule.INSTANCE, HiveFilterProjectTSTransposeRule.INSTANCE_DRUID,
          HiveProjectFilterPullUpConstantsRule.INSTANCE, HiveProjectMergeRule.INSTANCE,
          ProjectRemoveRule.Config.DEFAULT.toRule(), HiveSortMergeRule.INSTANCE);

      // 9. Get rid of sq_count_check if group by key is constant
      if (conf.getBoolVar(ConfVars.HIVE_REMOVE_SQ_COUNT_CHECK)) {
        generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
            HiveRemoveSqCountCheck.INSTANCE);
      }

      // 10. Convert left outer join + null filter on right side table column to anti join. Add this
      // rule after all the optimization for which calcite support for anti join is missing.
      // Needs to be done before ProjectRemoveRule as it expect a project over filter.
      // This is done before join re-ordering as join re-ordering is converting the left outer
      // to right join in some cases before converting back again to left outer.
      if (conf.getBoolVar(ConfVars.HIVE_CONVERT_ANTI_JOIN)) {
        generatePartialProgram(program, false, HepMatchOrder.DEPTH_FIRST,
                HiveAntiSemiJoinRule.INSTANCE);
      }

      generatePartialProgram(program, true, HepMatchOrder.DEPTH_FIRST,
              HiveRemoveEmptySingleRules.PROJECT_INSTANCE,
              HiveRemoveEmptySingleRules.FILTER_INSTANCE,
              HiveRemoveEmptySingleRules.JOIN_LEFT_INSTANCE,
              HiveRemoveEmptySingleRules.SEMI_JOIN_LEFT_INSTANCE,
              HiveRemoveEmptySingleRules.JOIN_RIGHT_INSTANCE,
              HiveRemoveEmptySingleRules.SEMI_JOIN_RIGHT_INSTANCE,
              HiveRemoveEmptySingleRules.ANTI_JOIN_RIGHT_INSTANCE,
              HiveRemoveEmptySingleRules.SORT_INSTANCE,
              HiveRemoveEmptySingleRules.SORT_FETCH_ZERO_INSTANCE,
              HiveRemoveEmptySingleRules.AGGREGATE_INSTANCE,
              HiveRemoveEmptySingleRules.UNION_INSTANCE,
              HiveRemoveEmptySingleRules.CORRELATE_LEFT_INSTANCE,
              HiveRemoveEmptySingleRules.CORRELATE_RIGHT_INSTANCE);

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

      return basePlan;
    }
Perform all optimizations before Join Ordering.

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