aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/analyzejoins.c
diff options
context:
space:
mode:
authorAlexander Korotkov <akorotkov@postgresql.org>2023-12-27 03:34:29 +0200
committerAlexander Korotkov <akorotkov@postgresql.org>2023-12-27 03:57:57 +0200
commite0477837ce49d73c9f21a5e00143b741ce6e1f89 (patch)
treee1029bfebccd8160cdfe381d292ba2dfbbc0aae0 /src/backend/optimizer/plan/analyzejoins.c
parent7d58f2342bd3d2f0474207b63a3a548c29e20a9e (diff)
downloadpostgresql-e0477837ce49d73c9f21a5e00143b741ce6e1f89.tar.gz
postgresql-e0477837ce49d73c9f21a5e00143b741ce6e1f89.zip
Make replace_relid() leave argument unmodified
There are a lot of situations when we share the same pointer to a Bitmapset structure across different places. In order to evade undesirable side effects replace_relid() function should always return a copy. Reported-by: Richard Guo Discussion: https://postgr.es/m/CAMbWs4_wJthNtYBL%2BSsebpgF-5L2r5zFFk6xYbS0A78GKOTFHw%40mail.gmail.com Reviewed-by: Richard Guo, Andres Freund, Ashutosh Bapat, Andrei Lepikhov
Diffstat (limited to 'src/backend/optimizer/plan/analyzejoins.c')
-rw-r--r--src/backend/optimizer/plan/analyzejoins.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c
index 6c02fe89085..80739451b7c 100644
--- a/src/backend/optimizer/plan/analyzejoins.c
+++ b/src/backend/optimizer/plan/analyzejoins.c
@@ -1522,6 +1522,10 @@ replace_varno_walker(Node *node, ReplaceVarnoContext *ctx)
/*
* Substitute newId by oldId in relids.
+ *
+ * We must make a copy of the original Bitmapset before making any
+ * modifications, because the same pointer to it might be shared among
+ * different places.
*/
static Bitmapset *
replace_relid(Relids relids, int oldId, int newId)
@@ -1529,12 +1533,13 @@ replace_relid(Relids relids, int oldId, int newId)
if (oldId < 0)
return relids;
+ /* Delete relid without substitution. */
if (newId < 0)
- /* Delete relid without substitution. */
- return bms_del_member(relids, oldId);
+ return bms_del_member(bms_copy(relids), oldId);
+ /* Substitute newId for oldId. */
if (bms_is_member(oldId, relids))
- return bms_add_member(bms_del_member(relids, oldId), newId);
+ return bms_add_member(bms_del_member(bms_copy(relids), oldId), newId);
return relids;
}