diff --git a/Cargo.lock b/Cargo.lock index 09a80f8..24207a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1211,7 +1211,7 @@ dependencies = [ [[package]] name = "seamantic" -version = "0.0.5" +version = "0.0.6" dependencies = [ "sea-orm", "sea-orm-migration", diff --git a/README.md b/README.md index aebb4e2..c4cf032 100644 --- a/README.md +++ b/README.md @@ -13,4 +13,5 @@ A library to enhance SeaORM - example: `cargo run --example=migrations --features=sqlite` - fmt: `cargo fmt --check` - docs: `RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features` +- semver: `cargo semver-checks --all-features` - publish: `cargo publish --dry-run -p seamantic` diff --git a/seamantic/Cargo.toml b/seamantic/Cargo.toml index 3d6a7fb..77827f8 100644 --- a/seamantic/Cargo.toml +++ b/seamantic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "seamantic" -version = "0.0.5" +version = "0.0.6" categories = [] description = "A library to enhance SeaORM" diff --git a/seamantic/src/lib.rs b/seamantic/src/lib.rs index c8aba77..dbe72de 100644 --- a/seamantic/src/lib.rs +++ b/seamantic/src/lib.rs @@ -6,6 +6,7 @@ pub use sea_orm; pub use sea_orm_migration; pub mod model; +pub mod orm; pub mod schema; /// A macro for defining a Migrator with a custom migration table while diff --git a/seamantic/src/orm/mod.rs b/seamantic/src/orm/mod.rs new file mode 100644 index 0000000..b225a97 --- /dev/null +++ b/seamantic/src/orm/mod.rs @@ -0,0 +1,4 @@ +//! Helpers for working with SeaORM + +mod upsert; +pub use upsert::UpsertTrait; diff --git a/seamantic/src/orm/upsert.rs b/seamantic/src/orm/upsert.rs new file mode 100644 index 0000000..26c8c03 --- /dev/null +++ b/seamantic/src/orm/upsert.rs @@ -0,0 +1,34 @@ +use sea_orm::sea_query::{IntoColumnRef, OnConflict}; +use sea_orm::{ActiveModelTrait, EntityTrait, Insert, Iterable}; + +/// This trait add a method on [Insert] to allow for upsert behavior +pub trait UpsertTrait: private::Sealed { + /// Set ON CONFLICT on primary key to update all other columns + fn on_conflict_upsert(self) -> Self; +} + +fn primary_key_iter() +-> impl Iterator::PrimaryKey> { + ::PrimaryKey::iter() +} + +fn column_iter() -> impl Iterator::Column> { + <::Entity as EntityTrait>::Column::iter() +} + +impl UpsertTrait for Insert { + fn on_conflict_upsert(self) -> Self { + self.on_conflict( + OnConflict::columns(primary_key_iter::()) + .update_columns(column_iter::().filter(|col| { + !primary_key_iter::().any(|pk| pk.into_column_ref() == col.into_column_ref()) + })) + .to_owned(), + ) + } +} + +mod private { + pub trait Sealed {} + impl Sealed for ::sea_orm::Insert {} +}