find_by_id and delete_by_id take any Into primary key value (#1362)

This commit is contained in:
Billy Chan 2023-01-11 15:28:10 +08:00 committed by GitHub
parent c49a8ac843
commit 0756adf647
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 19 deletions

View File

@ -256,10 +256,13 @@ pub trait EntityTrait: EntityName {
/// # Ok(())
/// # }
/// ```
fn find_by_id(values: <Self::PrimaryKey as PrimaryKeyTrait>::ValueType) -> Select<Self> {
fn find_by_id<T>(values: T) -> Select<Self>
where
T: Into<<Self::PrimaryKey as PrimaryKeyTrait>::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));
@ -815,10 +818,13 @@ pub trait EntityTrait: EntityName {
/// # Ok(())
/// # }
/// ```
fn delete_by_id(values: <Self::PrimaryKey as PrimaryKeyTrait>::ValueType) -> DeleteMany<Self> {
fn delete_by_id<T>(values: T) -> DeleteMany<Self>
where
T: Into<<Self::PrimaryKey as PrimaryKeyTrait>::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));
@ -910,4 +916,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<T>(value: T)
where
T: Into<<<hello::Entity as EntityTrait>::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"));
}
}

View File

@ -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,18 +89,18 @@ where
A: ActiveModelTrait,
C: ConnectionTrait,
{
type Entity<A> = <A as ActiveModelTrait>::Entity;
type Model<A> = <Entity<A> as EntityTrait>::Model;
type Column<A> = <Entity<A> as EntityTrait>::Column;
type ValueType<A> = <<Entity<A> as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType;
match db.support_returning() {
true => {
let returning = Query::returning().exprs(
<A::Entity as EntityTrait>::Column::iter()
.map(|c| cast_enum_as_text(Expr::col(c), &c)),
);
let returning = Query::returning()
.exprs(Column::<A>::iter().map(|c| cast_enum_as_text(Expr::col(c), &c)));
query.returning(returning);
let db_backend = db.get_database_backend();
let found: Option<<A::Entity as EntityTrait>::Model> =
SelectorRaw::<SelectModel<<A::Entity as EntityTrait>::Model>>::from_statement(
db_backend.build(&query),
)
let found: Option<Model<A>> =
SelectorRaw::<SelectModel<Model<A>>>::from_statement(db_backend.build(&query))
.one(db)
.await?;
// If we got `None` then we are updating a row that does not exist.
@ -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::<A>::from_value_tuple(val),
None => return Err(DbErr::UpdateGetPrimaryKey),
};
let found = <A::Entity as EntityTrait>::find_by_id(primary_key_value)
.one(db)
.await?;
let found = Entity::<A>::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),