SeaQL / sea-orm

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

Entity generation fails if `model-extra-attributes` include a comma surrounded by parentheses #2063

Open naskya opened 8 months ago

naskya commented 8 months ago

Description

We can't seem to pass a string containing a comma surrounded by parentheses as model-extra-attributes in sea-orm-cli. This becomes a problem when you want to pass cfg_attr(predicate, attribute), for instance.

Steps to Reproduce

$ sea-orm-cli generate entity --model-extra-attributes 'test(a, b)' -u 'postgres://username:password@localhost/dbname'

Expected Behavior

Since the following does work and produces Models with #[test(a)], I guess test(a, b) should also work.

$ sea-orm-cli generate entity --model-extra-attributes 'test(a)' -u 'postgres://username:password@localhost/dbname'

Actual Behavior

$ RUST_BACKTRACE=1 sea-orm-cli generate entity --model-extra-attributes 'test(a, b)' -u 'postgres://username:password@localhost/dbname'

Connecting to Postgres ...
Discovering schema ...
... discovered.
thread 'main' panicked at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/sea-orm-codegen-0.12.10/src/entity/writer.rs:108:57:
called `Result::unwrap()` on an `Err` value: LexError { span: Span }
stack backtrace:
   0: rust_begin_unwind
             at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panicking.rs:597:5
   1: core::panicking::panic_fmt
             at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panicking.rs:72:14
   2: core::result::unwrap_failed
             at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/result.rs:1652:5
   3: <core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::fold
   4: sea_orm_codegen::entity::writer::EntityWriterContext::new
   5: sea_orm_cli::commands::generate::run_generate_command::{{closure}}
   6: async_std::task::task_locals_wrapper::TaskLocalsWrapper::set_current
   7: <futures_lite::future::Or<F1,F2> as core::future::future::Future>::poll
   8: async_io::driver::block_on
   9: async_global_executor::executor::block_on
  10: async_std::task::task_locals_wrapper::TaskLocalsWrapper::set_current
  11: async_std::task::builder::Builder::blocking
  12: sea_orm_cli::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

Reproduces How Often

This is always reproducible.

Workarounds

There's no workaround as far as I'm aware (except manual string processing for generated entities)

Reproducible Example

  1. Create a postgres database and a table
$ sudo -u postgres psql --command="CREATE DATABASE test_db OWNER postgres_user encoding = 'UTF8';"
$ sudo -u postgres psql --dbname=test_db --command='CREATE TABLE test_table ("test_column" character varying(32));'
  1. Generate entities
$ sea-orm-cli generate entity --model-extra-attributes 'test(a, b)' -u 'postgres://postgres_user:password/test_db'

Connecting to Postgres ...
Discovering schema ...
... discovered.
thread 'main' panicked at /home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/sea-orm-codegen-0.12.10/src/entity/writer.rs:108:57:
called `Result::unwrap()` on an `Err` value: LexError { span: Span }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Versions

$ cargo tree | grep sea    
├── sea-orm v0.12.10
│   ├── sea-orm-macros v0.12.10 (proc-macro)
│   │   ├── sea-bae v0.2.0 (proc-macro)
│   ├── sea-query v0.30.5
│   ├── sea-query-binder v0.5.0
│   │   ├── sea-query v0.30.5 (*)

$ psql --version
psql (PostgreSQL) 16.1
yexiyue commented 6 months ago

I also encountered the same problem

sea-orm-cli generate entity   -o entity/src -l -u postgres://postgres:postgres@localhost:22732/postgres 
--with-serde both  
--model-extra-attributes='graphql(concrete(name = "Favorite",params()))' 
--model-extra-derives async_graphql::SimpleObject

result

yexiyue@wisteriadeMacBook-Pro graphql-study % sea-orm-cli generate entity   -o entity/src -l -u postgres://postgres:postgres@localhost:22732/postgres --with-serde both --model-extra-attributes='graphql(concrete(name = "Favorite",params()))' --model-extra-derives async_graphql::SimpleObject                                               
Connecting to Postgres ...
Discovering schema ...
... discovered.
thread 'main' panicked at /Users/yexiyue/.cargo/registry/src/mirrors.sjtug.sjtu.edu.cn-be2141875385cea5/sea-orm-codegen-0.12.14/src/entity/writer.rs:108:57:
called `Result::unwrap()` on an `Err` value: LexError { span: Span }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

When I remove the comma before params, it can work properly

However, there are still spaces in front, which is not very aesthetically pleasing

//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.14

use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(
    Clone,
    Debug,
    PartialEq,
    DeriveEntityModel,
    Eq,
    Serialize,
    Deserialize,
    async_graphql :: SimpleObject,
)]
#[sea_orm(table_name = "favorite")]
#[graphql(concrete(name = "Favorite"params()))]
pub struct Model {
    #[sea_orm(primary_key, auto_increment = false)]
    pub user_id: i32,
    #[sea_orm(primary_key, auto_increment = false)]
    pub action_id: i32,
    pub create_time: Option<DateTime>,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
    #[sea_orm(
        belongs_to = "super::actions::Entity",
        from = "Column::ActionId",
        to = "super::actions::Column::Id",
        on_update = "Cascade",
        on_delete = "Cascade"
    )]
    Actions,
    #[sea_orm(
        belongs_to = "super::user::Entity",
        from = "Column::UserId",
        to = "super::user::Column::Id",
        on_update = "Cascade",
        on_delete = "Cascade"
    )]
    User,
}

impl Related<super::actions::Entity> for Entity {
    fn to() -> RelationDef {
        Relation::Actions.def()
    }
}

impl Related<super::user::Entity> for Entity {
    fn to() -> RelationDef {
        Relation::User.def()
    }
}

impl ActiveModelBehavior for ActiveModel {}
vmg-dev commented 6 months ago

I also encountered the same problem

sea-orm-cli generate entity   -o entity/src -l -u postgres://postgres:postgres@localhost:22732/postgres 
--with-serde both  
--model-extra-attributes='graphql(concrete(name = "Favorite",params()))' 
--model-extra-derives async_graphql::SimpleObject

result

yexiyue@wisteriadeMacBook-Pro graphql-study % sea-orm-cli generate entity   -o entity/src -l -u postgres://postgres:postgres@localhost:22732/postgres --with-serde both --model-extra-attributes='graphql(concrete(name = "Favorite",params()))' --model-extra-derives async_graphql::SimpleObject                                               
Connecting to Postgres ...
Discovering schema ...
... discovered.
thread 'main' panicked at /Users/yexiyue/.cargo/registry/src/mirrors.sjtug.sjtu.edu.cn-be2141875385cea5/sea-orm-codegen-0.12.14/src/entity/writer.rs:108:57:
called `Result::unwrap()` on an `Err` value: LexError { span: Span }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

When I remove the comma before params, it can work properly

However, there are still spaces in front, which is not very aesthetically pleasing

//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.14

use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(
    Clone,
    Debug,
    PartialEq,
    DeriveEntityModel,
    Eq,
    Serialize,
    Deserialize,
    async_graphql :: SimpleObject,
)]
#[sea_orm(table_name = "favorite")]
#[graphql(concrete(name = "Favorite"params()))]
pub struct Model {
    #[sea_orm(primary_key, auto_increment = false)]
    pub user_id: i32,
    #[sea_orm(primary_key, auto_increment = false)]
    pub action_id: i32,
    pub create_time: Option<DateTime>,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
    #[sea_orm(
        belongs_to = "super::actions::Entity",
        from = "Column::ActionId",
        to = "super::actions::Column::Id",
        on_update = "Cascade",
        on_delete = "Cascade"
    )]
    Actions,
    #[sea_orm(
        belongs_to = "super::user::Entity",
        from = "Column::UserId",
        to = "super::user::Column::Id",
        on_update = "Cascade",
        on_delete = "Cascade"
    )]
    User,
}

impl Related<super::actions::Entity> for Entity {
    fn to() -> RelationDef {
        Relation::Actions.def()
    }
}

impl Related<super::user::Entity> for Entity {
    fn to() -> RelationDef {
        Relation::User.def()
    }
}

impl ActiveModelBehavior for ActiveModel {}

Removing the comma also doesn't allow the generated code to be compiled