Skip to content

Commit 5f6f951

Browse files
committed
Improve RowMark handling during Self-Join Elimination
The Self-Join Elimination SJE feature messes up keeping and removing RowMark's in remove_self_joins_one_group(). That didn't lead to user-level error, because the planned RowMark is only used to reference a rtable entry in later execution stages. An RTE entry for keeping and removing relations is identical and refers to the same relation OID. To reduce confusion and prevent future issues, this commit cleans up the code and fixes the incorrect behaviour. Furthermore, it includes sanity checks in setrefs.c on existing non-null RTE and RelOptInfo entries for each RowMark. Discussion: https://postgr.es/m/18c6bd6c-6d2a-419a-b0da-dfedef34b585%40gmail.com Author: Andrei Lepikhov <lepihov@gmail.com> Reviewed-by: Greg Sabino Mullane <htamfids@gmail.com> Backpatch-through: 18
1 parent d713cf9 commit 5f6f951

File tree

2 files changed

+10
-3
lines changed

2 files changed

+10
-3
lines changed

src/backend/optimizer/plan/analyzejoins.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,7 @@ remove_leftjoinrel_from_query(PlannerInfo *root, int relid,
631631
* remove_join_clause_from_rels will touch it.)
632632
*/
633633
root->simple_rel_array[relid] = NULL;
634+
root->simple_rte_array[relid] = NULL;
634635

635636
/* And nuke the RelOptInfo, just in case there's another access path */
636637
pfree(rel);
@@ -1978,10 +1979,12 @@ remove_self_join_rel(PlannerInfo *root, PlanRowMark *kmark, PlanRowMark *rmark,
19781979
* remove_join_clause_from_rels will touch it.)
19791980
*/
19801981
root->simple_rel_array[toRemove->relid] = NULL;
1982+
root->simple_rte_array[toRemove->relid] = NULL;
19811983

19821984
/* And nuke the RelOptInfo, just in case there's another access path. */
19831985
pfree(toRemove);
19841986

1987+
19851988
/*
19861989
* Now repeat construction of attr_needed bits coming from all other
19871990
* sources.
@@ -2193,12 +2196,12 @@ remove_self_joins_one_group(PlannerInfo *root, Relids relids)
21932196
{
21942197
PlanRowMark *rowMark = (PlanRowMark *) lfirst(lc);
21952198

2196-
if (rowMark->rti == k)
2199+
if (rowMark->rti == r)
21972200
{
21982201
Assert(rmark == NULL);
21992202
rmark = rowMark;
22002203
}
2201-
else if (rowMark->rti == r)
2204+
else if (rowMark->rti == k)
22022205
{
22032206
Assert(kmark == NULL);
22042207
kmark = rowMark;
@@ -2253,7 +2256,7 @@ remove_self_joins_one_group(PlannerInfo *root, Relids relids)
22532256
selfjoinquals = list_concat(selfjoinquals, krel->baserestrictinfo);
22542257

22552258
/*
2256-
* Determine if the rrel can duplicate outer rows. We must bypass
2259+
* Determine if the rrel can duplicate outer rows. We must bypass
22572260
* the unique rel cache here since we're possibly using a subset
22582261
* of join quals. We can use 'force_cache' == true when all join
22592262
* quals are self-join quals. Otherwise, we could end up putting

src/backend/optimizer/plan/setrefs.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@ set_plan_references(PlannerInfo *root, Plan *plan)
307307
PlanRowMark *rc = lfirst_node(PlanRowMark, lc);
308308
PlanRowMark *newrc;
309309

310+
/* sanity check on existing row marks */
311+
Assert(root->simple_rel_array[rc->rti] != NULL &&
312+
root->simple_rte_array[rc->rti] != NULL);
313+
310314
/* flat copy is enough since all fields are scalars */
311315
newrc = (PlanRowMark *) palloc(sizeof(PlanRowMark));
312316
memcpy(newrc, rc, sizeof(PlanRowMark));

0 commit comments

Comments
 (0)