Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enumeration #258

Merged
merged 45 commits into from
Nov 8, 2021
Merged

Enumeration #258

merged 45 commits into from
Nov 8, 2021

Conversation

billy1624
Copy link
Member

@billy1624 billy1624 commented Oct 19, 2021

@billy1624 billy1624 self-assigned this Oct 19, 2021
@tyt2y3
Copy link
Member

tyt2y3 commented Oct 20, 2021

Oh we have Derive macro already? Great

@billy1624
Copy link
Member Author

Oh we have Derive macro already? Great

Yep

@billy1624
Copy link
Member Author

Btw... I will try to document all newly added types starting from this PR. Plz check the docs and give me some feedback on it @tyt2y3

@tyt2y3
Copy link
Member

tyt2y3 commented Oct 20, 2021

Is there a test case for not using a Derive macro?

src/entity/active_enum.rs Outdated Show resolved Hide resolved
src/entity/active_enum.rs Outdated Show resolved Hide resolved
@billy1624 billy1624 mentioned this pull request Oct 20, 2021
1 task
@tyt2y3 tyt2y3 force-pushed the master branch 2 times, most recently from 75d6895 to e2c8d32 Compare October 23, 2021 10:03
@tyt2y3
Copy link
Member

tyt2y3 commented Nov 1, 2021

Sorry for creating the conflicts

@billy1624
Copy link
Member Author

No worries, I will resolve it

src/error.rs Outdated Show resolved Hide resolved
src/entity/active_enum.rs Outdated Show resolved Hide resolved
@tyt2y3
Copy link
Member

tyt2y3 commented Nov 3, 2021

I think we are pretty much done

Schema Definition

pub async fn create_active_enum_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let db_backend = db.get_database_backend();
let tea_enum = Alias::new("tea");
let create_enum_stmts = match db_backend {
DbBackend::MySql | DbBackend::Sqlite => Vec::new(),
DbBackend::Postgres => vec![Type::create()
.as_enum(tea_enum.clone())
.values(vec![Alias::new("EverydayTea"), Alias::new("BreakfastTea")])
.to_owned()],
};
create_enum(db, &create_enum_stmts, ActiveEnum).await?;
let mut tea_col = ColumnDef::new(active_enum::Column::Tea);
match db_backend {
DbBackend::MySql => tea_col.custom(Alias::new("ENUM('EverydayTea', 'BreakfastTea')")),
DbBackend::Sqlite => tea_col.text(),
DbBackend::Postgres => tea_col.custom(tea_enum),
};
let create_table_stmt = sea_query::Table::create()
.table(active_enum::Entity)
.col(
ColumnDef::new(active_enum::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(active_enum::Column::Category).string_len(1))
.col(ColumnDef::new(active_enum::Column::Color).integer())
.col(&mut tea_col)
.to_owned();
create_table(db, &create_table_stmt, ActiveEnum).await
}

Entity Definition

use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "active_enum")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub category: Option<Category>,
pub color: Option<Color>,
pub tea: Option<Tea>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum)]
#[sea_orm(rs_type = "String", db_type = "String(Some(1))")]
pub enum Category {
#[sea_orm(string_value = "B")]
Big,
#[sea_orm(string_value = "S")]
Small,
}
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum)]
#[sea_orm(rs_type = "i32", db_type = r#"Integer"#)]
pub enum Color {
#[sea_orm(num_value = 0)]
Black,
#[sea_orm(num_value = 1)]
White,
}
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum)]
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "tea")]
pub enum Tea {
#[sea_orm(string_value = "EverydayTea")]
EverydayTea,
#[sea_orm(string_value = "BreakfastTea")]
BreakfastTea,
}

Action

pub mod common;
pub use common::{features::*, setup::*, TestContext};
use sea_orm::{entity::prelude::*, entity::*, DatabaseConnection};
#[sea_orm_macros::test]
#[cfg(any(
feature = "sqlx-mysql",
feature = "sqlx-sqlite",
feature = "sqlx-postgres"
))]
async fn main() -> Result<(), DbErr> {
let ctx = TestContext::new("active_enum_tests").await;
create_tables(&ctx.db).await?;
insert_active_enum(&ctx.db).await?;
ctx.delete().await;
Ok(())
}
pub async fn insert_active_enum(db: &DatabaseConnection) -> Result<(), DbErr> {
use active_enum::*;
let am = ActiveModel {
category: Set(None),
color: Set(None),
tea: Set(None),
..Default::default()
}
.insert(db)
.await?;
assert_eq!(
Entity::find().one(db).await?.unwrap(),
Model {
id: 1,
category: None,
color: None,
tea: None,
}
);
let am = ActiveModel {
category: Set(Some(Category::Big)),
color: Set(Some(Color::Black)),
tea: Set(Some(Tea::EverydayTea)),
..am
}
.save(db)
.await?;
assert_eq!(
Entity::find().one(db).await?.unwrap(),
Model {
id: 1,
category: Some(Category::Big),
color: Some(Color::Black),
tea: Some(Tea::EverydayTea),
}
);
let res = am.delete(db).await?;
assert_eq!(res.rows_affected, 1);
assert_eq!(Entity::find().one(db).await?, None);
Ok(())
}

@acidic9 @nicoulaj request for comment 👀

@tqwewe
Copy link
Contributor

tqwewe commented Nov 3, 2021

Ooh I really like the look of this. I had a bried look at the linked code snippets you shared @tyt2y3 and it looks really explicit. I like how you can use an enum as an integer too!

@nicoulaj
Copy link

nicoulaj commented Nov 3, 2021

Just tried it on a complex project and it mostly worked flawlessly, awesome work !

Two things I noticed:

  • When using database enum, ColumnTrait::eq does not seem to cast the value, it generates WHERE mycol = ? and the query is invalid as a consequence
  • The new macros generate code with use sea_query instead of use sea_orm::sea_query, forcing users to add an explicit dependency on sea-query

@billy1624
Copy link
Member Author

  • The new macros generate code with use sea_query instead of use sea_orm::sea_query, forcing users to add an explicit dependency on sea-query

Nice catch! Fixed on f64f1e9

@billy1624
Copy link
Member Author

billy1624 commented Nov 4, 2021

  • When using database enum, ColumnTrait::eq does not seem to cast the value, it generates WHERE mycol = ? and the query is invalid as a consequence

That's bad. See 67bb168. Thanks!! @nicoulaj

@billy1624
Copy link
Member Author

After second thought, it only make sense to cast string to enum type inside = & != comparison. See 10f3de0

Copy link
Member

@tyt2y3 tyt2y3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's been a long road

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enumeration
4 participants