fix(bigquery): do not merge the rest of the query when angle brackets never balance - #975
Open
Jeremy-xuan wants to merge 1 commit into
Open
Jeremy-xuan wants to merge 1 commit into
Jeremy-xuan wants to merge 1 commit into
Conversation
… never balance
findClosingAngleBracketIndex() walked the token stream counting angle bracket
depth and returned the last index when the brackets never balanced. The caller
then merged everything from the type up to that index into a single IDENTIFIER.
For a nested type this could swallow the remainder of the query:
SELECT ARRAY /* c */ <ARRAY<INT64>>[1] FROM t;
produced a single identifier "ARRAY<INT64>>[1]FROMt ;", turning valid SQL into
silently broken SQL.
A comment between ARRAY/STRUCT and "<" is what makes the outer type fail to
combine, so the inner type is combined on its own; the remaining closing depth
is then even and ">>" drives the depth counter from 1 to -1, skipping 0, so the
loop never finds a closing bracket.
Returning -1 for "not found" and leaving the tokens untouched fixes it. The
tokens are now formatted as-is, which is not pretty but is correct, and can no
longer destroy the query. Types without comments are unaffected.
This branch has not been deployed
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.
fix(bigquery): do not merge the rest of the query when angle brackets never balance
What's wrong
For a nested parameterized type that has a comment between
ARRAY/STRUCTand<,BigQuery formatting silently destroyed the rest of the query:
FROM t;became a single identifierFROMt ;. A trailing alias goes the same way:No error is raised: valid SQL goes in, broken SQL comes out. Line comments do the
same (
ARRAY -- c\n<ARRAY<INT64>>[1]).Root cause
findClosingAngleBracketIndex()counts angle-bracket depth and, if the bracketsnever balance, returns the last token index:
The caller then does
tokens.slice(i, endIndex + 1)and.join(''), so "not found"means "merge everything up to the end of the query into one identifier", and
i = endIndexskips the remaining tokens.Two details decide whether it triggers:
ARRAYfail the adjacency test(
tokens[i + 1]?.text === '<'), so only the innerARRAYis combined — onits own, and starting at a depth that goes wrong.
level === 0can never fire at the starting
<.">>"then subtracts 2; whenlevelisexactly 1 it lands on −1, skipping 0 forever, and the loop falls through to
the
tokens.length - 1fallback. This is why the nested depth has to be even(depth 2 and 4 corrupt, depth 1 and 3 do not) and why writing
> >as twotokens does not trigger it.
The fix
Return −1 for "not found" and let the caller leave the tokens alone:
The type is then formatted as-is.
ARRAY /* c */ < ARRAY < INT64 >> [1]is notpretty, but it is correct and the query survives — the failure becomes cosmetic
instead of destructive.
Tests
Four tests in
test/bigquery.test.tscover a nested type with a block comment, witha line comment, with a trailing alias, and a nested type without comments (to show
that path is untouched). Three of them fail on
master.Regression check
Comparing
masteragainst the fix over 822 inputs (800 SQL literals harvested fromthe test suite plus 22 targeted nested-type cases), with "the formatter must not
create or destroy words" (word-multiset preservation against the input) as the
criterion: 725 byte-identical, 9 improved, 0 regressions. Types without comments
are byte-identical, and only BigQuery has this slice-and-join path — the other 13
dialects tested behave the same before and after.
Not addressed here
STRUCT<nested INT64 OPTIONS(...)>loses the space beforeOPTIONS([FORMATTING] Space between type and options removed in nested BigQuery fields #619) is adifferent mechanism in the same function (
formatTypeDefToken()only padsIDENTIFIERandCOMMA). This change neither fixes nor worsens it. It deservesits own issue.