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
|
| Список | 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 по дате отправления: