diff --git a/src/languages/mariadb/likeMariaDb.ts b/src/languages/mariadb/likeMariaDb.ts index 63c7cba1f7..1c43361417 100644 --- a/src/languages/mariadb/likeMariaDb.ts +++ b/src/languages/mariadb/likeMariaDb.ts @@ -14,6 +14,15 @@ export function postProcess(tokens: Token[]) { // This is VALUES() function, not VALUES clause return { ...token, type: TokenType.RESERVED_FUNCTION_NAME }; } + // INTERVAL is both a comparison function (INTERVAL(N, ...)) and a + // duration keyword (INTERVAL n DAY). Without '(', keep it as a keyword + // so keywordCase applies; otherwise disambiguateTokens would demote it + // to IDENTIFIER (see #985). + if (token.type === TokenType.RESERVED_FUNCTION_NAME && token.text === 'INTERVAL') { + if (nextToken.text !== '(') { + return { ...token, type: TokenType.RESERVED_KEYWORD }; + } + } return token; }); } diff --git a/test/mysql.test.ts b/test/mysql.test.ts index e6bcd37af9..0b654d4d6e 100644 --- a/test/mysql.test.ts +++ b/test/mysql.test.ts @@ -98,6 +98,27 @@ describe('MySqlFormatter', () => { `); }); + it('applies keywordCase to INTERVAL duration expressions (#985)', () => { + expect( + format(`select now() - interval 30 day; select date_sub(now(), interval 30 day);`, { + keywordCase: 'upper', + }) + ).toBe(dedent` + SELECT + now() - INTERVAL 30 day; + + SELECT + date_sub(now(), INTERVAL 30 day); + `); + }); + + it('still treats INTERVAL(...) as a function name', () => { + expect(format(`select interval(55, 0, 50, 100);`, { functionCase: 'upper' })).toBe(dedent` + select + INTERVAL(55, 0, 50, 100); + `); + }); + it('formats ALTER TABLE ... ALTER COLUMN', () => { expect( format(