Expressions (Expr)
Relevant source files
The following files were used as context for generating this wiki page:
Expressions (Expr) serve as the fundamental building blocks for constructing dynamic SQL queries in SeaQuery. They represent the abstract syntax tree (AST) nodes used to build components of SELECT, JOIN, WHERE, and HAVING clauses. By providing an ergonomic API, SeaQuery allows developers to represent SQL logic such as column references, function calls, binary operations, and subqueries as structured Rust code.
The Expr system is designed to handle parameter binding automatically, preventing common "off-by-one" errors in positional parameters (like $N in Postgres). It also respects operator precedence during SQL serialization, ensuring that the generated SQL contains only the necessary parentheses for clarity and correctness.
Sources: src/lib.rs:24-30, README.md:24-30, src/lib.rs:88-100
Core Expression Components
Expressions are implemented as a set of constructors and traits that define how data is manipulated within a query statement.
Expression Types
The expression system handles various SQL constructs through different variants:
| Component Type | Description | Relevant Source |
|---|---|---|
| Column | References to table columns, optionally qualified by table names. | src/backend/query_builder.rs:408-410 |
| Value | Constant data or parameters injected into the query. | src/backend/query_builder.rs:434-436 |
| Binary | Operations involving two expressions (e.g., +, -, AND, OR, LIKE). | src/backend/query_builder.rs:424-431 |
| Unary | Operations involving a single expression (e.g., NOT). | src/backend/query_builder.rs:414-423 |
| FunctionCall | Invocations of built-in or custom SQL functions. | src/backend/query_builder.rs:420-423 |
| SubQuery | Nested SQL statements used within an expression. | src/backend/query_builder.rs:432-436 |
| Custom | Raw SQL strings with support for sequential parameter rewriting. | src/lib.rs:118-125 |
Operator Precedence and Associativity
SeaQuery uses internal logic to determine when parentheses are required around expressions based on their operators. This prevents cluttered SQL while maintaining logical integrity.
This logic is primarily governed by the PrecedenceDecider and OperLeftAssocDecider traits.
Sources: src/backend/query_builder.rs:905-950, src/backend/query_builder.rs:952-957
Expression Construction API
Developers typically use the Expr static methods to initiate expression building.
Column and Value Binding
Expressions can be initiated by referencing columns or providing values. Parameter binding is handled dynamically by the query builder.
// Column addition and multiplication
Expr::col("size_w").add(1).mul(2)
// Value comparison
Expr::col("id").eq(1)
// In-subquery expression
Expr::col("char_code").is_in([3, 4, 5])
Sources: src/lib.rs:90-95, README.md:90-95
Custom Expressions
For complex SQL that falls outside the standard AST, Expr::cust_with_values allows providing raw SQL strings. SeaQuery automatically rewrites local parameter sequences (e.g., $1, $2) to match the global sequence of the entire query.
Sources: src/lib.rs:118-125, src/backend/query_builder.rs:456-487
Expressions in Query Statements
Expressions are integrated into various statement builders, including SelectStatement, UpdateStatement, and DeleteStatement.
Integration Flow
The following diagram illustrates how expressions flow from construction to final SQL serialization via a QueryBuilder.
Special Expression Types
Case Statements
Conditional logic within SQL is represented via CaseStatement.
// Architecture of CaseStatement serialization
// (CASE WHEN (condition) THEN result ELSE result END)
Sources: src/backend/query_builder.rs:511-529
Window Functions
Expressions used in window functions support PARTITION BY, ORDER BY, and frame definitions (ROWS or RANGE).
Sources: src/backend/query_builder.rs:815-859
Constraint Expressions
Expressions are also used in schema definitions, specifically for CHECK constraints and GENERATED columns.
Sources: src/backend/table_builder.rs:252-273
Summary
The Expr module is the core of SeaQuery's dynamic query generation. It abstracts SQL syntax into a type-safe Rust AST that automatically manages parameter binding and operator precedence. Through the QueryBuilder trait, these expressions are translated into dialect-specific SQL for MySQL, Postgres, and SQLite, enabling cross-database compatibility with a single source of query logic.
Sources: src/lib.rs:24-35, README.md:24-35