private List<Partition> exchangePartitions(Map<String, String> partitionSpecs,
      org.apache.hadoop.hive.metastore.api.Table sourceTable, TempTable sourceTempTable,
      org.apache.hadoop.hive.metastore.api.Table destTable, TempTable destTempTable) throws TException {
    if (partitionSpecs == null || partitionSpecs.isEmpty()) {
      throw new MetaException("PartitionSpecs cannot be null or empty.");
    }
    List<String> partitionVals = getPvals(sourceTable.getPartitionKeys(), partitionSpecs);
    if (partitionVals.stream().allMatch(String::isEmpty)) {
      throw new MetaException("Invalid partition key & values; keys " +
          Arrays.toString(sourceTable.getPartitionKeys().toArray()) + ", values " +
          Arrays.toString(partitionVals.toArray()));
    }
    List<Partition> partitionsToExchange = sourceTempTable
        .getPartitionsByPartitionVals(partitionVals);
    if (partitionSpecs == null) {
      throw new MetaException("The partition specs must be not null.");
    }
    if (partitionsToExchange.isEmpty()) {
      throw new MetaException(
          "No partition is found with the values " + partitionSpecs + " for the table " + sourceTable.getTableName());
    }

    boolean sameColumns = compareFieldColumns(sourceTable.getSd().getCols(), destTable.getSd().getCols());
    boolean samePartitions = compareFieldColumns(sourceTable.getPartitionKeys(), destTable.getPartitionKeys());
    if (!(sameColumns && samePartitions)) {
      throw new MetaException("The tables have different schemas. Their partitions cannot be exchanged.");
    }
    // Check if any of the partitions already exists in the destTable
    for (Partition partition : partitionsToExchange) {
      String partToExchangeName = makePartName(destTable.getPartitionKeys(), partition.getValues());
      if (destTempTable.getPartition(partToExchangeName) != null) {
        throw new MetaException(
            "The partition " + partToExchangeName + " already exists in the table " + destTable.getTableName());
      }
    }

    List<Partition> result = new ArrayList<>();
    for (Partition partition : partitionsToExchange) {
      Partition destPartition = new Partition(partition);
      destPartition.setCatName(destTable.getCatName());
      destPartition.setDbName(destTable.getDbName());
      destPartition.setTableName(destTable.getTableName());
      // the destPartition is created from the original partition, therefore all it's properties are copied, including
      // the location. We must force the rewrite of the location (getPartitionLocation(forceRewrite=true))
      destPartition.getSd().setLocation(getPartitionLocation(destTable, destPartition, true).toString());
      wh.renameDir(new Path(partition.getSd().getLocation()), new Path(destPartition.getSd().getLocation()), false);
      destPartition = destTempTable.addPartition(destPartition);
      dropPartition(sourceTable.getDbName(), sourceTable.getTableName(), partition.getValues());
      result.add(destPartition);
    }
    return result;
  }
@param partialPvals partition values, can be partial.  This really means that missing values
                   are represented by empty str.
@param maxParts maximum number of partitions to fetch, or -1 for all
ql/src/java/org/apache/hadoop/hive/ql/metadata/SessionHiveMetaStoreClient.java