Thread: BUG #2954: null is not checked against domain constraints in return clause

BUG #2954: null is not checked against domain constraints in return clause

From
"Sergiy Vyshnevetskiy"
Date:
The following bug has been logged online:

Bug reference:      2954
Logged by:          Sergiy Vyshnevetskiy
Email address:      serg@vostok.net
PostgreSQL version: 8.2.1
Operating system:   FreeBSD-6 stable
Description:        null is not checked against domain constraints in return
clause
Details:

#psql  = serg@[local]:5432 test
create domain "DInt" as int not null;
CREATE DOMAIN
#psql  = serg@[local]:5432 test
create or replace function test() returns "DInt" immutable strict language
plpgsql as $F$begin return null; end$F$;
CREATE FUNCTION
#psql  = serg@[local]:5432 test
select test() is null;
 ?column?
----------
 t
(1 запись)

#psql  = serg@[local]:5432 test

We should have gotten an error during execution of test().

Re: BUG #2954: null is not checked against domain constraints in return clause

From
Sergiy Vyshnevetskiy
Date:
I believe the bug to be here:

       /* Normal case for scalar results */
       estate->retval = exec_eval_expr(estate, stmt->expr,
                       &(estate->retisnull),
                       &(estate->rettype));

in exec_stmt_return() in pl_exec.c.

As I understand it, exec_eval_expr overwrites(!) estate->rettype instead
of casting the result to it.

What should be done is something like:

       Datum   value;
       Oid     valtype;

       value = exec_eval_expr(estate, stmt->expr, &(estate->retisnull),
&valtype);

       estate->retval = exec_cast_value(value, valtype, estate->rettype,
                        reqinput,
                        reqioparam,
                        reqtypmod,
                        estate->retisnull);


but where to get reqinput, reqioparam and reqtypmod? They should be
accessed through estate pointer, I think.
Sergiy Vyshnevetskiy <serg@vostok.net> writes:
> I believe the bug to be here:
>        /* Normal case for scalar results */
>        estate->retval = exec_eval_expr(estate, stmt->expr,
>                        &(estate->retisnull),
>                        &(estate->rettype));

> in exec_stmt_return() in pl_exec.c.

No, I don't think that code is wrong, the problem is that it's never
reached.  See the
        else if (!estate.retisnull)
line a bit further up.  Probably you can fix it with a small change to
check type strictness there.

            regards, tom lane