support PIVOT table syntax (#836)

Signed-off-by: Pawel Leszczynski <leszczynski.pawel@gmail.com>
This commit is contained in:
pawel.leszczynski 2023-03-26 13:33:35 +02:00 committed by GitHub
parent 79c7ac73df
commit 29dea5d017
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 146 additions and 0 deletions

View file

@ -21,6 +21,7 @@
use matches::assert_matches;
use sqlparser::ast::SelectItem::UnnamedExpr;
use sqlparser::ast::TableFactor::Pivot;
use sqlparser::ast::*;
use sqlparser::dialect::{
AnsiDialect, BigQueryDialect, ClickHouseDialect, GenericDialect, HiveDialect, MsSqlDialect,
@ -6718,6 +6719,67 @@ fn parse_with_recursion_limit() {
assert!(matches!(res, Ok(_)), "{res:?}");
}
#[test]
fn parse_pivot_table() {
let sql = concat!(
"SELECT * FROM monthly_sales AS a ",
"PIVOT(SUM(a.amount) FOR a.MONTH IN ('JAN', 'FEB', 'MAR', 'APR')) AS p (c, d) ",
"ORDER BY EMPID"
);
assert_eq!(
verified_only_select(sql).from[0].relation,
Pivot {
name: ObjectName(vec![Ident::new("monthly_sales")]),
table_alias: Some(TableAlias {
name: Ident::new("a"),
columns: vec![]
}),
aggregate_function: Expr::Function(Function {
name: ObjectName(vec![Ident::new("SUM")]),
args: (vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
Expr::CompoundIdentifier(vec![Ident::new("a"), Ident::new("amount"),])
))]),
over: None,
distinct: false,
special: false,
}),
value_column: vec![Ident::new("a"), Ident::new("MONTH")],
pivot_values: vec![
Value::SingleQuotedString("JAN".to_string()),
Value::SingleQuotedString("FEB".to_string()),
Value::SingleQuotedString("MAR".to_string()),
Value::SingleQuotedString("APR".to_string()),
],
pivot_alias: Some(TableAlias {
name: Ident {
value: "p".to_string(),
quote_style: None
},
columns: vec![Ident::new("c"), Ident::new("d")],
}),
}
);
assert_eq!(verified_stmt(sql).to_string(), sql);
let sql_without_table_alias = concat!(
"SELECT * FROM monthly_sales ",
"PIVOT(SUM(a.amount) FOR a.MONTH IN ('JAN', 'FEB', 'MAR', 'APR')) AS p (c, d) ",
"ORDER BY EMPID"
);
assert_matches!(
verified_only_select(sql_without_table_alias).from[0].relation,
Pivot {
table_alias: None, // parsing should succeed with empty alias
..
}
);
assert_eq!(
verified_stmt(sql_without_table_alias).to_string(),
sql_without_table_alias
);
}
/// Makes a predicate that looks like ((user_id = $id) OR user_id = $2...)
fn make_where_clause(num: usize) -> String {
use std::fmt::Write;