|
16 | 16 | * if it has one. When (and if) the next demand for a cached plan occurs,
|
17 | 17 | * parse analysis and rewrite is repeated to build a new valid query tree,
|
18 | 18 | * and then planning is performed as normal. We also force re-analysis and
|
19 |
| - * re-planning if the active search_path is different from the previous time. |
| 19 | + * re-planning if the active search_path is different from the previous time |
| 20 | + * or, if RLS is involved, if the user changes or the RLS environment changes. |
20 | 21 | *
10000
|
21 | 22 | * Note that if the sinval was a result of user DDL actions, parse analysis
|
22 | 23 | * could throw an error, for example if a column referenced by the query is
|
@@ -204,8 +205,8 @@ CreateCachedPlan(Node *raw_parse_tree,
|
204 | 205 | plansource->total_custom_cost = 0;
|
205 | 206 | plansource->num_custom_plans = 0;
|
206 | 207 | plansource->hasRowSecurity = false;
|
207 |
| - plansource->row_security_env = row_security; |
208 | 208 | plansource->planUserId = InvalidOid;
|
| 209 | + plansource->row_security_env = false; |
209 | 210 |
|
210 | 211 | MemoryContextSwitchTo(oldcxt);
|
211 | 212 |
|
@@ -271,6 +272,8 @@ CreateOneShotCachedPlan(Node *raw_parse_tree,
|
271 | 272 | plansource->generic_cost = -1;
|
272 | 273 | plansource->total_custom_cost = 0;
|
273 | 274 | plansource->num_custom_plans = 0;
|
| 275 | + plansource->planUserId = InvalidOid; |
| 276 | + plansource->row_security_env = false; |
274 | 277 |
|
275 | 278 | return plansource;
|
276 | 279 | }
|
@@ -409,6 +412,8 @@ CompleteCachedPlan(CachedPlanSource *plansource,
|
409 | 412 | plansource->cursor_options = cursor_options;
|
410 | 413 | plansource->fixed_result = fixed_result;
|
411 | 414 | plansource->resultDesc = PlanCacheComputeResultDesc(querytree_list);
|
| 415 | + plansource->planUserId = GetUserId(); |
| 416 | + plansource->row_security_env = row_security; |
412 | 417 |
|
413 | 418 | MemoryContextSwitchTo(oldcxt);
|
414 | 419 |
|
@@ -571,24 +576,15 @@ RevalidateCachedQuery(CachedPlanSource *plansource)
|
571 | 576 | return NIL;
|
572 | 577 | }
|
573 | 578 |
|
574 |
| - /* |
575 |
| - * If this is a new cached plan, then set the user id it was planned by |
576 |
| - * and under what row security settings; these are needed to determine |
577 |
| - * plan invalidation when RLS is involved. |
578 |
| - */ |
579 |
| - if (!OidIsValid(plansource->planUserId)) |
580 |
| - { |
581 |
| - plansource->planUserId = GetUserId(); |
582 |
| - plansource->row_security_env = row_security; |
583 |
| - } |
584 |
| - |
585 | 579 | /*
|
586 | 580 | * If the query is currently valid, we should have a saved search_path ---
|
587 | 581 | * check to see if that matches the current environment. If not, we want
|
588 |
| - * to force replan. |
| 582 | + * to force replan. We should also have a valid planUserId. |
589 | 583 | */
|
590 | 584 | if (plansource->is_valid)
|
591 | 585 | {
|
| 586 | + Assert(OidIsValid(plansource->planUserId)); |
| 587 | + |
592 | 588 | Assert(plansource->search_path != NULL);
|
593 | 589 | if (!OverrideSearchPathMatchesCurrent(plansource->search_path))
|
594 | 590 | {
|
@@ -643,6 +639,14 @@ RevalidateCachedQuery(CachedPlanSource *plansource)
|
643 | 639 | plansource->invalItems = NIL;
|
644 | 640 | plansource->search_path = NULL;
|
645 | 641 |
|
| 642 | + /* |
| 643 | + * The plan is invalid, possibly due to row security, so we need to reset |
| 644 | + * row_security_env and planUserId as we're about to re-plan with the |
| 645 | + * current settings. |
| 646 | + */ |
| 647 | + plansource->row_security_env = row_security; |
| 648 | + plansource->planUserId = GetUserId(); |
| 649 | + |
646 | 650 | /*
|
647 | 651 | * Free the query_context. We don't really expect MemoryContextDelete to
|
648 | 652 | * fail, but just in case, make sure the CachedPlanSource is left in a
|
@@ -1380,6 +1384,14 @@ CopyCachedPlan(CachedPlanSource *plansource)
|
1380 | 1384 | newsource->total_custom_cost = plansource->total_custom_cost;
|
1381 | 1385 | newsource->num_custom_plans = plansource->num_custom_plans;
|
1382 | 1386 |
|
| 1387 | + /* |
| 1388 | + * Copy over the user the query was planned as, and under what RLS |
| 1389 | + * environment. We will check during RevalidateCachedQuery() if the user |
| 1390 | + * or environment has changed and, if so, will force a re-plan. |
| 1391 | + */ |
| 1392 | + newsource->planUserId = plansource->planUserId; |
| 1393 | + newsource->row_security_env = plansource->row_security_env; |
| 1394 | + |
1383 | 1395 | MemoryContextSwitchTo(oldcxt);
|
1384 | 1396 |
|
1385 | 1397 | return newsource;
|
|
0 commit comments