Derive Macros (Iden & Enum Def)
Relevant source files
The following files were used as context for generating this wiki page:
Introduction
The SeaQuery project utilizes procedural macros to automate the implementation of the Iden trait and the generation of identifier enums. These macros, primarily Iden and #[enum_def], reduce boilerplate by allowing developers to define database identifiers (tables and columns) using standard Rust structures and enums. The implementation is housed within the sea-query-derive crate, which is a specialized procedural macro crate integrated into the main sea-query workspace.
These macros bridge the gap between Rust types and SQL strings, handling transformations like case conversion (e.g., PascalCase to snake_case) and supporting custom overrides via attributes. The Iden trait is fundamental to SeaQuery, acting as the standard interface for any identifier used within a dynamic query statement.
Sources: sea-query-derive/Cargo.toml:1-15, src/lib.rs:770-780, README.md:230-245
The Iden Derive Macro
The Iden derive macro is the primary tool for implementing the Iden trait on enums and unit structs. When applied, it generates code that enables the type to be converted into its string representation for SQL generation.
Supported Structures
The macro specifically supports two types of Rust data structures:
- Enums: Each variant represents an identifier (typically a table or column). A special
Tablevariant is often used to represent the table name itself. - Unit Structs: Useful for representing single identifiers, such as a table name without associated columns in that specific type.
Sources: sea-query-derive/src/iden/mod.rs:31-45, tests/derive.rs:60-70
Logic and Case Transformation
By default, the macro converts the Rust identifier name into snake_case. For example, a variant FontId becomes "font_id". This behavior can be overridden using the #[iden = "custom_name"] attribute on either the container or specific variants.
The diagram above illustrates the decision logic within the Iden derive expansion.
Sources: sea-query-derive/src/iden/mod.rs:142-155, README.md:246-258
The enum_def Attribute Macro
The #[enum_def] macro is an attribute procedural macro applied to structs. Its purpose is to automatically generate a corresponding Iden enum based on the fields of the struct, including a Table variant.
Component Generation
When used on a struct, it generates:
- A new enum (default naming convention:
[StructName]Iden). - The
Tablevariant within that enum. - Variants for each field in the struct, converted to PascalCase.
- Implementations for
Iden,IdenStatic, andAsRef<str>for the generated enum.
Sources: sea-query-derive/src/enum_def.rs:55-102, README.md:265-280
Configuration Options
The macro accepts several arguments to customize the output:
| Argument | Type | Description | Default |
|---|---|---|---|
prefix | String | Prefix for the generated enum name | "" (Empty) |
suffix | String | Suffix for the generated enum name | "Iden" |
crate_name | String | The path to the sea-query crate | "sea_query" |
table_name | String | Overrides the table name string | Struct name in snake_case |
Sources: sea-query-derive/src/iden/mod.rs:118-135, sea-query-derive/src/enum_def.rs:11-30
Implementation Architecture
The derive macros rely on several internal modules to handle the complexities of parsing and code generation.
Module Breakdown
- iden/mod.rs: Contains the entry point for
derive(Iden)and handles the high-level expansion for both enums and unit structs. - enum_def.rs: Manages the transformation of a struct definition into a new Iden-compatible enum.
- iden/iden_static.rs: Specifically handles the
IdenStaticimplementation, which provides'static straccess to identifiers. - iden/attr.rs: Utility for parsing macro attributes like
#[iden]and#[method].
Sources: sea-query-derive/src/lib.rs:8-35, sea-query-derive/src/iden/mod.rs:1-8
Sequence of Expansion
The following diagram shows the process when the compiler encounters an Iden derive.
Technical Constraints and Features
- Safety: The entire workspace, including derive macros, forbids unsafe code (
#![forbid(unsafe_code)]). - Crate Integration: The macros detect if they are being used within
sea-ormand adjust the import paths accordingly (e.g., usingsea_orm::sea_queryinstead ofsea_query). - Static Identifiers: The system checks if an identifier is "static" (composed of alphanumeric characters and underscores, not starting with a number) to optimize the
quotedandunquotedimplementations.
Sources: sea-query-derive/src/lib.rs:1, sea-query-derive/src/iden/mod.rs:107-115, sea-query-derive/src/iden/mod.rs:157-163
Summary
Derive macros in SeaQuery provide a robust mechanism for mapping Rust types to SQL identifiers. By leveraging derive(Iden) and #[enum_def], developers ensure compile-time consistency between their data models and query builders while benefiting from automatic case conversion and flexible attribute-based overrides. This system is a core component of the project's ergonomic API, facilitating the construction of dynamic queries with minimal manual string handling.