@@ -11,7 +11,9 @@ use syn::{
1111/// Method to derive an Model
1212pub fn expand_derive_entity_model ( data : & Data , attrs : & [ Attribute ] ) -> syn:: Result < TokenStream > {
1313 // if #[sea_orm(table_name = "foo", schema_name = "bar")] specified, create Entity struct
14+ // if #[sea_orm(table_name = "foo", view)] specified, create a View entity (read-only)
1415 let mut table_name = None ;
16+ let mut is_view = false ;
1517 let mut comment = quote ! { None } ;
1618 let mut schema_name = quote ! { None } ;
1719 let mut table_iden = false ;
@@ -28,6 +30,8 @@ pub fn expand_derive_entity_model(data: &Data, attrs: &[Attribute]) -> syn::Resu
2830 comment = quote ! { Some ( #name) } ;
2931 } else if meta. path . is_ident ( "table_name" ) {
3032 table_name = Some ( meta. value ( ) ?. parse :: < LitStr > ( ) ?) ;
33+ } else if meta. path . is_ident ( "view" ) {
34+ is_view = true ;
3135 } else if meta. path . is_ident ( "schema_name" ) {
3236 let name: Lit = meta. value ( ) ?. parse ( ) ?;
3337 schema_name = quote ! { Some ( #name) } ;
@@ -48,32 +52,92 @@ pub fn expand_derive_entity_model(data: &Data, attrs: &[Attribute]) -> syn::Resu
4852 } )
4953 } ) ?;
5054
51- let entity_def = table_name
55+ if is_view && table_name. is_none ( ) {
56+ return Err ( syn:: Error :: new (
57+ Span :: call_site ( ) ,
58+ "Attribute `view` requires `table_name` to be specified, e.g. #[sea_orm(table_name = \" foo\" , view)]." ,
59+ ) ) ;
60+ }
61+
62+ let entity_name = table_name. clone ( ) ;
63+
64+ // TODO: Add registry support to views
65+
66+ let entity_def = entity_name
5267 . as_ref ( )
53- . map ( |table_name| {
54- let entity_extra_attr = if model_ex {
55- quote ! ( #[ sea_orm( model_ex = ModelEx , active_model_ex = ActiveModelEx ) ] )
56- } else {
57- quote ! ( )
58- } ;
59- quote ! {
60- #[ doc = " Generated by sea-orm-macros" ]
61- #[ derive( Copy , Clone , Default , Debug , sea_orm:: prelude:: DeriveEntity ) ]
62- #entity_extra_attr
63- pub struct Entity ;
64-
65- #[ automatically_derived]
66- impl sea_orm:: prelude:: EntityName for Entity {
67- fn schema_name( & self ) -> Option <& str > {
68- #schema_name
68+ . map ( |name| {
69+ if is_view {
70+ quote ! {
71+ #[ doc = " Generated by sea-orm-macros" ]
72+ #[ derive( Copy , Clone , Default , Debug ) ]
73+ pub struct Entity ;
74+
75+ #[ automatically_derived]
76+ impl sea_orm:: prelude:: EntityName for Entity {
77+ fn schema_name( & self ) -> Option <& str > {
78+ #schema_name
79+ }
80+
81+ fn table_name( & self ) -> & ' static str {
82+ #name
83+ }
84+
85+ fn comment( & self ) -> Option <& str > {
86+ #comment
87+ }
88+ }
89+
90+ #[ automatically_derived]
91+ impl sea_orm:: prelude:: Iden for Entity {
92+ fn unquoted( & self ) -> & str {
93+ #name
94+ }
6995 }
7096
71- fn table_name( & self ) -> & ' static str {
72- #table_name
97+ #[ automatically_derived]
98+ impl sea_orm:: prelude:: IdenStatic for Entity {
99+ fn as_str( & self ) -> & ' static str {
100+ #name
101+ }
102+ }
103+
104+ #[ automatically_derived]
105+ impl sea_orm:: prelude:: EntityTrait for Entity {
106+ type Model = Model ;
107+ type ModelEx = Model ;
108+ type ActiveModel = sea_orm:: NeverActiveModel <Entity >;
109+ type ActiveModelEx = sea_orm:: NeverActiveModel <Entity >;
110+ type Column = Column ;
111+ type PrimaryKey = PrimaryKey ;
112+ type Relation = Relation ;
73113 }
114+ }
115+ } else {
116+ // Generate regular Entity (implements EntityTrait)
117+ let entity_extra_attr = if model_ex {
118+ quote ! ( #[ sea_orm( model_ex = ModelEx , active_model_ex = ActiveModelEx ) ] )
119+ } else {
120+ quote ! ( )
121+ } ;
122+ quote ! {
123+ #[ doc = "Generated by sea-orm-macros" ]
124+ #[ derive( Copy , Clone , Default , Debug , sea_orm:: prelude:: DeriveEntity ) ]
125+ #entity_extra_attr
126+ pub struct Entity ;
127+
128+ #[ automatically_derived]
129+ impl sea_orm:: prelude:: EntityName for Entity {
130+ fn schema_name( & self ) -> Option <& str > {
131+ #schema_name
132+ }
74133
75- fn comment( & self ) -> Option <& str > {
76- #comment
134+ fn table_name( & self ) -> & ' static str {
135+ #name
136+ }
137+
138+ fn comment( & self ) -> Option <& str > {
139+ #comment
140+ }
77141 }
78142 }
79143 }
@@ -90,11 +154,11 @@ pub fn expand_derive_entity_model(data: &Data, attrs: &[Attribute]) -> syn::Resu
90154 let mut primary_key_types: Punctuated < _ , Comma > = Punctuated :: new ( ) ;
91155 let mut auto_increment = true ;
92156 if table_iden {
93- if let Some ( table_name ) = & table_name {
157+ if let Some ( name ) = & entity_name {
94158 let table_field_name = Ident :: new ( "Table" , Span :: call_site ( ) ) ;
95159 columns_enum. push ( quote ! {
96160 #[ doc = " Generated by sea-orm-macros" ]
97- #[ sea_orm( table_name=#table_name ) ]
161+ #[ sea_orm( table_name=#name ) ]
98162 #[ strum( disabled) ]
99163 #table_field_name
100164 } ) ;
@@ -403,7 +467,13 @@ pub fn expand_derive_entity_model(data: &Data, attrs: &[Attribute]) -> syn::Resu
403467 columns_save_as. push_punct ( Comma :: default ( ) ) ;
404468 }
405469
406- let primary_key = {
470+ let primary_key = if is_view && primary_keys. is_empty ( ) {
471+ // Views may not have primary keys; use NeverPrimaryKey to satisfy EntityTrait bounds.
472+ quote ! {
473+ #[ doc = " Generated by sea-orm-macros" ]
474+ pub type PrimaryKey = sea_orm:: NeverPrimaryKey <Column >;
475+ }
476+ } else {
407477 let auto_increment = auto_increment && primary_keys. len ( ) == 1 ;
408478 let primary_key_types = if primary_key_types. len ( ) == 1 {
409479 let first = primary_key_types. first ( ) ;
0 commit comments