From 996664e4b4d7e65449b813828e81d0924af64e2b Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat@enterprisedb.com>
Date: Mon, 4 Sep 2023 14:56:21 +0530
Subject: [PATCH 3/4] Save commuted RestrictInfo for later use

A commuted RestrictInfo may be produced as many times as the number of indexes
it is used for. It's the same RestrictInfo always. Save some CPU and memory by
saving the result in the original RestrictInfo.

Ashutosh Bapat
---
 src/backend/optimizer/util/appendinfo.c   |  6 ++++++
 src/backend/optimizer/util/restrictinfo.c | 22 +++++++++++++++++++++-
 src/include/nodes/pathnodes.h             |  9 +++++++++
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/src/backend/optimizer/util/appendinfo.c b/src/backend/optimizer/util/appendinfo.c
index dd4251be80..cb9a6d2d95 100644
--- a/src/backend/optimizer/util/appendinfo.c
+++ b/src/backend/optimizer/util/appendinfo.c
@@ -492,6 +492,12 @@ adjust_appendrel_attrs_mutator(Node *node,
 		newinfo->left_mcvfreq = -1;
 		newinfo->right_mcvfreq = -1;
 
+		/*
+		 * Wipe out commuted parent RestrictInfo. The caller will compute
+		 * commuted clause if required.
+		 */
+		newinfo->comm_rinfo = NULL;
+
 		return (Node *) newinfo;
 	}
 
diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c
index 0b406e9334..48f8b38258 100644
--- a/src/backend/optimizer/util/restrictinfo.c
+++ b/src/backend/optimizer/util/restrictinfo.c
@@ -246,6 +246,8 @@ make_restrictinfo_internal(PlannerInfo *root,
 
 	restrictinfo->left_hasheqoperator = InvalidOid;
 	restrictinfo->right_hasheqoperator = InvalidOid;
+	restrictinfo->comm_rinfo = NULL;
+	restrictinfo->is_commuted = false;
 
 	return restrictinfo;
 }
@@ -354,14 +356,27 @@ make_sub_restrictinfos(PlannerInfo *root,
  * be hazardous if the source is subject to change.  Also notice that we
  * assume without checking that the commutator op is a member of the same
  * btree and hash opclasses as the original op.
+ *
+ * If a commuted RestrictInfo is already available it is returned.
  */
 RestrictInfo *
 commute_restrictinfo(RestrictInfo *rinfo, Oid comm_op)
 {
 	RestrictInfo *result;
 	OpExpr	   *newclause;
-	OpExpr	   *clause = castNode(OpExpr, rinfo->clause);
+	OpExpr	   *clause;
+
+	if (rinfo->comm_rinfo)
+	{
+		result = rinfo->comm_rinfo;
+		newclause = castNode(OpExpr, result->clause);
+		Assert(list_length(newclause->args) == 2);
+		Assert(newclause->opno == comm_op);
 
+		return result;
+	}
+
+	clause = castNode(OpExpr, rinfo->clause);
 	Assert(list_length(clause->args) == 2);
 
 	/* flat-copy all the fields of clause ... */
@@ -403,6 +418,11 @@ commute_restrictinfo(RestrictInfo *rinfo, Oid comm_op)
 	result->right_mcvfreq = rinfo->left_mcvfreq;
 	result->left_hasheqoperator = InvalidOid;
 	result->right_hasheqoperator = InvalidOid;
+	result->is_commuted = !rinfo->is_commuted;
+	result->comm_rinfo = rinfo;
+
+	/* Save the commuted RestrictInfo for later use. */
+	rinfo->comm_rinfo = result;
 
 	return result;
 }
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index 534692bee1..e4420acded 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -2529,6 +2529,13 @@ typedef struct LimitPath
  *
  * parent_ec, left_ec, right_ec are not printed, lest it lead to infinite
  * recursion in plan tree dump.
+ *
+ * A RestrictInfo may get commuted as many times as the number of indexes it is
+ * used for. The commuted clause is cached in the original RestrictInfo as
+ * comm_rinfo and vice versa. Both the RestrictInfos are commuted versions of
+ * each other. is_commuted flag is false for the first one to appear and is
+ * true in the other. The order doesn't matter. The flag just differentiate
+ * between the commuted version.
  */
 
 typedef struct RestrictInfo
@@ -2683,6 +2690,8 @@ typedef struct RestrictInfo
 	/* hash equality operators used for memoize nodes, else InvalidOid */
 	Oid			left_hasheqoperator pg_node_attr(equal_ignore);
 	Oid			right_hasheqoperator pg_node_attr(equal_ignore);
+	struct RestrictInfo *comm_rinfo pg_node_attr(equal_ignore);
+	bool		is_commuted pg_node_attr(equal_ignore);
 } RestrictInfo;
 
 /*
-- 
2.25.1

