From 42e4f1ce720d5b034d43790f08c9237fe8e61838 Mon Sep 17 00:00:00 2001
From: Richard Guo <guofenglinux@gmail.com>
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

