From b113894944c8c86ca584cbba4585a929681da72a Mon Sep 17 00:00:00 2001 From: zzoraemon043 <195147269+zzoraemon043@users.noreply.github.com> Date: Mon, 19 Oct 2026 09:56:02 +0800 Subject: [PATCH] Accept schema-qualified operator names in CREATE / DROP OPERATOR Fixes #997 --- src/lexer/disambiguateTokens.ts | 15 +++++++++++++++ test/postgresql.test.ts | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/lexer/disambiguateTokens.ts b/src/lexer/disambiguateTokens.ts index f8c42be3bb..9a019be41d 100644 --- a/src/lexer/disambiguateTokens.ts +++ b/src/lexer/disambiguateTokens.ts @@ -22,6 +22,7 @@ import { isReserved, Token, TokenType } from './token.js'; export function disambiguateTokens(tokens: Token[]): Token[] { return tokens .map(propertyNameKeywordToIdent) + .map(propertyNameOperatorToIdent) .map(keywordAliasAfterAs) .map(funcNameToIdent) .map(dataTypeToParameterizedDataType) @@ -43,6 +44,20 @@ const propertyNameKeywordToIdent = (token: Token, i: number, tokens: Token[]): T return token; }; +const propertyNameOperatorToIdent = (token: Token, i: number, tokens: Token[]): Token => { + if (token.type === TokenType.OPERATOR) { + const prevToken = prevNonCommentToken(tokens, i); + const nextToken = nextNonCommentToken(tokens, i); + if ( + prevToken?.type === TokenType.PROPERTY_ACCESS_OPERATOR && + nextToken?.type === TokenType.OPEN_PAREN + ) { + return { ...token, type: TokenType.IDENTIFIER, text: token.raw }; + } + } + return token; +}; + /** * Some dialects allow reserved words as aliases, as in `SELECT id AS set FROM tbl`. * Such a word is tokenized as a RESERVED_* token, which the parser then treats as diff --git a/test/postgresql.test.ts b/test/postgresql.test.ts index e8e99adfea..ed959ee444 100644 --- a/test/postgresql.test.ts +++ b/test/postgresql.test.ts @@ -225,6 +225,23 @@ describe('PostgreSqlFormatter', () => { }); // Issue #711 + // Issue #997 + it('supports schema-qualified operator names', () => { + expect( + format( + 'create operator pg_catalog.!! (rightarg = tsquery, function = pg_catalog.tsquery_not);' + ) + ).toBe(dedent` + create operator pg_catalog.!! ( + rightarg = tsquery, + function = pg_catalog.tsquery_not + ); + `); + expect(format('DROP OPERATOR pg_catalog.!! (none, tsquery);')).toBe(dedent` + DROP OPERATOR pg_catalog.!! (none, tsquery); + `); + }); + it('supports OPERATOR() syntax', () => { expect(format(`SELECT foo OPERATOR(public.===) bar;`)).toBe(dedent` SELECT