@@ -4,7 +4,10 @@ use crate::{
44} ;
55use async_trait:: async_trait;
66use sea_query:: { ColumnRef , DynIden , Expr , IntoColumnRef , SimpleExpr , TableRef , ValueTuple } ;
7- use std:: { collections:: HashMap , str:: FromStr } ;
7+ use std:: {
8+ collections:: { HashMap , HashSet } ,
9+ str:: FromStr ,
10+ } ;
811
912/// Entity, or a Select<Entity>; to be used as parameters in [`LoaderTrait`]
1013pub trait EntityOrSelect < E : EntityTrait > : Send {
@@ -399,8 +402,13 @@ where
399402}
400403
401404fn prepare_condition ( table : & TableRef , col : & Identity , keys : & [ ValueTuple ] ) -> Condition {
402- // TODO when value is hashable, retain only unique values
403- let keys = keys. to_owned ( ) ;
405+ let keys = if !keys. is_empty ( ) {
406+ let set: HashSet < _ > = keys. iter ( ) . cloned ( ) . collect ( ) ;
407+ set. into_iter ( ) . collect ( )
408+ } else {
409+ Vec :: new ( )
410+ } ;
411+
404412 match col {
405413 Identity :: Unary ( column_a) => {
406414 let column_a = table_column ( table, column_a) ;
@@ -688,4 +696,63 @@ mod tests {
688696
689697 assert_eq ! ( fillings, empty_vec) ;
690698 }
699+
700+ #[ tokio:: test]
701+ async fn test_load_one_duplicate_keys ( ) {
702+ use sea_orm:: { entity:: prelude:: * , tests_cfg:: * , DbBackend , LoaderTrait , MockDatabase } ;
703+
704+ let db = MockDatabase :: new ( DbBackend :: Postgres )
705+ . append_query_results ( [ [ cake_model ( 1 ) , cake_model ( 2 ) ] ] )
706+ . into_connection ( ) ;
707+
708+ let fruits = vec ! [
709+ fruit_model( 1 , Some ( 1 ) ) ,
710+ fruit_model( 2 , Some ( 1 ) ) ,
711+ fruit_model( 3 , Some ( 1 ) ) ,
712+ fruit_model( 4 , Some ( 1 ) ) ,
713+ ] ;
714+
715+ let cakes = fruits
716+ . load_one ( cake:: Entity :: find ( ) , & db)
717+ . await
718+ . expect ( "Should return something" ) ;
719+
720+ assert_eq ! ( cakes. len( ) , 4 ) ;
721+ for cake in & cakes {
722+ assert_eq ! ( cake, & Some ( cake_model( 1 ) ) ) ;
723+ }
724+ let logs = db. into_transaction_log ( ) ;
725+ let sql = format ! ( "{:?}" , logs[ 0 ] ) ;
726+
727+ let values_count = sql. matches ( "$1" ) . count ( ) ;
728+ assert_eq ! ( values_count, 1 , "Duplicate values were not removed" ) ;
729+ }
730+
731+ #[ tokio:: test]
732+ async fn test_load_many_duplicate_keys ( ) {
733+ use sea_orm:: { entity:: prelude:: * , tests_cfg:: * , DbBackend , LoaderTrait , MockDatabase } ;
734+
735+ let db = MockDatabase :: new ( DbBackend :: Postgres )
736+ . append_query_results ( [ [
737+ fruit_model ( 1 , Some ( 1 ) ) ,
738+ fruit_model ( 2 , Some ( 1 ) ) ,
739+ fruit_model ( 3 , Some ( 2 ) ) ,
740+ ] ] )
741+ . into_connection ( ) ;
742+
743+ let cakes = vec ! [ cake_model( 1 ) , cake_model( 1 ) , cake_model( 2 ) , cake_model( 2 ) ] ;
744+
745+ let fruits = cakes
746+ . load_many ( fruit:: Entity :: find ( ) , & db)
747+ . await
748+ . expect ( "Should return something" ) ;
749+
750+ assert_eq ! ( fruits. len( ) , 4 ) ;
751+
752+ let logs = db. into_transaction_log ( ) ;
753+ let sql = format ! ( "{:?}" , logs[ 0 ] ) ;
754+
755+ let values_count = sql. matches ( "$1" ) . count ( ) + sql. matches ( "$2" ) . count ( ) ;
756+ assert_eq ! ( values_count, 2 , "Duplicate values were not removed" ) ;
757+ }
691758}
0 commit comments