Allow raw SQL subqueries without surrounding brackets
Related to #247 Related to #225 Related to #1319
This commit is contained in:
parent
275cf18a3a
commit
185eb91f22
3 changed files with 52 additions and 13 deletions
|
@ -1,13 +1,16 @@
|
||||||
use crate::sql::comment::comment;
|
use crate::sql::comment::comment;
|
||||||
|
use crate::sql::comment::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;
|
||||||
use nom::bytes::complete::tag;
|
use nom::bytes::complete::tag;
|
||||||
|
use nom::bytes::complete::tag_no_case;
|
||||||
use nom::character::complete::char;
|
use nom::character::complete::char;
|
||||||
use nom::character::complete::multispace1;
|
use nom::character::complete::multispace1;
|
||||||
use nom::combinator::eof;
|
use nom::combinator::eof;
|
||||||
use nom::combinator::map;
|
use nom::combinator::map;
|
||||||
use nom::combinator::peek;
|
use nom::combinator::peek;
|
||||||
|
use nom::sequence::preceded;
|
||||||
|
|
||||||
pub fn number(i: &str) -> IResult<&str, ()> {
|
pub fn number(i: &str) -> IResult<&str, ()> {
|
||||||
peek(alt((
|
peek(alt((
|
||||||
|
@ -62,3 +65,17 @@ pub fn duration(i: &str) -> IResult<&str, ()> {
|
||||||
map(eof, |_| ()),
|
map(eof, |_| ()),
|
||||||
)))(i)
|
)))(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn subquery(i: &str) -> IResult<&str, ()> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ use crate::dbs::Options;
|
||||||
use crate::dbs::Transaction;
|
use crate::dbs::Transaction;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::comment::mightbespace;
|
use crate::sql::comment::mightbespace;
|
||||||
|
use crate::sql::ending::subquery as ending;
|
||||||
use crate::sql::error::IResult;
|
use crate::sql::error::IResult;
|
||||||
use crate::sql::statements::create::{create, CreateStatement};
|
use crate::sql::statements::create::{create, CreateStatement};
|
||||||
use crate::sql::statements::delete::{delete, DeleteStatement};
|
use crate::sql::statements::delete::{delete, DeleteStatement};
|
||||||
|
@ -222,7 +223,7 @@ impl Display for Subquery {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subquery(i: &str) -> IResult<&str, Subquery> {
|
pub fn subquery(i: &str) -> IResult<&str, Subquery> {
|
||||||
alt((subquery_ifelse, subquery_others))(i)
|
alt((subquery_ifelse, subquery_other, subquery_value))(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subquery_ifelse(i: &str) -> IResult<&str, Subquery> {
|
fn subquery_ifelse(i: &str) -> IResult<&str, Subquery> {
|
||||||
|
@ -230,10 +231,35 @@ fn subquery_ifelse(i: &str) -> IResult<&str, Subquery> {
|
||||||
Ok((i, v))
|
Ok((i, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subquery_others(i: &str) -> IResult<&str, Subquery> {
|
fn subquery_value(i: &str) -> IResult<&str, Subquery> {
|
||||||
let (i, _) = char('(')(i)?;
|
let (i, _) = char('(')(i)?;
|
||||||
let (i, _) = mightbespace(i)?;
|
let (i, _) = mightbespace(i)?;
|
||||||
let (i, v) = alt((
|
let (i, v) = map(value, Subquery::Value)(i)?;
|
||||||
|
let (i, _) = mightbespace(i)?;
|
||||||
|
let (i, _) = char(')')(i)?;
|
||||||
|
Ok((i, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subquery_other(i: &str) -> IResult<&str, Subquery> {
|
||||||
|
alt((
|
||||||
|
|i| {
|
||||||
|
let (i, _) = char('(')(i)?;
|
||||||
|
let (i, _) = mightbespace(i)?;
|
||||||
|
let (i, v) = subquery_inner(i)?;
|
||||||
|
let (i, _) = mightbespace(i)?;
|
||||||
|
let (i, _) = char(')')(i)?;
|
||||||
|
Ok((i, v))
|
||||||
|
},
|
||||||
|
|i| {
|
||||||
|
let (i, v) = subquery_inner(i)?;
|
||||||
|
let (i, _) = ending(i)?;
|
||||||
|
Ok((i, v))
|
||||||
|
},
|
||||||
|
))(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subquery_inner(i: &str) -> IResult<&str, Subquery> {
|
||||||
|
alt((
|
||||||
map(output, Subquery::Output),
|
map(output, Subquery::Output),
|
||||||
map(select, Subquery::Select),
|
map(select, Subquery::Select),
|
||||||
map(create, Subquery::Create),
|
map(create, Subquery::Create),
|
||||||
|
@ -241,11 +267,7 @@ fn subquery_others(i: &str) -> IResult<&str, Subquery> {
|
||||||
map(delete, Subquery::Delete),
|
map(delete, Subquery::Delete),
|
||||||
map(relate, Subquery::Relate),
|
map(relate, Subquery::Relate),
|
||||||
map(insert, Subquery::Insert),
|
map(insert, Subquery::Insert),
|
||||||
map(value, Subquery::Value),
|
))(i)
|
||||||
))(i)?;
|
|
||||||
let (i, _) = mightbespace(i)?;
|
|
||||||
let (i, _) = char(')')(i)?;
|
|
||||||
Ok((i, v))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -110,19 +110,19 @@ async fn subquery_ifelse() -> Result<(), Error> {
|
||||||
RETURN $record;
|
RETURN $record;
|
||||||
-- Update the record field if it exists
|
-- Update the record field if it exists
|
||||||
IF $record.count THEN
|
IF $record.count THEN
|
||||||
( UPDATE person:test SET sport += 'football' RETURN sport )
|
(UPDATE person:test SET sport += 'football' RETURN sport)
|
||||||
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
|
-- Check if the record exists
|
||||||
LET $record = (SELECT *, count() AS count FROM person:test);
|
LET $record = SELECT *, count() AS count FROM person:test;
|
||||||
-- Return the specified record
|
-- Return the specified record
|
||||||
RETURN $record;
|
RETURN $record;
|
||||||
-- Update the record field if it exists
|
-- Update the record field if it exists
|
||||||
IF $record.count THEN
|
IF $record.count THEN
|
||||||
( UPDATE person:test SET sport += 'football' RETURN sport )
|
UPDATE person:test SET sport += 'football' RETURN sport
|
||||||
ELSE
|
ELSE
|
||||||
( UPDATE person:test SET sport = ['basketball'] RETURN sport )
|
UPDATE person:test SET sport = ['basketball'] RETURN sport
|
||||||
END;
|
END;
|
||||||
";
|
";
|
||||||
let dbs = Datastore::new("memory").await?;
|
let dbs = Datastore::new("memory").await?;
|
||||||
|
|
Loading…
Reference in a new issue