Skip to content

Commit

Permalink
feat: Convert IS TRUE|FALSE to expression (#499)
Browse files Browse the repository at this point in the history
  • Loading branch information
ovr committed May 24, 2022
1 parent a6d7a35 commit 4070f3e
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 20 deletions.
6 changes: 6 additions & 0 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,10 @@ pub enum Expr {
},
/// CompositeAccess (postgres) eg: SELECT (information_schema._pg_expandarray(array['i','i'])).n
CompositeAccess { expr: Box<Expr>, key: Ident },
/// `IS FALSE` operator
IsFalse(Box<Expr>),
/// `IS TRUE` operator
IsTrue(Box<Expr>),
/// `IS NULL` operator
IsNull(Box<Expr>),
/// `IS NOT NULL` operator
Expand Down Expand Up @@ -379,6 +383,8 @@ impl fmt::Display for Expr {
Ok(())
}
Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
Expr::IsTrue(ast) => write!(f, "{} IS TRUE", ast),
Expr::IsFalse(ast) => write!(f, "{} IS FALSE", ast),
Expr::IsNull(ast) => write!(f, "{} IS NULL", ast),
Expr::IsNotNull(ast) => write!(f, "{} IS NOT NULL", ast),
Expr::InList {
Expand Down
18 changes: 5 additions & 13 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1155,28 +1155,20 @@ impl<'a> Parser<'a> {
Ok(Expr::IsNull(Box::new(expr)))
} else if self.parse_keywords(&[Keyword::NOT, Keyword::NULL]) {
Ok(Expr::IsNotNull(Box::new(expr)))
} else if self.parse_keywords(&[Keyword::TRUE]) {
Ok(Expr::IsTrue(Box::new(expr)))
} else if self.parse_keywords(&[Keyword::FALSE]) {
Ok(Expr::IsFalse(Box::new(expr)))
} else if self.parse_keywords(&[Keyword::DISTINCT, Keyword::FROM]) {
let expr2 = self.parse_expr()?;
Ok(Expr::IsDistinctFrom(Box::new(expr), Box::new(expr2)))
} else if self.parse_keywords(&[Keyword::NOT, Keyword::DISTINCT, Keyword::FROM])
{
let expr2 = self.parse_expr()?;
Ok(Expr::IsNotDistinctFrom(Box::new(expr), Box::new(expr2)))
} else if let Some(right) =
self.parse_one_of_keywords(&[Keyword::TRUE, Keyword::FALSE])
{
let mut val = Value::Boolean(true);
if right == Keyword::FALSE {
val = Value::Boolean(false);
}
Ok(Expr::BinaryOp {
left: Box::new(expr),
op: BinaryOperator::Eq,
right: Box::new(Expr::Value(val)),
})
} else {
self.expected(
"[NOT] NULL or [NOT] DISTINCT FROM TRUE FALSE after IS",
"[NOT] NULL or TRUE|FALSE or [NOT] DISTINCT FROM after IS",
self.peek_token(),
)
}
Expand Down
23 changes: 16 additions & 7 deletions tests/sqlparser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4768,21 +4768,30 @@ fn parse_position_negative() {

#[test]
fn parse_is_boolean() {
one_statement_parses_to(
"SELECT f from foo where field is true",
"SELECT f FROM foo WHERE field = true",
use self::Expr::*;

let sql = "a IS FALSE";
assert_eq!(
IsFalse(Box::new(Identifier(Ident::new("a")))),
verified_expr(sql)
);

one_statement_parses_to(
"SELECT f from foo where field is false",
"SELECT f FROM foo WHERE field = false",
let sql = "a IS TRUE";
assert_eq!(
IsTrue(Box::new(Identifier(Ident::new("a")))),
verified_expr(sql)
);

verified_stmt("SELECT f FROM foo WHERE field IS TRUE");

verified_stmt("SELECT f FROM foo WHERE field IS FALSE");

let sql = "SELECT f from foo where field is 0";
let res = parse_sql_statements(sql);
assert_eq!(
ParserError::ParserError(
"Expected [NOT] NULL or [NOT] DISTINCT FROM TRUE FALSE after IS, found: 0".to_string()
"Expected [NOT] NULL or TRUE|FALSE or [NOT] DISTINCT FROM after IS, found: 0"
.to_string()
),
res.unwrap_err()
);
Expand Down

0 comments on commit 4070f3e

Please sign in to comment.