diff --git a/filter_parser/Cargo.toml b/filter_parser/Cargo.toml index 80767d5c4..2bdb3316a 100644 --- a/filter_parser/Cargo.toml +++ b/filter_parser/Cargo.toml @@ -8,3 +8,4 @@ edition = "2021" [dependencies] nom = "7.0.0" nom_locate = "4.0.0" +nom-greedyerror = "0.4.0" diff --git a/filter_parser/src/lib.rs b/filter_parser/src/lib.rs index 007817655..7153c5361 100644 --- a/filter_parser/src/lib.rs +++ b/filter_parser/src/lib.rs @@ -24,17 +24,19 @@ use nom::branch::alt; use nom::bytes::complete::tag; use nom::character::complete::{char, multispace0}; use nom::combinator::map; -use nom::error::{ContextError, Error, VerboseError}; +use nom::error::{ContextError, Error, ErrorKind, VerboseError}; use nom::multi::{many0, separated_list1}; use nom::number::complete::recognize_float; use nom::sequence::{delimited, preceded, tuple}; use nom::{Finish, IResult}; +use nom_greedyerror::GreedyError; use nom_locate::LocatedSpan; pub(crate) use value::parse_value; pub type Span<'a> = LocatedSpan<&'a str>; pub trait FilterParserError<'a>: nom::error::ParseError> + ContextError> {} +impl<'a> FilterParserError<'a> for GreedyError, ErrorKind> {} impl<'a> FilterParserError<'a> for VerboseError> {} impl<'a> FilterParserError<'a> for Error> {} diff --git a/milli/Cargo.toml b/milli/Cargo.toml index 3fc53492f..1aaeed008 100644 --- a/milli/Cargo.toml +++ b/milli/Cargo.toml @@ -41,6 +41,7 @@ uuid = { version = "0.8.2", features = ["v4"] } # facet filter parser filter_parser = { path = "../filter_parser" } nom = "7.0.0" +nom-greedyerror = "0.4.0" # documents words self-join itertools = "0.10.0" diff --git a/milli/src/search/facet/filter_condition.rs b/milli/src/search/facet/filter_condition.rs index 50caf4eac..fca35ff4d 100644 --- a/milli/src/search/facet/filter_condition.rs +++ b/milli/src/search/facet/filter_condition.rs @@ -2,10 +2,11 @@ use std::fmt::Debug; use std::ops::Bound::{self, Excluded, Included}; use either::Either; -use filter_parser::{Condition, FilterCondition, Span, Token}; +use filter_parser::{Condition, FilterCondition, FilterParserError, Span, Token}; use heed::types::DecodeIgnore; use log::debug; -use nom::error::{convert_error, VerboseError}; +use nom::error::{ErrorKind, VerboseError}; +use nom_greedyerror::{convert_error, GreedyError}; use roaring::RoaringBitmap; use super::FacetNumberRange; @@ -20,12 +21,14 @@ pub struct Filter<'a> { condition: FilterCondition<'a>, } +impl<'a> From>> for Error { + fn from(nom_error: VerboseError>) -> Self { + UserError::InvalidFilter { input: nom_error.to_string() }.into() + } +} + impl<'a> Filter<'a> { - pub fn from_array( - rtxn: &heed::RoTxn, - index: &Index, - array: I, - ) -> Result>> + pub fn from_array(array: I) -> Result> where I: IntoIterator>, J: IntoIterator, @@ -37,8 +40,7 @@ impl<'a> Filter<'a> { Either::Left(array) => { let mut ors = None; for rule in array { - let condition = - FilterCondition::parse::>(rule.as_ref()).unwrap(); + let condition = Self::from_str(rule.as_ref())?.condition; ors = match ors.take() { Some(ors) => { Some(FilterCondition::Or(Box::new(ors), Box::new(condition))) @@ -57,8 +59,7 @@ impl<'a> Filter<'a> { } } Either::Right(rule) => { - let condition = - FilterCondition::parse::>(rule.as_ref()).unwrap(); + let condition = Self::from_str(rule.as_ref())?.condition; ands = match ands.take() { Some(ands) => { Some(FilterCondition::And(Box::new(ands), Box::new(condition))) @@ -69,29 +70,16 @@ impl<'a> Filter<'a> { } } - Ok(ands) + Ok(ands.map(|ands| Self { condition: ands })) } - pub fn from_str(rtxn: &heed::RoTxn, index: &Index, expression: &'a str) -> Result { - let fields_ids_map = index.fields_ids_map(rtxn)?; - let filterable_fields = index.filterable_fields(rtxn)?; - // TODO TAMO - let condition = FilterCondition::parse::>(expression).ok().unwrap(); - /* - let condition = match FilterCondition::parse::>(expression) { + pub fn from_str(expression: &'a str) -> Result { + let condition = match FilterCondition::parse::>(expression) { Ok(fc) => Ok(fc), - Err(e) => { - let ve = match e { - nom::Err::Error(x) => x, - nom::Err::Failure(x) => x, - _ => unreachable!(), - }; - Err(Error::UserError(UserError::InvalidFilter { - input: convert_error(Span::new(expression), ve).to_string(), - })) - } - }; - */ + Err(e) => Err(Error::UserError(UserError::InvalidFilter { + input: convert_error(Span::new(expression), e).to_string(), + })), + }?; Ok(Self { condition }) } } @@ -345,7 +333,8 @@ impl<'a> Filter<'a> { let rhs = Self::evaluate(&(rhs.as_ref().clone()).into(), rtxn, index)?; Ok(lhs & rhs) } - Empty => Ok(RoaringBitmap::new()), + FilterCondition::Empty => Ok(RoaringBitmap::new()), + _ => panic!("do the geosearch"), } } }