Skip to content

Commit 58372cf

Browse files
committed
Add support for PostgreSQL 'IN <SetExpression>'
1 parent 776b10a commit 58372cf

File tree

6 files changed

+32
-6
lines changed

6 files changed

+32
-6
lines changed

src/ast/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ pub enum Expr {
724724
/// `[ NOT ] IN (SELECT ...)`
725725
InSubquery {
726726
expr: Box<Expr>,
727-
subquery: Box<Query>,
727+
subquery: Box<SetExpr>,
728728
negated: bool,
729729
},
730730
/// `[ NOT ] IN UNNEST(array_expression)`

src/dialect/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,11 @@ pub trait Dialect: Debug + Any {
303303
false
304304
}
305305

306+
/// Returns true if the dialect supports `IN` with query bodies
307+
fn supports_in_query_body(&self) -> bool {
308+
false
309+
}
310+
306311
/// Returns true if the dialect supports `BEGIN {DEFERRED | IMMEDIATE | EXCLUSIVE | TRY | CATCH} [TRANSACTION]` statements
307312
fn supports_start_transaction_modifier(&self) -> bool {
308313
false

src/dialect/postgresql.rs

+4
Original file line numberDiff line numberDiff line change
@@ -258,4 +258,8 @@ impl Dialect for PostgreSqlDialect {
258258
fn supports_set_names(&self) -> bool {
259259
true
260260
}
261+
262+
fn supports_in_query_body(&self) -> bool {
263+
true
264+
}
261265
}

src/parser/mod.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -3744,10 +3744,18 @@ impl<'a> Parser<'a> {
37443744
self.expect_token(&Token::LParen)?;
37453745
let in_op = if self.parse_keyword(Keyword::SELECT) || self.parse_keyword(Keyword::WITH) {
37463746
self.prev_token();
3747-
Expr::InSubquery {
3748-
expr: Box::new(expr),
3749-
subquery: self.parse_query()?,
3750-
negated,
3747+
if self.dialect.supports_in_query_body() {
3748+
Expr::InSubquery {
3749+
expr: Box::new(expr),
3750+
subquery: self.parse_query_body(self.dialect.prec_unknown())?,
3751+
negated,
3752+
}
3753+
} else {
3754+
Expr::InSubquery {
3755+
expr: Box::new(expr),
3756+
subquery: Box::new(SetExpr::Query(self.parse_query()?)),
3757+
negated,
3758+
}
37513759
}
37523760
} else {
37533761
Expr::InList {

tests/sqlparser_common.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2224,7 +2224,9 @@ fn parse_in_subquery() {
22242224
assert_eq!(
22252225
Expr::InSubquery {
22262226
expr: Box::new(Expr::Identifier(Ident::new("segment"))),
2227-
subquery: Box::new(verified_query("SELECT segm FROM bar")),
2227+
subquery: Box::new(SetExpr::Query(Box::new(verified_query(
2228+
"SELECT segm FROM bar"
2229+
)))),
22282230
negated: false,
22292231
},
22302232
select.selection.unwrap()

tests/sqlparser_postgres.rs

+7
Original file line numberDiff line numberDiff line change
@@ -4063,6 +4063,13 @@ fn parse_update_in_with_subquery() {
40634063
pg_and_generic().verified_stmt(r#"WITH "result" AS (UPDATE "Hero" SET "name" = 'Captain America', "number_of_movies" = "number_of_movies" + 1 WHERE "secret_identity" = 'Sam Wilson' RETURNING "id", "name", "secret_identity", "number_of_movies") SELECT * FROM "result""#);
40644064
}
40654065

4066+
#[test]
4067+
fn parse_in_with_set_expression() {
4068+
pg().verified_stmt(
4069+
r#"SELECT 1 FROM t WHERE t.id IN ((SELECT id FROM t) UNION (SELECT id FROM t))"#,
4070+
);
4071+
}
4072+
40664073
#[test]
40674074
fn parse_create_function() {
40684075
let sql = "CREATE FUNCTION add(INTEGER, INTEGER) RETURNS INTEGER LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE AS 'select $1 + $2;'";

0 commit comments

Comments
 (0)