public void insertTableValuesAnalyzePipeline() throws SemanticException {
    // Instead of starting from analyze statement, we just generate the Select plan
    boolean isPartitionStats = StatsUtils.isPartitionStats(tbl, conf);
    if (isPartitionStats) {
      partSpec = new HashMap<>();
      List<String> partKeys = Utilities.getColumnNamesFromFieldSchema(tbl.getPartitionKeys());
      partKeys.forEach(k -> partSpec.put(k, null));

      if (tbl.hasNonNativePartitionSupport()) {
        partTransformSpec = tbl.getStorageHandler().getPartitionTransformSpec(tbl);
      }
    }
    String command = ColumnStatsSemanticAnalyzer.genRewrittenQuery(
        tbl, conf, partTransformSpec, partSpec, isPartitionStats);
    insertAnalyzePipeline(command, true);
  }
Generate the statement of SELECT compute_stats(col1) compute_stats(col2),...,
similar to the one generated from ANALYZE TABLE t1 COMPUTE STATISTICS FOR COLUMNS,
but t1 is replaced by a TABLE(VALUES(cast(null as int),cast(null as string))) AS t1(col1,col2).

We use TABLE-VALUES statement for computing stats for CTAS statement because in those cases
the table has not been created yet. Once the plan for the SELECT statement is generated,
we connect it to the existing CTAS plan as we do for INSERT or INSERT OVERWRITE.
ql/src/java/org/apache/hadoop/hive/ql/parse/ColumnStatsAutoGatherContext.java