diff --git a/crates/filter-parser/src/condition.rs b/crates/filter-parser/src/condition.rs index c407a1e45..8e3c04040 100644 --- a/crates/filter-parser/src/condition.rs +++ b/crates/filter-parser/src/condition.rs @@ -19,6 +19,7 @@ use Condition::*; use crate::error::IResultExt; use crate::value::parse_vector_value; +use crate::value::parse_vector_value_cut; use crate::Error; use crate::ErrorKind; use crate::VectorFilter; @@ -141,13 +142,13 @@ fn parse_vectors(input: Span) -> IResult<(Token, Option, VectorFilter<'_> } let (input, embedder_name) = - parse_vector_value(input).map_cut(ErrorKind::VectorFilterInvalidEmbedder)?; + parse_vector_value_cut(input, ErrorKind::VectorFilterInvalidEmbedder)?; let (input, filter) = alt(( map( preceded(tag(".fragments"), |input| { let (input, _) = tag(".")(input).map_cut(ErrorKind::VectorFilterMissingFragment)?; - parse_vector_value(input).map_cut(ErrorKind::VectorFilterInvalidFragment) + parse_vector_value_cut(input, ErrorKind::VectorFilterInvalidFragment) }), VectorFilter::Fragment, ), diff --git a/crates/filter-parser/src/error.rs b/crates/filter-parser/src/error.rs index 05aaf8c17..e381f45e2 100644 --- a/crates/filter-parser/src/error.rs +++ b/crates/filter-parser/src/error.rs @@ -79,6 +79,7 @@ pub enum ErrorKind<'a> { MisusedGeoRadius, MisusedGeoBoundingBox, VectorFilterLeftover, + VectorFilterInvalidQuotes, VectorFilterMissingEmbedder, VectorFilterInvalidEmbedder, VectorFilterMissingFragment, @@ -232,7 +233,7 @@ impl Display for Error<'_> { writeln!(f, "Vector filter can only accept one of `fragments`, `userProvided`, `documentTemplate` or `regenerate`, but found both `{previous_filter_kind}` and `{value}`.")? }, ErrorKind::VectorFilterInvalidFragment => { - writeln!(f, "The vector filter's fragment is invalid.")? + writeln!(f, "The vector filter's fragment name is invalid.")? } ErrorKind::VectorFilterMissingFragment => { writeln!(f, "The vector filter is missing a fragment name.")? @@ -246,6 +247,9 @@ impl Display for Error<'_> { ErrorKind::VectorFilterOperation => { writeln!(f, "Was expecting an operation like `EXISTS` or `NOT EXISTS` after the vector filter.")? } + ErrorKind::VectorFilterInvalidQuotes => { + writeln!(f, "The quotes in one of the values are inconsistent.")? + } ErrorKind::ReservedKeyword(word) => { writeln!(f, "`{word}` is a reserved keyword and thus cannot be used as a field name unless it is put inside quotes. Use \"{word}\" or \'{word}\' instead.")? } diff --git a/crates/filter-parser/src/lib.rs b/crates/filter-parser/src/lib.rs index 8f6f02691..c761c583b 100644 --- a/crates/filter-parser/src/lib.rs +++ b/crates/filter-parser/src/lib.rs @@ -1018,8 +1018,8 @@ pub mod tests { 22:23 _vectors.embedderName. EXISTS "); insta::assert_snapshot!(p(r#"_vectors."embedderName EXISTS"#), @r#" - The vector filter's embedder name is invalid. - 30:30 _vectors."embedderName EXISTS + The quotes in one of the values are inconsistent. + 10:30 _vectors."embedderName EXISTS "#); insta::assert_snapshot!(p(r#"_vectors."embedderNam"e EXISTS"#), @r#" The vector filter has leftover tokens. @@ -1034,7 +1034,7 @@ pub mod tests { 32:39 _vectors.embedderName.fragments EXISTS "); insta::assert_snapshot!(p(r#"_vectors.embedderName.fragments. EXISTS"#), @r" - The vector filter's fragment is invalid. + The vector filter's fragment name is invalid. 33:40 _vectors.embedderName.fragments. EXISTS "); insta::assert_snapshot!(p(r#"_vectors.embedderName.fragments.test test EXISTS"#), @r" @@ -1042,7 +1042,7 @@ pub mod tests { 38:49 _vectors.embedderName.fragments.test test EXISTS "); insta::assert_snapshot!(p(r#"_vectors.embedderName.fragments. test EXISTS"#), @r" - The vector filter's fragment is invalid. + The vector filter's fragment name is invalid. 33:45 _vectors.embedderName.fragments. test EXISTS "); insta::assert_snapshot!(p(r#"_vectors.embedderName .fragments. test EXISTS"#), @r" diff --git a/crates/filter-parser/src/value.rs b/crates/filter-parser/src/value.rs index dac96b4f4..35a5c0ab4 100644 --- a/crates/filter-parser/src/value.rs +++ b/crates/filter-parser/src/value.rs @@ -113,6 +113,18 @@ pub fn parse_vector_value(input: Span) -> IResult { } } +pub fn parse_vector_value_cut<'a>(input: Span<'a>, kind: ErrorKind<'a>) -> IResult<'a, Token<'a>> { + parse_vector_value(input).map_err(|e| match e { + nom::Err::Failure(e) => match e.kind() { + ErrorKind::Char(c) if *c == '"' || *c == '\'' => { + crate::Error::failure_from_kind(input, ErrorKind::VectorFilterInvalidQuotes) + } + _ => crate::Error::failure_from_kind(input, kind), + }, + _ => crate::Error::failure_from_kind(input, kind), + }) +} + /// value = WS* ( word | singleQuoted | doubleQuoted) WS+ pub fn parse_value(input: Span) -> IResult { // to get better diagnostic message we are going to strip the left whitespaces from the input right now