Skip to content

PostgreSqlDialect: *= and @@@ are split into two tokens, #2809

Open

Description

@soulstompp

version 0.63.0, PostgreSqlDialect.

PostgreSQL's lexer reads a run of operator characters as one operator (manual, "Lexical Structure", "Operators"; src/backend/parser/scan.l). However, sqlparser only recognizes a specific list, so operators end up split.

The composite type comparison operators (manual, "Composite Type Comparison")::

SELECT a *= b    -- Expected: an expression, found: =
SELECT a *<> b   -- Expected: an expression, found: <>
SELECT a *< b    -- Expected: an expression, found: <
SELECT a *<= b   -- Expected: an expression, found: <=
SELECT a *> b    -- Expected: an expression, found: >
SELECT a *>= b   -- Expected: an expression, found: >=

The @@@ operator doesn't cause an error but is parsed incoretory.

SELECT a @@@ b   -- parses as a @@ (@b); to_string() gives: SELECT a @@ @b
`SELECT 'a b'::tsvector @@@ 'a'::tsquery;   -- t
SELECT 'a b'::tsvector @@ @ 'a'::tsquery;  -- ERROR: operator does not exist

I ran into similar issues trying to write it as OPERATOR() which failed similiarly:

SELECT a OPERATOR(pg_catalog.*=) b    -- Expected: ), found: =
SELECT a OPERATOR(pg_catalog.@@@) b   -- Expected: ), found: @

The * operators are valid on PostgreSQL 18.6, on values of a record type:

SELECT a *= b, a = b, a *< b, a *<> b
FROM (SELECT ROW(1.0) a, ROW(1.00) b) s;   -- f | t | f | t

How to reproduce:

use sqlparser::{dialect::PostgreSqlDialect, parser::Parser};
for sql in ["SELECT a *= b", "SELECT a @@@ b"] {
    println!("{:?}", Parser::parse_sql(&PostgreSqlDialect {}, sql).map(|s| s
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions