sqlx-template 0.2.1

Template query library for Rust SQLx
Documentation
use sqlx_template::{SqliteTemplate, sqlite_query};
use sqlx::{FromRow, SqlitePool};

#[derive(SqliteTemplate, FromRow, Debug, Clone)]
#[table("users")]
#[tp_select_builder(
    with_email_domain = "email LIKE :domain$String",
    with_score_range = "score BETWEEN :min$i32 AND :max$i32"
)]
pub struct User {
    #[auto]
    pub id: i32,
    pub email: String,
    pub score: i32,
    pub active: bool,
    pub created_at: String,
    pub name: String,
}

// Create table using query macro
#[sqlite_query(
    r#"
    CREATE TABLE users (
        id INTEGER PRIMARY KEY,
        email TEXT NOT NULL,
        score INTEGER NOT NULL,
        active BOOLEAN NOT NULL,
        created_at TEXT NOT NULL,
        name TEXT NOT NULL
    )
    "#
)]
async fn create_users_table() {}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("Testing all builders with custom conditions");
    
    // Create in-memory SQLite database
    let pool = SqlitePool::connect(":memory:").await?;
    
    // Create table using generated function
    create_users_table(&pool).await?;

    // Insert test data using generated insert method
    let alice = User {
        id: 0, // Will be auto-generated
        email: "alice@company.com".to_string(),
        score: 85,
        active: true,
        created_at: "2023-01-01".to_string(),
        name: "Alice".to_string(),
    };
    User::insert(&alice, &pool).await?;

    let bob = User {
        id: 0, // Will be auto-generated
        email: "bob@personal.com".to_string(),
        score: 65,
        active: false,
        created_at: "2022-01-01".to_string(),
        name: "Bob".to_string(),
    };
    User::insert(&bob, &pool).await?;
    
    // Test SELECT builder with custom conditions
    println!("\n=== SELECT Builder Tests ===");
    
    println!("SQL: {}", User::builder_select().build_sql());
    
    let users = User::builder_select()
        .with_email_domain("%@company.com")?
        .find_all(&pool)
        .await?;
    println!("Users with company email: {} found", users.len());
    
    let users = User::builder_select()
        .with_score_range(60, 90)?
        .find_all(&pool)
        .await?;
    println!("Users with score 60-90: {} found", users.len());
    
    // Note: UPDATE and DELETE builders are generated by UpdateTemplate and DeleteTemplate
    // which are separate derives. SqliteTemplate only generates SELECT builder.
    
    // Test column list in SELECT (should not be SELECT *)
    let sql = User::builder_select().active(&true).unwrap().build_sql();
    println!("\nGenerated SQL: {}", sql);
    assert!(sql.contains("SELECT id, email, score, active, created_at, name FROM"));
    assert!(!sql.contains("SELECT * FROM"));
    println!("✅ SELECT uses column list instead of *");
    
    Ok(())
}