Skip to content

Commit c6a0497

Browse files
committed
bq: IN <expr>
1 parent 8e40ac9 commit c6a0497

2 files changed

Lines changed: 46 additions & 15 deletions

File tree

src/ast/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ pub enum Expr {
178178
subquery: Box<Query>,
179179
negated: bool,
180180
},
181+
/// `[ NOT ] IN <in_expr>`
182+
InExpr {
183+
expr: Box<Expr>,
184+
in_expr: Box<Expr>,
185+
negated: bool,
186+
},
181187
/// `<expr> [ NOT ] BETWEEN <low> AND <high>`
182188
Between {
183189
expr: Box<Expr>,
@@ -319,6 +325,17 @@ impl fmt::Display for Expr {
319325
if *negated { "NOT " } else { "" },
320326
subquery
321327
),
328+
Expr::InExpr {
329+
expr,
330+
in_expr,
331+
negated,
332+
} => write!(
333+
f,
334+
"{} {}IN {}",
335+
expr,
336+
if *negated { "NOT " } else { "" },
337+
in_expr,
338+
),
322339
Expr::Between {
323340
expr,
324341
negated,

src/parser.rs

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,11 @@ impl<'a> Parser<'a> {
436436
let window_frame = self.parse_window_frame()?;
437437

438438
let found_rparen = self.consume_token(&Token::RParen);
439-
if partition_by.is_empty() && order_by.is_empty() && window_frame.is_none() && !found_rparen {
439+
if partition_by.is_empty()
440+
&& order_by.is_empty()
441+
&& window_frame.is_none()
442+
&& !found_rparen
443+
{
440444
// try parsing a named window if we failed to parse any part of
441445
// a window spec and we haven't reached the rparen yet
442446
let ident = self.parse_identifier()?;
@@ -1011,23 +1015,33 @@ impl<'a> Parser<'a> {
10111015

10121016
/// Parses the parens following the `[ NOT ] IN` operator
10131017
pub fn parse_in(&mut self, expr: Expr, negated: bool) -> Result<Expr, ParserError> {
1014-
self.expect_token(&Token::LParen)?;
1015-
let in_op = if self.parse_keyword(Keyword::SELECT) || self.parse_keyword(Keyword::WITH) {
1016-
self.prev_token();
1017-
Expr::InSubquery {
1018-
expr: Box::new(expr),
1019-
subquery: Box::new(self.parse_query()?),
1020-
negated,
1021-
}
1018+
if self.consume_token(&Token::LParen) {
1019+
let in_op = if self.parse_keyword(Keyword::SELECT) || self.parse_keyword(Keyword::WITH)
1020+
{
1021+
self.prev_token();
1022+
Expr::InSubquery {
1023+
expr: Box::new(expr),
1024+
subquery: Box::new(self.parse_query()?),
1025+
negated,
1026+
}
1027+
} else {
1028+
Expr::InList {
1029+
expr: Box::new(expr),
1030+
list: self.parse_comma_separated(Parser::parse_expr)?,
1031+
negated,
1032+
}
1033+
};
1034+
self.expect_token(&Token::RParen)?;
1035+
Ok(in_op)
10221036
} else {
1023-
Expr::InList {
1037+
// parse an expr
1038+
let in_expr = self.parse_expr()?;
1039+
Ok(Expr::InExpr {
10241040
expr: Box::new(expr),
1025-
list: self.parse_comma_separated(Parser::parse_expr)?,
1041+
in_expr: Box::new(in_expr),
10261042
negated,
1027-
}
1028-
};
1029-
self.expect_token(&Token::RParen)?;
1030-
Ok(in_op)
1043+
})
1044+
}
10311045
}
10321046

10331047
/// Parses `BETWEEN <low> AND <high>`, assuming the `BETWEEN` keyword was already consumed

0 commit comments

Comments
 (0)