mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-11-18 22:11:25 +00:00
Implement is [not] distinct from (#361)
* Implement is [not] distinct from * Simplify message * Clippy
This commit is contained in:
parent
c9f8a44b55
commit
0f0b327e97
4 changed files with 47 additions and 7 deletions
|
|
@ -169,10 +169,14 @@ pub enum Expr {
|
||||||
QualifiedWildcard(Vec<Ident>),
|
QualifiedWildcard(Vec<Ident>),
|
||||||
/// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
|
/// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col`
|
||||||
CompoundIdentifier(Vec<Ident>),
|
CompoundIdentifier(Vec<Ident>),
|
||||||
/// `IS NULL` expression
|
/// `IS NULL` operator
|
||||||
IsNull(Box<Expr>),
|
IsNull(Box<Expr>),
|
||||||
/// `IS NOT NULL` expression
|
/// `IS NOT NULL` operator
|
||||||
IsNotNull(Box<Expr>),
|
IsNotNull(Box<Expr>),
|
||||||
|
/// `IS DISTINCT FROM` operator
|
||||||
|
IsDistinctFrom(Box<Expr>, Box<Expr>),
|
||||||
|
/// `IS NOT DISTINCT FROM` operator
|
||||||
|
IsNotDistinctFrom(Box<Expr>, Box<Expr>),
|
||||||
/// `[ NOT ] IN (val1, val2, ...)`
|
/// `[ NOT ] IN (val1, val2, ...)`
|
||||||
InList {
|
InList {
|
||||||
expr: Box<Expr>,
|
expr: Box<Expr>,
|
||||||
|
|
@ -387,6 +391,8 @@ impl fmt::Display for Expr {
|
||||||
|
|
||||||
write!(f, ")")
|
write!(f, ")")
|
||||||
}
|
}
|
||||||
|
Expr::IsDistinctFrom(a, b) => write!(f, "{} IS DISTINCT FROM {}", a, b),
|
||||||
|
Expr::IsNotDistinctFrom(a, b) => write!(f, "{} IS NOT DISTINCT FROM {}", a, b),
|
||||||
Expr::Trim { expr, trim_where } => {
|
Expr::Trim { expr, trim_where } => {
|
||||||
write!(f, "TRIM(")?;
|
write!(f, "TRIM(")?;
|
||||||
if let Some((ident, trim_char)) = trim_where {
|
if let Some((ident, trim_char)) = trim_where {
|
||||||
|
|
|
||||||
|
|
@ -87,9 +87,8 @@ mod tests {
|
||||||
|
|
||||||
assert!(dialect_of!(generic_holder is GenericDialect | AnsiDialect),);
|
assert!(dialect_of!(generic_holder is GenericDialect | AnsiDialect),);
|
||||||
assert!(!dialect_of!(generic_holder is AnsiDialect));
|
assert!(!dialect_of!(generic_holder is AnsiDialect));
|
||||||
|
assert!(dialect_of!(ansi_holder is AnsiDialect));
|
||||||
assert!(dialect_of!(ansi_holder is AnsiDialect));
|
assert!(dialect_of!(ansi_holder is GenericDialect | AnsiDialect));
|
||||||
assert!(dialect_of!(ansi_holder is GenericDialect | AnsiDialect),);
|
assert!(!dialect_of!(ansi_holder is GenericDialect | MsSqlDialect));
|
||||||
assert!(!dialect_of!(ansi_holder is GenericDialect | MsSqlDialect),);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -917,8 +917,18 @@ impl<'a> Parser<'a> {
|
||||||
Ok(Expr::IsNull(Box::new(expr)))
|
Ok(Expr::IsNull(Box::new(expr)))
|
||||||
} else if self.parse_keywords(&[Keyword::NOT, Keyword::NULL]) {
|
} else if self.parse_keywords(&[Keyword::NOT, Keyword::NULL]) {
|
||||||
Ok(Expr::IsNotNull(Box::new(expr)))
|
Ok(Expr::IsNotNull(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 {
|
} else {
|
||||||
self.expected("NULL or NOT NULL after IS", self.peek_token())
|
self.expected(
|
||||||
|
"[NOT] NULL or [NOT] DISTINCT FROM after IS",
|
||||||
|
self.peek_token(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Keyword::NOT | Keyword::IN | Keyword::BETWEEN => {
|
Keyword::NOT | Keyword::IN | Keyword::BETWEEN => {
|
||||||
|
|
|
||||||
|
|
@ -586,6 +586,31 @@ fn parse_is_not_null() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_is_distinct_from() {
|
||||||
|
use self::Expr::*;
|
||||||
|
let sql = "a IS DISTINCT FROM b";
|
||||||
|
assert_eq!(
|
||||||
|
IsDistinctFrom(
|
||||||
|
Box::new(Identifier(Ident::new("a"))),
|
||||||
|
Box::new(Identifier(Ident::new("b")))
|
||||||
|
),
|
||||||
|
verified_expr(sql)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn parse_is_not_distinct_from() {
|
||||||
|
use self::Expr::*;
|
||||||
|
let sql = "a IS NOT DISTINCT FROM b";
|
||||||
|
assert_eq!(
|
||||||
|
IsNotDistinctFrom(
|
||||||
|
Box::new(Identifier(Ident::new("a"))),
|
||||||
|
Box::new(Identifier(Ident::new("b")))
|
||||||
|
),
|
||||||
|
verified_expr(sql)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_not_precedence() {
|
fn parse_not_precedence() {
|
||||||
// NOT has higher precedence than OR/AND, so the following must parse as (NOT true) OR true
|
// NOT has higher precedence than OR/AND, so the following must parse as (NOT true) OR true
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue