mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-09-03 12:47:21 +00:00
Support HAVING without GROUP BY
...which is weird but allowed: https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#table-expression https://dba.stackexchange.com/a/57453/15599 Also add a test for GROUP BY .. HAVING
This commit is contained in:
parent
d60bdc0b92
commit
eb3450dd51
3 changed files with 30 additions and 2 deletions
|
@ -420,7 +420,7 @@ define_keywords!(
|
||||||
/// can be parsed unambiguously without looking ahead.
|
/// can be parsed unambiguously without looking ahead.
|
||||||
pub const RESERVED_FOR_TABLE_ALIAS: &[&str] = &[
|
pub const RESERVED_FOR_TABLE_ALIAS: &[&str] = &[
|
||||||
// Reserved as both a table and a column alias:
|
// Reserved as both a table and a column alias:
|
||||||
WITH, SELECT, WHERE, GROUP, ORDER, LIMIT, OFFSET, FETCH, UNION, EXCEPT, INTERSECT,
|
WITH, SELECT, WHERE, GROUP, HAVING, ORDER, LIMIT, OFFSET, FETCH, UNION, EXCEPT, INTERSECT,
|
||||||
// Reserved only as a table alias in the `FROM`/`JOIN` clauses:
|
// Reserved only as a table alias in the `FROM`/`JOIN` clauses:
|
||||||
ON, JOIN, INNER, CROSS, FULL, LEFT, RIGHT, NATURAL, USING,
|
ON, JOIN, INNER, CROSS, FULL, LEFT, RIGHT, NATURAL, USING,
|
||||||
];
|
];
|
||||||
|
@ -429,7 +429,7 @@ pub const RESERVED_FOR_TABLE_ALIAS: &[&str] = &[
|
||||||
/// can be parsed unambiguously without looking ahead.
|
/// can be parsed unambiguously without looking ahead.
|
||||||
pub const RESERVED_FOR_COLUMN_ALIAS: &[&str] = &[
|
pub const RESERVED_FOR_COLUMN_ALIAS: &[&str] = &[
|
||||||
// Reserved as both a table and a column alias:
|
// Reserved as both a table and a column alias:
|
||||||
WITH, SELECT, WHERE, GROUP, ORDER, LIMIT, OFFSET, FETCH, UNION, EXCEPT, INTERSECT,
|
WITH, SELECT, WHERE, GROUP, HAVING, ORDER, LIMIT, OFFSET, FETCH, UNION, EXCEPT, INTERSECT,
|
||||||
// Reserved only as a column alias in the `SELECT` clause:
|
// Reserved only as a column alias in the `SELECT` clause:
|
||||||
FROM,
|
FROM,
|
||||||
];
|
];
|
||||||
|
|
|
@ -1566,6 +1566,11 @@ impl Parser {
|
||||||
}
|
}
|
||||||
let projection = self.parse_select_list()?;
|
let projection = self.parse_select_list()?;
|
||||||
|
|
||||||
|
// Note that for keywords to be properly handled here, they need to be
|
||||||
|
// added to `RESERVED_FOR_COLUMN_ALIAS` / `RESERVED_FOR_TABLE_ALIAS`,
|
||||||
|
// otherwise they may be parsed as an alias as part of the `projection`
|
||||||
|
// or `from`.
|
||||||
|
|
||||||
let mut from = vec![];
|
let mut from = vec![];
|
||||||
if self.parse_keyword("FROM") {
|
if self.parse_keyword("FROM") {
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -789,6 +789,29 @@ fn parse_select_group_by() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_select_having() {
|
||||||
|
let sql = "SELECT foo FROM bar GROUP BY foo HAVING COUNT(*) > 1";
|
||||||
|
let select = verified_only_select(sql);
|
||||||
|
assert_eq!(
|
||||||
|
Some(ASTNode::SQLBinaryOp {
|
||||||
|
left: Box::new(ASTNode::SQLFunction(SQLFunction {
|
||||||
|
name: SQLObjectName(vec!["COUNT".to_string()]),
|
||||||
|
args: vec![ASTNode::SQLWildcard],
|
||||||
|
over: None,
|
||||||
|
distinct: false
|
||||||
|
})),
|
||||||
|
op: SQLBinaryOperator::Gt,
|
||||||
|
right: Box::new(ASTNode::SQLValue(Value::Long(1)))
|
||||||
|
}),
|
||||||
|
select.having
|
||||||
|
);
|
||||||
|
|
||||||
|
let sql = "SELECT 'foo' HAVING 1 = 1";
|
||||||
|
let select = verified_only_select(sql);
|
||||||
|
assert!(select.having.is_some());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_limit_accepts_all() {
|
fn parse_limit_accepts_all() {
|
||||||
one_statement_parses_to(
|
one_statement_parses_to(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue