Allow SQL subqueries to be ended witrh ; character

Related to #247
Related to #225
Related to #1319
This commit is contained in:
Tobie Morgan Hitchcock 2023-02-20 20:40:05 +00:00
parent 185eb91f22
commit 223d119b2c
2 changed files with 63 additions and 13 deletions

View file

@ -1,5 +1,5 @@
use crate::sql::comment::comment; use crate::sql::comment::comment;
use crate::sql::comment::shouldbespace; use crate::sql::comment::{mightbespace, shouldbespace};
use crate::sql::error::IResult; use crate::sql::error::IResult;
use crate::sql::operator::{assigner, operator}; use crate::sql::operator::{assigner, operator};
use nom::branch::alt; use nom::branch::alt;
@ -67,15 +67,27 @@ pub fn duration(i: &str) -> IResult<&str, ()> {
} }
pub fn subquery(i: &str) -> IResult<&str, ()> { pub fn subquery(i: &str) -> IResult<&str, ()> {
peek(alt(( alt((
map(preceded(shouldbespace, tag_no_case("THEN")), |_| ()), |i| {
map(preceded(shouldbespace, tag_no_case("ELSE")), |_| ()), let (i, _) = mightbespace(i)?;
map(preceded(shouldbespace, tag_no_case("END")), |_| ()), let (i, _) = char(';')(i)?;
map(comment, |_| ()), let (i, _) = peek(alt((
map(char(']'), |_| ()), preceded(shouldbespace, tag_no_case("THEN")),
map(char('}'), |_| ()), preceded(shouldbespace, tag_no_case("ELSE")),
map(char(';'), |_| ()), preceded(shouldbespace, tag_no_case("END")),
map(char(','), |_| ()), )))(i)?;
map(eof, |_| ()), Ok((i, ()))
)))(i) },
peek(alt((
map(preceded(shouldbespace, tag_no_case("THEN")), |_| ()),
map(preceded(shouldbespace, tag_no_case("ELSE")), |_| ()),
map(preceded(shouldbespace, tag_no_case("END")), |_| ()),
map(comment, |_| ()),
map(char(']'), |_| ()),
map(char('}'), |_| ()),
map(char(';'), |_| ()),
map(char(','), |_| ()),
map(eof, |_| ()),
))),
))(i)
} }

View file

@ -124,11 +124,21 @@ async fn subquery_ifelse() -> Result<(), Error> {
ELSE ELSE
UPDATE person:test SET sport = ['basketball'] RETURN sport UPDATE person:test SET sport = ['basketball'] RETURN sport
END; END;
-- Check if the record exists
LET $record = SELECT *, count() AS count FROM person:test;
-- Return the specified record
RETURN $record;
-- Update the record field if it exists
IF $record.count THEN
UPDATE person:test SET sport += 'football' RETURN sport;
ELSE
UPDATE person:test SET sport = ['basketball'] RETURN sport;
END;
"; ";
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(), 6); assert_eq!(res.len(), 9);
// //
let tmp = res.remove(0).result?; let tmp = res.remove(0).result?;
let val = Value::None; let val = Value::None;
@ -175,5 +185,33 @@ async fn subquery_ifelse() -> Result<(), Error> {
); );
assert_eq!(tmp, val); assert_eq!(tmp, val);
// //
let tmp = res.remove(0).result?;
let val = Value::None;
assert_eq!(tmp, val);
//
let tmp = res.remove(0).result?;
let val = Value::parse(
"{
count: 1,
id: person:test,
sport: [
'basketball',
'football'
]
}",
);
assert_eq!(tmp, val);
//
let tmp = res.remove(0).result?;
let val = Value::parse(
"{
sport: [
'basketball',
'football'
]
}",
);
assert_eq!(tmp, val);
//
Ok(()) Ok(())
} }