Skip to content

Commit 3b4b69e

Browse files
committed
Add support for qualified column names in JOIN ... USING
1 parent 36db176 commit 3b4b69e

File tree

5 files changed

+34
-6
lines changed

5 files changed

+34
-6
lines changed

src/ast/query.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2050,7 +2050,7 @@ pub enum JoinOperator {
20502050
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
20512051
pub enum JoinConstraint {
20522052
On(Expr),
2053-
Using(Vec<Ident>),
2053+
Using(Vec<ObjectName>),
20542054
Natural,
20552055
None,
20562056
}

src/ast/spans.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2002,7 +2002,7 @@ impl Spanned for JoinConstraint {
20022002
fn span(&self) -> Span {
20032003
match self {
20042004
JoinConstraint::On(expr) => expr.span(),
2005-
JoinConstraint::Using(vec) => union_spans(vec.iter().map(|i| i.span)),
2005+
JoinConstraint::Using(vec) => union_spans(vec.iter().map(|i| i.span())),
20062006
JoinConstraint::Natural => Span::empty(),
20072007
JoinConstraint::None => Span::empty(),
20082008
}

src/parser/mod.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9291,12 +9291,37 @@ impl<'a> Parser<'a> {
92919291
optional: IsOptional,
92929292
allow_empty: bool,
92939293
) -> Result<Vec<Ident>, ParserError> {
9294+
self.parse_parenthesized_column_list_inner(optional, allow_empty, |p| p.parse_identifier())
9295+
}
9296+
9297+
/// Parses a parenthesized comma-separated list of unqualified, possibly quoted identifiers
9298+
pub fn parse_parenthesized_qualified_column_list(
9299+
&mut self,
9300+
optional: IsOptional,
9301+
allow_empty: bool,
9302+
) -> Result<Vec<ObjectName>, ParserError> {
9303+
self.parse_parenthesized_column_list_inner(optional, allow_empty, |p| {
9304+
p.parse_object_name(false)
9305+
})
9306+
}
9307+
9308+
/// Parses a parenthesized comma-separated list of columns using
9309+
/// the provided function to parse each element.
9310+
fn parse_parenthesized_column_list_inner<F, T>(
9311+
&mut self,
9312+
optional: IsOptional,
9313+
allow_empty: bool,
9314+
mut f: F,
9315+
) -> Result<Vec<T>, ParserError>
9316+
where
9317+
F: FnMut(&mut Parser) -> Result<T, ParserError>,
9318+
{
92949319
if self.consume_token(&Token::LParen) {
92959320
if allow_empty && self.peek_token().token == Token::RParen {
92969321
self.next_token();
92979322
Ok(vec![])
92989323
} else {
9299-
let cols = self.parse_comma_separated(|p| p.parse_identifier())?;
9324+
let cols = self.parse_comma_separated(|p| f(p))?;
93009325
self.expect_token(&Token::RParen)?;
93019326
Ok(cols)
93029327
}
@@ -9307,7 +9332,7 @@ impl<'a> Parser<'a> {
93079332
}
93089333
}
93099334

9310-
/// Parse a parenthesized comma-separated list of table alias column definitions.
9335+
/// Parses a parenthesized comma-separated list of table alias column definitions.
93119336
fn parse_table_alias_column_defs(&mut self) -> Result<Vec<TableAliasColumnDef>, ParserError> {
93129337
if self.consume_token(&Token::LParen) {
93139338
let cols = self.parse_comma_separated(|p| {
@@ -11804,7 +11829,7 @@ impl<'a> Parser<'a> {
1180411829
let constraint = self.parse_expr()?;
1180511830
Ok(JoinConstraint::On(constraint))
1180611831
} else if self.parse_keyword(Keyword::USING) {
11807-
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
11832+
let columns = self.parse_parenthesized_qualified_column_list(Mandatory, false)?;
1180811833
Ok(JoinConstraint::Using(columns))
1180911834
} else {
1181011835
Ok(JoinConstraint::None)

tests/sqlparser_common.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6520,7 +6520,7 @@ fn parse_joins_using() {
65206520
sample: None,
65216521
},
65226522
global: false,
6523-
join_operator: f(JoinConstraint::Using(vec!["c1".into()])),
6523+
join_operator: f(JoinConstraint::Using(vec![ObjectName(vec!["c1".into()])])),
65246524
}
65256525
}
65266526
// Test parsing of aliases

tests/sqlparser_snowflake.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2650,6 +2650,9 @@ fn asof_joins() {
26502650
"ON s.state = p.state ",
26512651
"ORDER BY s.observed",
26522652
));
2653+
2654+
// Snowflake allows fully-qualified column names inside USING
2655+
snowflake().verified_stmt("SELECT * FROM tbl1 AS t1 JOIN tbl2 AS t2 USING(t2.col1)");
26532656
}
26542657

26552658
#[test]

0 commit comments

Comments
 (0)