handle _geo(x,y,z) filter error

This commit is contained in:
Filip Bachul 2023-03-31 16:21:27 +02:00
parent 114436926f
commit 3acc5bbb15
2 changed files with 35 additions and 5 deletions

View File

@ -382,6 +382,20 @@ fn parse_geo_point(input: Span) -> IResult<FilterCondition> {
Err(nom::Err::Failure(Error::new_from_kind(input, ErrorKind::ReservedGeo("_geoPoint")))) Err(nom::Err::Failure(Error::new_from_kind(input, ErrorKind::ReservedGeo("_geoPoint"))))
} }
/// geo = WS* "_geo(float WS* "," WS* float WS* "," WS* float)
fn parse_geo(input: Span) -> IResult<FilterCondition> {
// we want to forbid space BEFORE the _geo but not after
tuple((
multispace0,
word_exact("_geo"),
// if we were able to parse `_geo` we are going to return a Failure whatever happens next.
cut(delimited(char('('), separated_list1(tag(","), ws(recognize_float)), char(')'))),
))(input)
.map_err(|e| e.map(|_| Error::new_from_kind(input, ErrorKind::ReservedGeo("_geo"))))?;
// if we succeeded we still return a `Failure` because `_geo` filter is not allowed
Err(nom::Err::Failure(Error::new_from_kind(input, ErrorKind::ReservedGeo("_geo"))))
}
fn parse_error_reserved_keyword(input: Span) -> IResult<FilterCondition> { fn parse_error_reserved_keyword(input: Span) -> IResult<FilterCondition> {
match parse_condition(input) { match parse_condition(input) {
Ok(result) => Ok(result), Ok(result) => Ok(result),
@ -418,6 +432,7 @@ fn parse_primary(input: Span, depth: usize) -> IResult<FilterCondition> {
parse_not_exists, parse_not_exists,
parse_to, parse_to,
// the next lines are only for error handling and are written at the end to have the less possible performance impact // the next lines are only for error handling and are written at the end to have the less possible performance impact
parse_geo,
parse_geo_point, parse_geo_point,
parse_error_reserved_keyword, parse_error_reserved_keyword,
))(input) ))(input)
@ -630,6 +645,16 @@ pub mod tests {
13:34 position <= _geoPoint(12, 13, 14) 13:34 position <= _geoPoint(12, 13, 14)
"###); "###);
insta::assert_display_snapshot!(p("_geo(12, 13, 14)"), @r###"
`_geo` is a reserved keyword and thus can't be used as a filter expression. Use the `_geoRadius(latitude, longitude, distance), or _geoBoundingBox([latitude, longitude], [latitude, longitude]) built-in rules to filter on `_geo` coordinates.
1:17 _geo(12, 13, 14)
"###);
insta::assert_display_snapshot!(p("position <= _geo(12, 13, 14)"), @r###"
`_geo` is a reserved keyword and thus can't be used as a filter expression. Use the `_geoRadius(latitude, longitude, distance), or _geoBoundingBox([latitude, longitude], [latitude, longitude]) built-in rules to filter on `_geo` coordinates.
13:29 position <= _geo(12, 13, 14)
"###);
insta::assert_display_snapshot!(p("position <= _geoRadius(12, 13, 14)"), @r###" insta::assert_display_snapshot!(p("position <= _geoRadius(12, 13, 14)"), @r###"
The `_geoRadius` filter is an operation and can't be used as a value. The `_geoRadius` filter is an operation and can't be used as a value.
13:35 position <= _geoRadius(12, 13, 14) 13:35 position <= _geoRadius(12, 13, 14)

View File

@ -7,8 +7,8 @@ use nom::{InputIter, InputLength, InputTake, Slice};
use crate::error::{ExpectedValueKind, NomErrorExt}; use crate::error::{ExpectedValueKind, NomErrorExt};
use crate::{ use crate::{
parse_geo_bounding_box, parse_geo_point, parse_geo_radius, Error, ErrorKind, IResult, Span, parse_geo, parse_geo_bounding_box, parse_geo_point, parse_geo_radius, Error, ErrorKind,
Token, IResult, Span, Token,
}; };
/// This function goes through all characters in the [Span] if it finds any escaped character (`\`). /// This function goes through all characters in the [Span] if it finds any escaped character (`\`).
@ -88,11 +88,16 @@ pub fn parse_value(input: Span) -> IResult<Token> {
// then, we want to check if the user is misusing a geo expression // then, we want to check if the user is misusing a geo expression
// This expression cant finish without error. // This expression cant finish without error.
// We want to return an error in case of failure. // We want to return an error in case of failure.
if let Err(err) = parse_geo_point(input) { let geo_reserved_parse_functions = [parse_geo_point, parse_geo];
if err.is_failure() {
return Err(err); for parser in geo_reserved_parse_functions {
if let Err(err) = parser(input) {
if err.is_failure() {
return Err(err);
}
} }
} }
match parse_geo_radius(input) { match parse_geo_radius(input) {
Ok(_) => { Ok(_) => {
return Err(nom::Err::Failure(Error::new_from_kind(input, ErrorKind::MisusedGeoRadius))) return Err(nom::Err::Failure(Error::new_from_kind(input, ErrorKind::MisusedGeoRadius)))