Home Explore Blog CI



postgresql

33th chunk of `doc/src/sgml/syntax.sgml`
14f07d4162ed9d3265f50c55148f735664764d3591093a9d0000000100000fa1
 allowed by the laws of Boolean algebra.
   </para>

   <para>
    When it is essential to force evaluation order, a <literal>CASE</literal>
    construct (see <xref linkend="functions-conditional"/>) can be
    used.  For example, this is an untrustworthy way of trying to
    avoid division by zero in a <literal>WHERE</literal> clause:
<programlisting>
SELECT ... WHERE x &gt; 0 AND y/x &gt; 1.5;
</programlisting>
    But this is safe:
<programlisting>
SELECT ... WHERE CASE WHEN x &gt; 0 THEN y/x &gt; 1.5 ELSE false END;
</programlisting>
    A <literal>CASE</literal> construct used in this fashion will defeat optimization
    attempts, so it should only be done when necessary.  (In this particular
    example, it would be better to sidestep the problem by writing
    <literal>y &gt; 1.5*x</literal> instead.)
   </para>

   <para>
    <literal>CASE</literal> is not a cure-all for such issues, however.
    One limitation of the technique illustrated above is that it does not
    prevent early evaluation of constant subexpressions.
    As described in <xref linkend="xfunc-volatility"/>, functions and
    operators marked <literal>IMMUTABLE</literal> can be evaluated when
    the query is planned rather than when it is executed.  Thus for example
<programlisting>
SELECT CASE WHEN x &gt; 0 THEN x ELSE 1/0 END FROM tab;
</programlisting>
    is likely to result in a division-by-zero failure due to the planner
    trying to simplify the constant subexpression,
    even if every row in the table has <literal>x &gt; 0</literal> so that the
    <literal>ELSE</literal> arm would never be entered at run time.
   </para>

   <para>
    While that particular example might seem silly, related cases that don't
    obviously involve constants can occur in queries executed within
    functions, since the values of function arguments and local variables
    can be inserted into queries as constants for planning purposes.
    Within <application>PL/pgSQL</application> functions, for example, using an
    <literal>IF</literal>-<literal>THEN</literal>-<literal>ELSE</literal> statement to protect
    a risky computation is much safer than just nesting it in a
    <literal>CASE</literal> expression.
   </para>

   <para>
    Another limitation of the same kind is that a <literal>CASE</literal> cannot
    prevent evaluation of an aggregate expression contained within it,
    because aggregate expressions are computed before other
    expressions in a <literal>SELECT</literal> list or <literal>HAVING</literal> clause
    are considered.  For example, the following query can cause a
    division-by-zero error despite seemingly having protected against it:
<programlisting>
SELECT CASE WHEN min(employees) > 0
            THEN avg(expenses / employees)
       END
    FROM departments;
</programlisting>
    The <function>min()</function> and <function>avg()</function> aggregates are computed
    concurrently over all the input rows, so if any row
    has <structfield>employees</structfield> equal to zero, the division-by-zero error
    will occur before there is any opportunity to test the result of
    <function>min()</function>.  Instead, use a <literal>WHERE</literal>
    or <literal>FILTER</literal> clause to prevent problematic input rows from
    reaching an aggregate function in the first place.
   </para>
  </sect2>
 </sect1>

 <sect1 id="sql-syntax-calling-funcs">
  <title>Calling Functions</title>

   <indexterm zone="sql-syntax-calling-funcs">
    <primary>notation</primary>
    <secondary>functions</secondary>
   </indexterm>

   <para>
    <productname>PostgreSQL</productname> allows functions that have named
    parameters to be called using either <firstterm>positional</firstterm> or
    <firstterm>named</firstterm> notation.  Named notation is especially
    useful for functions that have a large number of parameters, since it
    makes the associations between parameters and actual arguments more
    explicit and reliable.
    In positional

Title: Limitations of CASE and Safe Alternatives
Summary
This section details the limitations of using `CASE` constructs to control evaluation order, particularly regarding early evaluation of constant subexpressions and aggregate expressions. It illustrates that even with `CASE`, division-by-zero errors can still occur due to the planner simplifying constant subexpressions or aggregate expressions being computed before the `CASE` condition is checked. It advises using `IF-THEN-ELSE` statements within PL/pgSQL functions for safer computation and using `WHERE` or `FILTER` clauses to prevent problematic input rows from reaching aggregate functions.