Skip to content

Commit

Permalink
feat: Group By All (apache#964)
Browse files Browse the repository at this point in the history
Co-authored-by: Andrew Lamb <[email protected]>
  • Loading branch information
2 people authored and serprex committed Nov 6, 2023
1 parent ce8050e commit b235d64
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 36 deletions.
2 changes: 1 addition & 1 deletion src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub use self::ddl::{
};
pub use self::operator::{BinaryOperator, UnaryOperator};
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,
NonBlock, Offset, OffsetRows, OrderByExpr, Query, RenameSelectItem, ReplaceSelectElement,
ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, SetOperator, SetQuantifier, Table,
Expand Down
37 changes: 34 additions & 3 deletions src/ast/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ pub struct Select {
/// WHERE
pub selection: Option<Expr>,
/// GROUP BY
pub group_by: Vec<Expr>,
pub group_by: GroupByExpr,
/// CLUSTER BY (Hive)
pub cluster_by: Vec<Expr>,
/// DISTRIBUTE BY (Hive)
Expand Down Expand Up @@ -259,8 +259,13 @@ impl fmt::Display for Select {
if let Some(ref selection) = self.selection {
write!(f, " WHERE {selection}")?;
}
if !self.group_by.is_empty() {
write!(f, " GROUP BY {}", display_comma_separated(&self.group_by))?;
match &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() {
write!(
Expand Down Expand Up @@ -1222,3 +1227,29 @@ impl fmt::Display for SelectInto {
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})")
}
}
}
}
8 changes: 6 additions & 2 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5709,9 +5709,13 @@ impl<'a> Parser<'a> {
};

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 {
vec![]
GroupByExpr::Expressions(vec![])
};

let cluster_by = if self.parse_keywords(&[Keyword::CLUSTER, Keyword::BY]) {
Expand Down
2 changes: 1 addition & 1 deletion tests/sqlparser_clickhouse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ fn parse_map_access_expr() {
right: Box::new(Expr::Value(Value::SingleQuotedString("foo".to_string())))
})
}),
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down
26 changes: 20 additions & 6 deletions tests/sqlparser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,9 @@ fn parse_update_set_from() {
}],
lateral_views: vec![],
selection: None,
group_by: vec![Expr::Identifier(Ident::new("id"))],
group_by: GroupByExpr::Expressions(vec![Expr::Identifier(Ident::new(
"id"
))]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down Expand Up @@ -1808,10 +1810,10 @@ fn parse_select_group_by() {
let sql = "SELECT id, fname, lname FROM customer GROUP BY lname, fname";
let select = verified_only_select(sql);
assert_eq!(
vec![
GroupByExpr::Expressions(vec![
Expr::Identifier(Ident::new("lname")),
Expr::Identifier(Ident::new("fname")),
],
]),
select.group_by
);

Expand All @@ -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]
fn parse_select_having() {
let sql = "SELECT foo FROM bar GROUP BY foo HAVING COUNT(*) > 1";
Expand Down Expand Up @@ -3543,7 +3557,7 @@ fn test_parse_named_window() {
}],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down Expand Up @@ -3930,7 +3944,7 @@ fn parse_interval_and_or_xor() {
}),
}),
}),
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down Expand Up @@ -6333,7 +6347,7 @@ fn parse_merge() {
}],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down
8 changes: 4 additions & 4 deletions tests/sqlparser_duckdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ fn test_select_union_by_name() {
}],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down Expand Up @@ -194,7 +194,7 @@ fn test_select_union_by_name() {
}],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down Expand Up @@ -236,7 +236,7 @@ fn test_select_union_by_name() {
}],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down Expand Up @@ -269,7 +269,7 @@ fn test_select_union_by_name() {
}],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down
4 changes: 2 additions & 2 deletions tests/sqlparser_mssql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ fn parse_create_procedure() {
from: vec![],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down Expand Up @@ -519,7 +519,7 @@ fn parse_substring_in_select() {
}],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down
16 changes: 8 additions & 8 deletions tests/sqlparser_mysql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ fn parse_escaped_quote_identifiers_with_escape() {
from: vec![],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down Expand Up @@ -538,7 +538,7 @@ fn parse_escaped_quote_identifiers_with_no_escape() {
from: vec![],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down Expand Up @@ -577,7 +577,7 @@ fn parse_escaped_backticks_with_escape() {
from: vec![],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down Expand Up @@ -616,7 +616,7 @@ fn parse_escaped_backticks_with_no_escape() {
from: vec![],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down Expand Up @@ -1100,7 +1100,7 @@ fn parse_select_with_numeric_prefix_column_name() {
}],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down Expand Up @@ -1149,7 +1149,7 @@ fn parse_select_with_concatenation_of_exp_number_and_numeric_prefix_column() {
}],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down Expand Up @@ -1325,7 +1325,7 @@ fn parse_substring_in_select() {
}],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down Expand Up @@ -1604,7 +1604,7 @@ fn parse_hex_string_introducer() {
from: vec![],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down
18 changes: 9 additions & 9 deletions tests/sqlparser_postgres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -991,7 +991,7 @@ fn parse_copy_to() {
from: vec![],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
having: None,
named_window: vec![],
cluster_by: vec![],
Expand Down Expand Up @@ -2020,7 +2020,7 @@ fn parse_array_subquery_expr() {
from: vec![],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand All @@ -2036,7 +2036,7 @@ fn parse_array_subquery_expr() {
from: vec![],
lateral_views: vec![],
selection: None,
group_by: vec![],
group_by: GroupByExpr::Expressions(vec![]),
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
Expand Down Expand Up @@ -3322,14 +3322,14 @@ fn parse_select_group_by_grouping_sets() {
"SELECT brand, size, sum(sales) FROM items_sold GROUP BY size, GROUPING SETS ((brand), (size), ())"
);
assert_eq!(
vec![
GroupByExpr::Expressions(vec![
Expr::Identifier(Ident::new("size")),
Expr::GroupingSets(vec![
vec![Expr::Identifier(Ident::new("brand"))],
vec![Expr::Identifier(Ident::new("size"))],
vec![],
]),
],
]),
select.group_by
);
}
Expand All @@ -3340,13 +3340,13 @@ fn parse_select_group_by_rollup() {
"SELECT brand, size, sum(sales) FROM items_sold GROUP BY size, ROLLUP (brand, size)",
);
assert_eq!(
vec![
GroupByExpr::Expressions(vec![
Expr::Identifier(Ident::new("size")),
Expr::Rollup(vec![
vec![Expr::Identifier(Ident::new("brand"))],
vec![Expr::Identifier(Ident::new("size"))],
]),
],
]),
select.group_by
);
}
Expand All @@ -3357,13 +3357,13 @@ fn parse_select_group_by_cube() {
"SELECT brand, size, sum(sales) FROM items_sold GROUP BY size, CUBE (brand, size)",
);
assert_eq!(
vec![
GroupByExpr::Expressions(vec![
Expr::Identifier(Ident::new("size")),
Expr::Cube(vec![
vec![Expr::Identifier(Ident::new("brand"))],
vec![Expr::Identifier(Ident::new("size"))],
]),
],
]),
select.group_by
);
}
Expand Down

0 comments on commit b235d64

Please sign in to comment.