diff --git a/editoast/editoast_derive/src/search.rs b/editoast/editoast_derive/src/search.rs index b00b076ac9f..aba01f9af3e 100644 --- a/editoast/editoast_derive/src/search.rs +++ b/editoast/editoast_derive/src/search.rs @@ -16,6 +16,8 @@ use syn::DeriveInput; )] struct SearchParams { table: String, + #[darling(default)] + distinct_on: Option, migration: Option, #[darling(default)] joins: String, @@ -165,6 +167,9 @@ pub fn expand_search(input: &DeriveInput) -> Result { let struct_name = &input.ident; let table = params.table; + let distinct_on = params + .distinct_on + .map_or_else(|| quote! { None }, |d| quote! { Some(#d.to_owned()) }); let joins = match params.joins { ref joins if !joins.is_empty() => quote! { Some(#joins.to_owned()) }, _ => quote! { None }, @@ -286,6 +291,7 @@ pub fn expand_search(input: &DeriveInput) -> Result { fn search_config() -> editoast_search::SearchConfig { editoast_search::SearchConfig { table: #table.to_owned(), + distinct_on: #distinct_on, joins: #joins, criterias: Vec::from([#criterias]), properties: Vec::from([#properties]), diff --git a/editoast/editoast_search/src/lib.rs b/editoast/editoast_search/src/lib.rs index 66af4d5c8b9..12eb62a576b 100644 --- a/editoast/editoast_search/src/lib.rs +++ b/editoast/editoast_search/src/lib.rs @@ -71,13 +71,17 @@ pub fn query_into_sql( } let where_expression = context.search_ast_to_sql(&ast)?; let table = &search_config.table; + let select = search_config.distinct_on.as_ref().map_or_else( + || "SELECT".to_owned(), + |columns| format!("SELECT DISTINCT ON {columns}"), + ); let joins = search_config.joins.as_ref().cloned().unwrap_or_default(); let result_columns = search_config.result_columns(); let mut bindings = Default::default(); let constraints = where_expression.to_sql(&mut bindings); let sql_code = format!( "WITH _RESULT AS ( - SELECT {result_columns} + {select} {result_columns} FROM {table} {joins} WHERE {constraints} diff --git a/editoast/editoast_search/src/search_object.rs b/editoast/editoast_search/src/search_object.rs index 266d221d42b..c55496b2e62 100644 --- a/editoast/editoast_search/src/search_object.rs +++ b/editoast/editoast_search/src/search_object.rs @@ -18,6 +18,7 @@ pub struct Property { pub struct SearchConfig { pub table: String, + pub distinct_on: Option, pub criterias: Vec, pub properties: Vec, pub joins: Option, diff --git a/editoast/src/views/search.rs b/editoast/src/views/search.rs index 9ae2c811cac..b4a2190f171 100644 --- a/editoast/src/views/search.rs +++ b/editoast/src/views/search.rs @@ -430,11 +430,11 @@ pub(super) struct SearchResultItemTrack { #[derive(Search, Serialize, ToSchema)] #[search( table = "search_operational_point", + distinct_on = "(infra_id, obj_id)", migration(src_table = "infra_object_operational_point"), joins = " INNER JOIN infra_object_operational_point AS OP ON OP.id = search_operational_point.id - INNER JOIN (SELECT DISTINCT ON (infra_id, obj_id) * FROM infra_layer_operational_point) - AS lay ON OP.obj_id = lay.obj_id AND OP.infra_id = lay.infra_id", + INNER JOIN infra_layer_operational_point AS lay ON OP.obj_id = lay.obj_id AND OP.infra_id = lay.infra_id", column( name = "obj_id", data_type = "varchar(255)",