Sergiy Vyshnevetskiy <[EMAIL PROTECTED]> 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;
---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?

               http://www.postgresql.org/docs/faq

Reply via email to