mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-31 03:07:20 +00:00
Consolidate representation of function calls, remove AggregateExpressionWithFilter
, ArraySubquery
, ListAgg
and ArrayAgg
(#1247)
Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
parent
5ea9c01bb2
commit
a14faa36bb
16 changed files with 773 additions and 1040 deletions
|
@ -1042,13 +1042,15 @@ fn parse_select_count_wildcard() {
|
|||
assert_eq!(
|
||||
&Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("COUNT")]),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Wildcard)],
|
||||
args: FunctionArguments::List(FunctionArgumentList {
|
||||
duplicate_treatment: None,
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Wildcard)],
|
||||
clauses: vec![],
|
||||
}),
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
within_group: vec![]
|
||||
}),
|
||||
expr_from_projection(only(&select.projection))
|
||||
);
|
||||
|
@ -1061,24 +1063,24 @@ fn parse_select_count_distinct() {
|
|||
assert_eq!(
|
||||
&Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("COUNT")]),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::UnaryOp {
|
||||
op: UnaryOperator::Plus,
|
||||
expr: Box::new(Expr::Identifier(Ident::new("x"))),
|
||||
}))],
|
||||
args: FunctionArguments::List(FunctionArgumentList {
|
||||
duplicate_treatment: Some(DuplicateTreatment::Distinct),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::UnaryOp {
|
||||
op: UnaryOperator::Plus,
|
||||
expr: Box::new(Expr::Identifier(Ident::new("x"))),
|
||||
}))],
|
||||
clauses: vec![],
|
||||
}),
|
||||
null_treatment: None,
|
||||
within_group: vec![],
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: true,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
over: None
|
||||
}),
|
||||
expr_from_projection(only(&select.projection))
|
||||
);
|
||||
|
||||
one_statement_parses_to(
|
||||
"SELECT COUNT(ALL +x) FROM customer",
|
||||
"SELECT COUNT(+x) FROM customer",
|
||||
);
|
||||
verified_stmt("SELECT COUNT(ALL +x) FROM customer");
|
||||
verified_stmt("SELECT COUNT(+x) FROM customer");
|
||||
|
||||
let sql = "SELECT COUNT(ALL DISTINCT + x) FROM customer";
|
||||
let res = parse_sql_statements(sql);
|
||||
|
@ -2142,13 +2144,15 @@ fn parse_select_having() {
|
|||
Some(Expr::BinaryOp {
|
||||
left: Box::new(Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("COUNT")]),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Wildcard)],
|
||||
args: FunctionArguments::List(FunctionArgumentList {
|
||||
duplicate_treatment: None,
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Wildcard)],
|
||||
clauses: vec![],
|
||||
}),
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
within_group: vec![]
|
||||
})),
|
||||
op: BinaryOperator::Gt,
|
||||
right: Box::new(Expr::Value(number("1"))),
|
||||
|
@ -2169,7 +2173,11 @@ fn parse_select_qualify() {
|
|||
Some(Expr::BinaryOp {
|
||||
left: Box::new(Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("ROW_NUMBER")]),
|
||||
args: vec![],
|
||||
args: FunctionArguments::List(FunctionArgumentList {
|
||||
duplicate_treatment: None,
|
||||
args: vec![],
|
||||
clauses: vec![],
|
||||
}),
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: Some(WindowType::WindowSpec(WindowSpec {
|
||||
|
@ -2182,9 +2190,7 @@ fn parse_select_qualify() {
|
|||
}],
|
||||
window_frame: None,
|
||||
})),
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
within_group: vec![]
|
||||
})),
|
||||
op: BinaryOperator::Eq,
|
||||
right: Box::new(Expr::Value(number("1"))),
|
||||
|
@ -2502,9 +2508,57 @@ fn parse_floor_datetime() {
|
|||
|
||||
#[test]
|
||||
fn parse_listagg() {
|
||||
let sql = "SELECT LISTAGG(DISTINCT dateid, ', ' ON OVERFLOW TRUNCATE '%' WITHOUT COUNT) \
|
||||
WITHIN GROUP (ORDER BY id, username)";
|
||||
let select = verified_only_select(sql);
|
||||
let select = verified_only_select(concat!(
|
||||
"SELECT LISTAGG(DISTINCT dateid, ', ' ON OVERFLOW TRUNCATE '%' WITHOUT COUNT) ",
|
||||
"WITHIN GROUP (ORDER BY id, username)",
|
||||
));
|
||||
|
||||
assert_eq!(
|
||||
&Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("LISTAGG")]),
|
||||
args: FunctionArguments::List(FunctionArgumentList {
|
||||
duplicate_treatment: Some(DuplicateTreatment::Distinct),
|
||||
args: vec![
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(Ident::new(
|
||||
"dateid"
|
||||
)))),
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
||||
Value::SingleQuotedString(", ".to_owned())
|
||||
)))
|
||||
],
|
||||
clauses: vec![FunctionArgumentClause::OnOverflow(
|
||||
ListAggOnOverflow::Truncate {
|
||||
filler: Some(Box::new(Expr::Value(Value::SingleQuotedString(
|
||||
"%".to_string(),
|
||||
)))),
|
||||
with_count: false,
|
||||
}
|
||||
)],
|
||||
}),
|
||||
filter: None,
|
||||
null_treatment: None,
|
||||
over: None,
|
||||
within_group: vec![
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier(Ident {
|
||||
value: "id".to_string(),
|
||||
quote_style: None,
|
||||
}),
|
||||
asc: None,
|
||||
nulls_first: None,
|
||||
},
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier(Ident {
|
||||
value: "username".to_string(),
|
||||
quote_style: None,
|
||||
}),
|
||||
asc: None,
|
||||
nulls_first: None,
|
||||
},
|
||||
]
|
||||
}),
|
||||
expr_from_projection(only(&select.projection))
|
||||
);
|
||||
|
||||
verified_stmt("SELECT LISTAGG(sellerid) WITHIN GROUP (ORDER BY dateid)");
|
||||
verified_stmt("SELECT LISTAGG(dateid)");
|
||||
|
@ -2512,44 +2566,6 @@ fn parse_listagg() {
|
|||
verified_stmt("SELECT LISTAGG(dateid ON OVERFLOW ERROR)");
|
||||
verified_stmt("SELECT LISTAGG(dateid ON OVERFLOW TRUNCATE N'...' WITH COUNT)");
|
||||
verified_stmt("SELECT LISTAGG(dateid ON OVERFLOW TRUNCATE X'deadbeef' WITH COUNT)");
|
||||
|
||||
let expr = Box::new(Expr::Identifier(Ident::new("dateid")));
|
||||
let on_overflow = Some(ListAggOnOverflow::Truncate {
|
||||
filler: Some(Box::new(Expr::Value(Value::SingleQuotedString(
|
||||
"%".to_string(),
|
||||
)))),
|
||||
with_count: false,
|
||||
});
|
||||
let within_group = vec![
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier(Ident {
|
||||
value: "id".to_string(),
|
||||
quote_style: None,
|
||||
}),
|
||||
asc: None,
|
||||
nulls_first: None,
|
||||
},
|
||||
OrderByExpr {
|
||||
expr: Expr::Identifier(Ident {
|
||||
value: "username".to_string(),
|
||||
quote_style: None,
|
||||
}),
|
||||
asc: None,
|
||||
nulls_first: None,
|
||||
},
|
||||
];
|
||||
assert_eq!(
|
||||
&Expr::ListAgg(ListAgg {
|
||||
distinct: true,
|
||||
expr,
|
||||
separator: Some(Box::new(Expr::Value(Value::SingleQuotedString(
|
||||
", ".to_string()
|
||||
)))),
|
||||
on_overflow,
|
||||
within_group,
|
||||
}),
|
||||
expr_from_projection(only(&select.projection))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2575,12 +2591,6 @@ fn parse_array_agg_func() {
|
|||
] {
|
||||
supported_dialects.verified_stmt(sql);
|
||||
}
|
||||
|
||||
// follows special-case array_agg code path. fails in everything except postgres
|
||||
let wc_sql = "SELECT ARRAY_AGG(sections_tbl.*) AS sections FROM sections_tbl";
|
||||
all_dialects_but_pg()
|
||||
.parse_sql_statements(wc_sql)
|
||||
.expect_err("should have failed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2664,24 +2674,31 @@ fn parse_window_function_null_treatment_arg() {
|
|||
unreachable!()
|
||||
};
|
||||
assert_eq!(ObjectName(vec![Ident::new("FIRST_VALUE")]), actual.name);
|
||||
assert!(actual.order_by.is_empty());
|
||||
assert_eq!(1, actual.args.len());
|
||||
let FunctionArguments::List(arg_list) = &actual.args else {
|
||||
panic!("expected argument list")
|
||||
};
|
||||
assert!({
|
||||
arg_list
|
||||
.clauses
|
||||
.iter()
|
||||
.all(|clause| !matches!(clause, FunctionArgumentClause::OrderBy(_)))
|
||||
});
|
||||
assert_eq!(1, arg_list.args.len());
|
||||
let FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(actual_expr))) =
|
||||
&actual.args[0]
|
||||
&arg_list.args[0]
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
assert_eq!(&Ident::new(expected_expr), actual_expr);
|
||||
let Some(NullTreatmentType::FunctionArg(actual_null_treatment)) = actual.null_treatment
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
assert_eq!(expected_null_treatment, actual_null_treatment);
|
||||
assert_eq!(
|
||||
Some(expected_null_treatment),
|
||||
arg_list.clauses.iter().find_map(|clause| match clause {
|
||||
FunctionArgumentClause::IgnoreOrRespectNulls(nt) => Some(*nt),
|
||||
_ => None,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
let sql = "SELECT FIRST_VALUE(a ORDER BY b IGNORE NULLS) OVER () FROM t1";
|
||||
dialects.verified_stmt(sql);
|
||||
|
||||
let sql = "SELECT LAG(1 IGNORE NULLS) IGNORE NULLS OVER () FROM t1";
|
||||
assert_eq!(
|
||||
dialects.parse_sql_statements(sql).unwrap_err(),
|
||||
|
@ -4074,18 +4091,7 @@ fn parse_scalar_function_in_projection() {
|
|||
let sql = dbg!(format!("SELECT {function_name}(id) FROM foo"));
|
||||
let select = verified_only_select(&sql);
|
||||
assert_eq!(
|
||||
&Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new(function_name)]),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||
Expr::Identifier(Ident::new("id"))
|
||||
))],
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
}),
|
||||
&call(function_name, [Expr::Identifier(Ident::new("id"))]),
|
||||
expr_from_projection(only(&select.projection))
|
||||
);
|
||||
}
|
||||
|
@ -4199,28 +4205,30 @@ fn parse_named_argument_function() {
|
|||
assert_eq!(
|
||||
&Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("FUN")]),
|
||||
args: vec![
|
||||
FunctionArg::Named {
|
||||
name: Ident::new("a"),
|
||||
arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString(
|
||||
"1".to_owned()
|
||||
))),
|
||||
operator: FunctionArgOperator::RightArrow
|
||||
},
|
||||
FunctionArg::Named {
|
||||
name: Ident::new("b"),
|
||||
arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString(
|
||||
"2".to_owned()
|
||||
))),
|
||||
operator: FunctionArgOperator::RightArrow
|
||||
},
|
||||
],
|
||||
args: FunctionArguments::List(FunctionArgumentList {
|
||||
duplicate_treatment: None,
|
||||
args: vec![
|
||||
FunctionArg::Named {
|
||||
name: Ident::new("a"),
|
||||
arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString(
|
||||
"1".to_owned()
|
||||
))),
|
||||
operator: FunctionArgOperator::RightArrow
|
||||
},
|
||||
FunctionArg::Named {
|
||||
name: Ident::new("b"),
|
||||
arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString(
|
||||
"2".to_owned()
|
||||
))),
|
||||
operator: FunctionArgOperator::RightArrow
|
||||
},
|
||||
],
|
||||
clauses: vec![],
|
||||
}),
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
within_group: vec![]
|
||||
}),
|
||||
expr_from_projection(only(&select.projection))
|
||||
);
|
||||
|
@ -4235,28 +4243,30 @@ fn parse_named_argument_function_with_eq_operator() {
|
|||
assert_eq!(
|
||||
&Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("FUN")]),
|
||||
args: vec![
|
||||
FunctionArg::Named {
|
||||
name: Ident::new("a"),
|
||||
arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString(
|
||||
"1".to_owned()
|
||||
))),
|
||||
operator: FunctionArgOperator::Equals
|
||||
},
|
||||
FunctionArg::Named {
|
||||
name: Ident::new("b"),
|
||||
arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString(
|
||||
"2".to_owned()
|
||||
))),
|
||||
operator: FunctionArgOperator::Equals
|
||||
},
|
||||
],
|
||||
args: FunctionArguments::List(FunctionArgumentList {
|
||||
duplicate_treatment: None,
|
||||
args: vec![
|
||||
FunctionArg::Named {
|
||||
name: Ident::new("a"),
|
||||
arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString(
|
||||
"1".to_owned()
|
||||
))),
|
||||
operator: FunctionArgOperator::Equals
|
||||
},
|
||||
FunctionArg::Named {
|
||||
name: Ident::new("b"),
|
||||
arg: FunctionArgExpr::Expr(Expr::Value(Value::SingleQuotedString(
|
||||
"2".to_owned()
|
||||
))),
|
||||
operator: FunctionArgOperator::Equals
|
||||
},
|
||||
],
|
||||
clauses: vec![],
|
||||
}),
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
within_group: vec![],
|
||||
}),
|
||||
expr_from_projection(only(&select.projection))
|
||||
);
|
||||
|
@ -4266,22 +4276,14 @@ fn parse_named_argument_function_with_eq_operator() {
|
|||
assert_eq!(
|
||||
all_dialects_except(|d| d.supports_named_fn_args_with_eq_operator())
|
||||
.verified_expr("foo(bar = 42)"),
|
||||
Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("foo")]),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||
Expr::BinaryOp {
|
||||
left: Box::new(Expr::Identifier(Ident::new("bar"))),
|
||||
op: BinaryOperator::Eq,
|
||||
right: Box::new(Expr::Value(number("42"))),
|
||||
},
|
||||
))],
|
||||
filter: None,
|
||||
null_treatment: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
})
|
||||
call(
|
||||
"foo",
|
||||
[Expr::BinaryOp {
|
||||
left: Box::new(Expr::Identifier(Ident::new("bar"))),
|
||||
op: BinaryOperator::Eq,
|
||||
right: Box::new(Expr::Value(number("42"))),
|
||||
}]
|
||||
),
|
||||
);
|
||||
|
||||
// TODO: should this parse for all dialects?
|
||||
|
@ -4313,7 +4315,11 @@ fn parse_window_functions() {
|
|||
assert_eq!(
|
||||
&Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("row_number")]),
|
||||
args: vec![],
|
||||
args: FunctionArguments::List(FunctionArgumentList {
|
||||
duplicate_treatment: None,
|
||||
args: vec![],
|
||||
clauses: vec![],
|
||||
}),
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: Some(WindowType::WindowSpec(WindowSpec {
|
||||
|
@ -4326,9 +4332,7 @@ fn parse_window_functions() {
|
|||
}],
|
||||
window_frame: None,
|
||||
})),
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
within_group: vec![],
|
||||
}),
|
||||
expr_from_projection(&select.projection[0])
|
||||
);
|
||||
|
@ -4439,21 +4443,23 @@ fn test_parse_named_window() {
|
|||
value: "MIN".to_string(),
|
||||
quote_style: None,
|
||||
}]),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||
Expr::Identifier(Ident {
|
||||
value: "c12".to_string(),
|
||||
quote_style: None,
|
||||
}),
|
||||
))],
|
||||
args: FunctionArguments::List(FunctionArgumentList {
|
||||
duplicate_treatment: None,
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||
Expr::Identifier(Ident {
|
||||
value: "c12".to_string(),
|
||||
quote_style: None,
|
||||
}),
|
||||
))],
|
||||
clauses: vec![],
|
||||
}),
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: Some(WindowType::NamedWindow(Ident {
|
||||
value: "window1".to_string(),
|
||||
quote_style: None,
|
||||
})),
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
within_group: vec![],
|
||||
}),
|
||||
alias: Ident {
|
||||
value: "min1".to_string(),
|
||||
|
@ -4466,21 +4472,23 @@ fn test_parse_named_window() {
|
|||
value: "MAX".to_string(),
|
||||
quote_style: None,
|
||||
}]),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||
Expr::Identifier(Ident {
|
||||
value: "c12".to_string(),
|
||||
quote_style: None,
|
||||
}),
|
||||
))],
|
||||
args: FunctionArguments::List(FunctionArgumentList {
|
||||
duplicate_treatment: None,
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||
Expr::Identifier(Ident {
|
||||
value: "c12".to_string(),
|
||||
quote_style: None,
|
||||
}),
|
||||
))],
|
||||
clauses: vec![],
|
||||
}),
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: Some(WindowType::NamedWindow(Ident {
|
||||
value: "window2".to_string(),
|
||||
quote_style: None,
|
||||
})),
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
within_group: vec![],
|
||||
}),
|
||||
alias: Ident {
|
||||
value: "max1".to_string(),
|
||||
|
@ -4982,19 +4990,7 @@ fn parse_at_timezone() {
|
|||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
&Expr::AtTimeZone {
|
||||
timestamp: Box::new(Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident {
|
||||
value: "FROM_UNIXTIME".to_string(),
|
||||
quote_style: None,
|
||||
}]),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(zero.clone()))],
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
})),
|
||||
timestamp: Box::new(call("FROM_UNIXTIME", [zero.clone()])),
|
||||
time_zone: "UTC-06:00".to_string(),
|
||||
},
|
||||
expr_from_projection(only(&select.projection)),
|
||||
|
@ -5004,39 +5000,16 @@ fn parse_at_timezone() {
|
|||
let select = verified_only_select(sql);
|
||||
assert_eq!(
|
||||
&SelectItem::ExprWithAlias {
|
||||
expr: Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident {
|
||||
value: "DATE_FORMAT".to_string(),
|
||||
quote_style: None,
|
||||
},],),
|
||||
args: vec![
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::AtTimeZone {
|
||||
timestamp: Box::new(Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident {
|
||||
value: "FROM_UNIXTIME".to_string(),
|
||||
quote_style: None,
|
||||
},],),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(zero))],
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
},)),
|
||||
expr: call(
|
||||
"DATE_FORMAT",
|
||||
[
|
||||
Expr::AtTimeZone {
|
||||
timestamp: Box::new(call("FROM_UNIXTIME", [zero])),
|
||||
time_zone: "UTC-06:00".to_string(),
|
||||
},),),
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
||||
Value::SingleQuotedString("%Y-%m-%dT%H".to_string()),
|
||||
),),),
|
||||
],
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
},),
|
||||
},
|
||||
Expr::Value(Value::SingleQuotedString("%Y-%m-%dT%H".to_string()),)
|
||||
]
|
||||
),
|
||||
alias: Ident {
|
||||
value: "hour".to_string(),
|
||||
quote_style: Some('"'),
|
||||
|
@ -5185,19 +5158,13 @@ fn parse_table_function() {
|
|||
|
||||
match only(select.from).relation {
|
||||
TableFactor::TableFunction { expr, alias } => {
|
||||
let expected_expr = Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("FUN")]),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
||||
Value::SingleQuotedString("1".to_owned()),
|
||||
)))],
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
});
|
||||
assert_eq!(expr, expected_expr);
|
||||
assert_eq!(
|
||||
call(
|
||||
"FUN",
|
||||
[Expr::Value(Value::SingleQuotedString("1".to_owned()))],
|
||||
),
|
||||
expr
|
||||
);
|
||||
assert_eq!(alias, table_alias("a"))
|
||||
}
|
||||
_ => panic!("Expecting TableFactor::TableFunction"),
|
||||
|
@ -5336,20 +5303,14 @@ fn parse_unnest_in_from_clause() {
|
|||
vec![TableWithJoins {
|
||||
relation: TableFactor::UNNEST {
|
||||
alias: None,
|
||||
array_exprs: vec![Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("make_array")]),
|
||||
args: vec![
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("1")))),
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("2")))),
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("3")))),
|
||||
array_exprs: vec![call(
|
||||
"make_array",
|
||||
[
|
||||
Expr::Value(number("1")),
|
||||
Expr::Value(number("2")),
|
||||
Expr::Value(number("3")),
|
||||
],
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
})],
|
||||
)],
|
||||
with_offset: false,
|
||||
with_offset_alias: None,
|
||||
},
|
||||
|
@ -5367,33 +5328,18 @@ fn parse_unnest_in_from_clause() {
|
|||
relation: TableFactor::UNNEST {
|
||||
alias: None,
|
||||
array_exprs: vec![
|
||||
Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("make_array")]),
|
||||
args: vec![
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("1")))),
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("2")))),
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("3")))),
|
||||
call(
|
||||
"make_array",
|
||||
[
|
||||
Expr::Value(number("1")),
|
||||
Expr::Value(number("2")),
|
||||
Expr::Value(number("3")),
|
||||
],
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
}),
|
||||
Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("make_array")]),
|
||||
args: vec![
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("5")))),
|
||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("6")))),
|
||||
],
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
}),
|
||||
),
|
||||
call(
|
||||
"make_array",
|
||||
[Expr::Value(number("5")), Expr::Value(number("6"))],
|
||||
),
|
||||
],
|
||||
with_offset: false,
|
||||
with_offset_alias: None,
|
||||
|
@ -8001,13 +7947,15 @@ fn parse_time_functions() {
|
|||
let select = verified_only_select(&sql);
|
||||
let select_localtime_func_call_ast = Function {
|
||||
name: ObjectName(vec![Ident::new(func_name)]),
|
||||
args: vec![],
|
||||
args: FunctionArguments::List(FunctionArgumentList {
|
||||
duplicate_treatment: None,
|
||||
args: vec![],
|
||||
clauses: vec![],
|
||||
}),
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
within_group: vec![],
|
||||
};
|
||||
assert_eq!(
|
||||
&Expr::Function(select_localtime_func_call_ast.clone()),
|
||||
|
@ -8017,7 +7965,7 @@ fn parse_time_functions() {
|
|||
// Validating Parenthesis
|
||||
let sql_without_parens = format!("SELECT {}", func_name);
|
||||
let mut ast_without_parens = select_localtime_func_call_ast;
|
||||
ast_without_parens.special = true;
|
||||
ast_without_parens.args = FunctionArguments::None;
|
||||
assert_eq!(
|
||||
&Expr::Function(ast_without_parens),
|
||||
expr_from_projection(&verified_only_select(&sql_without_parens).projection[0])
|
||||
|
@ -8556,18 +8504,13 @@ fn parse_pivot_table() {
|
|||
|
||||
fn expected_function(table: &'static str, alias: Option<&'static str>) -> ExprWithAlias {
|
||||
ExprWithAlias {
|
||||
expr: Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("SUM")]),
|
||||
args: (vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||
Expr::CompoundIdentifier(vec![Ident::new(table), Ident::new("amount")]),
|
||||
))]),
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
}),
|
||||
expr: call(
|
||||
"SUM",
|
||||
[Expr::CompoundIdentifier(vec![
|
||||
Ident::new(table),
|
||||
Ident::new("amount"),
|
||||
])],
|
||||
),
|
||||
alias: alias.map(Ident::new),
|
||||
}
|
||||
}
|
||||
|
@ -8739,18 +8682,7 @@ fn parse_pivot_unpivot_table() {
|
|||
}),
|
||||
}),
|
||||
aggregate_functions: vec![ExprWithAlias {
|
||||
expr: Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("sum")]),
|
||||
args: (vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||
Expr::Identifier(Ident::new("population"))
|
||||
))]),
|
||||
null_treatment: None,
|
||||
filter: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
}),
|
||||
expr: call("sum", [Expr::Identifier(Ident::new("population"))]),
|
||||
alias: None
|
||||
}],
|
||||
value_column: vec![Ident::new("year")],
|
||||
|
@ -8876,16 +8808,18 @@ fn parse_call() {
|
|||
assert_eq!(
|
||||
verified_stmt("CALL my_procedure('a')"),
|
||||
Statement::Call(Function {
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
||||
Value::SingleQuotedString("a".to_string())
|
||||
))),],
|
||||
args: FunctionArguments::List(FunctionArgumentList {
|
||||
duplicate_treatment: None,
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
||||
Value::SingleQuotedString("a".to_string())
|
||||
)))],
|
||||
clauses: vec![],
|
||||
}),
|
||||
name: ObjectName(vec![Ident::new("my_procedure")]),
|
||||
filter: None,
|
||||
null_treatment: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![]
|
||||
within_group: vec![],
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -9085,18 +9019,7 @@ fn parse_map_access_expr() {
|
|||
syntax: MapAccessSyntax::Bracket,
|
||||
},
|
||||
MapAccessKey {
|
||||
key: Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("safe_offset")]),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
||||
number("2"),
|
||||
)))],
|
||||
filter: None,
|
||||
null_treatment: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
}),
|
||||
key: call("safe_offset", [Expr::Value(number("2"))]),
|
||||
syntax: MapAccessSyntax::Bracket,
|
||||
},
|
||||
],
|
||||
|
@ -9284,34 +9207,42 @@ fn test_selective_aggregation() {
|
|||
.verified_only_select(sql)
|
||||
.projection,
|
||||
vec![
|
||||
SelectItem::UnnamedExpr(Expr::AggregateExpressionWithFilter {
|
||||
expr: Box::new(Expr::ArrayAgg(ArrayAgg {
|
||||
distinct: false,
|
||||
expr: Box::new(Expr::Identifier(Ident::new("name"))),
|
||||
order_by: None,
|
||||
limit: None,
|
||||
within_group: false,
|
||||
})),
|
||||
filter: Box::new(Expr::IsNotNull(Box::new(Expr::Identifier(Ident::new(
|
||||
"name"
|
||||
SelectItem::UnnamedExpr(Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("ARRAY_AGG")]),
|
||||
args: FunctionArguments::List(FunctionArgumentList {
|
||||
duplicate_treatment: None,
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||
Expr::Identifier(Ident::new("name"))
|
||||
))],
|
||||
clauses: vec![],
|
||||
}),
|
||||
filter: Some(Box::new(Expr::IsNotNull(Box::new(Expr::Identifier(
|
||||
Ident::new("name")
|
||||
))))),
|
||||
}),
|
||||
over: None,
|
||||
within_group: vec![],
|
||||
null_treatment: None
|
||||
})),
|
||||
SelectItem::ExprWithAlias {
|
||||
expr: Expr::AggregateExpressionWithFilter {
|
||||
expr: Box::new(Expr::ArrayAgg(ArrayAgg {
|
||||
distinct: false,
|
||||
expr: Box::new(Expr::Identifier(Ident::new("name"))),
|
||||
order_by: None,
|
||||
limit: None,
|
||||
within_group: false,
|
||||
})),
|
||||
filter: Box::new(Expr::Like {
|
||||
expr: Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("ARRAY_AGG")]),
|
||||
args: FunctionArguments::List(FunctionArgumentList {
|
||||
duplicate_treatment: None,
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||
Expr::Identifier(Ident::new("name"))
|
||||
))],
|
||||
clauses: vec![],
|
||||
}),
|
||||
filter: Some(Box::new(Expr::Like {
|
||||
negated: false,
|
||||
expr: Box::new(Expr::Identifier(Ident::new("name"))),
|
||||
pattern: Box::new(Expr::Value(Value::SingleQuotedString("a%".to_owned()))),
|
||||
escape_char: None,
|
||||
}),
|
||||
},
|
||||
})),
|
||||
null_treatment: None,
|
||||
over: None,
|
||||
within_group: vec![]
|
||||
}),
|
||||
alias: Ident::new("agg2")
|
||||
},
|
||||
]
|
||||
|
@ -9652,18 +9583,7 @@ fn test_select_wildcard_with_replace() {
|
|||
let expected = SelectItem::Wildcard(WildcardAdditionalOptions {
|
||||
opt_replace: Some(ReplaceSelectItem {
|
||||
items: vec![Box::new(ReplaceSelectElement {
|
||||
expr: Expr::Function(Function {
|
||||
name: ObjectName(vec![Ident::new("lower")]),
|
||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||
Expr::Identifier(Ident::new("city")),
|
||||
))],
|
||||
filter: None,
|
||||
null_treatment: None,
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
}),
|
||||
expr: call("lower", [Expr::Identifier(Ident::new("city"))]),
|
||||
column_name: Ident::new("city"),
|
||||
as_keyword: true,
|
||||
})],
|
||||
|
@ -9799,3 +9719,12 @@ fn test_dictionary_syntax() {
|
|||
]),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_within_group() {
|
||||
verified_expr("PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY sales_amount)");
|
||||
verified_expr(concat!(
|
||||
"PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY sales_amount) ",
|
||||
"OVER (PARTITION BY department)",
|
||||
));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue