From fa5550937c15c2da9b302aaebef24458d93b532b Mon Sep 17 00:00:00 2001
From: Richard Guo <guofenglinux@gmail.com>
Date: Wed, 2 Nov 2022 15:06:46 +0800
Subject: [PATCH v3] constant folding for indexquals in bitmap scan

---
 contrib/btree_gin/expected/bool.out     |  2 +-
 src/backend/optimizer/plan/createplan.c | 31 +++++++++++++++++++++++--
 src/backend/optimizer/util/clauses.c    | 13 ++++++-----
 src/include/optimizer/optimizer.h       |  2 ++
 4 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/contrib/btree_gin/expected/bool.out b/contrib/btree_gin/expected/bool.out
index 207a3f2328..51a70eb530 100644
--- a/contrib/btree_gin/expected/bool.out
+++ b/contrib/btree_gin/expected/bool.out
@@ -92,7 +92,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM test_bool WHERE i=true ORDER BY i;
  Sort
    Sort Key: i
    ->  Bitmap Heap Scan on test_bool
-         Filter: i
+         Recheck Cond: i
          ->  Bitmap Index Scan on idx_bool
                Index Cond: (i = true)
 (6 rows)
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index ac86ce9003..10705cb210 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -20,6 +20,7 @@
 
 #include "access/sysattr.h"
 #include "catalog/pg_class.h"
+#include "catalog/pg_operator.h"
 #include "foreign/fdwapi.h"
 #include "miscadmin.h"
 #include "nodes/extensible.h"
@@ -3480,11 +3481,37 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
 		{
 			IndexClause *iclause = (IndexClause *) lfirst(l);
 			RestrictInfo *rinfo = iclause->rinfo;
+			ListCell	 *l2;
 
 			Assert(!rinfo->pseudoconstant);
 			subquals = lappend(subquals, rinfo->clause);
-			subindexquals = list_concat(subindexquals,
-										get_actual_clauses(iclause->indexquals));
+
+			/*
+			 * The indexquals may have been transformed into form "indexkey =
+			 * true/false" in match_boolean_index_clause().  We need to
+			 * re-simplify them in order to compare them to scan_clauses in
+			 * create_bitmap_scan_plan().
+			 */
+			foreach(l2, iclause->indexquals)
+			{
+				RestrictInfo *restrictinfo = lfirst_node(RestrictInfo, l2);
+				OpExpr       *clause = (OpExpr *) restrictinfo->clause;
+
+				Assert(!restrictinfo->pseudoconstant);
+
+				if (is_opclause(clause) &&
+					clause->opno == BooleanEqualOperator)
+				{
+					Node    *simple;
+
+					simple = simplify_boolean_equality(clause->opno,
+													   clause->args);
+					if (simple) /* successfully simplified it */
+						clause = (OpExpr *) simple;
+				}
+
+				subindexquals = lappend(subindexquals, (Node *) clause);
+			}
 			if (rinfo->parent_ec)
 				subindexECs = lappend(subindexECs, rinfo->parent_ec);
 		}
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 7fb32a0710..50cd0cbe79 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -119,7 +119,6 @@ static List *simplify_or_arguments(List *args,
 static List *simplify_and_arguments(List *args,
 									eval_const_expressions_context *context,
 									bool *haveNull, bool *forceFalse);
-static Node *simplify_boolean_equality(Oid opno, List *args);
 static Expr *simplify_function(Oid funcid,
 							   Oid result_type, int32 result_typmod,
 							   Oid result_collid, Oid input_collid, List **args_p,
@@ -3774,8 +3773,8 @@ simplify_and_arguments(List *args,
 }
 
 /*
- * Subroutine for eval_const_expressions: try to simplify boolean equality
- * or inequality condition
+ * simplify_boolean_equality: try to simplify boolean equality or inequality
+ * condition
  *
  * Inputs are the operator OID and the simplified arguments to the operator.
  * Returns a simplified expression if successful, or NULL if cannot
@@ -3787,10 +3786,12 @@ simplify_and_arguments(List *args,
  * ensures that we will recognize these forms as being equivalent in, for
  * example, partial index matching.
  *
- * We come here only if simplify_function has failed; therefore we cannot
- * see two constant inputs, nor a constant-NULL input.
+ * We come here only if simplify_function has failed in
+ * eval_const_expressions_mutator, or we need to re-simplify the boolean
+ * equality expression in create_bitmap_subplan; therefore we cannot see two
+ * constant inputs, nor a constant-NULL input.
  */
-static Node *
+Node *
 simplify_boolean_equality(Oid opno, List *args)
 {
 	Node	   *leftop;
diff --git a/src/include/optimizer/optimizer.h b/src/include/optimizer/optimizer.h
index 409005bae9..e5d110744b 100644
--- a/src/include/optimizer/optimizer.h
+++ b/src/include/optimizer/optimizer.h
@@ -150,6 +150,8 @@ extern Node *estimate_expression_value(PlannerInfo *root, Node *node);
 extern Expr *evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
 						   Oid result_collation);
 
+extern Node *simplify_boolean_equality(Oid opno, List *args);
+
 extern List *expand_function_arguments(List *args, bool include_out_arguments,
 									   Oid result_type,
 									   struct HeapTupleData *func_tuple);
-- 
2.31.0

