mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-04 06:18:17 +00:00
Support multi args for unnest (#909)
Signed-off-by: jayzhan211 <jayzhan211@gmail.com> Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
parent
f05f71e20d
commit
20ac38b4da
6 changed files with 98 additions and 14 deletions
|
@ -677,7 +677,7 @@ pub enum TableFactor {
|
|||
/// ```
|
||||
UNNEST {
|
||||
alias: Option<TableAlias>,
|
||||
array_expr: Box<Expr>,
|
||||
array_exprs: Vec<Expr>,
|
||||
with_offset: bool,
|
||||
with_offset_alias: Option<Ident>,
|
||||
},
|
||||
|
@ -749,11 +749,12 @@ impl fmt::Display for TableFactor {
|
|||
}
|
||||
TableFactor::UNNEST {
|
||||
alias,
|
||||
array_expr,
|
||||
array_exprs,
|
||||
with_offset,
|
||||
with_offset_alias,
|
||||
} => {
|
||||
write!(f, "UNNEST({array_expr})")?;
|
||||
write!(f, "UNNEST({})", display_comma_separated(array_exprs))?;
|
||||
|
||||
if let Some(alias) = alias {
|
||||
write!(f, " AS {alias}")?;
|
||||
}
|
||||
|
|
|
@ -5999,7 +5999,7 @@ impl<'a> Parser<'a> {
|
|||
&& self.parse_keyword(Keyword::UNNEST)
|
||||
{
|
||||
self.expect_token(&Token::LParen)?;
|
||||
let expr = self.parse_expr()?;
|
||||
let array_exprs = self.parse_comma_separated(Parser::parse_expr)?;
|
||||
self.expect_token(&Token::RParen)?;
|
||||
|
||||
let alias = match self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS) {
|
||||
|
@ -6025,7 +6025,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
Ok(TableFactor::UNNEST {
|
||||
alias,
|
||||
array_expr: Box::new(expr),
|
||||
array_exprs,
|
||||
with_offset,
|
||||
with_offset_alias,
|
||||
})
|
||||
|
|
|
@ -197,6 +197,7 @@ pub fn expr_from_projection(item: &SelectItem) -> &Expr {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a `Value::Number`, panic'ing if n is not a number
|
||||
pub fn number(n: &'static str) -> Value {
|
||||
Value::Number(n.parse().unwrap(), false)
|
||||
}
|
||||
|
|
|
@ -160,10 +160,10 @@ fn parse_join_constraint_unnest_alias() {
|
|||
vec![Join {
|
||||
relation: TableFactor::UNNEST {
|
||||
alias: table_alias("f"),
|
||||
array_expr: Box::new(Expr::CompoundIdentifier(vec![
|
||||
array_exprs: vec![Expr::CompoundIdentifier(vec![
|
||||
Ident::new("t1"),
|
||||
Ident::new("a")
|
||||
])),
|
||||
])],
|
||||
with_offset: false,
|
||||
with_offset_alias: None
|
||||
},
|
||||
|
|
|
@ -4130,7 +4130,16 @@ fn parse_table_function() {
|
|||
|
||||
#[test]
|
||||
fn parse_unnest() {
|
||||
let sql = "SELECT UNNEST(make_array(1, 2, 3))";
|
||||
one_statement_parses_to(sql, sql);
|
||||
let sql = "SELECT UNNEST(make_array(1, 2, 3), make_array(4, 5))";
|
||||
one_statement_parses_to(sql, sql);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_unnest_in_from_clause() {
|
||||
fn chk(
|
||||
array_exprs: &str,
|
||||
alias: bool,
|
||||
with_offset: bool,
|
||||
with_offset_alias: bool,
|
||||
|
@ -4138,7 +4147,8 @@ fn parse_unnest() {
|
|||
want: Vec<TableWithJoins>,
|
||||
) {
|
||||
let sql = &format!(
|
||||
"SELECT * FROM UNNEST(expr){}{}{}",
|
||||
"SELECT * FROM UNNEST({}){}{}{}",
|
||||
array_exprs,
|
||||
if alias { " AS numbers" } else { "" },
|
||||
if with_offset { " WITH OFFSET" } else { "" },
|
||||
if with_offset_alias {
|
||||
|
@ -4156,6 +4166,7 @@ fn parse_unnest() {
|
|||
};
|
||||
// 1. both Alias and WITH OFFSET clauses.
|
||||
chk(
|
||||
"expr",
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
|
@ -4166,7 +4177,7 @@ fn parse_unnest() {
|
|||
name: Ident::new("numbers"),
|
||||
columns: vec![],
|
||||
}),
|
||||
array_expr: Box::new(Expr::Identifier(Ident::new("expr"))),
|
||||
array_exprs: vec![Expr::Identifier(Ident::new("expr"))],
|
||||
with_offset: true,
|
||||
with_offset_alias: None,
|
||||
},
|
||||
|
@ -4175,6 +4186,7 @@ fn parse_unnest() {
|
|||
);
|
||||
// 2. neither Alias nor WITH OFFSET clause.
|
||||
chk(
|
||||
"expr",
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
|
@ -4182,7 +4194,7 @@ fn parse_unnest() {
|
|||
vec![TableWithJoins {
|
||||
relation: TableFactor::UNNEST {
|
||||
alias: None,
|
||||
array_expr: Box::new(Expr::Identifier(Ident::new("expr"))),
|
||||
array_exprs: vec![Expr::Identifier(Ident::new("expr"))],
|
||||
with_offset: false,
|
||||
with_offset_alias: None,
|
||||
},
|
||||
|
@ -4191,6 +4203,7 @@ fn parse_unnest() {
|
|||
);
|
||||
// 3. Alias but no WITH OFFSET clause.
|
||||
chk(
|
||||
"expr",
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
|
@ -4198,7 +4211,7 @@ fn parse_unnest() {
|
|||
vec![TableWithJoins {
|
||||
relation: TableFactor::UNNEST {
|
||||
alias: None,
|
||||
array_expr: Box::new(Expr::Identifier(Ident::new("expr"))),
|
||||
array_exprs: vec![Expr::Identifier(Ident::new("expr"))],
|
||||
with_offset: true,
|
||||
with_offset_alias: None,
|
||||
},
|
||||
|
@ -4207,6 +4220,7 @@ fn parse_unnest() {
|
|||
);
|
||||
// 4. WITH OFFSET but no Alias.
|
||||
chk(
|
||||
"expr",
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
|
@ -4217,13 +4231,82 @@ fn parse_unnest() {
|
|||
name: Ident::new("numbers"),
|
||||
columns: vec![],
|
||||
}),
|
||||
array_expr: Box::new(Expr::Identifier(Ident::new("expr"))),
|
||||
array_exprs: vec![Expr::Identifier(Ident::new("expr"))],
|
||||
with_offset: false,
|
||||
with_offset_alias: None,
|
||||
},
|
||||
joins: vec![],
|
||||
}],
|
||||
);
|
||||
// 5. Simple array
|
||||
chk(
|
||||
"make_array(1, 2, 3)",
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
&dialects,
|
||||
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")))),
|
||||
],
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
})],
|
||||
with_offset: false,
|
||||
with_offset_alias: None,
|
||||
},
|
||||
joins: vec![],
|
||||
}],
|
||||
);
|
||||
// 6. Multiple arrays
|
||||
chk(
|
||||
"make_array(1, 2, 3), make_array(5, 6)",
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
&dialects,
|
||||
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")))),
|
||||
],
|
||||
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")))),
|
||||
],
|
||||
over: None,
|
||||
distinct: false,
|
||||
special: false,
|
||||
order_by: vec![],
|
||||
}),
|
||||
],
|
||||
with_offset: false,
|
||||
with_offset_alias: None,
|
||||
},
|
||||
joins: vec![],
|
||||
}],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -2407,7 +2407,7 @@ fn parse_create_role() {
|
|||
in_role,
|
||||
in_group,
|
||||
role,
|
||||
user,
|
||||
user: _,
|
||||
admin,
|
||||
authorization_owner,
|
||||
}],
|
||||
|
@ -2435,7 +2435,6 @@ fn parse_create_role() {
|
|||
assert_eq_vec(&["role1", "role2"], in_role);
|
||||
assert!(in_group.is_empty());
|
||||
assert_eq_vec(&["role3"], role);
|
||||
assert!(user.is_empty());
|
||||
assert_eq_vec(&["role4", "role5"], admin);
|
||||
assert_eq!(*authorization_owner, None);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue