private ParseResult rewriteASTWithMaskAndFilter(TableMask tableMask, ASTNode ast, TokenRewriteStream tokenRewriteStream,
                                                Context ctx, Hive db)
      throws SemanticException {
    // 1. collect information about CTE if there is any.
    // The base table of CTE should be masked.
    // The CTE itself should not be masked in the references in the following main query.
    Set<String> cteAlias = new HashSet<>();
    if (ast.getChildCount() > 0
        && HiveParser.TOK_CTE == ((ASTNode) ast.getChild(0)).getToken().getType()) {
      // the structure inside CTE is like this
      // TOK_CTE
      // TOK_SUBQUERY
      // sq1 (may refer to sq2)
      // ...
      // TOK_SUBQUERY
      // sq2
      ASTNode cte = (ASTNode) ast.getChild(0);
      // we start from sq2, end up with sq1.
      for (int index = cte.getChildCount() - 1; index >= 0; index--) {
        ASTNode subq = (ASTNode) cte.getChild(index);
        String alias = unescapeIdentifier(subq.getChild(1).getText());
        if (cteAlias.contains(alias)) {
          throw new SemanticException("Duplicate definition of " + alias);
        } else {
          cteAlias.add(alias);
          walkASTMarkTABREF(tableMask, subq, cteAlias, ctx);
        }
      }
      // walk the other part of ast
      for (int index = 1; index < ast.getChildCount(); index++) {
        walkASTMarkTABREF(tableMask, (ASTNode) ast.getChild(index), cteAlias, ctx);
      }
    }
    // there is no CTE, walk the whole AST
    else {
      walkASTMarkTABREF(tableMask, ast, cteAlias, ctx);
    }
    // 2. rewrite the AST, replace TABREF with masking/filtering
    if (tableMask.needsRewrite()) {
      quoteIdentifierTokens(tokenRewriteStream);
      tableMask.applyTranslations(tokenRewriteStream);
      String rewrittenQuery = tokenRewriteStream.toString(
          ast.getTokenStartIndex(), ast.getTokenStopIndex());
      ASTNode rewrittenTree;
      try {
        // We pass a new empty context with our HiveConf so the lexer can
        // detect if allowQuotedId is enabled.
        Context rewriteCtx = new Context(conf);
        ctx.addSubContext(rewriteCtx);
        rewrittenTree = ParseUtils.parse(rewrittenQuery, rewriteCtx);
        return new ParseResult(rewrittenTree, rewriteCtx.getTokenRewriteStream(),
            rewriteCtx.getParsedTables());
      } catch (ParseException e) {
        throw new SemanticException(e);
      }
    } else {
      return new ParseResult(ast, ctx.getTokenRewriteStream(), ctx.getParsedTables());
    }
  }
Planner specific stuff goes in here.
ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java