mirror of
https://git.postgresql.org/git/postgresql.git
synced 2026-02-22 06:17:00 +08:00
Fix plpgsql's handling of "return simple_record_variable".
If the variable's value is null, exec_stmt_return() missed filling in estate->rettype. This is a pretty old bug, but we'd managed not to notice because that value isn't consulted for a null result ... unless we have to cast it to a domain. That case led to a failure with "cache lookup failed for type 0". The correct way to assign the data type is known by exec_eval_datum. While we could copy-and-paste that logic, it seems like a better idea to just invoke exec_eval_datum, as the ROW case already does. Reported-by: Pavel Stehule <pavel.stehule@gmail.com> Author: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://postgr.es/m/CAFj8pRBT_ahexDf-zT-cyH8bMR_qcySKM8D5nv5MvTWPiatYGA@mail.gmail.com Backpatch-through: 14
This commit is contained in:
@ -395,3 +395,16 @@ SELECT * FROM test_assign_ordered_named_pairs(1,2,0); -- should fail someday
|
||||
{"(1,2)"}
|
||||
(1 row)
|
||||
|
||||
CREATE FUNCTION test_null_ordered_named_pair()
|
||||
RETURNS ordered_named_pair AS $$
|
||||
declare v ordered_named_pair;
|
||||
begin
|
||||
return v;
|
||||
end
|
||||
$$ LANGUAGE plpgsql;
|
||||
SELECT * FROM test_null_ordered_named_pair();
|
||||
i | j
|
||||
---+---
|
||||
|
|
||||
(1 row)
|
||||
|
||||
|
||||
@ -3255,28 +3255,14 @@ exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
|
||||
}
|
||||
break;
|
||||
|
||||
case PLPGSQL_DTYPE_ROW:
|
||||
case PLPGSQL_DTYPE_REC:
|
||||
{
|
||||
PLpgSQL_rec *rec = (PLpgSQL_rec *) retvar;
|
||||
|
||||
/* If record is empty, we return NULL not a row of nulls */
|
||||
if (rec->erh && !ExpandedRecordIsEmpty(rec->erh))
|
||||
{
|
||||
estate->retval = ExpandedRecordGetDatum(rec->erh);
|
||||
estate->retisnull = false;
|
||||
estate->rettype = rec->rectypeid;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PLPGSQL_DTYPE_ROW:
|
||||
{
|
||||
PLpgSQL_row *row = (PLpgSQL_row *) retvar;
|
||||
/* exec_eval_datum can handle these cases */
|
||||
int32 rettypmod;
|
||||
|
||||
/* We get here if there are multiple OUT parameters */
|
||||
exec_eval_datum(estate,
|
||||
(PLpgSQL_datum *) row,
|
||||
retvar,
|
||||
&estate->rettype,
|
||||
&rettypmod,
|
||||
&estate->retval,
|
||||
|
||||
@ -277,3 +277,13 @@ $$ LANGUAGE plpgsql;
|
||||
SELECT * FROM test_assign_ordered_named_pairs(1,2,3);
|
||||
SELECT * FROM test_assign_ordered_named_pairs(2,1,3);
|
||||
SELECT * FROM test_assign_ordered_named_pairs(1,2,0); -- should fail someday
|
||||
|
||||
CREATE FUNCTION test_null_ordered_named_pair()
|
||||
RETURNS ordered_named_pair AS $$
|
||||
declare v ordered_named_pair;
|
||||
begin
|
||||
return v;
|
||||
end
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
SELECT * FROM test_null_ordered_named_pair();
|
||||
|
||||
Reference in New Issue
Block a user