private static boolean compareOperator(ParseContext pctx, Operator<?> op1, Operator<?> op2)
          throws SemanticException {
    if (!op1.getClass().getName().equals(op2.getClass().getName())) {
      return false;
    }

    // We handle ReduceSinkOperator here as we can safely ignore table alias
    // and the current comparator implementation does not.
    // We can ignore table alias since when we compare ReduceSinkOperator, all
    // its ancestors need to match (down to table scan), thus we make sure that
    // both plans are the same.
    // TODO: move this to logicalEquals
    if (op1 instanceof ReduceSinkOperator) {
      ReduceSinkDesc op1Conf = ((ReduceSinkOperator) op1).getConf();
      ReduceSinkDesc op2Conf = ((ReduceSinkOperator) op2).getConf();

      if (StringUtils.equals(op1Conf.getKeyColString(), op2Conf.getKeyColString()) &&
        StringUtils.equals(op1Conf.getValueColsString(), op2Conf.getValueColsString()) &&
        StringUtils.equals(op1Conf.getParitionColsString(), op2Conf.getParitionColsString()) &&
        op1Conf.getTag() == op2Conf.getTag() &&
        StringUtils.equals(op1Conf.getOrder(), op2Conf.getOrder()) &&
        StringUtils.equals(op1Conf.getNullOrder(), op2Conf.getNullOrder()) &&
        op1Conf.getTopN() == op2Conf.getTopN() &&
        canDeduplicateReduceTraits(op1Conf, op2Conf)) {
        return true;
      } else {
        return false;
      }
    }

    // We handle TableScanOperator here as we can safely ignore table alias
    // and the current comparator implementation does not.
    // TODO: move this to logicalEquals
    if (op1 instanceof TableScanOperator) {
      TableScanOperator tsOp1 = (TableScanOperator) op1;
      TableScanOperator tsOp2 = (TableScanOperator) op2;
      TableScanDesc op1Conf = tsOp1.getConf();
      TableScanDesc op2Conf = tsOp2.getConf();

      Table tableMeta1 = op1Conf.getTableMetadata();
      Table tableMeta2 = op2Conf.getTableMetadata();
      if (StringUtils.equals(tableMeta1.getFullyQualifiedName(), tableMeta2.getFullyQualifiedName())
          && op1Conf.getNeededColumns().equals(op2Conf.getNeededColumns())
          && StringUtils.equals(op1Conf.getFilterExprString(), op2Conf.getFilterExprString())
          && pctx.getPrunedPartitions(tsOp1).getPartitions().equals(
              pctx.getPrunedPartitions(tsOp2).getPartitions())
          && op1Conf.getRowLimit() == op2Conf.getRowLimit()
          && Objects.equals(op1Conf.getIncludedBuckets(), op2Conf.getIncludedBuckets())
          && Objects.equals(op1Conf.getOpProps(), op2Conf.getOpProps())) {
        return true;
      } else {
        return false;
      }
    }

    return op1.logicalEquals(op2);
  }
Orders TS operators in decreasing order by "weight".
ql/src/java/org/apache/hadoop/hive/ql/optimizer/SharedWorkOptimizer.java