private WriteEntity generateTableWriteEntity(String dest, Table dest_tab,
                                               Map<String, String> partSpec, LoadTableDesc ltd,
                                               DynamicPartitionCtx dpCtx)
      throws SemanticException {
    WriteEntity output = null;

    // Here only register the whole table for post-exec hook if no DP present
    // in the case of DP, we will register WriteEntity in MoveTask when the
    // list of dynamically created partitions are known.
    if ((dpCtx == null || dpCtx.getNumDPCols() == 0)) {
      output = new WriteEntity(dest_tab, determineWriteType(ltd, dest));
      if (!outputs.add(output)) {
        if(!allowOutputMultipleTimes()) {
          /**
           * Merge stmt with early split update may create several (2) writes to the same
           * table with the same {@link WriteType}, e.g. if original Merge stmt has both update and
           * delete clauses, and update is split into insert + delete, in which case it's not an
           * error*/
          throw new SemanticException(ErrorMsg.OUTPUT_SPECIFIED_MULTIPLE_TIMES
              .getMsg(dest_tab.getTableName()));
        }
      }
    }

    if ((dpCtx != null) && (dpCtx.getNumDPCols() >= 0)) {
      // No static partition specified
      if (dpCtx.getNumSPCols() == 0) {
        output = new WriteEntity(dest_tab, determineWriteType(ltd, dest), true);
        outputs.add(output);
        output.setDynamicPartitionWrite(true);
      }
      // part of the partition specified
      // Create a DummyPartition in this case. Since, the metastore does not store partial
      // partitions currently, we need to store dummy partitions
      else {
        String ppath = dpCtx.getSPPath();
        ppath = ppath.substring(0, ppath.length() - 1);
        DummyPartition p = new DummyPartition(dest_tab, 
            dest_tab.getDbName() + "@" + dest_tab.getTableName() + "@" + ppath, 
          partSpec);
        WriteEntity.WriteType writeType;
        if (ltd.isInsertOverwrite()) {
          writeType = WriteEntity.WriteType.INSERT_OVERWRITE;
        } else {
          writeType = getWriteType(dest);
        }
        output = new WriteEntity(p, writeType, false);
        output.setDynamicPartitionWrite(true);
        outputs.add(output);
      }
    }
    return output;
  }
We will directly insert to the final destination in the following cases:
1. Non native table
2. Micro-managed (insert only table)
3. Full ACID table and operation type is INSERT
ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java