aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2020-10-05 13:15:40 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2020-10-05 13:15:40 -0400
commite3bd026fbb91c64e99c2a66eceb2dba3cc3ec6f0 (patch)
treeef6cda64aaea6f21b1bd4011a6b78654e98ebceb /src
parentd40a00003621eb635e57afe6ec5c1d9f2df4f1aa (diff)
downloadpostgresql-e3bd026fbb91c64e99c2a66eceb2dba3cc3ec6f0.tar.gz
postgresql-e3bd026fbb91c64e99c2a66eceb2dba3cc3ec6f0.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/path/equivclass.c12
1 files 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
@@ -566,12 +566,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
*/
foreach(lc1, root->eq_classes)
@@ -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);