Fix issue #217: Wrap FuncCall arguments in parentheses when using :: cast syntax #227
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.
Fix #217: Wrap FuncCall arguments in parentheses when using :: cast syntax
Summary
Fixes a bug where double type casts with the
::operator were being deparsed incorrectly due to operator precedence issues. When a FuncCall (likeAT TIME ZONE) was cast using the::shorthand syntax, the cast would bind to the wrong operand.Example of the bug:
SELECT CAST(t.date AT TIME ZONE 'America/New_York' AS text)::date FROM tbl tSELECT CAST(t.date AT TIME ZONE 'America/New_York'::text AS date) FROM tbl AS t::textwas binding to'America/New_York'instead of the entireCAST(...)expressionThe fix:
When using the
::cast shorthand syntax with a FuncCall argument, wrap the FuncCall in parentheses:(t.date AT TIME ZONE 'America/New_York')::textChanges:
TypeCastfunction inpackages/deparser/src/deparser.ts(13 lines changed)Review & Testing Checklist for Human
SELECT CAST(t.date AT TIME ZONE 'America/New_York' AS text)::date FROM tbl tnow deparses correctly and can be re-parsed without AST changes (parse → deparse → reparse should produce identical AST)'123'::intand'1 day'::intervalstill work correctly without unnecessary parenthesespublic.gen_random_uuid()::textnow becomes(public.gen_random_uuid())::text. Verify this is correct and doesn't break any downstream consumersTest Plan
cd packages/deparser && yarn test(all 654 tests should pass ✓)Notes
Devin Session: https://app.devin.ai/sessions/111a29019c274f83a61a873f35081622
Requested by: Dan Lynch (@pyramation)