mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-22 15:04:04 +00:00
Add support for ORDER BY ALL
(#1724)
This commit is contained in:
parent
8fc8082e9a
commit
1f1c0693da
11 changed files with 396 additions and 129 deletions
|
@ -68,11 +68,11 @@ pub use self::query::{
|
||||||
JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn, JsonTableNestedColumn,
|
JsonTableColumn, JsonTableColumnErrorHandling, JsonTableNamedColumn, JsonTableNestedColumn,
|
||||||
LateralView, LockClause, LockType, MatchRecognizePattern, MatchRecognizeSymbol, Measure,
|
LateralView, LockClause, LockType, MatchRecognizePattern, MatchRecognizeSymbol, Measure,
|
||||||
NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset, OffsetRows, OpenJsonTableColumn,
|
NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset, OffsetRows, OpenJsonTableColumn,
|
||||||
OrderBy, OrderByExpr, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
|
OrderBy, OrderByExpr, OrderByKind, OrderByOptions, PivotValueSource, ProjectionSelect, Query,
|
||||||
RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
|
RenameSelectItem, RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch,
|
||||||
SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SetExpr, SetOperator,
|
Select, SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SetExpr,
|
||||||
SetQuantifier, Setting, SymbolDefinition, Table, TableAlias, TableAliasColumnDef, TableFactor,
|
SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias, TableAliasColumnDef,
|
||||||
TableFunctionArgs, TableIndexHintForClause, TableIndexHintType, TableIndexHints,
|
TableFactor, TableFunctionArgs, TableIndexHintForClause, TableIndexHintType, TableIndexHints,
|
||||||
TableIndexType, TableSample, TableSampleBucket, TableSampleKind, TableSampleMethod,
|
TableIndexType, TableSample, TableSampleBucket, TableSampleKind, TableSampleMethod,
|
||||||
TableSampleModifier, TableSampleQuantity, TableSampleSeed, TableSampleSeedModifier,
|
TableSampleModifier, TableSampleQuantity, TableSampleSeed, TableSampleSeedModifier,
|
||||||
TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity, UpdateTableFromKind,
|
TableSampleUnit, TableVersion, TableWithJoins, Top, TopQuantity, UpdateTableFromKind,
|
||||||
|
|
|
@ -2218,30 +2218,50 @@ pub enum JoinConstraint {
|
||||||
None,
|
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)]
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
pub struct OrderBy {
|
pub struct OrderBy {
|
||||||
pub exprs: Vec<OrderByExpr>,
|
pub kind: OrderByKind,
|
||||||
|
|
||||||
/// Optional: `INTERPOLATE`
|
/// Optional: `INTERPOLATE`
|
||||||
/// Supported by [ClickHouse syntax]
|
/// 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>,
|
pub interpolate: Option<Interpolate>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for OrderBy {
|
impl fmt::Display for OrderBy {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "ORDER BY")?;
|
write!(f, "ORDER BY")?;
|
||||||
if !self.exprs.is_empty() {
|
match &self.kind {
|
||||||
write!(f, " {}", display_comma_separated(&self.exprs))?;
|
OrderByKind::Expressions(exprs) => {
|
||||||
|
write!(f, " {}", display_comma_separated(exprs))?;
|
||||||
}
|
}
|
||||||
|
OrderByKind::All(all) => {
|
||||||
|
write!(f, " ALL{}", all)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(ref interpolate) = self.interpolate {
|
if let Some(ref interpolate) = self.interpolate {
|
||||||
match &interpolate.exprs {
|
match &interpolate.exprs {
|
||||||
Some(exprs) => write!(f, " INTERPOLATE ({})", display_comma_separated(exprs))?,
|
Some(exprs) => write!(f, " INTERPOLATE ({})", display_comma_separated(exprs))?,
|
||||||
None => write!(f, " INTERPOLATE")?,
|
None => write!(f, " INTERPOLATE")?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2252,10 +2272,7 @@ impl fmt::Display for OrderBy {
|
||||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
pub struct OrderByExpr {
|
pub struct OrderByExpr {
|
||||||
pub expr: Expr,
|
pub expr: Expr,
|
||||||
/// Optional `ASC` or `DESC`
|
pub options: OrderByOptions,
|
||||||
pub asc: Option<bool>,
|
|
||||||
/// Optional `NULLS FIRST` or `NULLS LAST`
|
|
||||||
pub nulls_first: Option<bool>,
|
|
||||||
/// Optional: `WITH FILL`
|
/// Optional: `WITH FILL`
|
||||||
/// Supported by [ClickHouse syntax]: <https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier>
|
/// 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>,
|
pub with_fill: Option<WithFill>,
|
||||||
|
@ -2263,17 +2280,7 @@ pub struct OrderByExpr {
|
||||||
|
|
||||||
impl fmt::Display for OrderByExpr {
|
impl fmt::Display for OrderByExpr {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}", self.expr)?;
|
write!(f, "{}{}", self.expr, self.options)?;
|
||||||
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 => (),
|
|
||||||
}
|
|
||||||
if let Some(ref with_fill) = self.with_fill {
|
if let Some(ref with_fill) = self.with_fill {
|
||||||
write!(f, " {}", 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)]
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
|
|
|
@ -30,7 +30,7 @@ use super::{
|
||||||
GroupByExpr, HavingBound, IlikeSelectItem, Insert, Interpolate, InterpolateExpr, Join,
|
GroupByExpr, HavingBound, IlikeSelectItem, Insert, Interpolate, InterpolateExpr, Join,
|
||||||
JoinConstraint, JoinOperator, JsonPath, JsonPathElem, LateralView, MatchRecognizePattern,
|
JoinConstraint, JoinOperator, JsonPath, JsonPathElem, LateralView, MatchRecognizePattern,
|
||||||
Measure, NamedWindowDefinition, ObjectName, ObjectNamePart, Offset, OnConflict,
|
Measure, NamedWindowDefinition, ObjectName, ObjectNamePart, Offset, OnConflict,
|
||||||
OnConflictAction, OnInsert, OrderBy, OrderByExpr, Partition, PivotValueSource,
|
OnConflictAction, OnInsert, OrderBy, OrderByExpr, OrderByKind, Partition, PivotValueSource,
|
||||||
ProjectionSelect, Query, ReferentialAction, RenameSelectItem, ReplaceSelectElement,
|
ProjectionSelect, Query, ReferentialAction, RenameSelectItem, ReplaceSelectElement,
|
||||||
ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, SqlOption, Statement, Subscript,
|
ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, SqlOption, Statement, Subscript,
|
||||||
SymbolDefinition, TableAlias, TableAliasColumnDef, TableConstraint, TableFactor, TableObject,
|
SymbolDefinition, TableAlias, TableAliasColumnDef, TableConstraint, TableFactor, TableObject,
|
||||||
|
@ -1095,16 +1095,21 @@ impl Spanned for ProjectionSelect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # partial span
|
||||||
|
///
|
||||||
|
/// Missing spans:
|
||||||
|
/// - [OrderByKind::All]
|
||||||
impl Spanned for OrderBy {
|
impl Spanned for OrderBy {
|
||||||
fn span(&self) -> Span {
|
fn span(&self) -> Span {
|
||||||
let OrderBy { exprs, interpolate } = self;
|
match &self.kind {
|
||||||
|
OrderByKind::All(_) => Span::empty(),
|
||||||
union_spans(
|
OrderByKind::Expressions(exprs) => union_spans(
|
||||||
exprs
|
exprs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|i| i.span())
|
.map(|i| i.span())
|
||||||
.chain(interpolate.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 {
|
fn span(&self) -> Span {
|
||||||
let OrderByExpr {
|
let OrderByExpr {
|
||||||
expr,
|
expr,
|
||||||
asc: _, // bool
|
options: _,
|
||||||
nulls_first: _, // bool
|
|
||||||
with_fill,
|
with_fill,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,11 @@ impl Dialect for ClickHouseDialect {
|
||||||
true
|
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>
|
// See <https://clickhouse.com/docs/en/sql-reference/aggregate-functions/grouping_function#grouping-sets>
|
||||||
fn supports_group_by_expr(&self) -> bool {
|
fn supports_group_by_expr(&self) -> bool {
|
||||||
true
|
true
|
||||||
|
|
|
@ -89,4 +89,9 @@ impl Dialect for DuckDbDialect {
|
||||||
fn supports_from_first_select(&self) -> bool {
|
fn supports_from_first_select(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// See DuckDB <https://duckdb.org/docs/sql/query_syntax/orderby.html#order-by-all-examples>
|
||||||
|
fn supports_order_by_all(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -943,6 +943,14 @@ pub trait Dialect: Debug + Any {
|
||||||
fn supports_geometric_types(&self) -> bool {
|
fn supports_geometric_types(&self) -> bool {
|
||||||
false
|
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
|
/// This represents the operators for which precedence must be defined
|
||||||
|
|
|
@ -9369,17 +9369,26 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
pub fn parse_optional_order_by(&mut self) -> Result<Option<OrderBy>, ParserError> {
|
pub fn parse_optional_order_by(&mut self) -> Result<Option<OrderBy>, ParserError> {
|
||||||
if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
|
if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
|
||||||
let order_by_exprs = self.parse_comma_separated(Parser::parse_order_by_expr)?;
|
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) {
|
let interpolate = if dialect_of!(self is ClickHouseDialect | GenericDialect) {
|
||||||
self.parse_interpolations()?
|
self.parse_interpolations()?
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
OrderBy {
|
||||||
Ok(Some(OrderBy {
|
kind: OrderByKind::Expressions(exprs),
|
||||||
exprs: order_by_exprs,
|
|
||||||
interpolate,
|
interpolate,
|
||||||
}))
|
}
|
||||||
|
};
|
||||||
|
Ok(Some(order_by))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
@ -13557,15 +13566,7 @@ impl<'a> Parser<'a> {
|
||||||
pub fn parse_order_by_expr(&mut self) -> Result<OrderByExpr, ParserError> {
|
pub fn parse_order_by_expr(&mut self) -> Result<OrderByExpr, ParserError> {
|
||||||
let expr = self.parse_expr()?;
|
let expr = self.parse_expr()?;
|
||||||
|
|
||||||
let asc = self.parse_asc_desc();
|
let options = self.parse_order_by_options()?;
|
||||||
|
|
||||||
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 with_fill = if dialect_of!(self is ClickHouseDialect | GenericDialect)
|
let with_fill = if dialect_of!(self is ClickHouseDialect | GenericDialect)
|
||||||
&& self.parse_keywords(&[Keyword::WITH, Keyword::FILL])
|
&& self.parse_keywords(&[Keyword::WITH, Keyword::FILL])
|
||||||
|
@ -13577,12 +13578,25 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
Ok(OrderByExpr {
|
Ok(OrderByExpr {
|
||||||
expr,
|
expr,
|
||||||
asc,
|
options,
|
||||||
nulls_first,
|
|
||||||
with_fill,
|
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)
|
// Parse a WITH FILL clause (ClickHouse dialect)
|
||||||
// that follow the WITH FILL keywords in a ORDER BY clause
|
// that follow the WITH FILL keywords in a ORDER BY clause
|
||||||
pub fn parse_with_fill(&mut self) -> Result<WithFill, ParserError> {
|
pub fn parse_with_fill(&mut self) -> Result<WithFill, ParserError> {
|
||||||
|
|
|
@ -323,12 +323,14 @@ fn parse_alter_table_add_projection() {
|
||||||
vec![]
|
vec![]
|
||||||
)),
|
)),
|
||||||
order_by: Some(OrderBy {
|
order_by: Some(OrderBy {
|
||||||
exprs: vec![OrderByExpr {
|
kind: OrderByKind::Expressions(vec![OrderByExpr {
|
||||||
expr: Identifier(Ident::new("b")),
|
expr: Identifier(Ident::new("b")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: None,
|
asc: None,
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
}],
|
}]),
|
||||||
interpolate: None,
|
interpolate: None,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
@ -1068,11 +1070,13 @@ fn parse_select_order_by_with_fill_interpolate() {
|
||||||
let select = clickhouse().verified_query(sql);
|
let select = clickhouse().verified_query(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
OrderBy {
|
OrderBy {
|
||||||
exprs: vec![
|
kind: OrderByKind::Expressions(vec![
|
||||||
OrderByExpr {
|
OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("fname")),
|
expr: Expr::Identifier(Ident::new("fname")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: Some(true),
|
asc: Some(true),
|
||||||
nulls_first: Some(true),
|
nulls_first: Some(true),
|
||||||
|
},
|
||||||
with_fill: Some(WithFill {
|
with_fill: Some(WithFill {
|
||||||
from: Some(Expr::Value(number("10"))),
|
from: Some(Expr::Value(number("10"))),
|
||||||
to: Some(Expr::Value(number("20"))),
|
to: Some(Expr::Value(number("20"))),
|
||||||
|
@ -1081,15 +1085,17 @@ fn parse_select_order_by_with_fill_interpolate() {
|
||||||
},
|
},
|
||||||
OrderByExpr {
|
OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("lname")),
|
expr: Expr::Identifier(Ident::new("lname")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: Some(false),
|
asc: Some(false),
|
||||||
nulls_first: Some(false),
|
nulls_first: Some(false),
|
||||||
|
},
|
||||||
with_fill: Some(WithFill {
|
with_fill: Some(WithFill {
|
||||||
from: Some(Expr::Value(number("30"))),
|
from: Some(Expr::Value(number("30"))),
|
||||||
to: Some(Expr::Value(number("40"))),
|
to: Some(Expr::Value(number("40"))),
|
||||||
step: Some(Expr::Value(number("3"))),
|
step: Some(Expr::Value(number("3"))),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
],
|
]),
|
||||||
interpolate: Some(Interpolate {
|
interpolate: Some(Interpolate {
|
||||||
exprs: Some(vec![InterpolateExpr {
|
exprs: Some(vec![InterpolateExpr {
|
||||||
column: Ident::new("col1"),
|
column: Ident::new("col1"),
|
||||||
|
@ -1147,8 +1153,12 @@ fn parse_with_fill() {
|
||||||
from: Some(Expr::Value(number("10"))),
|
from: Some(Expr::Value(number("10"))),
|
||||||
to: Some(Expr::Value(number("20"))),
|
to: Some(Expr::Value(number("20"))),
|
||||||
step: Some(Expr::Value(number("2"))),
|
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 sql = "SELECT fname FROM customer ORDER BY fname WITH FILL INTERPOLATE";
|
||||||
let select = clickhouse().verified_query(sql);
|
let select = clickhouse().verified_query(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Some(Interpolate { exprs: None }),
|
Some(Interpolate { exprs: None }).as_ref(),
|
||||||
select.order_by.expect("ORDER BY expected").interpolate
|
select
|
||||||
|
.order_by
|
||||||
|
.expect("ORDER BY expected")
|
||||||
|
.interpolate
|
||||||
|
.as_ref()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1221,8 +1240,13 @@ fn parse_interpolate_with_empty_body() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Some(Interpolate {
|
Some(Interpolate {
|
||||||
exprs: Some(vec![])
|
exprs: Some(vec![])
|
||||||
}),
|
})
|
||||||
select.order_by.expect("ORDER BY expected").interpolate
|
.as_ref(),
|
||||||
|
select
|
||||||
|
.order_by
|
||||||
|
.expect("ORDER BY expected")
|
||||||
|
.interpolate
|
||||||
|
.as_ref()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2389,27 +2389,33 @@ fn parse_select_order_by() {
|
||||||
fn chk(sql: &str) {
|
fn chk(sql: &str) {
|
||||||
let select = verified_query(sql);
|
let select = verified_query(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
OrderByKind::Expressions(vec![
|
||||||
OrderByExpr {
|
OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("lname")),
|
expr: Expr::Identifier(Ident::new("lname")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: Some(true),
|
asc: Some(true),
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
},
|
},
|
||||||
OrderByExpr {
|
OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("fname")),
|
expr: Expr::Identifier(Ident::new("fname")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: Some(false),
|
asc: Some(false),
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
},
|
},
|
||||||
OrderByExpr {
|
OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("id")),
|
expr: Expr::Identifier(Ident::new("id")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: None,
|
asc: None,
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: 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");
|
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";
|
ORDER BY lname ASC, fname DESC LIMIT 2";
|
||||||
let select = verified_query(sql);
|
let select = verified_query(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
OrderByKind::Expressions(vec![
|
||||||
OrderByExpr {
|
OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("lname")),
|
expr: Expr::Identifier(Ident::new("lname")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: Some(true),
|
asc: Some(true),
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
},
|
},
|
||||||
OrderByExpr {
|
OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("fname")),
|
expr: Expr::Identifier(Ident::new("fname")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: Some(false),
|
asc: Some(false),
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: 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);
|
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]
|
#[test]
|
||||||
fn parse_select_order_by_nulls_order() {
|
fn parse_select_order_by_nulls_order() {
|
||||||
let sql = "SELECT id, fname, lname FROM customer WHERE id < 5 \
|
let sql = "SELECT id, fname, lname FROM customer WHERE id < 5 \
|
||||||
ORDER BY lname ASC NULLS FIRST, fname DESC NULLS LAST LIMIT 2";
|
ORDER BY lname ASC NULLS FIRST, fname DESC NULLS LAST LIMIT 2";
|
||||||
let select = verified_query(sql);
|
let select = verified_query(sql);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
OrderByKind::Expressions(vec![
|
||||||
OrderByExpr {
|
OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("lname")),
|
expr: Expr::Identifier(Ident::new("lname")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: Some(true),
|
asc: Some(true),
|
||||||
nulls_first: Some(true),
|
nulls_first: Some(true),
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
},
|
},
|
||||||
OrderByExpr {
|
OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("fname")),
|
expr: Expr::Identifier(Ident::new("fname")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: Some(false),
|
asc: Some(false),
|
||||||
nulls_first: Some(false),
|
nulls_first: Some(false),
|
||||||
|
},
|
||||||
with_fill: None,
|
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);
|
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"))],
|
partition_by: vec![Expr::Identifier(Ident::new("p"))],
|
||||||
order_by: vec![OrderByExpr {
|
order_by: vec![OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("o")),
|
expr: Expr::Identifier(Ident::new("o")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: None,
|
asc: None,
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
}],
|
}],
|
||||||
window_frame: None,
|
window_frame: None,
|
||||||
|
@ -3065,8 +3213,10 @@ fn parse_listagg() {
|
||||||
quote_style: None,
|
quote_style: None,
|
||||||
span: Span::empty(),
|
span: Span::empty(),
|
||||||
}),
|
}),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: None,
|
asc: None,
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
},
|
},
|
||||||
OrderByExpr {
|
OrderByExpr {
|
||||||
|
@ -3075,8 +3225,10 @@ fn parse_listagg() {
|
||||||
quote_style: None,
|
quote_style: None,
|
||||||
span: Span::empty(),
|
span: Span::empty(),
|
||||||
}),
|
}),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: None,
|
asc: None,
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -5172,8 +5324,10 @@ fn parse_window_functions() {
|
||||||
partition_by: vec![],
|
partition_by: vec![],
|
||||||
order_by: vec![OrderByExpr {
|
order_by: vec![OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("dt")),
|
expr: Expr::Identifier(Ident::new("dt")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: Some(false),
|
asc: Some(false),
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
}],
|
}],
|
||||||
window_frame: None,
|
window_frame: None,
|
||||||
|
@ -5386,8 +5540,10 @@ fn test_parse_named_window() {
|
||||||
quote_style: None,
|
quote_style: None,
|
||||||
span: Span::empty(),
|
span: Span::empty(),
|
||||||
}),
|
}),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: None,
|
asc: None,
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
}],
|
}],
|
||||||
window_frame: None,
|
window_frame: None,
|
||||||
|
@ -8584,14 +8740,18 @@ fn parse_create_index() {
|
||||||
let indexed_columns = vec![
|
let indexed_columns = vec![
|
||||||
OrderByExpr {
|
OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("name")),
|
expr: Expr::Identifier(Ident::new("name")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: None,
|
asc: None,
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
},
|
},
|
||||||
OrderByExpr {
|
OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("age")),
|
expr: Expr::Identifier(Ident::new("age")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: Some(false),
|
asc: Some(false),
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -8620,14 +8780,18 @@ fn test_create_index_with_using_function() {
|
||||||
let indexed_columns = vec![
|
let indexed_columns = vec![
|
||||||
OrderByExpr {
|
OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("name")),
|
expr: Expr::Identifier(Ident::new("name")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: None,
|
asc: None,
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
},
|
},
|
||||||
OrderByExpr {
|
OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("age")),
|
expr: Expr::Identifier(Ident::new("age")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: Some(false),
|
asc: Some(false),
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: 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 sql = "CREATE UNIQUE INDEX title_idx ON films(title) WITH (fillfactor = 70, single_param)";
|
||||||
let indexed_columns = vec![OrderByExpr {
|
let indexed_columns = vec![OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("title")),
|
expr: Expr::Identifier(Ident::new("title")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: None,
|
asc: None,
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
}];
|
}];
|
||||||
let with_parameters = vec![
|
let with_parameters = vec![
|
||||||
|
@ -11345,8 +11511,10 @@ fn test_match_recognize() {
|
||||||
partition_by: vec![Expr::Identifier(Ident::new("company"))],
|
partition_by: vec![Expr::Identifier(Ident::new("company"))],
|
||||||
order_by: vec![OrderByExpr {
|
order_by: vec![OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("price_date")),
|
expr: Expr::Identifier(Ident::new("price_date")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: None,
|
asc: None,
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
}],
|
}],
|
||||||
measures: vec![
|
measures: vec![
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
use sqlparser::ast::{
|
use sqlparser::ast::{
|
||||||
ClusteredBy, CommentDef, CreateFunction, CreateFunctionBody, CreateFunctionUsing, CreateTable,
|
ClusteredBy, CommentDef, CreateFunction, CreateFunctionBody, CreateFunctionUsing, CreateTable,
|
||||||
Expr, Function, FunctionArgumentList, FunctionArguments, Ident, ObjectName,
|
Expr, Function, FunctionArgumentList, FunctionArguments, Ident, ObjectName,
|
||||||
OneOrManyWithParens, OrderByExpr, SelectItem, Statement, TableFactor, UnaryOperator, Use,
|
OneOrManyWithParens, OrderByExpr, OrderByOptions, SelectItem, Statement, TableFactor,
|
||||||
Value,
|
UnaryOperator, Use, Value,
|
||||||
};
|
};
|
||||||
use sqlparser::dialect::{GenericDialect, HiveDialect, MsSqlDialect};
|
use sqlparser::dialect::{GenericDialect, HiveDialect, MsSqlDialect};
|
||||||
use sqlparser::parser::ParserError;
|
use sqlparser::parser::ParserError;
|
||||||
|
@ -171,14 +171,18 @@ fn create_table_with_clustered_by() {
|
||||||
sorted_by: Some(vec![
|
sorted_by: Some(vec![
|
||||||
OrderByExpr {
|
OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("a")),
|
expr: Expr::Identifier(Ident::new("a")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: Some(true),
|
asc: Some(true),
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
},
|
},
|
||||||
OrderByExpr {
|
OrderByExpr {
|
||||||
expr: Expr::Identifier(Ident::new("b")),
|
expr: Expr::Identifier(Ident::new("b")),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: Some(false),
|
asc: Some(false),
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
|
|
|
@ -2096,8 +2096,10 @@ fn parse_delete_with_order_by() {
|
||||||
quote_style: None,
|
quote_style: None,
|
||||||
span: Span::empty(),
|
span: Span::empty(),
|
||||||
}),
|
}),
|
||||||
|
options: OrderByOptions {
|
||||||
asc: Some(false),
|
asc: Some(false),
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
|
},
|
||||||
with_fill: None,
|
with_fill: None,
|
||||||
}],
|
}],
|
||||||
order_by
|
order_by
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue