From 0a2c232c8c32cb926334a4a3e7cf3e53cb84272d Mon Sep 17 00:00:00 2001 From: Wei-Ting Kuo Date: Tue, 2 Aug 2022 06:14:18 +0800 Subject: [PATCH 1/2] add alias for nestedjoin --- src/ast/query.rs | 16 ++++++++++++++-- src/parser.rs | 22 +++++++++++++++++----- tests/sqlparser_common.rs | 4 ++-- tests/test_utils/mod.rs | 4 ++-- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/ast/query.rs b/src/ast/query.rs index ed9d5781a..bc5af9e5f 100644 --- a/src/ast/query.rs +++ b/src/ast/query.rs @@ -375,7 +375,10 @@ pub enum TableFactor { /// /// The parser may also accept non-standard nesting of bare tables for some /// dialects, but the information about such nesting is stripped from AST. - NestedJoin(Box), + NestedJoin { + table_with_joins: Box, + alias: Option, + }, } impl fmt::Display for TableFactor { @@ -438,7 +441,16 @@ impl fmt::Display for TableFactor { } Ok(()) } - TableFactor::NestedJoin(table_reference) => write!(f, "({})", table_reference), + TableFactor::NestedJoin { + table_with_joins, + alias, + } => { + write!(f, "({})", table_with_joins)?; + if let Some(alias) = alias { + write!(f, " AS {}", alias)?; + } + Ok(()) + } } } } diff --git a/src/parser.rs b/src/parser.rs index d98fddc83..a751161c1 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3855,12 +3855,24 @@ impl<'a> Parser<'a> { #[allow(clippy::if_same_then_else)] if !table_and_joins.joins.is_empty() { self.expect_token(&Token::RParen)?; - Ok(TableFactor::NestedJoin(Box::new(table_and_joins))) // (A) - } else if let TableFactor::NestedJoin(_) = &table_and_joins.relation { + let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS)?; + Ok(TableFactor::NestedJoin { + table_with_joins: Box::new(table_and_joins), + alias, + }) // (A) + } else if let TableFactor::NestedJoin { + table_with_joins: _, + alias: _, + } = &table_and_joins.relation + { // (B): `table_and_joins` (what we found inside the parentheses) // is a nested join `(foo JOIN bar)`, not followed by other joins. self.expect_token(&Token::RParen)?; - Ok(TableFactor::NestedJoin(Box::new(table_and_joins))) + let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS)?; + Ok(TableFactor::NestedJoin { + table_with_joins: Box::new(table_and_joins), + alias, + }) } else if dialect_of!(self is SnowflakeDialect | GenericDialect) { // Dialect-specific behavior: Snowflake diverges from the // standard and from most of the other implementations by @@ -3879,7 +3891,8 @@ impl<'a> Parser<'a> { TableFactor::Derived { alias, .. } | TableFactor::Table { alias, .. } | TableFactor::UNNEST { alias, .. } - | TableFactor::TableFunction { alias, .. } => { + | TableFactor::TableFunction { alias, .. } + | TableFactor::NestedJoin { alias, .. } => { // but not `FROM (mytable AS alias1) AS alias2`. if let Some(inner_alias) = alias { return Err(ParserError::ParserError(format!( @@ -3892,7 +3905,6 @@ impl<'a> Parser<'a> { // `(mytable AS alias)` alias.replace(outer_alias); } - TableFactor::NestedJoin(_) => unreachable!(), }; } // Do not store the extra set of parens in the AST diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 18641a947..e954db1e9 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -3676,7 +3676,7 @@ fn parse_derived_tables() { let from = only(select.from); assert_eq!( from.relation, - TableFactor::NestedJoin(Box::new(TableWithJoins { + TableFactor::NestedJoin {table_with_joins: Box::new(TableWithJoins { relation: TableFactor::Derived { lateral: false, subquery: Box::new(verified_query("(SELECT 1) UNION (SELECT 2)")), @@ -3694,7 +3694,7 @@ fn parse_derived_tables() { }, join_operator: JoinOperator::Inner(JoinConstraint::Natural), }], - })) + }), alias: None} ); } diff --git a/tests/test_utils/mod.rs b/tests/test_utils/mod.rs index f224314b9..d3a56ce46 100644 --- a/tests/test_utils/mod.rs +++ b/tests/test_utils/mod.rs @@ -26,9 +26,9 @@ pub use sqlparser::test_utils::*; #[macro_export] macro_rules! nest { ($base:expr $(, $join:expr)*) => { - TableFactor::NestedJoin(Box::new(TableWithJoins { + TableFactor::NestedJoin { table_with_joins: Box::new(TableWithJoins { relation: $base, joins: vec![$(join($join)),*] - })) + }), alias: None} }; } From 65755136543b5fb6013ebae0ab500961b3b42817 Mon Sep 17 00:00:00 2001 From: Wei-Ting Kuo Date: Tue, 2 Aug 2022 06:16:00 +0800 Subject: [PATCH 2/2] fmt --- tests/sqlparser_common.rs | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index e954db1e9..de864b2d0 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -3676,25 +3676,28 @@ fn parse_derived_tables() { let from = only(select.from); assert_eq!( from.relation, - TableFactor::NestedJoin {table_with_joins: Box::new(TableWithJoins { - relation: TableFactor::Derived { - lateral: false, - subquery: Box::new(verified_query("(SELECT 1) UNION (SELECT 2)")), - alias: Some(TableAlias { - name: "t1".into(), - columns: vec![], - }) - }, - joins: vec![Join { - relation: TableFactor::Table { - name: ObjectName(vec!["t2".into()]), - alias: None, - args: None, - with_hints: vec![], + TableFactor::NestedJoin { + table_with_joins: Box::new(TableWithJoins { + relation: TableFactor::Derived { + lateral: false, + subquery: Box::new(verified_query("(SELECT 1) UNION (SELECT 2)")), + alias: Some(TableAlias { + name: "t1".into(), + columns: vec![], + }) }, - join_operator: JoinOperator::Inner(JoinConstraint::Natural), - }], - }), alias: None} + joins: vec![Join { + relation: TableFactor::Table { + name: ObjectName(vec!["t2".into()]), + alias: None, + args: None, + with_hints: vec![], + }, + join_operator: JoinOperator::Inner(JoinConstraint::Natural), + }], + }), + alias: None + } ); }