Cast enums in lt(), lte(), gt(), gte() (#2014)

* Cast enums in lt, lte, gt, gte (revert 10f3de0, discussed under #1527)

* Add tests for enum order comparisons
This commit is contained in:
Dmitrii Aleksandrov 2024-01-12 18:42:29 +04:00 committed by GitHub
parent 914ae2e166
commit a73f699578
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 18 deletions

View File

@ -20,18 +20,6 @@ pub struct ColumnDef {
}
macro_rules! bind_oper {
( $op: ident ) => {
#[allow(missing_docs)]
fn $op<V>(&self, v: V) -> SimpleExpr
where
V: Into<Value>,
{
Expr::col((self.entity_name(), *self)).$op(v)
}
};
}
macro_rules! bind_oper_with_enum_casting {
( $op: ident, $bin_op: ident ) => {
#[allow(missing_docs)]
fn $op<V>(&self, v: V) -> SimpleExpr
@ -97,12 +85,12 @@ pub trait ColumnTrait: IdenStatic + Iterable + FromStr {
(self.entity_name(), SeaRc::new(*self) as DynIden)
}
bind_oper_with_enum_casting!(eq, Equal);
bind_oper_with_enum_casting!(ne, NotEqual);
bind_oper!(gt);
bind_oper!(gte);
bind_oper!(lt);
bind_oper!(lte);
bind_oper!(eq, Equal);
bind_oper!(ne, NotEqual);
bind_oper!(gt, GreaterThan);
bind_oper!(gte, GreaterThanOrEqual);
bind_oper!(lt, SmallerThan);
bind_oper!(lte, SmallerThanOrEqual);
/// ```
/// use sea_orm::{entity::*, query::*, tests_cfg::cake, DbBackend};

View File

@ -167,6 +167,57 @@ pub async fn insert_active_enum(db: &DatabaseConnection) -> Result<(), DbErr> {
assert_eq!(model, select_with_tea_not_in.one(db).await?.unwrap());
// String enums should be compared alphabetically in all supported DBs.
// 'B' < 'S', so Big is considered "smaller" than Small.
assert_eq!(
model,
Entity::find()
.filter(Column::Category.lt(Category::Small))
.one(db)
.await?
.unwrap()
);
// Integer enums should be compared by value in all supported DBs.
// 0 <= 1, so Black is considered "smaller or equal to" White.
assert_eq!(
model,
Entity::find()
.filter(Column::Color.lte(Color::White))
.one(db)
.await?
.unwrap()
);
// Native enum comparisons are not portable.
//
// Postgres enums are compared by their definition order
// (see https://www.postgresql.org/docs/current/datatype-enum.html#DATATYPE-ENUM-ORDERING).
// Tea was defined as ('EverydayTea', 'BreakfastTea'), so EverydayTea is considered "smaller" than BreakfastTea.
//
// SQLite doesn't support enum types and SeaORM works around this limitation by storing them as strings.
// When treated as strings, EverydayTea is not "smaller" than BreakfastTea!
//
// MySQL should be the same as Postgres (see https://dev.mysql.com/doc/refman/8.0/en/enum.html#enum-sorting),
// but in practice this test case behaves like SQLite. I'm not sure why.
#[cfg(feature = "sqlx-postgres")]
assert_eq!(
model,
Entity::find()
.filter(Column::Tea.lt(Tea::BreakfastTea))
.one(db)
.await?
.unwrap()
);
#[cfg(any(feature = "sqlx-mysql", feature = "sqlx-sqlite"))]
assert_eq!(
None,
Entity::find()
.filter(Column::Tea.lt(Tea::BreakfastTea))
.one(db)
.await?
);
let res = model.delete(db).await?;
assert_eq!(res.rows_affected, 1);