Skip to content

Commit

Permalink
feat(query): support group by all syntax (#12173)
Browse files Browse the repository at this point in the history
  • Loading branch information
sundy-li authored Jul 24, 2023
1 parent f570127 commit ee43431
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/query/ast/src/ast/format/ast_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2439,6 +2439,7 @@ impl<'ast> Visitor<'ast> for AstFormatVisitor {
);
children.push(group_by_list_node);
}
GroupBy::All => {}
GroupBy::GroupingSets(sets) => {
let mut grouping_sets = Vec::with_capacity(sets.len());
for set in sets.iter() {
Expand Down
1 change: 1 addition & 0 deletions src/query/ast/src/ast/format/syntax/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ fn pretty_group_by(group_by: Option<GroupBy>) -> RcDoc<'static> {
.nest(NEST_FACTOR)
.group(),
),
GroupBy::All => RcDoc::line().append(RcDoc::text("GROUP BY ALL")),
GroupBy::GroupingSets(sets) => RcDoc::line()
.append(
RcDoc::text("GROUP BY GROUPING SETS (").append(RcDoc::line().nest(NEST_FACTOR)),
Expand Down
5 changes: 5 additions & 0 deletions src/query/ast/src/ast/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ pub struct SelectStmt {
pub enum GroupBy {
/// GROUP BY expr [, expr]*
Normal(Vec<Expr>),
/// GROUP By ALL
All,
/// GROUP BY GROUPING SETS ( GroupSet [, GroupSet]* )
///
/// GroupSet := (expr [, expr]*) | expr
Expand Down Expand Up @@ -602,6 +604,9 @@ impl Display for SelectStmt {
GroupBy::Normal(exprs) => {
write_comma_separated_list(f, exprs)?;
}
GroupBy::All => {
write!(f, "ALL")?;
}
GroupBy::GroupingSets(sets) => {
write!(f, "GROUPING SETS (")?;
for (i, set) in sets.iter().enumerate() {
Expand Down
5 changes: 4 additions & 1 deletion src/query/ast/src/parser/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,9 @@ pub fn group_by_items(i: Input) -> IResult<GroupBy> {
let normal = map(rule! { ^#comma_separated_list1(expr) }, |groups| {
GroupBy::Normal(groups)
});
let all = map(rule! { ALL }, |_| GroupBy::All);
let cube = map(
rule! { CUBE ~ "(" ~ ^#comma_separated_list1(expr) ~ ")" },
|(_, _, groups, _)| GroupBy::Cube(groups),
Expand All @@ -819,7 +822,7 @@ pub fn group_by_items(i: Input) -> IResult<GroupBy> {
rule! { GROUPING ~ SETS ~ "(" ~ ^#comma_separated_list1(group_set) ~ ")" },
|(_, _, _, sets, _)| GroupBy::GroupingSets(sets),
);
rule!(#group_sets | #cube | #rollup | #normal)(i)
rule!(#all | #group_sets | #cube | #rollup | #normal)(i)
}
pub fn window_frame_bound(i: Input) -> IResult<WindowFrameBound> {
Expand Down
32 changes: 32 additions & 0 deletions src/query/sql/src/planner/binder/aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use itertools::Itertools;

use super::prune_by_children;
use super::ExprContext;
use super::Finder;
use crate::binder::scalar::ScalarBinder;
use crate::binder::select::SelectList;
use crate::binder::Binder;
Expand Down Expand Up @@ -395,6 +396,18 @@ impl Binder {
)
.await
}
GroupBy::All => {
let groups = self.resolve_group_all(select_list)?;
self.resolve_group_items(
bind_context,
select_list,
&groups,
&available_aliases,
false,
&mut vec![],
)
.await
}
GroupBy::GroupingSets(sets) => {
self.resolve_grouping_sets(bind_context, select_list, sets, &available_aliases)
.await
Expand Down Expand Up @@ -538,6 +551,25 @@ impl Binder {
Ok(())
}

fn resolve_group_all(&mut self, select_list: &SelectList<'_>) -> Result<Vec<Expr>> {
// Resolve group items with `FROM` context. Since the alias item can not be resolved
// from the context, we can detect the failure and fallback to resolving with `available_aliases`.

let f = |scalar: &ScalarExpr| matches!(scalar, ScalarExpr::AggregateFunction(_));
let mut groups = Vec::new();
for (idx, select_item) in select_list.items.iter().enumerate() {
let finder = Finder::new(&f);
let finder = select_item.scalar.accept(finder)?;
if finder.scalars().is_empty() {
groups.push(Expr::Literal {
span: None,
lit: Literal::UInt64(idx as u64 + 1),
});
}
}
Ok(groups)
}

#[async_backtrace::framed]
async fn resolve_group_items(
&mut self,
Expand Down
10 changes: 6 additions & 4 deletions src/query/sql/src/planner/binder/scalar_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::plans::ScalarExpr;
use crate::plans::WindowFuncType;

// Visitor that find Expressions that match a particular predicate
struct Finder<'a, F>
pub struct Finder<'a, F>
where F: Fn(&ScalarExpr) -> bool
{
find_fn: &'a F,
Expand All @@ -39,14 +39,16 @@ where F: Fn(&ScalarExpr) -> bool
impl<'a, F> Finder<'a, F>
where F: Fn(&ScalarExpr) -> bool
{
/// Create a new finder with the `test_fn`
#[allow(dead_code)]
fn new(find_fn: &'a F) -> Self {
pub fn new(find_fn: &'a F) -> Self {
Self {
find_fn,
scalars: Vec::new(),
}
}

pub fn scalars(&self) -> &[ScalarExpr] {
&self.scalars
}
}

impl<'a, F> ScalarVisitor for Finder<'a, F>
Expand Down
10 changes: 10 additions & 0 deletions tests/sqllogictests/suites/base/03_common/03_0003_select_group_by
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,13 @@ select number::Decimal(15,2) a, number % 3 b from numbers(5) group by a, b order
2.00 2
3.00 0
4.00 1

query IIII
select number % 3 a, max(number) - 3, number % 2 b, sum(number) + 4 from numbers(1000) group by all order by a, b;
----
0 993 0 83170
0 996 1 83671
1 991 0 82838
1 994 1 83337
2 995 0 83504
2 992 1 83004

1 comment on commit ee43431

@vercel
Copy link

@vercel vercel bot commented on ee43431 Jul 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

databend – ./

databend-git-main-databend.vercel.app
databend-databend.vercel.app
databend.vercel.app
databend.rs

Please sign in to comment.