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