fix: support MySQL # line comments (#2499) - #2502
Conversation
A '#' followed by a blank now lexes as a line comment, the MySQL form from issue JSQLParser#2499. '#' without a following blank keeps its current lexing: identifier start (SQL Server #temp, ##global) and the JSON operators #> / #>> are unchanged. Signed-off-by: Fu Dian <fudianchn@gmail.com>
Ooofffff! |
For completeness on the lexeme: besides the bitwise XOR row in Table 9.4, Mathematical Operators (
Sources: Mathematical Functions and Operators, Geometric Functions and Operators |
|
Honestly a tough call, we are doomed when we do and also when we don't.
I am in favor of 1) or 3), but I won't oppose when you prefer 2). You have provided so much good stuff that I trust your good judgement. |
|
My position up front: either leave it as is (closing this PR is fine with me), or fix it properly with a switch, so that no reading silently loses data. The proper fix is an architecture decision that is yours to make; I will not push it unilaterally.
The simplest decision. Put "never silently change semantics" first, and current master is not only acceptable but safer than this PR. First-hand runs on both sides (master
All three are correct under real MySQL semantics, so for the MySQL reading this PR fixes a real gap. The problem is the other reading: data silently lost, no error at all. Master is the only state where neither reading gets silently changed. The "I want it all" route. My gut reaction to such conflicts is "I want it all :)", so I searched the code for switch-like mechanisms and found the earlier cases:
This class of problem has come up more than once, so for maintaining these switches we could consider a Feature set + Dialect enum extension, in three phases as I expect it:
If it is not worth it. The flag mechanism has existed for over six years and one more flag is cheap, so the real question is not feasibility but which side the default takes. My preference is PG syntax by default, for two reasons:
With PG as the default, if real demand shows up on the MySQL side, one flag (off by default) enables |
|
Greetings, this would be the best indeed and you are right: token manipulation should work although there is one particular challenge here. SPECIAL_TOKEN vs. TOKEN, so far we have manipulated only TOKEN vs. TOKEN. JavaCC is very poorly equipped for such use-cases and we won't get any help from anyone. But if you want to do this, you have my full support. I would suggest starting to implement the Postgres |
First step up for review: #2507, the Postgres One behavior delta disclosed there: a lone Second step: |
|
I assume, this is obsolete after #2508? |
…nts (#2508) * feat(parser): support MySQL # line comments behind allowHashLineComments The second step agreed in #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 #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 #2499, supersedes #2502. Signed-off-by: Fu Dian <fudianchn@gmail.com> * docs(parser): add regeneration warning to SimpleCharStream header 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 #2508. --------- Signed-off-by: Fu Dian <fudianchn@gmail.com>
AI disclosure: this change was prepared with AI coding agents, reviewed and revised line by line by me.
What
Support MySQL
#line comments, fixing #2499:Both forms currently fail with a
ParseException:#lexes as an identifier and the comment text then fails as keywords (SELECT 1 # commentfails oncomment).Why / Root cause
LINE_COMMENTonly knows--and//. A#falls through to the identifier token (#is a legal identifier start and part character), so the comment text itself has to parse and does not.How
One additional alternation in the
LINE_COMMENTtoken: a#followed by a blank runs to end of line. The blank gate keeps every existing#lexing intact:#temp,##global,#$tab1#,a#bstay identifiers (Single-line comment in mysql statement does not support # symbol #1197, MySQL "#..." comments style not recognized #1695)#>/#>>JSON operators are untouched (>is not a blank;-#and<#>never start at the#)Scope
SELECT 1 #comment(no blank) still lexes as an identifier (alias), as before: treating it as a comment would collide with#tempstyle identifiers.#column followed by a blank (SELECT # FROM t) now starts a comment instead of parsing; no dialect defines such an unquoted column name.SELECT 5 # 3(PostgreSQL bitwise XOR, never supported) now parses asSELECT 5plus comment, the same waySELECT 1 -- 2already behaves.Testing
CCJSqlParserUtilTest: 5 new tests. The 3 comment form tests were verified failing on master; the 2 guard tests pin the identifier and JSON operator families (they fail when the blank gate is removed). Full suite green.Performance
gradle jmh,JSQLParserBenchmark.parseSQLStatementsonperformance.sql,version=latest, 10 forks × 10 iterations (100 samples) on a 32-core host:1e4e92beaf9884Δ +0.9% with overlapping 99.9% CIs → no regression.