]> granicus.if.org Git - postgresql/commitdiff
Fix plpgsql so that when a local variable has no initial-value expression,
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 1 Feb 2007 19:22:07 +0000 (19:22 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 1 Feb 2007 19:22:07 +0000 (19:22 +0000)
an error will be thrown correctly if the variable is of a NOT NULL domain.
Report and almost-correct fix from Sergiy Vyshnevetskiy (bug #2948).

src/pl/plpgsql/src/pl_exec.c
src/test/regress/expected/domain.out
src/test/regress/sql/domain.sql

index 8a9c0093c5b5c98d4ae6ad0f9cb3bc413fb30725..cc5eb733534ce53dc083cf7ade185081c976933f 100644 (file)
@@ -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),
index c4cad728b3ac9b0dd13d131206fef33194b8747d..4acaaa4121cd564abde1a8915592ee08e2bd8b6f 100644 (file)
@@ -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;
index 21940e0e618cc8cb882dd212a3ac3e81084a4fd4..411d64648a6d7c0eb3a3a33654ee6c71af1ca1ac 100644 (file)
@@ -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;