Strongly-Typed Columns
Relevant source files
The following files were used as context for generating this wiki page:
Strongly-Typed Columns are a feature introduced in SeaORM 2.0 designed to provide compile-time type safety for database queries. By using a generated COLUMN constant with typed fields instead of the traditional untyped Column enum, developers can catch type mismatches during the build process rather than at runtime.
This system works by wrapping standard column identifiers in type-specific wrappers (e.g., StringColumn, IntegerColumn), allowing the Rust compiler to validate expressions like filters and updates against the actual data types defined in the entity model.
Sources: CLAUDE.md:10-12, CLAUDE.md:121-125
Architecture and Implementation
The strongly-typed column system relies on a combination of procedural macros and specialized data structures. When an entity is defined using the #[sea_orm::model] or #[derive(DeriveEntityModel)] macros, the system generates a TypedColumn struct and a corresponding const COLUMN instance.
The TypedColumn Generation Process
The generation logic resides in the macro expansion phase, specifically within expand_typed_column. This function iterates through the fields of a model struct, identifies their Rust types, and maps them to SeaORM-specific column wrappers.
The diagram shows how the procedural macro transforms a standard Rust struct into the strongly-typed metadata used by the ORM.
Sources: sea-orm-macros/src/derives/typed_column.rs:11-30
Type Mapping and Wrappers
The system determines which type wrapper to use based on the field's type string and optional attributes. If a field is an Option<T>, the macro extracts the inner type T to determine the appropriate SQL column definition.
| Component | Description |
|---|---|
TypedColumn | A generated struct containing fields that mirror the Model's fields, but with type-safe wrappers. |
const COLUMN | A static instance of TypedColumn used in query building. |
ColumnDef | The underlying definition containing SQL type, nullability, and constraints. |
ColumnTrait | Trait implemented by column identifiers to provide SQL definitions and type names. |
Sources: sea-orm-macros/src/derives/typed_column.rs:100-115, src/entity/column_def.rs:7-20, sea-orm-macros/src/derives/entity_model.rs:520-530
Comparison: 1.0 vs 2.0 Patterns
In SeaORM 1.0, columns were typically referenced via an enum, which lacked specific type information for the data held in that column. SeaORM 2.0 prefers the COLUMN constant.
Example Usage
// 1.0 (Untyped Enum)
user::Entity::find().filter(user::Column::Name.contains("Bob"))
// 2.0 (Strongly-Typed Constant)
user::Entity::find().filter(user::COLUMN.name.contains("Bob"))
Sources: CLAUDE.md:121-125
Column Definitions and Metadata
Strongly-typed columns are built upon the ColumnDef structure, which stores the technical metadata for the database schema. While the type-safe wrappers provide the interface for the developer, ColumnDef handles the actual SQL generation.
Metadata Properties
The following properties are associated with a column definition and are often configured via macro attributes like #[sea_orm(unique, indexed, nullable)]:
- SQL Type: Derived from the Rust type (e.g.,
i32maps toInteger). - Nullability: Set automatically if the type is
Option<T>. - Indexing/Uniqueness: Explicitly marked via attributes.
- Defaults: Can be provided as static values or SQL expressions (e.g.,
Expr::current_timestamp()).
Sources: src/entity/column_def.rs:35-100, sea-orm-macros/src/derives/entity_model.rs:550-575
Attribute Parsing Logic
The macro parser recognizes several specific attributes during the generation of typed columns:
column_type: Overrides the automatically inferred SQL type.enum_name: Specifies a different name for the column variant.ignore: Prevents the field from being included in the generated typed column.
Sources: sea-orm-macros/src/derives/typed_column.rs:43-75
Integration with Query Building
Typed columns integrate directly into the query builder. Methods such as .filter(), .col_expr(), and .order_by() accept these typed identifiers.
The sequence shows how the typed column validates the operation (like .contains()) against the allowed type at compile time.
Sources: src/lib.rs:705-715, CLAUDE.md:180-185
Conclusion
Strongly-Typed Columns in SeaORM 2.0 represent a significant shift toward compile-time safety. By generating a TypedColumn struct that mirrors the entity model, SeaORM allows the Rust compiler to enforce type correctness in query filters and expressions, reducing common runtime errors associated with database interactions.
Sources: CLAUDE.md:121-125, src/lib.rs:180-190