]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix plpgsql's handling of "return simple_record_variable".
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 11 Feb 2026 21:53:14 +0000 (16:53 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 11 Feb 2026 21:53:14 +0000 (16:53 -0500)
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

src/pl/plpgsql/src/expected/plpgsql_domain.out
src/pl/plpgsql/src/pl_exec.c
src/pl/plpgsql/src/sql/plpgsql_domain.sql

index 516c2b9e08ee1c1b77763ceebdbeb6f7395a6273..11c012ea0242f5d3dedfd86e7d087a26ad022984 100644 (file)
@@ -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)
+
index f80264e184eae163775727161d684ffcfc75d016..723048ab8338cddd0c5e2d5ec03ca912996f71e0 100644 (file)
@@ -3255,28 +3255,14 @@ exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
                                }
                                break;
 
-                       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:
+                       case PLPGSQL_DTYPE_REC:
                                {
-                                       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,
index 8f99aae5a9ffc07f4136b6af7d2f2ebdb40c0246..4c5dd7dc7072d24e55a7ee688813f65b1baed216 100644 (file)
@@ -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();