001package gudusoft.gsqlparser.nodes;
002
003
004import gudusoft.gsqlparser.TBaseType;
005import gudusoft.gsqlparser.TSourceToken;
006import gudusoft.gsqlparser.TSourceTokenList;
007
008import java.util.ArrayList;
009
010
011public class TNodeWithAliasClause extends TParseTreeNode {
012
013    /**
014     * 在 sql script 中,和该 relation 关联的 attribute。
015     * select a from t;
016     * attribute a 就是 relation t 的 referenceAttribute, 如果没有 metadata and ddl,
017     * relation t 的 relationAttributes 应该可以推断出包含 a, 但 t 是否还包含其他的 attribute 就无从得知。
018     */
019    ArrayList<TObjectName> referenceAttributes = new ArrayList<>();
020    public void setAliasClause(TAliasClause aliasClause) {
021        this.aliasClause = aliasClause;
022    }
023
024    private TAliasClause aliasClause = null;
025
026    public TAliasClause getAliasClause() {
027        return aliasClause;
028    }
029
030    /**
031     * Tf there is no alias clause of this node, then toString() is the same as {@link TParseTreeNode}
032     * <p> Otherwise, return text of  node only, don't include text of alias clause.
033     * <p> If this node was modified by {@link TParseTreeNode#setString(String)}, then node text including alias node
034     * text was replaced by new string.
035     * @return
036     */
037    public String toString() {
038        // Cache the alias clause reference to avoid repeated method calls
039        final TAliasClause aliasClause = this.getAliasClause();
040        
041        // Fast path for common case
042        if (aliasClause == null || aliasClause.isTeradataNamedAlais()) {
043            return super.toString();
044        }
045        
046        // Get required tokens for processing
047        final TSourceToken startToken = getStartToken();
048        if (startToken == null) return null;
049        
050        final TSourceTokenList tokenList = startToken.container;
051        if (tokenList == null) return null;
052        
053        // Determine the end token position in one go
054        final TSourceToken asToken = aliasClause.getAsToken();
055        final TSourceToken aliasStartToken = aliasClause.getStartToken();
056        
057        final TSourceToken endToken = (asToken != null) ?
058                tokenList.nextsolidtoken(asToken, -1, false) :
059                tokenList.nextsolidtoken(aliasStartToken, -1, false);
060                
061        if (endToken == null) return null;
062        
063        // Get position indices directly from tokens
064        final int beginPos = startToken.posinlist;
065        final int endPos = endToken.posinlist;
066        
067        // Calculate approximate buffer size needed (avoiding resizing)
068        int estimatedSize = 0;
069        for (int i = beginPos; i <= endPos && i < tokenList.size(); i++) {
070            TSourceToken token = tokenList.get(i);
071            if (includingComment || 
072                (token.tokencode != TBaseType.cmtslashstar && 
073                 token.tokencode != TBaseType.cmtdoublehyphen)) {
074                estimatedSize += token.toString().length();
075            }
076        }
077        
078        // Create properly sized buffer
079        StringBuilder sb = new StringBuilder(Math.max(16, estimatedSize));
080        
081        // Single pass to build result string
082        for (int i = beginPos; i <= endPos && i < tokenList.size(); i++) {
083            TSourceToken token = tokenList.get(i);
084            if (includingComment || 
085                (token.tokencode != TBaseType.cmtslashstar && 
086                 token.tokencode != TBaseType.cmtdoublehyphen)) {
087                sb.append(token.toString());
088            }
089        }
090        
091        return sb.toString();
092    }
093
094
095
096}