diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d7a6453e..ff0afceb 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -318,7 +318,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - path: [86, 249, 262, 319, 324, 352, 356, 471, 693] + path: [86, 249, 262, 319, 324, 352, 356, 471, 630, 693] steps: - uses: actions/checkout@v2 diff --git a/issues/630/Cargo.toml b/issues/630/Cargo.toml new file mode 100644 index 00000000..57fbc5f4 --- /dev/null +++ b/issues/630/Cargo.toml @@ -0,0 +1,23 @@ +[workspace] +# A separate workspace + +[package] +name = "sea-orm-issues-630" +version = "0.1.0" +authors = ["Erik Rhodes "] +edition = "2021" +publish = false + +[dependencies] +serde = "^1" +tokio = { version = "^1", features = ["rt", "rt-multi-thread", "macros"] } + +[dependencies.sea-orm] +path = "../../" # remove this line in your own project +version = "^0.7" +default-features = false +features = ["macros", "runtime-tokio-native-tls", "debug-print", "with-json", "with-chrono"] + +[features] +default = ["sqlx-mysql"] +sqlx-mysql = ["sea-orm/sqlx-mysql"] diff --git a/issues/630/README.md b/issues/630/README.md new file mode 100644 index 00000000..ccafeb5d --- /dev/null +++ b/issues/630/README.md @@ -0,0 +1,6 @@ +# sea_orm_underscore_fields +A minimal repository showing an issue with SeaORM. + +Connects to the database with `env!()`, so make sure to set `DATABASE_URL` when compiling. + +The file `src/entity/underscores_workaround.rs` shows the workaround to get the names to query correctly, and what happens if it's not included. diff --git a/issues/630/create_underscores_table.sql b/issues/630/create_underscores_table.sql new file mode 100644 index 00000000..49631858 --- /dev/null +++ b/issues/630/create_underscores_table.sql @@ -0,0 +1,17 @@ +CREATE TABLE underscores ( + `id` INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + `a_b_c_d` INT NOT NULL, + `a_b_c_dd` INT NOT NULL, + `a_b_cc_d` INT NOT NULL, + `a_bb_c_d` INT NOT NULL, + `aa_b_c_d` INT NOT NULL +); + +INSERT INTO underscores ( + `a_b_c_d`, + `a_b_c_dd`, + `a_b_cc_d`, + `a_bb_c_d`, + `aa_b_c_d` +) +VALUES (1, 2, 3, 4, 5); diff --git a/issues/630/src/entity/mod.rs b/issues/630/src/entity/mod.rs new file mode 100644 index 00000000..92ef1ec4 --- /dev/null +++ b/issues/630/src/entity/mod.rs @@ -0,0 +1,6 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 + +pub mod prelude; + +pub mod underscores; +pub mod underscores_workaround; diff --git a/issues/630/src/entity/prelude.rs b/issues/630/src/entity/prelude.rs new file mode 100644 index 00000000..5a3ce23d --- /dev/null +++ b/issues/630/src/entity/prelude.rs @@ -0,0 +1,3 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 + +pub use super::underscores::Entity as Underscores; diff --git a/issues/630/src/entity/underscores.rs b/issues/630/src/entity/underscores.rs new file mode 100644 index 00000000..ddd0be85 --- /dev/null +++ b/issues/630/src/entity/underscores.rs @@ -0,0 +1,41 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)] +#[sea_orm(table_name = "underscores")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: u32, + pub a_b_c_d: i32, + pub a_b_c_dd: i32, + pub a_b_cc_d: i32, + pub a_bb_c_d: i32, + pub aa_b_c_d: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation {} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + panic!("No RelationDef") + } +} + +impl ActiveModelBehavior for ActiveModel {} + +#[cfg(test)] +mod tests { + use super::*; + use sea_orm::Iterable; + + #[test] + fn column_names() { + assert_eq!( + Column::iter().map(|c| c.to_string()).collect::>(), + vec!["id", "a_b_c_d", "a_b_c_dd", "a_b_cc_d", "a_bb_c_d", "aa_b_c_d"] + ) + } +} diff --git a/issues/630/src/entity/underscores_workaround.rs b/issues/630/src/entity/underscores_workaround.rs new file mode 100644 index 00000000..6773ad15 --- /dev/null +++ b/issues/630/src/entity/underscores_workaround.rs @@ -0,0 +1,46 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.6.0 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)] +#[sea_orm(table_name = "underscores")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: u32, + #[sea_orm(column_name = "a_b_c_d")] + pub a_b_c_d: i32, + #[sea_orm(column_name = "a_b_c_dd")] + pub a_b_c_dd: i32, + #[sea_orm(column_name = "a_b_cc_d")] + pub a_b_cc_d: i32, + #[sea_orm(column_name = "a_bb_c_d")] + pub a_bb_c_d: i32, + #[sea_orm(column_name = "aa_b_c_d")] + pub aa_b_c_d: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation {} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + panic!("No RelationDef") + } +} + +impl ActiveModelBehavior for ActiveModel {} + +#[cfg(test)] +mod tests { + use super::*; + use sea_orm::Iterable; + + #[test] + fn column_names() { + assert_eq!( + Column::iter().map(|c| c.to_string()).collect::>(), + vec!["id", "a_b_c_d", "a_b_c_dd", "a_b_cc_d", "a_bb_c_d", "aa_b_c_d"] + ) + } +} diff --git a/issues/630/src/main.rs b/issues/630/src/main.rs new file mode 100644 index 00000000..4d1b5a15 --- /dev/null +++ b/issues/630/src/main.rs @@ -0,0 +1,32 @@ +use std::collections::HashMap; + +// use sea_orm::sea_query::tests_cfg::json; +use sea_orm::{ConnectOptions, Database, EntityTrait}; + +mod entity; +use entity::{underscores, underscores_workaround}; + +#[tokio::main] +async fn main() { + let url = option_env!("DATABASE_URL"); + if let Some(url) = url { + let opts = ConnectOptions::new(url.to_string()); + let conn = Database::connect(opts).await.unwrap(); + + let results = underscores::Entity::find().all(&conn).await; + dbg!(results); + + let results_workaround = underscores_workaround::Entity::find().all(&conn).await; + dbg!(results_workaround); + } + + let control = HashMap::from([ + ("a_b_c_d", 1i32), + ("a_b_c_dd", 2i32), + ("a_b_cc_d", 3i32), + ("a_bb_c_d", 4i32), + ("aa_b_c_d", 5i32), + ]); + // let control = json!(control); + dbg!(control); +} diff --git a/sea-orm-macros/src/derives/entity_model.rs b/sea-orm-macros/src/derives/entity_model.rs index bdb9c05a..61a45a43 100644 --- a/sea-orm-macros/src/derives/entity_model.rs +++ b/sea-orm-macros/src/derives/entity_model.rs @@ -1,5 +1,5 @@ use crate::util::{escape_rust_keyword, trim_starting_raw_identifier}; -use heck::CamelCase; +use heck::{CamelCase, SnakeCase}; use proc_macro2::{Ident, Span, TokenStream}; use quote::{quote, quote_spanned}; use syn::{ @@ -83,10 +83,9 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec) -> syn::Res if let Fields::Named(fields) = item_struct.fields { for field in fields.named { if let Some(ident) = &field.ident { - let mut field_name = Ident::new( - &trim_starting_raw_identifier(&ident).to_camel_case(), - Span::call_site(), - ); + let original_field_name = trim_starting_raw_identifier(&ident); + let mut field_name = + Ident::new(&original_field_name.to_camel_case(), Span::call_site()); let mut nullable = false; let mut default_value = None; @@ -95,7 +94,14 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec) -> syn::Res let mut ignore = false; let mut unique = false; let mut sql_type = None; - let mut column_name = None; + let mut column_name = if original_field_name + != original_field_name.to_camel_case().to_snake_case() + { + // `to_snake_case` was used to trim prefix and tailing underscore + Some(original_field_name.to_snake_case()) + } else { + None + }; let mut enum_name = None; let mut is_primary_key = false; // search for #[sea_orm(primary_key, auto_increment = false, column_type = "String(Some(255))", default_value = "new user", default_expr = "gen_random_uuid()", column_name = "name", enum_name = "Name", nullable, indexed, unique)]