Skip to content

Commit 2202e80

Browse files
committed
add InExpr (workaround for Sigma parameter substitution)
1 parent 306494a commit 2202e80

3 files changed

Lines changed: 47 additions & 18 deletions

File tree

src/ast/mod.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,13 @@ pub enum Expr {
412412
subquery: Box<Query>,
413413
negated: bool,
414414
},
415+
/// XXX not valid SQL syntax, this is a hack needed to support parameter substitution
416+
/// `[ NOT ] IN <in_expr>`
417+
InExpr {
418+
expr: Box<Expr>,
419+
in_expr: Box<Expr>,
420+
negated: bool,
421+
},
415422
/// `[ NOT ] IN UNNEST(array_expression)`
416423
InUnnest {
417424
expr: Box<Expr>,
@@ -734,6 +741,17 @@ impl fmt::Display for Expr {
734741
if *negated { "NOT " } else { "" },
735742
subquery
736743
),
744+
Expr::InExpr {
745+
expr,
746+
in_expr,
747+
negated,
748+
} => write!(
749+
f,
750+
"{} {}IN {}",
751+
expr,
752+
if *negated { "NOT " } else { "" },
753+
in_expr,
754+
),
737755
Expr::InUnnest {
738756
expr,
739757
array_expr,

src/parser/mod.rs

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2402,27 +2402,37 @@ impl<'a> Parser<'a> {
24022402
negated,
24032403
});
24042404
}
2405-
self.expect_token(&Token::LParen)?;
2406-
let in_op = if self.parse_keyword(Keyword::SELECT) || self.parse_keyword(Keyword::WITH) {
2407-
self.prev_token();
2408-
Expr::InSubquery {
2409-
expr: Box::new(expr),
2410-
subquery: Box::new(self.parse_query()?),
2411-
negated,
2412-
}
2405+
if self.consume_token(&Token::LParen) {
2406+
let in_op = if self.parse_keyword(Keyword::SELECT) || self.parse_keyword(Keyword::WITH)
2407+
{
2408+
self.prev_token();
2409+
Expr::InSubquery {
2410+
expr: Box::new(expr),
2411+
subquery: Box::new(self.parse_query()?),
2412+
negated,
2413+
}
2414+
} else {
2415+
Expr::InList {
2416+
expr: Box::new(expr),
2417+
list: if self.dialect.supports_in_empty_list() {
2418+
self.parse_comma_separated0(Parser::parse_expr)?
2419+
} else {
2420+
self.parse_comma_separated(Parser::parse_expr)?
2421+
},
2422+
negated,
2423+
}
2424+
};
2425+
self.expect_token(&Token::RParen)?;
2426+
Ok(in_op)
24132427
} else {
2414-
Expr::InList {
2428+
// parse an expr
2429+
let in_expr = self.parse_expr()?;
2430+
Ok(Expr::InExpr {
24152431
expr: Box::new(expr),
2416-
list: if self.dialect.supports_in_empty_list() {
2417-
self.parse_comma_separated0(Parser::parse_expr)?
2418-
} else {
2419-
self.parse_comma_separated(Parser::parse_expr)?
2420-
},
2432+
in_expr: Box::new(in_expr),
24212433
negated,
2422-
}
2423-
};
2424-
self.expect_token(&Token::RParen)?;
2425-
Ok(in_op)
2434+
})
2435+
}
24262436
}
24272437

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

tests/sqlparser_common.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1630,6 +1630,7 @@ fn parse_in_unnest() {
16301630
}
16311631

16321632
#[test]
1633+
#[ignore]
16331634
fn parse_in_error() {
16341635
// <expr> IN <expr> is no valid
16351636
let sql = "SELECT * FROM customers WHERE segment in segment";

0 commit comments

Comments
 (0)