From c5aa63e282eded7231f66fb6aa562c30ba9fbc51 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 11 Jul 2022 23:11:04 +0800 Subject: [PATCH] Generate entity files with PostgreSQL's schema name (#422) * feat(codegen): generate entity files with PostgreSQL's schema name * Ignore schema name `public` * Restore changes * Fix test cases * cargo fmt * [cli] fixup --- sea-orm-cli/src/commands.rs | 21 +- sea-orm-codegen/src/entity/writer.rs | 269 +++++++++++++----- .../tests/compact_with_schema_name/cake.rs | 35 +++ .../compact_with_schema_name/cake_filling.rs | 46 +++ .../tests/compact_with_schema_name/filling.rs | 31 ++ .../tests/compact_with_schema_name/fruit.rs | 38 +++ .../tests/compact_with_schema_name/mod.rs | 9 + .../tests/compact_with_schema_name/prelude.rs | 7 + .../compact_with_schema_name/rust_keyword.rs | 64 +++++ .../tests/compact_with_schema_name/vendor.rs | 32 +++ .../tests/expanded_with_schema_name/cake.rs | 81 ++++++ .../expanded_with_schema_name/cake_filling.rs | 87 ++++++ .../expanded_with_schema_name/filling.rs | 71 +++++ .../tests/expanded_with_schema_name/fruit.rs | 86 ++++++ .../tests/expanded_with_schema_name/mod.rs | 9 + .../expanded_with_schema_name/prelude.rs | 7 + .../expanded_with_schema_name/rust_keyword.rs | 129 +++++++++ .../tests/expanded_with_schema_name/vendor.rs | 80 ++++++ 18 files changed, 1029 insertions(+), 73 deletions(-) create mode 100644 sea-orm-codegen/tests/compact_with_schema_name/cake.rs create mode 100644 sea-orm-codegen/tests/compact_with_schema_name/cake_filling.rs create mode 100644 sea-orm-codegen/tests/compact_with_schema_name/filling.rs create mode 100644 sea-orm-codegen/tests/compact_with_schema_name/fruit.rs create mode 100644 sea-orm-codegen/tests/compact_with_schema_name/mod.rs create mode 100644 sea-orm-codegen/tests/compact_with_schema_name/prelude.rs create mode 100644 sea-orm-codegen/tests/compact_with_schema_name/rust_keyword.rs create mode 100644 sea-orm-codegen/tests/compact_with_schema_name/vendor.rs create mode 100644 sea-orm-codegen/tests/expanded_with_schema_name/cake.rs create mode 100644 sea-orm-codegen/tests/expanded_with_schema_name/cake_filling.rs create mode 100644 sea-orm-codegen/tests/expanded_with_schema_name/filling.rs create mode 100644 sea-orm-codegen/tests/expanded_with_schema_name/fruit.rs create mode 100644 sea-orm-codegen/tests/expanded_with_schema_name/mod.rs create mode 100644 sea-orm-codegen/tests/expanded_with_schema_name/prelude.rs create mode 100644 sea-orm-codegen/tests/expanded_with_schema_name/rust_keyword.rs create mode 100644 sea-orm-codegen/tests/expanded_with_schema_name/vendor.rs diff --git a/sea-orm-cli/src/commands.rs b/sea-orm-cli/src/commands.rs index 5b393645..70b13d01 100644 --- a/sea-orm-cli/src/commands.rs +++ b/sea-orm-cli/src/commands.rs @@ -1,7 +1,8 @@ use chrono::Local; use regex::Regex; use sea_orm_codegen::{ - EntityTransformer, EntityWriterContext, OutputFile, WithSerde, DateTimeCrate as CodegenDateTimeCrate, + DateTimeCrate as CodegenDateTimeCrate, EntityTransformer, EntityWriterContext, OutputFile, + WithSerde, }; use std::{error::Error, fmt::Display, fs, io::Write, path::Path, process::Command, str::FromStr}; use tracing_subscriber::{prelude::*, EnvFilter}; @@ -109,7 +110,7 @@ pub async fn run_generate_command( Default::default() }; - let table_stmts = match url.scheme() { + let (schema_name, table_stmts) = match url.scheme() { "mysql" => { use sea_schema::mysql::discovery::SchemaDiscovery; use sqlx::MySql; @@ -117,14 +118,15 @@ pub async fn run_generate_command( let connection = connect::(max_connections, url.as_str()).await?; let schema_discovery = SchemaDiscovery::new(connection, database_name); let schema = schema_discovery.discover().await; - schema + let table_stmts = schema .tables .into_iter() .filter(|schema| filter_tables(&schema.info.name)) .filter(|schema| filter_hidden_tables(&schema.info.name)) .filter(|schema| filter_skip_tables(&schema.info.name)) .map(|schema| schema.write()) - .collect() + .collect(); + (None, table_stmts) } "sqlite" => { use sea_schema::sqlite::discovery::SchemaDiscovery; @@ -133,14 +135,15 @@ pub async fn run_generate_command( let connection = connect::(max_connections, url.as_str()).await?; let schema_discovery = SchemaDiscovery::new(connection); let schema = schema_discovery.discover().await?; - schema + let table_stmts = schema .tables .into_iter() .filter(|schema| filter_tables(&schema.name)) .filter(|schema| filter_hidden_tables(&schema.name)) .filter(|schema| filter_skip_tables(&schema.name)) .map(|schema| schema.write()) - .collect() + .collect(); + (None, table_stmts) } "postgres" | "postgresql" => { use sea_schema::postgres::discovery::SchemaDiscovery; @@ -150,14 +153,15 @@ pub async fn run_generate_command( let connection = connect::(max_connections, url.as_str()).await?; let schema_discovery = SchemaDiscovery::new(connection, schema); let schema = schema_discovery.discover().await; - schema + let table_stmts = schema .tables .into_iter() .filter(|schema| filter_tables(&schema.info.name)) .filter(|schema| filter_hidden_tables(&schema.info.name)) .filter(|schema| filter_skip_tables(&schema.info.name)) .map(|schema| schema.write()) - .collect() + .collect(); + (Some(schema.schema), table_stmts) } _ => unimplemented!("{} is not supported", url.scheme()), }; @@ -166,6 +170,7 @@ pub async fn run_generate_command( expanded_format, WithSerde::from_str(&with_serde).unwrap(), date_time_crate.into(), + schema_name, ); let output = EntityTransformer::transform(table_stmts)?.generate(&writer_context); diff --git a/sea-orm-codegen/src/entity/writer.rs b/sea-orm-codegen/src/entity/writer.rs index 720e7791..4d9817a0 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -40,6 +40,7 @@ pub struct EntityWriterContext { pub(crate) expanded_format: bool, pub(crate) with_serde: WithSerde, pub(crate) date_time_crate: DateTimeCrate, + pub(crate) schema_name: Option, } impl WithSerde { @@ -97,11 +98,13 @@ impl EntityWriterContext { expanded_format: bool, with_serde: WithSerde, date_time_crate: DateTimeCrate, + schema_name: Option, ) -> Self { Self { expanded_format, with_serde, date_time_crate, + schema_name, } } } @@ -141,12 +144,14 @@ impl EntityWriter { entity, &context.with_serde, &context.date_time_crate, + &context.schema_name, ) } else { Self::gen_compact_code_blocks( entity, &context.with_serde, &context.date_time_crate, + &context.schema_name, ) }; Self::write(&mut lines, code_blocks); @@ -235,13 +240,14 @@ impl EntityWriter { entity: &Entity, with_serde: &WithSerde, date_time_crate: &DateTimeCrate, + schema_name: &Option, ) -> Vec { let mut imports = Self::gen_import(with_serde); imports.extend(Self::gen_import_active_enum(entity)); let mut code_blocks = vec![ imports, Self::gen_entity_struct(), - Self::gen_impl_entity_name(entity), + Self::gen_impl_entity_name(entity, schema_name), Self::gen_model_struct(entity, with_serde, date_time_crate), Self::gen_column_enum(entity), Self::gen_primary_key_enum(entity), @@ -260,12 +266,13 @@ impl EntityWriter { entity: &Entity, with_serde: &WithSerde, date_time_crate: &DateTimeCrate, + schema_name: &Option, ) -> Vec { let mut imports = Self::gen_import(with_serde); imports.extend(Self::gen_import_active_enum(entity)); let mut code_blocks = vec![ imports, - Self::gen_compact_model_struct(entity, with_serde, date_time_crate), + Self::gen_compact_model_struct(entity, with_serde, date_time_crate, schema_name), ]; let relation_defs = if entity.get_relation_enum_name().is_empty() { vec![ @@ -319,13 +326,25 @@ impl EntityWriter { } } - pub fn gen_impl_entity_name(entity: &Entity) -> TokenStream { + pub fn gen_impl_entity_name(entity: &Entity, schema_name: &Option) -> TokenStream { + let schema_name = match Self::gen_schema_name(schema_name) { + Some(schema_name) => quote! { + fn schema_name(&self) -> Option<&str> { + Some(#schema_name) + } + }, + None => quote! {}, + }; let table_name = entity.table_name.as_str(); + let table_name = quote! { + fn table_name(&self) -> &str { + #table_name + } + }; quote! { impl EntityName for Entity { - fn table_name(&self) -> &str { - #table_name - } + #schema_name + #table_name } } } @@ -533,6 +552,7 @@ impl EntityWriter { entity: &Entity, with_serde: &WithSerde, date_time_crate: &DateTimeCrate, + schema_name: &Option, ) -> TokenStream { let table_name = entity.table_name.as_str(); let column_names_snake_case = entity.get_column_names_snake_case(); @@ -582,12 +602,20 @@ impl EntityWriter { } }) .collect(); - + let schema_name = match Self::gen_schema_name(schema_name) { + Some(schema_name) => quote! { + schema_name = #schema_name, + }, + None => quote! {}, + }; let extra_derive = with_serde.extra_derive(); quote! { #[derive(Clone, Debug, PartialEq, DeriveEntityModel #extra_derive)] - #[sea_orm(table_name = #table_name)] + #[sea_orm( + #schema_name + table_name = #table_name + )] pub struct Model { #( #attrs @@ -610,6 +638,19 @@ impl EntityWriter { } } } + + pub fn gen_schema_name(schema_name: &Option) -> Option { + match schema_name { + Some(schema_name) => { + if schema_name != "public" { + Some(quote! { #schema_name }) + } else { + None + } + } + None => None, + } + } } #[cfg(test)] @@ -621,7 +662,7 @@ mod tests { use pretty_assertions::assert_eq; use proc_macro2::TokenStream; use sea_query::{ColumnType, ForeignKeyAction}; - use std::io::{self, BufRead, BufReader}; + use std::io::{self, BufRead, BufReader, Read}; fn setup() -> Vec { vec![ @@ -985,6 +1026,24 @@ mod tests { ] } + fn parse_from_file(inner: R) -> io::Result + where + R: Read, + { + let mut reader = BufReader::new(inner); + let mut lines: Vec = Vec::new(); + + reader.read_until(b';', &mut Vec::new())?; + + let mut line = String::new(); + while reader.read_line(&mut line)? > 0 { + lines.push(line.to_owned()); + line.clear(); + } + let content = lines.join(""); + Ok(content.parse().unwrap()) + } + #[test] fn test_gen_expanded_code_blocks() -> io::Result<()> { let entities = setup(); @@ -996,34 +1055,66 @@ mod tests { include_str!("../../tests/expanded/vendor.rs"), include_str!("../../tests/expanded/rust_keyword.rs"), ]; + const ENTITY_FILES_WITH_SCHEMA_NAME: [&str; 6] = [ + include_str!("../../tests/expanded_with_schema_name/cake.rs"), + include_str!("../../tests/expanded_with_schema_name/cake_filling.rs"), + include_str!("../../tests/expanded_with_schema_name/filling.rs"), + include_str!("../../tests/expanded_with_schema_name/fruit.rs"), + include_str!("../../tests/expanded_with_schema_name/vendor.rs"), + include_str!("../../tests/expanded_with_schema_name/rust_keyword.rs"), + ]; assert_eq!(entities.len(), ENTITY_FILES.len()); for (i, entity) in entities.iter().enumerate() { - let mut reader = BufReader::new(ENTITY_FILES[i].as_bytes()); - let mut lines: Vec = Vec::new(); - - reader.read_until(b';', &mut Vec::new())?; - - let mut line = String::new(); - while reader.read_line(&mut line)? > 0 { - lines.push(line.to_owned()); - line.clear(); - } - let content = lines.join(""); - let expected: TokenStream = content.parse().unwrap(); - let generated = EntityWriter::gen_expanded_code_blocks( - entity, - &crate::WithSerde::None, - &crate::DateTimeCrate::Chrono, - ) - .into_iter() - .skip(1) - .fold(TokenStream::new(), |mut acc, tok| { - acc.extend(tok); - acc - }); - assert_eq!(expected.to_string(), generated.to_string()); + assert_eq!( + parse_from_file(ENTITY_FILES[i].as_bytes())?.to_string(), + EntityWriter::gen_expanded_code_blocks( + entity, + &crate::WithSerde::None, + &crate::DateTimeCrate::Chrono, + &None + ) + .into_iter() + .skip(1) + .fold(TokenStream::new(), |mut acc, tok| { + acc.extend(tok); + acc + }) + .to_string() + ); + assert_eq!( + parse_from_file(ENTITY_FILES[i].as_bytes())?.to_string(), + EntityWriter::gen_expanded_code_blocks( + entity, + &crate::WithSerde::None, + &crate::DateTimeCrate::Chrono, + &Some("public".to_owned()) + ) + .into_iter() + .skip(1) + .fold(TokenStream::new(), |mut acc, tok| { + acc.extend(tok); + acc + }) + .to_string() + ); + assert_eq!( + parse_from_file(ENTITY_FILES_WITH_SCHEMA_NAME[i].as_bytes())?.to_string(), + EntityWriter::gen_expanded_code_blocks( + entity, + &crate::WithSerde::None, + &crate::DateTimeCrate::Chrono, + &Some("schema_name".to_owned()) + ) + .into_iter() + .skip(1) + .fold(TokenStream::new(), |mut acc, tok| { + acc.extend(tok); + acc + }) + .to_string() + ); } Ok(()) @@ -1040,34 +1131,66 @@ mod tests { include_str!("../../tests/compact/vendor.rs"), include_str!("../../tests/compact/rust_keyword.rs"), ]; + const ENTITY_FILES_WITH_SCHEMA_NAME: [&str; 6] = [ + include_str!("../../tests/compact_with_schema_name/cake.rs"), + include_str!("../../tests/compact_with_schema_name/cake_filling.rs"), + include_str!("../../tests/compact_with_schema_name/filling.rs"), + include_str!("../../tests/compact_with_schema_name/fruit.rs"), + include_str!("../../tests/compact_with_schema_name/vendor.rs"), + include_str!("../../tests/compact_with_schema_name/rust_keyword.rs"), + ]; assert_eq!(entities.len(), ENTITY_FILES.len()); for (i, entity) in entities.iter().enumerate() { - let mut reader = BufReader::new(ENTITY_FILES[i].as_bytes()); - let mut lines: Vec = Vec::new(); - - reader.read_until(b';', &mut Vec::new())?; - - let mut line = String::new(); - while reader.read_line(&mut line)? > 0 { - lines.push(line.to_owned()); - line.clear(); - } - let content = lines.join(""); - let expected: TokenStream = content.parse().unwrap(); - let generated = EntityWriter::gen_compact_code_blocks( - entity, - &crate::WithSerde::None, - &crate::DateTimeCrate::Chrono, - ) - .into_iter() - .skip(1) - .fold(TokenStream::new(), |mut acc, tok| { - acc.extend(tok); - acc - }); - assert_eq!(expected.to_string(), generated.to_string()); + assert_eq!( + parse_from_file(ENTITY_FILES[i].as_bytes())?.to_string(), + EntityWriter::gen_compact_code_blocks( + entity, + &crate::WithSerde::None, + &crate::DateTimeCrate::Chrono, + &None + ) + .into_iter() + .skip(1) + .fold(TokenStream::new(), |mut acc, tok| { + acc.extend(tok); + acc + }) + .to_string() + ); + assert_eq!( + parse_from_file(ENTITY_FILES[i].as_bytes())?.to_string(), + EntityWriter::gen_compact_code_blocks( + entity, + &crate::WithSerde::None, + &crate::DateTimeCrate::Chrono, + &Some("public".to_owned()) + ) + .into_iter() + .skip(1) + .fold(TokenStream::new(), |mut acc, tok| { + acc.extend(tok); + acc + }) + .to_string() + ); + assert_eq!( + parse_from_file(ENTITY_FILES_WITH_SCHEMA_NAME[i].as_bytes())?.to_string(), + EntityWriter::gen_compact_code_blocks( + entity, + &crate::WithSerde::None, + &crate::DateTimeCrate::Chrono, + &Some("schema_name".to_owned()) + ) + .into_iter() + .skip(1) + .fold(TokenStream::new(), |mut acc, tok| { + acc.extend(tok); + acc + }) + .to_string() + ); } Ok(()) @@ -1085,6 +1208,7 @@ mod tests { &( include_str!("../../tests/compact_with_serde/cake_none.rs").into(), WithSerde::None, + None, ), Box::new(EntityWriter::gen_compact_code_blocks), )?; @@ -1093,6 +1217,7 @@ mod tests { &( include_str!("../../tests/compact_with_serde/cake_serialize.rs").into(), WithSerde::Serialize, + None, ), Box::new(EntityWriter::gen_compact_code_blocks), )?; @@ -1101,6 +1226,7 @@ mod tests { &( include_str!("../../tests/compact_with_serde/cake_deserialize.rs").into(), WithSerde::Deserialize, + None, ), Box::new(EntityWriter::gen_compact_code_blocks), )?; @@ -1109,6 +1235,7 @@ mod tests { &( include_str!("../../tests/compact_with_serde/cake_both.rs").into(), WithSerde::Both, + None, ), Box::new(EntityWriter::gen_compact_code_blocks), )?; @@ -1119,6 +1246,7 @@ mod tests { &( include_str!("../../tests/expanded_with_serde/cake_none.rs").into(), WithSerde::None, + None, ), Box::new(EntityWriter::gen_expanded_code_blocks), )?; @@ -1127,6 +1255,7 @@ mod tests { &( include_str!("../../tests/expanded_with_serde/cake_serialize.rs").into(), WithSerde::Serialize, + None, ), Box::new(EntityWriter::gen_expanded_code_blocks), )?; @@ -1135,6 +1264,7 @@ mod tests { &( include_str!("../../tests/expanded_with_serde/cake_deserialize.rs").into(), WithSerde::Deserialize, + None, ), Box::new(EntityWriter::gen_expanded_code_blocks), )?; @@ -1143,6 +1273,7 @@ mod tests { &( include_str!("../../tests/expanded_with_serde/cake_both.rs").into(), WithSerde::Both, + None, ), Box::new(EntityWriter::gen_expanded_code_blocks), )?; @@ -1150,10 +1281,13 @@ mod tests { Ok(()) } + #[allow(clippy::type_complexity)] fn assert_serde_variant_results( cake_entity: &Entity, - entity_serde_variant: &(String, WithSerde), - generator: Box Vec>, + entity_serde_variant: &(String, WithSerde, Option), + generator: Box< + dyn Fn(&Entity, &WithSerde, &DateTimeCrate, &Option) -> Vec, + >, ) -> io::Result<()> { let mut reader = BufReader::new(entity_serde_variant.0.as_bytes()); let mut lines: Vec = Vec::new(); @@ -1167,12 +1301,17 @@ mod tests { } let content = lines.join(""); let expected: TokenStream = content.parse().unwrap(); - let generated = generator(cake_entity, &entity_serde_variant.1, &DateTimeCrate::Chrono) - .into_iter() - .fold(TokenStream::new(), |mut acc, tok| { - acc.extend(tok); - acc - }); + let generated = generator( + cake_entity, + &entity_serde_variant.1, + &DateTimeCrate::Chrono, + &entity_serde_variant.2, + ) + .into_iter() + .fold(TokenStream::new(), |mut acc, tok| { + acc.extend(tok); + acc + }); assert_eq!(expected.to_string(), generated.to_string()); Ok(()) diff --git a/sea-orm-codegen/tests/compact_with_schema_name/cake.rs b/sea-orm-codegen/tests/compact_with_schema_name/cake.rs new file mode 100644 index 00000000..d2efb986 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_schema_name/cake.rs @@ -0,0 +1,35 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(schema_name = "schema_name", table_name = "cake")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + #[sea_orm(column_type = "Text", nullable)] + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::fruit::Entity")] + Fruit, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/compact_with_schema_name/cake_filling.rs b/sea-orm-codegen/tests/compact_with_schema_name/cake_filling.rs new file mode 100644 index 00000000..a9704a8a --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_schema_name/cake_filling.rs @@ -0,0 +1,46 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(schema_name = "schema_name", table_name = "_cake_filling_")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub cake_id: i32, + #[sea_orm(primary_key, auto_increment = false)] + pub filling_id: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::cake::Entity", + from = "Column::CakeId", + to = "super::cake::Column::Id", + on_update = "Cascade", + on_delete = "Cascade", + )] + Cake, + #[sea_orm( + belongs_to = "super::filling::Entity", + from = "Column::FillingId", + to = "super::filling::Column::Id", + on_update = "Cascade", + on_delete = "Cascade", + )] + Filling, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Cake.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Filling.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/compact_with_schema_name/filling.rs b/sea-orm-codegen/tests/compact_with_schema_name/filling.rs new file mode 100644 index 00000000..94795811 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_schema_name/filling.rs @@ -0,0 +1,31 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(schema_name = "schema_name", table_name = "filling")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub name: String, +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation {} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + panic!("No RelationDef") + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Cake.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Filling.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/compact_with_schema_name/fruit.rs b/sea-orm-codegen/tests/compact_with_schema_name/fruit.rs new file mode 100644 index 00000000..28104324 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_schema_name/fruit.rs @@ -0,0 +1,38 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(schema_name = "schema_name", table_name = "fruit")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub name: String, + pub cake_id: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::cake::Entity", + from = "Column::CakeId", + to = "super::cake::Column::Id", + )] + Cake, + #[sea_orm(has_many = "super::vendor::Entity")] + Vendor, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Cake.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Vendor.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/compact_with_schema_name/mod.rs b/sea-orm-codegen/tests/compact_with_schema_name/mod.rs new file mode 100644 index 00000000..5a8c6c21 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_schema_name/mod.rs @@ -0,0 +1,9 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +pub mod prelude; + +pub mod cake; +pub mod cake_filling; +pub mod filling; +pub mod fruit; +pub mod vendor; diff --git a/sea-orm-codegen/tests/compact_with_schema_name/prelude.rs b/sea-orm-codegen/tests/compact_with_schema_name/prelude.rs new file mode 100644 index 00000000..b4e85c78 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_schema_name/prelude.rs @@ -0,0 +1,7 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +pub use super::cake::Entity as Cake; +pub use super::cake_filling::Entity as CakeFilling; +pub use super::filling::Entity as Filling; +pub use super::fruit::Entity as Fruit; +pub use super::vendor::Entity as Vendor; diff --git a/sea-orm-codegen/tests/compact_with_schema_name/rust_keyword.rs b/sea-orm-codegen/tests/compact_with_schema_name/rust_keyword.rs new file mode 100644 index 00000000..f3ca0314 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_schema_name/rust_keyword.rs @@ -0,0 +1,64 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(schema_name = "schema_name", table_name = "rust_keyword")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub testing: i8, + pub rust: u8, + pub keywords: i16, + pub r#type: u16, + pub r#typeof: i32, + pub crate_: u32, + pub self_: i64, + pub self_id1: u64, + pub self_id2: i32, + pub fruit_id1: i32, + pub fruit_id2: i32, + pub cake_id: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "Entity", + from = "Column::SelfId1", + to = "Column::Id", + )] + SelfRef1, + #[sea_orm( + belongs_to = "Entity", + from = "Column::SelfId2", + to = "Column::Id", + )] + SelfRef2, + #[sea_orm( + belongs_to = "super::fruit::Entity", + from = "Column::FruitId1", + to = "super::fruit::Column::Id", + )] + Fruit1, + #[sea_orm( + belongs_to = "super::fruit::Entity", + from = "Column::FruitId2", + to = "super::fruit::Column::Id", + )] + Fruit2, + #[sea_orm( + belongs_to = "super::cake::Entity", + from = "Column::CakeId", + to = "super::cake::Column::Id", + )] + Cake, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Cake.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/compact_with_schema_name/vendor.rs b/sea-orm-codegen/tests/compact_with_schema_name/vendor.rs new file mode 100644 index 00000000..85209c45 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_schema_name/vendor.rs @@ -0,0 +1,32 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(schema_name = "schema_name", table_name = "vendor")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + #[sea_orm(column_name = "_name_")] + pub name: String, + #[sea_orm(column_name = "fruitId")] + pub fruit_id: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::fruit::Entity", + from = "Column::FruitId", + to = "super::fruit::Column::Id", + )] + Fruit, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_schema_name/cake.rs b/sea-orm-codegen/tests/expanded_with_schema_name/cake.rs new file mode 100644 index 00000000..d37c2b08 --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_schema_name/cake.rs @@ -0,0 +1,81 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn schema_name(&self) -> Option< &str > { + Some("schema_name") + } + + fn table_name(&self) -> &str { + "cake" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub id: i32, + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Name, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + Id, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + + fn auto_increment() -> bool { + true + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Fruit, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Name => ColumnType::Text.def().null(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Fruit => Entity::has_many(super::fruit::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_schema_name/cake_filling.rs b/sea-orm-codegen/tests/expanded_with_schema_name/cake_filling.rs new file mode 100644 index 00000000..cde112e7 --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_schema_name/cake_filling.rs @@ -0,0 +1,87 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn schema_name(&self) -> Option< &str > { + Some("schema_name") + } + + fn table_name(&self) -> &str { + "_cake_filling_" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub cake_id: i32, + pub filling_id: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + CakeId, + FillingId, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + CakeId, + FillingId, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = (i32, i32); + + fn auto_increment() -> bool { + false + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Cake, + Filling, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::CakeId => ColumnType::Integer.def(), + Self::FillingId => ColumnType::Integer.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Cake => Entity::belongs_to(super::cake::Entity) + .from(Column::CakeId) + .to(super::cake::Column::Id) + .into(), + Self::Filling => Entity::belongs_to(super::filling::Entity) + .from(Column::FillingId) + .to(super::filling::Column::Id) + .into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Cake.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Filling.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_schema_name/filling.rs b/sea-orm-codegen/tests/expanded_with_schema_name/filling.rs new file mode 100644 index 00000000..eb9005fb --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_schema_name/filling.rs @@ -0,0 +1,71 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn schema_name(&self) -> Option< &str > { + Some("schema_name") + } + + fn table_name(&self) -> &str { + "filling" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub id: i32, + pub name: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Name, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + Id, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + + fn auto_increment() -> bool { + true + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation {} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Name => ColumnType::String(Some(255u32)).def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + panic!("No RelationDef") + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Cake.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Filling.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_schema_name/fruit.rs b/sea-orm-codegen/tests/expanded_with_schema_name/fruit.rs new file mode 100644 index 00000000..2b554f6e --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_schema_name/fruit.rs @@ -0,0 +1,86 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn schema_name(&self) -> Option< &str > { + Some("schema_name") + } + + fn table_name(&self) -> &str { + "fruit" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub id: i32, + pub name: String, + pub cake_id: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Name, + CakeId, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + Id, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + + fn auto_increment() -> bool { + true + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Cake, + Vendor, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Name => ColumnType::String(Some(255u32)).def(), + Self::CakeId => ColumnType::Integer.def().null(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Cake => Entity::belongs_to(super::cake::Entity) + .from(Column::CakeId) + .to(super::cake::Column::Id) + .into(), + Self::Vendor => Entity::has_many(super::vendor::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Cake.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Vendor.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_schema_name/mod.rs b/sea-orm-codegen/tests/expanded_with_schema_name/mod.rs new file mode 100644 index 00000000..5a8c6c21 --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_schema_name/mod.rs @@ -0,0 +1,9 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +pub mod prelude; + +pub mod cake; +pub mod cake_filling; +pub mod filling; +pub mod fruit; +pub mod vendor; diff --git a/sea-orm-codegen/tests/expanded_with_schema_name/prelude.rs b/sea-orm-codegen/tests/expanded_with_schema_name/prelude.rs new file mode 100644 index 00000000..b4e85c78 --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_schema_name/prelude.rs @@ -0,0 +1,7 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +pub use super::cake::Entity as Cake; +pub use super::cake_filling::Entity as CakeFilling; +pub use super::filling::Entity as Filling; +pub use super::fruit::Entity as Fruit; +pub use super::vendor::Entity as Vendor; diff --git a/sea-orm-codegen/tests/expanded_with_schema_name/rust_keyword.rs b/sea-orm-codegen/tests/expanded_with_schema_name/rust_keyword.rs new file mode 100644 index 00000000..faa8310f --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_schema_name/rust_keyword.rs @@ -0,0 +1,129 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn schema_name(&self) -> Option< &str > { + Some("schema_name") + } + + fn table_name(&self) -> &str { + "rust_keyword" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub id: i32, + pub testing: i8, + pub rust: u8, + pub keywords: i16, + pub r#type: u16, + pub r#typeof: i32, + pub crate_: u32, + pub self_: i64, + pub self_id1: u64, + pub self_id2: i32, + pub fruit_id1: i32, + pub fruit_id2: i32, + pub cake_id: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Testing, + Rust, + Keywords, + Type, + Typeof, + Crate, + Self_, + SelfId1, + SelfId2, + FruitId1, + FruitId2, + CakeId, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + Id, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + + fn auto_increment() -> bool { + true + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + SelfRef1, + SelfRef2, + Fruit1, + Fruit2, + Cake, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Testing => ColumnType::TinyInteger.def(), + Self::Rust => ColumnType::TinyUnsigned.def(), + Self::Keywords => ColumnType::SmallInteger.def(), + Self::Type => ColumnType::SmallUnsigned.def(), + Self::Typeof => ColumnType::Integer.def(), + Self::Crate => ColumnType::Unsigned.def(), + Self::Self_ => ColumnType::BigInteger.def(), + Self::SelfId1 => ColumnType::BigUnsigned.def(), + Self::SelfId2 => ColumnType::Integer.def(), + Self::FruitId1 => ColumnType::Integer.def(), + Self::FruitId2 => ColumnType::Integer.def(), + Self::CakeId => ColumnType::Integer.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::SelfRef1 => Entity::belongs_to(Entity) + .from(Column::SelfId1) + .to(Column::Id) + .into(), + Self::SelfRef2 => Entity::belongs_to(Entity) + .from(Column::SelfId2) + .to(Column::Id) + .into(), + Self::Fruit1 => Entity::belongs_to(super::fruit::Entity) + .from(Column::FruitId1) + .to(super::fruit::Column::Id) + .into(), + Self::Fruit2 => Entity::belongs_to(super::fruit::Entity) + .from(Column::FruitId2) + .to(super::fruit::Column::Id) + .into(), + Self::Cake => Entity::belongs_to(super::cake::Entity) + .from(Column::CakeId) + .to(super::cake::Column::Id) + .into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Cake.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_schema_name/vendor.rs b/sea-orm-codegen/tests/expanded_with_schema_name/vendor.rs new file mode 100644 index 00000000..fd3be27e --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_schema_name/vendor.rs @@ -0,0 +1,80 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn schema_name(&self) -> Option< &str > { + Some("schema_name") + } + + fn table_name(&self) -> &str { + "vendor" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub id: i32, + pub name: String, + pub fruit_id: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + #[sea_orm(column_name = "_name_")] + Name, + #[sea_orm(column_name = "fruitId")] + FruitId, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + Id, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + + fn auto_increment() -> bool { + true + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Fruit, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Name => ColumnType::String(Some(255u32)).def(), + Self::FruitId => ColumnType::Integer.def().null(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Fruit => Entity::belongs_to(super::fruit::Entity) + .from(Column::FruitId) + .to(super::fruit::Column::Id) + .into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl ActiveModelBehavior for ActiveModel {}