mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-09-07 22:50:31 +00:00
Named window frames (#881)
* after over clause, named window can be parsed with window ... as after having clause * Lint errors are fixed * Support for multiple windows * fix lint errors * simplifications * rename function * Rewrite named window search in functional style * Test added and some minor changes * Minor changes on tests and namings, and semantic check is removed --------- Co-authored-by: Mustafa Akur <mustafa.akur@synnada.ai> Co-authored-by: Mehmet Ozan Kabak <ozankabak@gmail.com>
This commit is contained in:
parent
1b86abebe2
commit
ef46cd3752
8 changed files with 225 additions and 37 deletions
|
@ -17,7 +17,7 @@ use alloc::{
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
use core::fmt;
|
use core::fmt::{self, Display};
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -35,10 +35,10 @@ pub use self::ddl::{
|
||||||
pub use self::operator::{BinaryOperator, UnaryOperator};
|
pub use self::operator::{BinaryOperator, UnaryOperator};
|
||||||
pub use self::query::{
|
pub use self::query::{
|
||||||
Cte, Distinct, ExceptSelectItem, ExcludeSelectItem, Fetch, IdentWithAlias, Join,
|
Cte, Distinct, ExceptSelectItem, ExcludeSelectItem, Fetch, IdentWithAlias, Join,
|
||||||
JoinConstraint, JoinOperator, LateralView, LockClause, LockType, NonBlock, Offset, OffsetRows,
|
JoinConstraint, JoinOperator, LateralView, LockClause, LockType, NamedWindowDefinition,
|
||||||
OrderByExpr, Query, RenameSelectItem, ReplaceSelectElement, ReplaceSelectItem, Select,
|
NonBlock, Offset, OffsetRows, OrderByExpr, Query, RenameSelectItem, ReplaceSelectElement,
|
||||||
SelectInto, SelectItem, SetExpr, SetOperator, SetQuantifier, Table, TableAlias, TableFactor,
|
ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, SetOperator, SetQuantifier, Table,
|
||||||
TableWithJoins, Top, Values, WildcardAdditionalOptions, With,
|
TableAlias, TableFactor, TableWithJoins, Top, Values, WildcardAdditionalOptions, With,
|
||||||
};
|
};
|
||||||
pub use self::value::{
|
pub use self::value::{
|
||||||
escape_quoted_string, DateTimeField, DollarQuotedString, TrimWhereField, Value,
|
escape_quoted_string, DateTimeField, DollarQuotedString, TrimWhereField, Value,
|
||||||
|
@ -930,6 +930,23 @@ impl fmt::Display for Expr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
|
pub enum WindowType {
|
||||||
|
WindowSpec(WindowSpec),
|
||||||
|
NamedWindow(Ident),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for WindowType {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
WindowType::WindowSpec(spec) => write!(f, "({})", spec),
|
||||||
|
WindowType::NamedWindow(name) => write!(f, "{}", name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A window specification (i.e. `OVER (PARTITION BY .. ORDER BY .. etc.)`)
|
/// A window specification (i.e. `OVER (PARTITION BY .. ORDER BY .. etc.)`)
|
||||||
#[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))]
|
||||||
|
@ -3360,7 +3377,7 @@ impl fmt::Display for CloseCursor {
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
pub name: ObjectName,
|
pub name: ObjectName,
|
||||||
pub args: Vec<FunctionArg>,
|
pub args: Vec<FunctionArg>,
|
||||||
pub over: Option<WindowSpec>,
|
pub over: Option<WindowType>,
|
||||||
// aggregate functions may specify eg `COUNT(DISTINCT x)`
|
// aggregate functions may specify eg `COUNT(DISTINCT x)`
|
||||||
pub distinct: bool,
|
pub distinct: bool,
|
||||||
// Some functions must be called without trailing parentheses, for example Postgres
|
// Some functions must be called without trailing parentheses, for example Postgres
|
||||||
|
@ -3409,7 +3426,7 @@ impl fmt::Display for Function {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if let Some(o) = &self.over {
|
if let Some(o) = &self.over {
|
||||||
write!(f, " OVER ({o})")?;
|
write!(f, " OVER {o}")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -216,6 +216,8 @@ pub struct Select {
|
||||||
pub sort_by: Vec<Expr>,
|
pub sort_by: Vec<Expr>,
|
||||||
/// HAVING
|
/// HAVING
|
||||||
pub having: Option<Expr>,
|
pub having: Option<Expr>,
|
||||||
|
/// WINDOW AS
|
||||||
|
pub named_window: Vec<NamedWindowDefinition>,
|
||||||
/// QUALIFY (Snowflake)
|
/// QUALIFY (Snowflake)
|
||||||
pub qualify: Option<Expr>,
|
pub qualify: Option<Expr>,
|
||||||
}
|
}
|
||||||
|
@ -269,6 +271,9 @@ impl fmt::Display for Select {
|
||||||
if let Some(ref having) = self.having {
|
if let Some(ref having) = self.having {
|
||||||
write!(f, " HAVING {having}")?;
|
write!(f, " HAVING {having}")?;
|
||||||
}
|
}
|
||||||
|
if !self.named_window.is_empty() {
|
||||||
|
write!(f, " WINDOW {}", display_comma_separated(&self.named_window))?;
|
||||||
|
}
|
||||||
if let Some(ref qualify) = self.qualify {
|
if let Some(ref qualify) = self.qualify {
|
||||||
write!(f, " QUALIFY {qualify}")?;
|
write!(f, " QUALIFY {qualify}")?;
|
||||||
}
|
}
|
||||||
|
@ -311,6 +316,17 @@ impl fmt::Display for LateralView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
|
pub struct NamedWindowDefinition(pub Ident, pub WindowSpec);
|
||||||
|
|
||||||
|
impl fmt::Display for NamedWindowDefinition {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{} AS ({})", self.0, self.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[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))]
|
||||||
|
|
|
@ -688,6 +688,7 @@ pub const RESERVED_FOR_TABLE_ALIAS: &[Keyword] = &[
|
||||||
Keyword::OUTER,
|
Keyword::OUTER,
|
||||||
Keyword::SET,
|
Keyword::SET,
|
||||||
Keyword::QUALIFY,
|
Keyword::QUALIFY,
|
||||||
|
Keyword::WINDOW,
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Can't be used as a column alias, so that `SELECT <expr> alias`
|
/// Can't be used as a column alias, so that `SELECT <expr> alias`
|
||||||
|
|
|
@ -884,32 +884,12 @@ impl<'a> Parser<'a> {
|
||||||
let distinct = self.parse_all_or_distinct()?.is_some();
|
let distinct = self.parse_all_or_distinct()?.is_some();
|
||||||
let (args, order_by) = self.parse_optional_args_with_orderby()?;
|
let (args, order_by) = self.parse_optional_args_with_orderby()?;
|
||||||
let over = if self.parse_keyword(Keyword::OVER) {
|
let over = if self.parse_keyword(Keyword::OVER) {
|
||||||
// TBD: support window names (`OVER mywin`) in place of inline specification
|
if self.consume_token(&Token::LParen) {
|
||||||
self.expect_token(&Token::LParen)?;
|
let window_spec = self.parse_window_spec()?;
|
||||||
let partition_by = if self.parse_keywords(&[Keyword::PARTITION, Keyword::BY]) {
|
Some(WindowType::WindowSpec(window_spec))
|
||||||
// a list of possibly-qualified column names
|
|
||||||
self.parse_comma_separated(Parser::parse_expr)?
|
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
Some(WindowType::NamedWindow(self.parse_identifier()?))
|
||||||
};
|
}
|
||||||
let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
|
|
||||||
self.parse_comma_separated(Parser::parse_order_by_expr)?
|
|
||||||
} else {
|
|
||||||
vec![]
|
|
||||||
};
|
|
||||||
let window_frame = if !self.consume_token(&Token::RParen) {
|
|
||||||
let window_frame = self.parse_window_frame()?;
|
|
||||||
self.expect_token(&Token::RParen)?;
|
|
||||||
Some(window_frame)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
Some(WindowSpec {
|
|
||||||
partition_by,
|
|
||||||
order_by,
|
|
||||||
window_frame,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -5367,6 +5347,12 @@ impl<'a> Parser<'a> {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let named_windows = if self.parse_keyword(Keyword::WINDOW) {
|
||||||
|
self.parse_comma_separated(Parser::parse_named_window)?
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
|
||||||
let qualify = if self.parse_keyword(Keyword::QUALIFY) {
|
let qualify = if self.parse_keyword(Keyword::QUALIFY) {
|
||||||
Some(self.parse_expr()?)
|
Some(self.parse_expr()?)
|
||||||
} else {
|
} else {
|
||||||
|
@ -5386,6 +5372,7 @@ impl<'a> Parser<'a> {
|
||||||
distribute_by,
|
distribute_by,
|
||||||
sort_by,
|
sort_by,
|
||||||
having,
|
having,
|
||||||
|
named_window: named_windows,
|
||||||
qualify,
|
qualify,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -7033,6 +7020,39 @@ impl<'a> Parser<'a> {
|
||||||
pub fn index(&self) -> usize {
|
pub fn index(&self) -> usize {
|
||||||
self.index
|
self.index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_named_window(&mut self) -> Result<NamedWindowDefinition, ParserError> {
|
||||||
|
let ident = self.parse_identifier()?;
|
||||||
|
self.expect_keyword(Keyword::AS)?;
|
||||||
|
self.expect_token(&Token::LParen)?;
|
||||||
|
let window_spec = self.parse_window_spec()?;
|
||||||
|
Ok(NamedWindowDefinition(ident, window_spec))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_window_spec(&mut self) -> Result<WindowSpec, ParserError> {
|
||||||
|
let partition_by = if self.parse_keywords(&[Keyword::PARTITION, Keyword::BY]) {
|
||||||
|
self.parse_comma_separated(Parser::parse_expr)?
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
|
||||||
|
self.parse_comma_separated(Parser::parse_order_by_expr)?
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
let window_frame = if !self.consume_token(&Token::RParen) {
|
||||||
|
let window_frame = self.parse_window_frame()?;
|
||||||
|
self.expect_token(&Token::RParen)?;
|
||||||
|
Some(window_frame)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
Ok(WindowSpec {
|
||||||
|
partition_by,
|
||||||
|
order_by,
|
||||||
|
window_frame,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Word {
|
impl Word {
|
||||||
|
|
|
@ -101,6 +101,7 @@ fn parse_map_access_expr() {
|
||||||
distribute_by: vec![],
|
distribute_by: vec![],
|
||||||
sort_by: vec![],
|
sort_by: vec![],
|
||||||
having: None,
|
having: None,
|
||||||
|
named_window: vec![],
|
||||||
qualify: None
|
qualify: None
|
||||||
},
|
},
|
||||||
select
|
select
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
//! dialect-specific parsing rules).
|
//! dialect-specific parsing rules).
|
||||||
|
|
||||||
use matches::assert_matches;
|
use matches::assert_matches;
|
||||||
|
|
||||||
use sqlparser::ast::SelectItem::UnnamedExpr;
|
use sqlparser::ast::SelectItem::UnnamedExpr;
|
||||||
use sqlparser::ast::TableFactor::Pivot;
|
use sqlparser::ast::TableFactor::Pivot;
|
||||||
use sqlparser::ast::*;
|
use sqlparser::ast::*;
|
||||||
|
@ -251,6 +250,7 @@ fn parse_update_set_from() {
|
||||||
distribute_by: vec![],
|
distribute_by: vec![],
|
||||||
sort_by: vec![],
|
sort_by: vec![],
|
||||||
having: None,
|
having: None,
|
||||||
|
named_window: vec![],
|
||||||
qualify: None
|
qualify: None
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
|
@ -1721,7 +1721,7 @@ fn parse_select_qualify() {
|
||||||
left: Box::new(Expr::Function(Function {
|
left: Box::new(Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::new("ROW_NUMBER")]),
|
name: ObjectName(vec![Ident::new("ROW_NUMBER")]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
over: Some(WindowSpec {
|
over: Some(WindowType::WindowSpec(WindowSpec {
|
||||||
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")),
|
||||||
|
@ -1729,7 +1729,7 @@ fn parse_select_qualify() {
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
}],
|
}],
|
||||||
window_frame: None,
|
window_frame: None,
|
||||||
}),
|
})),
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
|
@ -3295,7 +3295,7 @@ fn parse_window_functions() {
|
||||||
&Expr::Function(Function {
|
&Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::new("row_number")]),
|
name: ObjectName(vec![Ident::new("row_number")]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
over: Some(WindowSpec {
|
over: Some(WindowType::WindowSpec(WindowSpec {
|
||||||
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")),
|
||||||
|
@ -3303,7 +3303,7 @@ fn parse_window_functions() {
|
||||||
nulls_first: None,
|
nulls_first: None,
|
||||||
}],
|
}],
|
||||||
window_frame: None,
|
window_frame: None,
|
||||||
}),
|
})),
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
|
@ -3312,6 +3312,128 @@ fn parse_window_functions() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_named_window() {
|
||||||
|
let sql = "SELECT \
|
||||||
|
MIN(c12) OVER window1 AS min1, \
|
||||||
|
MAX(c12) OVER window2 AS max1 \
|
||||||
|
FROM aggregate_test_100 \
|
||||||
|
WINDOW window1 AS (ORDER BY C12), \
|
||||||
|
window2 AS (PARTITION BY C11) \
|
||||||
|
ORDER BY C3";
|
||||||
|
let actual_select_only = verified_only_select(sql);
|
||||||
|
let expected = Select {
|
||||||
|
distinct: None,
|
||||||
|
top: None,
|
||||||
|
projection: vec![
|
||||||
|
SelectItem::ExprWithAlias {
|
||||||
|
expr: Expr::Function(Function {
|
||||||
|
name: ObjectName(vec![Ident {
|
||||||
|
value: "MIN".to_string(),
|
||||||
|
quote_style: None,
|
||||||
|
}]),
|
||||||
|
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||||
|
Expr::Identifier(Ident {
|
||||||
|
value: "c12".to_string(),
|
||||||
|
quote_style: None,
|
||||||
|
}),
|
||||||
|
))],
|
||||||
|
over: Some(WindowType::NamedWindow(Ident {
|
||||||
|
value: "window1".to_string(),
|
||||||
|
quote_style: None,
|
||||||
|
})),
|
||||||
|
distinct: false,
|
||||||
|
special: false,
|
||||||
|
}),
|
||||||
|
alias: Ident {
|
||||||
|
value: "min1".to_string(),
|
||||||
|
quote_style: None,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SelectItem::ExprWithAlias {
|
||||||
|
expr: Expr::Function(Function {
|
||||||
|
name: ObjectName(vec![Ident {
|
||||||
|
value: "MAX".to_string(),
|
||||||
|
quote_style: None,
|
||||||
|
}]),
|
||||||
|
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||||
|
Expr::Identifier(Ident {
|
||||||
|
value: "c12".to_string(),
|
||||||
|
quote_style: None,
|
||||||
|
}),
|
||||||
|
))],
|
||||||
|
over: Some(WindowType::NamedWindow(Ident {
|
||||||
|
value: "window2".to_string(),
|
||||||
|
quote_style: None,
|
||||||
|
})),
|
||||||
|
distinct: false,
|
||||||
|
special: false,
|
||||||
|
}),
|
||||||
|
alias: Ident {
|
||||||
|
value: "max1".to_string(),
|
||||||
|
quote_style: None,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
into: None,
|
||||||
|
from: vec![TableWithJoins {
|
||||||
|
relation: TableFactor::Table {
|
||||||
|
name: ObjectName(vec![Ident {
|
||||||
|
value: "aggregate_test_100".to_string(),
|
||||||
|
quote_style: None,
|
||||||
|
}]),
|
||||||
|
alias: None,
|
||||||
|
args: None,
|
||||||
|
with_hints: vec![],
|
||||||
|
},
|
||||||
|
joins: vec![],
|
||||||
|
}],
|
||||||
|
lateral_views: vec![],
|
||||||
|
selection: None,
|
||||||
|
group_by: vec![],
|
||||||
|
cluster_by: vec![],
|
||||||
|
distribute_by: vec![],
|
||||||
|
sort_by: vec![],
|
||||||
|
having: None,
|
||||||
|
named_window: vec![
|
||||||
|
NamedWindowDefinition(
|
||||||
|
Ident {
|
||||||
|
value: "window1".to_string(),
|
||||||
|
quote_style: None,
|
||||||
|
},
|
||||||
|
WindowSpec {
|
||||||
|
partition_by: vec![],
|
||||||
|
order_by: vec![OrderByExpr {
|
||||||
|
expr: Expr::Identifier(Ident {
|
||||||
|
value: "C12".to_string(),
|
||||||
|
quote_style: None,
|
||||||
|
}),
|
||||||
|
asc: None,
|
||||||
|
nulls_first: None,
|
||||||
|
}],
|
||||||
|
window_frame: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
NamedWindowDefinition(
|
||||||
|
Ident {
|
||||||
|
value: "window2".to_string(),
|
||||||
|
quote_style: None,
|
||||||
|
},
|
||||||
|
WindowSpec {
|
||||||
|
partition_by: vec![Expr::Identifier(Ident {
|
||||||
|
value: "C11".to_string(),
|
||||||
|
quote_style: None,
|
||||||
|
})],
|
||||||
|
order_by: vec![],
|
||||||
|
window_frame: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
qualify: None,
|
||||||
|
};
|
||||||
|
assert_eq!(actual_select_only, expected);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_aggregate_with_group_by() {
|
fn parse_aggregate_with_group_by() {
|
||||||
let sql = "SELECT a, COUNT(1), MIN(b), MAX(b) FROM foo GROUP BY a";
|
let sql = "SELECT a, COUNT(1), MIN(b), MAX(b) FROM foo GROUP BY a";
|
||||||
|
@ -3659,6 +3781,7 @@ fn parse_interval_and_or_xor() {
|
||||||
distribute_by: vec![],
|
distribute_by: vec![],
|
||||||
sort_by: vec![],
|
sort_by: vec![],
|
||||||
having: None,
|
having: None,
|
||||||
|
named_window: vec![],
|
||||||
qualify: None,
|
qualify: None,
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
|
@ -5929,6 +6052,7 @@ fn parse_merge() {
|
||||||
distribute_by: vec![],
|
distribute_by: vec![],
|
||||||
sort_by: vec![],
|
sort_by: vec![],
|
||||||
having: None,
|
having: None,
|
||||||
|
named_window: vec![],
|
||||||
qualify: None,
|
qualify: None,
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
|
|
|
@ -460,6 +460,7 @@ fn parse_quote_identifiers_2() {
|
||||||
distribute_by: vec![],
|
distribute_by: vec![],
|
||||||
sort_by: vec![],
|
sort_by: vec![],
|
||||||
having: None,
|
having: None,
|
||||||
|
named_window: vec![],
|
||||||
qualify: None
|
qualify: None
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
|
@ -494,6 +495,7 @@ fn parse_quote_identifiers_3() {
|
||||||
distribute_by: vec![],
|
distribute_by: vec![],
|
||||||
sort_by: vec![],
|
sort_by: vec![],
|
||||||
having: None,
|
having: None,
|
||||||
|
named_window: vec![],
|
||||||
qualify: None
|
qualify: None
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
|
@ -884,6 +886,7 @@ fn parse_select_with_numeric_prefix_column_name() {
|
||||||
distribute_by: vec![],
|
distribute_by: vec![],
|
||||||
sort_by: vec![],
|
sort_by: vec![],
|
||||||
having: None,
|
having: None,
|
||||||
|
named_window: vec![],
|
||||||
qualify: None,
|
qualify: None,
|
||||||
})))
|
})))
|
||||||
);
|
);
|
||||||
|
@ -927,6 +930,7 @@ fn parse_select_with_concatenation_of_exp_number_and_numeric_prefix_column() {
|
||||||
distribute_by: vec![],
|
distribute_by: vec![],
|
||||||
sort_by: vec![],
|
sort_by: vec![],
|
||||||
having: None,
|
having: None,
|
||||||
|
named_window: vec![],
|
||||||
qualify: None,
|
qualify: None,
|
||||||
})))
|
})))
|
||||||
);
|
);
|
||||||
|
@ -1116,6 +1120,7 @@ fn parse_substring_in_select() {
|
||||||
distribute_by: vec![],
|
distribute_by: vec![],
|
||||||
sort_by: vec![],
|
sort_by: vec![],
|
||||||
having: None,
|
having: None,
|
||||||
|
named_window: vec![],
|
||||||
qualify: None
|
qualify: None
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
|
@ -1394,6 +1399,7 @@ fn parse_hex_string_introducer() {
|
||||||
distribute_by: vec![],
|
distribute_by: vec![],
|
||||||
sort_by: vec![],
|
sort_by: vec![],
|
||||||
having: None,
|
having: None,
|
||||||
|
named_window: vec![],
|
||||||
qualify: None,
|
qualify: None,
|
||||||
into: None
|
into: None
|
||||||
}))),
|
}))),
|
||||||
|
|
|
@ -954,6 +954,7 @@ fn parse_copy_to() {
|
||||||
selection: None,
|
selection: None,
|
||||||
group_by: vec![],
|
group_by: vec![],
|
||||||
having: None,
|
having: None,
|
||||||
|
named_window: vec![],
|
||||||
cluster_by: vec![],
|
cluster_by: vec![],
|
||||||
distribute_by: vec![],
|
distribute_by: vec![],
|
||||||
sort_by: vec![],
|
sort_by: vec![],
|
||||||
|
@ -1799,6 +1800,7 @@ fn parse_array_subquery_expr() {
|
||||||
distribute_by: vec![],
|
distribute_by: vec![],
|
||||||
sort_by: vec![],
|
sort_by: vec![],
|
||||||
having: None,
|
having: None,
|
||||||
|
named_window: vec![],
|
||||||
qualify: None,
|
qualify: None,
|
||||||
}))),
|
}))),
|
||||||
right: Box::new(SetExpr::Select(Box::new(Select {
|
right: Box::new(SetExpr::Select(Box::new(Select {
|
||||||
|
@ -1820,6 +1822,7 @@ fn parse_array_subquery_expr() {
|
||||||
distribute_by: vec![],
|
distribute_by: vec![],
|
||||||
sort_by: vec![],
|
sort_by: vec![],
|
||||||
having: None,
|
having: None,
|
||||||
|
named_window: vec![],
|
||||||
qualify: None,
|
qualify: None,
|
||||||
}))),
|
}))),
|
||||||
}),
|
}),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue