Repository navigation
Conversation
The `[<id> AS <name>]` item name and the `[<id>]` cluster and network
policy names only accept an identifier token for the id (the latter two
also a number token). Display printed a keyword id like `row` bare
(`RawItemName`), or printed the id with no quoting at all
(`RawClusterName`, `RawNetworkPolicyName`), so the output failed to
reparse ("expected id"). Route all three through one helper that prints
the id bare only when it lexes back as the same token, and force-quotes
it otherwise.
Found by the sql_roundtrip cargo-fuzz target (SQL-769).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
d7b70d0 to
df11609
Compare
QA LLM Review1. MEDIUM -- Long numeric
|
ggevay
left a comment
There was a problem hiding this comment.
One simplification inline, which also fixes the QA bot's finding.
(The bug itself is fuzzer-only: real ids always look something like u1, which are not keywords, so prod can't hit it.)
| /// only the reserved ones `Ident::can_be_printed_bare` checks. A normal global | ||
| /// id like `u1` is printed bare in every mode — including the stable mode | ||
| /// `pg_get_viewdef` renders in, which would otherwise force-quote it. | ||
| fn write_bracketed_id<W: fmt::Write>(f: &mut AstFormatter<W>, id: &str, allow_number: bool) { |
There was a problem hiding this comment.
Simpler: drop Token::Number from parse_raw_ident_str instead of handling it here. It's left over from integer cluster ids (IN CLUSTER [1], 395050f). ClusterId::from_str now needs an s/u prefix, so a numeric cluster id never resolves, and only three testdata/ddl cases use one. (Network policies resolve the bracket text as a name, and ["1"] still covers that.) Then this becomes:
fn write_bracketed_id<W: fmt::Write>(f: &mut AstFormatter<W>, id: &str) {
let ident = Ident::new_unchecked(id);
if ident.has_only_bare_chars() && ident.as_keyword().is_none() {
f.write_str(id);
} else {
f.write_str(ident.to_ast_string_stable());
}
}That also fixes the bot's finding: new_unchecked runs before the number check, so IN CLUSTER [<300 digits>] hits the 255-byte soft assert. Identifier tokens are capped at 255 bytes.
Also, the comment on the empty-id check in parse_raw_ident_str is stale with this change ([""] would now print as [""]). Please keep the check, but give the reason that parse_identifier rejects zero-length identifiers everywhere else, and let parse_raw_name reuse parse_raw_ident_str so item ids get it too.
| # An id that is a keyword must stay quoted when displayed: `[<id> AS …]` only | ||
| # accepts an identifier token, so a bare keyword id fails to reparse | ||
| # (SQL-769). Applies to every position that takes a raw item name, including a | ||
| # cast's type. |
There was a problem hiding this comment.
Please add it to the comment that this is just a fuzzer-only requirement, real queries can't hit it.
Quote bracketed ids that need it on display so the printed SQL parses back.
rowbare in[<id> AS <name>], and printed[<id>]cluster and network policy ids unquoted.[<id>]), so the output failed with "expected id".u1and numeric cluster ids like[1]still print bare, so there is no user-facing change.src/sql-parser/tests/testdata/id, covering item names, casts, clusters, network policies and the fuzz finding.Closes: SQL-769
🤖 Generated with Claude Code