From 534d0ea6c2b915ac9745d2f070afacd7ba003d28 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 24 Oct 2024 13:28:22 -0400 Subject: [PATCH] Generalize plpgsql's heuristic for importing expanded objects. If a R/W expanded-object pointer is passed as a function parameter, take ownership of the object, regardless of its type. Previously this happened only for expanded arrays, but that was a result of sloppy thinking. (If the plpgsql function did not end by returning the object, the result would be to leak the object until the surrounding memory context is cleaned up. That's not awful, since non-expanded values have always been managed that way, but we can do better.) Per discussion with Michel Pelletier. There's a lot more to do here to make plpgsql work efficiently with expanded objects that aren't arrays, but this is an easy first step. Discussion: https://postgr.es/m/CACxu=vJaKFNsYxooSnW1wEgsAO5u_v1XYBacfVJ14wgJV_PYeg@mail.gmail.com --- src/pl/plpgsql/src/pl_exec.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index ea9740e3f89..e69559b980e 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -532,21 +532,22 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo, false); /* - * Force any array-valued parameter to be stored in + * If it's a varlena type, check to see if we received a + * R/W expanded-object pointer. If so, we can commandeer + * the object rather than having to copy it. If passed a + * R/O expanded pointer, just keep it as the value of the + * variable for the moment. (We can change it to R/W if + * the variable gets modified, but that may very well + * never happen.) + * + * Also, force any flat array value to be stored in * expanded form in our local variable, in hopes of * improving efficiency of uses of the variable. (This is * a hack, really: why only arrays? Need more thought * about which cases are likely to win. See also * typisarray-specific heuristic in exec_assign_value.) - * - * Special cases: If passed a R/W expanded pointer, assume - * we can commandeer the object rather than having to copy - * it. If passed a R/O expanded pointer, just keep it as - * the value of the variable for the moment. (We'll force - * it to R/W if the variable gets modified, but that may - * very well never happen.) */ - if (!var->isnull && var->datatype->typisarray) + if (!var->isnull && var->datatype->typlen == -1) { if (VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(var->value))) { @@ -561,7 +562,7 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo, { /* R/O pointer, keep it as-is until assigned to */ } - else + else if (var->datatype->typisarray) { /* flat array, so force to expanded form */ assign_simple_var(&estate, var, -- 2.30.2