Skip to content

Commit 115afa4

Browse files
authored
fix: In the prepare_condition function, if the value is hashable, only unique values are retained. (#2569)
* fix: In the prepare_condition function, if the value is hashable, only unique values are retained. * fix: import
1 parent 6a1f67a commit 115afa4

1 file changed

Lines changed: 70 additions & 3 deletions

File tree

src/query/loader.rs

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ use crate::{
44
};
55
use async_trait::async_trait;
66
use 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`]
1013
pub trait EntityOrSelect<E: EntityTrait>: Send {
@@ -399,8 +402,13 @@ where
399402
}
400403

401404
fn 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

Comments
 (0)