public abstract class TParseTreeNode extends Object implements Visitable, Iterator<TSourceToken>
TSourceToken objects. Each node:
startToken and endToken that define its boundariesnodesStartFromThisToken
and nodesEndWithThisToken)
SQL: "SELECT * FROM table WHERE id = 1"
- SelectStatement node: [SELECT...1]
- SelectList node: [*]
- FromClause node: [FROM table]
- WhereClause node: [WHERE id = 1]
- Expression node: [id = 1]
- LeftOperand: [id]
- Operator: [=]
- RightOperand: [1]
nsDetached: Node's tokens were partially modifiednsPartitial: Node contains modified sub-nodesnsRemoved: Node's tokens were completely removed
// Original: WHERE id = 1
// Modify the right operand from "1" to "100"
rightOperandNode.setString("100");
Result:
- RightOperand node: replaced with new token "100"
- Expression node: status = nsPartitial (contains modified child)
- WhereClause node: status = nsPartitial (contains modified descendant)
Scenario 2: Modifying a Parent Node
// Original: WHERE id = 1
// Replace entire WHERE clause
whereClauseNode.setString("WHERE status = 'active'");
Result:
- All child nodes (Expression, operands): status = nsDetached
- WhereClause node: completely replaced with new tokens
- SelectStatement: updated to reference new WHERE tokens
Scenario 3: Removing a Node
// Remove WHERE clause entirely whereClauseNode.removeTokens(); Result: - WhereClause and all children: status = nsRemoved - Tokens removed from chain - Parent SelectStatement: adjusted boundaries
if (node.getNodeStatus() == ENodeStatus.nsNormal) {
// Safe to modify
node.setString(newText);
}
// GOOD: Modify specific value
tableNameNode.setString("new_table");
// AVOID: Replacing entire FROM clause when only table name needs change
fromClause.setString("FROM new_table");
// After multiple modifications, use script generator
if (statement.isChanged()) {
String result = statement.toScript();
}
// Modifying a node affects all overlapping nodes
expression.setString("new_condition");
// Parent WHERE clause is now marked as modified
assert whereClause.getNodeStatus() == ENodeStatus.nsPartitial;
setString(String) method:
TSingletonParser to create new tokensupdateNodeWithTheSameStartToken(): Updates nodes starting at modified positionupdateMeNodeWithTheSameEndToken(): Updates nodes ending at modified positionupdateStatusOfNodeShareSameTokens(): Propagates status changestoString())doubleLinkedTokenListToString is true:
refreshAllNodesTokenCount())nsNormal: Unmodified node with original tokensnsFlattened: Node created from user text (no original tokens)nsPartitial: Contains modified child nodes but own tokens unchangednsDetached: Tokens modified by parent/sibling operationnsRemoved: Tokens removed from chain, node is defunct
// Instead of token->lexer reference, use a TokenContext:
class TokenContext {
EDbVendor vendor;
SourceBuffer sourceBuffer;
int sourceId; // Identifies original vs modified source
}
class SourceBuffer {
List<TextSegment> segments;
class TextSegment {
String text;
SourceType type; // ORIGINAL, USER_MODIFIED, GENERATED
int startOffset;
int endOffset;
}
String getText(int segmentId, int start, int end);
int addSegment(String text, SourceType type);
}
class TSourceToken {
int sourceBufferId;
int segmentId;
int startOffset;
int endOffset;
SourceType sourceType;
String getText() {
return SourceBufferManager.getBuffer(sourceBufferId)
.getText(segmentId, startOffset, endOffset);
}
}
class NodeModification {
ModificationType type; // REPLACE, INSERT, DELETE
String newText;
boolean preserveFormatting;
boolean retokenize;
}
public void modifyNode(NodeModification mod) {
// Single entry point for all modifications
}
setString(String)toString()setText(TSourceToken, TSourceToken)TParseTreeNode node = ...; String originalText = node.toString(); // Get text from token chain
node.setString("new SQL text"); // Replace node's text
String modifiedText = node.toString(); // Get modified text
if (node.isChanged()) {
String newText = node.toScript(); // Use script generator for complex mods
}
TSourceToken,
TSingletonParser,
TScriptGenerator| Modifier and Type | Field and Description |
|---|---|
EDbVendor |
dbvendor
SQL dialect of this statement.
|
static boolean |
doubleLinkedTokenListToString |
static int |
nodeActionAppend |
static int |
nodeActionInsert |
static int |
nodeActionRemove |
static int |
nodeActionUnknown |
static int |
nodeActionUpdate |
static int |
nodeActionUpdateText |
static int |
nodeChangeEndToken |
static int |
nodeChangeStartToken |
| Constructor and Description |
|---|
TParseTreeNode() |
| Modifier and Type | Method and Description |
|---|---|
void |
accept(TParseTreeVisitor v)
Accept a visitor
|
void |
acceptChildren(TParseTreeVisitor v)
Accept a visitor to iterate this class and sub-nodes of this class
|
int |
addAllMyTokensToTokenList(TSourceTokenList targetList,
int index)
Deprecated.
since v1.8.8.0, use scriptWriter technology to modify the node
Inserts tokens(from start token to end token ) of this parse tree node at the specified position in this
list. Shifts the element currently at that position (if any) and
any subsequent elements to the right .
|
void |
addToTokenChain(TSourceToken anchorToken,
boolean beforeAnchorToken) |
void |
appendNewNode(TParseTreeNode newNode,
boolean needCommaBefore) |
void |
calculateTokenCount() |
protected void |
doAppendNewNode(TParseTreeNode newNode,
TParseTreeNode anchorNode,
boolean needCommaBefore) |
void |
doParse(TCustomSqlStatement psql,
ESqlClause plocation)
Analyze the sub-nodes inside this node.
|
void |
fastSetString(String sqlSegment) |
TParseTreeNode |
getAnchorNode() |
long |
getColumnNo()
Column position of the first token of this node
|
String |
getCommentAfterNode() |
String |
getCommentBeforeNode()
return null if no comment is found before this node.
|
String |
getCompactString()
representation of this node by removing all spaces, return and comments
|
int |
getDummyTag()
A temporary value can be used for any purposes
|
TSourceToken |
getEndToken()
The last token of the node
|
Class<?> |
getEvaluateDatatype()
Support String, Integer, Double and Boolean type
|
Object |
getEvalValue() |
TGSqlParser |
getGsqlparser()
The parser that generate this node.
|
long |
getLineNo()
Line number of the first token of this node
|
ESqlClause |
getLocation()
SQL clause that include this objectName such as select list, from clause, set clause
|
String |
getMd5()
md5 hash code of the string representation of this node.
|
ENodeStatus |
getNodeStatus() |
int |
getNodeType()
A unique value to distinguish this node from others
|
TParseTreeNode |
getParentObjectName() |
String |
getPlainText() |
TSourceToken |
getStartToken()
The first token in this parse tree node
|
int |
getTokenCount() |
boolean |
hasNext() |
void |
init(Object arg1)
Initialize a query tree node.
|
void |
init(Object arg1,
Object arg2) |
void |
init(Object arg1,
Object arg2,
Object arg3) |
void |
init(Object arg1,
Object arg2,
Object arg3,
Object arg4) |
void |
init(Object arg1,
Object arg2,
Object arg3,
Object arg4,
Object arg5) |
void |
init(Object arg1,
Object arg2,
Object arg3,
Object arg4,
Object arg5,
Object arg6) |
void |
init(Object arg1,
Object arg2,
Object arg3,
Object arg4,
Object arg5,
Object arg6,
Object arg7) |
void |
init(Object arg1,
Object arg2,
Object arg3,
Object arg4,
Object arg5,
Object arg6,
Object arg7,
Object arg8) |
void |
init(Object arg1,
Object arg2,
Object arg3,
Object arg4,
Object arg5,
Object arg6,
Object arg7,
Object arg8,
Object arg9) |
void |
init(Object arg1,
Object arg2,
Object arg3,
Object arg4,
Object arg5,
Object arg6,
Object arg7,
Object arg8,
Object arg9,
Object arg10) |
void |
insertAfterAToken(TSourceToken anchorToken) |
void |
insertNewNodeBeforeMe(TParseTreeNode newNode,
boolean needCommaBefore) |
boolean |
isChanged()
Detect wether this node is modified by checking all tokens included in this node.
|
boolean |
isTokensInChain() |
TSourceToken |
next() |
void |
refreshAllNodesTokenCount() |
void |
remove() |
protected int |
removeAllMyTokensFromTokenList(TSourceToken additionalToken)
Deprecated.
since v1.8.8.0, use scriptWriter technology to modify the node
|
void |
removeTokens() |
static void |
removeTokensBetweenNodes(TParseTreeNode startNode,
TParseTreeNode endNode) |
static void |
removeTokensBetweenToken(TSourceToken startToken,
TSourceToken endToken)
both begin and end token will be removed from the chain
|
void |
replaceWithNewNode(TParseTreeNode newNode) |
void |
resetIterator() |
void |
setAnchorNode(TParseTreeNode anchorNode) |
void |
setChanged() |
void |
setDummyTag(int dummyTag) |
void |
setEndToken(ArrayList endNode) |
void |
setEndToken(TFromTableList endNode) |
void |
setEndToken(TParseTreeNode endNode) |
void |
setEndToken(TSourceToken newEndToken) |
void |
setEndToken(TSourceTokenList endTokenList) |
void |
setEndTokenDirectly(TSourceToken newEndToken) |
void |
setEvaluateDatatype(Class<?> evaluateDatatype) |
void |
setEvalValue(Object evalValue) |
void |
setGsqlparser(TGSqlParser gsqlparser) |
void |
setIncludingComment(boolean includingComment) |
void |
setLocation(ESqlClause location) |
void |
setNewSubNode(TParseTreeNode oldSubNode,
TParseTreeNode newSubNode,
TParseTreeNode anchorNode) |
void |
setNodeStatus(ENodeStatus nodeStatus) |
void |
setNodeType(int nodeType)
Set the node type for this node.
|
void |
setParent(TParseTreeNode parent) |
void |
setPlainText(String plainText) |
void |
setStartToken(ArrayList startNode) |
void |
setStartToken(TParseTreeNode startNode) |
void |
setStartToken(TSourceToken newStartToken) |
void |
setStartToken(TSourceTokenList startTokenList) |
void |
setStartTokenDirectly(TSourceToken newStartToken) |
void |
setString(String sqlSegment)
Set the text of the node and update the corresponding source tokens synchronously.
|
void |
setString2(String sqlSegment)
Deprecated.
since v1.8.8.0, use scriptWriter technology to modify the node
Set the new string text of a node will destroy all the sub-node structure
|
static boolean |
subNodeInNode(TParseTreeNode subNode,
TParseTreeNode wholeNode) |
String |
toScript()
Return the text string of this node, the return value is the same as
toString() if this node is not modified manually
after created by parser. |
String |
toString()
将一个语法树节点(
TParseTreeNode)转换回它对应的原始SQL字符串。
它通过遍历一个由 startToken(起始词法单元)和 endToken(结束词法单元)界定的双向链表来实现这一功能。 |
String |
toString2()
String representation of this parse tree node.
|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, waitforEachRemainingpublic static boolean doubleLinkedTokenListToString
public static final int nodeActionUnknown
public static final int nodeActionRemove
public static final int nodeActionInsert
public static final int nodeActionUpdate
public static final int nodeActionUpdateText
public static final int nodeActionAppend
public static final int nodeChangeStartToken
public static final int nodeChangeEndToken
public TParseTreeNode()
public void setEvaluateDatatype(Class<?> evaluateDatatype)
public Class<?> getEvaluateDatatype()
public void setEvalValue(Object evalValue)
public Object getEvalValue()
public void setPlainText(String plainText)
public String getPlainText()
public void setLocation(ESqlClause location)
public ESqlClause getLocation()
public String getCompactString()
public String getMd5()
public TParseTreeNode getParentObjectName()
public void setParent(TParseTreeNode parent)
public void insertAfterAToken(TSourceToken anchorToken)
public void insertNewNodeBeforeMe(TParseTreeNode newNode, boolean needCommaBefore)
public void appendNewNode(TParseTreeNode newNode, boolean needCommaBefore)
public void replaceWithNewNode(TParseTreeNode newNode)
public void resetIterator()
public boolean hasNext()
hasNext in interface Iterator<TSourceToken>public TSourceToken next()
next in interface Iterator<TSourceToken>public void remove()
remove in interface Iterator<TSourceToken>public void setNodeStatus(ENodeStatus nodeStatus)
public ENodeStatus getNodeStatus()
public void addToTokenChain(TSourceToken anchorToken, boolean beforeAnchorToken)
public int getTokenCount()
public void refreshAllNodesTokenCount()
public void calculateTokenCount()
public static void removeTokensBetweenToken(TSourceToken startToken, TSourceToken endToken)
startToken - endToken - public static void removeTokensBetweenNodes(TParseTreeNode startNode, TParseTreeNode endNode)
public void removeTokens()
public TGSqlParser getGsqlparser()
public void setIncludingComment(boolean includingComment)
public void setGsqlparser(TGSqlParser gsqlparser)
public void setDummyTag(int dummyTag)
public int getDummyTag()
public TSourceToken getStartToken()
public TSourceToken getEndToken()
public long getColumnNo()
public long getLineNo()
public void setNodeType(int nodeType)
nodeType - The node type.public int getNodeType()
ENodeTypepublic void init(Object arg1)
arg1 - first argumentpublic void init(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7)
public void init(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8)
public void init(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9)
public void init(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10)
public void doParse(TCustomSqlStatement psql, ESqlClause plocation)
psql - SQL statement this node belongs toplocation - SQL clause this node belongs topublic void setStartToken(ArrayList startNode)
public void setEndToken(ArrayList endNode)
public void setStartToken(TSourceToken newStartToken)
public void setStartToken(TSourceTokenList startTokenList)
public void setStartToken(TParseTreeNode startNode)
public void setStartTokenDirectly(TSourceToken newStartToken)
public void setEndTokenDirectly(TSourceToken newEndToken)
public void setEndToken(TSourceToken newEndToken)
public void setEndToken(TSourceTokenList endTokenList)
public void setEndToken(TFromTableList endNode)
public void setEndToken(TParseTreeNode endNode)
public void setString2(String sqlSegment)
sqlSegment - that override original text of this node.public void setString(String sqlSegment)
sqlSegment - public void fastSetString(String sqlSegment)
public String getCommentBeforeNode()
public String getCommentAfterNode()
public String toString2()
This string was generated by collecting text from the start token of this node to the end token of this node.
If this node was modified, then use toScript() to get string representation of this node.
public String toString()
将一个语法树节点(TParseTreeNode)转换回它对应的原始SQL字符串。
它通过遍历一个由 startToken(起始词法单元)和 endToken(结束词法单元)界定的双向链表来实现这一功能。
这个方法的设计采用了“两遍扫描”(Two-Pass)的策略,也就是使用了两个 while 循环。
第一个循环是预处理阶段,用于清理格式;第二个循环则负责构建最终的字符串。
while 循环这个循环的主要目标是识别并“软删除”多余的换行符(newline tokens)。这种情况尤其在SQL被程序动态修改后容易出现。 这个循环本身不构建字符串,只负责分析和更新词法单元的状态。 其工作原理是:
startToken 开始,通过 getNextTokenInChain() 方法遍历到 endToken。posinlist(词法单元在原始完整列表中的位置索引)来判断链表是否“自然”。
如果不连续,意味着词法单元被插入或重排了,此时 isChainModified 标志位会被设为 true。while 循环这个循环负责从(经过第一步清理后的)词法单元流中实际地构建最终的输出字符串。 其工作原理是:
StringBuffer 之前,它会进行检查。StringBuffer 中。StringBuffer 就包含了该语法树节点的最终、重构后的SQL文本。
public boolean isTokensInChain()
public int addAllMyTokensToTokenList(TSourceTokenList targetList, int index)
targetList - the new list of source tokensindex - the position insert the targetListprotected int removeAllMyTokensFromTokenList(TSourceToken additionalToken)
additionalToken - usually was comma before or after this parse tree node that also need to be deletedpublic void accept(TParseTreeVisitor v)
accept in interface Visitablev - visitor is a descendant class of TParseTreeVisitorpublic void acceptChildren(TParseTreeVisitor v)
acceptChildren in interface Visitablev - visitor is a descendant class of TParseTreeVisitorpublic String toScript()
toString() if this node is not modified manually
after created by parser.
toString() method.public void setChanged()
public boolean isChanged()
protected void doAppendNewNode(TParseTreeNode newNode, TParseTreeNode anchorNode, boolean needCommaBefore)
public void setAnchorNode(TParseTreeNode anchorNode)
public TParseTreeNode getAnchorNode()
public void setNewSubNode(TParseTreeNode oldSubNode, TParseTreeNode newSubNode, TParseTreeNode anchorNode)
public static boolean subNodeInNode(TParseTreeNode subNode, TParseTreeNode wholeNode)