diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c
index 1cdb311..bc1929c 100644
--- a/src/backend/optimizer/plan/analyzejoins.c
+++ b/src/backend/optimizer/plan/analyzejoins.c
@@ -22,20 +22,16 @@
  */
 #include "postgres.h"
 
+#include "nodes/nodeFuncs.h"
+#include "optimizer/clauses.h"
 #include "optimizer/joininfo.h"
 #include "optimizer/pathnode.h"
 #include "optimizer/paths.h"
 #include "optimizer/planmain.h"
 #include "optimizer/var.h"
-#include "optimizer/clauses.h"
-#include "parser/parsetree.h"
-#include "optimizer/tlist.h"
-#include "nodes/nodeFuncs.h"
 
 /* local functions */
 static bool join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo);
-static bool	groupinglist_is_unique_on_restrictinfo(Query *query,
-					  List *clause_list, List *sortlist);
 static void remove_rel_from_query(PlannerInfo *root, int relid,
 					  Relids joinrelids);
 static List *remove_rel_from_joinlist(List *joinlist, int relid, int *nremoved);
@@ -153,7 +149,6 @@ join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo)
 {
 	int			innerrelid;
 	RelOptInfo *innerrel;
-	Query	   *subquery;
 	Relids		joinrelids;
 	List	   *clause_list = NIL;
 	ListCell   *l;
@@ -176,8 +171,8 @@ join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo)
 	 *    appear in the join condition with equality operators.
 	 *
 	 * The code below is written with the assumption that join removal is more
-	 * likely not to happen, for this reason there are fast paths for both of
-	 * the cases above to try to save on unnecessary processing.
+	 * likely not to happen, for this reason we try to fast path out of this
+	 * function early when possible.
 	 */
 
 	if (sjinfo->jointype != JOIN_LEFT ||
@@ -200,20 +195,7 @@ join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo)
 		if (innerrel->indexlist == NIL)
 			return false;
 	}
-	else if (innerrel->rtekind == RTE_SUBQUERY)
-	{
-		subquery = root->simple_rte_array[innerrelid]->subquery;
-
-		/*
-		 * The only means we currently use to check if the subquery is unique
-		 * are the GROUP BY and DISTINCT clause. If both of these are empty
-		 * then there's no point in going any further.
-		 */
-		if (subquery->groupClause == NIL &&
-			subquery->distinctClause == NIL)
-			return false;
-	}
-	else
+	else if (innerrel->rtekind != RTE_SUBQUERY)
 		return false; /* unsupported rtekind */
 
 	/* Compute the relid set for the join we are considering */
@@ -324,134 +306,76 @@ join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo)
 		return true;
 
 	/*
-	 * We can be certain that the sub query contains no duplicate values for
-	 * the join clause if item in the sub query's GROUP BY clause is also used
-	 * in the join clause using equality. This works the same way for the
-	 * DISTINCT clause. We need not pay any attention to WHERE or HAVING
-	 * clauses as these just restrict the results more and could not be the
-	 * cause of duplication in the result set. However there are a number of
-	 * pre-checks we must perform which could cause duplicate values even if
-	 * all the required columns are in the GROUP BY or DISTINCT clause.
+	 * For subqueries we should be able to remove the join if the subquery
+	 * can't produce more than 1 record which matches the outer query on the
+	 * join condition. However, there's a few pre-conditions that the subquery
+	 * must meet for it to be safe to remove:
+	 *
+	 * 1. The subquery mustn't contain a FOR UPDATE clause. Removing such a
+	 *    join would have the undesired side affect of not locking the rows.
+	 *
+	 * 2. The subquery mustn't contain any volatile functions. Removing such
+	 *    a join would cause side affects that the volatile functions may have,
+	 *    not to occur.
 	 *
-	 * NB: We must also not remove the join in the subquery contains a
-	 * FOR UDPATE clause, but we can actually skip this check as GROUP BY and
-	 * DISTINCT cannot be used at the same time as FOR UPDATE.
+	 * 3. The subquery mustn't contain any set returning functions. These can
+	 *    cause duplicate records despite the existence of a DISTINCT or
+	 *    GROUP BY clause which could otherwise make the subquery unique.
 	 */
 	if (innerrel->rtekind == RTE_SUBQUERY)
 	{
-		Assert(subquery == root->simple_rte_array[innerrelid]->subquery);
+		List	*colnos;
+		List	*opids;
+		Query	*subquery = root->simple_rte_array[innerrelid]->subquery;
 
-		/*
-		 * We cannot remove the subquery if the target list contains any set
-		 * returning functions as these may cause the query not to be unique
-		 * on the grouping columns, as per the following example:
-		 * "SELECT a.a,generate_series(1,2) FROM (VALUES(1)) a(a) GROUP BY a"
-		 */
-		if (expression_returns_set((Node *) subquery->targetList))
+		/* check point 1 */
+		if (subquery->hasForUpdate)
 			return false;
 
-		/*
-		 * Don't remove the join if the target list contains any volatile
-		 * functions. Doing so may remove desired side affects that calls
-		 * to the function may cause.
-		 */
+		/* check point 2 */
 		if (contain_volatile_functions((Node *) subquery->targetList))
 			return false;
 
-		/*
-		 * It should be safe to remove the join if all the GROUP BY expressions
-		 * have matching items in the join condition.
-		 */
-		if (subquery->groupClause != NIL &&
-			groupinglist_is_unique_on_restrictinfo(subquery, clause_list, subquery->groupClause))
-			return true;
-
-		/*
-		 * It should be safe to remove the join if all the DISTINCT column list have matching
-		 * items in the join condition.
-		 */
-		if (subquery->distinctClause != NIL &&
-			groupinglist_is_unique_on_restrictinfo(subquery, clause_list, subquery->distinctClause))
-			return true;
-	}
-
-	/*
-	 * Some day it would be nice to check for other methods of establishing
-	 * distinctness.
-	 */
-	return false;
-}
-
-/*
- * groupinglist_is_unique_on_restrictinfo
- *
- * Checks to see if all items in groupinglist also exist in rinfolist.
- * The function will return true if rinfolist is the same as or a superset
- * of groupinglist. If the groupinglist has Vars that don't exist in the rinfolist
- * then the query can't be guaranteed unique on the rinfolist columns.
- *
- * Note: The calling function must ensure that groupinglist is not NIL.
- */
-static bool
-groupinglist_is_unique_on_restrictinfo(Query *query, List *rinfolist, List *groupinglist)
-{
-	ListCell *l;
-
-	Assert(groupinglist != NIL);
-
-	/*
-	 * Loop over each groupinglist item to ensure that we have restrictinfo
-	 * item to match. We also need to ensure that the operators used in the
-	 * groupinglist matches that of the one in the restrict info.
-	 * Note that it does not matter if we have more items in the rinfolist than
-	 * we have in the groupinglist.
-	 */
-	foreach(l, groupinglist)
-	{
-		ListCell		*ri;
-		SortGroupClause *scl = (SortGroupClause *) lfirst(l);
-		TargetEntry		*sortTarget;
-		bool			 matched = false;
+		/* check point 3 */
+		if (expression_returns_set((Node *) subquery->targetList))
+			return false;
 
-		/* lookup the target list entry for the current sort sort group ref */
-		sortTarget = get_sortgroupref_tle(scl->tleSortGroupRef, query->targetList);
+		colnos = NULL;
+		opids = NULL;
 
 		/*
-		 * We can ignore constants since they have only one value and don't
-		 * affect uniqueness of results.
+		 * Build a list of varattnos that we require the subquery to be unique over.
+		 * We also build a list of the operators that are used with these vars in the
+		 * join condition so that query_is_distinct_for can check that these
+		 * operators are compatible with the GROUP BY or DISTINCT clause in the
+		 * subquery.
 		 */
-		if (IsA(sortTarget->expr, Const))
-			continue;
-
-		foreach(ri, rinfolist)
+		foreach(l, clause_list)
 		{
-			RestrictInfo *rinfo = (RestrictInfo *) lfirst(ri);
-			Node	   *rexpr;
+			RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
+			Var			 *var;
 
 			if (rinfo->outer_is_left)
-				rexpr = get_rightop(rinfo->clause);
-			else
-				rexpr = get_leftop(rinfo->clause);
-
-			if (IsA(rexpr, Var))
-			{
-				Var *var = (Var *)rexpr;
-
-				if (var->varattno == sortTarget->resno &&
-					scl->eqop == rinfo->hashjoinoperator)
-				{
-					matched = true;
-					break; /* match found */
-				}
-			}
+				var = (Var *) get_rightop(rinfo->clause);
 			else
-				return false;
+				var = (Var *) get_leftop(rinfo->clause);
+
+			if (!var || !IsA(var, Var) ||
+				var->varno != innerrelid)
+				continue;
+
+			colnos = lappend_int(colnos, var->varattno);
+			opids = lappend_oid(opids, rinfo->hashjoinoperator);
 		}
 
-		if (!matched)
-			return false;
+		return query_is_distinct_for(subquery, colnos, opids);
 	}
-	return true;
+
+	/*
+	 * Some day it would be nice to check for other methods of establishing
+	 * distinctness.
+	 */
+	return false;
 }
 
 /*
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 4e05dcd..f701954 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -38,7 +38,6 @@ typedef enum
 } PathCostComparison;
 
 static List *translate_sub_tlist(List *tlist, int relid);
-static bool query_is_distinct_for(Query *query, List *colnos, List *opids);
 static Oid	distinct_col_search(int colno, List *colnos, List *opids);
 
 
@@ -1465,7 +1464,7 @@ translate_sub_tlist(List *tlist, int relid)
  * should give trustworthy answers for all operators that we might need
  * to deal with here.)
  */
-static bool
+bool
 query_is_distinct_for(Query *query, List *colnos, List *opids)
 {
 	ListCell   *l;
@@ -1486,6 +1485,13 @@ query_is_distinct_for(Query *query, List *colnos, List *opids)
 			TargetEntry *tle = get_sortgroupclause_tle(sgc,
 													   query->targetList);
 
+			/*
+			 * We can ignore constants since they have only one value and don't
+			 * affect uniqueness of results.
+			 */
+			if (IsA(tle->expr, Const))
+				continue;
+
 			opid = distinct_col_search(tle->resno, colnos, opids);
 			if (!OidIsValid(opid) ||
 				!equality_ops_are_compatible(opid, sgc->eqop))
@@ -1507,6 +1513,13 @@ query_is_distinct_for(Query *query, List *colnos, List *opids)
 			TargetEntry *tle = get_sortgroupclause_tle(sgc,
 													   query->targetList);
 
+			/*
+			 * We can ignore constants since they have only one value and don't
+			 * affect uniqueness of results.
+			 */
+			if (IsA(tle->expr, Const))
+				continue;
+
 			opid = distinct_col_search(tle->resno, colnos, opids);
 			if (!OidIsValid(opid) ||
 				!equality_ops_are_compatible(opid, sgc->eqop))
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
index a0bcc82..2f571f5 100644
--- a/src/include/optimizer/pathnode.h
+++ b/src/include/optimizer/pathnode.h
@@ -67,6 +67,7 @@ extern ResultPath *create_result_path(List *quals);
 extern MaterialPath *create_material_path(RelOptInfo *rel, Path *subpath);
 extern UniquePath *create_unique_path(PlannerInfo *root, RelOptInfo *rel,
 				   Path *subpath, SpecialJoinInfo *sjinfo);
+extern bool query_is_distinct_for(Query *query, List *colnos, List *opids);
 extern Path *create_subqueryscan_path(PlannerInfo *root, RelOptInfo *rel,
 						 List *pathkeys, Relids required_outer);
 extern Path *create_functionscan_path(PlannerInfo *root, RelOptInfo *rel,
