Skip to content

Commit 6ab2e66

Browse files
committed
Allow to use the GLOBAL keyword before the join operator apache#1353
ClickHouse supports the GLOBAL keyworld while joining the right table, for the syntax, please refer to: ```SQL SELECT <expr_list> FROM <left_table> [GLOBAL] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI|ANY|ALL|ASOF] JOIN <right_table> (ON <expr_list>)|(USING <column_list>) ``` Reference: https://clickhouse.com/docs/en/sql-reference/statements/select/join
1 parent 6c64d43 commit 6ab2e66

File tree

9 files changed

+86
-13
lines changed

9 files changed

+86
-13
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: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
//! As a matter of fact, most of these keywords are not used at all
2121
//! and could be removed.
2222
//! 3) a `RESERVED_FOR_TABLE_ALIAS` array with keywords reserved in a
23-
//! "table alias" context.
23+
//! "table alias" context.
2424
2525
#[cfg(feature = "serde")]
2626
use serde::{Deserialize, Serialize};
@@ -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
@@ -9003,6 +9003,7 @@ impl<'a> Parser<'a> {
90039003
// a table alias.
90049004
let mut joins = vec![];
90059005
loop {
9006+
let global = self.parse_keyword(Keyword::GLOBAL);
90069007
let join = if self.parse_keyword(Keyword::CROSS) {
90079008
let join_operator = if self.parse_keyword(Keyword::JOIN) {
90089009
JoinOperator::CrossJoin
@@ -9014,13 +9015,15 @@ impl<'a> Parser<'a> {
90149015
};
90159016
Join {
90169017
relation: self.parse_table_factor()?,
9018+
global,
90179019
join_operator,
90189020
}
90199021
} else if self.parse_keyword(Keyword::OUTER) {
90209022
// MSSQL extension, similar to LEFT JOIN LATERAL .. ON 1=1
90219023
self.expect_keyword(Keyword::APPLY)?;
90229024
Join {
90239025
relation: self.parse_table_factor()?,
9026+
global,
90249027
join_operator: JoinOperator::OuterApply,
90259028
}
90269029
} else if self.parse_keyword(Keyword::ASOF) {
@@ -9030,6 +9033,7 @@ impl<'a> Parser<'a> {
90309033
let match_condition = self.parse_parenthesized(Self::parse_expr)?;
90319034
Join {
90329035
relation,
9036+
global,
90339037
join_operator: JoinOperator::AsOf {
90349038
match_condition,
90359039
constraint: self.parse_join_constraint(false)?,
@@ -9115,6 +9119,7 @@ impl<'a> Parser<'a> {
91159119
let join_constraint = self.parse_join_constraint(natural)?;
91169120
Join {
91179121
relation,
9122+
global,
91189123
join_operator: join_operator_type(join_constraint),
91199124
}
91209125
};

src/test_utils.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,10 @@ impl TestedDialects {
111111
/// that:
112112
///
113113
/// 1. parsing `sql` results in the same [`Statement`] as parsing
114-
/// `canonical`.
114+
/// `canonical`.
115115
///
116116
/// 2. re-serializing the result of parsing `sql` produces the same
117-
/// `canonical` sql string
117+
/// `canonical` sql string
118118
pub fn one_statement_parses_to(&self, sql: &str, canonical: &str) -> Statement {
119119
let mut statements = self.parse_sql_statements(sql).expect(sql);
120120
assert_eq!(statements.len(), 1);
@@ -180,10 +180,10 @@ impl TestedDialects {
180180
/// Ensures that `sql` parses as a single [`Select`], and that additionally:
181181
///
182182
/// 1. parsing `sql` results in the same [`Statement`] as parsing
183-
/// `canonical`.
183+
/// `canonical`.
184184
///
185185
/// 2. re-serializing the result of parsing `sql` produces the same
186-
/// `canonical` sql string
186+
/// `canonical` sql string
187187
pub fn verified_only_select_with_canonical(&self, query: &str, canonical: &str) -> Select {
188188
let q = match self.one_statement_parses_to(query, canonical) {
189189
Statement::Query(query) => *query,
@@ -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
@@ -5582,6 +5582,7 @@ fn parse_implicit_join() {
55825582
partitions: vec![],
55835583
with_ordinality: false,
55845584
},
5585+
global: false,
55855586
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
55865587
}],
55875588
},
@@ -5605,6 +5606,7 @@ fn parse_implicit_join() {
56055606
partitions: vec![],
56065607
with_ordinality: false,
56075608
},
5609+
global: false,
56085610
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
56095611
}],
56105612
},
@@ -5628,6 +5630,7 @@ fn parse_cross_join() {
56285630
partitions: vec![],
56295631
with_ordinality: false,
56305632
},
5633+
global: false,
56315634
join_operator: JoinOperator::CrossJoin,
56325635
},
56335636
only(only(select.from).joins),
@@ -5639,6 +5642,7 @@ fn parse_joins_on() {
56395642
fn join_with_constraint(
56405643
relation: impl Into<String>,
56415644
alias: Option<TableAlias>,
5645+
global: bool,
56425646
f: impl Fn(JoinConstraint) -> JoinOperator,
56435647
) -> Join {
56445648
Join {
@@ -5651,6 +5655,7 @@ fn parse_joins_on() {
56515655
partitions: vec![],
56525656
with_ordinality: false,
56535657
},
5658+
global,
56545659
join_operator: f(JoinConstraint::On(Expr::BinaryOp {
56555660
left: Box::new(Expr::Identifier("c1".into())),
56565661
op: BinaryOperator::Eq,
@@ -5664,6 +5669,7 @@ fn parse_joins_on() {
56645669
vec![join_with_constraint(
56655670
"t2",
56665671
table_alias("foo"),
5672+
false,
56675673
JoinOperator::Inner,
56685674
)]
56695675
);
@@ -5674,35 +5680,80 @@ fn parse_joins_on() {
56745680
// Test parsing of different join operators
56755681
assert_eq!(
56765682
only(&verified_only_select("SELECT * FROM t1 JOIN t2 ON c1 = c2").from).joins,
5677-
vec![join_with_constraint("t2", None, JoinOperator::Inner)]
5683+
vec![join_with_constraint("t2", None, false, JoinOperator::Inner)]
56785684
);
56795685
assert_eq!(
56805686
only(&verified_only_select("SELECT * FROM t1 LEFT JOIN t2 ON c1 = c2").from).joins,
5681-
vec![join_with_constraint("t2", None, JoinOperator::LeftOuter)]
5687+
vec![join_with_constraint(
5688+
"t2",
5689+
None,
5690+
false,
5691+
JoinOperator::LeftOuter
5692+
)]
56825693
);
56835694
assert_eq!(
56845695
only(&verified_only_select("SELECT * FROM t1 RIGHT JOIN t2 ON c1 = c2").from).joins,
5685-
vec![join_with_constraint("t2", None, JoinOperator::RightOuter)]
5696+
vec![join_with_constraint(
5697+
"t2",
5698+
None,
5699+
false,
5700+
JoinOperator::RightOuter
5701+
)]
56865702
);
56875703
assert_eq!(
56885704
only(&verified_only_select("SELECT * FROM t1 LEFT SEMI JOIN t2 ON c1 = c2").from).joins,
5689-
vec![join_with_constraint("t2", None, JoinOperator::LeftSemi)]
5705+
vec![join_with_constraint(
5706+
"t2",
5707+
None,
5708+
false,
5709+
JoinOperator::LeftSemi
5710+
)]
56905711
);
56915712
assert_eq!(
56925713
only(&verified_only_select("SELECT * FROM t1 RIGHT SEMI JOIN t2 ON c1 = c2").from).joins,
5693-
vec![join_with_constraint("t2", None, JoinOperator::RightSemi)]
5714+
vec![join_with_constraint(
5715+
"t2",
5716+
None,
5717+
false,
5718+
JoinOperator::RightSemi
5719+
)]
56945720
);
56955721
assert_eq!(
56965722
only(&verified_only_select("SELECT * FROM t1 LEFT ANTI JOIN t2 ON c1 = c2").from).joins,
5697-
vec![join_with_constraint("t2", None, JoinOperator::LeftAnti)]
5723+
vec![join_with_constraint(
5724+
"t2",
5725+
None,
5726+
false,
5727+
JoinOperator::LeftAnti
5728+
)]
56985729
);
56995730
assert_eq!(
57005731
only(&verified_only_select("SELECT * FROM t1 RIGHT ANTI JOIN t2 ON c1 = c2").from).joins,
5701-
vec![join_with_constraint("t2", None, JoinOperator::RightAnti)]
5732+
vec![join_with_constraint(
5733+
"t2",
5734+
None,
5735+
false,
5736+
JoinOperator::RightAnti
5737+
)]
57025738
);
57035739
assert_eq!(
57045740
only(&verified_only_select("SELECT * FROM t1 FULL JOIN t2 ON c1 = c2").from).joins,
5705-
vec![join_with_constraint("t2", None, JoinOperator::FullOuter)]
5741+
vec![join_with_constraint(
5742+
"t2",
5743+
None,
5744+
false,
5745+
JoinOperator::FullOuter
5746+
)]
5747+
);
5748+
5749+
assert_eq!(
5750+
only(&verified_only_select("SELECT * FROM t1 GLOBAL FULL JOIN t2 ON c1 = c2").from).joins,
5751+
vec![join_with_constraint(
5752+
"t2",
5753+
None,
5754+
true,
5755+
JoinOperator::FullOuter
5756+
)]
57065757
);
57075758
}
57085759

@@ -5723,6 +5774,7 @@ fn parse_joins_using() {
57235774
partitions: vec![],
57245775
with_ordinality: false,
57255776
},
5777+
global: false,
57265778
join_operator: f(JoinConstraint::Using(vec!["c1".into()])),
57275779
}
57285780
}
@@ -5787,6 +5839,7 @@ fn parse_natural_join() {
57875839
partitions: vec![],
57885840
with_ordinality: false,
57895841
},
5842+
global: false,
57905843
join_operator: f(JoinConstraint::Natural),
57915844
}
57925845
}
@@ -6055,6 +6108,7 @@ fn parse_derived_tables() {
60556108
partitions: vec![],
60566109
with_ordinality: false,
60576110
},
6111+
global: false,
60586112
join_operator: JoinOperator::Inner(JoinConstraint::Natural),
60596113
}],
60606114
}),
@@ -6965,6 +7019,7 @@ fn lateral_function() {
69657019
],
69667020
alias: None,
69677021
},
7022+
global: false,
69687023
join_operator: JoinOperator::LeftOuter(JoinConstraint::None),
69697024
}],
69707025
}],

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)