This is an automated email from the ASF dual-hosted git repository.

iffyio pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git


The following commit(s) were added to refs/heads/main by this push:
     new 1f1c0693 Add support for `ORDER BY ALL` (#1724)
1f1c0693 is described below

commit 1f1c0693daa031961a05f9a91cb154c2b3db5572
Author: SiLe Zhou <[email protected]>
AuthorDate: Sat Feb 22 13:52:07 2025 +0800

    Add support for `ORDER BY ALL` (#1724)
---
 src/ast/mod.rs                |  10 +-
 src/ast/query.rs              |  73 ++++++++----
 src/ast/spans.rs              |  26 +++--
 src/dialect/clickhouse.rs     |   5 +
 src/dialect/duckdb.rs         |   5 +
 src/dialect/mod.rs            |   8 ++
 src/parser/mod.rs             |  58 ++++++----
 tests/sqlparser_clickhouse.rs |  60 +++++++---
 tests/sqlparser_common.rs     | 258 ++++++++++++++++++++++++++++++++++--------
 tests/sqlparser_hive.rs       |  16 ++-
 tests/sqlparser_mysql.rs      |   6 +-
 11 files changed, 396 insertions(+), 129 deletions(-)

diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index 2b9016d9..ace752a8 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -68,11 +68,11 @@ pub use self::query::{
     JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn, 
JsonTableNestedColumn,
     LateralView, LockClause, LockType, MatchRecognizePattern, 
MatchRecognizeSymbol, Measure,
     NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset, OffsetRows, 
OpenJsonTableColumn,
-    OrderBy, OrderByExpr, PivotValueSource, ProjectionSelect, Query, 
RenameSelectItem,
-    RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, 
RowsPerMatch, Select,
-    SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, 
SetExpr, SetOperator,
-    SetQuantifier, Setting, SymbolDefinition, Table, TableAlias, 
TableAliasColumnDef, TableFactor,
-    TableFunctionArgs, TableIndexHintForClause, TableIndexHintType, 
TableIndexHints,
+    OrderBy, OrderByExpr, OrderByKind, OrderByOptions, PivotValueSource, 
ProjectionSelect, Query,
+    RenameSelectItem, RepetitionQuantifier, ReplaceSelectElement, 
ReplaceSelectItem, RowsPerMatch,
+    Select, SelectFlavor, SelectInto, SelectItem, 
SelectItemQualifiedWildcardKind, SetExpr,
+    SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias, 
TableAliasColumnDef,
+    TableFactor, TableFunctionArgs, TableIndexHintForClause, 
TableIndexHintType, TableIndexHints,
     TableIndexType, TableSample, TableSampleBucket, TableSampleKind, 
TableSampleMethod,
     TableSampleModifier, TableSampleQuantity, TableSampleSeed, 
TableSampleSeedModifier,
     TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity, 
UpdateTableFromKind,
diff --git a/src/ast/query.rs b/src/ast/query.rs
index c52a98b6..bed99111 100644
--- a/src/ast/query.rs
+++ b/src/ast/query.rs
@@ -2218,30 +2218,50 @@ pub enum JoinConstraint {
     None,
 }
 
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub enum OrderByKind {
+    /// ALL syntax of [DuckDB] and [ClickHouse].
+    ///
+    /// [DuckDB]:  <https://duckdb.org/docs/sql/query_syntax/orderby>
+    /// [ClickHouse]: 
<https://clickhouse.com/docs/en/sql-reference/statements/select/order-by>
+    All(OrderByOptions),
+
+    /// Expressions
+    Expressions(Vec<OrderByExpr>),
+}
+
 #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
 pub struct OrderBy {
-    pub exprs: Vec<OrderByExpr>,
+    pub kind: OrderByKind,
+
     /// Optional: `INTERPOLATE`
     /// Supported by [ClickHouse syntax]
-    ///
-    /// [ClickHouse syntax]: 
<https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier>
     pub interpolate: Option<Interpolate>,
 }
 
 impl fmt::Display for OrderBy {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "ORDER BY")?;
-        if !self.exprs.is_empty() {
-            write!(f, " {}", display_comma_separated(&self.exprs))?;
+        match &self.kind {
+            OrderByKind::Expressions(exprs) => {
+                write!(f, " {}", display_comma_separated(exprs))?;
+            }
+            OrderByKind::All(all) => {
+                write!(f, " ALL{}", all)?;
+            }
         }
+
         if let Some(ref interpolate) = self.interpolate {
             match &interpolate.exprs {
                 Some(exprs) => write!(f, " INTERPOLATE ({})", 
display_comma_separated(exprs))?,
                 None => write!(f, " INTERPOLATE")?,
             }
         }
+
         Ok(())
     }
 }
@@ -2252,10 +2272,7 @@ impl fmt::Display for OrderBy {
 #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
 pub struct OrderByExpr {
     pub expr: Expr,
-    /// Optional `ASC` or `DESC`
-    pub asc: Option<bool>,
-    /// Optional `NULLS FIRST` or `NULLS LAST`
-    pub nulls_first: Option<bool>,
+    pub options: OrderByOptions,
     /// Optional: `WITH FILL`
     /// Supported by [ClickHouse syntax]: 
<https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier>
     pub with_fill: Option<WithFill>,
@@ -2263,17 +2280,7 @@ pub struct OrderByExpr {
 
 impl fmt::Display for OrderByExpr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.expr)?;
-        match self.asc {
-            Some(true) => write!(f, " ASC")?,
-            Some(false) => write!(f, " DESC")?,
-            None => (),
-        }
-        match self.nulls_first {
-            Some(true) => write!(f, " NULLS FIRST")?,
-            Some(false) => write!(f, " NULLS LAST")?,
-            None => (),
-        }
+        write!(f, "{}{}", self.expr, self.options)?;
         if let Some(ref with_fill) = self.with_fill {
             write!(f, " {}", with_fill)?
         }
@@ -2339,6 +2346,32 @@ impl fmt::Display for InterpolateExpr {
     }
 }
 
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct OrderByOptions {
+    /// Optional `ASC` or `DESC`
+    pub asc: Option<bool>,
+    /// Optional `NULLS FIRST` or `NULLS LAST`
+    pub nulls_first: Option<bool>,
+}
+
+impl fmt::Display for OrderByOptions {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self.asc {
+            Some(true) => write!(f, " ASC")?,
+            Some(false) => write!(f, " DESC")?,
+            None => (),
+        }
+        match self.nulls_first {
+            Some(true) => write!(f, " NULLS FIRST")?,
+            Some(false) => write!(f, " NULLS LAST")?,
+            None => (),
+        }
+        Ok(())
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
diff --git a/src/ast/spans.rs b/src/ast/spans.rs
index 3de41902..88c3d8ae 100644
--- a/src/ast/spans.rs
+++ b/src/ast/spans.rs
@@ -30,7 +30,7 @@ use super::{
     GroupByExpr, HavingBound, IlikeSelectItem, Insert, Interpolate, 
InterpolateExpr, Join,
     JoinConstraint, JoinOperator, JsonPath, JsonPathElem, LateralView, 
MatchRecognizePattern,
     Measure, NamedWindowDefinition, ObjectName, ObjectNamePart, Offset, 
OnConflict,
-    OnConflictAction, OnInsert, OrderBy, OrderByExpr, Partition, 
PivotValueSource,
+    OnConflictAction, OnInsert, OrderBy, OrderByExpr, OrderByKind, Partition, 
PivotValueSource,
     ProjectionSelect, Query, ReferentialAction, RenameSelectItem, 
ReplaceSelectElement,
     ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, SqlOption, 
Statement, Subscript,
     SymbolDefinition, TableAlias, TableAliasColumnDef, TableConstraint, 
TableFactor, TableObject,
@@ -1095,16 +1095,21 @@ impl Spanned for ProjectionSelect {
     }
 }
 
+/// # partial span
+///
+/// Missing spans:
+/// - [OrderByKind::All]
 impl Spanned for OrderBy {
     fn span(&self) -> Span {
-        let OrderBy { exprs, interpolate } = self;
-
-        union_spans(
-            exprs
-                .iter()
-                .map(|i| i.span())
-                .chain(interpolate.iter().map(|i| i.span())),
-        )
+        match &self.kind {
+            OrderByKind::All(_) => Span::empty(),
+            OrderByKind::Expressions(exprs) => union_spans(
+                exprs
+                    .iter()
+                    .map(|i| i.span())
+                    .chain(self.interpolate.iter().map(|i| i.span())),
+            ),
+        }
     }
 }
 
@@ -1902,8 +1907,7 @@ impl Spanned for OrderByExpr {
     fn span(&self) -> Span {
         let OrderByExpr {
             expr,
-            asc: _,         // bool
-            nulls_first: _, // bool
+            options: _,
             with_fill,
         } = self;
 
diff --git a/src/dialect/clickhouse.rs b/src/dialect/clickhouse.rs
index 37da2ab5..f5e70c30 100644
--- a/src/dialect/clickhouse.rs
+++ b/src/dialect/clickhouse.rs
@@ -80,6 +80,11 @@ impl Dialect for ClickHouseDialect {
         true
     }
 
+    /// See 
<https://clickhouse.com/docs/en/sql-reference/statements/select/order-by>
+    fn supports_order_by_all(&self) -> bool {
+        true
+    }
+
     // See 
<https://clickhouse.com/docs/en/sql-reference/aggregate-functions/grouping_function#grouping-sets>
     fn supports_group_by_expr(&self) -> bool {
         true
diff --git a/src/dialect/duckdb.rs b/src/dialect/duckdb.rs
index a2e7fb6c..3595aa71 100644
--- a/src/dialect/duckdb.rs
+++ b/src/dialect/duckdb.rs
@@ -89,4 +89,9 @@ impl Dialect for DuckDbDialect {
     fn supports_from_first_select(&self) -> bool {
         true
     }
+
+    /// See DuckDB 
<https://duckdb.org/docs/sql/query_syntax/orderby.html#order-by-all-examples>
+    fn supports_order_by_all(&self) -> bool {
+        true
+    }
 }
diff --git a/src/dialect/mod.rs b/src/dialect/mod.rs
index 86e23c86..b68adc17 100644
--- a/src/dialect/mod.rs
+++ b/src/dialect/mod.rs
@@ -943,6 +943,14 @@ pub trait Dialect: Debug + Any {
     fn supports_geometric_types(&self) -> bool {
         false
     }
+
+    /// Returns true if the dialect supports `ORDER BY ALL`.
+    /// `ALL` which means all columns of the SELECT clause.
+    ///
+    /// For example: ```SELECT * FROM addresses ORDER BY ALL;```.
+    fn supports_order_by_all(&self) -> bool {
+        false
+    }
 }
 
 /// This represents the operators for which precedence must be defined
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 69268bc5..f80754a3 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -9369,17 +9369,26 @@ impl<'a> Parser<'a> {
 
     pub fn parse_optional_order_by(&mut self) -> Result<Option<OrderBy>, 
ParserError> {
         if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
-            let order_by_exprs = 
self.parse_comma_separated(Parser::parse_order_by_expr)?;
-            let interpolate = if dialect_of!(self is ClickHouseDialect | 
GenericDialect) {
-                self.parse_interpolations()?
-            } else {
-                None
-            };
-
-            Ok(Some(OrderBy {
-                exprs: order_by_exprs,
-                interpolate,
-            }))
+            let order_by =
+                if self.dialect.supports_order_by_all() && 
self.parse_keyword(Keyword::ALL) {
+                    let order_by_options = self.parse_order_by_options()?;
+                    OrderBy {
+                        kind: OrderByKind::All(order_by_options),
+                        interpolate: None,
+                    }
+                } else {
+                    let exprs = 
self.parse_comma_separated(Parser::parse_order_by_expr)?;
+                    let interpolate = if dialect_of!(self is ClickHouseDialect 
| GenericDialect) {
+                        self.parse_interpolations()?
+                    } else {
+                        None
+                    };
+                    OrderBy {
+                        kind: OrderByKind::Expressions(exprs),
+                        interpolate,
+                    }
+                };
+            Ok(Some(order_by))
         } else {
             Ok(None)
         }
@@ -13557,15 +13566,7 @@ impl<'a> Parser<'a> {
     pub fn parse_order_by_expr(&mut self) -> Result<OrderByExpr, ParserError> {
         let expr = self.parse_expr()?;
 
-        let asc = self.parse_asc_desc();
-
-        let nulls_first = if self.parse_keywords(&[Keyword::NULLS, 
Keyword::FIRST]) {
-            Some(true)
-        } else if self.parse_keywords(&[Keyword::NULLS, Keyword::LAST]) {
-            Some(false)
-        } else {
-            None
-        };
+        let options = self.parse_order_by_options()?;
 
         let with_fill = if dialect_of!(self is ClickHouseDialect | 
GenericDialect)
             && self.parse_keywords(&[Keyword::WITH, Keyword::FILL])
@@ -13577,12 +13578,25 @@ impl<'a> Parser<'a> {
 
         Ok(OrderByExpr {
             expr,
-            asc,
-            nulls_first,
+            options,
             with_fill,
         })
     }
 
+    fn parse_order_by_options(&mut self) -> Result<OrderByOptions, 
ParserError> {
+        let asc = self.parse_asc_desc();
+
+        let nulls_first = if self.parse_keywords(&[Keyword::NULLS, 
Keyword::FIRST]) {
+            Some(true)
+        } else if self.parse_keywords(&[Keyword::NULLS, Keyword::LAST]) {
+            Some(false)
+        } else {
+            None
+        };
+
+        Ok(OrderByOptions { asc, nulls_first })
+    }
+
     // Parse a WITH FILL clause (ClickHouse dialect)
     // that follow the WITH FILL keywords in a ORDER BY clause
     pub fn parse_with_fill(&mut self) -> Result<WithFill, ParserError> {
diff --git a/tests/sqlparser_clickhouse.rs b/tests/sqlparser_clickhouse.rs
index 34f684c6..99e76d45 100644
--- a/tests/sqlparser_clickhouse.rs
+++ b/tests/sqlparser_clickhouse.rs
@@ -323,12 +323,14 @@ fn parse_alter_table_add_projection() {
                             vec![]
                         )),
                         order_by: Some(OrderBy {
-                            exprs: vec![OrderByExpr {
+                            kind: OrderByKind::Expressions(vec![OrderByExpr {
                                 expr: Identifier(Ident::new("b")),
-                                asc: None,
-                                nulls_first: None,
+                                options: OrderByOptions {
+                                    asc: None,
+                                    nulls_first: None,
+                                },
                                 with_fill: None,
-                            }],
+                            }]),
                             interpolate: None,
                         }),
                     }
@@ -1068,11 +1070,13 @@ fn parse_select_order_by_with_fill_interpolate() {
     let select = clickhouse().verified_query(sql);
     assert_eq!(
         OrderBy {
-            exprs: vec![
+            kind: OrderByKind::Expressions(vec![
                 OrderByExpr {
                     expr: Expr::Identifier(Ident::new("fname")),
-                    asc: Some(true),
-                    nulls_first: Some(true),
+                    options: OrderByOptions {
+                        asc: Some(true),
+                        nulls_first: Some(true),
+                    },
                     with_fill: Some(WithFill {
                         from: Some(Expr::Value(number("10"))),
                         to: Some(Expr::Value(number("20"))),
@@ -1081,15 +1085,17 @@ fn parse_select_order_by_with_fill_interpolate() {
                 },
                 OrderByExpr {
                     expr: Expr::Identifier(Ident::new("lname")),
-                    asc: Some(false),
-                    nulls_first: Some(false),
+                    options: OrderByOptions {
+                        asc: Some(false),
+                        nulls_first: Some(false),
+                    },
                     with_fill: Some(WithFill {
                         from: Some(Expr::Value(number("30"))),
                         to: Some(Expr::Value(number("40"))),
                         step: Some(Expr::Value(number("3"))),
                     }),
                 },
-            ],
+            ]),
             interpolate: Some(Interpolate {
                 exprs: Some(vec![InterpolateExpr {
                     column: Ident::new("col1"),
@@ -1147,8 +1153,12 @@ fn parse_with_fill() {
             from: Some(Expr::Value(number("10"))),
             to: Some(Expr::Value(number("20"))),
             step: Some(Expr::Value(number("2"))),
-        }),
-        select.order_by.expect("ORDER BY expected").exprs[0].with_fill
+        })
+        .as_ref(),
+        match select.order_by.expect("ORDER BY expected").kind {
+            OrderByKind::Expressions(ref exprs) => exprs[0].with_fill.as_ref(),
+            _ => None,
+        }
     );
 }
 
@@ -1199,8 +1209,13 @@ fn parse_interpolate_body_with_columns() {
                     }),
                 },
             ])
-        }),
-        select.order_by.expect("ORDER BY expected").interpolate
+        })
+        .as_ref(),
+        select
+            .order_by
+            .expect("ORDER BY expected")
+            .interpolate
+            .as_ref()
     );
 }
 
@@ -1209,8 +1224,12 @@ fn parse_interpolate_without_body() {
     let sql = "SELECT fname FROM customer ORDER BY fname WITH FILL 
INTERPOLATE";
     let select = clickhouse().verified_query(sql);
     assert_eq!(
-        Some(Interpolate { exprs: None }),
-        select.order_by.expect("ORDER BY expected").interpolate
+        Some(Interpolate { exprs: None }).as_ref(),
+        select
+            .order_by
+            .expect("ORDER BY expected")
+            .interpolate
+            .as_ref()
     );
 }
 
@@ -1221,8 +1240,13 @@ fn parse_interpolate_with_empty_body() {
     assert_eq!(
         Some(Interpolate {
             exprs: Some(vec![])
-        }),
-        select.order_by.expect("ORDER BY expected").interpolate
+        })
+        .as_ref(),
+        select
+            .order_by
+            .expect("ORDER BY expected")
+            .interpolate
+            .as_ref()
     );
 }
 
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index 653142dc..c46072d0 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -2389,27 +2389,33 @@ fn parse_select_order_by() {
     fn chk(sql: &str) {
         let select = verified_query(sql);
         assert_eq!(
-            vec![
+            OrderByKind::Expressions(vec![
                 OrderByExpr {
                     expr: Expr::Identifier(Ident::new("lname")),
-                    asc: Some(true),
-                    nulls_first: None,
+                    options: OrderByOptions {
+                        asc: Some(true),
+                        nulls_first: None,
+                    },
                     with_fill: None,
                 },
                 OrderByExpr {
                     expr: Expr::Identifier(Ident::new("fname")),
-                    asc: Some(false),
-                    nulls_first: None,
+                    options: OrderByOptions {
+                        asc: Some(false),
+                        nulls_first: None,
+                    },
                     with_fill: None,
                 },
                 OrderByExpr {
                     expr: Expr::Identifier(Ident::new("id")),
-                    asc: None,
-                    nulls_first: None,
+                    options: OrderByOptions {
+                        asc: None,
+                        nulls_first: None,
+                    },
                     with_fill: None,
                 },
-            ],
-            select.order_by.expect("ORDER BY expected").exprs
+            ]),
+            select.order_by.expect("ORDER BY expected").kind
         );
     }
     chk("SELECT id, fname, lname FROM customer WHERE id < 5 ORDER BY lname 
ASC, fname DESC, id");
@@ -2424,46 +2430,186 @@ fn parse_select_order_by_limit() {
                ORDER BY lname ASC, fname DESC LIMIT 2";
     let select = verified_query(sql);
     assert_eq!(
-        vec![
+        OrderByKind::Expressions(vec![
             OrderByExpr {
                 expr: Expr::Identifier(Ident::new("lname")),
-                asc: Some(true),
-                nulls_first: None,
+                options: OrderByOptions {
+                    asc: Some(true),
+                    nulls_first: None,
+                },
                 with_fill: None,
             },
             OrderByExpr {
                 expr: Expr::Identifier(Ident::new("fname")),
-                asc: Some(false),
-                nulls_first: None,
+                options: OrderByOptions {
+                    asc: Some(false),
+                    nulls_first: None,
+                },
                 with_fill: None,
             },
-        ],
-        select.order_by.expect("ORDER BY expected").exprs
+        ]),
+        select.order_by.expect("ORDER BY expected").kind
     );
     assert_eq!(Some(Expr::Value(number("2"))), select.limit);
 }
 
+#[test]
+fn parse_select_order_by_all() {
+    fn chk(sql: &str, except_order_by: OrderByKind) {
+        let dialects = all_dialects_where(|d| d.supports_order_by_all());
+        let select = dialects.verified_query(sql);
+        assert_eq!(
+            except_order_by,
+            select.order_by.expect("ORDER BY expected").kind
+        );
+    }
+    let test_cases = [
+        (
+            "SELECT id, fname, lname FROM customer WHERE id < 5 ORDER BY ALL",
+            OrderByKind::All(OrderByOptions {
+                asc: None,
+                nulls_first: None,
+            }),
+        ),
+        (
+            "SELECT id, fname, lname FROM customer WHERE id < 5 ORDER BY ALL 
NULLS FIRST",
+            OrderByKind::All(OrderByOptions {
+                asc: None,
+                nulls_first: Some(true),
+            }),
+        ),
+        (
+            "SELECT id, fname, lname FROM customer WHERE id < 5 ORDER BY ALL 
NULLS LAST",
+            OrderByKind::All(OrderByOptions {
+                asc: None,
+                nulls_first: Some(false),
+            }),
+        ),
+        (
+            "SELECT id, fname, lname FROM customer ORDER BY ALL ASC",
+            OrderByKind::All(OrderByOptions {
+                asc: Some(true),
+                nulls_first: None,
+            }),
+        ),
+        (
+            "SELECT id, fname, lname FROM customer ORDER BY ALL ASC NULLS 
FIRST",
+            OrderByKind::All(OrderByOptions {
+                asc: Some(true),
+                nulls_first: Some(true),
+            }),
+        ),
+        (
+            "SELECT id, fname, lname FROM customer ORDER BY ALL ASC NULLS 
LAST",
+            OrderByKind::All(OrderByOptions {
+                asc: Some(true),
+                nulls_first: Some(false),
+            }),
+        ),
+        (
+            "SELECT id, fname, lname FROM customer WHERE id < 5 ORDER BY ALL 
DESC",
+            OrderByKind::All(OrderByOptions {
+                asc: Some(false),
+                nulls_first: None,
+            }),
+        ),
+        (
+            "SELECT id, fname, lname FROM customer WHERE id < 5 ORDER BY ALL 
DESC NULLS FIRST",
+            OrderByKind::All(OrderByOptions {
+                asc: Some(false),
+                nulls_first: Some(true),
+            }),
+        ),
+        (
+            "SELECT id, fname, lname FROM customer WHERE id < 5 ORDER BY ALL 
DESC NULLS LAST",
+            OrderByKind::All(OrderByOptions {
+                asc: Some(false),
+                nulls_first: Some(false),
+            }),
+        ),
+    ];
+
+    for (sql, expected_order_by) in test_cases {
+        chk(sql, expected_order_by);
+    }
+}
+
+#[test]
+fn parse_select_order_by_not_support_all() {
+    fn chk(sql: &str, except_order_by: OrderByKind) {
+        let dialects = all_dialects_where(|d| !d.supports_order_by_all());
+        let select = dialects.verified_query(sql);
+        assert_eq!(
+            except_order_by,
+            select.order_by.expect("ORDER BY expected").kind
+        );
+    }
+    let test_cases = [
+        (
+            "SELECT id, ALL FROM customer WHERE id < 5 ORDER BY ALL",
+            OrderByKind::Expressions(vec![OrderByExpr {
+                expr: Expr::Identifier(Ident::new("ALL")),
+                options: OrderByOptions {
+                    asc: None,
+                    nulls_first: None,
+                },
+                with_fill: None,
+            }]),
+        ),
+        (
+            "SELECT id, ALL FROM customer ORDER BY ALL ASC NULLS FIRST",
+            OrderByKind::Expressions(vec![OrderByExpr {
+                expr: Expr::Identifier(Ident::new("ALL")),
+                options: OrderByOptions {
+                    asc: Some(true),
+                    nulls_first: Some(true),
+                },
+                with_fill: None,
+            }]),
+        ),
+        (
+            "SELECT id, ALL FROM customer ORDER BY ALL DESC NULLS LAST",
+            OrderByKind::Expressions(vec![OrderByExpr {
+                expr: Expr::Identifier(Ident::new("ALL")),
+                options: OrderByOptions {
+                    asc: Some(false),
+                    nulls_first: Some(false),
+                },
+                with_fill: None,
+            }]),
+        ),
+    ];
+
+    for (sql, expected_order_by) in test_cases {
+        chk(sql, expected_order_by);
+    }
+}
+
 #[test]
 fn parse_select_order_by_nulls_order() {
     let sql = "SELECT id, fname, lname FROM customer WHERE id < 5 \
                ORDER BY lname ASC NULLS FIRST, fname DESC NULLS LAST LIMIT 2";
     let select = verified_query(sql);
     assert_eq!(
-        vec![
+        OrderByKind::Expressions(vec![
             OrderByExpr {
                 expr: Expr::Identifier(Ident::new("lname")),
-                asc: Some(true),
-                nulls_first: Some(true),
+                options: OrderByOptions {
+                    asc: Some(true),
+                    nulls_first: Some(true),
+                },
                 with_fill: None,
             },
             OrderByExpr {
                 expr: Expr::Identifier(Ident::new("fname")),
-                asc: Some(false),
-                nulls_first: Some(false),
+                options: OrderByOptions {
+                    asc: Some(false),
+                    nulls_first: Some(false),
+                },
                 with_fill: None,
             },
-        ],
-        select.order_by.expect("ORDER BY expeccted").exprs
+        ]),
+        select.order_by.expect("ORDER BY expeccted").kind
     );
     assert_eq!(Some(Expr::Value(number("2"))), select.limit);
 }
@@ -2641,8 +2787,10 @@ fn parse_select_qualify() {
                     partition_by: vec![Expr::Identifier(Ident::new("p"))],
                     order_by: vec![OrderByExpr {
                         expr: Expr::Identifier(Ident::new("o")),
-                        asc: None,
-                        nulls_first: None,
+                        options: OrderByOptions {
+                            asc: None,
+                            nulls_first: None,
+                        },
                         with_fill: None,
                     }],
                     window_frame: None,
@@ -3065,8 +3213,10 @@ fn parse_listagg() {
                         quote_style: None,
                         span: Span::empty(),
                     }),
-                    asc: None,
-                    nulls_first: None,
+                    options: OrderByOptions {
+                        asc: None,
+                        nulls_first: None,
+                    },
                     with_fill: None,
                 },
                 OrderByExpr {
@@ -3075,8 +3225,10 @@ fn parse_listagg() {
                         quote_style: None,
                         span: Span::empty(),
                     }),
-                    asc: None,
-                    nulls_first: None,
+                    options: OrderByOptions {
+                        asc: None,
+                        nulls_first: None,
+                    },
                     with_fill: None,
                 },
             ]
@@ -5172,8 +5324,10 @@ fn parse_window_functions() {
                 partition_by: vec![],
                 order_by: vec![OrderByExpr {
                     expr: Expr::Identifier(Ident::new("dt")),
-                    asc: Some(false),
-                    nulls_first: None,
+                    options: OrderByOptions {
+                        asc: Some(false),
+                        nulls_first: None,
+                    },
                     with_fill: None,
                 }],
                 window_frame: None,
@@ -5386,8 +5540,10 @@ fn test_parse_named_window() {
                             quote_style: None,
                             span: Span::empty(),
                         }),
-                        asc: None,
-                        nulls_first: None,
+                        options: OrderByOptions {
+                            asc: None,
+                            nulls_first: None,
+                        },
                         with_fill: None,
                     }],
                     window_frame: None,
@@ -8584,14 +8740,18 @@ fn parse_create_index() {
     let indexed_columns = vec![
         OrderByExpr {
             expr: Expr::Identifier(Ident::new("name")),
-            asc: None,
-            nulls_first: None,
+            options: OrderByOptions {
+                asc: None,
+                nulls_first: None,
+            },
             with_fill: None,
         },
         OrderByExpr {
             expr: Expr::Identifier(Ident::new("age")),
-            asc: Some(false),
-            nulls_first: None,
+            options: OrderByOptions {
+                asc: Some(false),
+                nulls_first: None,
+            },
             with_fill: None,
         },
     ];
@@ -8620,14 +8780,18 @@ fn test_create_index_with_using_function() {
     let indexed_columns = vec![
         OrderByExpr {
             expr: Expr::Identifier(Ident::new("name")),
-            asc: None,
-            nulls_first: None,
+            options: OrderByOptions {
+                asc: None,
+                nulls_first: None,
+            },
             with_fill: None,
         },
         OrderByExpr {
             expr: Expr::Identifier(Ident::new("age")),
-            asc: Some(false),
-            nulls_first: None,
+            options: OrderByOptions {
+                asc: Some(false),
+                nulls_first: None,
+            },
             with_fill: None,
         },
     ];
@@ -8664,8 +8828,10 @@ fn test_create_index_with_with_clause() {
     let sql = "CREATE UNIQUE INDEX title_idx ON films(title) WITH (fillfactor 
= 70, single_param)";
     let indexed_columns = vec![OrderByExpr {
         expr: Expr::Identifier(Ident::new("title")),
-        asc: None,
-        nulls_first: None,
+        options: OrderByOptions {
+            asc: None,
+            nulls_first: None,
+        },
         with_fill: None,
     }];
     let with_parameters = vec![
@@ -11345,8 +11511,10 @@ fn test_match_recognize() {
             partition_by: vec![Expr::Identifier(Ident::new("company"))],
             order_by: vec![OrderByExpr {
                 expr: Expr::Identifier(Ident::new("price_date")),
-                asc: None,
-                nulls_first: None,
+                options: OrderByOptions {
+                    asc: None,
+                    nulls_first: None,
+                },
                 with_fill: None,
             }],
             measures: vec![
diff --git a/tests/sqlparser_hive.rs b/tests/sqlparser_hive.rs
index 5d710b17..b2b300ae 100644
--- a/tests/sqlparser_hive.rs
+++ b/tests/sqlparser_hive.rs
@@ -23,8 +23,8 @@
 use sqlparser::ast::{
     ClusteredBy, CommentDef, CreateFunction, CreateFunctionBody, 
CreateFunctionUsing, CreateTable,
     Expr, Function, FunctionArgumentList, FunctionArguments, Ident, ObjectName,
-    OneOrManyWithParens, OrderByExpr, SelectItem, Statement, TableFactor, 
UnaryOperator, Use,
-    Value,
+    OneOrManyWithParens, OrderByExpr, OrderByOptions, SelectItem, Statement, 
TableFactor,
+    UnaryOperator, Use, Value,
 };
 use sqlparser::dialect::{GenericDialect, HiveDialect, MsSqlDialect};
 use sqlparser::parser::ParserError;
@@ -171,14 +171,18 @@ fn create_table_with_clustered_by() {
                     sorted_by: Some(vec![
                         OrderByExpr {
                             expr: Expr::Identifier(Ident::new("a")),
-                            asc: Some(true),
-                            nulls_first: None,
+                            options: OrderByOptions {
+                                asc: Some(true),
+                                nulls_first: None,
+                            },
                             with_fill: None,
                         },
                         OrderByExpr {
                             expr: Expr::Identifier(Ident::new("b")),
-                            asc: Some(false),
-                            nulls_first: None,
+                            options: OrderByOptions {
+                                asc: Some(false),
+                                nulls_first: None,
+                            },
                             with_fill: None,
                         },
                     ]),
diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs
index 44c8350f..03071074 100644
--- a/tests/sqlparser_mysql.rs
+++ b/tests/sqlparser_mysql.rs
@@ -2096,8 +2096,10 @@ fn parse_delete_with_order_by() {
                         quote_style: None,
                         span: Span::empty(),
                     }),
-                    asc: Some(false),
-                    nulls_first: None,
+                    options: OrderByOptions {
+                        asc: Some(false),
+                        nulls_first: None,
+                    },
                     with_fill: None,
                 }],
                 order_by


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to