TExpression - Basic Expressions
Overview
The TExpression
class is the foundation of all expression nodes in General SQL Parser. It represents any SQL element that evaluates to a value, from simple literals to complex nested expressions.
Expression Structure
Core TExpression Properties
| TExpression
├── expressionType -> EExpressionType (determines expression kind)
├── leftOperand -> TExpression (for binary operations)
├── rightOperand -> TExpression (for binary operations)
├── operatorToken -> TSourceToken (operator symbol)
├── constantOperand -> TConstant (for literal values)
├── objectOperand -> TObjectName (for column references)
├── functionCall -> TFunctionCall (for function expressions)
└── subQuery -> TSelectSqlStatement (for subquery expressions)
|
Expression Types
Primary Expression Types
Type |
Description |
Example |
Access Method |
simple_object_name_t |
Column reference |
customer_id |
getObjectOperand() |
constant_t |
Literal value |
'John' , 42 |
getConstantOperand() |
function_t |
Function call |
COUNT(*) |
getFunctionCall() |
subquery_t |
Subquery |
(SELECT ...) |
getSubQuery() |
parenthesis_t |
Parenthesized expr |
(age + 1) |
getLeftOperand() |
Binary Operator Types
Type |
Operator |
Example |
Description |
arithmetic_plus_t |
+ |
a + b |
Addition |
arithmetic_minus_t |
- |
a - b |
Subtraction |
arithmetic_times_t |
* |
a * b |
Multiplication |
arithmetic_divide_t |
/ |
a / b |
Division |
comparison_eq_t |
= |
a = b |
Equality |
comparison_ne_t |
<> |
a <> b |
Inequality |
comparison_gt_t |
> |
a > b |
Greater than |
comparison_lt_t |
< |
a < b |
Less than |
logical_and_t |
AND |
a AND b |
Logical AND |
logical_or_t |
OR |
a OR b |
Logical OR |
Common Usage Patterns
Expression Type Detection
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 | public void analyzeExpression(TExpression expr) {
switch (expr.getExpressionType()) {
case simple_object_name_t:
String columnName = expr.getObjectOperand().toString();
System.out.println("Column reference: " + columnName);
break;
case constant_t:
TConstant constant = expr.getConstantOperand();
System.out.println("Constant value: " + constant.toString());
break;
case function_t:
TFunctionCall func = expr.getFunctionCall();
System.out.println("Function call: " + func.getFunctionName());
break;
case arithmetic_plus_t:
System.out.println("Addition operation");
analyzeExpression(expr.getLeftOperand());
analyzeExpression(expr.getRightOperand());
break;
case comparison_eq_t:
System.out.println("Equality comparison");
analyzeExpression(expr.getLeftOperand());
analyzeExpression(expr.getRightOperand());
break;
default:
System.out.println("Other expression type: " + expr.getExpressionType());
}
}
|
Expression Tree Traversal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 | public void traverseExpressionTree(TExpression expr) {
// Pre-order traversal
processExpression(expr);
// Traverse children based on expression type
if (expr.getLeftOperand() != null) {
traverseExpressionTree(expr.getLeftOperand());
}
if (expr.getRightOperand() != null) {
traverseExpressionTree(expr.getRightOperand());
}
// Handle function parameters
if (expr.getFunctionCall() != null) {
TParameterList params = expr.getFunctionCall().getArgs();
if (params != null) {
for (int i = 0; i < params.size(); i++) {
traverseExpressionTree(params.getExpression(i));
}
}
}
// Handle subquery
if (expr.getSubQuery() != null) {
analyzeSubquery(expr.getSubQuery());
}
}
|
Built-in Expression Traversal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 | // TExpression provides built-in traversal methods
public void useBuiltInTraversal(TExpression expr) {
// Post-order traversal
expr.postOrderTraverse(new IExpressionVisitor() {
public boolean exprVisit(TParseTreeNode node, boolean isLeafNode) {
if (node instanceof TExpression) {
TExpression e = (TExpression) node;
System.out.println("Visiting: " + e.getExpressionType());
}
return true; // Continue traversal
}
});
// Pre-order traversal
expr.preOrderTraverse(new IExpressionVisitor() {
public boolean exprVisit(TParseTreeNode node, boolean isLeafNode) {
// Process node before children
return true;
}
});
// In-order traversal
expr.inOrderTraverse(new IExpressionVisitor() {
public boolean exprVisit(TParseTreeNode node, boolean isLeafNode) {
// Process node between left and right children
return true;
}
});
}
|
Expression Analysis Examples
Finding All Column References
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | public Set<String> findColumnReferences(TExpression expr) {
Set<String> columns = new HashSet<>();
expr.postOrderTraverse(new IExpressionVisitor() {
public boolean exprVisit(TParseTreeNode node, boolean isLeafNode) {
if (node instanceof TExpression) {
TExpression e = (TExpression) node;
if (e.getExpressionType() == EExpressionType.simple_object_name_t) {
TObjectName objName = e.getObjectOperand();
columns.add(objName.toString());
}
}
return true;
}
});
return columns;
}
|
Expression Complexity Calculation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 | public int calculateComplexity(TExpression expr) {
final int[] complexity = {0};
expr.postOrderTraverse(new IExpressionVisitor() {
public boolean exprVisit(TParseTreeNode node, boolean isLeafNode) {
if (node instanceof TExpression) {
TExpression e = (TExpression) node;
switch (e.getExpressionType()) {
case function_t:
complexity[0] += 3; // Functions are complex
break;
case subquery_t:
complexity[0] += 5; // Subqueries are very complex
break;
case arithmetic_plus_t:
case arithmetic_minus_t:
case arithmetic_times_t:
case arithmetic_divide_t:
complexity[0] += 1; // Arithmetic is simple
break;
case comparison_eq_t:
case comparison_ne_t:
complexity[0] += 1; // Comparisons are simple
break;
default:
complexity[0] += 1;
}
}
return true;
}
});
return complexity[0];
}
|
Expression Type Counting
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | public Map<EExpressionType, Integer> countExpressionTypes(TExpression expr) {
Map<EExpressionType, Integer> counts = new HashMap<>();
expr.postOrderTraverse(new IExpressionVisitor() {
public boolean exprVisit(TParseTreeNode node, boolean isLeafNode) {
if (node instanceof TExpression) {
TExpression e = (TExpression) node;
EExpressionType type = e.getExpressionType();
counts.put(type, counts.getOrDefault(type, 0) + 1);
}
return true;
}
});
return counts;
}
|
SQL to AST Examples
Arithmetic Expression
AST Structure:
| TExpression (arithmetic_plus_t)
├── leftOperand: TExpression (arithmetic_times_t)
│ ├── leftOperand: TExpression (price)
│ └── rightOperand: TExpression (quantity)
└── rightOperand: TExpression (tax)
|
Complex Condition
| (age > 18 AND status = 'active') OR priority = 1
|
AST Structure:
| TExpression (logical_or_t)
├── leftOperand: TExpression (parenthesis_t)
│ └── leftOperand: TExpression (logical_and_t)
│ ├── leftOperand: TExpression (age > 18)
│ └── rightOperand: TExpression (status = 'active')
└── rightOperand: TExpression (priority = 1)
|
Function with Subquery
| COALESCE(customer_name, (SELECT name FROM defaults WHERE id = 1))
|
AST Structure:
| TExpression (function_t)
└── functionCall: TFunctionCall
└── args: TParameterList
├── expression[0]: TExpression (customer_name)
└── expression[1]: TExpression (subquery_t)
└── subQuery: TSelectSqlStatement
|
Expression Caching
| // Cache frequently accessed expression properties
private Map<TExpression, String> expressionStringCache = new HashMap<>();
public String getExpressionString(TExpression expr) {
return expressionStringCache.computeIfAbsent(expr, TExpression::toString);
}
|
Lazy Evaluation
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | // Only traverse parts of expression tree you need
public boolean hasSubqueries(TExpression expr) {
// Quick check without full traversal
if (expr.getExpressionType() == EExpressionType.subquery_t) {
return true;
}
// Only check children if necessary
if (expr.getLeftOperand() != null && hasSubqueries(expr.getLeftOperand())) {
return true;
}
return expr.getRightOperand() != null && hasSubqueries(expr.getRightOperand());
}
|
See Also