private static boolean checkFullOuterMapJoinCompatible(HiveConf hiveConf,
      JoinOperator joinOp) throws SemanticException {
    JoinDesc joinDesc = joinOp.getConf();

    // Make sure all key and value expressions are columns.
    for (Entry<Byte, List<ExprNodeDesc>> mapEntry : joinDesc.getExprs().entrySet()) {
      List<ExprNodeDesc> exprList = mapEntry.getValue();
      for (ExprNodeDesc expr : exprList) {
        if (!(expr instanceof ExprNodeColumnDesc)) {
          LOG.debug("FULL OUTER MapJoin: only column expressions are supported " + expr.toString());
          return false;
        }
      }
    }

    // Check for supported key data types.
    Byte[] order = joinDesc.getTagOrder();
    ExprNodeDesc[][] joinKeysArray = joinDesc.getJoinKeys();
    for (int i = 0; i < order.length; i++) {
      byte pos = order[i];
      ExprNodeDesc[] keyExprs = joinKeysArray[pos];
      for (ExprNodeDesc keyExpr : keyExprs) {
        TypeInfo typeInfo = keyExpr.getTypeInfo();

        // Verify we handle the key column types for an optimized table.  This is the effectively
        // the same check used in Tez HashTableLoader.
        if (!MapJoinKey.isSupportedField(typeInfo)) {
          LOG.debug("FULL OUTER MapJoin not enabled: key type {} not supported", typeInfo);
          return false;
        }
      }
    }

    if (onExpressionHasNullSafes(joinDesc)) {
      LOG.debug("FULL OUTER MapJoin not enabled: nullsafe not supported");
      return false;
    }

    boolean isVectorizationMapJoinNativeEnabled = HiveConf.getBoolVar(hiveConf,
        HiveConf.ConfVars.HIVE_VECTORIZATION_MAPJOIN_NATIVE_ENABLED);
    boolean isHybridHashJoin = HiveConf.getBoolVar(hiveConf,
        HiveConf.ConfVars.HIVE_USE_HYBRIDGRACE_HASHJOIN);
    if (isVectorizationMapJoinNativeEnabled && isHybridHashJoin) {
      LOG.debug("FULL OUTER MapJoin not enabled: Native Vector MapJoin and Hybrid Grace not supported");
      return false;
    }

    if (joinDesc.getResidualFilterExprs() != null &&
        joinDesc.getResidualFilterExprs().size() != 0) {
      LOG.debug("FULL OUTER MapJoin not enabled: non-equi joins not supported");
      return false;
    }

    // Do not convert to MapJoin if FullOuterJoin has any filter expression.
    // This partially disables HIVE-18908 optimization and solves the MapJoin correctness problems
    // described in HIVE-27226.
    if (joinDesc.getFilters() != null) {
      // Unlike CommonJoinOperator.hasFilter(), we check getFilters() instead of getFilterMap() because
      // getFilterMap() can be non-null while getFilters() is empty.

      boolean hasFullOuterJoinWithFilter = Arrays.stream(joinDesc.getConds()).anyMatch(cond -> {
        if (cond.getType() == JoinDesc.FULL_OUTER_JOIN) {
          Byte left = (byte) cond.getLeft();
          Byte right = (byte) cond.getRight();
          boolean leftHasFilter =
              joinDesc.getFilters().containsKey(left) && !joinDesc.getFilters().get(left).isEmpty();
          boolean rightHasFilter =
              joinDesc.getFilters().containsKey(right) && !joinDesc.getFilters().get(right).isEmpty();
          return leftHasFilter || rightHasFilter;
        } else {
          return false;
        }
      });
      if (hasFullOuterJoinWithFilter) {
        LOG.debug("FULL OUTER MapJoin not enabled: FullOuterJoin with filters not supported");
        return false;
      }
    }

    return true;
  }
convert a regular join to a a map-side join.

@param op
         join operator
@param mapJoinPos
         position of the source to be read as part of map-reduce framework. All other sources
         are cached in memory
@param noCheckOuterJoin
@param validateMapJoinTree
ql/src/java/org/apache/hadoop/hive/ql/optimizer/MapJoinProcessor.java