Index: src/pl/plpgsql/src/pl_exec.c =================================================================== RCS file: /home/postgres/pgrepo/pgsql/src/pl/plpgsql/src/pl_exec.c,v retrieving revision 1.202.2.5 diff -c -r1.202.2.5 pl_exec.c *** src/pl/plpgsql/src/pl_exec.c 2 Apr 2009 01:16:17 -0000 1.202.2.5 --- src/pl/plpgsql/src/pl_exec.c 20 Jul 2009 06:37:15 -0000 *************** *** 2156,2161 **** --- 2156,2166 ---- PLpgSQL_stmt_return_query *stmt) { Portal portal; + int i; + bool dropped_columns = false; + Datum *dvalues; + bool *nulls; + int natts; if (!estate->retisset) ereport(ERROR, *************** *** 2172,2177 **** --- 2177,2191 ---- (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("structure of query does not match function result type"))); + natts = estate->rettupdesc->natts; + + if (natts > portal->tupDesc->natts) + { + dropped_columns = true; + dvalues = (Datum *) palloc0(natts * sizeof(Datum)); + nulls = (bool *) palloc(natts * sizeof(bool)); + } + while (true) { MemoryContext old_cxt; *************** *** 2186,2197 **** { HeapTuple tuple = SPI_tuptable->vals[i]; ! tuplestore_puttuple(estate->tuple_store, tuple); } MemoryContextSwitchTo(old_cxt); SPI_freetuptable(SPI_tuptable); } SPI_freetuptable(SPI_tuptable); SPI_cursor_close(portal); --- 2200,2238 ---- { HeapTuple tuple = SPI_tuptable->vals[i]; ! if (!dropped_columns) ! tuplestore_puttuple(estate->tuple_store, tuple); ! else ! { ! int anum; ! int j = 0; ! bool isnull; ! ! for (anum = 0; anum < natts; anum++) ! { ! if (estate->rettupdesc->attrs[anum]->attisdropped) ! nulls[anum] = true; ! else ! { ! dvalues[anum] = SPI_getbinval(tuple, portal->tupDesc, ! ++j, &isnull); ! nulls[anum] = isnull; ! } ! } ! tuple = heap_form_tuple(estate->rettupdesc, dvalues, nulls); ! tuplestore_puttuple(estate->tuple_store, tuple); ! } } MemoryContextSwitchTo(old_cxt); SPI_freetuptable(SPI_tuptable); } + + if (dropped_columns) + { + pfree(dvalues); + pfree(nulls); + } SPI_freetuptable(SPI_tuptable); SPI_cursor_close(portal); *************** *** 4910,4923 **** 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; --- 4951,4963 ---- compatible_tupdesc(TupleDesc td1, TupleDesc td2) { int i; ! int j = 0; for (i = 0; i < td1->natts; i++) { ! if (!td1->attrs[i]->attisdropped) ! if (td1->attrs[i]->atttypid != td2->attrs[j++]->atttypid) ! return false; } return true;