mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-22 15:04:04 +00:00
[ClickHouse] Add support for WITH FILL to OrderByExpr (#1330)
Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
parent
20f7ac59e3
commit
845a1aaddd
9 changed files with 397 additions and 47 deletions
|
@ -43,14 +43,15 @@ pub use self::operator::{BinaryOperator, UnaryOperator};
|
|||
pub use self::query::{
|
||||
AfterMatchSkip, ConnectBy, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
|
||||
ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, Fetch, ForClause, ForJson, ForXml,
|
||||
FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias, IlikeSelectItem, Join,
|
||||
JoinConstraint, JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, LateralView,
|
||||
LockClause, LockType, MatchRecognizePattern, MatchRecognizeSymbol, Measure,
|
||||
NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset, OffsetRows, OrderByExpr,
|
||||
PivotValueSource, Query, RenameSelectItem, RepetitionQuantifier, ReplaceSelectElement,
|
||||
ReplaceSelectItem, RowsPerMatch, Select, SelectInto, SelectItem, SetExpr, SetOperator,
|
||||
SetQuantifier, Setting, SymbolDefinition, Table, TableAlias, TableFactor, TableVersion,
|
||||
TableWithJoins, Top, TopQuantity, ValueTableMode, Values, WildcardAdditionalOptions, With,
|
||||
FormatClause, GroupByExpr, GroupByWithModifier, IdentWithAlias, IlikeSelectItem, Interpolate,
|
||||
InterpolateExpr, Join, JoinConstraint, JoinOperator, JsonTableColumn,
|
||||
JsonTableColumnErrorHandling, LateralView, LockClause, LockType, MatchRecognizePattern,
|
||||
MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
|
||||
OffsetRows, OrderBy, OrderByExpr, PivotValueSource, Query, RenameSelectItem,
|
||||
RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
|
||||
SelectInto, SelectItem, SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table,
|
||||
TableAlias, TableFactor, TableVersion, TableWithJoins, Top, TopQuantity, ValueTableMode,
|
||||
Values, WildcardAdditionalOptions, With, WithFill,
|
||||
};
|
||||
pub use self::value::{
|
||||
escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
|
||||
|
|
|
@ -33,7 +33,7 @@ pub struct Query {
|
|||
/// SELECT or UNION / EXCEPT / INTERSECT
|
||||
pub body: Box<SetExpr>,
|
||||
/// ORDER BY
|
||||
pub order_by: Vec<OrderByExpr>,
|
||||
pub order_by: Option<OrderBy>,
|
||||
/// `LIMIT { <N> | ALL }`
|
||||
pub limit: Option<Expr>,
|
||||
|
||||
|
@ -67,8 +67,17 @@ impl fmt::Display for Query {
|
|||
write!(f, "{with} ")?;
|
||||
}
|
||||
write!(f, "{}", self.body)?;
|
||||
if !self.order_by.is_empty() {
|
||||
write!(f, " ORDER BY {}", display_comma_separated(&self.order_by))?;
|
||||
if let Some(ref order_by) = self.order_by {
|
||||
write!(f, " ORDER BY")?;
|
||||
if !order_by.exprs.is_empty() {
|
||||
write!(f, " {}", display_comma_separated(&order_by.exprs))?;
|
||||
}
|
||||
if let Some(ref interpolate) = order_by.interpolate {
|
||||
match &interpolate.exprs {
|
||||
Some(exprs) => write!(f, " INTERPOLATE ({})", display_comma_separated(exprs))?,
|
||||
None => write!(f, " INTERPOLATE")?,
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(ref limit) = self.limit {
|
||||
write!(f, " LIMIT {limit}")?;
|
||||
|
@ -1668,6 +1677,18 @@ 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 struct OrderBy {
|
||||
pub exprs: Vec<OrderByExpr>,
|
||||
/// 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>,
|
||||
}
|
||||
|
||||
/// An `ORDER BY` expression
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
|
@ -1678,6 +1699,9 @@ pub struct OrderByExpr {
|
|||
pub asc: Option<bool>,
|
||||
/// Optional `NULLS FIRST` or `NULLS LAST`
|
||||
pub nulls_first: Option<bool>,
|
||||
/// 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>,
|
||||
}
|
||||
|
||||
impl fmt::Display for OrderByExpr {
|
||||
|
@ -1693,6 +1717,67 @@ impl fmt::Display for OrderByExpr {
|
|||
Some(false) => write!(f, " NULLS LAST")?,
|
||||
None => (),
|
||||
}
|
||||
if let Some(ref with_fill) = self.with_fill {
|
||||
write!(f, " {}", with_fill)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// ClickHouse `WITH FILL` modifier for `ORDER BY` clause.
|
||||
/// Supported by [ClickHouse syntax]
|
||||
///
|
||||
/// [ClickHouse syntax]: <https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier>
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||
pub struct WithFill {
|
||||
pub from: Option<Expr>,
|
||||
pub to: Option<Expr>,
|
||||
pub step: Option<Expr>,
|
||||
}
|
||||
|
||||
impl fmt::Display for WithFill {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "WITH FILL")?;
|
||||
if let Some(ref from) = self.from {
|
||||
write!(f, " FROM {}", from)?;
|
||||
}
|
||||
if let Some(ref to) = self.to {
|
||||
write!(f, " TO {}", to)?;
|
||||
}
|
||||
if let Some(ref step) = self.step {
|
||||
write!(f, " STEP {}", step)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// ClickHouse `INTERPOLATE` clause for use in `ORDER BY` clause when using `WITH FILL` modifier.
|
||||
/// Supported by [ClickHouse syntax]
|
||||
///
|
||||
/// [ClickHouse syntax]: <https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier>
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||
pub struct InterpolateExpr {
|
||||
pub column: Ident,
|
||||
pub expr: Option<Expr>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||
pub struct Interpolate {
|
||||
pub exprs: Option<Vec<InterpolateExpr>>,
|
||||
}
|
||||
|
||||
impl fmt::Display for InterpolateExpr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.column)?;
|
||||
if let Some(ref expr) = self.expr {
|
||||
write!(f, " AS {}", expr)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -297,6 +297,7 @@ define_keywords!(
|
|||
FILE,
|
||||
FILES,
|
||||
FILE_FORMAT,
|
||||
FILL,
|
||||
FILTER,
|
||||
FIRST,
|
||||
FIRST_VALUE,
|
||||
|
@ -382,6 +383,7 @@ define_keywords!(
|
|||
INT64,
|
||||
INT8,
|
||||
INTEGER,
|
||||
INTERPOLATE,
|
||||
INTERSECT,
|
||||
INTERSECTION,
|
||||
INTERVAL,
|
||||
|
@ -682,6 +684,7 @@ define_keywords!(
|
|||
STDDEV_SAMP,
|
||||
STDIN,
|
||||
STDOUT,
|
||||
STEP,
|
||||
STORAGE_INTEGRATION,
|
||||
STORED,
|
||||
STRICT,
|
||||
|
|
|
@ -7934,7 +7934,7 @@ impl<'a> Parser<'a> {
|
|||
body: self.parse_insert_setexpr_boxed()?,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
offset: None,
|
||||
fetch: None,
|
||||
locks: vec![],
|
||||
|
@ -7948,7 +7948,7 @@ impl<'a> Parser<'a> {
|
|||
body: self.parse_update_setexpr_boxed()?,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
offset: None,
|
||||
fetch: None,
|
||||
locks: vec![],
|
||||
|
@ -7960,9 +7960,19 @@ impl<'a> Parser<'a> {
|
|||
let body = self.parse_boxed_query_body(0)?;
|
||||
|
||||
let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
|
||||
self.parse_comma_separated(Parser::parse_order_by_expr)?
|
||||
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
|
||||
};
|
||||
|
||||
Some(OrderBy {
|
||||
exprs: order_by_exprs,
|
||||
interpolate,
|
||||
})
|
||||
} else {
|
||||
vec![]
|
||||
None
|
||||
};
|
||||
|
||||
let mut limit = None;
|
||||
|
@ -9193,7 +9203,7 @@ impl<'a> Parser<'a> {
|
|||
subquery: Box::new(Query {
|
||||
with: None,
|
||||
body: Box::new(values),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -10519,13 +10529,77 @@ impl<'a> Parser<'a> {
|
|||
None
|
||||
};
|
||||
|
||||
let with_fill = if dialect_of!(self is ClickHouseDialect | GenericDialect)
|
||||
&& self.parse_keywords(&[Keyword::WITH, Keyword::FILL])
|
||||
{
|
||||
Some(self.parse_with_fill()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(OrderByExpr {
|
||||
expr,
|
||||
asc,
|
||||
nulls_first,
|
||||
with_fill,
|
||||
})
|
||||
}
|
||||
|
||||
// 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> {
|
||||
let from = if self.parse_keyword(Keyword::FROM) {
|
||||
Some(self.parse_expr()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let to = if self.parse_keyword(Keyword::TO) {
|
||||
Some(self.parse_expr()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let step = if self.parse_keyword(Keyword::STEP) {
|
||||
Some(self.parse_expr()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(WithFill { from, to, step })
|
||||
}
|
||||
|
||||
// Parse a set of comma seperated INTERPOLATE expressions (ClickHouse dialect)
|
||||
// that follow the INTERPOLATE keyword in an ORDER BY clause with the WITH FILL modifier
|
||||
pub fn parse_interpolations(&mut self) -> Result<Option<Interpolate>, ParserError> {
|
||||
if !self.parse_keyword(Keyword::INTERPOLATE) {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if self.consume_token(&Token::LParen) {
|
||||
let interpolations = self.parse_comma_separated0(|p| p.parse_interpolation())?;
|
||||
self.expect_token(&Token::RParen)?;
|
||||
// INTERPOLATE () and INTERPOLATE ( ... ) variants
|
||||
return Ok(Some(Interpolate {
|
||||
exprs: Some(interpolations),
|
||||
}));
|
||||
}
|
||||
|
||||
// INTERPOLATE
|
||||
Ok(Some(Interpolate { exprs: None }))
|
||||
}
|
||||
|
||||
// Parse a INTERPOLATE expression (ClickHouse dialect)
|
||||
pub fn parse_interpolation(&mut self) -> Result<InterpolateExpr, ParserError> {
|
||||
let column = self.parse_identifier(false)?;
|
||||
let expr = if self.parse_keyword(Keyword::AS) {
|
||||
Some(self.parse_expr()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(InterpolateExpr { column, expr })
|
||||
}
|
||||
|
||||
/// Parse a TOP clause, MSSQL equivalent of LIMIT,
|
||||
/// that follows after `SELECT [DISTINCT]`.
|
||||
pub fn parse_top(&mut self) -> Result<Top, ParserError> {
|
||||
|
|
|
@ -720,6 +720,175 @@ fn parse_group_by_with_modifier() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_select_order_by_with_fill_interpolate() {
|
||||
let sql = "SELECT id, fname, lname FROM customer WHERE id < 5 \
|
||||
ORDER BY \
|
||||
fname ASC NULLS FIRST WITH FILL FROM 10 TO 20 STEP 2, \
|
||||
lname DESC NULLS LAST WITH FILL FROM 30 TO 40 STEP 3 \
|
||||
INTERPOLATE (col1 AS col1 + 1) \
|
||||
LIMIT 2";
|
||||
let select = clickhouse().verified_query(sql);
|
||||
assert_eq!(
|
||||
OrderBy {
|
||||
exprs: vec![
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier(Ident::new("fname")),
|
||||
asc: Some(true),
|
||||
nulls_first: Some(true),
|
||||
with_fill: Some(WithFill {
|
||||
from: Some(Expr::Value(number("10"))),
|
||||
to: Some(Expr::Value(number("20"))),
|
||||
step: Some(Expr::Value(number("2"))),
|
||||
}),
|
||||
},
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier(Ident::new("lname")),
|
||||
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"),
|
||||
expr: Some(Expr::BinaryOp {
|
||||
left: Box::new(Expr::Identifier(Ident::new("col1"))),
|
||||
op: BinaryOperator::Plus,
|
||||
right: Box::new(Expr::Value(number("1"))),
|
||||
}),
|
||||
}])
|
||||
})
|
||||
},
|
||||
select.order_by.expect("ORDER BY expected")
|
||||
);
|
||||
assert_eq!(Some(Expr::Value(number("2"))), select.limit);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_select_order_by_with_fill_interpolate_multi_interpolates() {
|
||||
let sql = "SELECT id, fname, lname FROM customer ORDER BY fname WITH FILL \
|
||||
INTERPOLATE (col1 AS col1 + 1) INTERPOLATE (col2 AS col2 + 2)";
|
||||
clickhouse_and_generic()
|
||||
.parse_sql_statements(sql)
|
||||
.expect_err("ORDER BY only accepts a single INTERPOLATE clause");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_select_order_by_with_fill_interpolate_multi_with_fill_interpolates() {
|
||||
let sql = "SELECT id, fname, lname FROM customer \
|
||||
ORDER BY \
|
||||
fname WITH FILL INTERPOLATE (col1 AS col1 + 1), \
|
||||
lname WITH FILL INTERPOLATE (col2 AS col2 + 2)";
|
||||
clickhouse_and_generic()
|
||||
.parse_sql_statements(sql)
|
||||
.expect_err("ORDER BY only accepts a single INTERPOLATE clause");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_select_order_by_interpolate_not_last() {
|
||||
let sql = "SELECT id, fname, lname FROM customer \
|
||||
ORDER BY \
|
||||
fname INTERPOLATE (col2 AS col2 + 2),
|
||||
lname";
|
||||
clickhouse_and_generic()
|
||||
.parse_sql_statements(sql)
|
||||
.expect_err("ORDER BY INTERPOLATE must be in the last position");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_with_fill() {
|
||||
let sql = "SELECT fname FROM customer ORDER BY fname \
|
||||
WITH FILL FROM 10 TO 20 STEP 2";
|
||||
let select = clickhouse().verified_query(sql);
|
||||
assert_eq!(
|
||||
Some(WithFill {
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_with_fill_missing_single_argument() {
|
||||
let sql = "SELECT id, fname, lname FROM customer ORDER BY \
|
||||
fname WITH FILL FROM TO 20";
|
||||
clickhouse_and_generic()
|
||||
.parse_sql_statements(sql)
|
||||
.expect_err("WITH FILL requires expressions for all arguments");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_with_fill_multiple_incomplete_arguments() {
|
||||
let sql = "SELECT id, fname, lname FROM customer ORDER BY \
|
||||
fname WITH FILL FROM TO 20, lname WITH FILL FROM TO STEP 1";
|
||||
clickhouse_and_generic()
|
||||
.parse_sql_statements(sql)
|
||||
.expect_err("WITH FILL requires expressions for all arguments");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_interpolate_body_with_columns() {
|
||||
let sql = "SELECT fname FROM customer ORDER BY fname WITH FILL \
|
||||
INTERPOLATE (col1 AS col1 + 1, col2 AS col3, col4 AS col4 + 4)";
|
||||
let select = clickhouse().verified_query(sql);
|
||||
assert_eq!(
|
||||
Some(Interpolate {
|
||||
exprs: Some(vec![
|
||||
InterpolateExpr {
|
||||
column: Ident::new("col1"),
|
||||
expr: Some(Expr::BinaryOp {
|
||||
left: Box::new(Expr::Identifier(Ident::new("col1"))),
|
||||
op: BinaryOperator::Plus,
|
||||
right: Box::new(Expr::Value(number("1"))),
|
||||
}),
|
||||
},
|
||||
InterpolateExpr {
|
||||
column: Ident::new("col2"),
|
||||
expr: Some(Expr::Identifier(Ident::new("col3"))),
|
||||
},
|
||||
InterpolateExpr {
|
||||
column: Ident::new("col4"),
|
||||
expr: Some(Expr::BinaryOp {
|
||||
left: Box::new(Expr::Identifier(Ident::new("col4"))),
|
||||
op: BinaryOperator::Plus,
|
||||
right: Box::new(Expr::Value(number("4"))),
|
||||
}),
|
||||
},
|
||||
])
|
||||
}),
|
||||
select.order_by.expect("ORDER BY expected").interpolate
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_interpolate_with_empty_body() {
|
||||
let sql = "SELECT fname FROM customer ORDER BY fname WITH FILL INTERPOLATE ()";
|
||||
let select = clickhouse().verified_query(sql);
|
||||
assert_eq!(
|
||||
Some(Interpolate {
|
||||
exprs: Some(vec![])
|
||||
}),
|
||||
select.order_by.expect("ORDER BY expected").interpolate
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prewhere() {
|
||||
match clickhouse_and_generic().verified_stmt("SELECT * FROM t PREWHERE x = 1 WHERE y = 2") {
|
||||
|
|
|
@ -409,7 +409,7 @@ fn parse_update_set_from() {
|
|||
value_table_mode: None,
|
||||
connect_by: None,
|
||||
}))),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -2065,19 +2065,22 @@ fn parse_select_order_by() {
|
|||
expr: Expr::Identifier(Ident::new("lname")),
|
||||
asc: Some(true),
|
||||
nulls_first: None,
|
||||
with_fill: None,
|
||||
},
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier(Ident::new("fname")),
|
||||
asc: Some(false),
|
||||
nulls_first: None,
|
||||
with_fill: None,
|
||||
},
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier(Ident::new("id")),
|
||||
asc: None,
|
||||
nulls_first: None,
|
||||
with_fill: None,
|
||||
},
|
||||
],
|
||||
select.order_by
|
||||
select.order_by.expect("ORDER BY expected").exprs
|
||||
);
|
||||
}
|
||||
chk("SELECT id, fname, lname FROM customer WHERE id < 5 ORDER BY lname ASC, fname DESC, id");
|
||||
|
@ -2097,14 +2100,16 @@ fn parse_select_order_by_limit() {
|
|||
expr: Expr::Identifier(Ident::new("lname")),
|
||||
asc: Some(true),
|
||||
nulls_first: None,
|
||||
with_fill: None,
|
||||
},
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier(Ident::new("fname")),
|
||||
asc: Some(false),
|
||||
nulls_first: None,
|
||||
with_fill: None,
|
||||
},
|
||||
],
|
||||
select.order_by
|
||||
select.order_by.expect("ORDER BY expected").exprs
|
||||
);
|
||||
assert_eq!(Some(Expr::Value(number("2"))), select.limit);
|
||||
}
|
||||
|
@ -2120,14 +2125,16 @@ fn parse_select_order_by_nulls_order() {
|
|||
expr: Expr::Identifier(Ident::new("lname")),
|
||||
asc: Some(true),
|
||||
nulls_first: Some(true),
|
||||
with_fill: None,
|
||||
},
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier(Ident::new("fname")),
|
||||
asc: Some(false),
|
||||
nulls_first: Some(false),
|
||||
with_fill: None,
|
||||
},
|
||||
],
|
||||
select.order_by
|
||||
select.order_by.expect("ORDER BY expeccted").exprs
|
||||
);
|
||||
assert_eq!(Some(Expr::Value(number("2"))), select.limit);
|
||||
}
|
||||
|
@ -2219,6 +2226,7 @@ fn parse_select_qualify() {
|
|||
expr: Expr::Identifier(Ident::new("o")),
|
||||
asc: None,
|
||||
nulls_first: None,
|
||||
with_fill: None,
|
||||
}],
|
||||
window_frame: None,
|
||||
})),
|
||||
|
@ -2579,6 +2587,7 @@ fn parse_listagg() {
|
|||
}),
|
||||
asc: None,
|
||||
nulls_first: None,
|
||||
with_fill: None,
|
||||
},
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier(Ident {
|
||||
|
@ -2587,6 +2596,7 @@ fn parse_listagg() {
|
|||
}),
|
||||
asc: None,
|
||||
nulls_first: None,
|
||||
with_fill: None,
|
||||
},
|
||||
]
|
||||
}),
|
||||
|
@ -3437,7 +3447,7 @@ fn parse_create_table_as_table() {
|
|||
table_name: Some("old_table".to_string()),
|
||||
schema_name: None,
|
||||
}))),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -3464,7 +3474,7 @@ fn parse_create_table_as_table() {
|
|||
table_name: Some("old_table".to_string()),
|
||||
schema_name: Some("schema_name".to_string()),
|
||||
}))),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -4384,6 +4394,7 @@ fn parse_window_functions() {
|
|||
expr: Expr::Identifier(Ident::new("dt")),
|
||||
asc: Some(false),
|
||||
nulls_first: None,
|
||||
with_fill: None,
|
||||
}],
|
||||
window_frame: None,
|
||||
})),
|
||||
|
@ -4593,6 +4604,7 @@ fn test_parse_named_window() {
|
|||
}),
|
||||
asc: None,
|
||||
nulls_first: None,
|
||||
with_fill: None,
|
||||
}],
|
||||
window_frame: None,
|
||||
}),
|
||||
|
@ -5014,7 +5026,7 @@ fn parse_interval_and_or_xor() {
|
|||
value_table_mode: None,
|
||||
connect_by: None,
|
||||
}))),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -7300,11 +7312,13 @@ fn parse_create_index() {
|
|||
expr: Expr::Identifier(Ident::new("name")),
|
||||
asc: None,
|
||||
nulls_first: None,
|
||||
with_fill: None,
|
||||
},
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier(Ident::new("age")),
|
||||
asc: Some(false),
|
||||
nulls_first: None,
|
||||
with_fill: None,
|
||||
},
|
||||
];
|
||||
match verified_stmt(sql) {
|
||||
|
@ -7334,11 +7348,13 @@ fn test_create_index_with_using_function() {
|
|||
expr: Expr::Identifier(Ident::new("name")),
|
||||
asc: None,
|
||||
nulls_first: None,
|
||||
with_fill: None,
|
||||
},
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier(Ident::new("age")),
|
||||
asc: Some(false),
|
||||
nulls_first: None,
|
||||
with_fill: None,
|
||||
},
|
||||
];
|
||||
match verified_stmt(sql) {
|
||||
|
@ -7691,7 +7707,7 @@ fn parse_merge() {
|
|||
value_table_mode: None,
|
||||
connect_by: None,
|
||||
}))),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -9223,7 +9239,7 @@ fn parse_unload() {
|
|||
fetch: None,
|
||||
locks: vec![],
|
||||
for_clause: None,
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
settings: None,
|
||||
format_clause: None,
|
||||
}),
|
||||
|
@ -9622,6 +9638,7 @@ fn test_match_recognize() {
|
|||
expr: Expr::Identifier(Ident::new("price_date")),
|
||||
asc: None,
|
||||
nulls_first: None,
|
||||
with_fill: None,
|
||||
}],
|
||||
measures: vec![
|
||||
Measure {
|
||||
|
|
|
@ -103,7 +103,7 @@ fn parse_create_procedure() {
|
|||
fetch: None,
|
||||
locks: vec![],
|
||||
for_clause: None,
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
settings: None,
|
||||
format_clause: None,
|
||||
body: Box::new(SetExpr::Select(Box::new(Select {
|
||||
|
@ -546,7 +546,7 @@ fn parse_substring_in_select() {
|
|||
value_table_mode: None,
|
||||
connect_by: None,
|
||||
}))),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
|
|
@ -946,7 +946,7 @@ fn parse_escaped_quote_identifiers_with_escape() {
|
|||
value_table_mode: None,
|
||||
connect_by: None,
|
||||
}))),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -996,7 +996,7 @@ fn parse_escaped_quote_identifiers_with_no_escape() {
|
|||
value_table_mode: None,
|
||||
connect_by: None,
|
||||
}))),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -1043,7 +1043,7 @@ fn parse_escaped_backticks_with_escape() {
|
|||
value_table_mode: None,
|
||||
connect_by: None,
|
||||
}))),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -1090,7 +1090,7 @@ fn parse_escaped_backticks_with_no_escape() {
|
|||
value_table_mode: None,
|
||||
connect_by: None,
|
||||
}))),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -1296,7 +1296,7 @@ fn parse_simple_insert() {
|
|||
]
|
||||
]
|
||||
})),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -1340,7 +1340,7 @@ fn parse_ignore_insert() {
|
|||
Expr::Value(number("1"))
|
||||
]]
|
||||
})),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -1384,7 +1384,7 @@ fn parse_priority_insert() {
|
|||
Expr::Value(number("1"))
|
||||
]]
|
||||
})),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -1425,7 +1425,7 @@ fn parse_priority_insert() {
|
|||
Expr::Value(number("1"))
|
||||
]]
|
||||
})),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -1474,7 +1474,7 @@ fn parse_insert_as() {
|
|||
"2024-01-01".to_string()
|
||||
))]]
|
||||
})),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -1535,7 +1535,7 @@ fn parse_insert_as() {
|
|||
Expr::Value(Value::SingleQuotedString("2024-01-01".to_string()))
|
||||
]]
|
||||
})),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -1580,7 +1580,7 @@ fn parse_replace_insert() {
|
|||
Expr::Value(number("1"))
|
||||
]]
|
||||
})),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -1619,7 +1619,7 @@ fn parse_empty_row_insert() {
|
|||
explicit_row: false,
|
||||
rows: vec![vec![], vec![]]
|
||||
})),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -1681,7 +1681,7 @@ fn parse_insert_with_on_duplicate_update() {
|
|||
Expr::Value(Value::Boolean(true)),
|
||||
]]
|
||||
})),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -1946,6 +1946,7 @@ fn parse_delete_with_order_by() {
|
|||
}),
|
||||
asc: Some(false),
|
||||
nulls_first: None,
|
||||
with_fill: None,
|
||||
}],
|
||||
order_by
|
||||
);
|
||||
|
@ -2331,7 +2332,7 @@ fn parse_substring_in_select() {
|
|||
value_table_mode: None,
|
||||
connect_by: None,
|
||||
}))),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -2639,7 +2640,7 @@ fn parse_hex_string_introducer() {
|
|||
into: None,
|
||||
connect_by: None,
|
||||
}))),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
|
|
@ -1159,7 +1159,7 @@ fn parse_copy_to() {
|
|||
value_table_mode: None,
|
||||
connect_by: None,
|
||||
}))),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -2491,7 +2491,7 @@ fn parse_array_subquery_expr() {
|
|||
connect_by: None,
|
||||
}))),
|
||||
}),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -4162,7 +4162,7 @@ fn test_simple_postgres_insert_with_alias() {
|
|||
Expr::Value(Value::Number("123".to_string(), false))
|
||||
]]
|
||||
})),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -4231,7 +4231,7 @@ fn test_simple_postgres_insert_with_alias() {
|
|||
))
|
||||
]]
|
||||
})),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
@ -4296,7 +4296,7 @@ fn test_simple_insert_with_quoted_alias() {
|
|||
Expr::Value(Value::SingleQuotedString("0123".to_string()))
|
||||
]]
|
||||
})),
|
||||
order_by: vec![],
|
||||
order_by: None,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
offset: None,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue