Skip to content

Commit f966580

Browse files
authored
Allow to use the GLOBAL keyword before the join operator (#1353)
1 parent bc15f7b commit f966580

File tree

9 files changed

+81
-8
lines changed

9 files changed

+81
-8
lines changed

src/ast/query.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,6 +1537,9 @@ impl Display for TableVersion {
15371537
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
15381538
pub struct Join {
15391539
pub relation: TableFactor,
1540+
/// ClickHouse supports the optional `GLOBAL` keyword before the join operator.
1541+
/// See [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/join)
1542+
pub global: bool,
15401543
pub join_operator: JoinOperator,
15411544
}
15421545

@@ -1563,6 +1566,10 @@ impl fmt::Display for Join {
15631566
}
15641567
Suffix(constraint)
15651568
}
1569+
if self.global {
1570+
write!(f, " GLOBAL")?;
1571+
}
1572+
15661573
match &self.join_operator {
15671574
JoinOperator::Inner(constraint) => write!(
15681575
f,

src/keywords.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,7 @@ pub const RESERVED_FOR_TABLE_ALIAS: &[Keyword] = &[
850850
Keyword::USING,
851851
Keyword::CLUSTER,
852852
Keyword::DISTRIBUTE,
853+
Keyword::GLOBAL,
853854
// for MSSQL-specific OUTER APPLY (seems reserved in most dialects)
854855
Keyword::OUTER,
855856
Keyword::SET,

src/parser/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9015,6 +9015,7 @@ impl<'a> Parser<'a> {
90159015
// a table alias.
90169016
let mut joins = vec![];
90179017
loop {
9018+
let global = self.parse_keyword(Keyword::GLOBAL);
90189019
let join = if self.parse_keyword(Keyword::CROSS) {
90199020
let join_operator = if self.parse_keyword(Keyword::JOIN) {
90209021
JoinOperator::CrossJoin
@@ -9026,13 +9027,15 @@ impl<'a> Parser<'a> {
90269027
};
90279028
Join {
90289029
relation: self.parse_table_factor()?,
9030+
global,
90299031
join_operator,
90309032
}
90319033
} else if self.parse_keyword(Keyword::OUTER) {
90329034
// MSSQL extension, similar to LEFT JOIN LATERAL .. ON 1=1
90339035
self.expect_keyword(Keyword::APPLY)?;
90349036
Join {
90359037
relation: self.parse_table_factor()?,
9038+
global,
90369039
join_operator: JoinOperator::OuterApply,
90379040
}
90389041
} else if self.parse_keyword(Keyword::ASOF) {
@@ -9042,6 +9045,7 @@ impl<'a> Parser<'a> {
90429045
let match_condition = self.parse_parenthesized(Self::parse_expr)?;
90439046
Join {
90449047
relation,
9048+
global,
90459049
join_operator: JoinOperator::AsOf {
90469050
match_condition,
90479051
constraint: self.parse_join_constraint(false)?,
@@ -9127,6 +9131,7 @@ impl<'a> Parser<'a> {
91279131
let join_constraint = self.parse_join_constraint(natural)?;
91289132
Join {
91299133
relation,
9134+
global,
91309135
join_operator: join_operator_type(join_constraint),
91319136
}
91329137
};

src/test_utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ pub fn table_with_alias(name: impl Into<String>, alias: impl Into<String>) -> Ta
331331
pub fn join(relation: TableFactor) -> Join {
332332
Join {
333333
relation,
334+
global: false,
334335
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
335336
}
336337
}

tests/sqlparser_bigquery.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,6 +1557,7 @@ fn parse_join_constraint_unnest_alias() {
15571557
with_offset_alias: None,
15581558
with_ordinality: false,
15591559
},
1560+
global: false,
15601561
join_operator: JoinOperator::Inner(JoinConstraint::On(Expr::BinaryOp {
15611562
left: Box::new(Expr::Identifier("c1".into())),
15621563
op: BinaryOperator::Eq,

tests/sqlparser_common.rs

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5600,6 +5600,7 @@ fn parse_implicit_join() {
56005600
partitions: vec![],
56015601
with_ordinality: false,
56025602
},
5603+
global: false,
56035604
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
56045605
}],
56055606
},
@@ -5623,6 +5624,7 @@ fn parse_implicit_join() {
56235624
partitions: vec![],
56245625
with_ordinality: false,
56255626
},
5627+
global: false,
56265628
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
56275629
}],
56285630
},
@@ -5646,6 +5648,7 @@ fn parse_cross_join() {
56465648
partitions: vec![],
56475649
with_ordinality: false,
56485650
},
5651+
global: false,
56495652
join_operator: JoinOperator::CrossJoin,
56505653
},
56515654
only(only(select.from).joins),
@@ -5657,6 +5660,7 @@ fn parse_joins_on() {
56575660
fn join_with_constraint(
56585661
relation: impl Into<String>,
56595662
alias: Option<TableAlias>,
5663+
global: bool,
56605664
f: impl Fn(JoinConstraint) -> JoinOperator,
56615665
) -> Join {
56625666
Join {
@@ -5669,6 +5673,7 @@ fn parse_joins_on() {
56695673
partitions: vec![],
56705674
with_ordinality: false,
56715675
},
5676+
global,
56725677
join_operator: f(JoinConstraint::On(Expr::BinaryOp {
56735678
left: Box::new(Expr::Identifier("c1".into())),
56745679
op: BinaryOperator::Eq,
@@ -5682,6 +5687,7 @@ fn parse_joins_on() {
56825687
vec![join_with_constraint(
56835688
"t2",
56845689
table_alias("foo"),
5690+
false,
56855691
JoinOperator::Inner,
56865692
)]
56875693
);
@@ -5692,35 +5698,80 @@ fn parse_joins_on() {
56925698
// Test parsing of different join operators
56935699
assert_eq!(
56945700
only(&verified_only_select("SELECT * FROM t1 JOIN t2 ON c1 = c2").from).joins,
5695-
vec![join_with_constraint("t2", None, JoinOperator::Inner)]
5701+
vec![join_with_constraint("t2", None, false, JoinOperator::Inner)]
56965702
);
56975703
assert_eq!(
56985704
only(&verified_only_select("SELECT * FROM t1 LEFT JOIN t2 ON c1 = c2").from).joins,
5699-
vec![join_with_constraint("t2", None, JoinOperator::LeftOuter)]
5705+
vec![join_with_constraint(
5706+
"t2",
5707+
None,
5708+
false,
5709+
JoinOperator::LeftOuter
5710+
)]
57005711
);
57015712
assert_eq!(
57025713
only(&verified_only_select("SELECT * FROM t1 RIGHT JOIN t2 ON c1 = c2").from).joins,
5703-
vec![join_with_constraint("t2", None, JoinOperator::RightOuter)]
5714+
vec![join_with_constraint(
5715+
"t2",
5716+
None,
5717+
false,
5718+
JoinOperator::RightOuter
5719+
)]
57045720
);
57055721
assert_eq!(
57065722
only(&verified_only_select("SELECT * FROM t1 LEFT SEMI JOIN t2 ON c1 = c2").from).joins,
5707-
vec![join_with_constraint("t2", None, JoinOperator::LeftSemi)]
5723+
vec![join_with_constraint(
5724+
"t2",
5725+
None,
5726+
false,
5727+
JoinOperator::LeftSemi
5728+
)]
57085729
);
57095730
assert_eq!(
57105731
only(&verified_only_select("SELECT * FROM t1 RIGHT SEMI JOIN t2 ON c1 = c2").from).joins,
5711-
vec![join_with_constraint("t2", None, JoinOperator::RightSemi)]
5732+
vec![join_with_constraint(
5733+
"t2",
5734+
None,
5735+
false,
5736+
JoinOperator::RightSemi
5737+
)]
57125738
);
57135739
assert_eq!(
57145740
only(&verified_only_select("SELECT * FROM t1 LEFT ANTI JOIN t2 ON c1 = c2").from).joins,
5715-
vec![join_with_constraint("t2", None, JoinOperator::LeftAnti)]
5741+
vec![join_with_constraint(
5742+
"t2",
5743+
None,
5744+
false,
5745+
JoinOperator::LeftAnti
5746+
)]
57165747
);
57175748
assert_eq!(
57185749
only(&verified_only_select("SELECT * FROM t1 RIGHT ANTI JOIN t2 ON c1 = c2").from).joins,
5719-
vec![join_with_constraint("t2", None, JoinOperator::RightAnti)]
5750+
vec![join_with_constraint(
5751+
"t2",
5752+
None,
5753+
false,
5754+
JoinOperator::RightAnti
5755+
)]
57205756
);
57215757
assert_eq!(
57225758
only(&verified_only_select("SELECT * FROM t1 FULL JOIN t2 ON c1 = c2").from).joins,
5723-
vec![join_with_constraint("t2", None, JoinOperator::FullOuter)]
5759+
vec![join_with_constraint(
5760+
"t2",
5761+
None,
5762+
false,
5763+
JoinOperator::FullOuter
5764+
)]
5765+
);
5766+
5767+
assert_eq!(
5768+
only(&verified_only_select("SELECT * FROM t1 GLOBAL FULL JOIN t2 ON c1 = c2").from).joins,
5769+
vec![join_with_constraint(
5770+
"t2",
5771+
None,
5772+
true,
5773+
JoinOperator::FullOuter
5774+
)]
57245775
);
57255776
}
57265777

@@ -5741,6 +5792,7 @@ fn parse_joins_using() {
57415792
partitions: vec![],
57425793
with_ordinality: false,
57435794
},
5795+
global: false,
57445796
join_operator: f(JoinConstraint::Using(vec!["c1".into()])),
57455797
}
57465798
}
@@ -5805,6 +5857,7 @@ fn parse_natural_join() {
58055857
partitions: vec![],
58065858
with_ordinality: false,
58075859
},
5860+
global: false,
58085861
join_operator: f(JoinConstraint::Natural),
58095862
}
58105863
}
@@ -6073,6 +6126,7 @@ fn parse_derived_tables() {
60736126
partitions: vec![],
60746127
with_ordinality: false,
60756128
},
6129+
global: false,
60766130
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
60776131
}],
60786132
}),
@@ -6983,6 +7037,7 @@ fn lateral_function() {
69837037
],
69847038
alias: None,
69857039
},
7040+
global: false,
69867041
join_operator: JoinOperator::LeftOuter(JoinConstraint::None),
69877042
}],
69887043
}],

tests/sqlparser_mysql.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1891,6 +1891,7 @@ fn parse_update_with_joins() {
18911891
partitions: vec![],
18921892
with_ordinality: false,
18931893
},
1894+
global: false,
18941895
join_operator: JoinOperator::Inner(JoinConstraint::On(Expr::BinaryOp {
18951896
left: Box::new(Expr::CompoundIdentifier(vec![
18961897
Ident::new("o"),

tests/sqlparser_postgres.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4102,6 +4102,7 @@ fn parse_join_constraint_unnest_alias() {
41024102
with_offset_alias: None,
41034103
with_ordinality: false,
41044104
},
4105+
global: false,
41054106
join_operator: JoinOperator::Inner(JoinConstraint::On(Expr::BinaryOp {
41064107
left: Box::new(Expr::Identifier("c1".into())),
41074108
op: BinaryOperator::Eq,

tests/sqlparser_snowflake.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2206,6 +2206,7 @@ fn asof_joins() {
22062206
relation: table_with_alias("trades_unixtime", "tu"),
22072207
joins: vec![Join {
22082208
relation: table_with_alias("quotes_unixtime", "qu"),
2209+
global: false,
22092210
join_operator: JoinOperator::AsOf {
22102211
match_condition: Expr::BinaryOp {
22112212
left: Box::new(Expr::CompoundIdentifier(vec![

0 commit comments

Comments
 (0)