From de406423a8814882dc1f747c3bc0d892ec440c65 Mon Sep 17 00:00:00 2001
From: James Hunter <james.hunter.pg@gmail.com>
Date: Wed, 9 Oct 2024 19:13:55 +0000
Subject: [PATCH] Move clause_sides_match_join() into pathnode.h

We had two almost-identical copies of the utility function
clause_sides_match_join() -- one in joinpath.c, and one in analyzejoins.c.
Both copies were marked "inline," so we might as well just move the
(inline) function definition into a common header file. I chose
pathnode.h, because it is already #included by both of the .c files.

This change doesn't help very much, on its own (since the almost-duplicate
functions are both "inline"), but it allows us to use the same utility
function from other source files, without making a third copy.
---
 src/backend/optimizer/path/joinpath.c     | 43 ++++-------------------
 src/backend/optimizer/plan/analyzejoins.c | 31 ----------------
 src/include/optimizer/pathnode.h          | 31 ++++++++++++++++
 3 files changed, 37 insertions(+), 68 deletions(-)

diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c
index a244300463..f1315606b8 100644
--- a/src/backend/optimizer/path/joinpath.c
+++ b/src/backend/optimizer/path/joinpath.c
@@ -58,9 +58,6 @@ static void try_partial_mergejoin_path(PlannerInfo *root,
 static void sort_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel,
 								 RelOptInfo *outerrel, RelOptInfo *innerrel,
 								 JoinType jointype, JoinPathExtraData *extra);
-static inline bool clause_sides_match_join(RestrictInfo *rinfo,
-										   RelOptInfo *outerrel,
-										   RelOptInfo *innerrel);
 static void match_unsorted_outer(PlannerInfo *root, RelOptInfo *joinrel,
 								 RelOptInfo *outerrel, RelOptInfo *innerrel,
 								 JoinType jointype, JoinPathExtraData *extra);
@@ -470,7 +467,8 @@ paraminfo_get_equal_hashops(PlannerInfo *root, ParamPathInfo *param_info,
 			 * with 2 args.
 			 */
 			if (!IsA(opexpr, OpExpr) || list_length(opexpr->args) != 2 ||
-				!clause_sides_match_join(rinfo, outerrel, innerrel))
+				!clause_sides_match_join(rinfo, outerrel->relids,
+										 innerrel->relids))
 			{
 				list_free(*operators);
 				list_free(*param_exprs);
@@ -1320,37 +1318,6 @@ try_partial_hashjoin_path(PlannerInfo *root,
 										  hashclauses));
 }
 
-/*
- * clause_sides_match_join
- *	  Determine whether a join clause is of the right form to use in this join.
- *
- * We already know that the clause is a binary opclause referencing only the
- * rels in the current join.  The point here is to check whether it has the
- * form "outerrel_expr op innerrel_expr" or "innerrel_expr op outerrel_expr",
- * rather than mixing outer and inner vars on either side.  If it matches,
- * we set the transient flag outer_is_left to identify which side is which.
- */
-static inline bool
-clause_sides_match_join(RestrictInfo *rinfo, RelOptInfo *outerrel,
-						RelOptInfo *innerrel)
-{
-	if (bms_is_subset(rinfo->left_relids, outerrel->relids) &&
-		bms_is_subset(rinfo->right_relids, innerrel->relids))
-	{
-		/* lefthand side is outer */
-		rinfo->outer_is_left = true;
-		return true;
-	}
-	else if (bms_is_subset(rinfo->left_relids, innerrel->relids) &&
-			 bms_is_subset(rinfo->right_relids, outerrel->relids))
-	{
-		/* righthand side is outer */
-		rinfo->outer_is_left = false;
-		return true;
-	}
-	return false;				/* no good for these input relations */
-}
-
 /*
  * sort_inner_and_outer
  *	  Create mergejoin join paths by explicitly sorting both the outer and
@@ -2264,7 +2231,8 @@ hash_inner_and_outer(PlannerInfo *root,
 		/*
 		 * Check if clause has the form "outer op inner" or "inner op outer".
 		 */
-		if (!clause_sides_match_join(restrictinfo, outerrel, innerrel))
+		if (!clause_sides_match_join(restrictinfo, outerrel->relids,
+									 innerrel->relids))
 			continue;			/* no good for these input relations */
 
 		/*
@@ -2549,7 +2517,8 @@ select_mergejoin_clauses(PlannerInfo *root,
 		/*
 		 * Check if clause has the form "outer op inner" or "inner op outer".
 		 */
-		if (!clause_sides_match_join(restrictinfo, outerrel, innerrel))
+		if (!clause_sides_match_join(restrictinfo, outerrel->relids,
+									 innerrel->relids))
 		{
 			have_nonmergeable_joinclause = true;
 			continue;			/* no good for these input relations */
diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c
index 928d926645..5bc16c4bfc 100644
--- a/src/backend/optimizer/plan/analyzejoins.c
+++ b/src/backend/optimizer/plan/analyzejoins.c
@@ -115,37 +115,6 @@ restart:
 	return joinlist;
 }
 
-/*
- * clause_sides_match_join
- *	  Determine whether a join clause is of the right form to use in this join.
- *
- * We already know that the clause is a binary opclause referencing only the
- * rels in the current join.  The point here is to check whether it has the
- * form "outerrel_expr op innerrel_expr" or "innerrel_expr op outerrel_expr",
- * rather than mixing outer and inner vars on either side.  If it matches,
- * we set the transient flag outer_is_left to identify which side is which.
- */
-static inline bool
-clause_sides_match_join(RestrictInfo *rinfo, Relids outerrelids,
-						Relids innerrelids)
-{
-	if (bms_is_subset(rinfo->left_relids, outerrelids) &&
-		bms_is_subset(rinfo->right_relids, innerrelids))
-	{
-		/* lefthand side is outer */
-		rinfo->outer_is_left = true;
-		return true;
-	}
-	else if (bms_is_subset(rinfo->left_relids, innerrelids) &&
-			 bms_is_subset(rinfo->right_relids, outerrelids))
-	{
-		/* righthand side is outer */
-		rinfo->outer_is_left = false;
-		return true;
-	}
-	return false;				/* no good for these input relations */
-}
-
 /*
  * join_is_removable
  *	  Check whether we need not perform this special join at all, because
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
index 1035e6560c..ccedda5103 100644
--- a/src/include/optimizer/pathnode.h
+++ b/src/include/optimizer/pathnode.h
@@ -18,6 +18,37 @@
 #include "nodes/pathnodes.h"
 
 
+/*
+ * clause_sides_match_join
+ *	  Determine whether a join clause is of the right form to use in this join.
+ *
+ * We already know that the clause is a binary opclause referencing only the
+ * rels in the current join.  The point here is to check whether it has the
+ * form "outerrel_expr op innerrel_expr" or "innerrel_expr op outerrel_expr",
+ * rather than mixing outer and inner vars on either side.  If it matches,
+ * we set the transient flag outer_is_left to identify which side is which.
+ */
+static inline bool
+clause_sides_match_join(RestrictInfo *rinfo, Relids outerrelids,
+						Relids innerrelids)
+{
+	if (bms_is_subset(rinfo->left_relids, outerrelids) &&
+		bms_is_subset(rinfo->right_relids, innerrelids))
+	{
+		/* lefthand side is outer */
+		rinfo->outer_is_left = true;
+		return true;
+	}
+	else if (bms_is_subset(rinfo->left_relids, innerrelids) &&
+			 bms_is_subset(rinfo->right_relids, outerrelids))
+	{
+		/* righthand side is outer */
+		rinfo->outer_is_left = false;
+		return true;
+	}
+	return false;				/* no good for these input relations */
+}
+
 /*
  * prototypes for pathnode.c
  */
-- 
2.40.1

