public void resolveConcatenateMerge(HiveConf conf) {
    isListBucketingAlterTableConcatenate =
        ((listBucketingCtx == null) ? false : listBucketingCtx
            .isSkewedStoredAsDir());
    LOG.info("isListBucketingAlterTableConcatenate : " +
        isListBucketingAlterTableConcatenate);
    if (isListBucketingAlterTableConcatenate) {
      // use sub-dir as inputpath.
      assert ((this.inputPaths != null) && (this.inputPaths.size() == 1)) :
          "alter table ... concatenate should only have one" +
              " directory inside inputpaths";
      Path dirPath = inputPaths.get(0);
      try {
        FileSystem inpFs = dirPath.getFileSystem(conf);
        List<FileStatus> status = HiveStatsUtils.getFileStatusRecurse(
            dirPath, listBucketingCtx.getSkewedColNames().size(), inpFs);
        List<Path> newInputPath = new ArrayList<Path>();
        boolean succeed = true;
        for (FileStatus s : status) {
          if (s.isDir()) {
            // Add the lb path to the list of input paths
            newInputPath.add(s.getPath());
          } else {
            // find file instead of dir. dont change inputpath
            succeed = false;
          }
        }
        assert (succeed || ((!succeed) && newInputPath.isEmpty())) :
            "This partition has "
                + " inconsistent file structure: "
                +
                "it is stored-as-subdir and expected all files in the same depth"
                + " of subdirectories.";
        if (succeed) {
          inputPaths.clear();
          inputPaths.addAll(newInputPath);
        }
      } catch (IOException e) {
        String msg =
            "Fail to get filesystem for directory name : " + dirPath.toUri();
        throw new RuntimeException(msg, e);
      }

    }
  }
alter table ... concatenate
<br>
If it is skewed table, use subdirectories in inputpaths.
ql/src/java/org/apache/hadoop/hive/ql/io/merge/MergeFileWork.java