Require that nested joins always have one join

The SQL specification prohibits constructions like

    SELECT * FROM a NATURAL JOIN (b)

where b sits alone inside parentheses. Parentheses in a FROM entry
always introduce either a derived table or a join.
This commit is contained in:
Nikhil Benesch 2019-06-09 15:08:17 -04:00
parent 8bee74277a
commit 4ee461bae4
No known key found for this signature in database
GPG key ID: FCF98542083C5A69
3 changed files with 27 additions and 1 deletions

View file

@ -238,6 +238,10 @@ pub enum TableFactor {
subquery: Box<SQLQuery>,
alias: Option<TableAlias>,
},
/// Represents a parenthesized join expression, such as
/// `(foo <JOIN> bar [ <JOIN> baz ... ])`.
/// The inner `TableWithJoins` can have no joins only if its
/// `relation` is itself a `TableFactor::NestedJoin`.
NestedJoin(Box<TableWithJoins>),
}

View file

@ -1719,6 +1719,16 @@ impl Parser {
// we won't, and we'll return that error instead.
self.index = index;
let table_and_joins = self.parse_table_and_joins()?;
match table_and_joins.relation {
TableFactor::NestedJoin { .. } => (),
_ => {
if table_and_joins.joins.is_empty() {
// The SQL spec prohibits derived tables and bare
// tables from appearing alone in parentheses.
self.expected("joined table", self.peek_token())?
}
}
}
self.expect_token(&Token::RParen)?;
Ok(TableFactor::NestedJoin(Box::new(table_and_joins)))
}

View file

@ -1742,6 +1742,12 @@ fn parse_join_nesting() {
from.joins,
vec![join(nest!(nest!(nest!(table("b"), table("c")))))]
);
let res = parse_sql_statements("SELECT * FROM (a NATURAL JOIN (b))");
assert_eq!(
ParserError::ParserError("Expected joined table, found: )".to_string()),
res.unwrap_err()
);
}
#[test]
@ -1873,7 +1879,13 @@ fn parse_derived_tables() {
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
}],
}))
)
);
let res = parse_sql_statements("SELECT * FROM ((SELECT 1) AS t)");
assert_eq!(
ParserError::ParserError("Expected joined table, found: )".to_string()),
res.unwrap_err()
);
}
#[test]