diff --git a/milli/src/search/facet/filter_condition.rs b/milli/src/search/facet/filter_condition.rs index c6dbbf056..a36fddb01 100644 --- a/milli/src/search/facet/filter_condition.rs +++ b/milli/src/search/facet/filter_condition.rs @@ -595,6 +595,18 @@ fn field_id( ) -> StdResult, PestError> { // lexing ensures that we at least have a key let key = items.next().unwrap(); + if key.as_rule() == Rule::reserved { + return Err(PestError::new_from_span( + ErrorVariant::CustomError { + message: format!( + "`{}` is a reserved keyword and thus can't be used as a filter expression. Available filterable attributes are: {}", + key.as_str(), + filterable_fields.iter().join(", "), + ), + }, + key.as_span(), + )); + } if !filterable_fields.contains(key.as_str()) { return Err(PestError::new_from_span( @@ -671,6 +683,13 @@ mod tests { let condition = FilterCondition::from_str(&rtxn, &index, "NOT channel = ponce").unwrap(); let expected = Operator(0, Operator::NotEqual(None, S("ponce"))); assert_eq!(condition, expected); + + let result = FilterCondition::from_str(&rtxn, &index, "_geo = France"); + assert!(result.is_err()); + let error = result.unwrap_err(); + assert!(error.to_string().contains( + "`_geo` is a reserved keyword and thus can't be used as a filter expression." + )); } #[test] diff --git a/milli/src/search/facet/grammar.pest b/milli/src/search/facet/grammar.pest index 8285f81a6..d07d5bca5 100644 --- a/milli/src/search/facet/grammar.pest +++ b/milli/src/search/facet/grammar.pest @@ -1,5 +1,5 @@ -key = _{quoted | word} -value = _{quoted | word} +key = _{reserved | quoted | word } +value = _{quoted | word } quoted = _{ (PUSH("'") | PUSH("\"")) ~ string ~ POP } string = {char*} word = ${(LETTER | NUMBER | "_" | "-" | ".")+} @@ -8,8 +8,9 @@ char = _{ !(PEEK | "\\") ~ ANY | "\\" ~ (PEEK | "\\" | "/" | "b" | "f" | "n" | "r" | "t") | "\\" ~ ("u" ~ ASCII_HEX_DIGIT{4})} +reserved = { "_geo" | "_geoDistance" | "_geoPoint" | ("_geoPoint" ~ parameters) } // we deliberately choose to allow empty parameters to generate more specific error message later -parameters ={("(" ~ (value ~ ",")* ~ value? ~ ")") | ""} +parameters = {("(" ~ (value ~ ",")* ~ value? ~ ")") | ""} condition = _{between | eq | greater | less | geq | leq | neq} between = {key ~ value ~ "TO" ~ value} geq = {key ~ ">=" ~ value}