diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index db475e25b15..d4c5738e965 100644 --- a/src/backend/optimizer/path/joinrels.c +++ b/src/backend/optimizer/path/joinrels.c @@ -45,7 +45,8 @@ static void try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, static SpecialJoinInfo *build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo, Relids left_relids, Relids right_relids); -static void free_child_join_sjinfo(SpecialJoinInfo *sjinfo); +static void free_child_join_sjinfo(SpecialJoinInfo *child_sjinfo, + SpecialJoinInfo *parent_sjinfo); static void compute_partition_bounds(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, RelOptInfo *joinrel, SpecialJoinInfo *parent_sjinfo, @@ -1677,7 +1678,7 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, child_restrictlist); pfree(appinfos); - free_child_join_sjinfo(child_sjinfo); + free_child_join_sjinfo(child_sjinfo, parent_sjinfo); } } @@ -1744,18 +1745,33 @@ build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo, * SpecialJoinInfo are freed here. */ static void -free_child_join_sjinfo(SpecialJoinInfo *sjinfo) +free_child_join_sjinfo(SpecialJoinInfo *child_sjinfo, + SpecialJoinInfo *parent_sjinfo) { /* * Dummy SpecialJoinInfos of inner joins do not have any translated fields * and hence no fields that to be freed. */ - if (sjinfo->jointype != JOIN_INNER) + if (child_sjinfo->jointype != JOIN_INNER) { - bms_free(sjinfo->min_lefthand); - bms_free(sjinfo->min_righthand); - bms_free(sjinfo->syn_lefthand); - bms_free(sjinfo->syn_righthand); + if (child_sjinfo->min_lefthand != parent_sjinfo->min_lefthand) + bms_free(child_sjinfo->min_lefthand); + + if (child_sjinfo->min_righthand != parent_sjinfo->min_righthand) + bms_free(child_sjinfo->min_righthand); + + if (child_sjinfo->syn_lefthand != parent_sjinfo->syn_lefthand) + bms_free(child_sjinfo->syn_lefthand); + + if (child_sjinfo->syn_righthand != parent_sjinfo->syn_righthand) + bms_free(child_sjinfo->syn_righthand); + + Assert(child_sjinfo->commute_above_l == parent_sjinfo->commute_above_l); + Assert(child_sjinfo->commute_above_r == parent_sjinfo->commute_above_r); + Assert(child_sjinfo->commute_below_l == parent_sjinfo->commute_below_l); + Assert(child_sjinfo->commute_below_r == parent_sjinfo->commute_below_r); + + Assert(child_sjinfo->semi_operators == parent_sjinfo->semi_operators); /* * semi_rhs_exprs may in principle be freed, but a simple pfree() does @@ -1763,7 +1779,7 @@ free_child_join_sjinfo(SpecialJoinInfo *sjinfo) */ } - pfree(sjinfo); + pfree(child_sjinfo); } /* diff --git a/src/test/regress/expected/partition_join.out b/src/test/regress/expected/partition_join.out index 6d07f86b9bc..b9b41340663 100644 --- a/src/test/regress/expected/partition_join.out +++ b/src/test/regress/expected/partition_join.out @@ -674,6 +674,41 @@ SELECT a, b FROM prt1 FULL JOIN prt2 p2(b,a,c) USING(a,b) RESET enable_partitionwise_aggregate; RESET enable_hashjoin; +-- bug in freeing the SpecialJoinInfo of a child-join +EXPLAIN (COSTS OFF) +SELECT * FROM prt1 t1 JOIN prt1 t2 ON t1.a = t2.a WHERE t1.a IN (SELECT a FROM prt1 t3); + QUERY PLAN +-------------------------------------------------- + Append + -> Hash Semi Join + Hash Cond: (t1_1.a = t3_1.a) + -> Hash Join + Hash Cond: (t1_1.a = t2_1.a) + -> Seq Scan on prt1_p1 t1_1 + -> Hash + -> Seq Scan on prt1_p1 t2_1 + -> Hash + -> Seq Scan on prt1_p1 t3_1 + -> Hash Semi Join + Hash Cond: (t1_2.a = t3_2.a) + -> Hash Join + Hash Cond: (t1_2.a = t2_2.a) + -> Seq Scan on prt1_p2 t1_2 + -> Hash + -> Seq Scan on prt1_p2 t2_2 + -> Hash + -> Seq Scan on prt1_p2 t3_2 + -> Hash Semi Join + Hash Cond: (t1_3.a = t3_3.a) + -> Hash Join + Hash Cond: (t1_3.a = t2_3.a) + -> Seq Scan on prt1_p3 t1_3 + -> Hash + -> Seq Scan on prt1_p3 t2_3 + -> Hash + -> Seq Scan on prt1_p3 t3_3 +(28 rows) + -- -- partitioned by expression -- diff --git a/src/test/regress/sql/partition_join.sql b/src/test/regress/sql/partition_join.sql index 128ce8376e6..afadefd50fd 100644 --- a/src/test/regress/sql/partition_join.sql +++ b/src/test/regress/sql/partition_join.sql @@ -138,6 +138,10 @@ SELECT a, b FROM prt1 FULL JOIN prt2 p2(b,a,c) USING(a,b) RESET enable_partitionwise_aggregate; RESET enable_hashjoin; +-- bug in freeing the SpecialJoinInfo of a child-join +EXPLAIN (COSTS OFF) +SELECT * FROM prt1 t1 JOIN prt1 t2 ON t1.a = t2.a WHERE t1.a IN (SELECT a FROM prt1 t3); + -- -- partitioned by expression --