Skip to content
This repository was archived by the owner on Dec 25, 2019. It is now read-only.

Commit 91a7f26

Browse files
authored
Merge pull request #12 from jamii/any
Parse ALL/SOME/ANY
2 parents 2e53850 + fb7dd77 commit 91a7f26

4 files changed

Lines changed: 114 additions & 5 deletions

File tree

src/ast/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,19 @@ pub enum Expr {
192192
/// A parenthesized subquery `(SELECT ...)`, used in expression like
193193
/// `SELECT (subquery) AS x` or `WHERE (subquery) = x`
194194
Subquery(Box<Query>),
195+
/// `<expr> <op> ANY/SOME (<query>)`
196+
Any {
197+
left: Box<Expr>,
198+
op: BinaryOperator,
199+
right: Box<Query>,
200+
some: bool, // just tracks which syntax was used
201+
},
202+
/// `<expr> <op> ALL (<query>)`
203+
All {
204+
left: Box<Expr>,
205+
op: BinaryOperator,
206+
right: Box<Query>,
207+
}
195208
}
196209

197210
impl fmt::Display for Expr {
@@ -267,6 +280,8 @@ impl fmt::Display for Expr {
267280
}
268281
Expr::Exists(s) => write!(f, "EXISTS ({})", s),
269282
Expr::Subquery(s) => write!(f, "({})", s),
283+
Expr::Any{left, op, right, some} => write!(f, "{} {} {} ({})", left, op, if *some { "SOME" } else { "ANY" }, right),
284+
Expr::All{left, op, right} => write!(f, "{} {} ALL ({})", left, op, right),
270285
}
271286
}
272287
}

src/ast/visit_macro.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,14 @@ macro_rules! make_visitor {
278278
visit_subquery(self, subquery)
279279
}
280280

281+
fn visit_any(&mut self, left: &'ast $($mut)* Expr, op: &'ast $($mut)* BinaryOperator, right: &'ast $($mut)* Query) {
282+
visit_any(self, left, op, right)
283+
}
284+
285+
fn visit_all(&mut self, left: &'ast $($mut)* Expr, op: &'ast $($mut)* BinaryOperator, right: &'ast $($mut)* Query) {
286+
visit_all(self, left, op, right)
287+
}
288+
281289
fn visit_insert(
282290
&mut self,
283291
table_name: &'ast $($mut)* ObjectName,
@@ -888,6 +896,8 @@ macro_rules! make_visitor {
888896
),
889897
Expr::Exists(query) => visitor.visit_exists(query),
890898
Expr::Subquery(query) => visitor.visit_subquery(query),
899+
Expr::Any{left, op, right, some: _} => visitor.visit_any(left, op, right),
900+
Expr::All{left, op, right} => visitor.visit_all(left, op, right),
891901
}
892902
}
893903

@@ -1089,6 +1099,14 @@ macro_rules! make_visitor {
10891099
visitor.visit_query(subquery)
10901100
}
10911101

1102+
pub fn visit_any<'ast, V: $name<'ast> + ?Sized>(visitor: &mut V, left: &'ast $($mut)* Expr, op: &'ast $($mut)* BinaryOperator, right: &'ast $($mut)* Query) {
1103+
visitor.visit_any(left, op, right)
1104+
}
1105+
1106+
pub fn visit_all<'ast, V: $name<'ast> + ?Sized>(visitor: &mut V, left: &'ast $($mut)* Expr, op: &'ast $($mut)* BinaryOperator, right: &'ast $($mut)* Query) {
1107+
visitor.visit_all(left, op, right)
1108+
}
1109+
10921110
pub fn visit_insert<'ast, V: $name<'ast> + ?Sized>(
10931111
visitor: &mut V,
10941112
table_name: &'ast $($mut)* ObjectName,

src/parser.rs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -670,11 +670,38 @@ impl Parser {
670670
};
671671

672672
if let Some(op) = regular_binary_operator {
673-
Ok(Expr::BinaryOp {
674-
left: Box::new(expr),
675-
op,
676-
right: Box::new(self.parse_subexpr(precedence)?),
677-
})
673+
let any = self.parse_keyword("ANY");
674+
let some = !any && self.parse_keyword("SOME");
675+
let all = !any && !some && self.parse_keyword("ALL");
676+
if any || some || all {
677+
use BinaryOperator::*;
678+
match op {
679+
Eq | NotEq | Gt | GtEq | Lt | LtEq => (),
680+
_ => self.expected("comparison operator", Some(tok))?,
681+
}
682+
self.expect_token(&Token::LParen)?;
683+
let query = self.parse_query()?;
684+
self.expect_token(&Token::RParen)?;
685+
if any || some {
686+
Ok(Expr::Any{
687+
left: Box::new(expr),
688+
op,
689+
right: Box::new(query),
690+
some,
691+
})
692+
} else {
693+
Ok(Expr::All{
694+
left: Box::new(expr),
695+
op,
696+
right: Box::new(query),
697+
})}
698+
} else {
699+
Ok(Expr::BinaryOp {
700+
left: Box::new(expr),
701+
op,
702+
right: Box::new(self.parse_subexpr(precedence)?),
703+
})
704+
}
678705
} else if let Token::Word(ref k) = tok {
679706
match k.keyword.as_ref() {
680707
"IS" => {

tests/sqlparser_common.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2415,6 +2415,55 @@ fn parse_scalar_subqueries() {
24152415
});
24162416
}
24172417

2418+
#[test]
2419+
fn parse_any_some_all() {
2420+
let sql = "1 < ANY (SELECT 2)";
2421+
assert_matches!(verified_expr(sql), Expr::Any {
2422+
op: BinaryOperator::Lt, ..
2423+
//left: box Expr,
2424+
//right: box Query { .. },
2425+
});
2426+
2427+
let sql = "1 < SOME (SELECT 2)";
2428+
assert_matches!(verified_expr(sql), Expr::Any {
2429+
op: BinaryOperator::Lt, ..
2430+
//left: box Expr,
2431+
//right: box Query { .. },
2432+
});
2433+
2434+
let sql = "1 < ALL (SELECT 2)";
2435+
assert_matches!(verified_expr(sql), Expr::All {
2436+
op: BinaryOperator::Lt, ..
2437+
//left: box Expr,
2438+
//right: box Query { .. },
2439+
});
2440+
2441+
let res = parse_sql_statements("SELECT 1 WHERE 1 < ANY SELECT 2");
2442+
assert_eq!(
2443+
ParserError::ParserError("Expected (, found: SELECT".to_string()),
2444+
res.unwrap_err()
2445+
);
2446+
2447+
let res = parse_sql_statements("SELECT 1 WHERE 1 < NONE (SELECT 2)");
2448+
assert_eq!(
2449+
// TODO this is a pretty unhelpful error - it started parsing "NONE (SELECT" as applying the function NONE to the argument SELECT
2450+
ParserError::ParserError("Expected ), found: 2".to_string()),
2451+
res.unwrap_err()
2452+
);
2453+
2454+
let res = parse_sql_statements("SELECT 1 WHERE 1 < ANY (SELECT 2");
2455+
assert_eq!(
2456+
ParserError::ParserError("Expected ), found: EOF".to_string()),
2457+
res.unwrap_err()
2458+
);
2459+
2460+
let res = parse_sql_statements("SELECT 1 WHERE 1 + ANY (SELECT 2)");
2461+
assert_eq!(
2462+
ParserError::ParserError("Expected comparison operator, found: +".to_string()),
2463+
res.unwrap_err()
2464+
);
2465+
}
2466+
24182467
#[test]
24192468
fn parse_exists_subquery() {
24202469
let expected_inner = verified_query("SELECT 1");

0 commit comments

Comments
 (0)