private static void processSetColsNode(ASTNode setCols, ASTSearcher searcher, Context ctx) {
    searcher.reset();
    CommonTree rootNode = setCols;
    while (rootNode != null && rootNode.getType() != HiveParser.TOK_INSERT) {
      rootNode = rootNode.parent;
    }
    if (rootNode == null || rootNode.parent == null) {
      // Couldn't find the parent insert; replace with ALLCOLREF.
      LOG.debug("Replacing SETCOLREF with ALLCOLREF because we couldn't find the root INSERT");
      setCols.token.setType(HiveParser.TOK_ALLCOLREF);
      return;
    }
    rootNode = rootNode.parent; // TOK_QUERY above insert
    Tree fromNode = null;
    for (int j = 0; j < rootNode.getChildCount(); ++j) {
      Tree child = rootNode.getChild(j);
      if (child.getType() == HiveParser.TOK_FROM) {
        fromNode = child;
        break;
      }
    }
    if (!(fromNode instanceof ASTNode)) {
      // Couldn't find the from that contains subquery; replace with ALLCOLREF.
      LOG.debug("Replacing SETCOLREF with ALLCOLREF because we couldn't find the FROM");
      setCols.token.setType(HiveParser.TOK_ALLCOLREF);
      return;
    }
    // We are making what we are trying to do more explicit if there's a union alias; so
    // that if we do something we didn't expect to do, it'd be more likely to fail.
    String alias = null;
    if (fromNode.getChildCount() > 0) {
      Tree fromWhat = fromNode.getChild(0);
      if (fromWhat.getType() == HiveParser.TOK_SUBQUERY && fromWhat.getChildCount() > 1) {
        Tree child = fromWhat.getChild(fromWhat.getChildCount() - 1);
        if (child.getType() == HiveParser.Identifier) {
          alias = child.getText();
        }
      }
    }
    // Note: we assume that this isn't an already malformed query;
    //       we don't check for that here - it will fail later anyway.
    // First, we find the SELECT closest to the top.
    ASTNode select = searcher.simpleBreadthFirstSearchAny((ASTNode)fromNode,
        HiveParser.TOK_SELECT, HiveParser.TOK_SELECTDI);
    if (select == null) {
      // Couldn't find the from that contains subquery; replace with ALLCOLREF.
      LOG.debug("Replacing SETCOLREF with ALLCOLREF because we couldn't find the SELECT");
      setCols.token.setType(HiveParser.TOK_ALLCOLREF);
      return;
    }

    // Then, find the leftmost logical sibling select, because that's what Hive uses for aliases.
    while (true) {
      CommonTree queryOfSelect = select.parent;
      while (queryOfSelect != null && queryOfSelect.getType() != HiveParser.TOK_QUERY) {
        queryOfSelect = queryOfSelect.parent;
      }
      // We should have some QUERY; and also its parent because by supposition we are in subq.
      if (queryOfSelect == null || queryOfSelect.parent == null) {
        LOG.debug("Replacing SETCOLREF with ALLCOLREF because we couldn't find the QUERY");
        setCols.token.setType(HiveParser.TOK_ALLCOLREF);
        return;
      }
      if (queryOfSelect.childIndex == 0) {
        break; // We are the left-most child.
      }
      Tree moreToTheLeft = queryOfSelect.parent.getChild(0);
      Preconditions.checkState(moreToTheLeft != queryOfSelect);
      ASTNode newSelect = searcher.simpleBreadthFirstSearchAny((ASTNode)moreToTheLeft,
          HiveParser.TOK_SELECT, HiveParser.TOK_SELECTDI);
      Preconditions.checkState(newSelect != select);
      select = newSelect;
      // Repeat the procedure for the new select.
    }

    // Find the proper columns.
    List<ASTNode> newChildren = new ArrayList<>(select.getChildCount());
    Set<String> aliases = new HashSet<>();
    for (int i = 0; i < select.getChildCount(); ++i) {
      Tree selExpr = select.getChild(i);
      if (selExpr.getType() == HiveParser.QUERY_HINT) {
        continue;
      }
      assert selExpr.getType() == HiveParser.TOK_SELEXPR;
      assert selExpr.getChildCount() > 0;
      // we can have functions which generate multiple aliases (e.g. explode(map(x, y)) as (key, val))
      boolean isFunctionWithMultipleParameters =
          selExpr.getChild(0).getType() == HiveParser.TOK_FUNCTION && selExpr.getChildCount() > 2;
      // if so let's skip the function token buth then examine all its parameters - otherwise check only the last item
      int start = isFunctionWithMultipleParameters ? 1 : selExpr.getChildCount() - 1;
      for (int j = start; j < selExpr.getChildCount(); ++j) {
        Tree child = selExpr.getChild(j);
        switch (child.getType()) {
        case HiveParser.TOK_SETCOLREF:
          // We have a nested setcolref. Process that and start from scratch TODO: use stack?
          processSetColsNode((ASTNode) child, searcher, ctx);
          processSetColsNode(setCols, searcher, ctx);
          return;
        case HiveParser.TOK_ALLCOLREF:
          // We should find an alias of this insert and do (alias).*. This however won't fix e.g.
          // positional order by alias case, cause we'd still have a star on the top level. Bail.
          LOG.debug("Replacing SETCOLREF with ALLCOLREF because of nested ALLCOLREF");
          setCols.token.setType(HiveParser.TOK_ALLCOLREF);
          return;
        case HiveParser.TOK_TABLE_OR_COL:
          Tree idChild = child.getChild(0);
          assert idChild.getType() == HiveParser.Identifier : idChild;
          if (!createChildColumnRef(idChild, alias, newChildren, aliases, ctx)) {
            setCols.token.setType(HiveParser.TOK_ALLCOLREF);
            return;
          }
          break;
        case HiveParser.Identifier:
          if (!createChildColumnRef(child, alias, newChildren, aliases, ctx)) {
            setCols.token.setType(HiveParser.TOK_ALLCOLREF);
            return;
          }
          break;
        case HiveParser.DOT:
          Tree colChild = child.getChild(child.getChildCount() - 1);
          assert colChild.getType() == HiveParser.Identifier : colChild;
          if (!createChildColumnRef(colChild, alias, newChildren, aliases, ctx)) {
            setCols.token.setType(HiveParser.TOK_ALLCOLREF);
            return;
          }
          break;
        default:
          // Not really sure how to refer to this (or if we can).
          // TODO: We could find a different from branch for the union, that might have an alias?
          //       Or we could add an alias here to refer to, but that might break other branches.
          LOG.debug("Replacing SETCOLREF with ALLCOLREF because of the nested node "
              + child.getType() + " " + child.getText());
          setCols.token.setType(HiveParser.TOK_ALLCOLREF);
          return;
        }
      }
    }
    // Insert search in the beginning would have failed if these parents didn't exist.
    ASTNode parent = (ASTNode)setCols.parent.parent;
    int t = parent.getType();
    assert t == HiveParser.TOK_SELECT || t == HiveParser.TOK_SELECTDI : t;
    int ix = setCols.parent.childIndex;
    parent.deleteChild(ix);
    for (ASTNode node : newChildren) {
      parent.insertChild(ix++, node);
    }
  }
Replaces a spurious TOK_SETCOLREF added by parser with column names referring to the query
in e.g. a union. This is to maintain the expectations that some code, like order by position
alias, might have about not having ALLCOLREF. If it cannot find the columns with confidence
it will just replace SETCOLREF with ALLCOLREF. Most of the cases where that happens are
easy to work around in the query (e.g. by adding column aliases in the union).
@param setCols TOK_SETCOLREF ASTNode.
@param searcher AST searcher to reuse.
ql/src/java/org/apache/hadoop/hive/ql/parse/ParseUtils.java