mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-21 14:40:18 +00:00
Support IN UNNEST(expression)
(#426)
* feat: support `IN UNNEST(expression)` * Add test for NOT IN UNNEST
This commit is contained in:
parent
2ebe18a94e
commit
0d1c5d1205
3 changed files with 50 additions and 0 deletions
|
@ -189,6 +189,12 @@ pub enum Expr {
|
||||||
subquery: Box<Query>,
|
subquery: Box<Query>,
|
||||||
negated: bool,
|
negated: bool,
|
||||||
},
|
},
|
||||||
|
/// `[ NOT ] IN UNNEST(array_expression)`
|
||||||
|
InUnnest {
|
||||||
|
expr: Box<Expr>,
|
||||||
|
array_expr: Box<Expr>,
|
||||||
|
negated: bool,
|
||||||
|
},
|
||||||
/// `<expr> [ NOT ] BETWEEN <low> AND <high>`
|
/// `<expr> [ NOT ] BETWEEN <low> AND <high>`
|
||||||
Between {
|
Between {
|
||||||
expr: Box<Expr>,
|
expr: Box<Expr>,
|
||||||
|
@ -335,6 +341,17 @@ impl fmt::Display for Expr {
|
||||||
if *negated { "NOT " } else { "" },
|
if *negated { "NOT " } else { "" },
|
||||||
subquery
|
subquery
|
||||||
),
|
),
|
||||||
|
Expr::InUnnest {
|
||||||
|
expr,
|
||||||
|
array_expr,
|
||||||
|
negated,
|
||||||
|
} => write!(
|
||||||
|
f,
|
||||||
|
"{} {}IN UNNEST({})",
|
||||||
|
expr,
|
||||||
|
if *negated { "NOT " } else { "" },
|
||||||
|
array_expr
|
||||||
|
),
|
||||||
Expr::Between {
|
Expr::Between {
|
||||||
expr,
|
expr,
|
||||||
negated,
|
negated,
|
||||||
|
|
|
@ -1143,6 +1143,18 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Parses the parens following the `[ NOT ] IN` operator
|
/// Parses the parens following the `[ NOT ] IN` operator
|
||||||
pub fn parse_in(&mut self, expr: Expr, negated: bool) -> Result<Expr, ParserError> {
|
pub fn parse_in(&mut self, expr: Expr, negated: bool) -> Result<Expr, ParserError> {
|
||||||
|
// BigQuery allows `IN UNNEST(array_expression)`
|
||||||
|
// https://cloud.google.com/bigquery/docs/reference/standard-sql/operators#in_operators
|
||||||
|
if self.parse_keyword(Keyword::UNNEST) {
|
||||||
|
self.expect_token(&Token::LParen)?;
|
||||||
|
let array_expr = self.parse_expr()?;
|
||||||
|
self.expect_token(&Token::RParen)?;
|
||||||
|
return Ok(Expr::InUnnest {
|
||||||
|
expr: Box::new(expr),
|
||||||
|
array_expr: Box::new(array_expr),
|
||||||
|
negated,
|
||||||
|
});
|
||||||
|
}
|
||||||
self.expect_token(&Token::LParen)?;
|
self.expect_token(&Token::LParen)?;
|
||||||
let in_op = if self.parse_keyword(Keyword::SELECT) || self.parse_keyword(Keyword::WITH) {
|
let in_op = if self.parse_keyword(Keyword::SELECT) || self.parse_keyword(Keyword::WITH) {
|
||||||
self.prev_token();
|
self.prev_token();
|
||||||
|
|
|
@ -903,6 +903,27 @@ fn parse_in_subquery() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_in_unnest() {
|
||||||
|
fn chk(negated: bool) {
|
||||||
|
let sql = &format!(
|
||||||
|
"SELECT * FROM customers WHERE segment {}IN UNNEST(expr)",
|
||||||
|
if negated { "NOT " } else { "" }
|
||||||
|
);
|
||||||
|
let select = verified_only_select(sql);
|
||||||
|
assert_eq!(
|
||||||
|
Expr::InUnnest {
|
||||||
|
expr: Box::new(Expr::Identifier(Ident::new("segment"))),
|
||||||
|
array_expr: Box::new(verified_expr("expr")),
|
||||||
|
negated,
|
||||||
|
},
|
||||||
|
select.selection.unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
chk(false);
|
||||||
|
chk(true);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_string_agg() {
|
fn parse_string_agg() {
|
||||||
let sql = "SELECT a || b";
|
let sql = "SELECT a || b";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue