Derive Macro SqlxTemplate

Source
#[derive(SqlxTemplate)]
{
    // Attributes available to this derive:
    #[table]
    #[tp_upsert]
    #[tp_select_all]
    #[tp_select_one]
    #[tp_select_page]
    #[tp_select_stream]
    #[tp_select_count]
    #[tp_update]
    #[tp_delete]
    #[tp_update_builder]
    #[tp_select_builder]
    #[tp_delete_builder]
    #[auto]
    #[debug_slow]
    #[db]
}
Expand description

SqlxTemplate is a comprehensive derive macro that combines all database operation templates into a single macro. This macro generates functions for insert, update, select, delete, and upsert operations based on sqlx. It’s a convenience macro that applies InsertTemplate, UpdateTemplate, SelectTemplate, DeleteTemplate, UpsertTemplate, and TableName all at once.

§Attributes

SqlxTemplate accepts all attributes from the individual template macros:

  • table: Specifies the name of the table in the database (mandatory).
  • debug_slow: Global debug configuration for all generated functions.
  • auto: Applied to fields that should be excluded from insert statements.
  • tp_select_all, tp_select_one, tp_select_page, tp_select_stream, tp_select_count: Select operation configurations.
  • tp_update: Update operation configurations.
  • tp_delete: Delete operation configurations.
  • tp_upsert: Upsert operation configurations.
  • tp_select_builder, tp_update_builder, tp_delete_builder: Builder pattern configurations.
  • db: Specifies the target database type.

§Builder Pattern Support

The macro supports fluent builder patterns for query construction with custom WHERE conditions.

§Builder Attributes

  • tp_select_builder: Builder pattern configuration for SELECT operations
  • tp_update_builder: Builder pattern configuration for UPDATE operations
  • tp_delete_builder: Builder pattern configuration for DELETE operations

§Custom Condition Syntax

Custom conditions are defined using the following syntax:

#[tp_select_builder(
    method_name = "SQL_expression_with_placeholders"
)]

§Parameter Types

  • Auto-mapping: :field_name automatically maps to struct field types
  • Explicit types: :param$Type for custom parameter types
  • Multiple parameters: Single condition can accept multiple parameters

§Examples

#[tp_select_builder(
    with_email_domain = "email LIKE :domain$String",
    with_score_range = "score BETWEEN :min$i32 AND :max$i32",
    with_active_status = "active = :active"  // Auto-mapped to bool
)]

§Generated Methods

For each field, the builder generates:

§Field-based Methods

  • Equality: .field_name(value), .field_name_not(value)
  • Comparison: .field_name_gt(value), .field_name_gte(value), .field_name_lt(value), .field_name_lte(value)
  • String operations: .field_name_like(pattern), .field_name_start_with(prefix), .field_name_end_with(suffix)
  • Ordering: .order_by_field_asc(), .order_by_field_desc()

§Builder-specific Methods

§SELECT Builder
  • Query execution: .find_all(), .find_one(), .count(), .find_page(), .stream()
  • SQL generation: .build_sql()
§UPDATE Builder
  • SET clauses: .on_field_name(value) - specify which fields to update
  • WHERE clauses: .by_field_name(value) - specify which records to update
  • Execution: .execute() - returns number of affected rows
§DELETE Builder
  • WHERE clauses: .field_name(value) - specify which records to delete
  • Execution: .execute() - returns number of deleted rows

§Usage Examples

§SELECT Builder

let users = User::builder_select()
    .email("john@example.com")?           // Field-based condition
    .score_gte(&75)?                      // Generated comparison method
    .with_email_domain("%@company.com")?  // Custom condition
    .with_score_range(60, 90)?            // Custom condition with multiple params
    .order_by_score_desc()?               // Generated ORDER BY method
    .find_all(&pool)
    .await?;

§UPDATE Builder

let affected = User::builder_update()
    .on_email("newemail@example.com")?    // SET email = ?
    .on_active(&true)?                    // SET active = ?
    .by_id(&user_id)?                     // WHERE id = ?
    .with_high_score(80)?                 // Custom WHERE condition
    .execute(&pool)
    .await?;

§DELETE Builder

let deleted = User::builder_delete()
    .active(&false)?                      // WHERE active = false
    .with_old_accounts("2023-01-01")?     // Custom WHERE condition
    .execute(&pool)
    .await?;

§Validation

  • Table alias validation: Prevents use of table aliases (e.g., u.field) in custom conditions
  • Column validation: Ensures referenced columns exist in the struct
  • Type safety: Compile-time parameter type checking
  • SQL injection protection: Uses parameterized queries

§Performance Features

  • Compile-time optimization: SQL templates pre-generated at compile time
  • Minimal runtime overhead: Reduced format! calls and string allocations
  • Efficient parameter binding: Direct parameter binding without intermediate formatting

§Document generated by LLMs

§Generated Functions

This macro generates all functions from the individual templates:

  • Insert operations: insert(), insert_return() (PostgreSQL only)
  • Update operations: Based on tp_update configurations
  • Select operations: Based on tp_select_* configurations, plus default find_all(), count_all(), find_page_all()
  • Delete operations: Based on tp_delete configurations
  • Upsert operations: Based on tp_upsert configurations
  • Table name function: table_name()

§Example

use sqlx_template::SqlxTemplate;
use sqlx::Pool;

#[derive(SqlxTemplate, sqlx::FromRow)]
#[table("users")]
#[db("postgres")]
#[debug_slow = 1000]
#[tp_select_one(by = "id", fn_name = "find_by_id")]
#[tp_select_all(by = "email", order = "id desc")]
#[tp_update(by = "id", op_lock = "version")]
#[tp_delete(by = "id")]
#[tp_upsert(by = "email", update = "password")]
pub struct User {
    #[auto]
    pub id: i32,
    pub email: String,
    pub password: String,
    pub version: i32,
}

let user = User {
    id: 1,
    email: "user@example.com".to_string(),
    password: "password".to_string(),
    version: 1
};

// All operations are now available:
let users = User::builder_select()
    .find_all(&pool)
    .await?;
let affected = User::builder_update()
    .execute(&pool)
    .await?;
let deleted = User::builder_delete()
    .execute(&pool)
    .await?;

§Note

This is the most convenient macro to use when you need comprehensive database operations for a struct. It combines all individual template macros into one.