Skip to content

Commit 7a0f5f0

Browse files
jayzhan211alamb
authored andcommitted
Support multi args for unnest (apache#909)
Signed-off-by: jayzhan211 <[email protected]> Co-authored-by: Andrew Lamb <[email protected]>
1 parent dd6b53a commit 7a0f5f0

File tree

6 files changed

+98
-14
lines changed

6 files changed

+98
-14
lines changed

src/ast/query.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ pub enum TableFactor {
681681
/// ```
682682
UNNEST {
683683
alias: Option<TableAlias>,
684-
array_expr: Box<Expr>,
684+
array_exprs: Vec<Expr>,
685685
with_offset: bool,
686686
with_offset_alias: Option<Ident>,
687687
},
@@ -753,11 +753,12 @@ impl fmt::Display for TableFactor {
753753
}
754754
TableFactor::UNNEST {
755755
alias,
756-
array_expr,
756+
array_exprs,
757757
with_offset,
758758
with_offset_alias,
759759
} => {
760-
write!(f, "UNNEST({array_expr})")?;
760+
write!(f, "UNNEST({})", display_comma_separated(array_exprs))?;
761+
761762
if let Some(alias) = alias {
762763
write!(f, " AS {alias}")?;
763764
}

src/parser.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6046,7 +6046,7 @@ impl<'a> Parser<'a> {
60466046
&& self.parse_keyword(Keyword::UNNEST)
60476047
{
60486048
self.expect_token(&Token::LParen)?;
6049-
let expr = self.parse_expr()?;
6049+
let array_exprs = self.parse_comma_separated(Parser::parse_expr)?;
60506050
self.expect_token(&Token::RParen)?;
60516051

60526052
let alias = match self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS) {
@@ -6072,7 +6072,7 @@ impl<'a> Parser<'a> {
60726072

60736073
Ok(TableFactor::UNNEST {
60746074
alias,
6075-
array_expr: Box::new(expr),
6075+
array_exprs,
60766076
with_offset,
60776077
with_offset_alias,
60786078
})

src/test_utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ pub fn expr_from_projection(item: &SelectItem) -> &Expr {
197197
}
198198
}
199199

200+
/// Creates a `Value::Number`, panic'ing if n is not a number
200201
pub fn number(n: &'static str) -> Value {
201202
Value::Number(n.parse().unwrap(), false)
202203
}

tests/sqlparser_bigquery.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,10 @@ fn parse_join_constraint_unnest_alias() {
160160
vec![Join {
161161
relation: TableFactor::UNNEST {
162162
alias: table_alias("f"),
163-
array_expr: Box::new(Expr::CompoundIdentifier(vec![
163+
array_exprs: vec![Expr::CompoundIdentifier(vec![
164164
Ident::new("t1"),
165165
Ident::new("a")
166-
])),
166+
])],
167167
with_offset: false,
168168
with_offset_alias: None
169169
},

tests/sqlparser_common.rs

Lines changed: 88 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4130,15 +4130,25 @@ fn parse_table_function() {
41304130

41314131
#[test]
41324132
fn parse_unnest() {
4133+
let sql = "SELECT UNNEST(make_array(1, 2, 3))";
4134+
one_statement_parses_to(sql, sql);
4135+
let sql = "SELECT UNNEST(make_array(1, 2, 3), make_array(4, 5))";
4136+
one_statement_parses_to(sql, sql);
4137+
}
4138+
4139+
#[test]
4140+
fn parse_unnest_in_from_clause() {
41334141
fn chk(
4142+
array_exprs: &str,
41344143
alias: bool,
41354144
with_offset: bool,
41364145
with_offset_alias: bool,
41374146
dialects: &TestedDialects,
41384147
want: Vec<TableWithJoins>,
41394148
) {
41404149
let sql = &format!(
4141-
"SELECT * FROM UNNEST(expr){}{}{}",
4150+
"SELECT * FROM UNNEST({}){}{}{}",
4151+
array_exprs,
41424152
if alias { " AS numbers" } else { "" },
41434153
if with_offset { " WITH OFFSET" } else { "" },
41444154
if with_offset_alias {
@@ -4156,6 +4166,7 @@ fn parse_unnest() {
41564166
};
41574167
// 1. both Alias and WITH OFFSET clauses.
41584168
chk(
4169+
"expr",
41594170
true,
41604171
true,
41614172
false,
@@ -4166,7 +4177,7 @@ fn parse_unnest() {
41664177
name: Ident::new("numbers"),
41674178
columns: vec![],
41684179
}),
4169-
array_expr: Box::new(Expr::Identifier(Ident::new("expr"))),
4180+
array_exprs: vec![Expr::Identifier(Ident::new("expr"))],
41704181
with_offset: true,
41714182
with_offset_alias: None,
41724183
},
@@ -4175,14 +4186,15 @@ fn parse_unnest() {
41754186
);
41764187
// 2. neither Alias nor WITH OFFSET clause.
41774188
chk(
4189+
"expr",
41784190
false,
41794191
false,
41804192
false,
41814193
&dialects,
41824194
vec![TableWithJoins {
41834195
relation: TableFactor::UNNEST {
41844196
alias: None,
4185-
array_expr: Box::new(Expr::Identifier(Ident::new("expr"))),
4197+
array_exprs: vec![Expr::Identifier(Ident::new("expr"))],
41864198
with_offset: false,
41874199
with_offset_alias: None,
41884200
},
@@ -4191,14 +4203,15 @@ fn parse_unnest() {
41914203
);
41924204
// 3. Alias but no WITH OFFSET clause.
41934205
chk(
4206+
"expr",
41944207
false,
41954208
true,
41964209
false,
41974210
&dialects,
41984211
vec![TableWithJoins {
41994212
relation: TableFactor::UNNEST {
42004213
alias: None,
4201-
array_expr: Box::new(Expr::Identifier(Ident::new("expr"))),
4214+
array_exprs: vec![Expr::Identifier(Ident::new("expr"))],
42024215
with_offset: true,
42034216
with_offset_alias: None,
42044217
},
@@ -4207,6 +4220,7 @@ fn parse_unnest() {
42074220
);
42084221
// 4. WITH OFFSET but no Alias.
42094222
chk(
4223+
"expr",
42104224
true,
42114225
false,
42124226
false,
@@ -4217,13 +4231,82 @@ fn parse_unnest() {
42174231
name: Ident::new("numbers"),
42184232
columns: vec![],
42194233
}),
4220-
array_expr: Box::new(Expr::Identifier(Ident::new("expr"))),
4234+
array_exprs: vec![Expr::Identifier(Ident::new("expr"))],
4235+
with_offset: false,
4236+
with_offset_alias: None,
4237+
},
4238+
joins: vec![],
4239+
}],
4240+
);
4241+
// 5. Simple array
4242+
chk(
4243+
"make_array(1, 2, 3)",
4244+
false,
4245+
false,
4246+
false,
4247+
&dialects,
4248+
vec![TableWithJoins {
4249+
relation: TableFactor::UNNEST {
4250+
alias: None,
4251+
array_exprs: vec![Expr::Function(Function {
4252+
name: ObjectName(vec![Ident::new("make_array")]),
4253+
args: vec![
4254+
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("1")))),
4255+
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("2")))),
4256+
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("3")))),
4257+
],
4258+
over: None,
4259+
distinct: false,
4260+
special: false,
4261+
order_by: vec![],
4262+
})],
42214263
with_offset: false,
42224264
with_offset_alias: None,
42234265
},
42244266
joins: vec![],
42254267
}],
42264268
);
4269+
// 6. Multiple arrays
4270+
chk(
4271+
"make_array(1, 2, 3), make_array(5, 6)",
4272+
false,
4273+
false,
4274+
false,
4275+
&dialects,
4276+
vec![TableWithJoins {
4277+
relation: TableFactor::UNNEST {
4278+
alias: None,
4279+
array_exprs: vec![
4280+
Expr::Function(Function {
4281+
name: ObjectName(vec![Ident::new("make_array")]),
4282+
args: vec![
4283+
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("1")))),
4284+
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("2")))),
4285+
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("3")))),
4286+
],
4287+
over: None,
4288+
distinct: false,
4289+
special: false,
4290+
order_by: vec![],
4291+
}),
4292+
Expr::Function(Function {
4293+
name: ObjectName(vec![Ident::new("make_array")]),
4294+
args: vec![
4295+
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("5")))),
4296+
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("6")))),
4297+
],
4298+
over: None,
4299+
distinct: false,
4300+
special: false,
4301+
order_by: vec![],
4302+
}),
4303+
],
4304+
with_offset: false,
4305+
with_offset_alias: None,
4306+
},
4307+
joins: vec![],
4308+
}],
4309+
)
42274310
}
42284311

42294312
#[test]

tests/sqlparser_postgres.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2407,7 +2407,7 @@ fn parse_create_role() {
24072407
in_role,
24082408
in_group,
24092409
role,
2410-
user,
2410+
user: _,
24112411
admin,
24122412
authorization_owner,
24132413
}],
@@ -2435,7 +2435,6 @@ fn parse_create_role() {
24352435
assert_eq_vec(&["role1", "role2"], in_role);
24362436
assert!(in_group.is_empty());
24372437
assert_eq_vec(&["role3"], role);
2438-
assert!(user.is_empty());
24392438
assert_eq_vec(&["role4", "role5"], admin);
24402439
assert_eq!(*authorization_owner, None);
24412440
}

0 commit comments

Comments
 (0)