Differentiate LEFT JOIN from LEFT OUTER JOIN (#1726)

This commit is contained in:
Michael Victor Zink 2025-02-14 08:23:00 -08:00 committed by GitHub
parent 1c0e5d3554
commit 68c41a9d5a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 65 additions and 23 deletions

View file

@ -2077,20 +2077,34 @@ impl fmt::Display for Join {
self.relation, self.relation,
suffix(constraint) suffix(constraint)
), ),
JoinOperator::LeftOuter(constraint) => write!( JoinOperator::Left(constraint) => write!(
f, f,
" {}LEFT JOIN {}{}", " {}LEFT JOIN {}{}",
prefix(constraint), prefix(constraint),
self.relation, self.relation,
suffix(constraint) suffix(constraint)
), ),
JoinOperator::RightOuter(constraint) => write!( JoinOperator::LeftOuter(constraint) => write!(
f,
" {}LEFT OUTER JOIN {}{}",
prefix(constraint),
self.relation,
suffix(constraint)
),
JoinOperator::Right(constraint) => write!(
f, f,
" {}RIGHT JOIN {}{}", " {}RIGHT JOIN {}{}",
prefix(constraint), prefix(constraint),
self.relation, self.relation,
suffix(constraint) suffix(constraint)
), ),
JoinOperator::RightOuter(constraint) => write!(
f,
" {}RIGHT OUTER JOIN {}{}",
prefix(constraint),
self.relation,
suffix(constraint)
),
JoinOperator::FullOuter(constraint) => write!( JoinOperator::FullOuter(constraint) => write!(
f, f,
" {}FULL JOIN {}{}", " {}FULL JOIN {}{}",
@ -2162,7 +2176,9 @@ impl fmt::Display for Join {
pub enum JoinOperator { pub enum JoinOperator {
Join(JoinConstraint), Join(JoinConstraint),
Inner(JoinConstraint), Inner(JoinConstraint),
Left(JoinConstraint),
LeftOuter(JoinConstraint), LeftOuter(JoinConstraint),
Right(JoinConstraint),
RightOuter(JoinConstraint), RightOuter(JoinConstraint),
FullOuter(JoinConstraint), FullOuter(JoinConstraint),
CrossJoin, CrossJoin,

View file

@ -2010,7 +2010,9 @@ impl Spanned for JoinOperator {
match self { match self {
JoinOperator::Join(join_constraint) => join_constraint.span(), JoinOperator::Join(join_constraint) => join_constraint.span(),
JoinOperator::Inner(join_constraint) => join_constraint.span(), JoinOperator::Inner(join_constraint) => join_constraint.span(),
JoinOperator::Left(join_constraint) => join_constraint.span(),
JoinOperator::LeftOuter(join_constraint) => join_constraint.span(), JoinOperator::LeftOuter(join_constraint) => join_constraint.span(),
JoinOperator::Right(join_constraint) => join_constraint.span(),
JoinOperator::RightOuter(join_constraint) => join_constraint.span(), JoinOperator::RightOuter(join_constraint) => join_constraint.span(),
JoinOperator::FullOuter(join_constraint) => join_constraint.span(), JoinOperator::FullOuter(join_constraint) => join_constraint.span(),
JoinOperator::CrossJoin => Span::empty(), JoinOperator::CrossJoin => Span::empty(),

View file

@ -5740,7 +5740,7 @@ impl<'a> Parser<'a> {
drop_behavior, drop_behavior,
}) })
} }
/// ```sql /// ```sql
/// DROP CONNECTOR [IF EXISTS] name /// DROP CONNECTOR [IF EXISTS] name
/// ``` /// ```
/// ///
@ -11190,9 +11190,9 @@ impl<'a> Parser<'a> {
} }
Some(Keyword::JOIN) => { Some(Keyword::JOIN) => {
if is_left { if is_left {
JoinOperator::LeftOuter JoinOperator::Left
} else { } else {
JoinOperator::RightOuter JoinOperator::Right
} }
} }
_ => { _ => {

View file

@ -6661,8 +6661,16 @@ fn parse_joins_on() {
only(&verified_only_select("SELECT * FROM t1 JOIN t2 ON c1 = c2").from).joins, only(&verified_only_select("SELECT * FROM t1 JOIN t2 ON c1 = c2").from).joins,
vec![join_with_constraint("t2", None, false, JoinOperator::Join)] vec![join_with_constraint("t2", None, false, JoinOperator::Join)]
); );
assert_eq!(
only(&verified_only_select("SELECT * FROM t1 INNER JOIN t2 ON c1 = c2").from).joins,
vec![join_with_constraint("t2", None, false, JoinOperator::Inner)]
);
assert_eq!( assert_eq!(
only(&verified_only_select("SELECT * FROM t1 LEFT JOIN t2 ON c1 = c2").from).joins, only(&verified_only_select("SELECT * FROM t1 LEFT JOIN t2 ON c1 = c2").from).joins,
vec![join_with_constraint("t2", None, false, JoinOperator::Left)]
);
assert_eq!(
only(&verified_only_select("SELECT * FROM t1 LEFT OUTER JOIN t2 ON c1 = c2").from).joins,
vec![join_with_constraint( vec![join_with_constraint(
"t2", "t2",
None, None,
@ -6672,6 +6680,10 @@ fn parse_joins_on() {
); );
assert_eq!( assert_eq!(
only(&verified_only_select("SELECT * FROM t1 RIGHT JOIN t2 ON c1 = c2").from).joins, only(&verified_only_select("SELECT * FROM t1 RIGHT JOIN t2 ON c1 = c2").from).joins,
vec![join_with_constraint("t2", None, false, JoinOperator::Right)]
);
assert_eq!(
only(&verified_only_select("SELECT * FROM t1 RIGHT OUTER JOIN t2 ON c1 = c2").from).joins,
vec![join_with_constraint( vec![join_with_constraint(
"t2", "t2",
None, None,
@ -6794,10 +6806,18 @@ fn parse_joins_using() {
); );
assert_eq!( assert_eq!(
only(&verified_only_select("SELECT * FROM t1 LEFT JOIN t2 USING(c1)").from).joins, only(&verified_only_select("SELECT * FROM t1 LEFT JOIN t2 USING(c1)").from).joins,
vec![join_with_constraint("t2", None, JoinOperator::Left)]
);
assert_eq!(
only(&verified_only_select("SELECT * FROM t1 LEFT OUTER JOIN t2 USING(c1)").from).joins,
vec![join_with_constraint("t2", None, JoinOperator::LeftOuter)] vec![join_with_constraint("t2", None, JoinOperator::LeftOuter)]
); );
assert_eq!( assert_eq!(
only(&verified_only_select("SELECT * FROM t1 RIGHT JOIN t2 USING(c1)").from).joins, only(&verified_only_select("SELECT * FROM t1 RIGHT JOIN t2 USING(c1)").from).joins,
vec![join_with_constraint("t2", None, JoinOperator::Right)]
);
assert_eq!(
only(&verified_only_select("SELECT * FROM t1 RIGHT OUTER JOIN t2 USING(c1)").from).joins,
vec![join_with_constraint("t2", None, JoinOperator::RightOuter)] vec![join_with_constraint("t2", None, JoinOperator::RightOuter)]
); );
assert_eq!( assert_eq!(
@ -6857,20 +6877,34 @@ fn parse_natural_join() {
only(&verified_only_select("SELECT * FROM t1 NATURAL JOIN t2").from).joins, only(&verified_only_select("SELECT * FROM t1 NATURAL JOIN t2").from).joins,
vec![natural_join(JoinOperator::Join, None)] vec![natural_join(JoinOperator::Join, None)]
); );
// inner join explicitly // inner join explicitly
assert_eq!( assert_eq!(
only(&verified_only_select("SELECT * FROM t1 NATURAL INNER JOIN t2").from).joins, only(&verified_only_select("SELECT * FROM t1 NATURAL INNER JOIN t2").from).joins,
vec![natural_join(JoinOperator::Inner, None)] vec![natural_join(JoinOperator::Inner, None)]
); );
// left join explicitly // left join explicitly
assert_eq!( assert_eq!(
only(&verified_only_select("SELECT * FROM t1 NATURAL LEFT JOIN t2").from).joins, only(&verified_only_select("SELECT * FROM t1 NATURAL LEFT JOIN t2").from).joins,
vec![natural_join(JoinOperator::Left, None)]
);
// left outer join explicitly
assert_eq!(
only(&verified_only_select("SELECT * FROM t1 NATURAL LEFT OUTER JOIN t2").from).joins,
vec![natural_join(JoinOperator::LeftOuter, None)] vec![natural_join(JoinOperator::LeftOuter, None)]
); );
// right join explicitly // right join explicitly
assert_eq!( assert_eq!(
only(&verified_only_select("SELECT * FROM t1 NATURAL RIGHT JOIN t2").from).joins, only(&verified_only_select("SELECT * FROM t1 NATURAL RIGHT JOIN t2").from).joins,
vec![natural_join(JoinOperator::Right, None)]
);
// right outer join explicitly
assert_eq!(
only(&verified_only_select("SELECT * FROM t1 NATURAL RIGHT OUTER JOIN t2").from).joins,
vec![natural_join(JoinOperator::RightOuter, None)] vec![natural_join(JoinOperator::RightOuter, None)]
); );
@ -6950,22 +6984,12 @@ fn parse_join_nesting() {
#[test] #[test]
fn parse_join_syntax_variants() { fn parse_join_syntax_variants() {
one_statement_parses_to( verified_stmt("SELECT c1 FROM t1 JOIN t2 USING(c1)");
"SELECT c1 FROM t1 JOIN t2 USING(c1)", verified_stmt("SELECT c1 FROM t1 INNER JOIN t2 USING(c1)");
"SELECT c1 FROM t1 JOIN t2 USING(c1)", verified_stmt("SELECT c1 FROM t1 LEFT JOIN t2 USING(c1)");
); verified_stmt("SELECT c1 FROM t1 LEFT OUTER JOIN t2 USING(c1)");
one_statement_parses_to( verified_stmt("SELECT c1 FROM t1 RIGHT JOIN t2 USING(c1)");
"SELECT c1 FROM t1 INNER JOIN t2 USING(c1)", verified_stmt("SELECT c1 FROM t1 RIGHT OUTER JOIN t2 USING(c1)");
"SELECT c1 FROM t1 INNER JOIN t2 USING(c1)",
);
one_statement_parses_to(
"SELECT c1 FROM t1 LEFT OUTER JOIN t2 USING(c1)",
"SELECT c1 FROM t1 LEFT JOIN t2 USING(c1)",
);
one_statement_parses_to(
"SELECT c1 FROM t1 RIGHT OUTER JOIN t2 USING(c1)",
"SELECT c1 FROM t1 RIGHT JOIN t2 USING(c1)",
);
one_statement_parses_to( one_statement_parses_to(
"SELECT c1 FROM t1 FULL OUTER JOIN t2 USING(c1)", "SELECT c1 FROM t1 FULL OUTER JOIN t2 USING(c1)",
"SELECT c1 FROM t1 FULL JOIN t2 USING(c1)", "SELECT c1 FROM t1 FULL JOIN t2 USING(c1)",
@ -8027,7 +8051,7 @@ fn lateral_derived() {
let join = &from.joins[0]; let join = &from.joins[0];
assert_eq!( assert_eq!(
join.join_operator, join.join_operator,
JoinOperator::LeftOuter(JoinConstraint::On(Expr::Value(test_utils::number("1")))) JoinOperator::Left(JoinConstraint::On(Expr::Value(test_utils::number("1"))))
); );
if let TableFactor::Derived { if let TableFactor::Derived {
lateral, lateral,
@ -8095,7 +8119,7 @@ fn lateral_function() {
alias: None, alias: None,
}, },
global: false, global: false,
join_operator: JoinOperator::LeftOuter(JoinConstraint::None), join_operator: JoinOperator::Left(JoinConstraint::None),
}], }],
}], }],
lateral_views: vec![], lateral_views: vec![],