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