|
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 | *
|
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
|
@@ -208,8 +209,8 @@ CreateCachedPlan(Node *raw_parse_tree,
|
208 | 209 | plansource->total_custom_cost = 0;
|
209 | 210 | plansource->num_custom_plans = 0;
|
210 | 211 | plansource->hasRowSecurity = false;
|
211 |
| - plansource->row_security_env = row_security; |
212 | 212 | plansource->planUserId = InvalidOid;
|
| 213 | + plansource->row_security_env = false; |
213 | 214 |
|
214 | 215 | MemoryContextSwitchTo(oldcxt);
|
215 | 216 |
|
@@ -275,6 +276,8 @@ CreateOneShotCachedPlan(Node *raw_parse_tree,
|
275 | 276 | plansource->generic_cost = -1;
|
276 | 277 | plansource->total_custom_cost = 0;
|
277 | 278 | plansource->num_custom_plans = 0;
|
| 279 | + plansource->planUserId = InvalidOid; |
| 280 | + plansource->row_security_env = false; |
278 | 281 |
|
279 | 282 | return plansource;
|
280 | 283 | }
|
@@ -413,6 +416,8 @@ CompleteCachedPlan(CachedPlanSource *plansource,
|
413 | 416 | plansource->cursor_options = cursor_options;
|
414 | 417 | plansource->fixed_result = fixed_result;
|
415 | 418 | plansource->resultDesc = PlanCacheComputeResultDesc(querytree_list);
|
| 419 | + plansource->planUserId = GetUserId(); |
| 420 | + plansource->row_security_env = row_security; |
416 | 421 |
|
417 | 422 | MemoryContextSwitchTo(oldcxt);
|
418 | 423 |
|
@@ -575,25 +580,15 @@ RevalidateCachedQuery(CachedPlanSource *plansource)
|
575 | 580 | return NIL;
|
576 | 581 | }
|
577 | 582 |
|
578 |
| - /* |
579 |
| - * If this is a new cached plan, then set the user id it was planned by |
580 |
| - * and under what row security settings; these are needed to determine |
581 |
| - * plan invalidation when RLS is involved or foreign joins are pushed |
582 |
| - * down. |
583 |
| - */ |
584 |
| - if (!OidIsValid(plansource->planUserId)) |
585 |
| - { |
586 |
| - plansource->planUserId = GetUserId(); |
587 |
| - plansource->row_security_env = row_security; |
588 |
| - } |
589 |
| - |
590 | 583 | /*
|
591 | 584 | * If the query is currently valid, we should have a saved search_path ---
|
592 | 585 | * check to see if that matches the current environment. If not, we want
|
593 |
| - * to force replan. |
| 586 | + * to force replan. We should also have a valid planUserId. |
594 | 587 | */
|
595 | 588 | if (plansource->is_valid)
|
596 | 589 | {
|
| 590 | + Assert(OidIsValid(plansource->planUserId)); |
| 591 | + |
597 | 592 | Assert(plansource->search_path != NULL);
|
598 | 593 | if (!OverrideSearchPathMatchesCurrent(plansource->search_path))
|
599 | 594 | {
|
@@ -660,6 +655,14 @@ RevalidateCachedQuery(CachedPlanSource *plansource)
|
660 | 655 | plansource->invalItems = NIL;
|
661 | 656 | plansource->search_path = NULL;
|
662 | 657 |
|
| 658 | + /* |
| 659 | + * The plan is invalid, possibly due to row security, so we need to reset |
| 660 | + * row_security_env and planUserId as we're about to re-plan with the |
| 661 | + * current settings. |
| 662 | + */ |
| 663 | + plansource->row_security_env = row_security; |
| 664 | + plansource->planUserId = GetUserId(); |
| 665 | + |
663 | 666 | /*
|
664 | 667 | * Free the query_context. We don't really expect MemoryContextDelete to
|
665 | 668 | * fail, but just in case, make sure the CachedPlanSource is left in a
|
@@ -1412,6 +1415,14 @@ CopyCachedPlan(CachedPlanSource *plansource)
|
1412 | 1415 | newsource->total_custom_cost = plansource->total_custom_cost;
|
1413 | 1416 | newsource->num_custom_plans = plansource->num_custom_plans;
|
1414 | 1417 |
|
| 1418 | + /* |
| 1419 | + * Copy over the user the query was planned as, and under what RLS |
| 1420 | + * environment. We will check during RevalidateCachedQuery() if the user |
| 1421 | + * or environment has changed and, if so, will force a re-plan. |
| 1422 | + */ |
| 1423 | + newsource->planUserId = plansource->planUserId; |
| 1424 | + newsource->row_security_env = plansource->row_security_env; |
| 1425 | + |
1415 | 1426 | MemoryContextSwitchTo(oldcxt);
|
1416 | 1427 |
|
1417 | 1428 | return newsource;
|
|
0 commit comments