Hello All,

I'm proposing the fix of this bug:
http://archives.postgresql.org/pgsql-hackers/2005-02/msg00498.php

The exact SQL code exposing the error:

----------

create table usno (ra real, dec real, bmag real, rmag real,ipix int8);
CREATE OR REPLACE FUNCTION xxx(refcursor) RETURNS refcursor AS '
DECLARE query varchar;
BEGIN
query = ''SELECT * FROM usno'';
OPEN $1 FOR EXECUTE query;
RETURN $1;
END;
' LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION yyy() RETURNS SETOF usno AS '
DECLARE rec record;
DECLARE cur refcursor;
BEGIN
cur=xxx(''curs_name'');
LOOP
        FETCH cur into rec;
        EXIT WHEN NOT FOUND;
        RETURN NEXT rec;
END LOOP;
RETURN;
END;
' LANGUAGE plpgsql;

insert into usno values(1,2,3,4);
select * from yyy();
alter table usno add column errbox box;
select * from yyy();
alter table usno drop column errbox;
select * from yyy();

-------

The problem with that is in fact in pl_exec.c in function
compatible_tupdesc(), which do not check for the deleted attributes.

The patch is attached.

Regards,
        Sergey

*****************************************************
Sergey E. Koposov
Max Planck Institute for Astronomy
Web: http://lnfm1.sai.msu.ru/~math 
E-mail: [EMAIL PROTECTED]

Index: pl_exec.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v
retrieving revision 1.160
diff -c -r1.160 pl_exec.c
*** pl_exec.c   10 Jan 2006 18:50:43 -0000      1.160
--- pl_exec.c   12 Feb 2006 17:13:39 -0000
***************
*** 4469,4483 ****
  static bool
  compatible_tupdesc(TupleDesc td1, TupleDesc td2)
  {
!       int                     i;
  
!       if (td1->natts != td2->natts)
!               return false;
! 
!       for (i = 0; i < td1->natts; i++)
        {
!               if (td1->attrs[i]->atttypid != td2->attrs[i]->atttypid)
                        return false;
        }
  
        return true;
--- 4469,4507 ----
  static bool
  compatible_tupdesc(TupleDesc td1, TupleDesc td2)
  {
!       int                     i = 0, j = 0, natts1 = td1->natts, natts2 = 
td2->natts;
  
!       while ((i < natts1) && (j < natts2))
        {
!       /* We should skip the dropped columns */
!               if (td1->attrs[i]->attisdropped)
!               {
!                       i++;
!                       continue;
!               }
!               if (td2->attrs[j]->attisdropped)
!               {
!                       j++;
!                       continue;
!               }
!               
!               if (td1->attrs[i]->atttypid != td2->attrs[j]->atttypid)
!               {
                        return false;
+               }
+               else
+               {
+                       i++;
+                       j++;
+               }       
+       }
+       
+       while ((i < natts1) && (td1->attrs[i]->attisdropped)) i++;
+       while ((j < natts2) && (td2->attrs[j]->attisdropped)) j++;
+       
+       if ((i != natts1) || (j != natts2))
+       {
+               return false;
        }
  
        return true;
---------------------------(end of broadcast)---------------------------
TIP 6: explain analyze is your friend

Reply via email to