Re: CASE Statement - Order of expression processing - Mailing list pgsql-general

From Stefan Drees
Subject Re: CASE Statement - Order of expression processing
Date
Msg-id 51BF7B6A.50301@drees.name
Whole thread Raw
In response to CASE Statement - Order of expression processing  (Andrea Lombardoni <andrea@lombardoni.ch>)
Responses Re: CASE Statement - Order of expression processing  (Albe Laurenz <laurenz.albe@wien.gv.at>)
Re: CASE Statement - Order of expression processing  (Albe Laurenz <laurenz.albe@wien.gv.at>)
List pgsql-general
On 2013-06-17 22:17 +02:00, Andrea Lombardoni wrote:
> I observed the following behaviour (I tested the following statements in
> 9.0.4, 9.0.5 and 9.3beta1):
>
> $ psql template1
> template1=# SELECT CASE WHEN 0=0 THEN 0 ELSE 1/0 END;
>   case
> ------
>      0
> (1 row)
>
> template1=# SELECT CASE WHEN 1=0 THEN 0 ELSE 1/0 END;
> ERROR:  division by zero
>
> In this case the CASE behaves as expected.
>
> But in the following expression:
>
> template1=# SELECT CASE WHEN (SELECT 0)=0 THEN 0 ELSE 1/0 END;
> ERROR:  division by zero
>
> (Just to be sure, a "SELECT (SELECT 0)=0;" returns true)
>
> It seems that when the "CASE WHEN expression" is a query, the evaluation
> order changes.
> According to the documentation, this behaviour is wrong.
>
> http://www.postgresql.org/docs/9.0/static/sql-expressions.html (4.2.13.
> Expression Evaluation Rules):
> "When it is essential to force evaluation order, a CASE construct (see
> Section 9.16) can be used. "
>
> http://www.postgresql.org/docs/9.0/static/functions-conditional.html
> (9.16.1. CASE):
> "If the condition's result is true, the value of the CASE expression is
> the result that follows the condition, and the remainder of the CASE
> expression is not processed."
> "A CASE expression does not evaluate any subexpressions that are not
> needed to determine the result."
>
> Did I miss anything? Or is this really a bug?

with psql v9.2.4:

pg924=# SELECT CASE WHEN (SELECT 0) = 0 THEN 0 END;
  case
------
     0
(1 row)

is like documented.

pg924=#  SELECT CASE WHEN (SELECT 0) != 0 THEN 0 END;
  case
------

(1 row)

also like documented "If no match is found, the result of the ELSE
clause (or a null value) is returned."

pg924=#  SELECT CASE WHEN (SELECT 0) != 0 THEN 0 ELSE 1 END;
  case
------
     1
(1 row)

also ok, now it returns the result of the ELSE clause.

So maybe "The data types of all the result expressions must be
convertible to a single output type. See Section 10.5 for more details."
The checking of convertibility is eagerly tried in case there is a
SELECT expression to be evaluated in the condition?

A simple arithmetic expression does not trigger this:

pg924=#  SELECT CASE WHEN (0+0) != 0 THEN 1/0 ELSE 1 END;
  case
------
     1
(1 row)

Now is a subquery "(SELECT 1) != 1" a valid expression for a condition
:-?) or does it trigger some unwanted checking:

pg924=#  SELECT CASE WHEN (SELECT 1) != 1 THEN 1/0 END;
ERROR:  division by zero

A subquery inside a "matched" ELSE clause (e.g.) does not trigger
evaluation of the 1/0 inside the unmatched WHEN clause:

pg924=#  SELECT CASE WHEN 1 != 1 THEN 1/0 ELSE ((SELECT 1)=1)::integer END;
  case
------
     1
(1 row)

here the 1/0 is happily ignored.

So it's us two already with a blind spot, or it's a bug.

All the best,
Stefan.



pgsql-general by date:

Previous
From: "Joshua D. Drake"
Date:
Subject: Re: PSA: If you are running Precise/12.04 upgrade your kernel.
Next
From: jmfox180
Date:
Subject: Re: pg_upgrade only to 9.0 ?