Skip to content

Commit 5d29091

Browse files
committed
Support array subscript operator in BigQuery
Refs #243
1 parent 1bb5d23 commit 5d29091

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

src/languages/bigquery.formatter.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Formatter from 'src/core/Formatter';
22
import Tokenizer from 'src/core/Tokenizer';
3-
import { EOF_TOKEN, type Token } from 'src/core/token';
3+
import { EOF_TOKEN, TokenType, type Token } from 'src/core/token';
44
import { dedupe } from 'src/utils';
55

66
/**
@@ -858,7 +858,27 @@ export default class BigQueryFormatter extends Formatter {
858858
}
859859
}
860860

861-
function preprocess(tokens: Token[]) {
861+
function preprocess(tokens: Token[]): Token[] {
862+
return detectArraySubscripts(combineParameterizedTypes(tokens));
863+
}
864+
865+
// Converts OFFSET token inside array from RESERVED_COMMAND to RESERVED_KEYWORD
866+
// See: https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#array_subscript_operator
867+
function detectArraySubscripts(tokens: Token[]) {
868+
let prevToken = EOF_TOKEN;
869+
return tokens.map(token => {
870+
if (token.value === 'OFFSET' && prevToken.value === '[') {
871+
prevToken = token;
872+
return { ...token, type: TokenType.RESERVED_KEYWORD };
873+
} else {
874+
prevToken = token;
875+
return token;
876+
}
877+
});
878+
}
879+
880+
// Combines multiple tokens forming a parameterized type like STRUCT<ARRAY<INT64>> into a single token
881+
function combineParameterizedTypes(tokens: Token[]) {
862882
const processed: Token[] = [];
863883
for (let i = 0; i < tokens.length; i++) {
864884
const token = tokens[i];

test/bigquery.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,25 @@ describe('BigQueryFormatter', () => {
145145
varBigdecimal BIGDECIMAL(1, 1);
146146
`);
147147
});
148+
149+
// Regression test for issue #243
150+
it('supports array subscript operator', () => {
151+
expect(
152+
format(`
153+
SELECT item_array[OFFSET(1)] AS item_offset,
154+
item_array[ORDINAL(1)] AS item_ordinal,
155+
item_array[SAFE_OFFSET(6)] AS item_safe_offset,
156+
item_array[SAFE_ORDINAL(6)] AS item_safe_ordinal
157+
FROM Items;
158+
`)
159+
).toBe(dedent`
160+
SELECT
161+
item_array[OFFSET(1)] AS item_offset,
162+
item_array[ORDINAL(1)] AS item_ordinal,
163+
item_array[SAFE_OFFSET(6)] AS item_safe_offset,
164+
item_array[SAFE_ORDINAL(6)] AS item_safe_ordinal
165+
FROM
166+
Items;
167+
`);
168+
});
148169
});

0 commit comments

Comments
 (0)