feat(parser): support MySQL # line comments behind allowHashLineComments - #2508
Conversation
The second step agreed in JSQLParser#2502: with Feature.allowHashLineComments (default off) a `#` runs to end of line as a comment, unconditional like MySQL itself (no blank needed, `42#24` is a comment too); with the flag off a lone `#` stays the binary operator introduced in JSQLParser#2507, so neither reading silently replaces the other. Mechanics: under the flag SimpleCharStream rewrites a token-start `#` in the buffer to a character no other lexical rule starts with, so the dedicated HASH_LINE_COMMENT production wins the match for every `#` form while identifier and JSON-operator lexing of the default mode stay untouched (rewriting the buffer keeps the matcher's backup / re-read arithmetic intact, and GetImage() restores the `#` in the token image). Unquoted identifiers (and @@variables) end at their first `#` via their token actions, which re-lex the remainder as the comment. Quoted forms ("#", `#`, "a#b") keep their `#` in both modes. Under the flag the statement semantics are MySQL's: `SELECT #temp FROM t` comments out the rest of the line and fails, quoted "#temp" still parses. Closes JSQLParser#2499, supersedes JSQLParser#2502. Signed-off-by: Fu Dian <fudianchn@gmail.com>
|
|
||
| absoluteTokenBegin = totalCharsRead; | ||
|
|
||
| if (c == '#' && featureConfiguration != null |
There was a problem hiding this comment.
This is very smart, to put this here! It totally makes sense, but I never thought of it!
|
Very smart solution! Just add more Warning to the header of |
The file is maintained by hand on top of the JavaCC template and carries the in-buffer rewrite of a leading # in BeginToken(), which Feature.allowHashLineComments depends on. Per review on JSQLParser#2508.
|
@manticore-projects Added the warning to the header of |
It really bothers me, that I did not think of this myself. So simple, so elegant. Kudos! |
AI disclosure: this change was prepared with AI coding agents, reviewed and revised line by line by me.
What
MySQL
#line comments behind a feature switch, the second step agreed in #2502 (fixes #2499):Why / Root cause
One lexeme, two dialects: PostgreSQL reads
#as the binary operator from #2507, MySQL as a line comment. The special-token-or-token identity is static per production, and longest match outranks any post-match rewrite (#wordlexes as an identifier before an operator or comment rule could act), so a static comment rule would silently drop one of the readings — the "no good solution" from the #2502 discussion.How
Three pieces, all inert while
Feature.allowHashLineCommentsis off (the default):SimpleCharStreamrewrites a token-start#in its buffer to a character no other lexical rule starts with. Rewriting the buffer (instead of synthesizing reads) keeps the matcher's backup / re-read arithmetic intact, andGetImage()restores the#, so the comment token carries the original text.HASH_LINE_COMMENTproduction claims that character, self-contained likeLINE_COMMENT, and emits the comment as a special token. Because nothing else starts with the character, it wins the match for every#form (# c,#c,#>,#-, ...).@@variablesend at their first#via their token actions, which back up and re-lex the remainder as the comment — real MySQL reads42#24as42plus comment too.Quoted forms (
'#',"a#b",`#`) keep their#in both modes. Under the flag the statement semantics are MySQL's:SELECT #temp FROM tcomments out the rest of the line and fails, quoted"#temp"still parses.Follow-up: with this landing there are now three lexer-level switches (square brackets, backslash,
#comments). The dialect presets sketched in the #2502 discussion would be a small standalone follow-up if you want them — a mapping from DatabaseType to the existing Feature set, no mechanism changes.Testing
CCJSqlParserUtilTest: 2 new tests (both states of the same SQL, MySQL statement semantics).SelectASTTest: 1 new test (the comment is a special token carrying the original# ...image). All verified failing under three mutants: stream rewrite removed, identifier truncation removed,#dropped from the identifier start set. Full suite green (4935 tests).Performance
gradle jmh,JSQLParserBenchmark.parseSQLStatementsonperformance.sql,version=latest, 10 forks × 10 iterations (100 samples) on a 32-core host, interleaved master/branch (one polluted run excluded, CI ± 0.15):dff722bΔ ≤ 1% with overlapping CIs in 2 of 3 windows; the residual is the three added per-token branches (token start, image, identifier action), each guarded to a null-check for parses that never opt in.