0003-Free-space-allocated-by-copy_plpgsql_datums.patch
text/x-patch
Filename: 0003-Free-space-allocated-by-copy_plpgsql_datums.patch
Type: text/x-patch
Part: 2
Patch
Format: format-patch
Series: patch 0003
Subject: Free space allocated by copy_plpgsql_datums
| File | + | − |
|---|---|---|
| src/pl/plpgsql/src/pl_exec.c | 34 | 5 |
From 4375046f8b1f376e404b6ed65a358ee6d55d3b41 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Sat, 13 May 2023 13:19:49 +0200
Subject: [PATCH 3/3] Free space allocated by copy_plpgsql_datums
During PL/pgSQL execution, we allocate a local copy for calls. When
executing triggers, this gets allocated in ExecutorState, so it'd be
kept until query completes.
Free it explicitly, as part of cleanup.
---
src/pl/plpgsql/src/pl_exec.c | 39 +++++++++++++++++++++++++++++++-----
1 file changed, 34 insertions(+), 5 deletions(-)
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 4b76f7699a6..99283d354f4 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -264,6 +264,8 @@ static void coerce_function_result_tuple(PLpgSQL_execstate *estate,
static void plpgsql_exec_error_callback(void *arg);
static void copy_plpgsql_datums(PLpgSQL_execstate *estate,
PLpgSQL_function *func);
+static void free_plpgsql_datums(PLpgSQL_execstate *estate,
+ PLpgSQL_function *func);
static void plpgsql_fulfill_promise(PLpgSQL_execstate *estate,
PLpgSQL_var *var);
static MemoryContext get_stmt_mcontext(PLpgSQL_execstate *estate);
@@ -788,6 +790,8 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo,
exec_eval_cleanup(&estate);
/* stmt_mcontext will be destroyed when function's main context is */
+ free_plpgsql_datums(&estate, func);
+
/*
* Pop the error context stack
*/
@@ -1142,6 +1146,8 @@ plpgsql_exec_trigger(PLpgSQL_function *func,
exec_eval_cleanup(&estate);
/* stmt_mcontext will be destroyed when function's main context is */
+ free_plpgsql_datums(&estate, func);
+
/*
* Pop the error context stack
*/
@@ -1217,6 +1223,8 @@ plpgsql_exec_event_trigger(PLpgSQL_function *func, EventTriggerData *trigdata)
exec_eval_cleanup(&estate);
/* stmt_mcontext will be destroyed when function's main context is */
+ free_plpgsql_datums(&estate, func);
+
/*
* Pop the error context stack
*/
@@ -1304,15 +1312,20 @@ copy_plpgsql_datums(PLpgSQL_execstate *estate,
char *ws_next;
int i;
- /* Allocate local datum-pointer array */
- estate->datums = (PLpgSQL_datum **)
- palloc(sizeof(PLpgSQL_datum *) * ndatums);
-
/*
+ * Allocate local datum-pointer array, followed by space for the values.
+ *
* To reduce palloc overhead, we make a single palloc request for all the
* space needed for locally-instantiated datums.
*/
- workspace = palloc(func->copiable_size);
+ estate->datums = (PLpgSQL_datum **)
+ palloc(MAXALIGN(sizeof(PLpgSQL_datum *) * ndatums) + func->copiable_size);
+
+ /*
+ * Space for values starts after the datum-pointer array, but we need to make
+ * sure it's aligned properly.
+ */
+ workspace = (char *) estate->datums + MAXALIGN(sizeof(PLpgSQL_datum *) * ndatums);
ws_next = workspace;
/* Fill datum-pointer array, copying datums into workspace as needed */
@@ -1362,6 +1375,22 @@ copy_plpgsql_datums(PLpgSQL_execstate *estate,
Assert(ws_next == workspace + func->copiable_size);
}
+/*
+ * Free the local execution variables. We've allocated all of the space at once
+ * so we can simply free the main pointer.
+ */
+static void
+free_plpgsql_datums(PLpgSQL_execstate *estate,
+ PLpgSQL_function *func)
+{
+ if (estate->datums != NULL)
+ {
+ pfree(estate->datums);
+ estate->datums = NULL;
+ }
+
+}
+
/*
* If the variable has an armed "promise", compute the promised value
* and assign it to the variable.
--
2.40.1