mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-17 02:53:51 +08:00
PG16: Fix join recursion
The initial approach to mark EquivalenceMember as derived had some loopholes still leading to infinite recursion with certain join conditions.
This commit is contained in:
parent
c34fd0b06c
commit
e93b5fa657
@ -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;
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user