@@ -27,6 +27,8 @@ pub(super) struct FromQueryResultItem {
2727 pub typ : ItemType ,
2828 pub ident : Ident ,
2929 pub alias : Option < String > ,
30+ pub field_type : syn:: Type ,
31+ pub prefix : bool ,
3032}
3133
3234/// Initially, we try to obtain the value for each field and check if it is an ordinary DB error
@@ -42,15 +44,26 @@ struct TryFromQueryResultCheck<'a>(bool, &'a FromQueryResultItem);
4244
4345impl ToTokens for TryFromQueryResultCheck < ' _ > {
4446 fn to_tokens ( & self , tokens : & mut TokenStream ) {
45- let FromQueryResultItem { ident, typ, alias } = self . 1 ;
47+ let FromQueryResultItem {
48+ ident,
49+ typ,
50+ alias,
51+ field_type,
52+ ..
53+ } = self . 1 ;
4654
4755 match typ {
4856 ItemType :: Flat => {
4957 let name = alias
5058 . to_owned ( )
5159 . unwrap_or_else ( || ident. unraw ( ) . to_string ( ) ) ;
60+ let prefix_to_use = if alias. is_some ( ) {
61+ quote ! { "" }
62+ } else {
63+ quote ! { pre }
64+ } ;
5265 tokens. extend ( quote ! {
53- let #ident = match row. try_get_nullable( pre , #name) {
66+ let #ident = match row. try_get_nullable( #prefix_to_use , #name) {
5467 Err ( v @ sea_orm:: TryGetError :: DbErr ( _) ) => {
5568 return Err ( v) ;
5669 }
@@ -64,14 +77,32 @@ impl ToTokens for TryFromQueryResultCheck<'_> {
6477 } ) ;
6578 }
6679 ItemType :: Nested => {
67- let prefix = if self . 0 {
80+ let prefix_str = if self . 1 . prefix {
6881 let name = ident. unraw ( ) . to_string ( ) ;
6982 quote ! { & format!( "{pre}{}_" , #name) }
83+ } else if self . 0 {
84+ let is_option = if let syn:: Type :: Path ( type_path) = field_type {
85+ type_path
86+ . path
87+ . segments
88+ . last ( )
89+ . map ( |seg| seg. ident == "Option" )
90+ . unwrap_or ( false )
91+ } else {
92+ false
93+ } ;
94+
95+ if is_option {
96+ let name = ident. unraw ( ) . to_string ( ) ;
97+ quote ! { & format!( "{pre}{}_" , #name) }
98+ } else {
99+ quote ! { pre }
100+ }
70101 } else {
71102 quote ! { pre }
72103 } ;
73104 tokens. extend ( quote ! {
74- let #ident = match sea_orm:: FromQueryResult :: from_query_result_nullable( row, #prefix ) {
105+ let #ident = match sea_orm:: FromQueryResult :: from_query_result_nullable( row, #prefix_str ) {
75106 Err ( v @ sea_orm:: TryGetError :: DbErr ( _) ) => {
76107 return Err ( v) ;
77108 }
@@ -87,14 +118,45 @@ struct TryFromQueryResultAssignment<'a>(&'a FromQueryResultItem);
87118
88119impl ToTokens for TryFromQueryResultAssignment < ' _ > {
89120 fn to_tokens ( & self , tokens : & mut TokenStream ) {
90- let FromQueryResultItem { ident, typ, .. } = self . 0 ;
121+ let FromQueryResultItem {
122+ ident,
123+ typ,
124+ field_type,
125+ ..
126+ } = self . 0 ;
91127
92128 match typ {
93- ItemType :: Flat | ItemType :: Nested => {
129+ ItemType :: Flat => {
94130 tokens. extend ( quote ! {
95131 #ident: #ident?,
96132 } ) ;
97133 }
134+ ItemType :: Nested => {
135+ let is_option = if let syn:: Type :: Path ( type_path) = field_type {
136+ type_path
137+ . path
138+ . segments
139+ . last ( )
140+ . map ( |seg| seg. ident == "Option" )
141+ . unwrap_or ( false )
142+ } else {
143+ false
144+ } ;
145+
146+ if is_option {
147+ tokens. extend ( quote ! {
148+ #ident: match #ident {
149+ Ok ( v) => Some ( v) ,
150+ Err ( sea_orm:: TryGetError :: Null ( _) ) => None ,
151+ Err ( e) => return Err ( e) ,
152+ } ,
153+ } ) ;
154+ } else {
155+ tokens. extend ( quote ! {
156+ #ident: #ident?,
157+ } ) ;
158+ }
159+ }
98160 ItemType :: Skip => {
99161 tokens. extend ( quote ! {
100162 #ident,
@@ -125,6 +187,7 @@ impl DeriveFromQueryResult {
125187 for parsed_field in parsed_fields {
126188 let mut typ = ItemType :: Flat ;
127189 let mut alias = None ;
190+ let mut prefix = false ;
128191 for attr in parsed_field. attrs . iter ( ) {
129192 if !attr. path ( ) . is_ident ( "sea_orm" ) {
130193 continue ;
@@ -136,6 +199,8 @@ impl DeriveFromQueryResult {
136199 typ = ItemType :: Skip ;
137200 } else if meta. exists ( "nested" ) {
138201 typ = ItemType :: Nested ;
202+ } else if meta. exists ( "prefix" ) {
203+ prefix = true ;
139204 } else if let Some ( alias_) = meta. get_as_kv ( "from_alias" ) {
140205 alias = Some ( alias_) ;
141206 } else {
@@ -145,7 +210,14 @@ impl DeriveFromQueryResult {
145210 }
146211 }
147212 let ident = format_ident ! ( "{}" , parsed_field. ident. unwrap( ) . to_string( ) ) ;
148- fields. push ( FromQueryResultItem { typ, ident, alias } ) ;
213+ let field_type = parsed_field. ty ;
214+ fields. push ( FromQueryResultItem {
215+ typ,
216+ ident,
217+ alias,
218+ field_type,
219+ prefix,
220+ } ) ;
149221 }
150222
151223 Ok ( Self {
0 commit comments