diff --git a/tsl/src/nodes/decompress_chunk/decompress_chunk.c b/tsl/src/nodes/decompress_chunk/decompress_chunk.c index 3e14dc2cb..ebc65003d 100644 --- a/tsl/src/nodes/decompress_chunk/decompress_chunk.c +++ b/tsl/src/nodes/decompress_chunk/decompress_chunk.c @@ -1416,22 +1416,6 @@ create_var_for_compressed_equivalence_member(Var *var, const EMCreationContext * return NULL; } -#if PG16_GE -static EquivalenceMember * -find_em_for_relid(EquivalenceClass *ec, Index relid) -{ - ListCell *lc; - - foreach (lc, ec->ec_members) - { - EquivalenceMember *em = lfirst_node(EquivalenceMember, lc); - if (bms_is_member(relid, em->em_relids) && bms_num_members(em->em_relids) == 1) - return em; - } - return NULL; -} -#endif - /* This function is inspired by the Postgres add_child_rel_equivalences. */ static bool add_segmentby_to_equivalence_class(PlannerInfo *root, EquivalenceClass *cur_ec, @@ -1545,22 +1529,24 @@ add_segmentby_to_equivalence_class(PlannerInfo *root, EquivalenceClass *cur_ec, lappend(compressed_fdw_private->compressed_ec_em_pairs, list_make2(cur_ec, em)); #if PG16_GE - EquivalenceMember *ht_em = find_em_for_relid(cur_ec, info->ht_rel->relid); + /* Record EquivalenceMember for the compressed chunk as derived to prevent + * infinite recursion. + */ - if (ht_em && ht_em->em_jdomain) + foreach (lc, cur_ec->ec_members) { - int i = -1; - while ((i = bms_next_member(ht_em->em_jdomain->jd_relids, i)) >= 0) - { - RestrictInfo *d = make_simple_restrictinfo_compat(root, em->em_expr); - d->parent_ec = cur_ec; - d->left_em = find_em_for_relid(cur_ec, i); - if (!d->left_em) - continue; - d->right_em = em; - cur_ec->ec_derives = lappend(cur_ec->ec_derives, d); - } + EquivalenceMember *p_em = lfirst_node(EquivalenceMember, lc); + /* Assume non-child member are at the beginning */ + if (p_em->em_is_child) + break; + + RestrictInfo *d = make_simple_restrictinfo_compat(root, p_em->em_expr); + d->parent_ec = cur_ec; + d->left_em = p_em; + d->right_em = em; + cur_ec->ec_derives = lappend(cur_ec->ec_derives, d); } + #endif return true; diff --git a/tsl/test/shared/expected/decompress_join.out b/tsl/test/shared/expected/decompress_join.out index fd294a177..0b619022d 100644 --- a/tsl/test/shared/expected/decompress_join.out +++ b/tsl/test/shared/expected/decompress_join.out @@ -60,3 +60,12 @@ SELECT * FROM partial_join m1 INNER JOIN partial_join m2 ON m1.device = m2.devic (4 rows) DROP TABLE partial_join; +-- This resulted in a recursion in the join planner code on PG16 +SELECT * FROM metrics_tstz as m +INNER JOIN metrics_space as ms on (true) +INNER JOIN metrics_space_compressed as msc on (true) +WHERE CASE WHEN m.device_id is not NULL and ms.v2 is not NULL THEN NULL::int2 end = msc.device_id; + time | device_id | v1 | v2 | time | device_id | v0 | v1 | v2 | v3 | time | device_id | v0 | v1 | v2 | v3 +------+-----------+----+----+------+-----------+----+----+----+----+------+-----------+----+----+----+---- +(0 rows) + diff --git a/tsl/test/shared/sql/decompress_join.sql b/tsl/test/shared/sql/decompress_join.sql index 424119d26..d8e5b0765 100644 --- a/tsl/test/shared/sql/decompress_join.sql +++ b/tsl/test/shared/sql/decompress_join.sql @@ -35,3 +35,9 @@ SELECT * FROM partial_join m1 INNER JOIN partial_join m2 ON m1.device = m2.devic DROP TABLE partial_join; +-- This resulted in a recursion in the join planner code on PG16 +SELECT * FROM metrics_tstz as m +INNER JOIN metrics_space as ms on (true) +INNER JOIN metrics_space_compressed as msc on (true) +WHERE CASE WHEN m.device_id is not NULL and ms.v2 is not NULL THEN NULL::int2 end = msc.device_id; +