add more consistency in ast (#523)

* add more consistency in ast

* refactor styling
This commit is contained in:
Andrey Frolov 2022-06-15 00:02:03 +03:00 committed by GitHub
parent d981f70143
commit c884fbc388
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 15 deletions

View file

@ -337,9 +337,9 @@ pub enum Expr {
results: Vec<Expr>, results: Vec<Expr>,
else_result: Option<Box<Expr>>, else_result: Option<Box<Expr>>,
}, },
/// An exists expression `EXISTS(SELECT ...)`, used in expressions like /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like
/// `WHERE EXISTS (SELECT ...)`. /// `WHERE [ NOT ] EXISTS (SELECT ...)`.
Exists(Box<Query>), Exists { subquery: Box<Query>, negated: bool },
/// A parenthesized subquery `(SELECT ...)`, used in expression like /// A parenthesized subquery `(SELECT ...)`, used in expression like
/// `SELECT (subquery) AS x` or `WHERE (subquery) = x` /// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
Subquery(Box<Query>), Subquery(Box<Query>),
@ -466,7 +466,12 @@ impl fmt::Display for Expr {
} }
write!(f, " END") write!(f, " END")
} }
Expr::Exists(s) => write!(f, "EXISTS ({})", s), Expr::Exists { subquery, negated } => write!(
f,
"{}EXISTS ({})",
if *negated { "NOT " } else { "" },
subquery
),
Expr::Subquery(s) => write!(f, "({})", s), Expr::Subquery(s) => write!(f, "({})", s),
Expr::ListAgg(listagg) => write!(f, "{}", listagg), Expr::ListAgg(listagg) => write!(f, "{}", listagg),
Expr::GroupingSets(sets) => { Expr::GroupingSets(sets) => {

View file

@ -426,7 +426,7 @@ impl<'a> Parser<'a> {
Keyword::CASE => self.parse_case_expr(), Keyword::CASE => self.parse_case_expr(),
Keyword::CAST => self.parse_cast_expr(), Keyword::CAST => self.parse_cast_expr(),
Keyword::TRY_CAST => self.parse_try_cast_expr(), Keyword::TRY_CAST => self.parse_try_cast_expr(),
Keyword::EXISTS => self.parse_exists_expr(), Keyword::EXISTS => self.parse_exists_expr(false),
Keyword::EXTRACT => self.parse_extract_expr(), Keyword::EXTRACT => self.parse_extract_expr(),
Keyword::POSITION => self.parse_position_expr(), Keyword::POSITION => self.parse_position_expr(),
Keyword::SUBSTRING => self.parse_substring_expr(), Keyword::SUBSTRING => self.parse_substring_expr(),
@ -438,10 +438,7 @@ impl<'a> Parser<'a> {
self.expect_token(&Token::LBracket)?; self.expect_token(&Token::LBracket)?;
self.parse_array_expr(true) self.parse_array_expr(true)
} }
Keyword::NOT => Ok(Expr::UnaryOp { Keyword::NOT => self.parse_not(),
op: UnaryOperator::Not,
expr: Box::new(self.parse_subexpr(Self::UNARY_NOT_PREC)?),
}),
// Here `w` is a word, check if it's a part of a multi-part // Here `w` is a word, check if it's a part of a multi-part
// identifier, a function call, or a simple identifier: // identifier, a function call, or a simple identifier:
_ => match self.peek_token() { _ => match self.peek_token() {
@ -783,9 +780,12 @@ impl<'a> Parser<'a> {
} }
/// Parse a SQL EXISTS expression e.g. `WHERE EXISTS(SELECT ...)`. /// Parse a SQL EXISTS expression e.g. `WHERE EXISTS(SELECT ...)`.
pub fn parse_exists_expr(&mut self) -> Result<Expr, ParserError> { pub fn parse_exists_expr(&mut self, negated: bool) -> Result<Expr, ParserError> {
self.expect_token(&Token::LParen)?; self.expect_token(&Token::LParen)?;
let exists_node = Expr::Exists(Box::new(self.parse_query()?)); let exists_node = Expr::Exists {
negated,
subquery: Box::new(self.parse_query()?),
};
self.expect_token(&Token::RParen)?; self.expect_token(&Token::RParen)?;
Ok(exists_node) Ok(exists_node)
} }
@ -984,6 +984,26 @@ impl<'a> Parser<'a> {
} }
} }
pub fn parse_not(&mut self) -> Result<Expr, ParserError> {
match self.peek_token() {
Token::Word(w) => match w.keyword {
Keyword::EXISTS => {
let negated = true;
let _ = self.parse_keyword(Keyword::EXISTS);
self.parse_exists_expr(negated)
}
_ => Ok(Expr::UnaryOp {
op: UnaryOperator::Not,
expr: Box::new(self.parse_subexpr(Self::UNARY_NOT_PREC)?),
}),
},
_ => Ok(Expr::UnaryOp {
op: UnaryOperator::Not,
expr: Box::new(self.parse_subexpr(Self::UNARY_NOT_PREC)?),
}),
}
}
/// Parse an INTERVAL literal. /// Parse an INTERVAL literal.
/// ///
/// Some syntactically valid intervals: /// Some syntactically valid intervals:

View file

@ -3625,16 +3625,19 @@ fn parse_exists_subquery() {
let sql = "SELECT * FROM t WHERE EXISTS (SELECT 1)"; let sql = "SELECT * FROM t WHERE EXISTS (SELECT 1)";
let select = verified_only_select(sql); let select = verified_only_select(sql);
assert_eq!( assert_eq!(
Expr::Exists(Box::new(expected_inner.clone())), Expr::Exists {
negated: false,
subquery: Box::new(expected_inner.clone())
},
select.selection.unwrap(), select.selection.unwrap(),
); );
let sql = "SELECT * FROM t WHERE NOT EXISTS (SELECT 1)"; let sql = "SELECT * FROM t WHERE NOT EXISTS (SELECT 1)";
let select = verified_only_select(sql); let select = verified_only_select(sql);
assert_eq!( assert_eq!(
Expr::UnaryOp { Expr::Exists {
op: UnaryOperator::Not, negated: true,
expr: Box::new(Expr::Exists(Box::new(expected_inner))), subquery: Box::new(expected_inner)
}, },
select.selection.unwrap(), select.selection.unwrap(),
); );