Skip to content

Comments

Optimise prefix/identifier parsing#2227

Closed
alexander-beedie wants to merge 1 commit intoapache:mainfrom
alexander-beedie:perf-parse-prefix
Closed

Optimise prefix/identifier parsing#2227
alexander-beedie wants to merge 1 commit intoapache:mainfrom
alexander-beedie:perf-parse-prefix

Conversation

@alexander-beedie
Copy link
Contributor

@alexander-beedie alexander-beedie commented Feb 21, 2026

Description

  • Tweaked parse_expr_prefix_by_unreserved_word to use into_ident() (move) instead of to_ident() (clone).
  • Added a NoKeyword fast path in parse_prefix (most column references are likely plain identifiers).

Results

Other sqlparser_bench tests just show noise (not really impacted by this change):

┌──────────────────────────────┬───────────┬───────────┬────────┐
│ benchmark                    │ baseline  │ this pr   │ change │
├──────────────────────────────┼───────────┼───────────┼────────┤
│ select_100_columns           │  67.93 µs │  64.32 µs │  −5.1% │
├──────────────────────────────┼───────────┼───────────┼────────┤
│ select_100_qualified_columns │ 140.92 µs │ 136.64 µs │  −3.0% │
├──────────────────────────────┼───────────┼───────────┼────────┤
│ parse_large_statement        │   4.50 ms │   4.47 ms │  −0.8% │
└──────────────────────────────┴───────────┴───────────┴────────┘

@alexander-beedie
Copy link
Contributor Author

alexander-beedie commented Feb 23, 2026

Rebased / conflicts resolved 👍

Comment on lines +1760 to +1781
// 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)?)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this block isnt ideal. its not clear what the special flag entails and why we're specifically looking ahead for a lambda function and I'm afraid that we'll likely accumulate similar special cases going forward

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, no problem. I can drop this part of the patch for now and see if there's a simpler way to get the benefits of the fast path 🤔

Copy link
Contributor Author

@alexander-beedie alexander-beedie Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it looks like the NoKeyword fast-path was responsible for the vast majority of the performance gains here; the reduced patch would just save 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 👍

@alexander-beedie alexander-beedie deleted the perf-parse-prefix branch February 24, 2026 13:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants