mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-22 15:04:04 +00:00
Allow plain JOIN without turning it into INNER (#1692)
This commit is contained in:
parent
784605c913
commit
252fdbab82
8 changed files with 42 additions and 16 deletions
|
@ -2038,13 +2038,20 @@ impl fmt::Display for Join {
|
||||||
}
|
}
|
||||||
|
|
||||||
match &self.join_operator {
|
match &self.join_operator {
|
||||||
JoinOperator::Inner(constraint) => write!(
|
JoinOperator::Join(constraint) => write!(
|
||||||
f,
|
f,
|
||||||
" {}JOIN {}{}",
|
" {}JOIN {}{}",
|
||||||
prefix(constraint),
|
prefix(constraint),
|
||||||
self.relation,
|
self.relation,
|
||||||
suffix(constraint)
|
suffix(constraint)
|
||||||
),
|
),
|
||||||
|
JoinOperator::Inner(constraint) => write!(
|
||||||
|
f,
|
||||||
|
" {}INNER JOIN {}{}",
|
||||||
|
prefix(constraint),
|
||||||
|
self.relation,
|
||||||
|
suffix(constraint)
|
||||||
|
),
|
||||||
JoinOperator::LeftOuter(constraint) => write!(
|
JoinOperator::LeftOuter(constraint) => write!(
|
||||||
f,
|
f,
|
||||||
" {}LEFT JOIN {}{}",
|
" {}LEFT JOIN {}{}",
|
||||||
|
@ -2128,6 +2135,7 @@ impl fmt::Display for Join {
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
pub enum JoinOperator {
|
pub enum JoinOperator {
|
||||||
|
Join(JoinConstraint),
|
||||||
Inner(JoinConstraint),
|
Inner(JoinConstraint),
|
||||||
LeftOuter(JoinConstraint),
|
LeftOuter(JoinConstraint),
|
||||||
RightOuter(JoinConstraint),
|
RightOuter(JoinConstraint),
|
||||||
|
|
|
@ -2001,6 +2001,7 @@ impl Spanned for Join {
|
||||||
impl Spanned for JoinOperator {
|
impl Spanned for JoinOperator {
|
||||||
fn span(&self) -> Span {
|
fn span(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
|
JoinOperator::Join(join_constraint) => join_constraint.span(),
|
||||||
JoinOperator::Inner(join_constraint) => join_constraint.span(),
|
JoinOperator::Inner(join_constraint) => join_constraint.span(),
|
||||||
JoinOperator::LeftOuter(join_constraint) => join_constraint.span(),
|
JoinOperator::LeftOuter(join_constraint) => join_constraint.span(),
|
||||||
JoinOperator::RightOuter(join_constraint) => join_constraint.span(),
|
JoinOperator::RightOuter(join_constraint) => join_constraint.span(),
|
||||||
|
|
|
@ -11000,9 +11000,13 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let join_operator_type = match peek_keyword {
|
let join_operator_type = match peek_keyword {
|
||||||
Keyword::INNER | Keyword::JOIN => {
|
Keyword::INNER | Keyword::JOIN => {
|
||||||
let _ = self.parse_keyword(Keyword::INNER); // [ INNER ]
|
let inner = self.parse_keyword(Keyword::INNER); // [ INNER ]
|
||||||
self.expect_keyword_is(Keyword::JOIN)?;
|
self.expect_keyword_is(Keyword::JOIN)?;
|
||||||
JoinOperator::Inner
|
if inner {
|
||||||
|
JoinOperator::Inner
|
||||||
|
} else {
|
||||||
|
JoinOperator::Join
|
||||||
|
}
|
||||||
}
|
}
|
||||||
kw @ Keyword::LEFT | kw @ Keyword::RIGHT => {
|
kw @ Keyword::LEFT | kw @ Keyword::RIGHT => {
|
||||||
let _ = self.next_token(); // consume LEFT/RIGHT
|
let _ = self.next_token(); // consume LEFT/RIGHT
|
||||||
|
|
|
@ -403,7 +403,7 @@ pub fn join(relation: TableFactor) -> Join {
|
||||||
Join {
|
Join {
|
||||||
relation,
|
relation,
|
||||||
global: false,
|
global: false,
|
||||||
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
|
join_operator: JoinOperator::Join(JoinConstraint::Natural),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1602,7 +1602,7 @@ fn parse_join_constraint_unnest_alias() {
|
||||||
with_ordinality: false,
|
with_ordinality: false,
|
||||||
},
|
},
|
||||||
global: false,
|
global: false,
|
||||||
join_operator: JoinOperator::Inner(JoinConstraint::On(Expr::BinaryOp {
|
join_operator: JoinOperator::Join(JoinConstraint::On(Expr::BinaryOp {
|
||||||
left: Box::new(Expr::Identifier("c1".into())),
|
left: Box::new(Expr::Identifier("c1".into())),
|
||||||
op: BinaryOperator::Eq,
|
op: BinaryOperator::Eq,
|
||||||
right: Box::new(Expr::Identifier("c2".into())),
|
right: Box::new(Expr::Identifier("c2".into())),
|
||||||
|
|
|
@ -6457,7 +6457,7 @@ fn parse_implicit_join() {
|
||||||
joins: vec![Join {
|
joins: vec![Join {
|
||||||
relation: table_from_name(ObjectName::from(vec!["t1b".into()])),
|
relation: table_from_name(ObjectName::from(vec!["t1b".into()])),
|
||||||
global: false,
|
global: false,
|
||||||
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
|
join_operator: JoinOperator::Join(JoinConstraint::Natural),
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
TableWithJoins {
|
TableWithJoins {
|
||||||
|
@ -6465,7 +6465,7 @@ fn parse_implicit_join() {
|
||||||
joins: vec![Join {
|
joins: vec![Join {
|
||||||
relation: table_from_name(ObjectName::from(vec!["t2b".into()])),
|
relation: table_from_name(ObjectName::from(vec!["t2b".into()])),
|
||||||
global: false,
|
global: false,
|
||||||
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
|
join_operator: JoinOperator::Join(JoinConstraint::Natural),
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -6523,7 +6523,7 @@ fn parse_joins_on() {
|
||||||
"t2",
|
"t2",
|
||||||
table_alias("foo"),
|
table_alias("foo"),
|
||||||
false,
|
false,
|
||||||
JoinOperator::Inner,
|
JoinOperator::Join,
|
||||||
)]
|
)]
|
||||||
);
|
);
|
||||||
one_statement_parses_to(
|
one_statement_parses_to(
|
||||||
|
@ -6533,7 +6533,7 @@ fn parse_joins_on() {
|
||||||
// Test parsing of different join operators
|
// Test parsing of different join operators
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
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::Inner)]
|
vec![join_with_constraint("t2", None, false, JoinOperator::Join)]
|
||||||
);
|
);
|
||||||
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,
|
||||||
|
@ -6650,7 +6650,7 @@ fn parse_joins_using() {
|
||||||
vec![join_with_constraint(
|
vec![join_with_constraint(
|
||||||
"t2",
|
"t2",
|
||||||
table_alias("foo"),
|
table_alias("foo"),
|
||||||
JoinOperator::Inner,
|
JoinOperator::Join,
|
||||||
)]
|
)]
|
||||||
);
|
);
|
||||||
one_statement_parses_to(
|
one_statement_parses_to(
|
||||||
|
@ -6660,6 +6660,10 @@ fn parse_joins_using() {
|
||||||
// Test parsing of different join operators
|
// Test parsing of different join operators
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
only(&verified_only_select("SELECT * FROM t1 JOIN t2 USING(c1)").from).joins,
|
only(&verified_only_select("SELECT * FROM t1 JOIN t2 USING(c1)").from).joins,
|
||||||
|
vec![join_with_constraint("t2", None, JoinOperator::Join)]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
only(&verified_only_select("SELECT * FROM t1 INNER JOIN t2 USING(c1)").from).joins,
|
||||||
vec![join_with_constraint("t2", None, JoinOperator::Inner)]
|
vec![join_with_constraint("t2", None, JoinOperator::Inner)]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -6722,9 +6726,14 @@ fn parse_natural_join() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if not specified, inner join as default
|
// unspecified join
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
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)]
|
||||||
|
);
|
||||||
|
// inner join explicitly
|
||||||
|
assert_eq!(
|
||||||
|
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
|
||||||
|
@ -6748,7 +6757,7 @@ fn parse_natural_join() {
|
||||||
// natural join another table with alias
|
// natural join another table with alias
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
only(&verified_only_select("SELECT * FROM t1 NATURAL JOIN t2 AS t3").from).joins,
|
only(&verified_only_select("SELECT * FROM t1 NATURAL JOIN t2 AS t3").from).joins,
|
||||||
vec![natural_join(JoinOperator::Inner, table_alias("t3"))]
|
vec![natural_join(JoinOperator::Join, table_alias("t3"))]
|
||||||
);
|
);
|
||||||
|
|
||||||
let sql = "SELECT * FROM t1 natural";
|
let sql = "SELECT * FROM t1 natural";
|
||||||
|
@ -6816,8 +6825,12 @@ fn parse_join_nesting() {
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_join_syntax_variants() {
|
fn parse_join_syntax_variants() {
|
||||||
one_statement_parses_to(
|
one_statement_parses_to(
|
||||||
"SELECT c1 FROM t1 INNER JOIN t2 USING(c1)",
|
|
||||||
"SELECT c1 FROM t1 JOIN t2 USING(c1)",
|
"SELECT c1 FROM t1 JOIN t2 USING(c1)",
|
||||||
|
"SELECT c1 FROM t1 JOIN t2 USING(c1)",
|
||||||
|
);
|
||||||
|
one_statement_parses_to(
|
||||||
|
"SELECT c1 FROM t1 INNER JOIN t2 USING(c1)",
|
||||||
|
"SELECT c1 FROM t1 INNER JOIN t2 USING(c1)",
|
||||||
);
|
);
|
||||||
one_statement_parses_to(
|
one_statement_parses_to(
|
||||||
"SELECT c1 FROM t1 LEFT OUTER JOIN t2 USING(c1)",
|
"SELECT c1 FROM t1 LEFT OUTER JOIN t2 USING(c1)",
|
||||||
|
@ -6981,7 +6994,7 @@ fn parse_derived_tables() {
|
||||||
joins: vec![Join {
|
joins: vec![Join {
|
||||||
relation: table_from_name(ObjectName::from(vec!["t2".into()])),
|
relation: table_from_name(ObjectName::from(vec!["t2".into()])),
|
||||||
global: false,
|
global: false,
|
||||||
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
|
join_operator: JoinOperator::Join(JoinConstraint::Natural),
|
||||||
}],
|
}],
|
||||||
}),
|
}),
|
||||||
alias: None,
|
alias: None,
|
||||||
|
|
|
@ -2055,7 +2055,7 @@ fn parse_update_with_joins() {
|
||||||
index_hints: vec![],
|
index_hints: vec![],
|
||||||
},
|
},
|
||||||
global: false,
|
global: false,
|
||||||
join_operator: JoinOperator::Inner(JoinConstraint::On(Expr::BinaryOp {
|
join_operator: JoinOperator::Join(JoinConstraint::On(Expr::BinaryOp {
|
||||||
left: Box::new(Expr::CompoundIdentifier(vec![
|
left: Box::new(Expr::CompoundIdentifier(vec![
|
||||||
Ident::new("o"),
|
Ident::new("o"),
|
||||||
Ident::new("customer_id")
|
Ident::new("customer_id")
|
||||||
|
|
|
@ -4371,7 +4371,7 @@ fn parse_join_constraint_unnest_alias() {
|
||||||
with_ordinality: false,
|
with_ordinality: false,
|
||||||
},
|
},
|
||||||
global: false,
|
global: false,
|
||||||
join_operator: JoinOperator::Inner(JoinConstraint::On(Expr::BinaryOp {
|
join_operator: JoinOperator::Join(JoinConstraint::On(Expr::BinaryOp {
|
||||||
left: Box::new(Expr::Identifier("c1".into())),
|
left: Box::new(Expr::Identifier("c1".into())),
|
||||||
op: BinaryOperator::Eq,
|
op: BinaryOperator::Eq,
|
||||||
right: Box::new(Expr::Identifier("c2".into())),
|
right: Box::new(Expr::Identifier("c2".into())),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue