Re: BUG #2948: default null values for not-null domains - Mailing list pgsql-bugs
From | Tom Lane |
---|---|
Subject | Re: BUG #2948: default null values for not-null domains |
Date | |
Msg-id | 22892.1170358094@sss.pgh.pa.us Whole thread Raw |
In response to | Re: BUG #2948: default null values for not-null domains (Sergiy Vyshnevetskiy <serg@vostok.net>) |
Responses |
Re: BUG #2948: default null values for not-null domains
|
List | pgsql-bugs |
Sergiy Vyshnevetskiy <serg@vostok.net> writes: > If input function IS strict then nulls are ALWAYS accepted. > If input function IS NOT strict then nulls MIGHT be rejectted. > And the patch is much more simple now (attached). > Is that it? Almost right. exec_assign_value() thinks its isNull argument is the null flag for the *source* value (not sure why it's pass by reference). As you set it up, var->isnull would be aliased by *isNull, which might manage to break things within that function if the code were ever rearranged. Also, some comments are usually a good idea (if the purpose were obvious, it'd have been right the first time, no?), and you always need to check the regression tests --- it turns out that the wrong behavior was actually being exposed by the tests. Patch as-applied is attached. regards, tom lane Index: src/pl/plpgsql/src/pl_exec.c =================================================================== RCS file: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v retrieving revision 1.186 diff -c -r1.186 pl_exec.c *** src/pl/plpgsql/src/pl_exec.c 30 Jan 2007 18:02:22 -0000 1.186 --- src/pl/plpgsql/src/pl_exec.c 1 Feb 2007 19:10:51 -0000 *************** *** 890,897 **** --- 890,916 ---- { if (var->default_val == NULL) { + /* Initially it contains a NULL */ var->value = (Datum) 0; var->isnull = true; + /* + * If needed, give the datatype a chance to reject + * NULLs, by assigning a NULL to the variable. + * We claim the value is of type UNKNOWN, not the + * var's datatype, else coercion will be skipped. + * (Do this before the notnull check to be + * consistent with exec_assign_value.) + */ + if (!var->datatype->typinput.fn_strict) + { + bool valIsNull = true; + + exec_assign_value(estate, + (PLpgSQL_datum *) var, + (Datum) 0, + UNKNOWNOID, + &valIsNull); + } if (var->notnull) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), Index: src/test/regress/expected/domain.out =================================================================== RCS file: /cvsroot/pgsql/src/test/regress/expected/domain.out,v retrieving revision 1.38 diff -c -r1.38 domain.out *** src/test/regress/expected/domain.out 6 Oct 2006 17:14:01 -0000 1.38 --- src/test/regress/expected/domain.out 1 Feb 2007 19:10:51 -0000 *************** *** 383,388 **** --- 383,404 ---- create function doubledecrement(p1 pos_int) returns pos_int as $$ declare v pos_int; begin + return p1; + end$$ language plpgsql; + select doubledecrement(3); -- fail because of implicit null assignment + ERROR: domain pos_int does not allow null values + CONTEXT: PL/pgSQL function "doubledecrement" line 2 during statement block local variable initialization + create or replace function doubledecrement(p1 pos_int) returns pos_int as $$ + declare v pos_int := 0; + begin + return p1; + end$$ language plpgsql; + select doubledecrement(3); -- fail at initialization assignment + ERROR: value for domain pos_int violates check constraint "pos_int_check" + CONTEXT: PL/pgSQL function "doubledecrement" line 2 during statement block local variable initialization + create or replace function doubledecrement(p1 pos_int) returns pos_int as $$ + declare v pos_int := 1; + begin v := p1 - 1; return v - 1; end$$ language plpgsql; Index: src/test/regress/sql/domain.sql =================================================================== RCS file: /cvsroot/pgsql/src/test/regress/sql/domain.sql,v retrieving revision 1.21 diff -c -r1.21 domain.sql *** src/test/regress/sql/domain.sql 5 Apr 2006 22:11:58 -0000 1.21 --- src/test/regress/sql/domain.sql 1 Feb 2007 19:10:51 -0000 *************** *** 310,315 **** --- 310,331 ---- create function doubledecrement(p1 pos_int) returns pos_int as $$ declare v pos_int; begin + return p1; + end$$ language plpgsql; + + select doubledecrement(3); -- fail because of implicit null assignment + + create or replace function doubledecrement(p1 pos_int) returns pos_int as $$ + declare v pos_int := 0; + begin + return p1; + end$$ language plpgsql; + + select doubledecrement(3); -- fail at initialization assignment + + create or replace function doubledecrement(p1 pos_int) returns pos_int as $$ + declare v pos_int := 1; + begin v := p1 - 1; return v - 1; end$$ language plpgsql;
pgsql-bugs by date: