Skip to content

Commit 6a54d27

Browse files
authored
feat: Support ANY/ALL subquery (#42)
1 parent 347f769 commit 6a54d27

File tree

3 files changed

+64
-3
lines changed

3 files changed

+64
-3
lines changed

src/ast/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,9 @@ pub enum Expr {
341341
/// A parenthesized subquery `(SELECT ...)`, used in expression like
342342
/// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
343343
Subquery(Box<Query>),
344+
/// An ANY/ALL subquery `op ANY(SELECT ...)`, used in expression like
345+
/// `SELECT x = ANY(subquery) AS c`
346+
AnyAllSubquery(Box<Query>),
344347
/// The `LISTAGG` function `SELECT LISTAGG(...) WITHIN GROUP (ORDER BY ...)`
345348
ListAgg(ListAgg),
346349
/// The `ARRAY_AGG` function `SELECT ARRAY_AGG(... ORDER BY ...)`
@@ -542,6 +545,7 @@ impl fmt::Display for Expr {
542545
}
543546
Expr::Exists(s) => write!(f, "EXISTS ({})", s),
544547
Expr::Subquery(s) => write!(f, "({})", s),
548+
Expr::AnyAllSubquery(s) => write!(f, "{}", s),
545549
Expr::ArraySubquery(s) => write!(f, "ARRAY({})", s),
546550
Expr::ListAgg(listagg) => write!(f, "{}", listagg),
547551
Expr::ArrayAgg(arrayagg) => write!(f, "{}", arrayagg),

src/parser.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -1247,14 +1247,20 @@ impl<'a> Parser<'a> {
12471247
};
12481248

12491249
if let Some(op) = regular_binary_operator {
1250-
if let Some(keyword) = self.parse_one_of_keywords(&[Keyword::ANY, Keyword::ALL]) {
1250+
if let Some(keyword) =
1251+
self.parse_one_of_keywords(&[Keyword::ANY, Keyword::SOME, Keyword::ALL])
1252+
{
12511253
self.expect_token(&Token::LParen)?;
1252-
let right = self.parse_subexpr(precedence)?;
1254+
let right = if let Ok(query) = self.parse_query() {
1255+
Expr::AnyAllSubquery(Box::new(query))
1256+
} else {
1257+
self.parse_subexpr(precedence)?
1258+
};
12531259
self.expect_token(&Token::RParen)?;
12541260

12551261
let right = match keyword {
12561262
Keyword::ALL => Box::new(Expr::AllOp(Box::new(right))),
1257-
Keyword::ANY => Box::new(Expr::AnyOp(Box::new(right))),
1263+
Keyword::ANY | Keyword::SOME => Box::new(Expr::AnyOp(Box::new(right))),
12581264
_ => unreachable!(),
12591265
};
12601266

tests/sqlparser_common.rs

+51
Original file line numberDiff line numberDiff line change
@@ -1145,6 +1145,11 @@ fn parse_binary_any() {
11451145
);
11461146
}
11471147

1148+
#[test]
1149+
fn parse_select_some() {
1150+
one_statement_parses_to("SELECT a = SOME(b)", "SELECT a = ANY(b)");
1151+
}
1152+
11481153
#[test]
11491154
fn parse_binary_all() {
11501155
let select = verified_only_select("SELECT a = ALL(b)");
@@ -1158,6 +1163,52 @@ fn parse_binary_all() {
11581163
);
11591164
}
11601165

1166+
#[test]
1167+
fn parse_binary_any_subquery() {
1168+
let select = verified_only_select("SELECT a <> ANY(SELECT b FROM c)");
1169+
assert_eq!(
1170+
SelectItem::UnnamedExpr(Expr::BinaryOp {
1171+
left: Box::new(Expr::Identifier(Ident::new("a"))),
1172+
op: BinaryOperator::NotEq,
1173+
right: Box::new(Expr::AnyOp(Box::new(Expr::AnyAllSubquery(Box::new(
1174+
Query {
1175+
with: None,
1176+
body: SetExpr::Select(Box::new(Select {
1177+
distinct: false,
1178+
top: None,
1179+
projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident::new(
1180+
"b"
1181+
)))],
1182+
into: None,
1183+
from: vec![TableWithJoins {
1184+
relation: TableFactor::Table {
1185+
name: ObjectName(vec![Ident::new("c")]),
1186+
alias: None,
1187+
args: vec![],
1188+
with_hints: vec![],
1189+
},
1190+
joins: vec![]
1191+
}],
1192+
lateral_views: vec![],
1193+
selection: None,
1194+
group_by: vec![],
1195+
cluster_by: vec![],
1196+
distribute_by: vec![],
1197+
sort_by: vec![],
1198+
having: None
1199+
})),
1200+
order_by: vec![],
1201+
limit: None,
1202+
offset: None,
1203+
fetch: None,
1204+
lock: None,
1205+
}
1206+
))))),
1207+
}),
1208+
select.projection[0]
1209+
);
1210+
}
1211+
11611212
#[test]
11621213
fn parse_logical_xor() {
11631214
let sql = "SELECT true XOR true, false XOR false, true XOR false, false XOR true";

0 commit comments

Comments
 (0)