Skip to content

Commit 3a78e14

Browse files
yoavcloudayman-sigma
authored andcommitted
Add support for qualified column names in JOIN ... USING (apache#1663)
1 parent 9d3904a commit 3a78e14

File tree

4 files changed

+35
-7
lines changed

4 files changed

+35
-7
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
@@ -2013,7 +2013,7 @@ impl Spanned for JoinConstraint {
20132013
fn span(&self) -> Span {
20142014
match self {
20152015
JoinConstraint::On(expr) => expr.span(),
2016-
JoinConstraint::Using(vec) => union_spans(vec.iter().map(|i| i.span)),
2016+
JoinConstraint::Using(vec) => union_spans(vec.iter().map(|i| i.span())),
20172017
JoinConstraint::Natural => Span::empty(),
20182018
JoinConstraint::None => Span::empty(),
20192019
}

src/parser/mod.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9346,18 +9346,45 @@ impl<'a> Parser<'a> {
93469346
})
93479347
}
93489348

9349-
/// Parse a parenthesized comma-separated list of unqualified, possibly quoted identifiers
9349+
/// Parses a parenthesized comma-separated list of unqualified, possibly quoted identifiers.
9350+
/// For example: `(col1, "col 2", ...)`
93509351
pub fn parse_parenthesized_column_list(
93519352
&mut self,
93529353
optional: IsOptional,
93539354
allow_empty: bool,
93549355
) -> Result<Vec<Ident>, ParserError> {
9356+
self.parse_parenthesized_column_list_inner(optional, allow_empty, |p| p.parse_identifier())
9357+
}
9358+
9359+
/// Parses a parenthesized comma-separated list of qualified, possibly quoted identifiers.
9360+
/// For example: `(db1.sc1.tbl1.col1, db1.sc1.tbl1."col 2", ...)`
9361+
pub fn parse_parenthesized_qualified_column_list(
9362+
&mut self,
9363+
optional: IsOptional,
9364+
allow_empty: bool,
9365+
) -> Result<Vec<ObjectName>, ParserError> {
9366+
self.parse_parenthesized_column_list_inner(optional, allow_empty, |p| {
9367+
p.parse_object_name(true)
9368+
})
9369+
}
9370+
9371+
/// Parses a parenthesized comma-separated list of columns using
9372+
/// the provided function to parse each element.
9373+
fn parse_parenthesized_column_list_inner<F, T>(
9374+
&mut self,
9375+
optional: IsOptional,
9376+
allow_empty: bool,
9377+
mut f: F,
9378+
) -> Result<Vec<T>, ParserError>
9379+
where
9380+
F: FnMut(&mut Parser) -> Result<T, ParserError>,
9381+
{
93559382
if self.consume_token(&Token::LParen) {
93569383
if allow_empty && self.peek_token().token == Token::RParen {
93579384
self.next_token();
93589385
Ok(vec![])
93599386
} else {
9360-
let cols = self.parse_comma_separated(|p| p.parse_identifier())?;
9387+
let cols = self.parse_comma_separated(|p| f(p))?;
93619388
self.expect_token(&Token::RParen)?;
93629389
Ok(cols)
93639390
}
@@ -9368,7 +9395,7 @@ impl<'a> Parser<'a> {
93689395
}
93699396
}
93709397

9371-
/// Parse a parenthesized comma-separated list of table alias column definitions.
9398+
/// Parses a parenthesized comma-separated list of table alias column definitions.
93729399
fn parse_table_alias_column_defs(&mut self) -> Result<Vec<TableAliasColumnDef>, ParserError> {
93739400
if self.consume_token(&Token::LParen) {
93749401
let cols = self.parse_comma_separated(|p| {
@@ -11863,7 +11890,7 @@ impl<'a> Parser<'a> {
1186311890
let constraint = self.parse_expr()?;
1186411891
Ok(JoinConstraint::On(constraint))
1186511892
} else if self.parse_keyword(Keyword::USING) {
11866-
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
11893+
let columns = self.parse_parenthesized_qualified_column_list(Mandatory, false)?;
1186711894
Ok(JoinConstraint::Using(columns))
1186811895
} else {
1186911896
Ok(JoinConstraint::None)

tests/sqlparser_common.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6542,7 +6542,7 @@ fn parse_joins_using() {
65426542
sample: None,
65436543
},
65446544
global: false,
6545-
join_operator: f(JoinConstraint::Using(vec!["c1".into()])),
6545+
join_operator: f(JoinConstraint::Using(vec![ObjectName(vec!["c1".into()])])),
65466546
}
65476547
}
65486548
// Test parsing of aliases
@@ -6599,6 +6599,7 @@ fn parse_joins_using() {
65996599
only(&verified_only_select("SELECT * FROM t1 FULL JOIN t2 USING(c1)").from).joins,
66006600
vec![join_with_constraint("t2", None, JoinOperator::FullOuter)]
66016601
);
6602+
verified_stmt("SELECT * FROM tbl1 AS t1 JOIN tbl2 AS t2 USING(t2.col1)");
66026603
}
66036604

66046605
#[test]

0 commit comments

Comments
 (0)