Skip to content

Commit c3e092a

Browse files
committed
[Oracle] Parse CONNECT BY before GROUP BY
1 parent abb2cf7 commit c3e092a

3 files changed

Lines changed: 31 additions & 23 deletions

File tree

src/ast/query.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,8 @@ pub struct Select {
480480
pub prewhere: Option<Expr>,
481481
/// WHERE
482482
pub selection: Option<Expr>,
483+
/// STARTING WITH .. CONNECT BY
484+
pub connect_by: Option<ConnectBy>,
483485
/// GROUP BY
484486
pub group_by: GroupByExpr,
485487
/// CLUSTER BY (Hive)
@@ -501,8 +503,6 @@ pub struct Select {
501503
pub window_before_qualify: bool,
502504
/// BigQuery syntax: `SELECT AS VALUE | SELECT AS STRUCT`
503505
pub value_table_mode: Option<ValueTableMode>,
504-
/// STARTING WITH .. CONNECT BY
505-
pub connect_by: Option<ConnectBy>,
506506
/// Was this a FROM-first query?
507507
pub flavor: SelectFlavor,
508508
}
@@ -585,6 +585,10 @@ impl fmt::Display for Select {
585585
SpaceOrNewline.fmt(f)?;
586586
Indent(selection).fmt(f)?;
587587
}
588+
if let Some(ref connect_by) = self.connect_by {
589+
SpaceOrNewline.fmt(f)?;
590+
connect_by.fmt(f)?;
591+
}
588592
match &self.group_by {
589593
GroupByExpr::All(_) => {
590594
SpaceOrNewline.fmt(f)?;
@@ -648,10 +652,6 @@ impl fmt::Display for Select {
648652
display_comma_separated(&self.named_window).fmt(f)?;
649653
}
650654
}
651-
if let Some(ref connect_by) = self.connect_by {
652-
SpaceOrNewline.fmt(f)?;
653-
connect_by.fmt(f)?;
654-
}
655655
Ok(())
656656
}
657657
}

src/parser/mod.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14032,6 +14032,17 @@ impl<'a> Parser<'a> {
1403214032
None
1403314033
};
1403414034

14035+
let connect_by = if self.dialect.supports_connect_by()
14036+
&& self
14037+
.parse_one_of_keywords(&[Keyword::START, Keyword::CONNECT])
14038+
.is_some()
14039+
{
14040+
self.prev_token();
14041+
Some(self.parse_connect_by()?)
14042+
} else {
14043+
None
14044+
};
14045+
1403514046
let group_by = self
1403614047
.parse_optional_group_by()?
1403714048
.unwrap_or_else(|| GroupByExpr::Expressions(vec![], vec![]));
@@ -14084,17 +14095,6 @@ impl<'a> Parser<'a> {
1408414095
Default::default()
1408514096
};
1408614097

14087-
let connect_by = if self.dialect.supports_connect_by()
14088-
&& self
14089-
.parse_one_of_keywords(&[Keyword::START, Keyword::CONNECT])
14090-
.is_some()
14091-
{
14092-
self.prev_token();
14093-
Some(self.parse_connect_by()?)
14094-
} else {
14095-
None
14096-
};
14097-
1409814098
Ok(Select {
1409914099
select_token: AttachedToken(select_token),
1410014100
optimizer_hint,

tests/sqlparser_common.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12644,6 +12644,8 @@ fn parse_map_access_expr() {
1264412644

1264512645
#[test]
1264612646
fn parse_connect_by() {
12647+
let dialects = all_dialects_where(|d| d.supports_connect_by());
12648+
1264712649
let expect_query = Select {
1264812650
select_token: AttachedToken::empty(),
1264912651
optimizer_hint: None,
@@ -12702,7 +12704,7 @@ fn parse_connect_by() {
1270212704
);
1270312705

1270412706
assert_eq!(
12705-
all_dialects_where(|d| d.supports_connect_by()).verified_only_select(connect_by_1),
12707+
dialects.verified_only_select(connect_by_1),
1270612708
expect_query
1270712709
);
1270812710

@@ -12714,8 +12716,7 @@ fn parse_connect_by() {
1271412716
"ORDER BY employee_id"
1271512717
);
1271612718
assert_eq!(
12717-
all_dialects_where(|d| d.supports_connect_by())
12718-
.verified_only_select_with_canonical(connect_by_2, connect_by_1),
12719+
dialects.verified_only_select_with_canonical(connect_by_2, connect_by_1),
1271912720
expect_query
1272012721
);
1272112722

@@ -12728,7 +12729,7 @@ fn parse_connect_by() {
1272812729
"ORDER BY employee_id"
1272912730
);
1273012731
assert_eq!(
12731-
all_dialects_where(|d| d.supports_connect_by()).verified_only_select(connect_by_3),
12732+
dialects.verified_only_select(connect_by_3),
1273212733
Select {
1273312734
select_token: AttachedToken::empty(),
1273412735
optimizer_hint: None,
@@ -12791,7 +12792,7 @@ fn parse_connect_by() {
1279112792
"WHERE employee_id <> 42 ",
1279212793
"ORDER BY employee_id"
1279312794
);
12794-
all_dialects_where(|d| d.supports_connect_by())
12795+
dialects
1279512796
.parse_sql_statements(connect_by_4)
1279612797
.expect_err("should have failed");
1279712798

@@ -12809,7 +12810,7 @@ fn parse_connect_by() {
1280912810
// no START WITH and NOCYCLE
1281012811
let connect_by_5 = "SELECT child, parent FROM t CONNECT BY NOCYCLE parent = PRIOR child";
1281112812
assert_eq!(
12812-
all_dialects_where(|d| d.supports_connect_by()).verified_only_select(connect_by_5),
12813+
dialects.verified_only_select(connect_by_5),
1281312814
Select {
1281412815
select_token: AttachedToken::empty(),
1281512816
optimizer_hint: None,
@@ -12850,6 +12851,13 @@ fn parse_connect_by() {
1285012851
flavor: SelectFlavor::Standard,
1285112852
}
1285212853
);
12854+
12855+
// ~ CONNECT BY after WHERE and before GROUP BY
12856+
dialects.verified_only_select("SELECT 0 FROM t WHERE 1 = 1 CONNECT BY 2 = 2 GROUP BY 3");
12857+
dialects.verified_only_select("SELECT 0 FROM t WHERE 1 = 1 START WITH 'a' = 'a' CONNECT BY 2 = 2 GROUP BY 3");
12858+
dialects.verified_only_select_with_canonical(
12859+
"SELECT 0 FROM t WHERE 1 = 1 CONNECT BY 2 = 2 START WITH 'a' = 'a' GROUP BY 3",
12860+
"SELECT 0 FROM t WHERE 1 = 1 START WITH 'a' = 'a' CONNECT BY 2 = 2 GROUP BY 3");
1285312861
}
1285412862

1285512863
#[test]

0 commit comments

Comments
 (0)