From f2d62ff4ceca2a33e557e5fb8bc4a2f6f3de872a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=80=E6=8C=83?= Date: Sun, 25 Jul 2021 16:26:45 +0800 Subject: [PATCH v3 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