-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Description
EXCEPT ALL, EXCEPT DISTINCT, MINUS ALL, and MINUS DISTINCT modifiers are silently dropped during parsing. The parser accepts the modifier syntax but does not pass the captured modifier string to the ExceptOp and MinusOp constructors.
Reproducer
String sql = "SELECT a FROM t1 EXCEPT ALL SELECT a FROM t2";
Statement stmt = CCJSqlParserUtil.parse(sql);
System.out.println(stmt.toString());
// Expected: SELECT a FROM t1 EXCEPT ALL SELECT a FROM t2
// Actual: SELECT a FROM t1 EXCEPT SELECT a FROM t2The same issue affects MINUS ALL:
String sql = "SELECT a FROM t1 MINUS ALL SELECT a FROM t2";
Statement stmt = CCJSqlParserUtil.parse(sql);
System.out.println(stmt.toString());
// Expected: SELECT a FROM t1 MINUS ALL SELECT a FROM t2
// Actual: SELECT a FROM t1 MINUS SELECT a FROM t2Root Cause
In JSqlParserCC.jjt, the SetOperationList rule captures the modifier via modifier=SetOperationModifier() but constructs MinusOp and ExceptOp with their no-arg constructors (which default to empty string), discarding the modifier:
<K_MINUS> [ modifier=SetOperationModifier() ] { MinusOp minus = new MinusOp(); ... }
<K_EXCEPT> [ modifier=SetOperationModifier() ] { ExceptOp except = new ExceptOp(); ... }
Compare with UnionOp and IntersectOp which correctly pass the modifier:
<K_UNION> [ modifier=SetOperationModifier() ] { UnionOp union = new UnionOp(modifier); ... }
<K_INTERSECT> [ modifier=SetOperationModifier() ] { IntersectOp intersect = new IntersectOp(modifier); ... }
Additionally, the modifier variable was not reset between iterations of the set-operation loop, causing modifiers to leak from one operator to the next (e.g., UNION ALL ... EXCEPT would incorrectly make the EXCEPT inherit ALL).
Impact
- Semantic correctness:
EXCEPT ALLpreserves duplicates whileEXCEPTremoves them. Silently dropping theALLmodifier changes query semantics. - Round-trip fidelity:
parse(sql).toString()does not reproduce the original SQL.
Affected versions
Current master (regression introduced in commit 5fe938bc which refactored SetOperationModifier handling for the CORRESPONDING feature).
Fix
- Pass
modifiertoMinusOpandExceptOpconstructors - Reset
modifier = nullat the start of each set-operation loop iteration
A PR with the fix and regression tests will follow.