diff options
Diffstat (limited to 'src/backend/utils/cache/plancache.c')
-rw-r--r-- | src/backend/utils/cache/plancache.c | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c index 1be20fcd9aa..5eefa74a61d 100644 --- a/src/backend/utils/cache/plancache.c +++ b/src/backend/utils/cache/plancache.c @@ -16,7 +16,8 @@ * if it has one. When (and if) the next demand for a cached plan occurs, * parse analysis and rewrite is repeated to build a new valid query tree, * and then planning is performed as normal. We also force re-analysis and - * re-planning if the active search_path is different from the previous time. + * re-planning if the active search_path is different from the previous time + * or, if RLS is involved, if the user changes or the RLS environment changes. * * Note that if the sinval was a result of user DDL actions, parse analysis * could throw an error, for example if a column referenced by the query is @@ -204,8 +205,8 @@ CreateCachedPlan(Node *raw_parse_tree, plansource->total_custom_cost = 0; plansource->num_custom_plans = 0; plansource->hasRowSecurity = false; - plansource->row_security_env = row_security; plansource->planUserId = InvalidOid; + plansource->row_security_env = false; MemoryContextSwitchTo(oldcxt); @@ -271,6 +272,8 @@ CreateOneShotCachedPlan(Node *raw_parse_tree, plansource->generic_cost = -1; plansource->total_custom_cost = 0; plansource->num_custom_plans = 0; + plansource->planUserId = InvalidOid; + plansource->row_security_env = false; return plansource; } @@ -409,6 +412,8 @@ CompleteCachedPlan(CachedPlanSource *plansource, plansource->cursor_options = cursor_options; plansource->fixed_result = fixed_result; plansource->resultDesc = PlanCacheComputeResultDesc(querytree_list); + plansource->planUserId = GetUserId(); + plansource->row_security_env = row_security; MemoryContextSwitchTo(oldcxt); @@ -572,23 +577,14 @@ RevalidateCachedQuery(CachedPlanSource *plansource) } /* - * If this is a new cached plan, then set the user id it was planned by - * and under what row security settings; these are needed to determine - * plan invalidation when RLS is involved. - */ - if (!OidIsValid(plansource->planUserId)) - { - plansource->planUserId = GetUserId(); - plansource->row_security_env = row_security; - } - - /* * If the query is currently valid, we should have a saved search_path --- * check to see if that matches the current environment. If not, we want - * to force replan. + * to force replan. We should also have a valid planUserId. */ if (plansource->is_valid) { + Assert(OidIsValid(plansource->planUserId)); + Assert(plansource->search_path != NULL); if (!OverrideSearchPathMatchesCurrent(plansource->search_path)) { @@ -644,6 +640,14 @@ RevalidateCachedQuery(CachedPlanSource *plansource) plansource->search_path = NULL; /* + * The plan is invalid, possibly due to row security, so we need to reset + * row_security_env and planUserId as we're about to re-plan with the + * current settings. + */ + plansource->row_security_env = row_security; + plansource->planUserId = GetUserId(); + + /* * Free the query_context. We don't really expect MemoryContextDelete to * fail, but just in case, make sure the CachedPlanSource is left in a * reasonably sane state. (The generic plan won't get unlinked yet, but @@ -1380,6 +1384,14 @@ CopyCachedPlan(CachedPlanSource *plansource) newsource->total_custom_cost = plansource->total_custom_cost; newsource->num_custom_plans = plansource->num_custom_plans; + /* + * Copy over the user the query was planned as, and under what RLS + * environment. We will check during RevalidateCachedQuery() if the user + * or environment has changed and, if so, will force a re-plan. + */ + newsource->planUserId = plansource->planUserId; + newsource->row_security_env = plansource->row_security_env; + MemoryContextSwitchTo(oldcxt); return newsource; |