This is an automated email from the ASF dual-hosted git repository.
iffyio pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 44df6d6f Add support for qualified column names in JOIN ... USING
(#1663)
44df6d6f is described below
commit 44df6d6f92e8bba1cbc6d4b57c99f8f126b786fd
Author: Yoav Cohen <[email protected]>
AuthorDate: Sun Jan 19 11:43:45 2025 +0100
Add support for qualified column names in JOIN ... USING (#1663)
---
src/ast/query.rs | 2 +-
src/ast/spans.rs | 2 +-
src/parser/mod.rs | 35 +++++++++++++++++++++++++++++++----
tests/sqlparser_common.rs | 3 ++-
4 files changed, 35 insertions(+), 7 deletions(-)
diff --git a/src/ast/query.rs b/src/ast/query.rs
index 9bcdc2e7..66c70b46 100644
--- a/src/ast/query.rs
+++ b/src/ast/query.rs
@@ -2050,7 +2050,7 @@ pub enum JoinOperator {
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum JoinConstraint {
On(Expr),
- Using(Vec<Ident>),
+ Using(Vec<ObjectName>),
Natural,
None,
}
diff --git a/src/ast/spans.rs b/src/ast/spans.rs
index 2a5a75b4..1ddd47d7 100644
--- a/src/ast/spans.rs
+++ b/src/ast/spans.rs
@@ -2008,7 +2008,7 @@ impl Spanned for JoinConstraint {
fn span(&self) -> Span {
match self {
JoinConstraint::On(expr) => expr.span(),
- JoinConstraint::Using(vec) => union_spans(vec.iter().map(|i|
i.span)),
+ JoinConstraint::Using(vec) => union_spans(vec.iter().map(|i|
i.span())),
JoinConstraint::Natural => Span::empty(),
JoinConstraint::None => Span::empty(),
}
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 5cacfda9..a3adb023 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -9336,18 +9336,45 @@ impl<'a> Parser<'a> {
})
}
- /// Parse a parenthesized comma-separated list of unqualified, possibly
quoted identifiers
+ /// Parses a parenthesized comma-separated list of unqualified, possibly
quoted identifiers.
+ /// For example: `(col1, "col 2", ...)`
pub fn parse_parenthesized_column_list(
&mut self,
optional: IsOptional,
allow_empty: bool,
) -> Result<Vec<Ident>, ParserError> {
+ self.parse_parenthesized_column_list_inner(optional, allow_empty, |p|
p.parse_identifier())
+ }
+
+ /// Parses a parenthesized comma-separated list of qualified, possibly
quoted identifiers.
+ /// For example: `(db1.sc1.tbl1.col1, db1.sc1.tbl1."col 2", ...)`
+ pub fn parse_parenthesized_qualified_column_list(
+ &mut self,
+ optional: IsOptional,
+ allow_empty: bool,
+ ) -> Result<Vec<ObjectName>, ParserError> {
+ self.parse_parenthesized_column_list_inner(optional, allow_empty, |p| {
+ p.parse_object_name(true)
+ })
+ }
+
+ /// Parses a parenthesized comma-separated list of columns using
+ /// the provided function to parse each element.
+ fn parse_parenthesized_column_list_inner<F, T>(
+ &mut self,
+ optional: IsOptional,
+ allow_empty: bool,
+ mut f: F,
+ ) -> Result<Vec<T>, ParserError>
+ where
+ F: FnMut(&mut Parser) -> Result<T, ParserError>,
+ {
if self.consume_token(&Token::LParen) {
if allow_empty && self.peek_token().token == Token::RParen {
self.next_token();
Ok(vec![])
} else {
- let cols = self.parse_comma_separated(|p|
p.parse_identifier())?;
+ let cols = self.parse_comma_separated(|p| f(p))?;
self.expect_token(&Token::RParen)?;
Ok(cols)
}
@@ -9358,7 +9385,7 @@ impl<'a> Parser<'a> {
}
}
- /// Parse a parenthesized comma-separated list of table alias column
definitions.
+ /// Parses a parenthesized comma-separated list of table alias column
definitions.
fn parse_table_alias_column_defs(&mut self) ->
Result<Vec<TableAliasColumnDef>, ParserError> {
if self.consume_token(&Token::LParen) {
let cols = self.parse_comma_separated(|p| {
@@ -11853,7 +11880,7 @@ impl<'a> Parser<'a> {
let constraint = self.parse_expr()?;
Ok(JoinConstraint::On(constraint))
} else if self.parse_keyword(Keyword::USING) {
- let columns = self.parse_parenthesized_column_list(Mandatory,
false)?;
+ let columns =
self.parse_parenthesized_qualified_column_list(Mandatory, false)?;
Ok(JoinConstraint::Using(columns))
} else {
Ok(JoinConstraint::None)
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index 49588a58..7271d637 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -6541,7 +6541,7 @@ fn parse_joins_using() {
sample: None,
},
global: false,
- join_operator: f(JoinConstraint::Using(vec!["c1".into()])),
+ join_operator:
f(JoinConstraint::Using(vec![ObjectName(vec!["c1".into()])])),
}
}
// Test parsing of aliases
@@ -6598,6 +6598,7 @@ fn parse_joins_using() {
only(&verified_only_select("SELECT * FROM t1 FULL JOIN t2
USING(c1)").from).joins,
vec![join_with_constraint("t2", None, JoinOperator::FullOuter)]
);
+ verified_stmt("SELECT * FROM tbl1 AS t1 JOIN tbl2 AS t2 USING(t2.col1)");
}
#[test]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]