diff --git a/crates/dump/src/reader/compat/v5_to_v6.rs b/crates/dump/src/reader/compat/v5_to_v6.rs index b4a4fcb24..14570c258 100644 --- a/crates/dump/src/reader/compat/v5_to_v6.rs +++ b/crates/dump/src/reader/compat/v5_to_v6.rs @@ -1,3 +1,4 @@ +use std::num::NonZeroUsize; use std::str::FromStr; use super::v4_to_v5::{CompatIndexV4ToV5, CompatV4ToV5}; @@ -388,7 +389,13 @@ impl From> for v6::Settings { }, pagination: match settings.pagination { v5::Setting::Set(pagination) => v6::Setting::Set(v6::PaginationSettings { - max_total_hits: pagination.max_total_hits.into(), + max_total_hits: match pagination.max_total_hits { + v5::Setting::Set(max_total_hits) => v6::Setting::Set( + max_total_hits.try_into().unwrap_or(NonZeroUsize::new(1).unwrap()), + ), + v5::Setting::Reset => v6::Setting::Reset, + v5::Setting::NotSet => v6::Setting::NotSet, + }, }), v5::Setting::Reset => v6::Setting::Reset, v5::Setting::NotSet => v6::Setting::NotSet, diff --git a/crates/meilisearch-types/src/settings.rs b/crates/meilisearch-types/src/settings.rs index ccf0d75ee..edb136567 100644 --- a/crates/meilisearch-types/src/settings.rs +++ b/crates/meilisearch-types/src/settings.rs @@ -132,7 +132,7 @@ pub struct PaginationSettings { #[serde(default, skip_serializing_if = "Setting::is_not_set")] #[deserr(default)] #[schema(value_type = Option, example = json!(250))] - pub max_total_hits: Setting, + pub max_total_hits: Setting, } impl MergeWithError for DeserrJsonError { @@ -748,7 +748,7 @@ pub fn apply_settings_to_builder( match pagination { Setting::Set(ref value) => match value.max_total_hits { - Setting::Set(val) => builder.set_pagination_max_total_hits(val), + Setting::Set(val) => builder.set_pagination_max_total_hits(val.into()), Setting::Reset => builder.reset_pagination_max_total_hits(), Setting::NotSet => (), }, @@ -867,8 +867,8 @@ pub fn settings( max_total_hits: Setting::Set( index .pagination_max_total_hits(rtxn)? - .map(|x| x as usize) - .unwrap_or(DEFAULT_PAGINATION_MAX_TOTAL_HITS), + .and_then(|x| (x as usize).try_into().ok()) + .unwrap_or(NonZeroUsize::new(DEFAULT_PAGINATION_MAX_TOTAL_HITS).unwrap()), ), }; diff --git a/crates/meilisearch/src/routes/indexes/settings_analytics.rs b/crates/meilisearch/src/routes/indexes/settings_analytics.rs index cb5983f02..41df91966 100644 --- a/crates/meilisearch/src/routes/indexes/settings_analytics.rs +++ b/crates/meilisearch/src/routes/indexes/settings_analytics.rs @@ -454,7 +454,9 @@ pub struct PaginationAnalytics { impl PaginationAnalytics { pub fn new(setting: Option<&PaginationSettings>) -> Self { - Self { max_total_hits: setting.as_ref().and_then(|s| s.max_total_hits.set()) } + Self { + max_total_hits: setting.as_ref().and_then(|s| s.max_total_hits.set().map(|x| x.into())), + } } pub fn into_settings(self) -> SettingsAnalytics { diff --git a/crates/meilisearch/tests/settings/errors.rs b/crates/meilisearch/tests/settings/errors.rs index 4220cdbf8..6654a95a4 100644 --- a/crates/meilisearch/tests/settings/errors.rs +++ b/crates/meilisearch/tests/settings/errors.rs @@ -338,6 +338,47 @@ async fn settings_bad_pagination() { "###); } +#[actix_rt::test] +async fn settings_bad_max_total_hits() { + let server = Server::new_shared(); + let index = server.unique_index(); + + let (response, code) = + index.update_settings(json!({ "pagination": { "maxTotalHits": "doggo" } })).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Invalid value type at `.pagination.maxTotalHits`: expected a positive integer, but found a string: `\"doggo\"`", + "code": "invalid_settings_pagination", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid_settings_pagination" + } + "###); + + let (response, code) = + index.update_settings_pagination(json!({ "maxTotalHits": "doggo" } )).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r#" + { + "message": "Invalid value type at `.maxTotalHits`: expected a positive integer, but found a string: `\"doggo\"`", + "code": "invalid_settings_pagination", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid_settings_pagination" + } + "#); + + let (response, code) = index.update_settings_pagination(json!({ "maxTotalHits": 0 } )).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r#" + { + "message": "Invalid value at `.maxTotalHits`: a non-zero integer value lower than `18446744073709551615` was expected, but found a zero", + "code": "invalid_settings_pagination", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid_settings_pagination" + } + "#); +} + #[actix_rt::test] async fn settings_bad_search_cutoff_ms() { let server = Server::new_shared();