Skip to content

Commit 79f06bd

Browse files
Add support for PostgreSQL's ORDER BY ... USING <operator> clause (apache#2246)
1 parent f98c9d1 commit 79f06bd

11 files changed

Lines changed: 197 additions & 62 deletions

src/ast/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub use self::query::{
9999
JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
100100
MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
101101
OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
102-
PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
102+
OrderBySort, PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
103103
RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
104104
SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SelectModifiers,
105105
SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias,

src/ast/query.rs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2927,7 +2927,7 @@ impl fmt::Display for OrderBy {
29272927
pub struct OrderByExpr {
29282928
/// The expression to order by.
29292929
pub expr: Expr,
2930-
/// Ordering options such as `ASC`/`DESC` and `NULLS` behavior.
2930+
/// Ordering options such as `ASC`/`DESC`/`USING <operator>` and `NULLS` behavior.
29312931
pub options: OrderByOptions,
29322932
/// Optional `WITH FILL` clause (ClickHouse extension) which specifies how to fill gaps.
29332933
pub with_fill: Option<WithFill>,
@@ -2945,7 +2945,8 @@ impl From<Ident> for OrderByExpr {
29452945

29462946
impl fmt::Display for OrderByExpr {
29472947
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2948-
write!(f, "{}{}", self.expr, self.options)?;
2948+
write!(f, "{}", self.expr)?;
2949+
write!(f, "{}", self.options)?;
29492950
if let Some(ref with_fill) = self.with_fill {
29502951
write!(f, " {with_fill}")?
29512952
}
@@ -3020,22 +3021,47 @@ impl fmt::Display for InterpolateExpr {
30203021
}
30213022
}
30223023

3023-
#[derive(Default, Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3024+
/// The sort order for an `ORDER BY` expression.
3025+
///
3026+
/// See PostgreSQL `USING` operator:
3027+
/// <https://www.postgresql.org/docs/current/sql-select.html>
3028+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
30243029
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
30253030
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3026-
/// Options for an `ORDER BY` expression (ASC/DESC and NULLS FIRST/LAST).
3031+
pub enum OrderBySort {
3032+
/// `ASC`
3033+
Asc,
3034+
/// `DESC`
3035+
Desc,
3036+
/// PostgreSQL `USING <operator>` ordering.
3037+
///
3038+
/// See <https://www.postgresql.org/docs/current/sql-select.html>
3039+
Using(ObjectName),
3040+
}
3041+
3042+
#[derive(Default, Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3043+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3044+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3045+
/// Options for an `ORDER BY` expression.
30273046
pub struct OrderByOptions {
3028-
/// Optional `ASC` (`Some(true)`) or `DESC` (`Some(false)`).
3029-
pub asc: Option<bool>,
3047+
/// Optional sort order: `ASC`, `DESC`, or `USING <operator>`.
3048+
pub sort: Option<OrderBySort>,
30303049
/// Optional `NULLS FIRST` (`Some(true)`) or `NULLS LAST` (`Some(false)`).
30313050
pub nulls_first: Option<bool>,
30323051
}
30333052

30343053
impl fmt::Display for OrderByOptions {
30353054
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3036-
match self.asc {
3037-
Some(true) => write!(f, " ASC")?,
3038-
Some(false) => write!(f, " DESC")?,
3055+
match &self.sort {
3056+
Some(OrderBySort::Asc) => write!(f, " ASC")?,
3057+
Some(OrderBySort::Desc) => write!(f, " DESC")?,
3058+
Some(OrderBySort::Using(op)) => {
3059+
if op.0.len() > 1 {
3060+
write!(f, " USING OPERATOR({op})")?;
3061+
} else {
3062+
write!(f, " USING {op}")?;
3063+
}
3064+
}
30393065
None => (),
30403066
}
30413067
match self.nulls_first {

src/dialect/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,14 @@ pub trait Dialect: Debug + Any {
14141414
false
14151415
}
14161416

1417+
/// Returns true if the dialect supports PostgreSQL-style ordering operators:
1418+
/// `ORDER BY expr USING <operator>`.
1419+
///
1420+
/// For example: `SELECT * FROM t ORDER BY a USING <`.
1421+
fn supports_order_by_using_operator(&self) -> bool {
1422+
false
1423+
}
1424+
14171425
/// Returns true if the dialect supports `SET NAMES <charset_name> [COLLATE <collation_name>]`.
14181426
///
14191427
/// - [MySQL](https://dev.mysql.com/doc/refman/8.4/en/set-names.html)

src/dialect/postgresql.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,10 @@ impl Dialect for PostgreSqlDialect {
278278
true
279279
}
280280

281+
fn supports_order_by_using_operator(&self) -> bool {
282+
true
283+
}
284+
281285
fn supports_set_names(&self) -> bool {
282286
true
283287
}

src/parser/mod.rs

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,7 +1378,7 @@ impl<'a> Parser<'a> {
13781378
}
13791379
let alias = self.parse_optional_alias_inner(None, validator)?;
13801380
let order_by = OrderByOptions {
1381-
asc: self.parse_asc_desc(),
1381+
sort: self.parse_optional_order_by_sort(),
13821382
nulls_first: None,
13831383
};
13841384
Ok(ExprWithAliasAndOrderBy {
@@ -18852,6 +18852,15 @@ impl<'a> Parser<'a> {
1885218852
}
1885318853
}
1885418854

18855+
/// Parse ASC or DESC and map to [OrderBySort].
18856+
fn parse_optional_order_by_sort(&mut self) -> Option<OrderBySort> {
18857+
match self.parse_asc_desc() {
18858+
Some(true) => Some(OrderBySort::Asc),
18859+
Some(false) => Some(OrderBySort::Desc),
18860+
None => None,
18861+
}
18862+
}
18863+
1885518864
/// Parse an [OrderByExpr] expression.
1885618865
pub fn parse_order_by_expr(&mut self) -> Result<OrderByExpr, ParserError> {
1885718866
self.parse_order_by_expr_inner(false)
@@ -18888,7 +18897,18 @@ impl<'a> Parser<'a> {
1888818897
None
1888918898
};
1889018899

18891-
let options = self.parse_order_by_options()?;
18900+
let options = if !with_operator_class
18901+
&& self.dialect.supports_order_by_using_operator()
18902+
&& self.parse_keyword(Keyword::USING)
18903+
{
18904+
let op = self.parse_order_by_using_operator()?;
18905+
OrderByOptions {
18906+
sort: Some(OrderBySort::Using(op)),
18907+
nulls_first: self.parse_null_ordering_modifier(),
18908+
}
18909+
} else {
18910+
self.parse_order_by_options()?
18911+
};
1889218912

1889318913
let with_fill = if self.dialect.supports_with_fill()
1889418914
&& self.parse_keywords(&[Keyword::WITH, Keyword::FILL])
@@ -18908,18 +18928,33 @@ impl<'a> Parser<'a> {
1890818928
))
1890918929
}
1891018930

18911-
fn parse_order_by_options(&mut self) -> Result<OrderByOptions, ParserError> {
18912-
let asc = self.parse_asc_desc();
18931+
fn parse_order_by_using_operator(&mut self) -> Result<ObjectName, ParserError> {
18932+
if self.parse_keyword(Keyword::OPERATOR) {
18933+
self.expect_token(&Token::LParen)?;
18934+
let operator_name = self.parse_operator_name()?;
18935+
self.expect_token(&Token::RParen)?;
18936+
return Ok(operator_name);
18937+
}
18938+
18939+
let token = self.next_token();
18940+
Ok(ObjectName::from(vec![Ident::new(token.token.to_string())]))
18941+
}
1891318942

18914-
let nulls_first = if self.parse_keywords(&[Keyword::NULLS, Keyword::FIRST]) {
18943+
fn parse_null_ordering_modifier(&mut self) -> Option<bool> {
18944+
if self.parse_keywords(&[Keyword::NULLS, Keyword::FIRST]) {
1891518945
Some(true)
1891618946
} else if self.parse_keywords(&[Keyword::NULLS, Keyword::LAST]) {
1891718947
Some(false)
1891818948
} else {
1891918949
None
18920-
};
18950+
}
18951+
}
18952+
18953+
fn parse_order_by_options(&mut self) -> Result<OrderByOptions, ParserError> {
18954+
let sort = self.parse_optional_order_by_sort();
18955+
let nulls_first = self.parse_null_ordering_modifier();
1892118956

18922-
Ok(OrderByOptions { asc, nulls_first })
18957+
Ok(OrderByOptions { sort, nulls_first })
1892318958
}
1892418959

1892518960
// Parse a WITH FILL clause (ClickHouse dialect)
@@ -21170,7 +21205,7 @@ mod tests {
2117021205
column: OrderByExpr {
2117121206
expr: Expr::Identifier(name.into()),
2117221207
options: OrderByOptions {
21173-
asc: None,
21208+
sort: None,
2117421209
nulls_first: None,
2117521210
},
2117621211
with_fill: None,

tests/sqlparser_bigquery.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2731,7 +2731,7 @@ fn test_export_data() {
27312731
kind: OrderByKind::Expressions(vec![OrderByExpr {
27322732
expr: Expr::Identifier(Ident::new("field1")),
27332733
options: OrderByOptions {
2734-
asc: None,
2734+
sort: None,
27352735
nulls_first: None,
27362736
},
27372737
with_fill: None,
@@ -2837,7 +2837,7 @@ fn test_export_data() {
28372837
kind: OrderByKind::Expressions(vec![OrderByExpr {
28382838
expr: Expr::Identifier(Ident::new("field1")),
28392839
options: OrderByOptions {
2840-
asc: None,
2840+
sort: None,
28412841
nulls_first: None,
28422842
},
28432843
with_fill: None,

tests/sqlparser_clickhouse.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ fn parse_alter_table_add_projection() {
390390
kind: OrderByKind::Expressions(vec![OrderByExpr {
391391
expr: Identifier(Ident::new("b")),
392392
options: OrderByOptions {
393-
asc: None,
393+
sort: None,
394394
nulls_first: None,
395395
},
396396
with_fill: None,
@@ -1218,7 +1218,7 @@ fn parse_select_order_by_with_fill_interpolate() {
12181218
OrderByExpr {
12191219
expr: Expr::Identifier(Ident::new("fname")),
12201220
options: OrderByOptions {
1221-
asc: Some(true),
1221+
sort: Some(OrderBySort::Asc),
12221222
nulls_first: Some(true),
12231223
},
12241224
with_fill: Some(WithFill {
@@ -1230,7 +1230,7 @@ fn parse_select_order_by_with_fill_interpolate() {
12301230
OrderByExpr {
12311231
expr: Expr::Identifier(Ident::new("lname")),
12321232
options: OrderByOptions {
1233-
asc: Some(false),
1233+
sort: Some(OrderBySort::Desc),
12341234
nulls_first: Some(false),
12351235
},
12361236
with_fill: Some(WithFill {

0 commit comments

Comments
 (0)