drizzle 0.1.14

A type-safe SQL query builder for Rust
Documentation
#![cfg(any(feature = "rusqlite", feature = "turso", feature = "libsql"))]
#[cfg(feature = "uuid")]
use crate::common::schema::sqlite::Role;
#[cfg(feature = "uuid")]
use crate::common::schema::sqlite::{Complex, ComplexSchema, InsertComplex, UpdateComplex};
use crate::common::schema::sqlite::{
    InsertSimple, SelectSimple, Simple, SimpleSchema, UpdateSimple,
};
#[cfg(all(feature = "serde", feature = "uuid"))]
use crate::common::schema::sqlite::{UserConfig, UserMetadata};
use drizzle::core::expr::*;
use drizzle::sqlite::prelude::*;

#[cfg(feature = "uuid")]
#[allow(dead_code)]
#[derive(SQLiteFromRow, Debug)]
struct ComplexResult {
    id: uuid::Uuid,
    name: String,
    email: Option<String>,
    age: Option<i32>,
    description: Option<String>,
}

#[drizzle::test]
fn simple_update(db: &mut TestDb<SimpleSchema>) {
    let SimpleSchema { simple } = schema;
    // Insert initial Simple record
    let insert_data = InsertSimple::new("original");
    let insert_result = db.insert(simple).values([insert_data]).execute();
    assert_eq!(insert_result, 1);

    // Update the record
    let stmt = db
        .update(simple)
        .set(UpdateSimple::default().with_name("updated"))
        .r#where(eq(Simple::name, "original"));
    let update_result = stmt.execute();
    assert_eq!(update_result, 1);

    // Verify the update by selecting the record
    let results: Vec<SelectSimple> = db
        .select((simple.id, simple.name))
        .from(simple)
        .r#where(eq(simple.name, "updated"))
        .all();

    assert_eq!(results.len(), 1);
    assert_eq!(results[0].name, "updated");

    // Verify original name is gone
    let old_results: Vec<SelectSimple> = db
        .select((simple.id, simple.name))
        .from(simple)
        .r#where(eq(simple.name, "original"))
        .all();

    assert_eq!(old_results.len(), 0);
}

#[drizzle::test]
fn update_returning_star(db: &mut TestDb<SimpleSchema>) {
    let SimpleSchema { simple } = schema;

    db.insert(simple)
        .values([InsertSimple::new("before_returning").with_id(102)])
        .execute();

    let stmt = db
        .update(simple)
        .set(UpdateSimple::default().with_name("after_returning"))
        .r#where(eq(simple.id, 102))
        .returning(());

    assert_eq!(
        stmt.to_sql().sql(),
        r#"UPDATE "simple" SET "name" = ? WHERE "simple"."id" = ? RETURNING *"#
    );

    let rows: Vec<SelectSimple> = stmt.all();
    assert_eq!(rows.len(), 1);
    assert_eq!(rows[0].id, 102);
    assert_eq!(rows[0].name, "after_returning");
}

#[cfg(feature = "uuid")]
#[drizzle::test]
fn complex_update(db: &mut TestDb<ComplexSchema>) {
    let ComplexSchema { complex } = schema;

    // Insert initial Complex record
    #[cfg(not(feature = "uuid"))]
    let insert_data = InsertComplex::new("user", true, Role::User)
        .with_email("old@example.com".to_string())
        .with_age(25)
        .with_description("Original description".to_string());

    #[cfg(feature = "uuid")]
    let insert_data = InsertComplex::new("user", true, Role::User)
        .with_id(uuid::Uuid::new_v4())
        .with_email("old@example.com".to_string())
        .with_age(25)
        .with_description("Original description".to_string());

    let insert_result = db.insert(complex).values([insert_data]).execute();
    assert_eq!(insert_result, 1);

    // Update multiple fields
    let stmt = db
        .update(complex)
        .set(
            UpdateComplex::default()
                .with_email("new@example.com".to_string())
                .with_age(30)
                .with_description("Updated description".to_string()),
        )
        .r#where(eq(Complex::name, "user"));
    let update_result = stmt.execute();
    assert_eq!(update_result, 1);

    // Verify the update by selecting the record
    let results: Vec<ComplexResult> = db
        .select((
            complex.id,
            complex.name,
            complex.email,
            complex.age,
            complex.description,
        ))
        .from(complex)
        .r#where(eq(complex.name, "user"))
        .all();

    assert_eq!(results.len(), 1);
    assert_eq!(results[0].name, "user");
    assert_eq!(results[0].email, Some("new@example.com".to_string()));
    assert_eq!(results[0].age, Some(30));
    assert_eq!(
        results[0].description,
        Some("Updated description".to_string())
    );
}

#[drizzle::test]
fn update_multiple_rows(db: &mut TestDb<SimpleSchema>) {
    let SimpleSchema { simple } = schema;

    let stmt = db.insert(simple).values([
        InsertSimple::new("test_one"),
        InsertSimple::new("test_two"),
        InsertSimple::new("other"),
    ]);
    stmt.execute();

    let stmt = db
        .update(simple)
        .set(UpdateSimple::default().with_name("updated"))
        .r#where(like(Simple::name, "test%"));
    stmt.execute();

    let results: Vec<SelectSimple> = db
        .select((simple.id, simple.name))
        .from(simple)
        .r#where(eq(simple.name, "updated"))
        .all();
    assert_eq!(results.len(), 2);

    let results: Vec<SelectSimple> = db
        .select((simple.id, simple.name))
        .from(simple)
        .r#where(eq(simple.name, "other"))
        .all();
    assert_eq!(results.len(), 1);
}

#[cfg(feature = "uuid")]
#[drizzle::test]
fn update_with_complex_where(db: &mut TestDb<ComplexSchema>) {
    let ComplexSchema { complex } = schema;

    let stmt = db.insert(complex).values([
        InsertComplex::new("Young", true, Role::User)
            .with_id(uuid::Uuid::new_v4())
            .with_age(16),
        InsertComplex::new("Adult", true, Role::User)
            .with_id(uuid::Uuid::new_v4())
            .with_age(25),
        InsertComplex::new("Senior", true, Role::User)
            .with_id(uuid::Uuid::new_v4())
            .with_age(70),
    ]);
    stmt.execute();

    let stmt = db
        .update(complex)
        .set(UpdateComplex::default().with_name("matched"))
        .r#where(and(gte(complex.age, 18), lte(complex.age, 65)));
    stmt.execute();

    let results: Vec<ComplexResult> = db
        .select((
            complex.id,
            complex.name,
            complex.email,
            complex.age,
            complex.description,
        ))
        .from(complex)
        .r#where(eq(complex.name, "matched"))
        .all();
    assert_eq!(results.len(), 1);
    assert_eq!(results[0].name, "matched");
}

#[drizzle::test]
fn update_with_in_condition(db: &mut TestDb<SimpleSchema>) {
    let SimpleSchema { simple } = schema;

    let stmt = db.insert(simple).values([
        InsertSimple::new("Alice"),
        InsertSimple::new("Bob"),
        InsertSimple::new("Charlie"),
        InsertSimple::new("David"),
    ]);
    stmt.execute();

    let stmt = db
        .update(simple)
        .set(UpdateSimple::default().with_name("Updated"))
        .r#where(in_array(simple.name, ["Alice", "Charlie"]));
    stmt.execute();

    let results: Vec<SelectSimple> = db
        .select((simple.id, simple.name))
        .from(simple)
        .r#where(eq(simple.name, "Updated"))
        .all();
    assert_eq!(results.len(), 2);

    let results: Vec<SelectSimple> = db
        .select((simple.id, simple.name))
        .from(simple)
        .r#where(in_array(simple.name, ["Bob", "David"]))
        .all();
    assert_eq!(results.len(), 2);
}

#[drizzle::test]
fn update_no_matching_rows(db: &mut TestDb<SimpleSchema>) {
    let SimpleSchema { simple } = schema;

    let stmt = db.insert(simple).values([InsertSimple::new("Alice")]);
    stmt.execute();

    let stmt = db
        .update(simple)
        .set(UpdateSimple::default().with_name("Updated"))
        .r#where(eq(simple.name, "NonExistent"));
    stmt.execute();

    let results: Vec<SelectSimple> = db.select((simple.id, simple.name)).from(simple).all();

    assert_eq!(results.len(), 1);
    assert_eq!(results[0].name, "Alice");
}

#[cfg(all(feature = "serde", feature = "uuid"))]
#[drizzle::test]
fn feature_gated_update(db: &mut TestDb<ComplexSchema>) {
    let ComplexSchema { complex } = schema;
    // Insert initial Complex record with UUID
    let test_id = uuid::Uuid::new_v4();
    let insert_data = InsertComplex::new("feature_user", true, Role::User)
        .with_id(test_id)
        .with_metadata(UserMetadata {
            preferences: vec!["user_mode".to_string()],
            last_login: Some("2023-01-15".to_string()),
            theme: "light".to_string(),
        })
        .with_config(UserConfig {
            notifications: true,
            language: "en".to_string(),
            settings: std::collections::HashMap::new(),
        });

    let insert_result = db.insert(complex).values([insert_data]).execute();
    assert_eq!(insert_result, 1);

    // Update feature-gated fields using UUID primary key
    let stmt = db
        .update(complex)
        .set(
            UpdateComplex::default()
                .with_metadata(UserMetadata {
                    preferences: vec!["admin_mode".to_string(), "updated".to_string()],
                    last_login: Some("2023-12-15".to_string()),
                    theme: "admin".to_string(),
                })
                .with_config(UserConfig {
                    notifications: false,
                    language: "en".to_string(),
                    settings: std::collections::HashMap::from([(
                        "updated".to_string(),
                        "true".to_string(),
                    )]),
                }),
        )
        .r#where(eq(Complex::id, test_id));
    let update_result = stmt.execute();
    assert_eq!(update_result, 1);

    // Verify the update by selecting with UUID
    let results: Vec<ComplexResult> = db
        .select((
            complex.id,
            complex.name,
            complex.email,
            complex.age,
            complex.description,
        ))
        .from(complex)
        .r#where(eq(complex.id, test_id))
        .all();

    assert_eq!(results.len(), 1);
    assert_eq!(results[0].name, "feature_user");
    assert_eq!(results[0].id, test_id);
}