public List<FieldNode> genColLists(Operator<? extends OperatorDesc> curOp)
      throws SemanticException {
    if (curOp.getChildOperators() == null) {
      return null;
    }
    List<FieldNode> colList = null;
    for (Operator<? extends OperatorDesc> child : curOp.getChildOperators()) {
      List<FieldNode> prunList = null;
      if (child instanceof CommonJoinOperator) {
        int tag = child.getParentOperators().indexOf(curOp);
        prunList = joinPrunedColLists.get(child).get((byte) tag);
      } else if (child instanceof FileSinkOperator) {
        prunList = new ArrayList<>();
        RowSchema oldRS = curOp.getSchema();
        for (ColumnInfo colInfo : oldRS.getSignature()) {
          prunList.add(new FieldNode(colInfo.getInternalName()));
        }
      } else {
        prunList = prunedColLists.get(child);
      }
      if (prunList == null) {
        continue;
      }
      if (colList == null) {
        colList = new ArrayList<>(prunList);
      } else {
        colList = mergeFieldNodes(colList, prunList);
      }
    }
    return colList;
  }
Creates the list of internal column names(represented by field nodes,
these names are used in the RowResolver and are different from the
external column names) that are needed in the subtree. These columns
eventually have to be selected from the table scan.

@param curOp The root of the operator subtree.
@return a list of field nodes representing the internal column names.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/ColumnPrunerProcCtx.java