From: | Andrew Gierth <andrew(at)tao11(dot)riddles(dot)org(dot)uk> |
---|---|
To: | pgsql-hackers(at)postgresql(dot)org |
Subject: | A really subtle lexer bug |
Date: | 2018-08-20 07:38:52 |
Message-ID: | 87va851ppl.fsf@news-spur.riddles.org.uk |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
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)
From | Date | Subject | |
---|---|---|---|
Next Message | David Rowley | 2018-08-20 07:45:35 | Calculate total_table_pages after set_base_rel_sizes() |
Previous Message | Tatsuro Yamada | 2018-08-20 06:51:07 | Re: Fix help option of contrib/oid2name |