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}