SeaQL / sea-orm

🐚 An async & dynamic ORM for Rust
https://www.sea-ql.org/SeaORM/
Apache License 2.0
6.56k stars 459 forks source link

Fixed the issue of losing Chinese characters when converting ORM fields when database field names contain Chinese characters #2200

Closed fswdev closed 2 months ago

fswdev commented 2 months ago

PR Info

Bug Fixes

Fixed the issue of losing Chinese characters when converting ORM fields when database field names contain Chinese characters For example:

-- ----------------------------
-- Table structure for t_truck_type
-- ----------------------------
DROP TABLE IF EXISTS `t_truck_type`;
CREATE TABLE `t_truck_type`  (
  `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
  `truck13整车` double NULL DEFAULT NULL COMMENT '车型',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `idx_t_City_deleted_at`(`deleted_at` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;

SET FOREIGN_KEY_CHECKS = 1;
//  
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "t_city")]
pub struct Model {
    #[sea_orm(primary_key)]
    pub id: u64,
    #[sea_orm(column_name = "truck13米整车", column_type = "Double", nullable)]
    pub truck13: Option<f64>,     // <---  **Error**
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}

impl ActiveModelBehavior for ActiveModel {}

//truck13整车 -> truck13      //Error
//truck13整车 -> truck13整车           //Correct

The cause of the problem:

On line 95 of the "crates/sea-orm-macros-0.12.15/src/derives/entity_model.rs" file: Thrown by calling the trait "to_uper_camel_case" of heck.

92                if let Some(ident) = &field.ident {
93                    let original_field_name = trim_starting_raw_identifier(ident);
94                    let mut field_name = Ident::new(
95--->                    &original_field_name.to_upper_camel_case(),
96                        Span::call_site(),
97                    );

Two solutions:

The first method:

Dependency between two files sea-orm-codegen/Cargo.toml sea-orm-macros/Cargo.toml [dependencies] heck = { version = "0.4", features = ["unicode"] }

conversion result :  "truck13整车 -> truck13_整_车"

Second method: (Recommended, the conversion result looks more reasonable)

Dependency between two files sea-orm-codegen/Cargo.toml sea-orm-macros/Cargo.toml [dependencies] heck = { version = "0.5.0"}

conversion result :  "truck13整车 ->truck13整车"
billy1624 commented 2 months ago

Hey @fswdev, thanks for the quick fix!

From the CHANGELOG. In v0.5, heck employ another way to determine the word boundaries to apply the word casing conversion. I guess that's why upgrading to v0.5 fix the issue?

  • Remove non-additive unicode feature. The library now uses char::is_alphanumeric instead of the unicode-segmentation library to determine word boundaries in all cases.

I support upgrading heck to v0.5. However, we need a more comprehensive testing before merging this PR.

tyt2y3 commented 2 months ago

@billy1624 where's the file containing the test cases for this macro?

@fswdev can you add some test cases there to ensure it will not break in the future?

fswdev commented 2 months ago

@billy1624 where's the file containing the test cases for this macro?

@fswdev can you add some test cases there to ensure it will not break in the future?

dear @tyt2y3 :

//Database structure (Show two examples of Chinese fields)
CREATE Table ` t truck type `(
    `Id ` bigint UNSIGNED NOT NULL AUTO-INCREMENT,
    `truck13整车 whole vehicle 'double NULL DEFAULT NULL COMMENT' model 1 ',
    `truck13配货 distribution 'double NULL DEFAULT NULL COMMENT' model 2 ',
    ......
)ENGINE=InnoDB AUTO-INCREMENT=1 CHARACTER SET=utf8mb4 COLLATE=utf8mb4:0900-ai_ci ROW-FORMAT=DYNAMIC;

//Generated RUST code
Use sea_orm:: entity:: prelude:: *;
#[derived (Clone, Debug, PartialEq, DeriveEntityModel)]//<-- The "DeriveEntityModel" macro can also cause errors
    #[sea_orm (tablename="tcity")]
    Pub struct model{
    #[sea_orm (primary_key)]
    Pub id: u64,
    #[sea_orm (columnname="truck13整车 whole vehicle", columntype="Double", nullable)]
    Pub truck13: Option<f64>,//<--- * * Error 1**
    #[sea_orm (columnname="truck13配货 distribution", columntype="Double", nullable)]
    Pub truck13: Option<f64>,//<--- * * Error 2**
}

I found two application scenarios affected by this bug

  1. sea orm cli: When using this command to generate entity, there will be abnormal conversion of Chinese fields in the database
  2. The 'DeriveEntityModel' macro will cause errors

I don't know how to do the test cases you mentioned, but if you can provide more details, I can try to do it (I am not particularly proficient in using Rust) :)