#![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, InsertComplex};
use crate::common::schema::sqlite::{InsertSimple, UpdateSimple};
#[cfg(feature = "serde")]
use crate::common::schema::sqlite::{UserConfig, UserMetadata};
use drizzle::core::expr::*;
use drizzle::sqlite::prelude::*;
#[cfg(feature = "uuid")]
use uuid::Uuid;
#[cfg(feature = "uuid")]
use crate::common::schema::sqlite::ComplexSchema;
use crate::common::schema::sqlite::{SelectSimple, SimpleSchema};
#[cfg(feature = "uuid")]
#[allow(dead_code)]
#[derive(SQLiteFromRow, Debug)]
struct ComplexResult {
id: Uuid,
name: String,
email: Option<String>,
age: Option<i32>,
description: Option<String>,
}
#[drizzle::test]
fn simple_insert(db: &mut TestDb<SimpleSchema>) {
let SimpleSchema { simple } = schema;
let data = InsertSimple::new("test");
let result = db.insert(simple).values([data]).execute();
assert_eq!(result, 1);
let results: Vec<SelectSimple> = db
.select((simple.id, simple.name))
.from(simple)
.r#where(eq(simple.name, "test"))
.all();
assert_eq!(results.len(), 1);
assert_eq!(results[0].name, "test");
}
#[drizzle::test]
fn insert_with_table_and_column_refs(db: &mut TestDb<SimpleSchema>) {
let SimpleSchema { simple } = schema;
let simple_ref = &simple;
let name_ref = &simple.name;
let data = InsertSimple::new("ref_test");
let result = db.insert(simple_ref).values([data]).execute();
assert_eq!(result, 1);
let results: Vec<SelectSimple> = db
.select((simple_ref.id, simple_ref.name))
.from(simple_ref)
.r#where(eq(name_ref, "ref_test"))
.all();
assert_eq!(results.len(), 1);
assert_eq!(results[0].name, "ref_test");
}
#[cfg(feature = "uuid")]
#[drizzle::test]
fn complex_insert(db: &mut TestDb<ComplexSchema>) {
let ComplexSchema { complex } = schema;
#[cfg(not(feature = "uuid"))]
let data = InsertComplex::new("complex_user", true, Role::User)
.with_email("test@example.com".to_string())
.with_age(25)
.with_score(95.5)
.with_description("Test description".to_string())
.with_data_blob(vec![1, 2, 3, 4]);
#[cfg(feature = "uuid")]
let data = InsertComplex::new("complex_user", true, Role::User)
.with_id(uuid::Uuid::new_v4())
.with_email("test@example.com".to_string())
.with_age(25)
.with_score(95.5)
.with_description("Test description".to_string())
.with_data_blob(vec![1, 2, 3, 4]);
let result = db.insert(complex).values([data]).execute();
assert_eq!(result, 1);
let results: Vec<ComplexResult> = db
.select((
complex.id,
complex.name,
complex.email,
complex.age,
complex.description,
))
.from(complex)
.r#where(eq(Complex::name, "complex_user"))
.all();
assert_eq!(results.len(), 1);
assert_eq!(results[0].name, "complex_user");
assert_eq!(results[0].email, Some("test@example.com".to_string()));
assert_eq!(results[0].age, Some(25));
assert_eq!(results[0].description, Some("Test description".to_string()));
}
#[drizzle::test]
fn conflict_resolution(db: &mut TestDb<SimpleSchema>) {
let SimpleSchema { simple } = schema;
let initial_data = InsertSimple::new("conflict_test").with_id(1);
db.insert(simple).values([initial_data]).execute();
let duplicate_data = InsertSimple::new("conflict_test").with_id(1);
let stmt = db
.insert(simple)
.values([duplicate_data])
.on_conflict_do_nothing();
let result = stmt.execute();
assert_eq!(result, 0);
let results: Vec<SelectSimple> = db
.select((simple.id, simple.name))
.from(simple)
.r#where(eq(simple.name, "conflict_test"))
.all();
assert_eq!(results.len(), 1);
assert_eq!(results[0].name, "conflict_test");
}
#[cfg(all(feature = "serde", feature = "uuid"))]
#[drizzle::test]
fn feature_gated_insert(db: &mut TestDb<ComplexSchema>) {
let ComplexSchema { complex } = schema;
let data = InsertComplex::new("feature_test", true, Role::User)
.with_id(uuid::Uuid::new_v4())
.with_metadata(UserMetadata {
preferences: vec!["dark_mode".to_string()],
last_login: Some("2023-01-01".to_string()),
theme: "dark".to_string(),
})
.with_config(UserConfig {
notifications: true,
language: "en".to_string(),
settings: std::collections::HashMap::new(),
});
let stmt = db.insert(complex).values([data]);
let result = stmt.execute();
assert_eq!(result, 1);
let results: Vec<ComplexResult> = db
.select((
complex.id,
complex.name,
complex.email,
complex.age,
complex.description,
))
.from(complex)
.r#where(eq(complex.name, "feature_test"))
.all();
assert_eq!(results.len(), 1);
assert_eq!(results[0].name, "feature_test");
}
#[drizzle::test]
fn on_conflict_do_nothing_no_target_sql(db: &mut TestDb<SimpleSchema>) {
let SimpleSchema { simple } = schema;
let stmt = db
.insert(simple)
.values([InsertSimple::new("test").with_id(1)])
.on_conflict_do_nothing();
assert_eq!(
stmt.to_sql().sql(),
r#"INSERT INTO "simple" ("id", "name") VALUES (?, ?) ON CONFLICT DO NOTHING"#
);
db.insert(simple)
.values([InsertSimple::new("original").with_id(10)])
.execute();
db.insert(simple)
.values([InsertSimple::new("duplicate").with_id(10)])
.on_conflict_do_nothing()
.execute();
let results: Vec<SelectSimple> = db
.select((simple.id, simple.name))
.from(simple)
.r#where(eq(simple.id, 10))
.all();
assert_eq!(results.len(), 1);
assert_eq!(results[0].name, "original");
}
#[drizzle::test]
fn on_conflict_column_do_nothing_sql(db: &mut TestDb<SimpleSchema>) {
let SimpleSchema { simple } = schema;
let stmt = db
.insert(simple)
.values([InsertSimple::new("test").with_id(1)])
.on_conflict(simple.id)
.do_nothing();
assert_eq!(
stmt.to_sql().sql(),
r#"INSERT INTO "simple" ("id", "name") VALUES (?, ?) ON CONFLICT ("id") DO NOTHING"#
);
db.insert(simple)
.values([InsertSimple::new("first").with_id(20)])
.execute();
db.insert(simple)
.values([InsertSimple::new("second").with_id(20)])
.on_conflict(simple.id)
.do_nothing()
.execute();
let results: Vec<SelectSimple> = db
.select((simple.id, simple.name))
.from(simple)
.r#where(eq(simple.id, 20))
.all();
assert_eq!(results.len(), 1);
assert_eq!(results[0].name, "first");
}
#[drizzle::test]
fn on_conflict_do_update_sql(db: &mut TestDb<SimpleSchema>) {
let SimpleSchema { simple } = schema;
let stmt = db
.insert(simple)
.values([InsertSimple::new("test").with_id(1)])
.on_conflict(simple.id)
.do_update(UpdateSimple::default().with_name("updated"));
assert_eq!(
stmt.to_sql().sql(),
r#"INSERT INTO "simple" ("id", "name") VALUES (?, ?) ON CONFLICT ("id") DO UPDATE SET "name" = ?"#
);
db.insert(simple)
.values([InsertSimple::new("before").with_id(30)])
.execute();
db.insert(simple)
.values([InsertSimple::new("ignored").with_id(30)])
.on_conflict(simple.id)
.do_update(UpdateSimple::default().with_name("after"))
.execute();
let results: Vec<SelectSimple> = db
.select((simple.id, simple.name))
.from(simple)
.r#where(eq(simple.id, 30))
.all();
assert_eq!(results.len(), 1);
assert_eq!(results[0].name, "after");
}
#[drizzle::test]
fn on_conflict_do_update_where_sql(db: &mut TestDb<SimpleSchema>) {
let SimpleSchema { simple } = schema;
let stmt = db
.insert(simple)
.values([InsertSimple::new("test").with_id(1)])
.on_conflict(simple.id)
.do_update(UpdateSimple::default().with_name("updated"))
.r#where(gt(simple.id, 0));
assert_eq!(
stmt.to_sql().sql(),
r#"INSERT INTO "simple" ("id", "name") VALUES (?, ?) ON CONFLICT ("id") DO UPDATE SET "name" = ? WHERE "simple"."id" > ?"#
);
db.insert(simple)
.values([InsertSimple::new("original").with_id(40)])
.execute();
db.insert(simple)
.values([InsertSimple::new("ignored").with_id(40)])
.on_conflict(simple.id)
.do_update(UpdateSimple::default().with_name("updated_via_where"))
.r#where(gt(simple.id, 0))
.execute();
let results: Vec<SelectSimple> = db
.select((simple.id, simple.name))
.from(simple)
.r#where(eq(simple.id, 40))
.all();
assert_eq!(results.len(), 1);
assert_eq!(results[0].name, "updated_via_where");
}
#[drizzle::test]
fn on_conflict_do_update_e2e(db: &mut TestDb<SimpleSchema>) {
let SimpleSchema { simple } = schema;
db.insert(simple)
.values([InsertSimple::new("original").with_id(1)])
.execute();
let result = db
.insert(simple)
.values([InsertSimple::new("ignored").with_id(1)])
.on_conflict(simple.id)
.do_update(UpdateSimple::default().with_name("updated"))
.execute();
assert_eq!(result, 1);
let results: Vec<SelectSimple> = db
.select((simple.id, simple.name))
.from(simple)
.r#where(eq(simple.id, 1))
.all();
assert_eq!(results.len(), 1);
assert_eq!(results[0].name, "updated");
}
#[drizzle::test]
fn on_conflict_do_update_excluded_sql(db: &mut TestDb<SimpleSchema>) {
let SimpleSchema { simple } = schema;
let stmt = db
.insert(simple)
.values([InsertSimple::new("test").with_id(1)])
.on_conflict(simple.id)
.do_update(UpdateSimple::default().with_name(excluded(simple.name)));
assert_eq!(
stmt.to_sql().sql(),
r#"INSERT INTO "simple" ("id", "name") VALUES (?, ?) ON CONFLICT ("id") DO UPDATE SET "name" = EXCLUDED."name""#
);
db.insert(simple)
.values([InsertSimple::new("old_name").with_id(50)])
.execute();
db.insert(simple)
.values([InsertSimple::new("new_name").with_id(50)])
.on_conflict(simple.id)
.do_update(UpdateSimple::default().with_name(excluded(simple.name)))
.execute();
let results: Vec<SelectSimple> = db
.select((simple.id, simple.name))
.from(simple)
.r#where(eq(simple.id, 50))
.all();
assert_eq!(results.len(), 1);
assert_eq!(results[0].name, "new_name");
}
#[drizzle::test]
fn on_conflict_do_update_excluded_e2e(db: &mut TestDb<SimpleSchema>) {
let SimpleSchema { simple } = schema;
db.insert(simple)
.values([InsertSimple::new("original").with_id(1)])
.execute();
let result = db
.insert(simple)
.values([InsertSimple::new("from_excluded").with_id(1)])
.on_conflict(simple.id)
.do_update(UpdateSimple::default().with_name(excluded(simple.name)))
.execute();
assert_eq!(result, 1);
let results: Vec<SelectSimple> = db
.select((simple.id, simple.name))
.from(simple)
.r#where(eq(simple.id, 1))
.all();
assert_eq!(results.len(), 1);
assert_eq!(results[0].name, "from_excluded");
}