While looking at fixing the multiple-evaluation issue in IN and BETWEEN
discussed a while ago, I realized that the current assumption that only
one CaseTestExpr placeholder needs to be valid at any given time is not
true.
Here's a bit contrived example:
CREATE FUNCTION evileq (timestamptz, int4) returns boolean AS $$
SELECT case $2 WHEN length($1::text) THEN true ELSE false END;
$$ language sql;
CREATE OPERATOR = (procedure = evileq, leftarg = timestamptz, rightarg =
int4);
postgres=# SELECT now() = 29, CASE now() WHEN 29 THEN 'foo' ELSE 'bar' END;
?column? | case
----------+------
t | bar
(1 row)
Direct call to the operator, "now () = 29" returns true, but when used
in CASE-WHEN, which implicitly does the same comparison, the result is
false. Admittedly that's pretty far-fetched, but nevertheless it's a bug.
As part of the BETWEEN/IN fix, I was going to refactor CaseTestExpr and
CoerceToDomainValue placeholder node types into one generic placeholder
node. BETWEEN needs three placeholder slots in the worst case [*], and
now it seems that we need to handle an arbitrary number of simultaneous
placeholders even for CASE-WHEN.
So I'm going to put the BETWEEN/IN fix aside for now, and refactor the
placeholder infrastructure to handle several simultaneous placeholders,
and replace CaseTestExpr and CoerceToDomainValue with it. Actually
AggRef and WindowFunc nodes look a lot like CaseTestExpr and
CoerceToDomainValue too, but I'm a bit scared of touching those.
PS. This is all 9.2 material, in case you're wondering. We're talking
about pretty big patches.
[*] a BETWEEN SYMMETRIC b AND c is handled as "(a <= b AND a >= c) OR (a
>= b AND a <= c)", leading to multiple evaluation of all three operands
if placeholders are not used
--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers