From 9972f87669ffa48e1dab24f4663ea688cefb5fd6 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 3 Sep 2026 11:00:34 +0000 Subject: [PATCH] fix: repair CI lints and failing unit tests on master MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Clippy and Unit Test jobs are red on master, independent of any dependency bump. Three unrelated causes: Clippy (stable is now 1.98, where `unnecessary_unwrap` also fires on `as_ref().unwrap()`, plus `useless_borrows_in_formatting` and `useless_conversion` hits): - `active_model_ex.rs` / `model_ex.rs`: bind the `LitStr` with a pattern instead of re-checking `is_some()` and unwrapping. - `statement.rs`, `helper.rs`, `sea-orm-cli/commands/migrate.rs`: drop the redundant borrows in `write!`/`format!` and the redundant `into_iter()`. Unit Test, `cargo test --workspace` failed to compile with `cannot find register_entity in sea_orm`. `DeriveEntity` gates the registry submission on `sea-orm-macros`' own `entity-registry` feature, but the proc-macro crate is resolved once for the whole build while `sea-orm` is not, so the macro can emit `sea_orm::register_entity!` into a `sea-orm` built without the feature. `sea-orm` (and its `sea-orm-sync` mirror) now provide a no-op `register_entity!` in that configuration, so the generated code compiles either way. `cargo test --features entity-registry` also failed to build the integration tests: the submission named `Entity` as a value and hardcoded that name, which breaks for an entity struct with fields, such as `tests/common/features/dyn_table_name.rs`. Use the derived ident, and skip entities that are not unit structs — those have no static schema to register. Finally, `examples/quickstart` goes back to being its own workspace. As a member it unified `sqlx-sqlite`, `runtime-tokio`, `schema-sync` and `entity-registry` into `sea-orm`'s own test targets, which made the Unit Test job compile and run the database integration tests, and those need a `DATABASE_URL` that the job does not set. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_013LqKqpvKd1hWCpWvAZeQmn --- Cargo.toml | 2 +- examples/quickstart/Cargo.toml | 3 ++ sea-orm-cli/src/commands/migrate.rs | 2 +- sea-orm-macros/src/derives/active_model_ex.rs | 18 +++-------- sea-orm-macros/src/derives/entity.rs | 30 +++++++++++++------ sea-orm-macros/src/derives/model_ex.rs | 16 +++++----- sea-orm-sync/src/database/statement.rs | 4 +-- sea-orm-sync/src/entity/mod.rs | 11 +++++++ sea-orm-sync/src/query/helper.rs | 2 +- src/database/statement.rs | 4 +-- src/entity/mod.rs | 11 +++++++ src/query/helper.rs | 2 +- 12 files changed, 65 insertions(+), 40 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a7c5252a41..f89da3da21 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = [".", "sea-orm-macros", "sea-orm-codegen", "examples/quickstart"] +members = [".", "sea-orm-macros", "sea-orm-codegen"] [package] authors = ["Chris Tsang "] diff --git a/examples/quickstart/Cargo.toml b/examples/quickstart/Cargo.toml index 2395f0d013..ea3dfba255 100644 --- a/examples/quickstart/Cargo.toml +++ b/examples/quickstart/Cargo.toml @@ -1,3 +1,6 @@ +[workspace] +# A separate workspace + [package] edition = "2024" name = "sea-orm-quickstart" diff --git a/sea-orm-cli/src/commands/migrate.rs b/sea-orm-cli/src/commands/migrate.rs index 11978b4dd8..895f11a050 100644 --- a/sea-orm-cli/src/commands/migrate.rs +++ b/sea-orm-cli/src/commands/migrate.rs @@ -178,7 +178,7 @@ fn get_full_migration_dir(migration_dir: &str) -> PathBuf { fn create_new_migration(migration_name: &str, migration_dir: &str) -> Result<(), Box> { let migration_filepath = - get_full_migration_dir(migration_dir).join(format!("{}.rs", &migration_name)); + get_full_migration_dir(migration_dir).join(format!("{migration_name}.rs")); println!("Creating migration file `{}`", migration_filepath.display()); // TODO: make OS agnostic let migration_template = diff --git a/sea-orm-macros/src/derives/active_model_ex.rs b/sea-orm-macros/src/derives/active_model_ex.rs index e779ff5fc9..6c97e0a487 100644 --- a/sea-orm-macros/src/derives/active_model_ex.rs +++ b/sea-orm-macros/src/derives/active_model_ex.rs @@ -114,23 +114,13 @@ pub fn expand_derive_active_model_ex( )); } } - if compound_attrs.self_ref.is_some() - && compound_attrs.via.is_some() - && compound_attrs.reverse.is_none() + if let (Some(()), Some(via)) = + (&compound_attrs.self_ref, &compound_attrs.via) { has_many_via_self_fields.push(( ident.clone(), - compound_attrs.via.as_ref().unwrap().value(), - false, - )); - } else if compound_attrs.self_ref.is_some() - && compound_attrs.via.is_some() - && compound_attrs.reverse.is_some() - { - has_many_via_self_fields.push(( - ident.clone(), - compound_attrs.via.as_ref().unwrap().value(), - true, + via.value(), + compound_attrs.reverse.is_some(), )); } } diff --git a/sea-orm-macros/src/derives/entity.rs b/sea-orm-macros/src/derives/entity.rs index bf896bf81e..f420f4899a 100644 --- a/sea-orm-macros/src/derives/entity.rs +++ b/sea-orm-macros/src/derives/entity.rs @@ -16,12 +16,21 @@ struct DeriveEntity { relation_ident: syn::Ident, schema_name: Option, table_name: Option, + unit_struct: bool, } impl DeriveEntity { fn new(input: syn::DeriveInput) -> Result { let sea_attr = derive_attr::SeaOrm::try_from_attributes(&input.attrs)?.unwrap_or_default(); + let unit_struct = matches!( + &input.data, + syn::Data::Struct(syn::DataStruct { + fields: syn::Fields::Unit, + .. + }) + ); + let ident = input.ident; let column_ident = sea_attr.column.unwrap_or_else(|| format_ident!("Column")); let model_ident = sea_attr.model.unwrap_or_else(|| format_ident!("Model")); @@ -53,6 +62,7 @@ impl DeriveEntity { relation_ident, schema_name, table_name, + unit_struct, }) } @@ -161,17 +171,19 @@ impl DeriveEntity { } fn impl_entity_registry(&self) -> TokenStream { - if cfg!(feature = "entity-registry") { - quote! { - sea_orm::register_entity! { - sea_orm::EntityRegistry { - module_path: module_path!(), - schema_info: |schema| sea_orm::EntitySchemaInfo::new(Entity, schema), - } + // An Entity that carries data (e.g. a runtime table name) has no static schema, and + // cannot be named as a value here either, so there is nothing to register. + if !cfg!(feature = "entity-registry") || !self.unit_struct { + return quote!(); + } + let ident = &self.ident; + quote! { + sea_orm::register_entity! { + sea_orm::EntityRegistry { + module_path: module_path!(), + schema_info: |schema| sea_orm::EntitySchemaInfo::new(#ident, schema), } } - } else { - quote!() } } } diff --git a/sea-orm-macros/src/derives/model_ex.rs b/sea-orm-macros/src/derives/model_ex.rs index b181a9ae9d..80f26170d8 100644 --- a/sea-orm-macros/src/derives/model_ex.rs +++ b/sea-orm-macros/src/derives/model_ex.rs @@ -442,16 +442,14 @@ fn relation_enum_variant(attr: &compound_attr::SeaOrm, ty: &str) -> Option { - write!(f, "{}", &self.sql) + write!(f, "{}", self.sql) } } } diff --git a/sea-orm-sync/src/entity/mod.rs b/sea-orm-sync/src/entity/mod.rs index d82fd4ce54..4dadf7c4ff 100644 --- a/sea-orm-sync/src/entity/mod.rs +++ b/sea-orm-sync/src/entity/mod.rs @@ -115,6 +115,17 @@ mod primary_key; mod registry; mod relation; +/// Registers an Entity with the Entity Registry. +/// +/// This no-op fallback is used when the `entity-registry` feature is disabled, so that +/// the code emitted by `DeriveEntity` compiles no matter how the feature is resolved +/// for `sea-orm-macros`. +#[cfg(not(feature = "entity-registry"))] +#[macro_export] +macro_rules! register_entity { + ($($entity:tt)*) => {}; +} + pub use active_enum::*; pub use active_model::*; pub use active_model_ex::*; diff --git a/sea-orm-sync/src/query/helper.rs b/sea-orm-sync/src/query/helper.rs index 4ec5153e74..52a1496ee4 100644 --- a/sea-orm-sync/src/query/helper.rs +++ b/sea-orm-sync/src/query/helper.rs @@ -902,7 +902,7 @@ pub(crate) fn join_tbl_on_condition( foreign_keys: Identity, ) -> Condition { let mut cond = Condition::all(); - for (owner_key, foreign_key) in owner_keys.into_iter().zip(foreign_keys.into_iter()) { + for (owner_key, foreign_key) in owner_keys.into_iter().zip(foreign_keys) { cond = cond .add(Expr::col((from_tbl.clone(), owner_key)).equals((to_tbl.clone(), foreign_key))); } diff --git a/src/database/statement.rs b/src/database/statement.rs index 6bd96ce75a..4d3d68ad92 100644 --- a/src/database/statement.rs +++ b/src/database/statement.rs @@ -75,10 +75,10 @@ impl fmt::Display for Statement { inject_parameters(&self.sql, &values.0, &SqliteQueryBuilder) } }; - write!(f, "{}", &string) + write!(f, "{string}") } None => { - write!(f, "{}", &self.sql) + write!(f, "{}", self.sql) } } } diff --git a/src/entity/mod.rs b/src/entity/mod.rs index d82fd4ce54..4dadf7c4ff 100644 --- a/src/entity/mod.rs +++ b/src/entity/mod.rs @@ -115,6 +115,17 @@ mod primary_key; mod registry; mod relation; +/// Registers an Entity with the Entity Registry. +/// +/// This no-op fallback is used when the `entity-registry` feature is disabled, so that +/// the code emitted by `DeriveEntity` compiles no matter how the feature is resolved +/// for `sea-orm-macros`. +#[cfg(not(feature = "entity-registry"))] +#[macro_export] +macro_rules! register_entity { + ($($entity:tt)*) => {}; +} + pub use active_enum::*; pub use active_model::*; pub use active_model_ex::*; diff --git a/src/query/helper.rs b/src/query/helper.rs index 4ec5153e74..52a1496ee4 100644 --- a/src/query/helper.rs +++ b/src/query/helper.rs @@ -902,7 +902,7 @@ pub(crate) fn join_tbl_on_condition( foreign_keys: Identity, ) -> Condition { let mut cond = Condition::all(); - for (owner_key, foreign_key) in owner_keys.into_iter().zip(foreign_keys.into_iter()) { + for (owner_key, foreign_key) in owner_keys.into_iter().zip(foreign_keys) { cond = cond .add(Expr::col((from_tbl.clone(), owner_key)).equals((to_tbl.clone(), foreign_key))); }