Skip to content

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

1
2
3
4
5
6
7
8
9
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

1
price * quantity + tax

AST Structure:

1
2
3
4
5
TExpression (arithmetic_plus_t)
├── leftOperand: TExpression (arithmetic_times_t)
│   ├── leftOperand: TExpression (price)
│   └── rightOperand: TExpression (quantity)
└── rightOperand: TExpression (tax)

Complex Condition

1
(age > 18 AND status = 'active') OR priority = 1

AST Structure:

1
2
3
4
5
6
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

1
COALESCE(customer_name, (SELECT name FROM defaults WHERE id = 1))

AST Structure:

1
2
3
4
5
6
TExpression (function_t)
└── functionCall: TFunctionCall
    └── args: TParameterList
        ├── expression[0]: TExpression (customer_name)
        └── expression[1]: TExpression (subquery_t)
            └── subQuery: TSelectSqlStatement

Performance Considerations

Expression Caching

1
2
3
4
5
6
// 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