From 42e4f1ce720d5b034d43790f08c9237fe8e61838 Mon Sep 17 00:00:00 2001 From: Richard Guo Date: Sat, 7 Oct 2023 17:04:07 +0800 Subject: [PATCH v1] Check each of base restriction clauses for constant-FALSE In relation_excluded_by_constraints() when we're trying to figure out whether the relation need not be scanned, one of the checks we do is to detect constant-FALSE-or-NULL restriction clauses. Currently we perform this check only when there is exactly one baserestrictinfo entry. This doesn't seem entirely correct, because equivclass.c may generate constant-FALSE baserestrictinfo entry on the fly. In addition, other quals could get pushed down to the baserel. All these cases would result in that the baserestrictinfo list might possibly have other members besides the FALSE constant. This patch instead checks each of base restriction clauses for constant-FALSE-or-NULL quals. --- src/backend/optimizer/util/plancat.c | 18 ++++++++++-------- src/test/regress/expected/join.out | 8 +++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 243c8fb1e4..4e9736122e 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -1549,16 +1549,18 @@ relation_excluded_by_constraints(PlannerInfo *root, /* * Regardless of the setting of constraint_exclusion, detect - * constant-FALSE-or-NULL restriction clauses. Because const-folding will - * reduce "anything AND FALSE" to just "FALSE", any such case should - * result in exactly one baserestrictinfo entry. This doesn't fire very - * often, but it seems cheap enough to be worth doing anyway. (Without - * this, we'd miss some optimizations that 9.5 and earlier found via much - * more roundabout methods.) + * constant-FALSE-or-NULL restriction clauses. Although const-folding will + * reduce "anything AND FALSE" to just "FALSE", the baserestrictinfo list + * might possibly have other members besides the FALSE constant, since + * equivclass.c may generate constant-FALSE baserestrictinfo entry on the + * fly. In addition, other quals could get "pushed down" to the baserel. + * This doesn't fire very often, but it seems cheap enough to be worth + * doing anyway. (Without this, we'd miss some optimizations that 9.5 and + * earlier found via much more roundabout methods.) */ - if (list_length(rel->baserestrictinfo) == 1) + foreach(lc, rel->baserestrictinfo) { - RestrictInfo *rinfo = (RestrictInfo *) linitial(rel->baserestrictinfo); + RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); Expr *clause = rinfo->clause; if (clause && IsA(clause, Const) && diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index 9b8638f286..b95d30f658 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -5788,13 +5788,11 @@ explain (costs off) select p.* from parent p left join child c on (p.k = c.k) where p.k = 1 and p.k = 2; - QUERY PLAN ------------------------------------------------- + QUERY PLAN +-------------------------- Result One-Time Filter: false - -> Index Scan using parent_pkey on parent p - Index Cond: (k = 1) -(4 rows) +(2 rows) select p.* from (parent p left join child c on (p.k = c.k)) join parent x on p.k = x.k -- 2.31.0