From d26c4a0408cf6af783216540cb189a64e8fa5579 Mon Sep 17 00:00:00 2001
From: Alexander Korotkov <akorotkov@postgresql.org>
Date: Wed, 9 Oct 2024 18:44:25 +0300
Subject: [PATCH v41 3/3] Allow match_orclause_to_indexcol() for joins

---
 src/backend/optimizer/path/indxpath.c | 19 ++++++++++---------
 src/test/regress/expected/join.out    | 10 +++++-----
 2 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 5c8b64a5b1e..ed3f8ff9991 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -2418,8 +2418,8 @@ match_join_clauses_to_index(PlannerInfo *root,
 		/* Potentially usable, so see if it matches the index or is an OR */
 		if (restriction_is_or_clause(rinfo))
 			*joinorclauses = lappend(*joinorclauses, rinfo);
-		else
-			match_clause_to_index(root, rinfo, index, clauseset);
+
+		match_clause_to_index(root, rinfo, index, clauseset);
 	}
 }
 
@@ -3229,6 +3229,7 @@ match_orclause_to_indexcol(PlannerInfo *root,
 	Oid			inputcollid = InvalidOid;
 	bool		firstTime = true;
 	bool		have_param = false;
+	Index		index_relid = index->rel->relid;
 
 	Assert(IsA(orclause, BoolExpr));
 	Assert(orclause->boolop == OR_EXPR);
@@ -3295,12 +3296,16 @@ match_orclause_to_indexcol(PlannerInfo *root,
 		 */
 		leftop = (Node *) linitial(subClause->args);
 		rightop = (Node *) lsecond(subClause->args);
-		if (match_index_to_operand(leftop, indexcol, index))
+		if (match_index_to_operand(leftop, indexcol, index) &&
+			!bms_is_member(index_relid, rinfo->right_relids) &&
+			!contain_volatile_functions(rightop))
 		{
 			indexExpr = leftop;
 			constExpr = rightop;
 		}
-		else if (match_index_to_operand(rightop, indexcol, index))
+		else if (match_index_to_operand(rightop, indexcol, index) &&
+			!bms_is_member(index_relid, rinfo->left_relids) &&
+			!contain_volatile_functions(leftop))
 		{
 			opno = get_commutator(opno);
 			if (!OidIsValid(opno))
@@ -3327,10 +3332,6 @@ match_orclause_to_indexcol(PlannerInfo *root,
 		if (IsA(indexExpr, RelabelType))
 			indexExpr = (Node *) ((RelabelType *) indexExpr)->arg;
 
-		/* We allow constant to be Const or Param */
-		if (!IsA(constExpr, Const) && !IsA(constExpr, Param))
-			break;
-
 		/* Forbid transformation for composite types, records. */
 		if (type_is_rowtype(exprType(constExpr)) ||
 			type_is_rowtype(exprType(indexExpr)))
@@ -3367,7 +3368,7 @@ match_orclause_to_indexcol(PlannerInfo *root,
 				break;
 		}
 
-		if (IsA(constExpr, Param))
+		if (!IsA(constExpr, Const))
 			have_param = true;
 		consts = lappend(consts, constExpr);
 	}
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 198b9168045..b4354c12079 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -3729,8 +3729,8 @@ select * from
   tenk1 join int4_tbl on f1 = twothousand,
   q1, q2
 where q1 = thousand or q2 = thousand;
-                               QUERY PLAN                               
-------------------------------------------------------------------------
+                                                                                QUERY PLAN                                                                                
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  Hash Join
    Hash Cond: (tenk1.twothousand = int4_tbl.f1)
    ->  Nested Loop
@@ -3738,12 +3738,12 @@ where q1 = thousand or q2 = thousand;
                ->  Seq Scan on q1
                ->  Seq Scan on q2
          ->  Bitmap Heap Scan on tenk1
-               Recheck Cond: ((q1.q1 = thousand) OR (q2.q2 = thousand))
+               Recheck Cond: (((q1.q1 = thousand) AND ((q1.q1 = thousand) OR (q2.q2 = thousand))) OR ((q2.q2 = thousand) AND ((q1.q1 = thousand) OR (q2.q2 = thousand))))
                ->  BitmapOr
                      ->  Bitmap Index Scan on tenk1_thous_tenthous
-                           Index Cond: (thousand = q1.q1)
+                           Index Cond: ((thousand = q1.q1) AND (thousand = ANY (ARRAY[q1.q1, q2.q2])))
                      ->  Bitmap Index Scan on tenk1_thous_tenthous
-                           Index Cond: (thousand = q2.q2)
+                           Index Cond: ((thousand = q2.q2) AND (thousand = ANY (ARRAY[q1.q1, q2.q2])))
    ->  Hash
          ->  Seq Scan on int4_tbl
 (15 rows)
-- 
2.39.5 (Apple Git-154)

