postgres.git / summary / log / commit / refs

commit    e3bd026fbb91c64e99c2a66eceb2dba3cc3ec6f0
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Mon Oct 05 17:15:40 2020 +0000
First released in: 14.0, 9.5.24, 9.6.20, 10.15, 11.10, 12.5, 13.1

    Fix two latent(?) bugs in equivclass.c.
    
    get_eclass_for_sort_expr() computes expr_relids and nullable_relids
    early on, even though they won't be needed unless we make a new
    EquivalenceClass, which we often don't.  Aside from the probably-minor
    inefficiency, there's a memory management problem: these bitmapsets will
    be built in the caller's context, leading to dangling pointers if that
    is shorter-lived than root->planner_cxt.  This would be a live bug if
    get_eclass_for_sort_expr() could be called with create_it = true during
    GEQO join planning.  So far as I can find, the core code never does
    that, but it's hard to be sure that no extensions do, especially since
    the comments make it clear that that's supposed to be a supported case.
    Fix by not computing these values until we've switched into planner_cxt
    to build the new EquivalenceClass.
    
    generate_join_implied_equalities() uses inner_rel->relids to look up
    relevant eclasses, but it ought to be using nominal_inner_relids.
    This is presently harmless because a child RelOptInfo will always have
    exactly the same eclass_indexes as its topmost parent; but that might
    not be true forever, and anyway it makes the code confusing.
    
    The first of these is old (introduced by me in f3b3b8d5b), so back-patch
    to all supported branches.  The second only dates to v13, but we might
    as well back-patch it to keep the code looking similar across branches.
    
    Discussion: https://postgr.es/m/1508010.1601832581@sss.pgh.pa.us


src/backend/optimizer/path/equivclass.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c index 9408feacb8e..2e23ab673fa 100644 --- a/src/backend/optimizer/path/equivclass.c +++ b/src/backend/optimizer/path/equivclass.c @@ -565,12 +565,6 @@ get_eclass_for_sort_expr(PlannerInfo *root, */ expr = canonicalize_ec_expression(expr, opcintype, collation); - /* - * Get the precise set of nullable relids appearing in the expression. - */ - expr_relids = pull_varnos((Node *) expr); - nullable_relids = bms_intersect(nullable_relids, expr_relids); - /* * Scan through the existing EquivalenceClasses for a match */ @@ -645,6 +639,12 @@ get_eclass_for_sort_expr(PlannerInfo *root, if (newec->ec_has_volatile && sortref == 0) /* should not happen */ elog(ERROR, "volatile EquivalenceClass has no sortref"); + /* + * Get the precise set of nullable relids appearing in the expression. + */ + expr_relids = pull_varnos((Node *) expr); + nullable_relids = bms_intersect(nullable_relids, expr_relids); + newem = add_eq_member(newec, copyObject(expr), expr_relids, nullable_relids, false, opcintype); [parent: d40a00003621]