Re: BUG #17610: Use of multiple composite types incompatible with record-typed function parameter

Поиск
Список
Период
Сортировка
От Tom Lane
Тема Re: BUG #17610: Use of multiple composite types incompatible with record-typed function parameter
Дата
Msg-id 4048043.1662653834@sss.pgh.pa.us
обсуждение исходный текст
Ответ на Re: BUG #17610: Use of multiple composite types incompatible with record-typed function parameter  (Japin Li <japinli@hotmail.com>)
Ответы Re: BUG #17610: Use of multiple composite types incompatible with record-typed function parameter  (Tom Lane <tgl@sss.pgh.pa.us>)
Список pgsql-bugs
Japin Li <japinli@hotmail.com> writes:
> On Thu, 08 Sep 2022 at 18:19, PG Bug reporting form <noreply@postgresql.org> wrote:
>> The SQL code at the end of this bug report ends with the following error:
>> 2022-09-08 10:09:02.173 GMT [174] ERROR:  type of parameter 1
>> (composite_type_2) does not match that when preparing the plan
>> (composite_type_1)

> The documentation says:

>   The mutable nature of record variables presents another problem in this
>   connection. When fields of a record variable are used in expressions or
>   statements, **the data types of the fields must not change from one call
>   of the function to the next**, since each expression will be analyzed
>   using the data type that is present when the expression is first reached.

I think that is specifically referring to function internal variables of
type RECORD, which are handled specially.  For function input arguments,
we could get around this by treating RECORD like a polymorphic type, as
attached.  (For some reason I thought we already did that, but nope.)

            regards, tom lane

diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 61fbdf0686..4d68f030e4 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -2498,9 +2498,15 @@ compute_function_hashkey(FunctionCallInfo fcinfo,
 
 /*
  * This is the same as the standard resolve_polymorphic_argtypes() function,
- * but with a special case for validation: assume that polymorphic arguments
- * are integer, integer-array or integer-range.  Also, we go ahead and report
- * the error if we can't resolve the types.
+ * except that:
+ * 1. We go ahead and report the error if we can't resolve the types.
+ * 2. We treat RECORD-type input parameters (not output parameters) as if
+ *    they were polymorphic, replacing their types with the actual input
+ *    types if we can determine those.  This allows us to create a separate
+ *    function cache entry for each named composite type passed to such a
+ *    parameter.
+ * 3. In validation mode, we have no inputs to look at, so assume that
+ *    polymorphic arguments are integer, integer-array or integer-range.
  */
 static void
 plpgsql_resolve_polymorphic_argtypes(int numargs,
@@ -2512,6 +2518,8 @@ plpgsql_resolve_polymorphic_argtypes(int numargs,
 
     if (!forValidator)
     {
+        int            inargno;
+
         /* normal case, pass to standard routine */
         if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
                                           call_expr))
@@ -2520,10 +2528,28 @@ plpgsql_resolve_polymorphic_argtypes(int numargs,
                      errmsg("could not determine actual argument "
                             "type for polymorphic function \"%s\"",
                             proname)));
+        /* also, treat RECORD inputs (but not outputs) as polymorphic */
+        inargno = 0;
+        for (i = 0; i < numargs; i++)
+        {
+            char        argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
+
+            if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
+                continue;
+            if (argtypes[i] == RECORDOID || argtypes[i] == RECORDARRAYOID)
+            {
+                Oid            resolvedtype = get_call_expr_argtype(call_expr,
+                                                                 inargno);
+
+                if (OidIsValid(resolvedtype))
+                    argtypes[i] = resolvedtype;
+            }
+            inargno++;
+        }
     }
     else
     {
-        /* special validation case */
+        /* special validation case (no need to do anything for RECORD) */
         for (i = 0; i < numargs; i++)
         {
             switch (argtypes[i])

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

Предыдущее
От: Japin Li
Дата:
Сообщение: Re: BUG #17610: Use of multiple composite types incompatible with record-typed function parameter
Следующее
От: Jeff Davis
Дата:
Сообщение: Re: PANIC in heap_delete during ALTER TABLE