Conversation
Signed-off-by: 付典 <fudianchn@gmail.com>
|
I do appreciate your work, but I think we are overshooting here. |
Signed-off-by: 付典 <fudianchn@gmail.com>
Signed-off-by: 付典 <fudianchn@gmail.com>
|
The revision separates opaque capture from syntax-error recovery. Generic Opaque capture starts at the first token. H2's Unknown roots and existing explicit opaque branches still cannot certify validity in an unknown dialect. Their capture compatibility remains; extensions sharing a recognized root may now raise an error where the former fallback captured them. The affected malformed IF and later SELECT/FROM cases also now use error placeholders instead of partial ASTs with unsupported capture disabled and error recovery enabled. These acceptance/recovery changes are documented. The private dispatch predicate must stay aligned with future statement roots. All 62 regression/guard records pass. The same tests produce 46 failures and 16 passing preservation guards on each of the original parent, original PR head, and current master. Independent boundary probes and isolated routing/boundary mutations verify the guards. Local Gradle/Maven verification passes; the project SIMPLE JMH benchmark showed no measurable regression in three interleaved forks per version. Other unsupported/recovery workloads were not benchmarked. |
AI disclosure: this change was prepared with AI coding agents, reviewed and revised line by line by me.
What
UnsupportedStatement error recovery now retains tokens already consumed by a failed production and avoids dereferencing an unassigned statement. Single-statement IF recovery returns the recovered statement instead of a partially parsed IF node.
Why
CCJSqlParserUtil.parse("INSERT INTO t (a", p -> p.withUnsupportedStatements(true))throws JSQLParserException with a NullPointerException cause. Statement-list recovery can return an empty UnsupportedStatement for the same input, losing the SQL needed to inspect or handle the failure.How
Root cause
A nested production can consume tokens and throw before SingleStatement returns an AST. The single-statement catch calls
stm.toString()while stm is null. All three recovery catches combine AST text with only the unconsumed suffix, so consumed tokens are lost or rewritten. The single IF return also prioritizes its prior AST over the recovered result.Testing
bb55bb9d, 35 fail and 14 normal controls pass; the fix passes all 49. Cases cover single and list parsing, configured Reader/InputStream parsers, EOF/separators, first and later failures, following statements, original token case/punctuation, quoted semicolons, recovery options, typed SELECT/IF nodes and parse/deparse behavior.Behavior notes
Verification of the original issue
No existing issue is linked. The failure was reproduced on upstream master
bb55bb9de8377de9880b14e4fe3b3cc94bf63498; the locally verified fixed commit isb7c937df24869b84e8900049211e0f158e56b063. This builds on Andreas Reichel's UnsupportedStatement capture in063d2442, while preserving the strict single-statement EOF contract restored by #2733. Thanks to Andreas Reichel for establishing that recovery path; this change completes its handling of already-consumed tokens and does not claim to fix #1984 or #2681 again.The first two return UnsupportedStatement with text
INSERT INTO t ( aandUPDATE t SET, respectively. The third retainsSELECT 0, the complete unsupported INSERT token sequence andSELECT 2as three separate statements.