From 3d50c248a57f0cf5168392dd4dafad5edfdfcdde Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Wed, 4 Jan 2023 14:22:52 +0800 Subject: [PATCH] `find_by_id` and `delete_by_id` take any Into primary key value --- src/entity/base_entity.rs | 55 ++++++++++++++++++++++++++++++++++++--- src/executor/update.rs | 28 +++++++++----------- 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/src/entity/base_entity.rs b/src/entity/base_entity.rs index 443827d4b..9bc71b928 100644 --- a/src/entity/base_entity.rs +++ b/src/entity/base_entity.rs @@ -256,10 +256,13 @@ pub trait EntityTrait: EntityName { /// # Ok(()) /// # } /// ``` - fn find_by_id(values: ::ValueType) -> Select { + fn find_by_id(values: T) -> Select + where + T: Into<::ValueType>, + { let mut select = Self::find(); let mut keys = Self::PrimaryKey::iter(); - for v in values.into_value_tuple() { + for v in values.into().into_value_tuple() { if let Some(key) = keys.next() { let col = key.into_column(); select = select.filter(col.eq(v)); @@ -819,10 +822,13 @@ pub trait EntityTrait: EntityName { /// # Ok(()) /// # } /// ``` - fn delete_by_id(values: ::ValueType) -> DeleteMany { + fn delete_by_id(values: T) -> DeleteMany + where + T: Into<::ValueType>, + { let mut delete = Self::delete_many(); let mut keys = Self::PrimaryKey::iter(); - for v in values.into_value_tuple() { + for v in values.into().into_value_tuple() { if let Some(key) = keys.next() { let col = key.into_column(); delete = delete.filter(col.eq(v)); @@ -914,4 +920,45 @@ mod tests { assert_eq!(hello::Entity.table_name(), "hello"); assert_eq!(hello::Entity.schema_name(), Some("world")); } + + #[test] + #[cfg(feature = "macros")] + fn entity_model_3() { + use crate::{entity::*, query::*, DbBackend}; + use std::borrow::Cow; + + mod hello { + use crate as sea_orm; + use crate::entity::prelude::*; + + #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] + #[sea_orm(table_name = "hello", schema_name = "world")] + pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + } + + #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] + pub enum Relation {} + + impl ActiveModelBehavior for ActiveModel {} + } + + fn delete_by_id(value: T) + where + T: Into<<::PrimaryKey as PrimaryKeyTrait>::ValueType>, + { + assert_eq!( + hello::Entity::delete_by_id(value) + .build(DbBackend::Sqlite) + .to_string(), + r#"DELETE FROM "world"."hello" WHERE "hello"."id" = 'UUID'"# + ); + } + + delete_by_id(format!("UUID")); + delete_by_id("UUID".to_string()); + delete_by_id("UUID"); + delete_by_id(Cow::from("UUID")); + } } diff --git a/src/executor/update.rs b/src/executor/update.rs index 190347e02..7cff7d765 100644 --- a/src/executor/update.rs +++ b/src/executor/update.rs @@ -1,6 +1,6 @@ use crate::{ cast_enum_as_text, error::*, ActiveModelTrait, ConnectionTrait, EntityTrait, IntoActiveModel, - Iterable, SelectModel, SelectorRaw, Statement, UpdateMany, UpdateOne, + Iterable, PrimaryKeyTrait, SelectModel, SelectorRaw, Statement, UpdateMany, UpdateOne, }; use sea_query::{Expr, FromValueTuple, Query, UpdateStatement}; use std::future::Future; @@ -89,20 +89,20 @@ where A: ActiveModelTrait, C: ConnectionTrait, { + type Entity = ::Entity; + type Model = as EntityTrait>::Model; + type Column = as EntityTrait>::Column; + type ValueType = < as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType; match db.support_returning() { true => { - let returning = Query::returning().exprs( - ::Column::iter() - .map(|c| cast_enum_as_text(Expr::col(c), &c)), - ); + let returning = Query::returning() + .exprs(Column::::iter().map(|c| cast_enum_as_text(Expr::col(c), &c))); query.returning(returning); let db_backend = db.get_database_backend(); - let found: Option<::Model> = - SelectorRaw::::Model>>::from_statement( - db_backend.build(&query), - ) - .one(db) - .await?; + let found: Option> = + SelectorRaw::>>::from_statement(db_backend.build(&query)) + .one(db) + .await?; // If we got `None` then we are updating a row that does not exist. match found { Some(model) => Ok(model), @@ -115,12 +115,10 @@ where // If we updating a row that does not exist then an error will be thrown here. Updater::new(query).check_record_exists().exec(db).await?; let primary_key_value = match model.get_primary_key_value() { - Some(val) => FromValueTuple::from_value_tuple(val), + Some(val) => ValueType::::from_value_tuple(val), None => return Err(DbErr::UpdateGetPrimaryKey), }; - let found = ::find_by_id(primary_key_value) - .one(db) - .await?; + let found = Entity::::find_by_id(primary_key_value).one(db).await?; // If we cannot select the updated row from db by the cached primary key match found { Some(model) => Ok(model),