use std::{fs, panic};
use crate::{Database, Lazy, migration::Config};
#[test]
fn unique_constraint_violation() {
mod schema {
#[crate::migration::schema(Test)]
#[version(0..=1)]
pub mod vN {
#[no_reference]
pub struct Foo {
#[version(..1)]
pub name: String,
#[version(1..)]
#[unique]
pub name_new: String, }
}
}
use schema::*;
const FILE: &str = "unique_constraint_violation.sqlite";
let _ = fs::remove_file(FILE);
let db: Database<v0::Test> = Database::new(Config::open(FILE));
db.transaction_mut_ok(|txn| {
txn.insert_ok(v0::Foo {
name: "alpha".to_owned(),
});
txn.insert_ok(v0::Foo {
name: "alpha".to_owned(),
});
});
Database::migrator(Config::open(FILE))
.unwrap()
.migrate(|txn| {
let res = txn.migrate::<v1::Foo>(|prev: Lazy<v0::Foo>| v0::migrate::Foo {
name_new: prev.name.clone(),
});
assert!(res.is_err(), "the new unique constraint should be caught");
v0::migrate::Test {
foo: txn.migrate_optional(|_| None).unwrap().no_reference(),
}
})
.finish()
.unwrap();
}
#[test]
fn migrations_preserve_index() {
mod schema {
#[crate::migration::schema(Test)]
#[version(0..=1)]
pub mod vN {
#[version(..1)]
pub struct Foo {
pub name: String,
}
#[version(1..)]
#[from(Foo)]
#[primary_key("new_id")]
pub struct FooNew {
pub name: String,
}
pub struct Ref {
pub foo: rust_query::TableRow<FooNew>,
}
}
}
mod schema_with_index {
#[crate::migration::schema(Test)]
#[version(1..=1)]
pub mod vN {
#[primary_key("new_id")]
pub struct FooNew {
#[index]
pub name: String,
}
pub struct Ref {
pub foo: rust_query::TableRow<FooNew>,
}
}
}
use schema::*;
const FILE: &str = "migrations_preserve_index.sqlite";
let _ = fs::remove_file(FILE);
let db: Database<v0::Test> = Database::new(Config::open(FILE));
db.transaction_mut_ok(|txn| {
let alpha = txn.insert_ok(v0::Foo {
name: "alpha".to_owned(),
});
txn.insert_ok(v0::Foo {
name: "brave".to_owned(),
});
let charlie = txn.insert_ok(v0::Foo {
name: "charlie".to_owned(),
});
txn.insert_ok(v0::Ref { foo: charlie });
let txn = txn.downgrade();
assert!(txn.delete(alpha).unwrap());
});
Database::migrator(Config::open(FILE))
.unwrap()
.migrate(|txn| v0::migrate::Test {
foo_new: txn
.migrate(|prev: Lazy<v0::Foo>| v0::migrate::FooNew {
name: prev.name.clone(),
})
.unwrap(),
})
.finish()
.unwrap();
let db: Database<schema_with_index::v1::Test> = Database::new(Config::open(FILE));
db.transaction(|txn| {
let [item] = txn
.lazy_iter(schema_with_index::v1::Ref)
.collect::<Vec<_>>()
.try_into()
.unwrap();
assert_eq!(item.foo.name, "charlie");
});
}
#[test]
fn foreign_key_violation() {
mod schema {
#[crate::migration::schema(Test)]
#[version(0..=1)]
pub mod vN {
use crate::TableRow;
pub struct Ref {
pub foo: TableRow<Foo>,
}
pub struct Foo {
#[version(..1)]
pub name: String,
}
}
}
use schema::*;
const FILE: &str = "foreign_key_violation.sqlite";
let _ = fs::remove_file(FILE);
let db: Database<v0::Test> = Database::new(Config::open(FILE));
db.transaction_mut_ok(|txn| {
let spacer = txn.insert_ok(v0::Foo {
name: "spacer".to_owned(),
});
let foo = txn.insert_ok(v0::Foo {
name: "referenced".to_owned(),
});
txn.insert_ok(v0::Ref { foo });
let txn = txn.downgrade();
txn.delete(spacer).unwrap();
});
let err = panic::catch_unwind(|| {
Database::migrator(Config::open(FILE))
.unwrap()
.migrate(|txn| v0::migrate::Test {
foo: txn
.migrate_optional(|old: Lazy<'_, v0::Foo>| {
assert_eq!(old.name, "referenced");
None
})
.unwrap()
.map_fk_err(|| panic!("this should trigger")),
})
.finish()
.unwrap();
})
.unwrap_err();
assert_eq!(err.downcast_ref::<&str>().unwrap(), &"this should trigger");
}