00002_free_plpgsql_function_memory.patch
application/octet-stream
Filename: 00002_free_plpgsql_function_memory.patch
Type: application/octet-stream
Part: 0
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index a341cde2c14..8aad27a9028 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -2670,3 +2670,31 @@ plpgsql_HashTableDelete(PLpgSQL_function *function)
/* remove back link, which no longer points to allocated storage */
function->fn_hashkey = NULL;
}
+
+/* Try to delete and release the plan cache from the hash table */
+void
+plpgsql_func_inval_callback(Datum arg, int cacheid, uint32 hashvalue)
+{
+ HASH_SEQ_STATUS scan;
+ plpgsql_HashEnt *entry;
+ uint32 funcOid_hashvalue;
+
+ Assert(cacheid == PROCOID);
+
+ hash_seq_init(&scan, plpgsql_HashTable);
+ while ((entry = (plpgsql_HashEnt *) hash_seq_search(&scan)))
+ {
+ funcOid_hashvalue = GetSysCacheHashValue1(PROCOID,
+ ObjectIdGetDatum(entry->key.funcOid));
+ /* Ignore invalid entries */
+ if (entry->function == NULL)
+ continue;
+
+ /* hashvalue == 0 means a cache reset, must clear all state */
+ if (hashvalue == 0 ||
+ (cacheid == PROCOID && funcOid_hashvalue == hashvalue))
+ {
+ delete_function(entry->function);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c
index d8994538b76..5b2e50913ba 100644
--- a/src/pl/plpgsql/src/pl_handler.c
+++ b/src/pl/plpgsql/src/pl_handler.c
@@ -26,6 +26,7 @@
#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "utils/varlena.h"
+#include "utils/inval.h"
static bool plpgsql_extra_checks_check_hook(char **newvalue, void **extra, GucSource source);
static void plpgsql_extra_warnings_assign_hook(const char *newvalue, void *extra);
@@ -202,6 +203,7 @@ _PG_init(void)
plpgsql_HashTableInit();
RegisterXactCallback(plpgsql_xact_cb, NULL);
RegisterSubXactCallback(plpgsql_subxact_cb, NULL);
+ CacheRegisterSyscacheCallback(PROCOID, plpgsql_func_inval_callback, (Datum) 0);
/* Set up a rendezvous point with optional instrumentation plugin */
plpgsql_plugin_ptr = (PLpgSQL_plugin **) find_rendezvous_variable("PLpgSQL_plugin");
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index cead9eb7263..20a006ca331 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -1263,6 +1263,7 @@ extern PLpgSQL_condition *plpgsql_parse_err_condition(char *condname);
extern void plpgsql_adddatum(PLpgSQL_datum *newdatum);
extern int plpgsql_add_initdatums(int **varnos);
extern void plpgsql_HashTableInit(void);
+extern void plpgsql_func_inval_callback(Datum arg, int cacheid, uint32 hashvalue);
/*
* Functions in pl_exec.c