On Sat, 10 Oct 2020 at 15:45, Hou, Zhijie <houzj.f...@cn.fujitsu.com> wrote:
> I found some code places call list_delete_ptr can be replaced by 
> list_delete_xxxcell which can be faster.
>
> diff --git a/src/backend/optimizer/path/joinpath.c 
> b/src/backend/optimizer/path/joinpath.c
> index db54a6b..61ef7c8 100644
> --- a/src/backend/optimizer/path/joinpath.c
> +++ b/src/backend/optimizer/path/joinpath.c
> @@ -1005,8 +1005,8 @@ sort_inner_and_outer(PlannerInfo *root,
>                 /* Make a pathkey list with this guy first */
>                 if (l != list_head(all_pathkeys))
>                         outerkeys = lcons(front_pathkey,
> -                                                         
> list_delete_ptr(list_copy(all_pathkeys),
> -                                                                             
>             front_pathkey));
> +                                                         
> list_delete_nth_cell(list_copy(all_pathkeys),
> +                                                                             
>                      foreach_current_index(l)));
>                 else
>                         outerkeys = all_pathkeys;       /* no work at first 
> one... */

That looks ok to me. It would be more optimal if we had a method to
move an element to the front of a list, or to any specified position,
but I can't imagine it's worth making such a function just for that.
So what you have there seems fine.

> diff --git a/src/backend/rewrite/rewriteHandler.c 
> b/src/backend/rewrite/rewriteHandler.c
> index fe777c3..d0f15b8 100644
> --- a/src/backend/rewrite/rewriteHandler.c
> +++ b/src/backend/rewrite/rewriteHandler.c
> @@ -650,7 +650,7 @@ adjustJoinTreeList(Query *parsetree, bool removert, int 
> rt_index)
>                         if (IsA(rtr, RangeTblRef) &&
>                                 rtr->rtindex == rt_index)
>                         {
> -                               newjointree = list_delete_ptr(newjointree, 
> rtr);
> +                               newjointree = list_delete_cell(newjointree, 
> l);

I think you may as well just use newjointree =
foreach_delete_current(newjointree, l);.  The comment about why the
list_delete is ok inside a foreach is then irrelevant since
foreach_delete_current() is designed for deleting the current foreach
cell.

Looking around for other places I found two more in equivclass.c.
These two do require an additional moving part to keep track of the
index we want to delete, so they're not quite as clear cut a win to
do. However, I don't think tracking the index makes the code overly
complex, so I'm thinking they're both fine to do. Does anyone think
differently?

Updated patch attached.

David
diff --git a/src/backend/optimizer/path/equivclass.c 
b/src/backend/optimizer/path/equivclass.c
index 823422edad..690b753369 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -137,6 +137,7 @@ process_equivalence(PlannerInfo *root,
        EquivalenceMember *em1,
                           *em2;
        ListCell   *lc1;
+       int                     ec2_idx;
 
        /* Should not already be marked as having generated an eclass */
        Assert(restrictinfo->left_ec == NULL);
@@ -258,6 +259,7 @@ process_equivalence(PlannerInfo *root,
         */
        ec1 = ec2 = NULL;
        em1 = em2 = NULL;
+       ec2_idx = -1;
        foreach(lc1, root->eq_classes)
        {
                EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
@@ -311,6 +313,7 @@ process_equivalence(PlannerInfo *root,
                                equal(item2, cur_em->em_expr))
                        {
                                ec2 = cur_ec;
+                               ec2_idx = foreach_current_index(lc1);
                                em2 = cur_em;
                                if (ec1)
                                        break;
@@ -371,7 +374,7 @@ process_equivalence(PlannerInfo *root,
                ec1->ec_max_security = Max(ec1->ec_max_security,
                                                                   
ec2->ec_max_security);
                ec2->ec_merged = ec1;
-               root->eq_classes = list_delete_ptr(root->eq_classes, ec2);
+               root->eq_classes = list_delete_nth_cell(root->eq_classes, 
ec2_idx);
                /* just to avoid debugging confusion w/ dangling pointers: */
                ec2->ec_members = NIL;
                ec2->ec_sources = NIL;
@@ -1964,6 +1967,7 @@ reconsider_full_join_clause(PlannerInfo *root, 
RestrictInfo *rinfo)
                bool            matchleft;
                bool            matchright;
                ListCell   *lc2;
+               int                     coal_idx = -1;
 
                /* Ignore EC unless it contains pseudoconstants */
                if (!cur_ec->ec_has_const)
@@ -2008,6 +2012,7 @@ reconsider_full_join_clause(PlannerInfo *root, 
RestrictInfo *rinfo)
 
                                if (equal(leftvar, cfirst) && equal(rightvar, 
csecond))
                                {
+                                       coal_idx = foreach_current_index(lc2);
                                        match = true;
                                        break;
                                }
@@ -2072,7 +2077,7 @@ reconsider_full_join_clause(PlannerInfo *root, 
RestrictInfo *rinfo)
                 */
                if (matchleft && matchright)
                {
-                       cur_ec->ec_members = 
list_delete_ptr(cur_ec->ec_members, coal_em);
+                       cur_ec->ec_members = 
list_delete_nth_cell(cur_ec->ec_members, coal_idx);
                        return true;
                }
 
diff --git a/src/backend/optimizer/path/joinpath.c 
b/src/backend/optimizer/path/joinpath.c
index db54a6ba2e..4a35903b29 100644
--- a/src/backend/optimizer/path/joinpath.c
+++ b/src/backend/optimizer/path/joinpath.c
@@ -1005,8 +1005,8 @@ sort_inner_and_outer(PlannerInfo *root,
                /* Make a pathkey list with this guy first */
                if (l != list_head(all_pathkeys))
                        outerkeys = lcons(front_pathkey,
-                                                         
list_delete_ptr(list_copy(all_pathkeys),
-                                                                               
          front_pathkey));
+                                                         
list_delete_nth_cell(list_copy(all_pathkeys),
+                                                                               
                   foreach_current_index(l)));
                else
                        outerkeys = all_pathkeys;       /* no work at first 
one... */
 
diff --git a/src/backend/rewrite/rewriteHandler.c 
b/src/backend/rewrite/rewriteHandler.c
index fe777c3103..1faaafab08 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -650,11 +650,7 @@ adjustJoinTreeList(Query *parsetree, bool removert, int 
rt_index)
                        if (IsA(rtr, RangeTblRef) &&
                                rtr->rtindex == rt_index)
                        {
-                               newjointree = list_delete_ptr(newjointree, rtr);
-
-                               /*
-                                * foreach is safe because we exit loop after 
list_delete...
-                                */
+                               newjointree = 
foreach_delete_current(newjointree, l);
                                break;
                        }
                }

Reply via email to