diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2021-01-04 12:39:27 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2021-01-04 12:39:27 -0500 |
commit | 1c1cbe279b3c6e8038c8f8079402f069bb4cea4c (patch) | |
tree | 44fbb03a989f507755f7d5b3b2fa9d6ffe6d0aa1 /src/backend/utils/adt/arrayfuncs.c | |
parent | 1788828d33516809fa2d842bf6e273d78e21d957 (diff) | |
download | postgresql-1c1cbe279b3c6e8038c8f8079402f069bb4cea4c.tar.gz postgresql-1c1cbe279b3c6e8038c8f8079402f069bb4cea4c.zip |
Rethink the "read/write parameter" mechanism in pl/pgsql.
Performance issues with the preceding patch to re-implement array
element assignment within pl/pgsql led me to realize that the read/write
parameter mechanism is misdesigned. Instead of requiring the assignment
source expression to be such that *all* its references to the target
variable could be passed as R/W, we really want to identify *one*
reference to the target variable to be passed as R/W, allowing any other
ones to be passed read/only as they would be by default. As long as the
R/W reference is a direct argument to the top-level (hence last to be
executed) function in the expression, there is no harm in R/O references
being passed to other lower parts of the expression. Nor is there any
use-case for more than one argument of the top-level function being R/W.
Hence, rewrite that logic to identify one single Param that references
the target variable, and make only that Param pass a read/write
reference, not any other Params referencing the target variable.
Discussion: https://postgr.es/m/4165684.1607707277@sss.pgh.pa.us
Diffstat (limited to 'src/backend/utils/adt/arrayfuncs.c')
-rw-r--r-- | src/backend/utils/adt/arrayfuncs.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index 1b618356606..f7012cc5d98 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -2582,8 +2582,11 @@ array_set_element_expanded(Datum arraydatum, /* * Copy new element into array's context, if needed (we assume it's - * already detoasted, so no junk should be created). If we fail further - * down, this memory is leaked, but that's reasonably harmless. + * already detoasted, so no junk should be created). Doing this before + * we've made any significant changes ensures that our behavior is sane + * even when the source is a reference to some element of this same array. + * If we fail further down, this memory is leaked, but that's reasonably + * harmless. */ if (!eah->typbyval && !isNull) { |