Skip to content

Commit 1f1c069

Browse files
authored
Add support for ORDER BY ALL (apache#1724)
1 parent 8fc8082 commit 1f1c069

11 files changed

+396
-129
lines changed

src/ast/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ pub use self::query::{
6868
JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn, JsonTableNestedColumn,
6969
LateralView, LockClause, LockType, MatchRecognizePattern, MatchRecognizeSymbol, Measure,
7070
NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset, OffsetRows, OpenJsonTableColumn,
71-
OrderBy, OrderByExpr, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
72-
RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
73-
SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SetExpr, SetOperator,
74-
SetQuantifier, Setting, SymbolDefinition, Table, TableAlias, TableAliasColumnDef, TableFactor,
75-
TableFunctionArgs, TableIndexHintForClause, TableIndexHintType, TableIndexHints,
71+
OrderBy, OrderByExpr, OrderByKind, OrderByOptions, PivotValueSource, ProjectionSelect, Query,
72+
RenameSelectItem, RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch,
73+
Select, SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SetExpr,
74+
SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias, TableAliasColumnDef,
75+
TableFactor, TableFunctionArgs, TableIndexHintForClause, TableIndexHintType, TableIndexHints,
7676
TableIndexType, TableSample, TableSampleBucket, TableSampleKind, TableSampleMethod,
7777
TableSampleModifier, TableSampleQuantity, TableSampleSeed, TableSampleSeedModifier,
7878
TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity, UpdateTableFromKind,

src/ast/query.rs

+53-20
Original file line numberDiff line numberDiff line change
@@ -2218,30 +2218,50 @@ pub enum JoinConstraint {
22182218
None,
22192219
}
22202220

2221+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2222+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2223+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2224+
pub enum OrderByKind {
2225+
/// ALL syntax of [DuckDB] and [ClickHouse].
2226+
///
2227+
/// [DuckDB]: <https://duckdb.org/docs/sql/query_syntax/orderby>
2228+
/// [ClickHouse]: <https://clickhouse.com/docs/en/sql-reference/statements/select/order-by>
2229+
All(OrderByOptions),
2230+
2231+
/// Expressions
2232+
Expressions(Vec<OrderByExpr>),
2233+
}
2234+
22212235
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
22222236
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
22232237
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
22242238
pub struct OrderBy {
2225-
pub exprs: Vec<OrderByExpr>,
2239+
pub kind: OrderByKind,
2240+
22262241
/// Optional: `INTERPOLATE`
22272242
/// Supported by [ClickHouse syntax]
2228-
///
2229-
/// [ClickHouse syntax]: <https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier>
22302243
pub interpolate: Option<Interpolate>,
22312244
}
22322245

22332246
impl fmt::Display for OrderBy {
22342247
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22352248
write!(f, "ORDER BY")?;
2236-
if !self.exprs.is_empty() {
2237-
write!(f, " {}", display_comma_separated(&self.exprs))?;
2249+
match &self.kind {
2250+
OrderByKind::Expressions(exprs) => {
2251+
write!(f, " {}", display_comma_separated(exprs))?;
2252+
}
2253+
OrderByKind::All(all) => {
2254+
write!(f, " ALL{}", all)?;
2255+
}
22382256
}
2257+
22392258
if let Some(ref interpolate) = self.interpolate {
22402259
match &interpolate.exprs {
22412260
Some(exprs) => write!(f, " INTERPOLATE ({})", display_comma_separated(exprs))?,
22422261
None => write!(f, " INTERPOLATE")?,
22432262
}
22442263
}
2264+
22452265
Ok(())
22462266
}
22472267
}
@@ -2252,28 +2272,15 @@ impl fmt::Display for OrderBy {
22522272
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
22532273
pub struct OrderByExpr {
22542274
pub expr: Expr,
2255-
/// Optional `ASC` or `DESC`
2256-
pub asc: Option<bool>,
2257-
/// Optional `NULLS FIRST` or `NULLS LAST`
2258-
pub nulls_first: Option<bool>,
2275+
pub options: OrderByOptions,
22592276
/// Optional: `WITH FILL`
22602277
/// Supported by [ClickHouse syntax]: <https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier>
22612278
pub with_fill: Option<WithFill>,
22622279
}
22632280

22642281
impl fmt::Display for OrderByExpr {
22652282
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2266-
write!(f, "{}", self.expr)?;
2267-
match self.asc {
2268-
Some(true) => write!(f, " ASC")?,
2269-
Some(false) => write!(f, " DESC")?,
2270-
None => (),
2271-
}
2272-
match self.nulls_first {
2273-
Some(true) => write!(f, " NULLS FIRST")?,
2274-
Some(false) => write!(f, " NULLS LAST")?,
2275-
None => (),
2276-
}
2283+
write!(f, "{}{}", self.expr, self.options)?;
22772284
if let Some(ref with_fill) = self.with_fill {
22782285
write!(f, " {}", with_fill)?
22792286
}
@@ -2339,6 +2346,32 @@ impl fmt::Display for InterpolateExpr {
23392346
}
23402347
}
23412348

2349+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2350+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2351+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2352+
pub struct OrderByOptions {
2353+
/// Optional `ASC` or `DESC`
2354+
pub asc: Option<bool>,
2355+
/// Optional `NULLS FIRST` or `NULLS LAST`
2356+
pub nulls_first: Option<bool>,
2357+
}
2358+
2359+
impl fmt::Display for OrderByOptions {
2360+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2361+
match self.asc {
2362+
Some(true) => write!(f, " ASC")?,
2363+
Some(false) => write!(f, " DESC")?,
2364+
None => (),
2365+
}
2366+
match self.nulls_first {
2367+
Some(true) => write!(f, " NULLS FIRST")?,
2368+
Some(false) => write!(f, " NULLS LAST")?,
2369+
None => (),
2370+
}
2371+
Ok(())
2372+
}
2373+
}
2374+
23422375
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
23432376
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
23442377
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]

src/ast/spans.rs

+15-11
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use super::{
3030
GroupByExpr, HavingBound, IlikeSelectItem, Insert, Interpolate, InterpolateExpr, Join,
3131
JoinConstraint, JoinOperator, JsonPath, JsonPathElem, LateralView, MatchRecognizePattern,
3232
Measure, NamedWindowDefinition, ObjectName, ObjectNamePart, Offset, OnConflict,
33-
OnConflictAction, OnInsert, OrderBy, OrderByExpr, Partition, PivotValueSource,
33+
OnConflictAction, OnInsert, OrderBy, OrderByExpr, OrderByKind, Partition, PivotValueSource,
3434
ProjectionSelect, Query, ReferentialAction, RenameSelectItem, ReplaceSelectElement,
3535
ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, SqlOption, Statement, Subscript,
3636
SymbolDefinition, TableAlias, TableAliasColumnDef, TableConstraint, TableFactor, TableObject,
@@ -1095,16 +1095,21 @@ impl Spanned for ProjectionSelect {
10951095
}
10961096
}
10971097

1098+
/// # partial span
1099+
///
1100+
/// Missing spans:
1101+
/// - [OrderByKind::All]
10981102
impl Spanned for OrderBy {
10991103
fn span(&self) -> Span {
1100-
let OrderBy { exprs, interpolate } = self;
1101-
1102-
union_spans(
1103-
exprs
1104-
.iter()
1105-
.map(|i| i.span())
1106-
.chain(interpolate.iter().map(|i| i.span())),
1107-
)
1104+
match &self.kind {
1105+
OrderByKind::All(_) => Span::empty(),
1106+
OrderByKind::Expressions(exprs) => union_spans(
1107+
exprs
1108+
.iter()
1109+
.map(|i| i.span())
1110+
.chain(self.interpolate.iter().map(|i| i.span())),
1111+
),
1112+
}
11081113
}
11091114
}
11101115

@@ -1902,8 +1907,7 @@ impl Spanned for OrderByExpr {
19021907
fn span(&self) -> Span {
19031908
let OrderByExpr {
19041909
expr,
1905-
asc: _, // bool
1906-
nulls_first: _, // bool
1910+
options: _,
19071911
with_fill,
19081912
} = self;
19091913

src/dialect/clickhouse.rs

+5
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ impl Dialect for ClickHouseDialect {
8080
true
8181
}
8282

83+
/// See <https://clickhouse.com/docs/en/sql-reference/statements/select/order-by>
84+
fn supports_order_by_all(&self) -> bool {
85+
true
86+
}
87+
8388
// See <https://clickhouse.com/docs/en/sql-reference/aggregate-functions/grouping_function#grouping-sets>
8489
fn supports_group_by_expr(&self) -> bool {
8590
true

src/dialect/duckdb.rs

+5
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,9 @@ impl Dialect for DuckDbDialect {
8989
fn supports_from_first_select(&self) -> bool {
9090
true
9191
}
92+
93+
/// See DuckDB <https://duckdb.org/docs/sql/query_syntax/orderby.html#order-by-all-examples>
94+
fn supports_order_by_all(&self) -> bool {
95+
true
96+
}
9297
}

src/dialect/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,14 @@ pub trait Dialect: Debug + Any {
943943
fn supports_geometric_types(&self) -> bool {
944944
false
945945
}
946+
947+
/// Returns true if the dialect supports `ORDER BY ALL`.
948+
/// `ALL` which means all columns of the SELECT clause.
949+
///
950+
/// For example: ```SELECT * FROM addresses ORDER BY ALL;```.
951+
fn supports_order_by_all(&self) -> bool {
952+
false
953+
}
946954
}
947955

948956
/// This represents the operators for which precedence must be defined

src/parser/mod.rs

+36-22
Original file line numberDiff line numberDiff line change
@@ -9369,17 +9369,26 @@ impl<'a> Parser<'a> {
93699369

93709370
pub fn parse_optional_order_by(&mut self) -> Result<Option<OrderBy>, ParserError> {
93719371
if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
9372-
let order_by_exprs = self.parse_comma_separated(Parser::parse_order_by_expr)?;
9373-
let interpolate = if dialect_of!(self is ClickHouseDialect | GenericDialect) {
9374-
self.parse_interpolations()?
9375-
} else {
9376-
None
9377-
};
9378-
9379-
Ok(Some(OrderBy {
9380-
exprs: order_by_exprs,
9381-
interpolate,
9382-
}))
9372+
let order_by =
9373+
if self.dialect.supports_order_by_all() && self.parse_keyword(Keyword::ALL) {
9374+
let order_by_options = self.parse_order_by_options()?;
9375+
OrderBy {
9376+
kind: OrderByKind::All(order_by_options),
9377+
interpolate: None,
9378+
}
9379+
} else {
9380+
let exprs = self.parse_comma_separated(Parser::parse_order_by_expr)?;
9381+
let interpolate = if dialect_of!(self is ClickHouseDialect | GenericDialect) {
9382+
self.parse_interpolations()?
9383+
} else {
9384+
None
9385+
};
9386+
OrderBy {
9387+
kind: OrderByKind::Expressions(exprs),
9388+
interpolate,
9389+
}
9390+
};
9391+
Ok(Some(order_by))
93839392
} else {
93849393
Ok(None)
93859394
}
@@ -13557,15 +13566,7 @@ impl<'a> Parser<'a> {
1355713566
pub fn parse_order_by_expr(&mut self) -> Result<OrderByExpr, ParserError> {
1355813567
let expr = self.parse_expr()?;
1355913568

13560-
let asc = self.parse_asc_desc();
13561-
13562-
let nulls_first = if self.parse_keywords(&[Keyword::NULLS, Keyword::FIRST]) {
13563-
Some(true)
13564-
} else if self.parse_keywords(&[Keyword::NULLS, Keyword::LAST]) {
13565-
Some(false)
13566-
} else {
13567-
None
13568-
};
13569+
let options = self.parse_order_by_options()?;
1356913570

1357013571
let with_fill = if dialect_of!(self is ClickHouseDialect | GenericDialect)
1357113572
&& self.parse_keywords(&[Keyword::WITH, Keyword::FILL])
@@ -13577,12 +13578,25 @@ impl<'a> Parser<'a> {
1357713578

1357813579
Ok(OrderByExpr {
1357913580
expr,
13580-
asc,
13581-
nulls_first,
13581+
options,
1358213582
with_fill,
1358313583
})
1358413584
}
1358513585

13586+
fn parse_order_by_options(&mut self) -> Result<OrderByOptions, ParserError> {
13587+
let asc = self.parse_asc_desc();
13588+
13589+
let nulls_first = if self.parse_keywords(&[Keyword::NULLS, Keyword::FIRST]) {
13590+
Some(true)
13591+
} else if self.parse_keywords(&[Keyword::NULLS, Keyword::LAST]) {
13592+
Some(false)
13593+
} else {
13594+
None
13595+
};
13596+
13597+
Ok(OrderByOptions { asc, nulls_first })
13598+
}
13599+
1358613600
// Parse a WITH FILL clause (ClickHouse dialect)
1358713601
// that follow the WITH FILL keywords in a ORDER BY clause
1358813602
pub fn parse_with_fill(&mut self) -> Result<WithFill, ParserError> {

0 commit comments

Comments
 (0)