public Table toTable(HiveConf conf) throws HiveException {

    Table tbl = new Table(tableName.getDb(), tableName.getTable());

    if (getTblProps() != null) {
      tbl.getTTable().getParameters().putAll(getTblProps());
    }

    if (getNumBuckets() != -1) {
      tbl.setNumBuckets(getNumBuckets());
    }

    if (getStorageHandler() != null) {
      tbl.setProperty(
              org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.META_TABLE_STORAGE,
              getStorageHandler());
    }
    HiveStorageHandler storageHandler = tbl.getStorageHandler();

    /*
     * If the user didn't specify a SerDe, we use the default.
     */
    String serDeClassName;
    if (getSerde() == null) {
      if (storageHandler == null) {
        serDeClassName = PlanUtils.getDefaultSerDe().getName();
        LOG.info("Default to " + serDeClassName + " for table " + tableName);
      } else {
        serDeClassName = storageHandler.getSerDeClass().getName();
        LOG.info("Use StorageHandler-supplied " + serDeClassName
                + " for table " + tableName);
      }
    } else {
      // let's validate that the serde exists
      serDeClassName = getSerde();
      DDLUtils.validateSerDe(serDeClassName, conf);
    }
    tbl.setSerializationLib(serDeClassName);

    if (getFieldDelim() != null) {
      tbl.setSerdeParam(serdeConstants.FIELD_DELIM, getFieldDelim());
      tbl.setSerdeParam(serdeConstants.SERIALIZATION_FORMAT, getFieldDelim());
    }
    if (getFieldEscape() != null) {
      tbl.setSerdeParam(serdeConstants.ESCAPE_CHAR, getFieldEscape());
    }

    if (getCollItemDelim() != null) {
      tbl.setSerdeParam(serdeConstants.COLLECTION_DELIM, getCollItemDelim());
    }
    if (getMapKeyDelim() != null) {
      tbl.setSerdeParam(serdeConstants.MAPKEY_DELIM, getMapKeyDelim());
    }
    if (getLineDelim() != null) {
      tbl.setSerdeParam(serdeConstants.LINE_DELIM, getLineDelim());
    }
    if (getNullFormat() != null) {
      tbl.setSerdeParam(serdeConstants.SERIALIZATION_NULL_FORMAT, getNullFormat());
    }
    if (getSerdeProps() != null) {
      getSerdeProps().forEach(tbl::setSerdeParam);
    }

    setColumnsAndStorePartitionTransformSpecOfTable(getCols(), getPartCols(), conf, tbl);

    if (getBucketCols() != null) {
      tbl.setBucketCols(getBucketCols());
    }
    if (getSortCols() != null) {
      tbl.setSortCols(getSortCols());
    }
    if (getComment() != null) {
      tbl.setProperty("comment", getComment());
    }
    if (getLocation() != null) {
      tbl.setDataLocation(new Path(getLocation()));
    }

    if (getSkewedColNames() != null) {
      tbl.setSkewedColNames(getSkewedColNames());
    }
    if (getSkewedColValues() != null) {
      tbl.setSkewedColValues(getSkewedColValues());
    }

    tbl.getTTable().setTemporary(isTemporary());

    tbl.setStoredAsSubDirectories(isStoredAsSubDirectories());

    tbl.setInputFormatClass(getInputFormat());
    tbl.setOutputFormatClass(getOutputFormat());

    // only persist input/output format to metadata when it is explicitly specified.
    // Otherwise, load lazily via StorageHandler at query time.
    if (getInputFormat() != null && !getInputFormat().isEmpty()) {
      tbl.getTTable().getSd().setInputFormat(tbl.getInputFormatClass().getName());
    }
    if (getOutputFormat() != null && !getOutputFormat().isEmpty()) {
      tbl.getTTable().getSd().setOutputFormat(tbl.getOutputFormatClass().getName());
    }

    if (CreateTableOperation.doesTableNeedLocation(tbl)) {
      // If location is specified - ensure that it is a full qualified name
      CreateTableOperation.makeLocationQualified(tbl, conf);
    }

    if (isExternal()) {
      tbl.setProperty("EXTERNAL", "TRUE");
      tbl.setTableType(TableType.EXTERNAL_TABLE);
    }

    // If the sorted columns is a superset of bucketed columns, store this fact.
    // It can be later used to
    // optimize some group-by queries. Note that, the order does not matter as
    // long as it in the first
    // 'n' columns where 'n' is the length of the bucketed columns.
    if ((tbl.getBucketCols() != null) && (tbl.getSortCols() != null)) {
      List<String> bucketCols = tbl.getBucketCols();
      List<Order> sortCols = tbl.getSortCols();

      if ((!sortCols.isEmpty()) && (sortCols.size() >= bucketCols.size())) {
        boolean found = true;

        for (String bucketCol : bucketCols) {
          boolean colFound = false;
          for (int i = 0; i < bucketCols.size(); i++) {
            if (bucketCol.equals(sortCols.get(i).getCol())) {
              colFound = true;
              break;
            }
          }
          if (!colFound) {
            found = false;
            break;
          }
        }
        if (found) {
          tbl.setProperty("SORTBUCKETCOLSPREFIX", "TRUE");
        }
      }
    }

    if (colStats != null) {
      ColumnStatisticsDesc colStatsDesc = new ColumnStatisticsDesc(colStats.getStatsDesc());
      colStatsDesc.setCatName(tbl.getCatName());
      colStatsDesc.setDbName(tbl.getDbName());
      colStatsDesc.setTableName(tbl.getTableName());
      String engine = colStats.getEngine();
      if (engine == null) {
        engine = org.apache.hadoop.hive.conf.Constants.HIVE_ENGINE;
      }
      ColumnStatistics columnStatistics = new ColumnStatistics(colStatsDesc, colStats.getStatsObj());
      columnStatistics.setEngine(engine);
      tbl.getTTable().setColStats(columnStatistics);
      // Statistics will have an associated write Id for a transactional table. We need it to
      // update column statistics.
      if (replWriteId > 0) {
        tbl.getTTable().setWriteId(replWriteId);
      }
    }

    // When replicating the statistics for a table will be obtained from the source. Do not
    // reset it on replica.
    if (replicationSpec == null || !replicationSpec.isInReplicationScope()) {
      // Remove COLUMN_STATS_ACCURATE=true from table's parameter, let the HMS determine if
      // there is need to add column stats dependent on the table's location.
      StatsSetupConst.setStatsStateForCreateTable(tbl.getTTable().getParameters(), null,
          StatsSetupConst.FALSE);
      if (!this.isCTAS && !tbl.isPartitioned() && !tbl.isTemporary() &&
          conf.getBoolVar(HiveConf.ConfVars.HIVE_STATS_AUTOGATHER)) {
        // Put the flag into the dictionary in order not to pollute the table,
        // ObjectDictionary is meant to convey repeatitive messages.
        ObjectDictionary dictionary = tbl.getTTable().isSetDictionary() ?
            tbl.getTTable().getDictionary() : new ObjectDictionary();
        List<ByteBuffer> buffers = new ArrayList<>();
        String statsSetup = StatsSetupConst.ColumnStatsSetup.getStatsSetupAsString(true,
            // Ignore all Iceberg leftover files when storageHandler.isTableIdentifierSupported() is true,
            // as the method is only enabled in Iceberg currently.
            storageHandler != null && storageHandler.isTableMetaRefSupported(),
            MetaStoreUtils.getColumnNames(tbl.getCols()));
        buffers.add(ByteBuffer.wrap(statsSetup.getBytes(StandardCharsets.UTF_8)));
        dictionary.putToValues(StatsSetupConst.STATS_FOR_CREATE_TABLE, buffers);
        tbl.getTTable().setDictionary(dictionary);
      }
    }

    if (ownerName != null) {
      tbl.setOwner(ownerName);
    }
    return tbl;
  }
@return what kind of replication scope this drop is running under.
This can result in a "CREATE/REPLACE IF NEWER THAN" kind of semantic
ql/src/java/org/apache/hadoop/hive/ql/ddl/table/create/CreateTableDesc.java