mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-19 13:40:15 +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>,
|
||||
negated: bool,
|
||||
},
|
||||
/// `[ NOT ] IN UNNEST(array_expression)`
|
||||
InUnnest {
|
||||
expr: Box<Expr>,
|
||||
array_expr: Box<Expr>,
|
||||
negated: bool,
|
||||
},
|
||||
/// `<expr> [ NOT ] BETWEEN <low> AND <high>`
|
||||
Between {
|
||||
expr: Box<Expr>,
|
||||
|
@ -335,6 +341,17 @@ impl fmt::Display for Expr {
|
|||
if *negated { "NOT " } else { "" },
|
||||
subquery
|
||||
),
|
||||
Expr::InUnnest {
|
||||
expr,
|
||||
array_expr,
|
||||
negated,
|
||||
} => write!(
|
||||
f,
|
||||
"{} {}IN UNNEST({})",
|
||||
expr,
|
||||
if *negated { "NOT " } else { "" },
|
||||
array_expr
|
||||
),
|
||||
Expr::Between {
|
||||
expr,
|
||||
negated,
|
||||
|
|
|
@ -1143,6 +1143,18 @@ impl<'a> Parser<'a> {
|
|||
|
||||
/// Parses the parens following the `[ NOT ] IN` operator
|
||||
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)?;
|
||||
let in_op = if self.parse_keyword(Keyword::SELECT) || self.parse_keyword(Keyword::WITH) {
|
||||
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]
|
||||
fn parse_string_agg() {
|
||||
let sql = "SELECT a || b";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue