parser: fold a top-level bare VALUES as a set-op LEFT operand - #57
Merged
Conversation
parse_statement dispatched a leading VALUES straight to parse_values_stmt()
with no set-operation fold, unlike the leading-SELECT path (parse_select_stmt
-> fold_set_operations) and the leading-'(' path (parse_parenthesized_query ->
fold_set_operations). So a top-level bare VALUES that is the LEFT operand of a
set operation silently dropped the operator and the entire right arm:
`VALUES (1) UNION SELECT 2` parsed to a bare ValuesStmt(1), discarding
`UNION SELECT 2` with no error. The symmetric forms already worked
(`SELECT 1 UNION VALUES (2)` and `(VALUES (1)) UNION SELECT 2`).
VALUES is a query primary and a legal set-op operand on either side (Postgres:
`VALUES (1) UNION SELECT 2` is a 2-row UNION). Route the top-level VALUES
through fold_set_operations, exactly like the other two leading-operand paths.
A standalone VALUES has no set-op tail, so the fold returns it unchanged and it
keeps its own trailing ORDER BY / LIMIT; a `VALUES ... UNION ...` binds a
trailing ORDER BY to the whole set operation.
This completes the VALUES-as-set-op-operand work of #53 (2548bcf, VALUES on the
RHS) and #56 (d7e4494, bare-VALUES RHS ORDER BY), which handled the RHS and
parenthesized cases but left the bare top-level LEFT operand behind.
Adds SetOpBareValuesLeftOperand (UNION/INTERSECT/EXCEPT),
SetOpBareValuesLeftOperandTrailingOrderBy, and a StandaloneValuesUnchangedByFold
control to test_precedence_regression.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FyKDAbMWGwiZq4iJx3imsg
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
parse_statementdispatched a leadingVALUESstraight toparse_values_stmt()with no set-operation fold — unlike the leading-SELECTpath (parse_select_stmt → fold_set_operations) and the leading-(path (parse_parenthesized_query → fold_set_operations). So a top-level bareVALUESthat is the LEFT operand of a set operation silently dropped the operator and the entire right arm:The symmetric forms already worked:
SELECT 1 UNION VALUES (2)→UnionStmt, and(VALUES (1)) UNION SELECT 2→UnionStmt. Only the bare-LEFT top-level case was left behind.VALUESis a query primary and a legal set-op operand on either side (Postgres:VALUES (1) UNION SELECT 2is a 2-row UNION). Found by the repeatable frontend-audit's regression sweep of the VALUES set-op work.Fix
Route the top-level
VALUESthroughfold_set_operations, exactly like the other two leading-operand paths:VALUES (1) UNION SELECT 2ValuesStmt(1)UNION(VALUES(1), SELECT 2)VALUES (1) INTERSECT SELECT 2ValuesStmt(1)INTERSECT(…)VALUES (1) UNION SELECT 2 ORDER BY 1ValuesStmt(1)UNION(…)with ORDER BY on the unionVALUES (3),(1) ORDER BY 1(standalone)A standalone
VALUEShas no set-op tail, sofold_set_operationsreturns it unchanged (and it keeps its own trailingORDER BY/LIMIT); aVALUES … UNION …binds a trailingORDER BYto the whole set operation.This completes the VALUES-as-set-op-operand work of #53 (VALUES on the RHS) and #56 (bare-VALUES RHS ORDER BY).
Tests
Adds
SetOpBareValuesLeftOperand(UNION/INTERSECT/EXCEPT),SetOpBareValuesLeftOperandTrailingOrderBy, and aStandaloneValuesUnchangedByFoldcontrol totest_precedence_regression. Full suite 37/37 green.