From: Tom Lane Date: Wed, 10 Jan 2024 18:51:36 +0000 (-0500) Subject: Fix Asserts in calc_non_nestloop_required_outer(). X-Git-Tag: REL_17_BETA1~1148 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=add673b897c3d76767cec5ac1619fad6b1eb7582;p=thirdparty%2Fpostgresql.git Fix Asserts in calc_non_nestloop_required_outer(). These were not testing the same thing as the comparable Assert in calc_nestloop_required_outer(), because we neglected to map the given Paths' relids to top-level relids. When considering a partition child join the latter is the correct thing to do. This oversight is old, but since it's only an overly-weak Assert check there doesn't seem to be much value in back-patching. Richard Guo (with cosmetic changes and comment updates by me) Discussion: https://postgr.es/m/CAMbWs49sqbe9GBZ8sy8dSfKRNURgicR85HX8vgzcgQsPF0XY1w@mail.gmail.com --- diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c index 3fd5a24fadc..e9def9d540a 100644 --- a/src/backend/optimizer/path/joinpath.c +++ b/src/backend/optimizer/path/joinpath.c @@ -730,8 +730,11 @@ try_nestloop_path(PlannerInfo *root, return; /* - * Paths are parameterized by top-level parents, so run parameterization - * tests on the parent relids. + * Any parameterization of the input paths refers to topmost parents of + * the relevant relations, because reparameterize_path_by_child() hasn't + * been called yet. So we must consider topmost parents of the relations + * being joined, too, while determining parameterization of the result and + * checking for disallowed parameterization cases. */ if (innerrel->top_parent_relids) innerrelids = innerrel->top_parent_relids; diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index f7ac71087a6..8dbf790e893 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -2360,6 +2360,9 @@ create_foreign_upper_path(PlannerInfo *root, RelOptInfo *rel, * calc_nestloop_required_outer * Compute the required_outer set for a nestloop join path * + * Note: when considering a child join, the inputs nonetheless use top-level + * parent relids + * * Note: result must not share storage with either input */ Relids @@ -2394,11 +2397,30 @@ calc_non_nestloop_required_outer(Path *outer_path, Path *inner_path) { Relids outer_paramrels = PATH_REQ_OUTER(outer_path); Relids inner_paramrels = PATH_REQ_OUTER(inner_path); + Relids innerrelids PG_USED_FOR_ASSERTS_ONLY; + Relids outerrelids PG_USED_FOR_ASSERTS_ONLY; Relids required_outer; + /* + * Any parameterization of the input paths refers to topmost parents of + * the relevant relations, because reparameterize_path_by_child() hasn't + * been called yet. So we must consider topmost parents of the relations + * being joined, too, while checking for disallowed parameterization + * cases. + */ + if (inner_path->parent->top_parent_relids) + innerrelids = inner_path->parent->top_parent_relids; + else + innerrelids = inner_path->parent->relids; + + if (outer_path->parent->top_parent_relids) + outerrelids = outer_path->parent->top_parent_relids; + else + outerrelids = outer_path->parent->relids; + /* neither path can require rels from the other */ - Assert(!bms_overlap(outer_paramrels, inner_path->parent->relids)); - Assert(!bms_overlap(inner_paramrels, outer_path->parent->relids)); + Assert(!bms_overlap(outer_paramrels, innerrelids)); + Assert(!bms_overlap(inner_paramrels, outerrelids)); /* form the union ... */ required_outer = bms_union(outer_paramrels, inner_paramrels); /* we do not need an explicit test for empty; bms_union gets it right */