snowflake: add qualify expression (#465)

Signed-off-by: Maciej Obuchowski <obuchowski.maciej@gmail.com>
This commit is contained in:
Maciej Obuchowski 2022-04-29 20:11:11 +02:00 committed by GitHub
parent edad20cbb8
commit 525ba527bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 60 additions and 2 deletions

View file

@ -154,6 +154,8 @@ pub struct Select {
pub sort_by: Vec<Expr>,
/// HAVING
pub having: Option<Expr>,
/// QUALIFY (Snowflake)
pub qualify: Option<Expr>,
}
impl fmt::Display for Select {
@ -202,6 +204,9 @@ impl fmt::Display for Select {
if let Some(ref having) = self.having {
write!(f, " HAVING {}", having)?;
}
if let Some(ref qualify) = self.qualify {
write!(f, " QUALIFY {}", qualify)?;
}
Ok(())
}
}

View file

@ -382,6 +382,7 @@ define_keywords!(
PROCEDURE,
PROGRAM,
PURGE,
QUALIFY,
QUARTER,
QUOTE,
RANGE,
@ -584,6 +585,7 @@ pub const RESERVED_FOR_TABLE_ALIAS: &[Keyword] = &[
// for MSSQL-specific OUTER APPLY (seems reserved in most dialects)
Keyword::OUTER,
Keyword::SET,
Keyword::QUALIFY,
];
/// Can't be used as a column alias, so that `SELECT <expr> alias`

View file

@ -3167,6 +3167,12 @@ impl<'a> Parser<'a> {
None
};
let qualify = if self.parse_keyword(Keyword::QUALIFY) {
Some(self.parse_expr()?)
} else {
None
};
Ok(Select {
distinct,
top,
@ -3180,6 +3186,7 @@ impl<'a> Parser<'a> {
distribute_by,
sort_by,
having,
qualify,
})
}

View file

@ -1322,6 +1322,45 @@ fn parse_select_having() {
assert!(select.having.is_some());
}
#[cfg(feature = "bigdecimal")]
#[test]
fn parse_select_qualify() {
let sql = "SELECT i, p, o FROM qt QUALIFY ROW_NUMBER() OVER (PARTITION BY p ORDER BY o) = 1";
let select = verified_only_select(sql);
assert_eq!(
Some(Expr::BinaryOp {
left: Box::new(Expr::Function(Function {
name: ObjectName(vec![Ident::new("ROW_NUMBER")]),
args: vec![],
over: Some(WindowSpec {
partition_by: vec![Expr::Identifier(Ident::new("p"))],
order_by: vec![OrderByExpr {
expr: Expr::Identifier(Ident::new("o")),
asc: None,
nulls_first: None
}],
window_frame: None
}),
distinct: false
})),
op: BinaryOperator::Eq,
right: Box::new(Expr::Value(number("1")))
}),
select.qualify
);
let sql = "SELECT i, p, o, ROW_NUMBER() OVER (PARTITION BY p ORDER BY o) AS row_num FROM qt QUALIFY row_num = 1";
let select = verified_only_select(sql);
assert_eq!(
Some(Expr::BinaryOp {
left: Box::new(Expr::Identifier(Ident::new("row_num"))),
op: BinaryOperator::Eq,
right: Box::new(Expr::Value(number("1")))
}),
select.qualify
);
}
#[test]
fn parse_limit_accepts_all() {
one_statement_parses_to(
@ -4336,7 +4375,8 @@ fn parse_merge() {
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
having: None
having: None,
qualify: None
})),
order_by: vec![],
limit: None,

View file

@ -314,6 +314,7 @@ fn parse_quote_identifiers_2() {
distribute_by: vec![],
sort_by: vec![],
having: None,
qualify: None
})),
order_by: vec![],
limit: None,
@ -754,6 +755,7 @@ fn parse_substring_in_select() {
distribute_by: vec![],
sort_by: vec![],
having: None,
qualify: None
})),
order_by: vec![],
limit: None,

View file

@ -450,6 +450,7 @@ fn parse_update_set_from() {
distribute_by: vec![],
sort_by: vec![],
having: None,
qualify: None
})),
order_by: vec![],
limit: None,

View file

@ -96,7 +96,8 @@ fn parse_map_access_expr() {
cluster_by: vec![],
distribute_by: vec![],
sort_by: vec![],
having: None
having: None,
qualify: None
},
select
);