Skip to content

Commit 1ad467f

Browse files
committed
support the single table in parnes with alias in snowflake by dialect
1 parent f500a42 commit 1ad467f

File tree

4 files changed

+248
-74
lines changed

4 files changed

+248
-74
lines changed

src/parser.rs

+52-8
Original file line numberDiff line numberDiff line change
@@ -2116,14 +2116,58 @@ impl<'a> Parser<'a> {
21162116
// recently consumed does not start a derived table (cases 1, 2, or 4).
21172117
// `maybe_parse` will ignore such an error and rewind to be after the opening '('.
21182118

2119-
// Inside the parentheses we expect to find a table factor
2120-
// followed by some joins or another level of nesting.
2121-
let table_and_joins = self.parse_table_and_joins()?;
2122-
self.expect_token(&Token::RParen)?;
2123-
// The SQL spec prohibits derived and bare tables from appearing
2124-
// alone in parentheses. We don't enforce this as some databases
2125-
// (e.g. Snowflake) allow such syntax.
2126-
Ok(TableFactor::NestedJoin(Box::new(table_and_joins)))
2119+
// Inside the parentheses we expect to find an (A) table factor
2120+
// followed by some joins or (B) another level of nesting.
2121+
let mut table_and_joins = self.parse_table_and_joins()?;
2122+
2123+
if !table_and_joins.joins.is_empty() {
2124+
self.expect_token(&Token::RParen)?;
2125+
Ok(TableFactor::NestedJoin(Box::new(table_and_joins))) // (A)
2126+
} else if let TableFactor::NestedJoin(_) = &table_and_joins.relation {
2127+
// (B): `table_and_joins` (what we found inside the parentheses)
2128+
// is a nested join `(foo JOIN bar)`, not followed by other joins.
2129+
self.expect_token(&Token::RParen)?;
2130+
Ok(TableFactor::NestedJoin(Box::new(table_and_joins)))
2131+
} else if dialect_of!(self is SnowflakeDialect) {
2132+
// Dialect-specific behavior: Snowflake diverges from the
2133+
// standard and most of other implementations by allowing
2134+
// extra parentheses not only around a join (B), but around
2135+
// lone table names (e.g. `FROM (mytable [AS alias])`) and
2136+
// around derived tables (e.g. `FROM ((SELECT ...) [AS alias])`
2137+
// as well.
2138+
self.expect_token(&Token::RParen)?;
2139+
2140+
if let Some(outer_alias) =
2141+
self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS)?
2142+
{
2143+
// Snowflake also allows specifying an alias *after* parens
2144+
// e.g. `FROM (mytable) AS alias`
2145+
match &mut table_and_joins.relation {
2146+
TableFactor::Derived { alias, .. }
2147+
| TableFactor::Table { alias, .. }
2148+
| TableFactor::TableFunction { alias, .. } => {
2149+
// but not `FROM (mytable AS alias1) AS alias2`.
2150+
if let Some(inner_alias) = alias {
2151+
return Err(ParserError::ParserError(format!(
2152+
"duplicate alias {}",
2153+
inner_alias
2154+
)));
2155+
}
2156+
// Act as if the alias was specified normally next
2157+
// to the table name: `(mytable) AS alias` ->
2158+
// `(mytable AS alias)`
2159+
alias.replace(outer_alias);
2160+
}
2161+
TableFactor::NestedJoin(_) => unreachable!(),
2162+
};
2163+
}
2164+
// Do not store the extra set of parens in the AST
2165+
Ok(table_and_joins.relation)
2166+
} else {
2167+
// The SQL spec prohibits derived tables and bare tables from
2168+
// appearing alone in parentheses (e.g. `FROM (mytable)`)
2169+
self.expected("joined table", self.peek_token())
2170+
}
21272171
} else {
21282172
let name = self.parse_object_name()?;
21292173
// Postgres, MSSQL: table-valued functions:

tests/sqlparser_common.rs

+27-66
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@
1717
//! that 1) it's either standard or widely supported and 2) it can be parsed by
1818
//! sqlparser regardless of the chosen dialect (i.e. it doesn't conflict with
1919
//! dialect-specific parsing rules).
20+
//!
21+
//!
22+
23+
#[macro_use]
24+
#[path = "utils/mod.rs"]
25+
mod utils;
26+
27+
use utils::*;
2028

2129
use matches::assert_matches;
2230

@@ -2282,75 +2290,48 @@ fn parse_complex_join() {
22822290

22832291
#[test]
22842292
fn parse_join_nesting() {
2285-
fn table(name: impl Into<String>) -> TableFactor {
2286-
TableFactor::Table {
2287-
name: ObjectName(vec![Ident::new(name.into())]),
2288-
alias: None,
2289-
args: vec![],
2290-
with_hints: vec![],
2291-
}
2292-
}
2293-
2294-
fn join(relation: TableFactor) -> Join {
2295-
Join {
2296-
relation,
2297-
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
2298-
}
2299-
}
2300-
2301-
macro_rules! nest {
2302-
($base:expr $(, $join:expr)*) => {
2303-
TableFactor::NestedJoin(Box::new(TableWithJoins {
2304-
relation: $base,
2305-
joins: vec![$(join($join)),*]
2306-
}))
2307-
};
2308-
}
2309-
23102293
let sql = "SELECT * FROM a NATURAL JOIN (b NATURAL JOIN (c NATURAL JOIN d NATURAL JOIN e)) \
23112294
NATURAL JOIN (f NATURAL JOIN (g NATURAL JOIN h))";
23122295
assert_eq!(
23132296
only(&verified_only_select(sql).from).joins,
23142297
vec![
2315-
join(nest!(table("b"), nest!(table("c"), table("d"), table("e")))),
2316-
join(nest!(table("f"), nest!(table("g"), table("h"))))
2298+
join(nest!(
2299+
table("b", None),
2300+
nest!(table("c", None), table("d", None), table("e", None))
2301+
)),
2302+
join(nest!(
2303+
table("f", None),
2304+
nest!(table("g", None), table("h", None))
2305+
))
23172306
],
23182307
);
23192308

23202309
let sql = "SELECT * FROM (a NATURAL JOIN b) NATURAL JOIN c";
23212310
let select = verified_only_select(sql);
23222311
let from = only(select.from);
2323-
assert_eq!(from.relation, nest!(table("a"), table("b")));
2324-
assert_eq!(from.joins, vec![join(table("c"))]);
2312+
assert_eq!(from.relation, nest!(table("a", None), table("b", None)));
2313+
assert_eq!(from.joins, vec![join(table("c", None))]);
23252314

23262315
let sql = "SELECT * FROM (((a NATURAL JOIN b)))";
23272316
let select = verified_only_select(sql);
23282317
let from = only(select.from);
2329-
assert_eq!(from.relation, nest!(nest!(nest!(table("a"), table("b")))));
2318+
assert_eq!(
2319+
from.relation,
2320+
nest!(nest!(nest!(table("a", None), table("b", None))))
2321+
);
23302322
assert_eq!(from.joins, vec![]);
23312323

23322324
let sql = "SELECT * FROM a NATURAL JOIN (((b NATURAL JOIN c)))";
23332325
let select = verified_only_select(sql);
23342326
let from = only(select.from);
2335-
assert_eq!(from.relation, table("a"));
2327+
assert_eq!(from.relation, table("a", None));
23362328
assert_eq!(
23372329
from.joins,
2338-
vec![join(nest!(nest!(nest!(table("b"), table("c")))))]
2330+
vec![join(nest!(nest!(nest!(
2331+
table("b", None),
2332+
table("c", None)
2333+
))))]
23392334
);
2340-
2341-
// Parenthesized table names are non-standard, but supported in Snowflake SQL
2342-
let sql = "SELECT * FROM (a NATURAL JOIN (b))";
2343-
let select = verified_only_select(sql);
2344-
let from = only(select.from);
2345-
2346-
assert_eq!(from.relation, nest!(table("a"), nest!(table("b"))));
2347-
2348-
// Double parentheses around table names are non-standard, but supported in Snowflake SQL
2349-
let sql = "SELECT * FROM (a NATURAL JOIN ((b)))";
2350-
let select = verified_only_select(sql);
2351-
let from = only(select.from);
2352-
2353-
assert_eq!(from.relation, nest!(table("a"), nest!(nest!(table("b")))));
23542335
}
23552336

23562337
#[test]
@@ -2492,26 +2473,6 @@ fn parse_derived_tables() {
24922473
}],
24932474
}))
24942475
);
2495-
2496-
// Nesting a subquery in parentheses is non-standard, but supported in Snowflake SQL
2497-
let sql = "SELECT * FROM ((SELECT 1) AS t)";
2498-
let select = verified_only_select(sql);
2499-
let from = only(select.from);
2500-
2501-
assert_eq!(
2502-
from.relation,
2503-
TableFactor::NestedJoin(Box::new(TableWithJoins {
2504-
relation: TableFactor::Derived {
2505-
lateral: false,
2506-
subquery: Box::new(verified_query("SELECT 1")),
2507-
alias: Some(TableAlias {
2508-
name: "t".into(),
2509-
columns: vec![],
2510-
})
2511-
},
2512-
joins: Vec::new(),
2513-
}))
2514-
);
25152476
}
25162477

25172478
#[test]

tests/sqlparser_snowflake.rs

+131
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,26 @@
99
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1010
// See the License for the specific language governing permissions and
1111
// limitations under the License.
12+
13+
#[macro_use]
14+
#[path = "utils/mod.rs"]
15+
mod utils;
16+
1217
use sqlparser::ast::*;
1318
use sqlparser::dialect::{GenericDialect, SnowflakeDialect};
19+
use sqlparser::parser::ParserError;
1420
use sqlparser::test_utils::*;
21+
use utils::*;
22+
23+
fn table_alias(alias: &str) -> TableAlias {
24+
TableAlias {
25+
name: Ident {
26+
value: alias.to_owned(),
27+
quote_style: None,
28+
},
29+
columns: Vec::new(),
30+
}
31+
}
1532

1633
#[test]
1734
fn test_snowflake_create_table() {
@@ -24,6 +41,120 @@ fn test_snowflake_create_table() {
2441
}
2542
}
2643

44+
fn get_from_section_from_select_query(query: &str) -> Vec<TableWithJoins> {
45+
let statement = snowflake().parse_sql_statements(query).unwrap()[0].clone();
46+
47+
let query = match statement {
48+
Statement::Query(query) => query,
49+
_ => panic!("Not a query"),
50+
};
51+
52+
let select = match query.body {
53+
SetExpr::Select(select) => select,
54+
_ => panic!("not a select query"),
55+
};
56+
57+
select.from.clone()
58+
}
59+
60+
#[test]
61+
fn test_sf_derives_single_table_in_parenthesis() {
62+
let from = get_from_section_from_select_query("SELECT * FROM (((SELECT 1) AS t))");
63+
64+
assert_eq!(
65+
from[0].relation,
66+
TableFactor::Derived {
67+
lateral: false,
68+
subquery: Box::new(snowflake().verified_query("SELECT 1")),
69+
alias: Some(TableAlias {
70+
name: "t".into(),
71+
columns: vec![],
72+
})
73+
}
74+
);
75+
}
76+
77+
#[test]
78+
fn test_single_table_in_parenthesis() {
79+
//Parenthesized table names are non-standard, but supported in Snowflake SQL
80+
let from = get_from_section_from_select_query("SELECT * FROM (a NATURAL JOIN (b))");
81+
82+
assert_eq!(from[0].relation, nest!(table("a", None), table("b", None)));
83+
84+
let from = get_from_section_from_select_query("SELECT * FROM (a NATURAL JOIN ((b)))");
85+
assert_eq!(from[0].relation, nest!(table("a", None), table("b", None)));
86+
}
87+
88+
#[test]
89+
fn test_single_table_in_parenthesis_with_alias() {
90+
let sql = "SELECT * FROM (a NATURAL JOIN (b) c )";
91+
let table_with_joins = get_from_section_from_select_query(sql)[0].clone();
92+
assert_eq!(
93+
table_with_joins.relation,
94+
nest!(table("a", None), table("b", Some(table_alias("c"))))
95+
);
96+
97+
let sql = "SELECT * FROM (a NATURAL JOIN ((b)) c )";
98+
let table_with_joins = get_from_section_from_select_query(sql)[0].clone();
99+
assert_eq!(
100+
table_with_joins.relation,
101+
nest!(table("a", None), table("b", Some(table_alias("c"))))
102+
);
103+
104+
let sql = "SELECT * FROM (a NATURAL JOIN ( (b) c ) )";
105+
let table_with_joins = get_from_section_from_select_query(sql)[0].clone();
106+
assert_eq!(
107+
table_with_joins.relation,
108+
nest!(table("a", None), table("b", Some(table_alias("c"))))
109+
);
110+
111+
let sql = "SELECT * FROM (a NATURAL JOIN ( (b) as c ) )";
112+
let table_with_joins = get_from_section_from_select_query(sql)[0].clone();
113+
assert_eq!(
114+
table_with_joins.relation,
115+
nest!(table("a", None), table("b", Some(table_alias("c"))))
116+
);
117+
118+
let sql = "SELECT * FROM (a alias1 NATURAL JOIN ( (b) c ) )";
119+
let table_with_joins = get_from_section_from_select_query(sql)[0].clone();
120+
assert_eq!(
121+
table_with_joins.relation,
122+
nest!(
123+
table("a", Some(table_alias("alias1"))),
124+
table("b", Some(table_alias("c")))
125+
)
126+
);
127+
128+
let sql = "SELECT * FROM (a as alias1 NATURAL JOIN ( (b) as c ) )";
129+
let table_with_joins = get_from_section_from_select_query(sql)[0].clone();
130+
assert_eq!(
131+
table_with_joins.relation,
132+
nest!(
133+
table("a", Some(table_alias("alias1"))),
134+
table("b", Some(table_alias("c")))
135+
)
136+
);
137+
138+
let res = snowflake().parse_sql_statements("SELECT * FROM (a NATURAL JOIN b) c");
139+
assert_eq!(
140+
ParserError::ParserError("Expected end of statement, found: c".to_string()),
141+
res.unwrap_err()
142+
);
143+
144+
let res = snowflake().parse_sql_statements("SELECT * FROM (a b) c");
145+
assert_eq!(
146+
ParserError::ParserError("duplicate alias b".to_string()),
147+
res.unwrap_err()
148+
);
149+
}
150+
151+
fn snowflake() -> TestedDialects {
152+
TestedDialects {
153+
// we don't have a separate SQLite dialect, so test only the generic dialect for now
154+
dialects: vec![Box::new(SnowflakeDialect {})],
155+
}
156+
}
157+
27158
fn snowflake_and_generic() -> TestedDialects {
28159
TestedDialects {
29160
dialects: vec![Box::new(SnowflakeDialect {}), Box::new(GenericDialect {})],

tests/utils/mod.rs

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Licensed under the Apache License, Version 2.0 (the "License");
2+
// you may not use this file except in compliance with the License.
3+
// You may obtain a copy of the License at
4+
//
5+
// http://www.apache.org/licenses/LICENSE-2.0
6+
//
7+
// Unless required by applicable law or agreed to in writing, software
8+
// distributed under the License is distributed on an "AS IS" BASIS,
9+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
// See the License for the specific language governing permissions and
11+
// limitations under the License.
12+
13+
use sqlparser::ast::*;
14+
15+
pub fn table(name: impl Into<String>, alias: Option<TableAlias>) -> TableFactor {
16+
TableFactor::Table {
17+
name: ObjectName(vec![Ident::new(name.into())]),
18+
alias,
19+
args: vec![],
20+
with_hints: vec![],
21+
}
22+
}
23+
24+
pub fn join(relation: TableFactor) -> Join {
25+
Join {
26+
relation,
27+
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
28+
}
29+
}
30+
31+
macro_rules! nest {
32+
($base:expr $(, $join:expr)*) => {
33+
TableFactor::NestedJoin(Box::new(TableWithJoins {
34+
relation: $base,
35+
joins: vec![$(join($join)),*]
36+
}))
37+
};
38+
}

0 commit comments

Comments
 (0)