@@ -4521,16 +4521,25 @@ impl<'a> Parser<'a> {
45214521 /// consumed and returns false
45224522 #[must_use]
45234523 pub fn parse_keywords(&mut self, keywords: &[Keyword]) -> bool {
4524- let index = self.index;
4524+ self.parse_keywords_indexed(keywords).is_some()
4525+ }
4526+
4527+ /// Just like [Self::parse_keywords], but - upon success - returns the
4528+ /// token index of the first keyword.
4529+ #[must_use]
4530+ fn parse_keywords_indexed(&mut self, keywords: &[Keyword]) -> Option<usize> {
4531+ let start_index = self.index;
4532+ let mut first_keyword_index = None;
45254533 for &keyword in keywords {
45264534 if !self.parse_keyword(keyword) {
4527- // println!("parse_keywords aborting .. did not find {:?}", keyword);
4528- // reset index and return immediately
4529- self.index = index;
4530- return false;
4535+ self.index = start_index;
4536+ return None;
4537+ }
4538+ if first_keyword_index.is_none() {
4539+ first_keyword_index = Some(self.index.saturating_sub(1));
45314540 }
45324541 }
4533- true
4542+ first_keyword_index
45344543 }
45354544
45364545 /// If the current token is one of the given `keywords`, returns the keyword
@@ -13921,7 +13930,7 @@ impl<'a> Parser<'a> {
1392113930 window_before_qualify: false,
1392213931 qualify: None,
1392313932 value_table_mode: None,
13924- connect_by: None ,
13933+ connect_by: vec![] ,
1392513934 flavor: SelectFlavor::FromFirstNoSelect,
1392613935 });
1392713936 }
@@ -14032,6 +14041,8 @@ impl<'a> Parser<'a> {
1403214041 None
1403314042 };
1403414043
14044+ let connect_by = self.maybe_parse_connect_by()?;
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,
@@ -14279,27 +14279,28 @@ impl<'a> Parser<'a> {
1427914279 }
1428014280
1428114281 /// Parse a `CONNECT BY` clause (Oracle-style hierarchical query support).
14282- pub fn parse_connect_by(&mut self) -> Result<ConnectBy, ParserError> {
14283- let (condition, relationships) = if self.parse_keywords(&[Keyword::CONNECT, Keyword::BY]) {
14284- let relationships = self.with_state(ParserState::ConnectBy, |parser| {
14285- parser.parse_comma_separated(Parser::parse_expr)
14286- })?;
14287- self.expect_keywords(&[Keyword::START, Keyword::WITH])?;
14288- let condition = self.parse_expr()?;
14289- (condition, relationships)
14290- } else {
14291- self.expect_keywords(&[Keyword::START, Keyword::WITH])?;
14292- let condition = self.parse_expr()?;
14293- self.expect_keywords(&[Keyword::CONNECT, Keyword::BY])?;
14294- let relationships = self.with_state(ParserState::ConnectBy, |parser| {
14295- parser.parse_comma_separated(Parser::parse_expr)
14296- })?;
14297- (condition, relationships)
14298- };
14299- Ok(ConnectBy {
14300- condition,
14301- relationships,
14302- })
14282+ pub fn maybe_parse_connect_by(&mut self) -> Result<Vec<ConnectByKind>, ParserError> {
14283+ let mut clauses = Vec::with_capacity(2);
14284+ loop {
14285+ if let Some(idx) = self.parse_keywords_indexed(&[Keyword::START, Keyword::WITH]) {
14286+ clauses.push(ConnectByKind::StartWith {
14287+ start_token: self.token_at(idx).clone().into(),
14288+ condition: self.parse_expr()?.into(),
14289+ });
14290+ } else if let Some(idx) = self.parse_keywords_indexed(&[Keyword::CONNECT, Keyword::BY])
14291+ {
14292+ clauses.push(ConnectByKind::ConnectBy {
14293+ connect_token: self.token_at(idx).clone().into(),
14294+ nocycle: self.parse_keyword(Keyword::NOCYCLE),
14295+ relationships: self.with_state(ParserState::ConnectBy, |parser| {
14296+ parser.parse_comma_separated(Parser::parse_expr)
14297+ })?,
14298+ });
14299+ } else {
14300+ break;
14301+ }
14302+ }
14303+ Ok(clauses)
1430314304 }
1430414305
1430514306 /// Parse `CREATE TABLE x AS TABLE y`
0 commit comments