From f2d62ff4ceca2a33e557e5fb8bc4a2f6f3de872a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=B8=80=E6=8C=83?= <yizhi.fzh@alibaba-inc.com>
Date: Sun, 25 Jul 2021 16:26:45 +0800
Subject: [PATCH v4 2/6] Just some utils functions.

---
 src/backend/nodes/list.c                | 21 ++++++++++++
 src/backend/optimizer/path/equivclass.c | 45 +++++++++++++++++++++++++
 src/backend/optimizer/util/tlist.c      | 19 +++++++++++
 src/include/nodes/pg_list.h             |  2 ++
 src/include/optimizer/optimizer.h       |  1 +
 src/include/optimizer/paths.h           |  6 ++++
 6 files changed, 94 insertions(+)

diff --git a/src/backend/nodes/list.c b/src/backend/nodes/list.c
index 94fb236daf..8f2b00012e 100644
--- a/src/backend/nodes/list.c
+++ b/src/backend/nodes/list.c
@@ -702,6 +702,27 @@ list_member_oid(const List *list, Oid datum)
 	return false;
 }
 
+
+/*
+ * list_is_subset_ptr - is A a subset of B?
+ */
+bool
+list_is_subset_ptr(const List *a, const List *b)
+{
+	ListCell *lc;
+	Assert(IsPointerList(a));
+	check_list_invariants(a);
+	Assert(IsPointerList(b));
+	check_list_invariants(b);
+	foreach(lc, a)
+	{
+		if (!list_member_ptr(b, lfirst(lc)))
+			return false;
+	}
+	return true;
+}
+
+
 /*
  * Delete the n'th cell (counting from 0) in list.
  *
diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c
index 2f688807af..b8ada6e8a3 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -770,6 +770,26 @@ get_eclass_for_sort_expr(PlannerInfo *root,
 	return newec;
 }
 
+/*
+ * find_ec_member_matching_expr
+ *		Locate an EquivalenceClass matching the given expr, if any;
+ *		return NULL if no match.
+ */
+EquivalenceClass *
+find_ec_matching_expr(PlannerInfo *root,
+					  Expr *expr,
+					  RelOptInfo *baserel)
+{
+	int i = -1;
+	while ((i = bms_next_member(baserel->eclass_indexes, i)) >= 0)
+	{
+		EquivalenceClass *ec = list_nth(root->eq_classes, i);
+		if (find_ec_member_matching_expr(ec, expr, baserel->relids))
+			return ec;
+	}
+	return NULL;
+}
+
 /*
  * find_ec_member_matching_expr
  *		Locate an EquivalenceClass member matching the given expr, if any;
@@ -960,6 +980,31 @@ find_em_expr_for_rel(EquivalenceClass *ec, RelOptInfo *rel)
 	return NULL;
 }
 
+
+/*
+ * build_equivalanceclass_list_for_exprs
+ *
+ * 	Given a list of expr, find the related ECs for everyone of them.
+ * if any exprs has no EC related, return NIL.
+ */
+List *
+build_equivalanceclass_list_for_exprs(PlannerInfo *root,
+									  List *exprs,
+									  RelOptInfo *rel)
+{
+	ListCell	*lc;
+	List	*ecs = NIL;
+
+	foreach(lc, exprs)
+	{
+		EquivalenceClass *ec = find_ec_matching_expr(root, lfirst(lc), rel);
+		if (!ec)
+			return NIL;
+		ecs = lappend(ecs, ec);
+	}
+	return ecs;
+}
+
 /*
  * ec_useful_for_merging
  *	check if the ec exists in rel's merageable restrictinfo_lists.
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index 311579d059..5d8493c8d6 100644
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -359,6 +359,25 @@ get_sortgroupclause_tle(SortGroupClause *sgClause,
 	return get_sortgroupref_tle(sgClause->tleSortGroupRef, targetList);
 }
 
+/*
+ * get_tle_from_expr
+ *
+ *	Find the targetlist entry matching the given expr and return it.
+ */
+TargetEntry *
+get_tle_from_expr(Expr *expr, List *targetlist)
+{
+	ListCell	*lc;
+
+	foreach(lc, targetlist)
+	{
+		TargetEntry *tle = (TargetEntry *) lfirst(lc);
+
+		if (equal(tle->expr, expr))
+			return tle;
+	}
+	return NULL;
+}
 /*
  * get_sortgroupclause_expr
  *		Find the targetlist entry matching the given SortGroupClause
diff --git a/src/include/nodes/pg_list.h b/src/include/nodes/pg_list.h
index 30f98c4595..bbe0209d7e 100644
--- a/src/include/nodes/pg_list.h
+++ b/src/include/nodes/pg_list.h
@@ -558,6 +558,8 @@ extern bool list_member_ptr(const List *list, const void *datum);
 extern bool list_member_int(const List *list, int datum);
 extern bool list_member_oid(const List *list, Oid datum);
 
+extern bool list_is_subset_ptr(const List *a, const List *b);
+
 extern pg_nodiscard List *list_delete(List *list, void *datum);
 extern pg_nodiscard List *list_delete_ptr(List *list, void *datum);
 extern pg_nodiscard List *list_delete_int(List *list, int datum);
diff --git a/src/include/optimizer/optimizer.h b/src/include/optimizer/optimizer.h
index 41b49b2662..5911014a32 100644
--- a/src/include/optimizer/optimizer.h
+++ b/src/include/optimizer/optimizer.h
@@ -171,6 +171,7 @@ extern TargetEntry *get_sortgroupref_tle(Index sortref,
 										 List *targetList);
 extern TargetEntry *get_sortgroupclause_tle(SortGroupClause *sgClause,
 											List *targetList);
+extern TargetEntry *get_tle_from_expr(Expr *expr, List *targetlist);
 extern Node *get_sortgroupclause_expr(SortGroupClause *sgClause,
 									  List *targetList);
 extern List *get_sortgrouplist_exprs(List *sgClauses,
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index a29f616423..e813d82483 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -135,6 +135,9 @@ extern EquivalenceClass *get_eclass_for_sort_expr(PlannerInfo *root,
 												  Index sortref,
 												  Relids rel,
 												  bool create_it);
+extern EquivalenceClass *find_ec_matching_expr(PlannerInfo *root,
+											   Expr *expr,
+											   RelOptInfo *rel);
 extern EquivalenceMember *find_ec_member_matching_expr(EquivalenceClass *ec,
 													   Expr *expr,
 													   Relids relids);
@@ -146,6 +149,9 @@ extern EquivalenceMember *find_computable_ec_member(PlannerInfo *root,
 extern bool ec_useful_for_merging(PlannerInfo *root, RelOptInfo *rel,
 								  EquivalenceClass *ec);
 extern Expr *find_em_expr_for_rel(EquivalenceClass *ec, RelOptInfo *rel);
+extern List *build_equivalanceclass_list_for_exprs(PlannerInfo *root,
+												   List *exprs,
+												   RelOptInfo *rel);
 extern bool relation_can_be_sorted_early(PlannerInfo *root, RelOptInfo *rel,
 										 EquivalenceClass *ec,
 										 bool require_parallel_safe);
-- 
2.21.0

