From 2728677923d2a025575dee4a24580e3e899c5615 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 9 May 2024 13:16:21 -0400
Subject: Fix recursive RECORD-returning plpython functions.

If we recursed to a new call of the same function, with a different
coldeflist (AS clause), it would fail because the inner call would
overwrite the outer call's idea of what to return.  This is vaguely
like 1d2fe56e4 and c5bec5426, but it's not due to any API decisions:
it's just that we computed the actual output rowtype at the start of
the call, and saved it in the per-procedure data structure.  We can
fix it at basically zero cost by doing the computation at the end
of each call instead of the start.

It's not clear that there's any real-world use-case for such a
function, but given that it doesn't cost anything to fix,
it'd be silly not to.

Per report from Andreas Karlsson.  Back-patch to all supported
branches.

Discussion: https://postgr.es/m/1651a46d-3c15-4028-a8c1-d74937b54e19@proxel.se
---
 src/pl/plpython/sql/plpython_composite.sql | 11 +++++++++++
 1 file changed, 11 insertions(+)

(limited to 'src/pl/plpython/sql/plpython_composite.sql')

diff --git a/src/pl/plpython/sql/plpython_composite.sql b/src/pl/plpython/sql/plpython_composite.sql
index 0fd2f5d5e3b..844b761bf11 100644
--- a/src/pl/plpython/sql/plpython_composite.sql
+++ b/src/pl/plpython/sql/plpython_composite.sql
@@ -208,6 +208,17 @@ SELECT * FROM return_record_2('v4') AS (v1 int, v3 int, v2 int);
 SELECT * FROM return_record_2('v3') AS (v1 int, v3 int, v2 int);
 SELECT * FROM return_record_2('v3') AS (v1 int, v2 int, v3 int);
 
+-- recursion with a different inner result type didn't use to work
+CREATE FUNCTION return_record_3(t text) RETURNS record AS $$
+if t == "text":
+     plpy.execute("SELECT * FROM return_record_3('int') AS (a int)");
+     return { "a": "x" }
+elif t == "int":
+     return { "a": 1 }
+$$ LANGUAGE plpythonu;
+
+SELECT * FROM return_record_3('text') AS (a text);
+
 -- multi-dimensional array of composite types.
 CREATE FUNCTION composite_type_as_list()  RETURNS type_record[] AS $$
   return [[('first', 1), ('second', 1)], [('first', 2), ('second', 2)], [('first', 3), ('second', 3)]];
-- 
cgit v1.2.3

