diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 8a9c0093c5..cc5eb73353 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.186 2007/01/30 18:02:22 tgl Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.187 2007/02/01 19:22:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -890,8 +890,27 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block) { 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), diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out index c4cad728b3..4acaaa4121 100644 --- a/src/test/regress/expected/domain.out +++ b/src/test/regress/expected/domain.out @@ -382,6 +382,22 @@ ERROR: domain pos_int does not allow null values -- and local variables are enforced correctly. 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; diff --git a/src/test/regress/sql/domain.sql b/src/test/regress/sql/domain.sql index 21940e0e61..411d64648a 100644 --- a/src/test/regress/sql/domain.sql +++ b/src/test/regress/sql/domain.sql @@ -309,6 +309,22 @@ execute s1(NULL); -- should fail 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;