xitep commented on code in PR #2216:
URL:
https://github.com/apache/datafusion-sqlparser-rs/pull/2216#discussion_r2802543481
##########
src/parser/mod.rs:
##########
@@ -14168,53 +14168,75 @@ impl<'a> Parser<'a> {
})
}
- /// Parses an optional optimizer hint at the current token position
+ /// Parses optimizer hints at the current token position.
+ ///
+ /// Collects all `/*prefix+...*/` and `--prefix+...` patterns.
+ /// The `prefix` is any run of ASCII alphanumeric characters between the
+ /// comment marker and `+` (e.g. `""` for `/*+...*/`, `"abc"` for
`/*abc+...*/`).
///
///
[MySQL](https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html#optimizer-hints-overview)
///
[Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/Comments.html#GUID-D316D545-89E2-4D54-977F-FC97815CD62E)
- fn maybe_parse_optimizer_hint(&mut self) -> Result<Option<OptimizerHint>,
ParserError> {
+ fn maybe_parse_optimizer_hints(&mut self) -> Result<Vec<OptimizerHint>,
ParserError> {
let supports_hints = self.dialect.supports_comment_optimizer_hint();
if !supports_hints {
- return Ok(None);
+ return Ok(vec![]);
}
+ let mut hints = vec![];
loop {
let t = self.peek_nth_token_no_skip_ref(0);
match &t.token {
- Token::Whitespace(ws) => {
- match ws {
- Whitespace::SingleLineComment { comment, .. }
- | Whitespace::MultiLineComment(comment) => {
- return Ok(match comment.strip_prefix("+") {
- None => None,
- Some(text) => {
- let hint = OptimizerHint {
- text: text.into(),
- style: if let
Whitespace::SingleLineComment {
- prefix, ..
- } = ws
- {
- OptimizerHintStyle::SingleLine {
- prefix: prefix.clone(),
- }
- } else {
- OptimizerHintStyle::MultiLine
- },
- };
- // Consume the comment token
- self.next_token_no_skip();
- Some(hint)
- }
+ Token::Whitespace(ws) => match ws {
+ Whitespace::SingleLineComment { comment, prefix } => {
+ if let Some((hint_prefix, text)) =
+ Self::extract_hint_prefix_and_text(comment)
+ {
+ hints.push(OptimizerHint {
+ prefix: hint_prefix,
+ text,
+ style: OptimizerHintStyle::SingleLine {
+ prefix: prefix.clone(),
+ },
});
+ self.next_token_no_skip();
+ } else {
+ break;
}
- Whitespace::Space | Whitespace::Tab |
Whitespace::Newline => {
- // Consume the token and try with the next
whitespace or comment
+ }
+ Whitespace::MultiLineComment(comment) => {
+ if let Some((hint_prefix, text)) =
+ Self::extract_hint_prefix_and_text(comment)
+ {
+ hints.push(OptimizerHint {
+ prefix: hint_prefix,
+ text,
+ style: OptimizerHintStyle::MultiLine,
+ });
self.next_token_no_skip();
+ } else {
+ break;
}
}
- }
- _ => return Ok(None),
+ Whitespace::Space | Whitespace::Tab | Whitespace::Newline
=> {
+ self.next_token_no_skip();
+ }
+ },
+ _ => break,
}
}
+ Ok(hints)
+ }
+
+ /// Checks if a comment's content starts with `[ASCII-alphanumeric]*+`
+ /// and returns `(prefix, text_after_plus)` if so.
+ fn extract_hint_prefix_and_text(comment: &str) -> Option<(String, String)>
{
+ let plus_pos = comment.find('+')?;
+ let before_plus = &comment[..plus_pos];
+ if before_plus.chars().all(|c| c.is_ascii_alphanumeric()) {
+ let text = &comment[plus_pos + 1..];
+ Some((before_plus.to_string(), text.to_string()))
+ } else {
+ None
+ }
Review Comment:
i think using `str::split_once` would make this shorter and leaner (possibly
slightly more efficient), e.g.
https://gist.github.com/rust-play/146d81960095525d6384f34d84ac7419
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]