diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c index 87210fc..411655a 100644 --- a/src/backend/utils/cache/plancache.c +++ b/src/backend/utils/cache/plancache.c @@ -1643,9 +1643,14 @@ CachedPlanGetTargetList(CachedPlanSource *plansource, * The result is stashed in a private, long-lived memory context. * (Note that this might leak a good deal of memory in the caller's * context before that.) The passed-in expr tree is not modified. + * + * CachedExpression memory will be assigned in CacheMemoryContext if + * SP is using session wide cast hash table, Otherise memory will be + * allocated in SPI proc context which is having lifetime till SP + * execution and avoids memory leak in Cachememorycontext. */ CachedExpression * -GetCachedExpression(Node *expr) +GetCachedExpression(Node *expr, MemoryContext context, bool is_session_cast_hash) { CachedExpression *cexpr; List *relationOids; @@ -1683,16 +1688,24 @@ GetCachedExpression(Node *expr) MemoryContextSwitchTo(oldcxt); - /* - * Reparent the expr's memory context under CacheMemoryContext so that it - * will live indefinitely. - */ - MemoryContextSetParent(cexpr_context, CacheMemoryContext); + if (is_session_cast_hash) + { - /* - * Add the entry to the global list of cached expressions. - */ - dlist_push_tail(&cached_expression_list, &cexpr->node); + /* + * Reparent the expr's memory context under CacheMemoryContext so that it + * will live indefinitely. + */ + MemoryContextSetParent(cexpr_context, CacheMemoryContext); + + /* + * Add the entry to the global list of cached expressions. + */ + dlist_push_tail(&cached_expression_list, &cexpr->node); + } + else + { + MemoryContextSetParent(cexpr_context, context); + } return cexpr; } diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h index a443181..b163b95 100644 --- a/src/include/utils/plancache.h +++ b/src/include/utils/plancache.h @@ -230,7 +230,9 @@ extern bool CachedPlanIsSimplyValid(CachedPlanSource *plansource, CachedPlan *plan, ResourceOwner owner); -extern CachedExpression *GetCachedExpression(Node *expr); +extern CachedExpression *GetCachedExpression(Node *expr, + MemoryContext context, + bool is_session_cast_hash); extern void FreeCachedExpression(CachedExpression *cexpr); #endif /* PLANCACHE_H */ diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index e271ae5..5b7a0fc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -447,7 +447,6 @@ static char *format_preparedparamsdata(PLpgSQL_execstate *estate, static PLpgSQL_variable *make_callstmt_target(PLpgSQL_execstate *estate, PLpgSQL_expr *expr); - /* ---------- * plpgsql_exec_function Called by the call handler for * function execution. @@ -7873,7 +7872,8 @@ get_cast_hashentry(PLpgSQL_execstate *estate, /* Note: we don't bother labeling the expression tree with collation */ /* Plan the expression and build a CachedExpression */ - cast_cexpr = GetCachedExpression(cast_expr); + cast_cexpr = GetCachedExpression(cast_expr, estate->cast_hash_context, + (estate->cast_hash == shared_cast_hash)); cast_expr = cast_cexpr->expr; /* Detect whether we have a no-op (RelabelType) coercion */