Re: Fix for recursive plpython triggers

Поиск
Список
Период
Сортировка
От Tom Lane
Тема Re: Fix for recursive plpython triggers
Дата
Msg-id 552755.1715183477@sss.pgh.pa.us
обсуждение исходный текст
Ответ на Re: Fix for recursive plpython triggers  (Andreas Karlsson <andreas@proxel.se>)
Список pgsql-hackers
Andreas Karlsson <andreas@proxel.se> writes:
> I found this issue while reading the code, so am very unclear if there 
> is any sane code which could trigger it.

> In the example below the recursive call to f('int') changes the return 
> type of the f('text') call causing it to fail.

> # CREATE OR REPLACE FUNCTION f(t text) RETURNS record LANGUAGE 
> plpython3u AS $$
> if t == "text":
>      plpy.execute("SELECT * FROM f('int') AS (a int)");
>      return { "a": "x" }
> elif t == "int":
>      return { "a": 1 }
> $$;
> CREATE FUNCTION

> # SELECT * FROM f('text') AS (a text);
> ERROR:  invalid input syntax for type integer: "x"
> CONTEXT:  while creating return value
> PL/Python function "f"

Oh, nice one.  I think we can fix this trivially though: the problem
is that RECORD return-type setup was stuck into PLy_function_build_args,
where it has no particular business being in the first place, rather
than being done at the point of use.  We can just move the code.

            regards, tom lane

diff --git a/src/pl/plpython/plpy_exec.c b/src/pl/plpython/plpy_exec.c
index 6f7b5e121d..157229e96f 100644
--- a/src/pl/plpython/plpy_exec.c
+++ b/src/pl/plpython/plpy_exec.c
@@ -231,7 +231,23 @@ PLy_exec_function(FunctionCallInfo fcinfo, PLyProcedure *proc)
         }
         else
         {
-            /* Normal conversion of result */
+            /*
+             * Normal conversion of result.  However, if the result is of type
+             * RECORD, we have to set up for that each time through, since it
+             * might be different from last time.
+             */
+            if (proc->result.typoid == RECORDOID)
+            {
+                TupleDesc    desc;
+
+                if (get_call_result_type(fcinfo, NULL, &desc) != TYPEFUNC_COMPOSITE)
+                    ereport(ERROR,
+                            (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                             errmsg("function returning record called in context "
+                                    "that cannot accept type record")));
+                PLy_output_setup_record(&proc->result, desc, proc);
+            }
+
             rv = PLy_output_convert(&proc->result, plrv,
                                     &fcinfo->isnull);
         }
@@ -456,21 +472,6 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
                 PLy_elog(ERROR, "PyDict_SetItemString() failed, while setting up arguments");
             arg = NULL;
         }
-
-        /* Set up output conversion for functions returning RECORD */
-        if (proc->result.typoid == RECORDOID)
-        {
-            TupleDesc    desc;
-
-            if (get_call_result_type(fcinfo, NULL, &desc) != TYPEFUNC_COMPOSITE)
-                ereport(ERROR,
-                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                         errmsg("function returning record called in context "
-                                "that cannot accept type record")));
-
-            /* cache the output conversion functions */
-            PLy_output_setup_record(&proc->result, desc, proc);
-        }
     }
     PG_CATCH();
     {

В списке pgsql-hackers по дате отправления:

Предыдущее
От: "Andrey M. Borodin"
Дата:
Сообщение: Re: UUID v7
Следующее
От: "Jonathan S. Katz"
Дата:
Сообщение: Re: 2024-05-09 release announcement draft