@@ -40,8 +40,9 @@ mod magnet {
4040 impl ActiveModelBehavior for ActiveModel { }
4141}
4242
43- mod mixed {
43+ pub mod mixed {
4444 use super :: * ;
45+ use sea_orm_migration:: prelude:: * ;
4546
4647 #[ derive( Clone , Debug , PartialEq , DeriveEntityModel ) ]
4748 #[ sea_orm( table_name = "mixed" ) ]
@@ -61,9 +62,7 @@ mod mixed {
6162 impl ActiveModelBehavior for ActiveModel { }
6263
6364 pub mod migration {
64- use sea_orm_migration:: prelude:: * ;
65-
66- mod m20251115_01_mixed {
65+ pub mod m20251115_01_mixed {
6766 use sea_orm_migration:: { prelude:: * , schema:: * } ;
6867
6968 #[ derive( DeriveMigrationName ) ]
@@ -100,13 +99,83 @@ mod mixed {
10099 Magnet ,
101100 }
102101 }
102+ }
103+
104+ pub struct Migrator ;
105+
106+ #[ async_trait:: async_trait]
107+ impl MigratorTrait for Migrator {
108+ fn migrations ( ) -> Vec < Box < dyn MigrationTrait > > {
109+ vec ! [ Box :: new( migration:: m20251115_01_mixed:: Migration ) ]
110+ }
111+ }
112+ }
113+
114+ pub mod optional_mixed {
115+ use super :: * ;
116+
117+ #[ derive( Clone , Debug , PartialEq , DeriveEntityModel ) ]
118+ #[ sea_orm( table_name = "optional_mixed" ) ]
119+ pub struct Model {
120+ #[ sea_orm( primary_key) ]
121+ pub id : i32 ,
122+ pub torrent_id : Option < TorrentID > ,
123+ pub magnet : Option < MagnetLink > ,
124+ }
125+
126+ #[ derive( Copy , Clone , Debug , EnumIter , DeriveRelation ) ]
127+ pub enum Relation { }
128+
129+ #[ async_trait:: async_trait]
130+ impl ActiveModelBehavior for ActiveModel { }
131+
132+ pub mod migration {
133+ use sea_orm_migration:: prelude:: * ;
134+
135+ pub mod m20251118_01_optional_mixed {
136+ use sea_orm_migration:: { prelude:: * , schema:: * } ;
137+
138+ #[ derive( DeriveMigrationName ) ]
139+ pub struct Migration ;
140+
141+ #[ async_trait:: async_trait]
142+ impl MigrationTrait for Migration {
143+ async fn up ( & self , manager : & SchemaManager ) -> Result < ( ) , DbErr > {
144+ manager
145+ . create_table (
146+ Table :: create ( )
147+ . table ( OptionalMixed :: Table )
148+ . if_not_exists ( )
149+ . col ( pk_auto ( OptionalMixed :: Id ) )
150+ . col ( string ( OptionalMixed :: TorrentID ) )
151+ . col ( string ( OptionalMixed :: Magnet ) )
152+ . to_owned ( ) ,
153+ )
154+ . await
155+ }
156+
157+ async fn down ( & self , manager : & SchemaManager ) -> Result < ( ) , DbErr > {
158+ manager
159+ . drop_table ( Table :: drop ( ) . table ( OptionalMixed :: Table ) . to_owned ( ) )
160+ . await
161+ }
162+ }
163+
164+ #[ derive( DeriveIden ) ]
165+ enum OptionalMixed {
166+ Table ,
167+ Id ,
168+ TorrentID ,
169+ Magnet ,
170+ }
171+ }
103172
104173 pub struct Migrator ;
105174
106175 #[ async_trait:: async_trait]
107176 impl MigratorTrait for Migrator {
108177 fn migrations ( ) -> Vec < Box < dyn MigrationTrait > > {
109- vec ! [ Box :: new( m20251115_01_mixed :: Migration ) ]
178+ vec ! [ Box :: new( m20251118_01_optional_mixed :: Migration ) ]
110179 }
111180 }
112181 }
@@ -143,13 +212,13 @@ async fn test_torrent_real_db() {
143212 use sea_orm_migration:: * ;
144213
145214 let tmpdir = async_tempfile:: TempDir :: new ( ) . await . unwrap ( ) ;
146- let sqlite = tmpdir. join ( "db .sqlite" ) ;
215+ let sqlite = tmpdir. join ( "mixed .sqlite" ) ;
147216 let sqlite_str = sqlite. to_str ( ) . unwrap ( ) ;
148217
149218 let db = sea_orm:: Database :: connect ( & format ! ( "sqlite://{}?mode=rwc" , sqlite_str) )
150219 . await
151220 . unwrap ( ) ;
152- mixed:: migration :: Migrator :: up ( & db, None ) . await . unwrap ( ) ;
221+ mixed:: Migrator :: up ( & db, None ) . await . unwrap ( ) ;
153222
154223 let magnet =
155224 MagnetLink :: new ( & std:: fs:: read_to_string ( "tests/bittorrent-v2-test.magnet" ) . unwrap ( ) )
@@ -237,3 +306,75 @@ async fn test_torrent_real_db() {
237306 assert ! ( found_one) ;
238307 assert ! ( found_two) ;
239308}
309+
310+ #[ tokio:: test]
311+ async fn test_torrent_real_optional_none ( ) {
312+ use sea_orm_migration:: * ;
313+
314+ let tmpdir = async_tempfile:: TempDir :: new ( ) . await . unwrap ( ) ;
315+ let sqlite = tmpdir. join ( "optional_mixed_none.sqlite" ) ;
316+ let sqlite_str = sqlite. to_str ( ) . unwrap ( ) ;
317+
318+ let db = sea_orm:: Database :: connect ( & format ! ( "sqlite://{}?mode=rwc" , sqlite_str) )
319+ . await
320+ . unwrap ( ) ;
321+ optional_mixed:: migration:: Migrator :: up ( & db, None )
322+ . await
323+ . unwrap ( ) ;
324+
325+ // Try with None
326+ let model = optional_mixed:: ActiveModel {
327+ torrent_id : Set ( None ) ,
328+ magnet : Set ( None ) ,
329+ ..Default :: default ( )
330+ }
331+ . save ( & db)
332+ . await
333+ . unwrap ( ) ;
334+
335+ let nonactive_model = model. try_into_model ( ) . unwrap ( ) ;
336+ let saved_model = optional_mixed:: Entity :: find ( )
337+ . filter ( optional_mixed:: Column :: Magnet . eq ( Option :: < MagnetLink > :: None ) )
338+ . one ( & db)
339+ . await
340+ . unwrap ( )
341+ . unwrap ( ) ;
342+ assert_eq ! ( saved_model. magnet. as_ref( ) , None ) ;
343+ assert_eq ! ( nonactive_model. magnet. as_ref( ) , None ) ;
344+ }
345+
346+ #[ tokio:: test]
347+ async fn test_torrent_real_optional_notset ( ) {
348+ use sea_orm_migration:: * ;
349+
350+ let tmpdir = async_tempfile:: TempDir :: new ( ) . await . unwrap ( ) ;
351+ let sqlite = tmpdir. join ( "optional_mixed_none.sqlite" ) ;
352+ let sqlite_str = sqlite. to_str ( ) . unwrap ( ) ;
353+
354+ let db = sea_orm:: Database :: connect ( & format ! ( "sqlite://{}?mode=rwc" , sqlite_str) )
355+ . await
356+ . unwrap ( ) ;
357+ optional_mixed:: migration:: Migrator :: up ( & db, None )
358+ . await
359+ . unwrap ( ) ;
360+
361+ // Try with None
362+ let model = optional_mixed:: ActiveModel {
363+ torrent_id : NotSet ,
364+ magnet : NotSet ,
365+ ..Default :: default ( )
366+ }
367+ . save ( & db)
368+ . await
369+ . unwrap ( ) ;
370+
371+ let nonactive_model = model. try_into_model ( ) . unwrap ( ) ;
372+ let saved_model = optional_mixed:: Entity :: find ( )
373+ . filter ( optional_mixed:: Column :: Magnet . eq ( Option :: < MagnetLink > :: None ) )
374+ . one ( & db)
375+ . await
376+ . unwrap ( )
377+ . unwrap ( ) ;
378+ assert_eq ! ( saved_model. magnet. as_ref( ) , None ) ;
379+ assert_eq ! ( nonactive_model. magnet. as_ref( ) , None ) ;
380+ }
0 commit comments