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]