feat: Group By All (#964)

Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
Berkay Şahin 2023-09-08 13:47:56 +03:00 committed by GitHub
parent 2593dcfb79
commit bb7b05e106
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 85 additions and 36 deletions

View file

@ -36,7 +36,7 @@ pub use self::ddl::{
}; };
pub use self::operator::{BinaryOperator, UnaryOperator}; pub use self::operator::{BinaryOperator, UnaryOperator};
pub use self::query::{ pub use self::query::{
Cte, Distinct, ExceptSelectItem, ExcludeSelectItem, Fetch, IdentWithAlias, Join, Cte, Distinct, ExceptSelectItem, ExcludeSelectItem, Fetch, GroupByExpr, IdentWithAlias, Join,
JoinConstraint, JoinOperator, LateralView, LockClause, LockType, NamedWindowDefinition, JoinConstraint, JoinOperator, LateralView, LockClause, LockType, NamedWindowDefinition,
NonBlock, Offset, OffsetRows, OrderByExpr, Query, RenameSelectItem, ReplaceSelectElement, NonBlock, Offset, OffsetRows, OrderByExpr, Query, RenameSelectItem, ReplaceSelectElement,
ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, SetOperator, SetQuantifier, Table, ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, SetOperator, SetQuantifier, Table,

View file

@ -214,7 +214,7 @@ pub struct Select {
/// WHERE /// WHERE
pub selection: Option<Expr>, pub selection: Option<Expr>,
/// GROUP BY /// GROUP BY
pub group_by: Vec<Expr>, pub group_by: GroupByExpr,
/// CLUSTER BY (Hive) /// CLUSTER BY (Hive)
pub cluster_by: Vec<Expr>, pub cluster_by: Vec<Expr>,
/// DISTRIBUTE BY (Hive) /// DISTRIBUTE BY (Hive)
@ -255,8 +255,13 @@ impl fmt::Display for Select {
if let Some(ref selection) = self.selection { if let Some(ref selection) = self.selection {
write!(f, " WHERE {selection}")?; write!(f, " WHERE {selection}")?;
} }
if !self.group_by.is_empty() { match &self.group_by {
write!(f, " GROUP BY {}", display_comma_separated(&self.group_by))?; GroupByExpr::All => write!(f, " GROUP BY ALL")?,
GroupByExpr::Expressions(exprs) => {
if !exprs.is_empty() {
write!(f, " GROUP BY {}", display_comma_separated(exprs))?;
}
}
} }
if !self.cluster_by.is_empty() { if !self.cluster_by.is_empty() {
write!( write!(
@ -1218,3 +1223,29 @@ impl fmt::Display for SelectInto {
write!(f, "INTO{}{}{} {}", temporary, unlogged, table, self.name) write!(f, "INTO{}{}{} {}", temporary, unlogged, table, self.name)
} }
} }
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum GroupByExpr {
/// ALL syntax of [Snowflake], and [DuckDB]
///
/// [Snowflake]: <https://docs.snowflake.com/en/sql-reference/constructs/group-by#label-group-by-all-columns>
/// [DuckDB]: <https://duckdb.org/docs/sql/query_syntax/groupby.html>
All,
/// Expressions
Expressions(Vec<Expr>),
}
impl fmt::Display for GroupByExpr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
GroupByExpr::All => write!(f, "GROUP BY ALL"),
GroupByExpr::Expressions(col_names) => {
let col_names = display_comma_separated(col_names);
write!(f, "GROUP BY ({col_names})")
}
}
}
}

View file

@ -5662,9 +5662,13 @@ impl<'a> Parser<'a> {
}; };
let group_by = if self.parse_keywords(&[Keyword::GROUP, Keyword::BY]) { let group_by = if self.parse_keywords(&[Keyword::GROUP, Keyword::BY]) {
self.parse_comma_separated(Parser::parse_group_by_expr)? if self.parse_keyword(Keyword::ALL) {
GroupByExpr::All
} else {
GroupByExpr::Expressions(self.parse_comma_separated(Parser::parse_group_by_expr)?)
}
} else { } else {
vec![] GroupByExpr::Expressions(vec![])
}; };
let cluster_by = if self.parse_keywords(&[Keyword::CLUSTER, Keyword::BY]) { let cluster_by = if self.parse_keywords(&[Keyword::CLUSTER, Keyword::BY]) {

View file

@ -97,7 +97,7 @@ fn parse_map_access_expr() {
right: Box::new(Expr::Value(Value::SingleQuotedString("foo".to_string()))) right: Box::new(Expr::Value(Value::SingleQuotedString("foo".to_string())))
}) })
}), }),
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],

View file

@ -247,7 +247,9 @@ fn parse_update_set_from() {
}], }],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![Expr::Identifier(Ident::new("id"))], group_by: GroupByExpr::Expressions(vec![Expr::Identifier(Ident::new(
"id"
))]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],
@ -1808,10 +1810,10 @@ fn parse_select_group_by() {
let sql = "SELECT id, fname, lname FROM customer GROUP BY lname, fname"; let sql = "SELECT id, fname, lname FROM customer GROUP BY lname, fname";
let select = verified_only_select(sql); let select = verified_only_select(sql);
assert_eq!( assert_eq!(
vec![ GroupByExpr::Expressions(vec![
Expr::Identifier(Ident::new("lname")), Expr::Identifier(Ident::new("lname")),
Expr::Identifier(Ident::new("fname")), Expr::Identifier(Ident::new("fname")),
], ]),
select.group_by select.group_by
); );
@ -1822,6 +1824,18 @@ fn parse_select_group_by() {
); );
} }
#[test]
fn parse_select_group_by_all() {
let sql = "SELECT id, fname, lname, SUM(order) FROM customer GROUP BY ALL";
let select = verified_only_select(sql);
assert_eq!(GroupByExpr::All, select.group_by);
one_statement_parses_to(
"SELECT id, fname, lname, SUM(order) FROM customer GROUP BY ALL",
"SELECT id, fname, lname, SUM(order) FROM customer GROUP BY ALL",
);
}
#[test] #[test]
fn parse_select_having() { fn parse_select_having() {
let sql = "SELECT foo FROM bar GROUP BY foo HAVING COUNT(*) > 1"; let sql = "SELECT foo FROM bar GROUP BY foo HAVING COUNT(*) > 1";
@ -3543,7 +3557,7 @@ fn test_parse_named_window() {
}], }],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],
@ -3930,7 +3944,7 @@ fn parse_interval_and_or_xor() {
}), }),
}), }),
}), }),
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],
@ -6333,7 +6347,7 @@ fn parse_merge() {
}], }],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],

View file

@ -161,7 +161,7 @@ fn test_select_union_by_name() {
}], }],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],
@ -194,7 +194,7 @@ fn test_select_union_by_name() {
}], }],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],
@ -236,7 +236,7 @@ fn test_select_union_by_name() {
}], }],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],
@ -269,7 +269,7 @@ fn test_select_union_by_name() {
}], }],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],

View file

@ -103,7 +103,7 @@ fn parse_create_procedure() {
from: vec![], from: vec![],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],
@ -519,7 +519,7 @@ fn parse_substring_in_select() {
}], }],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],

View file

@ -496,7 +496,7 @@ fn parse_escaped_quote_identifiers_with_escape() {
from: vec![], from: vec![],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],
@ -538,7 +538,7 @@ fn parse_escaped_quote_identifiers_with_no_escape() {
from: vec![], from: vec![],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],
@ -577,7 +577,7 @@ fn parse_escaped_backticks_with_escape() {
from: vec![], from: vec![],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],
@ -616,7 +616,7 @@ fn parse_escaped_backticks_with_no_escape() {
from: vec![], from: vec![],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],
@ -1100,7 +1100,7 @@ fn parse_select_with_numeric_prefix_column_name() {
}], }],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],
@ -1149,7 +1149,7 @@ fn parse_select_with_concatenation_of_exp_number_and_numeric_prefix_column() {
}], }],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],
@ -1325,7 +1325,7 @@ fn parse_substring_in_select() {
}], }],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],
@ -1604,7 +1604,7 @@ fn parse_hex_string_introducer() {
from: vec![], from: vec![],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],

View file

@ -990,7 +990,7 @@ fn parse_copy_to() {
from: vec![], from: vec![],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
having: None, having: None,
named_window: vec![], named_window: vec![],
cluster_by: vec![], cluster_by: vec![],
@ -2019,7 +2019,7 @@ fn parse_array_subquery_expr() {
from: vec![], from: vec![],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],
@ -2035,7 +2035,7 @@ fn parse_array_subquery_expr() {
from: vec![], from: vec![],
lateral_views: vec![], lateral_views: vec![],
selection: None, selection: None,
group_by: vec![], group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![], cluster_by: vec![],
distribute_by: vec![], distribute_by: vec![],
sort_by: vec![], sort_by: vec![],
@ -3321,14 +3321,14 @@ fn parse_select_group_by_grouping_sets() {
"SELECT brand, size, sum(sales) FROM items_sold GROUP BY size, GROUPING SETS ((brand), (size), ())" "SELECT brand, size, sum(sales) FROM items_sold GROUP BY size, GROUPING SETS ((brand), (size), ())"
); );
assert_eq!( assert_eq!(
vec![ GroupByExpr::Expressions(vec![
Expr::Identifier(Ident::new("size")), Expr::Identifier(Ident::new("size")),
Expr::GroupingSets(vec![ Expr::GroupingSets(vec![
vec![Expr::Identifier(Ident::new("brand"))], vec![Expr::Identifier(Ident::new("brand"))],
vec![Expr::Identifier(Ident::new("size"))], vec![Expr::Identifier(Ident::new("size"))],
vec![], vec![],
]), ]),
], ]),
select.group_by select.group_by
); );
} }
@ -3339,13 +3339,13 @@ fn parse_select_group_by_rollup() {
"SELECT brand, size, sum(sales) FROM items_sold GROUP BY size, ROLLUP (brand, size)", "SELECT brand, size, sum(sales) FROM items_sold GROUP BY size, ROLLUP (brand, size)",
); );
assert_eq!( assert_eq!(
vec![ GroupByExpr::Expressions(vec![
Expr::Identifier(Ident::new("size")), Expr::Identifier(Ident::new("size")),
Expr::Rollup(vec![ Expr::Rollup(vec![
vec![Expr::Identifier(Ident::new("brand"))], vec![Expr::Identifier(Ident::new("brand"))],
vec![Expr::Identifier(Ident::new("size"))], vec![Expr::Identifier(Ident::new("size"))],
]), ]),
], ]),
select.group_by select.group_by
); );
} }
@ -3356,13 +3356,13 @@ fn parse_select_group_by_cube() {
"SELECT brand, size, sum(sales) FROM items_sold GROUP BY size, CUBE (brand, size)", "SELECT brand, size, sum(sales) FROM items_sold GROUP BY size, CUBE (brand, size)",
); );
assert_eq!( assert_eq!(
vec![ GroupByExpr::Expressions(vec![
Expr::Identifier(Ident::new("size")), Expr::Identifier(Ident::new("size")),
Expr::Cube(vec![ Expr::Cube(vec![
vec![Expr::Identifier(Ident::new("brand"))], vec![Expr::Identifier(Ident::new("brand"))],
vec![Expr::Identifier(Ident::new("size"))], vec![Expr::Identifier(Ident::new("size"))],
]), ]),
], ]),
select.group_by select.group_by
); );
} }