From: Andrew Gierth <andrew@tao11.riddles.org.uk>
To: pgsql-hackers@postgresql.org
Subject: A really subtle lexer bug
Date: Mon, 20 Aug 2018 08:38:52 +0100
Message-ID: <87va851ppl.fsf@news-spur.riddles.org.uk> (raw)
Currently in PG, the precedence of = and <> is supposed to be equal, and
the precedence of unary - is very high.
So, (true=1 between 1 and 1) parses as ((true)=(1 between 1 and 1)),
and (true=-1 between 1 and 1) parses as ((true)=((-1) between 1 and 1)).
All good so far.
(true<>-1 between 1 and 1) parses as ((true<>(-1)) between 1 and 1). ???
The fault here is in the lexer. The input "<>-" is being lexed as an Op
followed by '-' rather than as NOT_EQUAL followed by '-' because it
looks like a match for a multi-character operator, with the - being
thrown back into the input afterwards. So the precedence of <> gets
inflated to that of Op, which is higher than BETWEEN.
More seriously, this also breaks named arguments:
create function f(a integer) returns integer language sql
as $$ select a; $$;
select f(a => 1); -- works
select f(a => -1); -- works
select f(a =>-1); -- ERROR: column "a" does not exist
I guess the fix is to extend the existing special case code that checks
for one character left after removing trailing [+-] and also check for
the two-character ops "<>" ">=" "<=" "=>" "!=".
--
Andrew (irc:RhodiumToad)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: andrew@tao11.riddles.org.uk
Subject: Re: A really subtle lexer bug
In-Reply-To: <87va851ppl.fsf@news-spur.riddles.org.uk>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox