Allow trailing commas in SQL Geometry types

Closes #1523
This commit is contained in:
Tobie Morgan Hitchcock 2023-01-03 17:52:22 +00:00
parent 5d4cb3bbbf
commit c0d5aace54
2 changed files with 157 additions and 20 deletions

View file

@ -12,6 +12,7 @@ use geo::{MultiLineString, MultiPoint, MultiPolygon};
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::character::complete::char; use nom::character::complete::char;
use nom::combinator::opt;
use nom::multi::separated_list0; use nom::multi::separated_list0;
use nom::multi::separated_list1; use nom::multi::separated_list1;
use nom::number::complete::double; use nom::number::complete::double;
@ -591,9 +592,7 @@ fn simple(i: &str) -> IResult<&str, Geometry> {
let (i, _) = char('(')(i)?; let (i, _) = char('(')(i)?;
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, x) = double(i)?; let (i, x) = double(i)?;
let (i, _) = mightbespace(i)?; let (i, _) = commas(i)?;
let (i, _) = char(',')(i)?;
let (i, _) = mightbespace(i)?;
let (i, y) = double(i)?; let (i, y) = double(i)?;
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, _) = char(')')(i)?; let (i, _) = char(')')(i)?;
@ -606,14 +605,20 @@ fn point(i: &str) -> IResult<&str, Geometry> {
let (i, v) = alt(( let (i, v) = alt((
|i| { |i| {
let (i, _) = preceded(key_type, point_type)(i)?; let (i, _) = preceded(key_type, point_type)(i)?;
let (i, _) = delimited(mightbespace, char(','), mightbespace)(i)?; let (i, _) = commas(i)?;
let (i, v) = preceded(key_vals, point_vals)(i)?; let (i, v) = preceded(key_vals, point_vals)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
|i| { |i| {
let (i, v) = preceded(key_vals, point_vals)(i)?; let (i, v) = preceded(key_vals, point_vals)(i)?;
let (i, _) = delimited(mightbespace, char(','), mightbespace)(i)?; let (i, _) = commas(i)?;
let (i, _) = preceded(key_type, point_type)(i)?; let (i, _) = preceded(key_type, point_type)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
))(i)?; ))(i)?;
@ -628,14 +633,20 @@ fn line(i: &str) -> IResult<&str, Geometry> {
let (i, v) = alt(( let (i, v) = alt((
|i| { |i| {
let (i, _) = preceded(key_type, line_type)(i)?; let (i, _) = preceded(key_type, line_type)(i)?;
let (i, _) = delimited(mightbespace, char(','), mightbespace)(i)?; let (i, _) = commas(i)?;
let (i, v) = preceded(key_vals, line_vals)(i)?; let (i, v) = preceded(key_vals, line_vals)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
|i| { |i| {
let (i, v) = preceded(key_vals, line_vals)(i)?; let (i, v) = preceded(key_vals, line_vals)(i)?;
let (i, _) = delimited(mightbespace, char(','), mightbespace)(i)?; let (i, _) = commas(i)?;
let (i, _) = preceded(key_type, line_type)(i)?; let (i, _) = preceded(key_type, line_type)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
))(i)?; ))(i)?;
@ -650,14 +661,20 @@ fn polygon(i: &str) -> IResult<&str, Geometry> {
let (i, v) = alt(( let (i, v) = alt((
|i| { |i| {
let (i, _) = preceded(key_type, polygon_type)(i)?; let (i, _) = preceded(key_type, polygon_type)(i)?;
let (i, _) = delimited(mightbespace, char(','), mightbespace)(i)?; let (i, _) = commas(i)?;
let (i, v) = preceded(key_vals, polygon_vals)(i)?; let (i, v) = preceded(key_vals, polygon_vals)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
|i| { |i| {
let (i, v) = preceded(key_vals, polygon_vals)(i)?; let (i, v) = preceded(key_vals, polygon_vals)(i)?;
let (i, _) = delimited(mightbespace, char(','), mightbespace)(i)?; let (i, _) = commas(i)?;
let (i, _) = preceded(key_type, polygon_type)(i)?; let (i, _) = preceded(key_type, polygon_type)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
))(i)?; ))(i)?;
@ -672,14 +689,20 @@ fn multipoint(i: &str) -> IResult<&str, Geometry> {
let (i, v) = alt(( let (i, v) = alt((
|i| { |i| {
let (i, _) = preceded(key_type, multipoint_type)(i)?; let (i, _) = preceded(key_type, multipoint_type)(i)?;
let (i, _) = delimited(mightbespace, char(','), mightbespace)(i)?; let (i, _) = commas(i)?;
let (i, v) = preceded(key_vals, multipoint_vals)(i)?; let (i, v) = preceded(key_vals, multipoint_vals)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
|i| { |i| {
let (i, v) = preceded(key_vals, multipoint_vals)(i)?; let (i, v) = preceded(key_vals, multipoint_vals)(i)?;
let (i, _) = delimited(mightbespace, char(','), mightbespace)(i)?; let (i, _) = commas(i)?;
let (i, _) = preceded(key_type, multipoint_type)(i)?; let (i, _) = preceded(key_type, multipoint_type)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
))(i)?; ))(i)?;
@ -694,14 +717,20 @@ fn multiline(i: &str) -> IResult<&str, Geometry> {
let (i, v) = alt(( let (i, v) = alt((
|i| { |i| {
let (i, _) = preceded(key_type, multiline_type)(i)?; let (i, _) = preceded(key_type, multiline_type)(i)?;
let (i, _) = delimited(mightbespace, char(','), mightbespace)(i)?; let (i, _) = commas(i)?;
let (i, v) = preceded(key_vals, multiline_vals)(i)?; let (i, v) = preceded(key_vals, multiline_vals)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
|i| { |i| {
let (i, v) = preceded(key_vals, multiline_vals)(i)?; let (i, v) = preceded(key_vals, multiline_vals)(i)?;
let (i, _) = delimited(mightbespace, char(','), mightbespace)(i)?; let (i, _) = commas(i)?;
let (i, _) = preceded(key_type, multiline_type)(i)?; let (i, _) = preceded(key_type, multiline_type)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
))(i)?; ))(i)?;
@ -716,14 +745,20 @@ fn multipolygon(i: &str) -> IResult<&str, Geometry> {
let (i, v) = alt(( let (i, v) = alt((
|i| { |i| {
let (i, _) = preceded(key_type, multipolygon_type)(i)?; let (i, _) = preceded(key_type, multipolygon_type)(i)?;
let (i, _) = delimited(mightbespace, char(','), mightbespace)(i)?; let (i, _) = commas(i)?;
let (i, v) = preceded(key_vals, multipolygon_vals)(i)?; let (i, v) = preceded(key_vals, multipolygon_vals)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
|i| { |i| {
let (i, v) = preceded(key_vals, multipolygon_vals)(i)?; let (i, v) = preceded(key_vals, multipolygon_vals)(i)?;
let (i, _) = delimited(mightbespace, char(','), mightbespace)(i)?; let (i, _) = commas(i)?;
let (i, _) = preceded(key_type, multipolygon_type)(i)?; let (i, _) = preceded(key_type, multipolygon_type)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
))(i)?; ))(i)?;
@ -738,14 +773,20 @@ fn collection(i: &str) -> IResult<&str, Geometry> {
let (i, v) = alt(( let (i, v) = alt((
|i| { |i| {
let (i, _) = preceded(key_type, collection_type)(i)?; let (i, _) = preceded(key_type, collection_type)(i)?;
let (i, _) = delimited(mightbespace, char(','), mightbespace)(i)?; let (i, _) = commas(i)?;
let (i, v) = preceded(key_geom, collection_vals)(i)?; let (i, v) = preceded(key_geom, collection_vals)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
|i| { |i| {
let (i, v) = preceded(key_geom, collection_vals)(i)?; let (i, v) = preceded(key_geom, collection_vals)(i)?;
let (i, _) = delimited(mightbespace, char(','), mightbespace)(i)?; let (i, _) = commas(i)?;
let (i, _) = preceded(key_type, collection_type)(i)?; let (i, _) = preceded(key_type, collection_type)(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
Ok((i, v)) Ok((i, v))
}, },
))(i)?; ))(i)?;
@ -768,6 +809,8 @@ fn line_vals(i: &str) -> IResult<&str, LineString<f64>> {
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, v) = separated_list1(commas, coordinate)(i)?; let (i, v) = separated_list1(commas, coordinate)(i)?;
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char(']')(i)?; let (i, _) = char(']')(i)?;
Ok((i, v.into())) Ok((i, v.into()))
} }
@ -777,12 +820,16 @@ fn polygon_vals(i: &str) -> IResult<&str, Polygon<f64>> {
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, e) = line_vals(i)?; let (i, e) = line_vals(i)?;
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char(']')(i)?; let (i, _) = char(']')(i)?;
let (i, v) = separated_list0(commas, |i| { let (i, v) = separated_list0(commas, |i| {
let (i, _) = char('[')(i)?; let (i, _) = char('[')(i)?;
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, v) = line_vals(i)?; let (i, v) = line_vals(i)?;
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char(']')(i)?; let (i, _) = char(']')(i)?;
Ok((i, v)) Ok((i, v))
})(i)?; })(i)?;
@ -794,6 +841,8 @@ fn multipoint_vals(i: &str) -> IResult<&str, Vec<Point<f64>>> {
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, v) = separated_list1(commas, point_vals)(i)?; let (i, v) = separated_list1(commas, point_vals)(i)?;
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char(']')(i)?; let (i, _) = char(']')(i)?;
Ok((i, v)) Ok((i, v))
} }
@ -803,6 +852,8 @@ fn multiline_vals(i: &str) -> IResult<&str, Vec<LineString<f64>>> {
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, v) = separated_list1(commas, line_vals)(i)?; let (i, v) = separated_list1(commas, line_vals)(i)?;
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char(']')(i)?; let (i, _) = char(']')(i)?;
Ok((i, v)) Ok((i, v))
} }
@ -812,6 +863,8 @@ fn multipolygon_vals(i: &str) -> IResult<&str, Vec<Polygon<f64>>> {
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, v) = separated_list1(commas, polygon_vals)(i)?; let (i, v) = separated_list1(commas, polygon_vals)(i)?;
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char(']')(i)?; let (i, _) = char(']')(i)?;
Ok((i, v)) Ok((i, v))
} }
@ -821,6 +874,8 @@ fn collection_vals(i: &str) -> IResult<&str, Vec<Geometry>> {
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, v) = separated_list1(commas, geometry)(i)?; let (i, v) = separated_list1(commas, geometry)(i)?;
let (i, _) = mightbespace(i)?; let (i, _) = mightbespace(i)?;
let (i, _) = opt(char(','))(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char(']')(i)?; let (i, _) = char(']')(i)?;
Ok((i, v)) Ok((i, v))
} }

View file

@ -58,12 +58,42 @@ async fn geometry_polygon() -> Result<(), Error> {
[-0.38314819, 51.37692386] [-0.38314819, 51.37692386]
]] ]]
}; };
UPDATE city:london SET area = {
type: 'Polygon',
coordinates: [[
[-0.38314819, 51.37692386], [0.1785278, 51.37692386],
[0.1785278, 51.61460570], [-0.38314819, 51.61460570],
[-0.38314819, 51.37692386],
]],
};
SELECT * FROM city:london; SELECT * FROM city:london;
"; ";
let dbs = Datastore::new("memory").await?; let dbs = Datastore::new("memory").await?;
let ses = Session::for_kv().with_ns("test").with_db("test"); let ses = Session::for_kv().with_ns("test").with_db("test");
let res = &mut dbs.execute(&sql, &ses, None, false).await?; let res = &mut dbs.execute(&sql, &ses, None, false).await?;
assert_eq!(res.len(), 2); assert_eq!(res.len(), 3);
//
let tmp = res.remove(0).result?;
let val = Value::parse(
r#"[
{
"area": {
"type": "Polygon",
"coordinates": [
[
[-0.38314819, 51.37692386],
[0.1785278, 51.37692386],
[0.1785278, 51.6146057],
[-0.38314819, 51.6146057],
[-0.38314819, 51.37692386]
]
]
},
"id": "city:london"
}
]"#,
);
assert_eq!(tmp, val);
// //
let tmp = res.remove(0).result?; let tmp = res.remove(0).result?;
let val = Value::parse( let val = Value::parse(
@ -122,12 +152,36 @@ async fn geometry_multipoint() -> Result<(), Error> {
[-0.118092, 51.509865] [-0.118092, 51.509865]
] ]
}; };
UPDATE city:london SET points = {
type: 'MultiPoint',
coordinates: [
[-0.118092, 51.509865],
[-0.118092, 51.509865],
],
};
SELECT * FROM city:london; SELECT * FROM city:london;
"; ";
let dbs = Datastore::new("memory").await?; let dbs = Datastore::new("memory").await?;
let ses = Session::for_kv().with_ns("test").with_db("test"); let ses = Session::for_kv().with_ns("test").with_db("test");
let res = &mut dbs.execute(&sql, &ses, None, false).await?; let res = &mut dbs.execute(&sql, &ses, None, false).await?;
assert_eq!(res.len(), 2); assert_eq!(res.len(), 3);
//
let tmp = res.remove(0).result?;
let val = Value::parse(
r#"[
{
"points": {
"type": "MultiPoint",
"coordinates": [
[-0.118092, 51.509865],
[-0.118092, 51.509865]
]
},
"id": "city:london"
}
]"#,
);
assert_eq!(tmp, val);
// //
let tmp = res.remove(0).result?; let tmp = res.remove(0).result?;
let val = Value::parse( let val = Value::parse(
@ -176,12 +230,40 @@ async fn geometry_multipolygon() -> Result<(), Error> {
[[ [9.0, 11.2], [10.5, 11.9], [10.3, 13.0], [9.0, 11.2] ]] [[ [9.0, 11.2], [10.5, 11.9], [10.3, 13.0], [9.0, 11.2] ]]
] ]
}; };
UPDATE university:oxford SET area = {
type: 'MultiPolygon',
coordinates: [
[[ [10.0, 11.2], [10.5, 11.9], [10.8, 12.0], [10.0, 11.2] ]],
[[ [9.0, 11.2], [10.5, 11.9], [10.3, 13.0], [9.0, 11.2] ]],
],
};
SELECT * FROM university:oxford; SELECT * FROM university:oxford;
"; ";
let dbs = Datastore::new("memory").await?; let dbs = Datastore::new("memory").await?;
let ses = Session::for_kv().with_ns("test").with_db("test"); let ses = Session::for_kv().with_ns("test").with_db("test");
let res = &mut dbs.execute(&sql, &ses, None, false).await?; let res = &mut dbs.execute(&sql, &ses, None, false).await?;
assert_eq!(res.len(), 2); assert_eq!(res.len(), 3);
//
let tmp = res.remove(0).result?;
let val = Value::parse(
r#"[
{
"area": {
"type": "MultiPolygon",
"coordinates": [
[
[[10.0, 11.2], [10.5, 11.9], [10.8, 12.0], [10.0, 11.2]]
],
[
[[9.0, 11.2], [10.5, 11.9], [10.3, 13.0], [9.0, 11.2]]
]
]
},
"id": "university:oxford"
}
]"#,
);
assert_eq!(tmp, val);
// //
let tmp = res.remove(0).result?; let tmp = res.remove(0).result?;
let val = Value::parse( let val = Value::parse(