alexander-beedie commented on code in PR #2227:
URL:
https://github.com/apache/datafusion-sqlparser-rs/pull/2227#discussion_r2847238447
##########
src/parser/mod.rs:
##########
@@ -1756,31 +1756,60 @@ impl<'a> Parser<'a> {
// ^^^^^^^^^^^^^^^^ ^^^^^^^^
// interval expression identifier
//
- // We first try to parse the word and following tokens as a
special expression, and if that fails,
- // we rollback and try to parse it as an identifier.
- let w = w.clone();
- match self.try_parse(|parser|
parser.parse_expr_prefix_by_reserved_word(&w, span)) {
- // This word indicated an expression prefix and parsing
was successful
- Ok(Some(expr)) => Ok(expr),
-
- // No expression prefix associated with this word
- Ok(None) =>
Ok(self.parse_expr_prefix_by_unreserved_word(&w, span)?),
-
- // If parsing of the word as a special expression failed,
we are facing two options:
- // 1. The statement is malformed, e.g. `SELECT INTERVAL '1
DAI` (`DAI` instead of `DAY`)
- // 2. The word is used as an identifier, e.g. `SELECT
MAX(interval) FROM tbl`
- // We first try to parse the word as an identifier and if
that fails
- // we rollback and return the parsing error we got from
trying to parse a
- // special expression (to maintain backwards compatibility
of parsing errors).
- Err(e) => {
- if !self.dialect.is_reserved_for_identifier(w.keyword)
{
- if let Ok(Some(expr)) = self.maybe_parse(|parser| {
-
parser.parse_expr_prefix_by_unreserved_word(&w, span)
- }) {
- return Ok(expr);
+ if w.keyword == Keyword::NoKeyword {
+ // Fast path: for non-keyword words not followed by
+ // special tokens, produce an identifier directly.
+ let peek = &self.peek_token_ref().token;
+ let is_special = matches!(
+ peek,
+ Token::LParen
+ | Token::Arrow
+ | Token::SingleQuotedString(_)
+ | Token::DoubleQuotedString(_)
+ | Token::HexStringLiteral(_)
+ );
+ // Typed lambda: `a INT -> a * 2`
+ let is_typed_lambda = matches!(peek, Token::Word(_))
+ && self.dialect.supports_lambda_functions()
+ && self.peek_nth_token_ref(1).token == Token::Arrow;
+ if !is_special && !is_typed_lambda {
+ Ok(Expr::Identifier(w.to_ident(span)))
+ } else {
+ // Non-keyword followed by special token (e.g.
function call)
+ let w = w.clone();
+ Ok(self.parse_expr_prefix_by_unreserved_word(w, span)?)
+ }
Review Comment:
Actually, it looks like the `NoKeyword` fast-path was responsible for the
vast majority of the performance gains here; the modified patch just saves us a
single String clone, which isn't measurable in benchmarks.
I'll close this one out for simplicity as I have several other more
meaningful optimisations brewing 👍
--
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]