static ASTNode replaceAliases(ASTNode node, int nodePos, Map<String, String> colToTableAlias) {
    if (node == null) {
      return node;
    }

    int nodeType = node.getToken().getType();
    if (nodeType == HiveParser.TOK_TABLE_OR_COL || nodeType == HiveParser.DOT) {
      String colName = HQLParser.getColName(node);
      String newAlias = colToTableAlias.get(colName.toLowerCase());

      if (StringUtils.isBlank(newAlias)) {
        return node;
      }

      if (nodeType == HiveParser.DOT) {
        // No need to create a new node, just replace the table name ident
        ASTNode aliasNode = (ASTNode) node.getChild(0);
        ASTNode newAliasIdent = new ASTNode(new CommonToken(HiveParser.Identifier, newAlias));
        aliasNode.setChild(0, newAliasIdent);
      } else {
        // Just a column ref, we need to make it alias.col
        // '.' will become the parent node
        ASTNode dot = new ASTNode(new CommonToken(HiveParser.DOT, "."));
        ASTNode aliasIdentNode = new ASTNode(new CommonToken(HiveParser.Identifier, newAlias));
        ASTNode tabRefNode =
            new ASTNode(new CommonToken(HiveParser.TOK_TABLE_OR_COL, "TOK_TABLE_OR_COL"));

        tabRefNode.addChild(aliasIdentNode);
        dot.addChild(tabRefNode);

        ASTNode colIdentNode = new ASTNode(new CommonToken(HiveParser.Identifier, colName));
        dot.addChild(colIdentNode);

        ASTNode parent = (ASTNode) node.getParent();
        if (parent != null) {
          parent.setChild(nodePos, dot);
        } else {
          return dot;
        }
      }
    } else {
      // recurse down
      for (int i = 0; i < node.getChildCount(); i++) {
        ASTNode child = (ASTNode) node.getChild(i);
        replaceAliases(child, i, colToTableAlias);
      }
    }
    return node;
  }
  @Override
  public void rewriteContext(CubeQueryContext cubeql) throws LensException {
    Map<String, String> colToTableAlias = cubeql.getColToTableAlias();

    extractTabAliasForCol(cubeql);
    findDimAttributesAndMeasures(cubeql);

    if (colToTableAlias.isEmpty()) {
      return;
    }

    // Rewrite the all the columns in the query with table alias prefixed.
    // If col1 of table tab1 is accessed, it would be changed as tab1.col1.
    // If tab1 is already aliased say with t1, col1 is changed as t1.col1
    // replace the columns in select, groupby, having, orderby by
    // prepending the table alias to the col
    // sample select trees
    // 1: (TOK_SELECT (TOK_SELEXPR (TOK_TABLE_OR_COL key))
    // (TOK_SELEXPR (TOK_FUNCTION count (TOK_TABLE_OR_COL value))))
    // 2: (TOK_SELECT (TOK_SELEXPR (. (TOK_TABLE_OR_COL src) key))
    // (TOK_SELEXPR (TOK_FUNCTION count (. (TOK_TABLE_OR_COL src) value))))
    // 3: (TOK_SELECT (TOK_SELEXPR (. (TOK_TABLE_OR_COL src) key) srckey))))
    replaceAliases(cubeql.getSelectAST(), 0, colToTableAlias);

    replaceAliases(cubeql.getHavingAST(), 0, colToTableAlias);

    replaceAliases(cubeql.getOrderByAST(), 0, colToTableAlias);

    replaceAliases(cubeql.getGroupByAST(), 0, colToTableAlias);

    replaceAliases(cubeql.getWhereAST(), 0, colToTableAlias);

    replaceAliases(cubeql.getJoinAST(), 0, colToTableAlias);

    // Update the aggregate expression set
    AggregateResolver.updateAggregates(cubeql.getSelectAST(), cubeql);
    AggregateResolver.updateAggregates(cubeql.getHavingAST(), cubeql);
    // Update alias map as well
    updateAliasMap(cubeql.getSelectAST(), cubeql);
  }
 public void replaceAliasInAST(CubeQueryContext cubeql) throws SemanticException {
   AliasReplacer.extractTabAliasForCol(cubeql, this);
   AliasReplacer.replaceAliases(finalAST, 0, cubeql.getColToTableAlias());
 }