Index: src/pl/plpgsql/src/pl_exec.c =================================================================== RCS file: /var/lib/cvs/pgsql-server/src/pl/plpgsql/src/pl_exec.c,v retrieving revision 1.76 diff -c -r1.76 pl_exec.c *** src/pl/plpgsql/src/pl_exec.c 17 Dec 2002 15:45:01 -0000 1.76 --- src/pl/plpgsql/src/pl_exec.c 13 Jan 2003 18:43:04 -0000 *************** *** 1627,1635 **** { PLpgSQL_rec *rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->recno]); ! if (!compatible_tupdesc(tupdesc, rec->tupdesc)) ! elog(ERROR, "Wrong record type supplied in RETURN NEXT"); ! tuple = rec->tup; } else if (stmt->row) { --- 1627,1656 ---- { PLpgSQL_rec *rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->recno]); ! /* ! * If the RECORD value we're attempting to return is undefined ! * (e.g. a SELECT INTO the record finds no results), we should ! * return a row of NULLs. This is consistent with the behavior ! * when returning an undefined rowtype variable. ! */ ! if (rec->tup == NULL) ! { ! char *nulls; ! ! nulls = (char *) palloc(natts * sizeof(char)); ! MemSet(nulls, 'n', natts * sizeof(char)); ! ! tuple = heap_formtuple(tupdesc, NULL, nulls); ! ! pfree(nulls); ! free_tuple = true; ! } ! else ! { ! if (!compatible_tupdesc(tupdesc, rec->tupdesc)) ! elog(ERROR, "Wrong record type supplied in RETURN NEXT"); ! tuple = rec->tup; ! } } else if (stmt->row) { *************** *** 1642,1648 **** dvalues = (Datum *) palloc0(natts * sizeof(Datum)); nulls = (char *) palloc(natts * sizeof(char)); ! MemSet(nulls, 'n', natts); for (i = 0; i < natts; i++) { --- 1663,1669 ---- dvalues = (Datum *) palloc0(natts * sizeof(Datum)); nulls = (char *) palloc(natts * sizeof(char)); ! MemSet(nulls, 'n', natts * sizeof(char)); for (i = 0; i < natts; i++) { Index: src/test/regress/expected/plpgsql.out =================================================================== RCS file: /var/lib/cvs/pgsql-server/src/test/regress/expected/plpgsql.out,v retrieving revision 1.12 diff -c -r1.12 plpgsql.out *** src/test/regress/expected/plpgsql.out 10 Nov 2002 00:35:58 -0000 1.12 --- src/test/regress/expected/plpgsql.out 13 Jan 2003 18:57:49 -0000 *************** *** 1733,1738 **** --- 1733,1770 ---- 50 | 5 | xxx (1 row) + CREATE TYPE simple_type AS ( + a int, + b int, + c TEXT + ); + -- + -- If the user attempts to use RETURN NEXT on an undefined RECORD + -- variable, we should return a row of NULLs. Per bug report 10-01-2003. + create function test_ret_rec_null() returns setof simple_type as ' + DECLARE + rec RECORD; + i INTEGER; + BEGIN + RETURN NEXT rec; + FOR i IN 1 .. 5 LOOP + -- should not return any results + SELECT INTO rec 5, 10, ''foo'' FROM pg_class WHERE oid = -1; + RETURN NEXT rec; + END LOOP; + RETURN; + END;' language 'plpgsql'; + SELECT * FROM test_ret_rec_null(); + a | b | c + ---+---+--- + | | + | | + | | + | | + | | + | | + (6 rows) + -- -- test PERFORM -- Index: src/test/regress/sql/plpgsql.sql =================================================================== RCS file: /var/lib/cvs/pgsql-server/src/test/regress/sql/plpgsql.sql,v retrieving revision 1.11 diff -c -r1.11 plpgsql.sql *** src/test/regress/sql/plpgsql.sql 10 Nov 2002 00:35:58 -0000 1.11 --- src/test/regress/sql/plpgsql.sql 13 Jan 2003 18:55:08 -0000 *************** *** 1560,1565 **** --- 1560,1590 ---- SELECT * FROM test_ret_rec_dyn(1500) AS (a int, b int, c int); SELECT * FROM test_ret_rec_dyn(5) AS (a int, b numeric, c text); + CREATE TYPE simple_type AS ( + a int, + b int, + c TEXT + ); + + -- + -- If the user attempts to use RETURN NEXT on an undefined RECORD + -- variable, we should return a row of NULLs. Per bug report 10-01-2003. + create function test_ret_rec_null() returns setof simple_type as ' + DECLARE + rec RECORD; + i INTEGER; + BEGIN + RETURN NEXT rec; + FOR i IN 1 .. 5 LOOP + -- should not return any results + SELECT INTO rec 5, 10, ''foo'' FROM pg_class WHERE oid = -1; + RETURN NEXT rec; + END LOOP; + RETURN; + END;' language 'plpgsql'; + + SELECT * FROM test_ret_rec_null(); + -- -- test PERFORM --