drizzle 0.1.12

A type-safe SQL query builder for Rust
Documentation
//! PostgreSQL UPDATE statement tests

#![cfg(any(feature = "postgres-sync", feature = "tokio-postgres"))]

use crate::common::schema::postgres::*;
use drizzle::core::expr::*;
use drizzle::postgres::prelude::*;

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

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

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

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

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

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

#[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 stmt = db
        .select((simple.id, simple.name))
        .from(simple)
        .r#where(eq(simple.name, "updated"));
    let results: Vec<SelectSimple> = stmt.all();
    assert_eq!(results.len(), 2);

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

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

    let stmt = db
        .insert(complex)
        .values([InsertComplex::new("Alice", true, Role::User)
            .with_email("old@example.com")
            .with_age(25)]);
    stmt.execute();

    let stmt = db
        .update(complex)
        .set(
            UpdateComplex::default()
                .with_email("new@example.com")
                .with_age(30)
                .with_active(false),
        )
        .r#where(eq(complex.name, "Alice"));
    stmt.execute();

    let stmt = db.select(()).from(complex);
    let results: Vec<PgComplexResult> = stmt.all();

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

#[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_age(16),
        InsertComplex::new("Adult", true, Role::User).with_age(25),
        InsertComplex::new("Senior", true, Role::User).with_age(70),
    ]);
    stmt.execute();

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

    let stmt = db
        .select(())
        .from(complex)
        .r#where(eq(complex.active, false));
    let results: Vec<PgComplexResult> = stmt.all();

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

#[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 stmt = db
        .select((simple.id, simple.name))
        .from(simple)
        .r#where(eq(simple.name, "Updated"));
    let results: Vec<SelectSimple> = stmt.all();
    assert_eq!(results.len(), 2);

    let stmt = db
        .select((simple.id, simple.name))
        .from(simple)
        .r#where(in_array(simple.name, ["Bob", "David"]));
    let results: Vec<SelectSimple> = stmt.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 stmt = db.select((simple.id, simple.name)).from(simple);
    let results: Vec<SelectSimple> = stmt.all();

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

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

    let new_name = simple.name.placeholder("new_name");
    let old_name = simple.name.placeholder("old_name");

    let update = UpdateSimple::default().with_name(new_name);
    let stmt = db
        .update(simple)
        .set(update)
        .r#where(eq(simple.name, old_name));

    let sql = stmt.to_sql();
    let sql_string = sql.sql();

    assert!(
        sql_string.starts_with("UPDATE"),
        "Should be an UPDATE statement, got: {}",
        sql_string
    );
    assert!(
        sql_string.contains("\"simple\""),
        "Should reference the simple table, got: {}",
        sql_string
    );
    assert!(
        sql_string.contains("$1"),
        "Expected first PostgreSQL placeholder in SQL, got: {}",
        sql_string
    );
    assert!(
        sql_string.contains("$2"),
        "Expected second PostgreSQL placeholder in SQL, got: {}",
        sql_string
    );

    let params: Vec<_> = sql.params().collect();
    assert!(
        params.is_empty(),
        "Should have no bound params when using placeholders, got {}",
        params.len()
    );
}

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

    db.insert(simple)
        .values([InsertSimple::new("original_name")])
        .execute();

    let new_name = simple.name.placeholder("new_name");
    let old_name = simple.name.placeholder("old_name");

    let update = UpdateSimple::default().with_name(new_name);
    let prepared = db
        .update(simple)
        .set(update)
        .r#where(eq(simple.name, old_name))
        .prepare()
        .into_owned();

    let updated = prepared.execute(
        drizzle_client!(),
        [
            new_name.bind("updated_name"),
            old_name.bind("original_name"),
        ],
    );
    assert_eq!(updated, 1);

    let stmt = db
        .select((simple.id, simple.name))
        .from(simple)
        .r#where(eq(simple.name, "updated_name"));
    let rows: Vec<SelectSimple> = stmt.all();

    assert_eq!(rows.len(), 1);
    assert_eq!(rows[0].name, "updated_name");
}