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