mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-04 06:18:17 +00:00
Allow to use the GLOBAL keyword before the join operator (#1353)
This commit is contained in:
parent
bc15f7b4ce
commit
f96658006f
9 changed files with 81 additions and 8 deletions
|
@ -1537,6 +1537,9 @@ impl Display for TableVersion {
|
|||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||
pub struct Join {
|
||||
pub relation: TableFactor,
|
||||
/// ClickHouse supports the optional `GLOBAL` keyword before the join operator.
|
||||
/// See [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/join)
|
||||
pub global: bool,
|
||||
pub join_operator: JoinOperator,
|
||||
}
|
||||
|
||||
|
@ -1563,6 +1566,10 @@ impl fmt::Display for Join {
|
|||
}
|
||||
Suffix(constraint)
|
||||
}
|
||||
if self.global {
|
||||
write!(f, " GLOBAL")?;
|
||||
}
|
||||
|
||||
match &self.join_operator {
|
||||
JoinOperator::Inner(constraint) => write!(
|
||||
f,
|
||||
|
|
|
@ -850,6 +850,7 @@ pub const RESERVED_FOR_TABLE_ALIAS: &[Keyword] = &[
|
|||
Keyword::USING,
|
||||
Keyword::CLUSTER,
|
||||
Keyword::DISTRIBUTE,
|
||||
Keyword::GLOBAL,
|
||||
// for MSSQL-specific OUTER APPLY (seems reserved in most dialects)
|
||||
Keyword::OUTER,
|
||||
Keyword::SET,
|
||||
|
|
|
@ -9015,6 +9015,7 @@ impl<'a> Parser<'a> {
|
|||
// a table alias.
|
||||
let mut joins = vec![];
|
||||
loop {
|
||||
let global = self.parse_keyword(Keyword::GLOBAL);
|
||||
let join = if self.parse_keyword(Keyword::CROSS) {
|
||||
let join_operator = if self.parse_keyword(Keyword::JOIN) {
|
||||
JoinOperator::CrossJoin
|
||||
|
@ -9026,6 +9027,7 @@ impl<'a> Parser<'a> {
|
|||
};
|
||||
Join {
|
||||
relation: self.parse_table_factor()?,
|
||||
global,
|
||||
join_operator,
|
||||
}
|
||||
} else if self.parse_keyword(Keyword::OUTER) {
|
||||
|
@ -9033,6 +9035,7 @@ impl<'a> Parser<'a> {
|
|||
self.expect_keyword(Keyword::APPLY)?;
|
||||
Join {
|
||||
relation: self.parse_table_factor()?,
|
||||
global,
|
||||
join_operator: JoinOperator::OuterApply,
|
||||
}
|
||||
} else if self.parse_keyword(Keyword::ASOF) {
|
||||
|
@ -9042,6 +9045,7 @@ impl<'a> Parser<'a> {
|
|||
let match_condition = self.parse_parenthesized(Self::parse_expr)?;
|
||||
Join {
|
||||
relation,
|
||||
global,
|
||||
join_operator: JoinOperator::AsOf {
|
||||
match_condition,
|
||||
constraint: self.parse_join_constraint(false)?,
|
||||
|
@ -9127,6 +9131,7 @@ impl<'a> Parser<'a> {
|
|||
let join_constraint = self.parse_join_constraint(natural)?;
|
||||
Join {
|
||||
relation,
|
||||
global,
|
||||
join_operator: join_operator_type(join_constraint),
|
||||
}
|
||||
};
|
||||
|
|
|
@ -331,6 +331,7 @@ pub fn table_with_alias(name: impl Into<String>, alias: impl Into<String>) -> Ta
|
|||
pub fn join(relation: TableFactor) -> Join {
|
||||
Join {
|
||||
relation,
|
||||
global: false,
|
||||
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1557,6 +1557,7 @@ fn parse_join_constraint_unnest_alias() {
|
|||
with_offset_alias: None,
|
||||
with_ordinality: false,
|
||||
},
|
||||
global: false,
|
||||
join_operator: JoinOperator::Inner(JoinConstraint::On(Expr::BinaryOp {
|
||||
left: Box::new(Expr::Identifier("c1".into())),
|
||||
op: BinaryOperator::Eq,
|
||||
|
|
|
@ -5600,6 +5600,7 @@ fn parse_implicit_join() {
|
|||
partitions: vec![],
|
||||
with_ordinality: false,
|
||||
},
|
||||
global: false,
|
||||
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
|
||||
}],
|
||||
},
|
||||
|
@ -5623,6 +5624,7 @@ fn parse_implicit_join() {
|
|||
partitions: vec![],
|
||||
with_ordinality: false,
|
||||
},
|
||||
global: false,
|
||||
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
|
||||
}],
|
||||
},
|
||||
|
@ -5646,6 +5648,7 @@ fn parse_cross_join() {
|
|||
partitions: vec![],
|
||||
with_ordinality: false,
|
||||
},
|
||||
global: false,
|
||||
join_operator: JoinOperator::CrossJoin,
|
||||
},
|
||||
only(only(select.from).joins),
|
||||
|
@ -5657,6 +5660,7 @@ fn parse_joins_on() {
|
|||
fn join_with_constraint(
|
||||
relation: impl Into<String>,
|
||||
alias: Option<TableAlias>,
|
||||
global: bool,
|
||||
f: impl Fn(JoinConstraint) -> JoinOperator,
|
||||
) -> Join {
|
||||
Join {
|
||||
|
@ -5669,6 +5673,7 @@ fn parse_joins_on() {
|
|||
partitions: vec![],
|
||||
with_ordinality: false,
|
||||
},
|
||||
global,
|
||||
join_operator: f(JoinConstraint::On(Expr::BinaryOp {
|
||||
left: Box::new(Expr::Identifier("c1".into())),
|
||||
op: BinaryOperator::Eq,
|
||||
|
@ -5682,6 +5687,7 @@ fn parse_joins_on() {
|
|||
vec![join_with_constraint(
|
||||
"t2",
|
||||
table_alias("foo"),
|
||||
false,
|
||||
JoinOperator::Inner,
|
||||
)]
|
||||
);
|
||||
|
@ -5692,35 +5698,80 @@ fn parse_joins_on() {
|
|||
// Test parsing of different join operators
|
||||
assert_eq!(
|
||||
only(&verified_only_select("SELECT * FROM t1 JOIN t2 ON c1 = c2").from).joins,
|
||||
vec![join_with_constraint("t2", None, JoinOperator::Inner)]
|
||||
vec![join_with_constraint("t2", None, false, JoinOperator::Inner)]
|
||||
);
|
||||
assert_eq!(
|
||||
only(&verified_only_select("SELECT * FROM t1 LEFT JOIN t2 ON c1 = c2").from).joins,
|
||||
vec![join_with_constraint("t2", None, JoinOperator::LeftOuter)]
|
||||
vec![join_with_constraint(
|
||||
"t2",
|
||||
None,
|
||||
false,
|
||||
JoinOperator::LeftOuter
|
||||
)]
|
||||
);
|
||||
assert_eq!(
|
||||
only(&verified_only_select("SELECT * FROM t1 RIGHT JOIN t2 ON c1 = c2").from).joins,
|
||||
vec![join_with_constraint("t2", None, JoinOperator::RightOuter)]
|
||||
vec![join_with_constraint(
|
||||
"t2",
|
||||
None,
|
||||
false,
|
||||
JoinOperator::RightOuter
|
||||
)]
|
||||
);
|
||||
assert_eq!(
|
||||
only(&verified_only_select("SELECT * FROM t1 LEFT SEMI JOIN t2 ON c1 = c2").from).joins,
|
||||
vec![join_with_constraint("t2", None, JoinOperator::LeftSemi)]
|
||||
vec![join_with_constraint(
|
||||
"t2",
|
||||
None,
|
||||
false,
|
||||
JoinOperator::LeftSemi
|
||||
)]
|
||||
);
|
||||
assert_eq!(
|
||||
only(&verified_only_select("SELECT * FROM t1 RIGHT SEMI JOIN t2 ON c1 = c2").from).joins,
|
||||
vec![join_with_constraint("t2", None, JoinOperator::RightSemi)]
|
||||
vec![join_with_constraint(
|
||||
"t2",
|
||||
None,
|
||||
false,
|
||||
JoinOperator::RightSemi
|
||||
)]
|
||||
);
|
||||
assert_eq!(
|
||||
only(&verified_only_select("SELECT * FROM t1 LEFT ANTI JOIN t2 ON c1 = c2").from).joins,
|
||||
vec![join_with_constraint("t2", None, JoinOperator::LeftAnti)]
|
||||
vec![join_with_constraint(
|
||||
"t2",
|
||||
None,
|
||||
false,
|
||||
JoinOperator::LeftAnti
|
||||
)]
|
||||
);
|
||||
assert_eq!(
|
||||
only(&verified_only_select("SELECT * FROM t1 RIGHT ANTI JOIN t2 ON c1 = c2").from).joins,
|
||||
vec![join_with_constraint("t2", None, JoinOperator::RightAnti)]
|
||||
vec![join_with_constraint(
|
||||
"t2",
|
||||
None,
|
||||
false,
|
||||
JoinOperator::RightAnti
|
||||
)]
|
||||
);
|
||||
assert_eq!(
|
||||
only(&verified_only_select("SELECT * FROM t1 FULL JOIN t2 ON c1 = c2").from).joins,
|
||||
vec![join_with_constraint("t2", None, JoinOperator::FullOuter)]
|
||||
vec![join_with_constraint(
|
||||
"t2",
|
||||
None,
|
||||
false,
|
||||
JoinOperator::FullOuter
|
||||
)]
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
only(&verified_only_select("SELECT * FROM t1 GLOBAL FULL JOIN t2 ON c1 = c2").from).joins,
|
||||
vec![join_with_constraint(
|
||||
"t2",
|
||||
None,
|
||||
true,
|
||||
JoinOperator::FullOuter
|
||||
)]
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -5741,6 +5792,7 @@ fn parse_joins_using() {
|
|||
partitions: vec![],
|
||||
with_ordinality: false,
|
||||
},
|
||||
global: false,
|
||||
join_operator: f(JoinConstraint::Using(vec!["c1".into()])),
|
||||
}
|
||||
}
|
||||
|
@ -5805,6 +5857,7 @@ fn parse_natural_join() {
|
|||
partitions: vec![],
|
||||
with_ordinality: false,
|
||||
},
|
||||
global: false,
|
||||
join_operator: f(JoinConstraint::Natural),
|
||||
}
|
||||
}
|
||||
|
@ -6073,6 +6126,7 @@ fn parse_derived_tables() {
|
|||
partitions: vec![],
|
||||
with_ordinality: false,
|
||||
},
|
||||
global: false,
|
||||
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
|
||||
}],
|
||||
}),
|
||||
|
@ -6983,6 +7037,7 @@ fn lateral_function() {
|
|||
],
|
||||
alias: None,
|
||||
},
|
||||
global: false,
|
||||
join_operator: JoinOperator::LeftOuter(JoinConstraint::None),
|
||||
}],
|
||||
}],
|
||||
|
|
|
@ -1891,6 +1891,7 @@ fn parse_update_with_joins() {
|
|||
partitions: vec![],
|
||||
with_ordinality: false,
|
||||
},
|
||||
global: false,
|
||||
join_operator: JoinOperator::Inner(JoinConstraint::On(Expr::BinaryOp {
|
||||
left: Box::new(Expr::CompoundIdentifier(vec![
|
||||
Ident::new("o"),
|
||||
|
|
|
@ -4102,6 +4102,7 @@ fn parse_join_constraint_unnest_alias() {
|
|||
with_offset_alias: None,
|
||||
with_ordinality: false,
|
||||
},
|
||||
global: false,
|
||||
join_operator: JoinOperator::Inner(JoinConstraint::On(Expr::BinaryOp {
|
||||
left: Box::new(Expr::Identifier("c1".into())),
|
||||
op: BinaryOperator::Eq,
|
||||
|
|
|
@ -2206,6 +2206,7 @@ fn asof_joins() {
|
|||
relation: table_with_alias("trades_unixtime", "tu"),
|
||||
joins: vec![Join {
|
||||
relation: table_with_alias("quotes_unixtime", "qu"),
|
||||
global: false,
|
||||
join_operator: JoinOperator::AsOf {
|
||||
match_condition: Expr::BinaryOp {
|
||||
left: Box::new(Expr::CompoundIdentifier(vec![
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue