LCOV - code coverage report
Current view: top level - src/backend/nodes - list.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 88.3 % 409 361
Test Date: 2026-08-17 23:15:54 Functions: 89.4 % 66 59
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 78.4 % 296 232

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * list.c
       4                 :             :  *    implementation for PostgreSQL generic list package
       5                 :             :  *
       6                 :             :  * See comments in pg_list.h.
       7                 :             :  *
       8                 :             :  *
       9                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      10                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
      11                 :             :  *
      12                 :             :  *
      13                 :             :  * IDENTIFICATION
      14                 :             :  *    src/backend/nodes/list.c
      15                 :             :  *
      16                 :             :  *-------------------------------------------------------------------------
      17                 :             :  */
      18                 :             : #include "postgres.h"
      19                 :             : 
      20                 :             : #include "common/int.h"
      21                 :             : #include "nodes/pg_list.h"
      22                 :             : #include "port/pg_bitutils.h"
      23                 :             : #include "utils/memdebug.h"
      24                 :             : #include "utils/memutils.h"
      25                 :             : 
      26                 :             : 
      27                 :             : /*
      28                 :             :  * The previous List implementation, since it used a separate palloc chunk
      29                 :             :  * for each cons cell, had the property that adding or deleting list cells
      30                 :             :  * did not move the storage of other existing cells in the list.  Quite a
      31                 :             :  * bit of existing code depended on that, by retaining ListCell pointers
      32                 :             :  * across such operations on a list.  There is no such guarantee in this
      33                 :             :  * implementation, so instead we have debugging support that is meant to
      34                 :             :  * help flush out now-broken assumptions.  Defining DEBUG_LIST_MEMORY_USAGE
      35                 :             :  * while building this file causes the List operations to forcibly move
      36                 :             :  * all cells in a list whenever a cell is added or deleted.  In combination
      37                 :             :  * with MEMORY_CONTEXT_CHECKING and/or Valgrind, this can usually expose
      38                 :             :  * broken code.  It's a bit expensive though, as there's many more palloc
      39                 :             :  * cycles and a lot more data-copying than in a default build.
      40                 :             :  *
      41                 :             :  * By default, we enable this when building for Valgrind.
      42                 :             :  */
      43                 :             : #ifdef USE_VALGRIND
      44                 :             : #define DEBUG_LIST_MEMORY_USAGE
      45                 :             : #endif
      46                 :             : 
      47                 :             : /* Overhead for the fixed part of a List header, measured in ListCells */
      48                 :             : #define LIST_HEADER_OVERHEAD  \
      49                 :             :     ((int) ((offsetof(List, initial_elements) - 1) / sizeof(ListCell) + 1))
      50                 :             : 
      51                 :             : /*
      52                 :             :  * Macros to simplify writing assertions about the type of a list; a
      53                 :             :  * NIL list is considered to be an empty list of any type.
      54                 :             :  */
      55                 :             : #define IsPointerList(l)        ((l) == NIL || IsA((l), List))
      56                 :             : #define IsIntegerList(l)        ((l) == NIL || IsA((l), IntList))
      57                 :             : #define IsOidList(l)            ((l) == NIL || IsA((l), OidList))
      58                 :             : #define IsXidList(l)            ((l) == NIL || IsA((l), XidList))
      59                 :             : 
      60                 :             : #ifdef USE_ASSERT_CHECKING
      61                 :             : /*
      62                 :             :  * Check that the specified List is valid (so far as we can tell).
      63                 :             :  */
      64                 :             : static void
      65                 :             : check_list_invariants(const List *list)
      66                 :             : {
      67                 :             :     if (list == NIL)
      68                 :             :         return;
      69                 :             : 
      70                 :             :     Assert(list->length > 0);
      71                 :             :     Assert(list->length <= list->max_length);
      72                 :             :     Assert(list->elements != NULL);
      73                 :             : 
      74                 :             :     Assert(list->type == T_List ||
      75                 :             :            list->type == T_IntList ||
      76                 :             :            list->type == T_OidList ||
      77                 :             :            list->type == T_XidList);
      78                 :             : }
      79                 :             : #else
      80                 :             : #define check_list_invariants(l)  ((void) 0)
      81                 :             : #endif                          /* USE_ASSERT_CHECKING */
      82                 :             : 
      83                 :             : /*
      84                 :             :  * Return a freshly allocated List with room for at least min_size cells.
      85                 :             :  *
      86                 :             :  * Since empty non-NIL lists are invalid, new_list() sets the initial length
      87                 :             :  * to min_size, effectively marking that number of cells as valid; the caller
      88                 :             :  * is responsible for filling in their data.
      89                 :             :  */
      90                 :             : static List *
      91                 :    84942797 : new_list(NodeTag type, int min_size)
      92                 :             : {
      93                 :             :     List       *newlist;
      94                 :             :     int         max_size;
      95                 :             : 
      96                 :             :     Assert(min_size > 0);
      97                 :             : 
      98                 :             :     /*
      99                 :             :      * We allocate all the requested cells, and possibly some more, as part of
     100                 :             :      * the same palloc request as the List header.  This is a big win for the
     101                 :             :      * typical case of short fixed-length lists.  It can lose if we allocate a
     102                 :             :      * moderately long list and then it gets extended; we'll be wasting more
     103                 :             :      * initial_elements[] space than if we'd made the header small.  However,
     104                 :             :      * rounding up the request as we do in the normal code path provides some
     105                 :             :      * defense against small extensions.
     106                 :             :      */
     107                 :             : 
     108                 :             : #ifndef DEBUG_LIST_MEMORY_USAGE
     109                 :             : 
     110                 :             :     /*
     111                 :             :      * Normally, we set up a list with some extra cells, to allow it to grow
     112                 :             :      * without a repalloc.  Prefer cell counts chosen to make the total
     113                 :             :      * allocation a power-of-2, since palloc would round it up to that anyway.
     114                 :             :      * (That stops being true for very large allocations, but very long lists
     115                 :             :      * are infrequent, so it doesn't seem worth special logic for such cases.)
     116                 :             :      *
     117                 :             :      * The minimum allocation is 8 ListCell units, providing either 4 or 5
     118                 :             :      * available ListCells depending on the machine's word width.  Counting
     119                 :             :      * palloc's overhead, this uses the same amount of space as a one-cell
     120                 :             :      * list did in the old implementation, and less space for any longer list.
     121                 :             :      *
     122                 :             :      * We needn't worry about integer overflow; no caller passes min_size
     123                 :             :      * that's more than twice the size of an existing list, so the size limits
     124                 :             :      * within palloc will ensure that we don't overflow here.
     125                 :             :      */
     126                 :    84942797 :     max_size = pg_nextpower2_32(Max(8, min_size + LIST_HEADER_OVERHEAD));
     127                 :    84942797 :     max_size -= LIST_HEADER_OVERHEAD;
     128                 :             : #else
     129                 :             : 
     130                 :             :     /*
     131                 :             :      * For debugging, don't allow any extra space.  This forces any cell
     132                 :             :      * addition to go through enlarge_list() and thus move the existing data.
     133                 :             :      */
     134                 :             :     max_size = min_size;
     135                 :             : #endif
     136                 :             : 
     137                 :    84942797 :     newlist = (List *) palloc(offsetof(List, initial_elements) +
     138                 :             :                               max_size * sizeof(ListCell));
     139                 :    84942797 :     newlist->type = type;
     140                 :    84942797 :     newlist->length = min_size;
     141                 :    84942797 :     newlist->max_length = max_size;
     142                 :    84942797 :     newlist->elements = newlist->initial_elements;
     143                 :             : 
     144                 :    84942797 :     return newlist;
     145                 :             : }
     146                 :             : 
     147                 :             : /*
     148                 :             :  * Enlarge an existing non-NIL List to have room for at least min_size cells.
     149                 :             :  *
     150                 :             :  * This does *not* update list->length, as some callers would find that
     151                 :             :  * inconvenient.  (list->length had better be the correct number of existing
     152                 :             :  * valid cells, though.)
     153                 :             :  */
     154                 :             : static void
     155                 :     4079404 : enlarge_list(List *list, int min_size)
     156                 :             : {
     157                 :             :     int         new_max_len;
     158                 :             : 
     159                 :             :     Assert(min_size > list->max_length);  /* else we shouldn't be here */
     160                 :             : 
     161                 :             : #ifndef DEBUG_LIST_MEMORY_USAGE
     162                 :             : 
     163                 :             :     /*
     164                 :             :      * As above, we prefer power-of-two total allocations; but here we need
     165                 :             :      * not account for list header overhead.
     166                 :             :      */
     167                 :             : 
     168                 :             :     /* clamp the minimum value to 16, a semi-arbitrary small power of 2 */
     169                 :     4079404 :     new_max_len = pg_nextpower2_32(Max(16, min_size));
     170                 :             : 
     171                 :             : #else
     172                 :             :     /* As above, don't allocate anything extra */
     173                 :             :     new_max_len = min_size;
     174                 :             : #endif
     175                 :             : 
     176         [ +  + ]:     4079404 :     if (list->elements == list->initial_elements)
     177                 :             :     {
     178                 :             :         /*
     179                 :             :          * Replace original in-line allocation with a separate palloc block.
     180                 :             :          * Ensure it is in the same memory context as the List header.  (The
     181                 :             :          * previous List implementation did not offer any guarantees about
     182                 :             :          * keeping all list cells in the same context, but it seems reasonable
     183                 :             :          * to create such a guarantee now.)
     184                 :             :          */
     185                 :     2565997 :         list->elements = (ListCell *)
     186                 :     2565997 :             MemoryContextAlloc(GetMemoryChunkContext(list),
     187                 :             :                                new_max_len * sizeof(ListCell));
     188                 :     2565997 :         memcpy(list->elements, list->initial_elements,
     189                 :     2565997 :                list->length * sizeof(ListCell));
     190                 :             : 
     191                 :             :         /*
     192                 :             :          * We must not move the list header, so it's unsafe to try to reclaim
     193                 :             :          * the initial_elements[] space via repalloc.  In debugging builds,
     194                 :             :          * however, we can clear that space and/or mark it inaccessible.
     195                 :             :          * (wipe_mem includes VALGRIND_MAKE_MEM_NOACCESS.)
     196                 :             :          */
     197                 :             : #ifdef CLOBBER_FREED_MEMORY
     198                 :             :         wipe_mem(list->initial_elements,
     199                 :             :                  list->max_length * sizeof(ListCell));
     200                 :             : #else
     201                 :             :         VALGRIND_MAKE_MEM_NOACCESS(list->initial_elements,
     202                 :             :                                    list->max_length * sizeof(ListCell));
     203                 :             : #endif
     204                 :             :     }
     205                 :             :     else
     206                 :             :     {
     207                 :             : #ifndef DEBUG_LIST_MEMORY_USAGE
     208                 :             :         /* Normally, let repalloc deal with enlargement */
     209                 :     1513407 :         list->elements = repalloc_array(list->elements, ListCell, new_max_len);
     210                 :             : #else
     211                 :             :         /*
     212                 :             :          * repalloc() might enlarge the space in-place, which we don't want
     213                 :             :          * for debugging purposes, so forcibly move the data somewhere else.
     214                 :             :          */
     215                 :             :         ListCell   *newelements;
     216                 :             : 
     217                 :             :         newelements = (ListCell *)
     218                 :             :             MemoryContextAlloc(GetMemoryChunkContext(list),
     219                 :             :                                new_max_len * sizeof(ListCell));
     220                 :             :         memcpy(newelements, list->elements,
     221                 :             :                list->length * sizeof(ListCell));
     222                 :             :         pfree(list->elements);
     223                 :             :         list->elements = newelements;
     224                 :             : #endif
     225                 :             :     }
     226                 :             : 
     227                 :     4079404 :     list->max_length = new_max_len;
     228                 :     4079404 : }
     229                 :             : 
     230                 :             : /*
     231                 :             :  * Convenience functions to construct short Lists from given values.
     232                 :             :  * (These are normally invoked via the list_makeN macros.)
     233                 :             :  */
     234                 :             : List *
     235                 :     9571207 : list_make1_impl(NodeTag t, ListCell datum1)
     236                 :             : {
     237                 :     9571207 :     List       *list = new_list(t, 1);
     238                 :             : 
     239                 :     9571207 :     list->elements[0] = datum1;
     240                 :             :     check_list_invariants(list);
     241                 :     9571207 :     return list;
     242                 :             : }
     243                 :             : 
     244                 :             : List *
     245                 :     1165707 : list_make2_impl(NodeTag t, ListCell datum1, ListCell datum2)
     246                 :             : {
     247                 :     1165707 :     List       *list = new_list(t, 2);
     248                 :             : 
     249                 :     1165707 :     list->elements[0] = datum1;
     250                 :     1165707 :     list->elements[1] = datum2;
     251                 :             :     check_list_invariants(list);
     252                 :     1165707 :     return list;
     253                 :             : }
     254                 :             : 
     255                 :             : List *
     256                 :        5009 : list_make3_impl(NodeTag t, ListCell datum1, ListCell datum2,
     257                 :             :                 ListCell datum3)
     258                 :             : {
     259                 :        5009 :     List       *list = new_list(t, 3);
     260                 :             : 
     261                 :        5009 :     list->elements[0] = datum1;
     262                 :        5009 :     list->elements[1] = datum2;
     263                 :        5009 :     list->elements[2] = datum3;
     264                 :             :     check_list_invariants(list);
     265                 :        5009 :     return list;
     266                 :             : }
     267                 :             : 
     268                 :             : List *
     269                 :         131 : list_make4_impl(NodeTag t, ListCell datum1, ListCell datum2,
     270                 :             :                 ListCell datum3, ListCell datum4)
     271                 :             : {
     272                 :         131 :     List       *list = new_list(t, 4);
     273                 :             : 
     274                 :         131 :     list->elements[0] = datum1;
     275                 :         131 :     list->elements[1] = datum2;
     276                 :         131 :     list->elements[2] = datum3;
     277                 :         131 :     list->elements[3] = datum4;
     278                 :             :     check_list_invariants(list);
     279                 :         131 :     return list;
     280                 :             : }
     281                 :             : 
     282                 :             : List *
     283                 :         171 : list_make5_impl(NodeTag t, ListCell datum1, ListCell datum2,
     284                 :             :                 ListCell datum3, ListCell datum4, ListCell datum5)
     285                 :             : {
     286                 :         171 :     List       *list = new_list(t, 5);
     287                 :             : 
     288                 :         171 :     list->elements[0] = datum1;
     289                 :         171 :     list->elements[1] = datum2;
     290                 :         171 :     list->elements[2] = datum3;
     291                 :         171 :     list->elements[3] = datum4;
     292                 :         171 :     list->elements[4] = datum5;
     293                 :             :     check_list_invariants(list);
     294                 :         171 :     return list;
     295                 :             : }
     296                 :             : 
     297                 :             : /*
     298                 :             :  * Make room for a new head cell in the given (non-NIL) list.
     299                 :             :  *
     300                 :             :  * The data in the new head cell is undefined; the caller should be
     301                 :             :  * sure to fill it in
     302                 :             :  */
     303                 :             : static void
     304                 :     2263889 : new_head_cell(List *list)
     305                 :             : {
     306                 :             :     /* Enlarge array if necessary */
     307         [ +  + ]:     2263889 :     if (list->length >= list->max_length)
     308                 :       39871 :         enlarge_list(list, list->length + 1);
     309                 :             :     /* Now shove the existing data over */
     310                 :     2263889 :     memmove(&list->elements[1], &list->elements[0],
     311                 :     2263889 :             list->length * sizeof(ListCell));
     312                 :     2263889 :     list->length++;
     313                 :     2263889 : }
     314                 :             : 
     315                 :             : /*
     316                 :             :  * Make room for a new tail cell in the given (non-NIL) list.
     317                 :             :  *
     318                 :             :  * The data in the new tail cell is undefined; the caller should be
     319                 :             :  * sure to fill it in
     320                 :             :  */
     321                 :             : static void
     322                 :    67948057 : new_tail_cell(List *list)
     323                 :             : {
     324                 :             :     /* Enlarge array if necessary */
     325         [ +  + ]:    67948057 :     if (list->length >= list->max_length)
     326                 :     4019158 :         enlarge_list(list, list->length + 1);
     327                 :    67948057 :     list->length++;
     328                 :    67948057 : }
     329                 :             : 
     330                 :             : /*
     331                 :             :  * Append a pointer to the list. A pointer to the modified list is
     332                 :             :  * returned. Note that this function may or may not destructively
     333                 :             :  * modify the list; callers should always use this function's return
     334                 :             :  * value, rather than continuing to use the pointer passed as the
     335                 :             :  * first argument.
     336                 :             :  */
     337                 :             : List *
     338                 :   104332206 : lappend(List *list, void *datum)
     339                 :             : {
     340                 :             :     Assert(IsPointerList(list));
     341                 :             : 
     342         [ +  + ]:   104332206 :     if (list == NIL)
     343                 :    43648241 :         list = new_list(T_List, 1);
     344                 :             :     else
     345                 :    60683965 :         new_tail_cell(list);
     346                 :             : 
     347                 :   104332206 :     llast(list) = datum;
     348                 :             :     check_list_invariants(list);
     349                 :   104332206 :     return list;
     350                 :             : }
     351                 :             : 
     352                 :             : /*
     353                 :             :  * Append an integer to the specified list. See lappend()
     354                 :             :  */
     355                 :             : List *
     356                 :     6910848 : lappend_int(List *list, int datum)
     357                 :             : {
     358                 :             :     Assert(IsIntegerList(list));
     359                 :             : 
     360         [ +  + ]:     6910848 :     if (list == NIL)
     361                 :     1248403 :         list = new_list(T_IntList, 1);
     362                 :             :     else
     363                 :     5662445 :         new_tail_cell(list);
     364                 :             : 
     365                 :     6910848 :     llast_int(list) = datum;
     366                 :             :     check_list_invariants(list);
     367                 :     6910848 :     return list;
     368                 :             : }
     369                 :             : 
     370                 :             : /*
     371                 :             :  * Append an OID to the specified list. See lappend()
     372                 :             :  */
     373                 :             : List *
     374                 :     5435009 : lappend_oid(List *list, Oid datum)
     375                 :             : {
     376                 :             :     Assert(IsOidList(list));
     377                 :             : 
     378         [ +  + ]:     5435009 :     if (list == NIL)
     379                 :     3833392 :         list = new_list(T_OidList, 1);
     380                 :             :     else
     381                 :     1601617 :         new_tail_cell(list);
     382                 :             : 
     383                 :     5435009 :     llast_oid(list) = datum;
     384                 :             :     check_list_invariants(list);
     385                 :     5435009 :     return list;
     386                 :             : }
     387                 :             : 
     388                 :             : /*
     389                 :             :  * Append a TransactionId to the specified list. See lappend()
     390                 :             :  */
     391                 :             : List *
     392                 :          87 : lappend_xid(List *list, TransactionId datum)
     393                 :             : {
     394                 :             :     Assert(IsXidList(list));
     395                 :             : 
     396         [ +  + ]:          87 :     if (list == NIL)
     397                 :          57 :         list = new_list(T_XidList, 1);
     398                 :             :     else
     399                 :          30 :         new_tail_cell(list);
     400                 :             : 
     401                 :          87 :     llast_xid(list) = datum;
     402                 :             :     check_list_invariants(list);
     403                 :          87 :     return list;
     404                 :             : }
     405                 :             : 
     406                 :             : /*
     407                 :             :  * Make room for a new cell at position 'pos' (measured from 0).
     408                 :             :  * The data in the cell is left undefined, and must be filled in by the
     409                 :             :  * caller. 'list' is assumed to be non-NIL, and 'pos' must be a valid
     410                 :             :  * list position, ie, 0 <= pos <= list's length.
     411                 :             :  * Returns address of the new cell.
     412                 :             :  */
     413                 :             : static ListCell *
     414                 :      744214 : insert_new_cell(List *list, int pos)
     415                 :             : {
     416                 :             :     Assert(pos >= 0 && pos <= list->length);
     417                 :             : 
     418                 :             :     /* Enlarge array if necessary */
     419         [ +  + ]:      744214 :     if (list->length >= list->max_length)
     420                 :        1323 :         enlarge_list(list, list->length + 1);
     421                 :             :     /* Now shove the existing data over */
     422         [ +  + ]:      744214 :     if (pos < list->length)
     423                 :      321857 :         memmove(&list->elements[pos + 1], &list->elements[pos],
     424                 :      321857 :                 (list->length - pos) * sizeof(ListCell));
     425                 :      744214 :     list->length++;
     426                 :             : 
     427                 :      744214 :     return &list->elements[pos];
     428                 :             : }
     429                 :             : 
     430                 :             : /*
     431                 :             :  * Insert the given datum at position 'pos' (measured from 0) in the list.
     432                 :             :  * 'pos' must be valid, ie, 0 <= pos <= list's length.
     433                 :             :  *
     434                 :             :  * Note that this takes time proportional to the distance to the end of the
     435                 :             :  * list, since the following entries must be moved.
     436                 :             :  */
     437                 :             : List *
     438                 :     2426048 : list_insert_nth(List *list, int pos, void *datum)
     439                 :             : {
     440         [ +  + ]:     2426048 :     if (list == NIL)
     441                 :             :     {
     442                 :             :         Assert(pos == 0);
     443                 :     1681834 :         return list_make1(datum);
     444                 :             :     }
     445                 :             :     Assert(IsPointerList(list));
     446                 :      744214 :     lfirst(insert_new_cell(list, pos)) = datum;
     447                 :             :     check_list_invariants(list);
     448                 :      744214 :     return list;
     449                 :             : }
     450                 :             : 
     451                 :             : List *
     452                 :           0 : list_insert_nth_int(List *list, int pos, int datum)
     453                 :             : {
     454         [ #  # ]:           0 :     if (list == NIL)
     455                 :             :     {
     456                 :             :         Assert(pos == 0);
     457                 :           0 :         return list_make1_int(datum);
     458                 :             :     }
     459                 :             :     Assert(IsIntegerList(list));
     460                 :           0 :     lfirst_int(insert_new_cell(list, pos)) = datum;
     461                 :             :     check_list_invariants(list);
     462                 :           0 :     return list;
     463                 :             : }
     464                 :             : 
     465                 :             : List *
     466                 :           0 : list_insert_nth_oid(List *list, int pos, Oid datum)
     467                 :             : {
     468         [ #  # ]:           0 :     if (list == NIL)
     469                 :             :     {
     470                 :             :         Assert(pos == 0);
     471                 :           0 :         return list_make1_oid(datum);
     472                 :             :     }
     473                 :             :     Assert(IsOidList(list));
     474                 :           0 :     lfirst_oid(insert_new_cell(list, pos)) = datum;
     475                 :             :     check_list_invariants(list);
     476                 :           0 :     return list;
     477                 :             : }
     478                 :             : 
     479                 :             : /*
     480                 :             :  * Prepend a new element to the list. A pointer to the modified list
     481                 :             :  * is returned. Note that this function may or may not destructively
     482                 :             :  * modify the list; callers should always use this function's return
     483                 :             :  * value, rather than continuing to use the pointer passed as the
     484                 :             :  * second argument.
     485                 :             :  *
     486                 :             :  * Note that this takes time proportional to the length of the list,
     487                 :             :  * since the existing entries must be moved.
     488                 :             :  *
     489                 :             :  * Caution: before Postgres 8.0, the original List was unmodified and
     490                 :             :  * could be considered to retain its separate identity.  This is no longer
     491                 :             :  * the case.
     492                 :             :  */
     493                 :             : List *
     494                 :     5405311 : lcons(void *datum, List *list)
     495                 :             : {
     496                 :             :     Assert(IsPointerList(list));
     497                 :             : 
     498         [ +  + ]:     5405311 :     if (list == NIL)
     499                 :     3178671 :         list = new_list(T_List, 1);
     500                 :             :     else
     501                 :     2226640 :         new_head_cell(list);
     502                 :             : 
     503                 :     5405311 :     linitial(list) = datum;
     504                 :             :     check_list_invariants(list);
     505                 :     5405311 :     return list;
     506                 :             : }
     507                 :             : 
     508                 :             : /*
     509                 :             :  * Prepend an integer to the list. See lcons()
     510                 :             :  */
     511                 :             : List *
     512                 :       17234 : lcons_int(int datum, List *list)
     513                 :             : {
     514                 :             :     Assert(IsIntegerList(list));
     515                 :             : 
     516         [ +  + ]:       17234 :     if (list == NIL)
     517                 :        7805 :         list = new_list(T_IntList, 1);
     518                 :             :     else
     519                 :        9429 :         new_head_cell(list);
     520                 :             : 
     521                 :       17234 :     linitial_int(list) = datum;
     522                 :             :     check_list_invariants(list);
     523                 :       17234 :     return list;
     524                 :             : }
     525                 :             : 
     526                 :             : /*
     527                 :             :  * Prepend an OID to the list. See lcons()
     528                 :             :  */
     529                 :             : List *
     530                 :       29991 : lcons_oid(Oid datum, List *list)
     531                 :             : {
     532                 :             :     Assert(IsOidList(list));
     533                 :             : 
     534         [ +  + ]:       29991 :     if (list == NIL)
     535                 :        2171 :         list = new_list(T_OidList, 1);
     536                 :             :     else
     537                 :       27820 :         new_head_cell(list);
     538                 :             : 
     539                 :       29991 :     linitial_oid(list) = datum;
     540                 :             :     check_list_invariants(list);
     541                 :       29991 :     return list;
     542                 :             : }
     543                 :             : 
     544                 :             : /*
     545                 :             :  * Concatenate list2 to the end of list1, and return list1.
     546                 :             :  *
     547                 :             :  * This is equivalent to lappend'ing each element of list2, in order, to list1.
     548                 :             :  * list1 is destructively changed, list2 is not.  (However, in the case of
     549                 :             :  * pointer lists, list1 and list2 will point to the same structures.)
     550                 :             :  *
     551                 :             :  * Callers should be sure to use the return value as the new pointer to the
     552                 :             :  * concatenated list: the 'list1' input pointer may or may not be the same
     553                 :             :  * as the returned pointer.
     554                 :             :  *
     555                 :             :  * Note that this takes at least time proportional to the length of list2.
     556                 :             :  * It'd typically be the case that we have to enlarge list1's storage,
     557                 :             :  * probably adding time proportional to the length of list1.
     558                 :             :  */
     559                 :             : List *
     560                 :     5219053 : list_concat(List *list1, const List *list2)
     561                 :             : {
     562                 :             :     int         new_len;
     563                 :             : 
     564         [ +  + ]:     5219053 :     if (list1 == NIL)
     565                 :     3697172 :         return list_copy(list2);
     566         [ +  + ]:     1521881 :     if (list2 == NIL)
     567                 :      891316 :         return list1;
     568                 :             : 
     569                 :             :     Assert(list1->type == list2->type);
     570                 :             : 
     571                 :      630565 :     new_len = list1->length + list2->length;
     572                 :             :     /* Enlarge array if necessary */
     573         [ +  + ]:      630565 :     if (new_len > list1->max_length)
     574                 :       19052 :         enlarge_list(list1, new_len);
     575                 :             : 
     576                 :             :     /* Even if list1 == list2, using memcpy should be safe here */
     577                 :      630565 :     memcpy(&list1->elements[list1->length], &list2->elements[0],
     578                 :      630565 :            list2->length * sizeof(ListCell));
     579                 :      630565 :     list1->length = new_len;
     580                 :             : 
     581                 :             :     check_list_invariants(list1);
     582                 :      630565 :     return list1;
     583                 :             : }
     584                 :             : 
     585                 :             : /*
     586                 :             :  * Form a new list by concatenating the elements of list1 and list2.
     587                 :             :  *
     588                 :             :  * Neither input list is modified.  (However, if they are pointer lists,
     589                 :             :  * the output list will point to the same structures.)
     590                 :             :  *
     591                 :             :  * This is equivalent to, but more efficient than,
     592                 :             :  * list_concat(list_copy(list1), list2).
     593                 :             :  * Note that some pre-v13 code might list_copy list2 as well, but that's
     594                 :             :  * pointless now.
     595                 :             :  */
     596                 :             : List *
     597                 :      871535 : list_concat_copy(const List *list1, const List *list2)
     598                 :             : {
     599                 :             :     List       *result;
     600                 :             :     int         new_len;
     601                 :             : 
     602         [ +  + ]:      871535 :     if (list1 == NIL)
     603                 :      374880 :         return list_copy(list2);
     604         [ +  + ]:      496655 :     if (list2 == NIL)
     605                 :      415626 :         return list_copy(list1);
     606                 :             : 
     607                 :             :     Assert(list1->type == list2->type);
     608                 :             : 
     609                 :       81029 :     new_len = list1->length + list2->length;
     610                 :       81029 :     result = new_list(list1->type, new_len);
     611                 :       81029 :     memcpy(result->elements, list1->elements,
     612                 :       81029 :            list1->length * sizeof(ListCell));
     613                 :       81029 :     memcpy(result->elements + list1->length, list2->elements,
     614                 :       81029 :            list2->length * sizeof(ListCell));
     615                 :             : 
     616                 :             :     check_list_invariants(result);
     617                 :       81029 :     return result;
     618                 :             : }
     619                 :             : 
     620                 :             : /*
     621                 :             :  * Truncate 'list' to contain no more than 'new_size' elements. This
     622                 :             :  * modifies the list in-place! Despite this, callers should use the
     623                 :             :  * pointer returned by this function to refer to the newly truncated
     624                 :             :  * list -- it may or may not be the same as the pointer that was
     625                 :             :  * passed.
     626                 :             :  *
     627                 :             :  * Note that any cells removed by list_truncate() are NOT pfree'd.
     628                 :             :  */
     629                 :             : List *
     630                 :      536574 : list_truncate(List *list, int new_size)
     631                 :             : {
     632         [ +  + ]:      536574 :     if (new_size <= 0)
     633                 :       58819 :         return NIL;             /* truncate to zero length */
     634                 :             : 
     635                 :             :     /* If asked to effectively extend the list, do nothing */
     636         [ +  + ]:      477755 :     if (new_size < list_length(list))
     637                 :      132609 :         list->length = new_size;
     638                 :             : 
     639                 :             :     /*
     640                 :             :      * Note: unlike the individual-list-cell deletion functions, we don't move
     641                 :             :      * the list cells to new storage, even in DEBUG_LIST_MEMORY_USAGE mode.
     642                 :             :      * This is because none of them can move in this operation, so just like
     643                 :             :      * in the old cons-cell-based implementation, this function doesn't
     644                 :             :      * invalidate any pointers to cells of the list.  This is also the reason
     645                 :             :      * for not wiping the memory of the deleted cells: the old code didn't
     646                 :             :      * free them either.  Perhaps later we'll tighten this up.
     647                 :             :      */
     648                 :             : 
     649                 :      477755 :     return list;
     650                 :             : }
     651                 :             : 
     652                 :             : /*
     653                 :             :  * Return true iff 'datum' is a member of the list. Equality is
     654                 :             :  * determined via equal(), so callers should ensure that they pass a
     655                 :             :  * Node as 'datum'.
     656                 :             :  *
     657                 :             :  * This does a simple linear search --- avoid using it on long lists.
     658                 :             :  */
     659                 :             : bool
     660                 :      882449 : list_member(const List *list, const void *datum)
     661                 :             : {
     662                 :             :     const ListCell *cell;
     663                 :             : 
     664                 :             :     Assert(IsPointerList(list));
     665                 :             :     check_list_invariants(list);
     666                 :             : 
     667   [ +  +  +  +  :     1554850 :     foreach(cell, list)
                   +  + ]
     668                 :             :     {
     669         [ +  + ]:      774138 :         if (equal(lfirst(cell), datum))
     670                 :      101737 :             return true;
     671                 :             :     }
     672                 :             : 
     673                 :      780712 :     return false;
     674                 :             : }
     675                 :             : 
     676                 :             : /*
     677                 :             :  * Return true iff 'datum' is a member of the list. Equality is
     678                 :             :  * determined by using simple pointer comparison.
     679                 :             :  */
     680                 :             : bool
     681                 :      465296 : list_member_ptr(const List *list, const void *datum)
     682                 :             : {
     683                 :             :     const ListCell *cell;
     684                 :             : 
     685                 :             :     Assert(IsPointerList(list));
     686                 :             :     check_list_invariants(list);
     687                 :             : 
     688   [ +  +  +  +  :      752054 :     foreach(cell, list)
                   +  + ]
     689                 :             :     {
     690         [ +  + ]:      465560 :         if (lfirst(cell) == datum)
     691                 :      178802 :             return true;
     692                 :             :     }
     693                 :             : 
     694                 :      286494 :     return false;
     695                 :             : }
     696                 :             : 
     697                 :             : /*
     698                 :             :  * Return true iff the integer 'datum' is a member of the list.
     699                 :             :  */
     700                 :             : bool
     701                 :       89219 : list_member_int(const List *list, int datum)
     702                 :             : {
     703                 :             :     const ListCell *cell;
     704                 :             : 
     705                 :             :     Assert(IsIntegerList(list));
     706                 :             :     check_list_invariants(list);
     707                 :             : 
     708   [ +  +  +  +  :     5036409 :     foreach(cell, list)
                   +  + ]
     709                 :             :     {
     710         [ +  + ]:     4962523 :         if (lfirst_int(cell) == datum)
     711                 :       15333 :             return true;
     712                 :             :     }
     713                 :             : 
     714                 :       73886 :     return false;
     715                 :             : }
     716                 :             : 
     717                 :             : /*
     718                 :             :  * Return true iff the OID 'datum' is a member of the list.
     719                 :             :  */
     720                 :             : bool
     721                 :    63473276 : list_member_oid(const List *list, Oid datum)
     722                 :             : {
     723                 :             :     const ListCell *cell;
     724                 :             : 
     725                 :             :     Assert(IsOidList(list));
     726                 :             :     check_list_invariants(list);
     727                 :             : 
     728   [ +  +  +  +  :    67133689 :     foreach(cell, list)
                   +  + ]
     729                 :             :     {
     730         [ +  + ]:     4585940 :         if (lfirst_oid(cell) == datum)
     731                 :      925527 :             return true;
     732                 :             :     }
     733                 :             : 
     734                 :    62547749 :     return false;
     735                 :             : }
     736                 :             : 
     737                 :             : /*
     738                 :             :  * Return true iff the TransactionId 'datum' is a member of the list.
     739                 :             :  */
     740                 :             : bool
     741                 :      170945 : list_member_xid(const List *list, TransactionId datum)
     742                 :             : {
     743                 :             :     const ListCell *cell;
     744                 :             : 
     745                 :             :     Assert(IsXidList(list));
     746                 :             :     check_list_invariants(list);
     747                 :             : 
     748   [ +  +  +  +  :      211795 :     foreach(cell, list)
                   +  + ]
     749                 :             :     {
     750         [ +  + ]:      211708 :         if (lfirst_xid(cell) == datum)
     751                 :      170858 :             return true;
     752                 :             :     }
     753                 :             : 
     754                 :          87 :     return false;
     755                 :             : }
     756                 :             : 
     757                 :             : /*
     758                 :             :  * Delete the n'th cell (counting from 0) in list.
     759                 :             :  *
     760                 :             :  * The List is pfree'd if this was the last member.
     761                 :             :  *
     762                 :             :  * Note that this takes time proportional to the distance to the end of the
     763                 :             :  * list, since the following entries must be moved.
     764                 :             :  */
     765                 :             : List *
     766                 :     2801858 : list_delete_nth_cell(List *list, int n)
     767                 :             : {
     768                 :             :     check_list_invariants(list);
     769                 :             : 
     770                 :             :     Assert(n >= 0 && n < list->length);
     771                 :             : 
     772                 :             :     /*
     773                 :             :      * If we're about to delete the last node from the list, free the whole
     774                 :             :      * list instead and return NIL, which is the only valid representation of
     775                 :             :      * a zero-length list.
     776                 :             :      */
     777         [ +  + ]:     2801858 :     if (list->length == 1)
     778                 :             :     {
     779                 :     1397351 :         list_free(list);
     780                 :     1397351 :         return NIL;
     781                 :             :     }
     782                 :             : 
     783                 :             :     /*
     784                 :             :      * Otherwise, we normally just collapse out the removed element.  But for
     785                 :             :      * debugging purposes, move the whole list contents someplace else.
     786                 :             :      *
     787                 :             :      * (Note that we *must* keep the contents in the same memory context.)
     788                 :             :      */
     789                 :             : #ifndef DEBUG_LIST_MEMORY_USAGE
     790                 :     1404507 :     memmove(&list->elements[n], &list->elements[n + 1],
     791                 :     1404507 :             (list->length - 1 - n) * sizeof(ListCell));
     792                 :     1404507 :     list->length--;
     793                 :             : #else
     794                 :             :     {
     795                 :             :         ListCell   *newelems;
     796                 :             :         int         newmaxlen = list->length - 1;
     797                 :             : 
     798                 :             :         newelems = (ListCell *)
     799                 :             :             MemoryContextAlloc(GetMemoryChunkContext(list),
     800                 :             :                                newmaxlen * sizeof(ListCell));
     801                 :             :         memcpy(newelems, list->elements, n * sizeof(ListCell));
     802                 :             :         memcpy(&newelems[n], &list->elements[n + 1],
     803                 :             :                (list->length - 1 - n) * sizeof(ListCell));
     804                 :             :         if (list->elements != list->initial_elements)
     805                 :             :             pfree(list->elements);
     806                 :             :         else
     807                 :             :         {
     808                 :             :             /*
     809                 :             :              * As in enlarge_list(), clear the initial_elements[] space and/or
     810                 :             :              * mark it inaccessible.
     811                 :             :              */
     812                 :             : #ifdef CLOBBER_FREED_MEMORY
     813                 :             :             wipe_mem(list->initial_elements,
     814                 :             :                      list->max_length * sizeof(ListCell));
     815                 :             : #else
     816                 :             :             VALGRIND_MAKE_MEM_NOACCESS(list->initial_elements,
     817                 :             :                                        list->max_length * sizeof(ListCell));
     818                 :             : #endif
     819                 :             :         }
     820                 :             :         list->elements = newelems;
     821                 :             :         list->max_length = newmaxlen;
     822                 :             :         list->length--;
     823                 :             :         check_list_invariants(list);
     824                 :             :     }
     825                 :             : #endif
     826                 :             : 
     827                 :     1404507 :     return list;
     828                 :             : }
     829                 :             : 
     830                 :             : /*
     831                 :             :  * Delete 'cell' from 'list'.
     832                 :             :  *
     833                 :             :  * The List is pfree'd if this was the last member.  However, we do not
     834                 :             :  * touch any data the cell might've been pointing to.
     835                 :             :  *
     836                 :             :  * Note that this takes time proportional to the distance to the end of the
     837                 :             :  * list, since the following entries must be moved.
     838                 :             :  */
     839                 :             : List *
     840                 :     1402192 : list_delete_cell(List *list, ListCell *cell)
     841                 :             : {
     842                 :     1402192 :     return list_delete_nth_cell(list, cell - list->elements);
     843                 :             : }
     844                 :             : 
     845                 :             : /*
     846                 :             :  * Delete the first cell in list that matches datum, if any.
     847                 :             :  * Equality is determined via equal().
     848                 :             :  *
     849                 :             :  * This does a simple linear search --- avoid using it on long lists.
     850                 :             :  */
     851                 :             : List *
     852                 :        3798 : list_delete(List *list, void *datum)
     853                 :             : {
     854                 :             :     ListCell   *cell;
     855                 :             : 
     856                 :             :     Assert(IsPointerList(list));
     857                 :             :     check_list_invariants(list);
     858                 :             : 
     859   [ +  +  +  -  :        4040 :     foreach(cell, list)
                   +  + ]
     860                 :             :     {
     861         [ +  + ]:        4037 :         if (equal(lfirst(cell), datum))
     862                 :        3795 :             return list_delete_cell(list, cell);
     863                 :             :     }
     864                 :             : 
     865                 :             :     /* Didn't find a match: return the list unmodified */
     866                 :           3 :     return list;
     867                 :             : }
     868                 :             : 
     869                 :             : /* As above, but use simple pointer equality */
     870                 :             : List *
     871                 :     1387973 : list_delete_ptr(List *list, void *datum)
     872                 :             : {
     873                 :             :     ListCell   *cell;
     874                 :             : 
     875                 :             :     Assert(IsPointerList(list));
     876                 :             :     check_list_invariants(list);
     877                 :             : 
     878   [ +  -  +  -  :     1388343 :     foreach(cell, list)
                   +  - ]
     879                 :             :     {
     880         [ +  + ]:     1388343 :         if (lfirst(cell) == datum)
     881                 :     1387973 :             return list_delete_cell(list, cell);
     882                 :             :     }
     883                 :             : 
     884                 :             :     /* Didn't find a match: return the list unmodified */
     885                 :           0 :     return list;
     886                 :             : }
     887                 :             : 
     888                 :             : /* As above, but for integers */
     889                 :             : List *
     890                 :         144 : list_delete_int(List *list, int datum)
     891                 :             : {
     892                 :             :     ListCell   *cell;
     893                 :             : 
     894                 :             :     Assert(IsIntegerList(list));
     895                 :             :     check_list_invariants(list);
     896                 :             : 
     897   [ +  -  +  -  :         149 :     foreach(cell, list)
                   +  - ]
     898                 :             :     {
     899         [ +  + ]:         149 :         if (lfirst_int(cell) == datum)
     900                 :         144 :             return list_delete_cell(list, cell);
     901                 :             :     }
     902                 :             : 
     903                 :             :     /* Didn't find a match: return the list unmodified */
     904                 :           0 :     return list;
     905                 :             : }
     906                 :             : 
     907                 :             : /* As above, but for OIDs */
     908                 :             : List *
     909                 :        4936 : list_delete_oid(List *list, Oid datum)
     910                 :             : {
     911                 :             :     ListCell   *cell;
     912                 :             : 
     913                 :             :     Assert(IsOidList(list));
     914                 :             :     check_list_invariants(list);
     915                 :             : 
     916   [ +  +  +  -  :        4936 :     foreach(cell, list)
                   +  + ]
     917                 :             :     {
     918         [ +  - ]:        1160 :         if (lfirst_oid(cell) == datum)
     919                 :        1160 :             return list_delete_cell(list, cell);
     920                 :             :     }
     921                 :             : 
     922                 :             :     /* Didn't find a match: return the list unmodified */
     923                 :        3776 :     return list;
     924                 :             : }
     925                 :             : 
     926                 :             : /*
     927                 :             :  * Delete the first element of the list.
     928                 :             :  *
     929                 :             :  * This is useful to replace the Lisp-y code "list = lnext(list);" in cases
     930                 :             :  * where the intent is to alter the list rather than just traverse it.
     931                 :             :  * Beware that the list is modified, whereas the Lisp-y coding leaves
     932                 :             :  * the original list head intact in case there's another pointer to it.
     933                 :             :  *
     934                 :             :  * Note that this takes time proportional to the length of the list,
     935                 :             :  * since the remaining entries must be moved.  Consider reversing the
     936                 :             :  * list order so that you can use list_delete_last() instead.  However,
     937                 :             :  * if that causes you to replace lappend() with lcons(), you haven't
     938                 :             :  * improved matters.  (In short, you can make an efficient stack from
     939                 :             :  * a List, but not an efficient FIFO queue.)
     940                 :             :  */
     941                 :             : List *
     942                 :      635304 : list_delete_first(List *list)
     943                 :             : {
     944                 :             :     check_list_invariants(list);
     945                 :             : 
     946         [ -  + ]:      635304 :     if (list == NIL)
     947                 :           0 :         return NIL;             /* would an error be better? */
     948                 :             : 
     949                 :      635304 :     return list_delete_nth_cell(list, 0);
     950                 :             : }
     951                 :             : 
     952                 :             : /*
     953                 :             :  * Delete the last element of the list.
     954                 :             :  */
     955                 :             : List *
     956                 :       70752 : list_delete_last(List *list)
     957                 :             : {
     958                 :             :     check_list_invariants(list);
     959                 :             : 
     960         [ -  + ]:       70752 :     if (list == NIL)
     961                 :           0 :         return NIL;             /* would an error be better? */
     962                 :             : 
     963                 :             :     /* list_truncate won't free list if it goes to empty, but this should */
     964         [ +  + ]:       70752 :     if (list_length(list) <= 1)
     965                 :             :     {
     966                 :       18490 :         list_free(list);
     967                 :       18490 :         return NIL;
     968                 :             :     }
     969                 :             : 
     970                 :       52262 :     return list_truncate(list, list_length(list) - 1);
     971                 :             : }
     972                 :             : 
     973                 :             : /*
     974                 :             :  * Delete the first N cells of the list.
     975                 :             :  *
     976                 :             :  * The List is pfree'd if the request causes all cells to be deleted.
     977                 :             :  *
     978                 :             :  * Note that this takes time proportional to the distance to the end of the
     979                 :             :  * list, since the following entries must be moved.
     980                 :             :  */
     981                 :             : List *
     982                 :         476 : list_delete_first_n(List *list, int n)
     983                 :             : {
     984                 :             :     check_list_invariants(list);
     985                 :             : 
     986                 :             :     /* No-op request? */
     987         [ +  + ]:         476 :     if (n <= 0)
     988                 :          10 :         return list;
     989                 :             : 
     990                 :             :     /* Delete whole list? */
     991         [ -  + ]:         466 :     if (n >= list_length(list))
     992                 :             :     {
     993                 :           0 :         list_free(list);
     994                 :           0 :         return NIL;
     995                 :             :     }
     996                 :             : 
     997                 :             :     /*
     998                 :             :      * Otherwise, we normally just collapse out the removed elements.  But for
     999                 :             :      * debugging purposes, move the whole list contents someplace else.
    1000                 :             :      *
    1001                 :             :      * (Note that we *must* keep the contents in the same memory context.)
    1002                 :             :      */
    1003                 :             : #ifndef DEBUG_LIST_MEMORY_USAGE
    1004                 :         466 :     memmove(&list->elements[0], &list->elements[n],
    1005                 :         466 :             (list->length - n) * sizeof(ListCell));
    1006                 :         466 :     list->length -= n;
    1007                 :             : #else
    1008                 :             :     {
    1009                 :             :         ListCell   *newelems;
    1010                 :             :         int         newmaxlen = list->length - n;
    1011                 :             : 
    1012                 :             :         newelems = (ListCell *)
    1013                 :             :             MemoryContextAlloc(GetMemoryChunkContext(list),
    1014                 :             :                                newmaxlen * sizeof(ListCell));
    1015                 :             :         memcpy(newelems, &list->elements[n], newmaxlen * sizeof(ListCell));
    1016                 :             :         if (list->elements != list->initial_elements)
    1017                 :             :             pfree(list->elements);
    1018                 :             :         else
    1019                 :             :         {
    1020                 :             :             /*
    1021                 :             :              * As in enlarge_list(), clear the initial_elements[] space and/or
    1022                 :             :              * mark it inaccessible.
    1023                 :             :              */
    1024                 :             : #ifdef CLOBBER_FREED_MEMORY
    1025                 :             :             wipe_mem(list->initial_elements,
    1026                 :             :                      list->max_length * sizeof(ListCell));
    1027                 :             : #else
    1028                 :             :             VALGRIND_MAKE_MEM_NOACCESS(list->initial_elements,
    1029                 :             :                                        list->max_length * sizeof(ListCell));
    1030                 :             : #endif
    1031                 :             :         }
    1032                 :             :         list->elements = newelems;
    1033                 :             :         list->max_length = newmaxlen;
    1034                 :             :         list->length = newmaxlen;
    1035                 :             :         check_list_invariants(list);
    1036                 :             :     }
    1037                 :             : #endif
    1038                 :             : 
    1039                 :         466 :     return list;
    1040                 :             : }
    1041                 :             : 
    1042                 :             : /*
    1043                 :             :  * Generate the union of two lists. This is calculated by copying
    1044                 :             :  * list1 via list_copy(), then adding to it all the members of list2
    1045                 :             :  * that aren't already in list1.
    1046                 :             :  *
    1047                 :             :  * Whether an element is already a member of the list is determined
    1048                 :             :  * via equal().
    1049                 :             :  *
    1050                 :             :  * The returned list is newly-allocated, although the content of the
    1051                 :             :  * cells is the same (i.e. any pointed-to objects are not copied).
    1052                 :             :  *
    1053                 :             :  * NB: this function will NOT remove any duplicates that are present
    1054                 :             :  * in list1 (so it only performs a "union" if list1 is known unique to
    1055                 :             :  * start with).  Also, if you are about to write "x = list_union(x, y)"
    1056                 :             :  * you probably want to use list_concat_unique() instead to avoid wasting
    1057                 :             :  * the storage of the old x list.
    1058                 :             :  *
    1059                 :             :  * Note that this takes time proportional to the product of the list
    1060                 :             :  * lengths, so beware of using it on long lists.  (We could probably
    1061                 :             :  * improve that, but really you should be using some other data structure
    1062                 :             :  * if this'd be a performance bottleneck.)
    1063                 :             :  */
    1064                 :             : List *
    1065                 :        8756 : list_union(const List *list1, const List *list2)
    1066                 :             : {
    1067                 :             :     List       *result;
    1068                 :             :     const ListCell *cell;
    1069                 :             : 
    1070                 :             :     Assert(IsPointerList(list1));
    1071                 :             :     Assert(IsPointerList(list2));
    1072                 :             : 
    1073                 :        8756 :     result = list_copy(list1);
    1074   [ +  +  +  +  :       17964 :     foreach(cell, list2)
                   +  + ]
    1075                 :             :     {
    1076         [ +  + ]:        9208 :         if (!list_member(result, lfirst(cell)))
    1077                 :        9146 :             result = lappend(result, lfirst(cell));
    1078                 :             :     }
    1079                 :             : 
    1080                 :             :     check_list_invariants(result);
    1081                 :        8756 :     return result;
    1082                 :             : }
    1083                 :             : 
    1084                 :             : /*
    1085                 :             :  * This variant of list_union() determines duplicates via simple
    1086                 :             :  * pointer comparison.
    1087                 :             :  */
    1088                 :             : List *
    1089                 :           0 : list_union_ptr(const List *list1, const List *list2)
    1090                 :             : {
    1091                 :             :     List       *result;
    1092                 :             :     const ListCell *cell;
    1093                 :             : 
    1094                 :             :     Assert(IsPointerList(list1));
    1095                 :             :     Assert(IsPointerList(list2));
    1096                 :             : 
    1097                 :           0 :     result = list_copy(list1);
    1098   [ #  #  #  #  :           0 :     foreach(cell, list2)
                   #  # ]
    1099                 :             :     {
    1100         [ #  # ]:           0 :         if (!list_member_ptr(result, lfirst(cell)))
    1101                 :           0 :             result = lappend(result, lfirst(cell));
    1102                 :             :     }
    1103                 :             : 
    1104                 :             :     check_list_invariants(result);
    1105                 :           0 :     return result;
    1106                 :             : }
    1107                 :             : 
    1108                 :             : /*
    1109                 :             :  * This variant of list_union() operates upon lists of integers.
    1110                 :             :  */
    1111                 :             : List *
    1112                 :        5211 : list_union_int(const List *list1, const List *list2)
    1113                 :             : {
    1114                 :             :     List       *result;
    1115                 :             :     const ListCell *cell;
    1116                 :             : 
    1117                 :             :     Assert(IsIntegerList(list1));
    1118                 :             :     Assert(IsIntegerList(list2));
    1119                 :             : 
    1120                 :        5211 :     result = list_copy(list1);
    1121   [ +  +  +  +  :       10362 :     foreach(cell, list2)
                   +  + ]
    1122                 :             :     {
    1123         [ +  + ]:        5151 :         if (!list_member_int(result, lfirst_int(cell)))
    1124                 :        4983 :             result = lappend_int(result, lfirst_int(cell));
    1125                 :             :     }
    1126                 :             : 
    1127                 :             :     check_list_invariants(result);
    1128                 :        5211 :     return result;
    1129                 :             : }
    1130                 :             : 
    1131                 :             : /*
    1132                 :             :  * This variant of list_union() operates upon lists of OIDs.
    1133                 :             :  */
    1134                 :             : List *
    1135                 :           0 : list_union_oid(const List *list1, const List *list2)
    1136                 :             : {
    1137                 :             :     List       *result;
    1138                 :             :     const ListCell *cell;
    1139                 :             : 
    1140                 :             :     Assert(IsOidList(list1));
    1141                 :             :     Assert(IsOidList(list2));
    1142                 :             : 
    1143                 :           0 :     result = list_copy(list1);
    1144   [ #  #  #  #  :           0 :     foreach(cell, list2)
                   #  # ]
    1145                 :             :     {
    1146         [ #  # ]:           0 :         if (!list_member_oid(result, lfirst_oid(cell)))
    1147                 :           0 :             result = lappend_oid(result, lfirst_oid(cell));
    1148                 :             :     }
    1149                 :             : 
    1150                 :             :     check_list_invariants(result);
    1151                 :           0 :     return result;
    1152                 :             : }
    1153                 :             : 
    1154                 :             : /*
    1155                 :             :  * Return a list that contains all the cells that are in both list1 and
    1156                 :             :  * list2.  The returned list is freshly allocated via palloc(), but the
    1157                 :             :  * cells themselves point to the same objects as the cells of the
    1158                 :             :  * input lists.
    1159                 :             :  *
    1160                 :             :  * Duplicate entries in list1 will not be suppressed, so it's only a true
    1161                 :             :  * "intersection" if list1 is known unique beforehand.
    1162                 :             :  *
    1163                 :             :  * This variant works on lists of pointers, and determines list
    1164                 :             :  * membership via equal().  Note that the list1 member will be pointed
    1165                 :             :  * to in the result.
    1166                 :             :  *
    1167                 :             :  * Note that this takes time proportional to the product of the list
    1168                 :             :  * lengths, so beware of using it on long lists.  (We could probably
    1169                 :             :  * improve that, but really you should be using some other data structure
    1170                 :             :  * if this'd be a performance bottleneck.)
    1171                 :             :  */
    1172                 :             : List *
    1173                 :           0 : list_intersection(const List *list1, const List *list2)
    1174                 :             : {
    1175                 :             :     List       *result;
    1176                 :             :     const ListCell *cell;
    1177                 :             : 
    1178   [ #  #  #  # ]:           0 :     if (list1 == NIL || list2 == NIL)
    1179                 :           0 :         return NIL;
    1180                 :             : 
    1181                 :             :     Assert(IsPointerList(list1));
    1182                 :             :     Assert(IsPointerList(list2));
    1183                 :             : 
    1184                 :           0 :     result = NIL;
    1185   [ #  #  #  #  :           0 :     foreach(cell, list1)
                   #  # ]
    1186                 :             :     {
    1187         [ #  # ]:           0 :         if (list_member(list2, lfirst(cell)))
    1188                 :           0 :             result = lappend(result, lfirst(cell));
    1189                 :             :     }
    1190                 :             : 
    1191                 :             :     check_list_invariants(result);
    1192                 :           0 :     return result;
    1193                 :             : }
    1194                 :             : 
    1195                 :             : /*
    1196                 :             :  * As list_intersection but operates on lists of integers.
    1197                 :             :  */
    1198                 :             : List *
    1199                 :         354 : list_intersection_int(const List *list1, const List *list2)
    1200                 :             : {
    1201                 :             :     List       *result;
    1202                 :             :     const ListCell *cell;
    1203                 :             : 
    1204   [ +  -  -  + ]:         354 :     if (list1 == NIL || list2 == NIL)
    1205                 :           0 :         return NIL;
    1206                 :             : 
    1207                 :             :     Assert(IsIntegerList(list1));
    1208                 :             :     Assert(IsIntegerList(list2));
    1209                 :             : 
    1210                 :         354 :     result = NIL;
    1211   [ +  -  +  +  :         740 :     foreach(cell, list1)
                   +  + ]
    1212                 :             :     {
    1213         [ +  + ]:         386 :         if (list_member_int(list2, lfirst_int(cell)))
    1214                 :         156 :             result = lappend_int(result, lfirst_int(cell));
    1215                 :             :     }
    1216                 :             : 
    1217                 :             :     check_list_invariants(result);
    1218                 :         354 :     return result;
    1219                 :             : }
    1220                 :             : 
    1221                 :             : /*
    1222                 :             :  * Return a list that contains all the cells in list1 that are not in
    1223                 :             :  * list2. The returned list is freshly allocated via palloc(), but the
    1224                 :             :  * cells themselves point to the same objects as the cells of the
    1225                 :             :  * input lists.
    1226                 :             :  *
    1227                 :             :  * This variant works on lists of pointers, and determines list
    1228                 :             :  * membership via equal()
    1229                 :             :  *
    1230                 :             :  * Note that this takes time proportional to the product of the list
    1231                 :             :  * lengths, so beware of using it on long lists.  (We could probably
    1232                 :             :  * improve that, but really you should be using some other data structure
    1233                 :             :  * if this'd be a performance bottleneck.)
    1234                 :             :  */
    1235                 :             : List *
    1236                 :       41072 : list_difference(const List *list1, const List *list2)
    1237                 :             : {
    1238                 :             :     const ListCell *cell;
    1239                 :       41072 :     List       *result = NIL;
    1240                 :             : 
    1241                 :             :     Assert(IsPointerList(list1));
    1242                 :             :     Assert(IsPointerList(list2));
    1243                 :             : 
    1244         [ +  + ]:       41072 :     if (list2 == NIL)
    1245                 :        1335 :         return list_copy(list1);
    1246                 :             : 
    1247   [ +  -  +  +  :       85577 :     foreach(cell, list1)
                   +  + ]
    1248                 :             :     {
    1249         [ +  + ]:       45840 :         if (!list_member(list2, lfirst(cell)))
    1250                 :        1317 :             result = lappend(result, lfirst(cell));
    1251                 :             :     }
    1252                 :             : 
    1253                 :             :     check_list_invariants(result);
    1254                 :       39737 :     return result;
    1255                 :             : }
    1256                 :             : 
    1257                 :             : /*
    1258                 :             :  * This variant of list_difference() determines list membership via
    1259                 :             :  * simple pointer equality.
    1260                 :             :  */
    1261                 :             : List *
    1262                 :       19962 : list_difference_ptr(const List *list1, const List *list2)
    1263                 :             : {
    1264                 :             :     const ListCell *cell;
    1265                 :       19962 :     List       *result = NIL;
    1266                 :             : 
    1267                 :             :     Assert(IsPointerList(list1));
    1268                 :             :     Assert(IsPointerList(list2));
    1269                 :             : 
    1270         [ +  + ]:       19962 :     if (list2 == NIL)
    1271                 :       16845 :         return list_copy(list1);
    1272                 :             : 
    1273   [ +  +  +  +  :        7868 :     foreach(cell, list1)
                   +  + ]
    1274                 :             :     {
    1275         [ +  + ]:        4751 :         if (!list_member_ptr(list2, lfirst(cell)))
    1276                 :        2063 :             result = lappend(result, lfirst(cell));
    1277                 :             :     }
    1278                 :             : 
    1279                 :             :     check_list_invariants(result);
    1280                 :        3117 :     return result;
    1281                 :             : }
    1282                 :             : 
    1283                 :             : /*
    1284                 :             :  * This variant of list_difference() operates upon lists of integers.
    1285                 :             :  */
    1286                 :             : List *
    1287                 :        2625 : list_difference_int(const List *list1, const List *list2)
    1288                 :             : {
    1289                 :             :     const ListCell *cell;
    1290                 :        2625 :     List       *result = NIL;
    1291                 :             : 
    1292                 :             :     Assert(IsIntegerList(list1));
    1293                 :             :     Assert(IsIntegerList(list2));
    1294                 :             : 
    1295         [ +  + ]:        2625 :     if (list2 == NIL)
    1296                 :        2005 :         return list_copy(list1);
    1297                 :             : 
    1298   [ +  -  +  +  :        1840 :     foreach(cell, list1)
                   +  + ]
    1299                 :             :     {
    1300         [ +  + ]:        1220 :         if (!list_member_int(list2, lfirst_int(cell)))
    1301                 :         496 :             result = lappend_int(result, lfirst_int(cell));
    1302                 :             :     }
    1303                 :             : 
    1304                 :             :     check_list_invariants(result);
    1305                 :         620 :     return result;
    1306                 :             : }
    1307                 :             : 
    1308                 :             : /*
    1309                 :             :  * This variant of list_difference() operates upon lists of OIDs.
    1310                 :             :  */
    1311                 :             : List *
    1312                 :        7761 : list_difference_oid(const List *list1, const List *list2)
    1313                 :             : {
    1314                 :             :     const ListCell *cell;
    1315                 :        7761 :     List       *result = NIL;
    1316                 :             : 
    1317                 :             :     Assert(IsOidList(list1));
    1318                 :             :     Assert(IsOidList(list2));
    1319                 :             : 
    1320         [ +  + ]:        7761 :     if (list2 == NIL)
    1321                 :        7353 :         return list_copy(list1);
    1322                 :             : 
    1323   [ +  +  +  +  :        2716 :     foreach(cell, list1)
                   +  + ]
    1324                 :             :     {
    1325         [ +  + ]:        2308 :         if (!list_member_oid(list2, lfirst_oid(cell)))
    1326                 :        1324 :             result = lappend_oid(result, lfirst_oid(cell));
    1327                 :             :     }
    1328                 :             : 
    1329                 :             :     check_list_invariants(result);
    1330                 :         408 :     return result;
    1331                 :             : }
    1332                 :             : 
    1333                 :             : /*
    1334                 :             :  * Append datum to list, but only if it isn't already in the list.
    1335                 :             :  *
    1336                 :             :  * Whether an element is already a member of the list is determined
    1337                 :             :  * via equal().
    1338                 :             :  *
    1339                 :             :  * This does a simple linear search --- avoid using it on long lists.
    1340                 :             :  */
    1341                 :             : List *
    1342                 :      147656 : list_append_unique(List *list, void *datum)
    1343                 :             : {
    1344         [ +  + ]:      147656 :     if (list_member(list, datum))
    1345                 :       11931 :         return list;
    1346                 :             :     else
    1347                 :      135725 :         return lappend(list, datum);
    1348                 :             : }
    1349                 :             : 
    1350                 :             : /*
    1351                 :             :  * This variant of list_append_unique() determines list membership via
    1352                 :             :  * simple pointer equality.
    1353                 :             :  */
    1354                 :             : List *
    1355                 :      387778 : list_append_unique_ptr(List *list, void *datum)
    1356                 :             : {
    1357         [ +  + ]:      387778 :     if (list_member_ptr(list, datum))
    1358                 :      154990 :         return list;
    1359                 :             :     else
    1360                 :      232788 :         return lappend(list, datum);
    1361                 :             : }
    1362                 :             : 
    1363                 :             : /*
    1364                 :             :  * This variant of list_append_unique() operates upon lists of integers.
    1365                 :             :  */
    1366                 :             : List *
    1367                 :           0 : list_append_unique_int(List *list, int datum)
    1368                 :             : {
    1369         [ #  # ]:           0 :     if (list_member_int(list, datum))
    1370                 :           0 :         return list;
    1371                 :             :     else
    1372                 :           0 :         return lappend_int(list, datum);
    1373                 :             : }
    1374                 :             : 
    1375                 :             : /*
    1376                 :             :  * This variant of list_append_unique() operates upon lists of OIDs.
    1377                 :             :  */
    1378                 :             : List *
    1379                 :        4243 : list_append_unique_oid(List *list, Oid datum)
    1380                 :             : {
    1381         [ +  + ]:        4243 :     if (list_member_oid(list, datum))
    1382                 :        1367 :         return list;
    1383                 :             :     else
    1384                 :        2876 :         return lappend_oid(list, datum);
    1385                 :             : }
    1386                 :             : 
    1387                 :             : /*
    1388                 :             :  * Append to list1 each member of list2 that isn't already in list1.
    1389                 :             :  *
    1390                 :             :  * Whether an element is already a member of the list is determined
    1391                 :             :  * via equal().
    1392                 :             :  *
    1393                 :             :  * This is almost the same functionality as list_union(), but list1 is
    1394                 :             :  * modified in-place rather than being copied. However, callers of this
    1395                 :             :  * function may have strict ordering expectations -- i.e. that the relative
    1396                 :             :  * order of those list2 elements that are not duplicates is preserved.
    1397                 :             :  *
    1398                 :             :  * Note that this takes time proportional to the product of the list
    1399                 :             :  * lengths, so beware of using it on long lists.  (We could probably
    1400                 :             :  * improve that, but really you should be using some other data structure
    1401                 :             :  * if this'd be a performance bottleneck.)
    1402                 :             :  */
    1403                 :             : List *
    1404                 :        3161 : list_concat_unique(List *list1, const List *list2)
    1405                 :             : {
    1406                 :             :     ListCell   *cell;
    1407                 :             : 
    1408                 :             :     Assert(IsPointerList(list1));
    1409                 :             :     Assert(IsPointerList(list2));
    1410                 :             : 
    1411   [ +  +  +  +  :        5818 :     foreach(cell, list2)
                   +  + ]
    1412                 :             :     {
    1413         [ +  + ]:        2657 :         if (!list_member(list1, lfirst(cell)))
    1414                 :        2632 :             list1 = lappend(list1, lfirst(cell));
    1415                 :             :     }
    1416                 :             : 
    1417                 :             :     check_list_invariants(list1);
    1418                 :        3161 :     return list1;
    1419                 :             : }
    1420                 :             : 
    1421                 :             : /*
    1422                 :             :  * This variant of list_concat_unique() determines list membership via
    1423                 :             :  * simple pointer equality.
    1424                 :             :  */
    1425                 :             : List *
    1426                 :        1721 : list_concat_unique_ptr(List *list1, const List *list2)
    1427                 :             : {
    1428                 :             :     ListCell   *cell;
    1429                 :             : 
    1430                 :             :     Assert(IsPointerList(list1));
    1431                 :             :     Assert(IsPointerList(list2));
    1432                 :             : 
    1433   [ +  -  +  +  :        5885 :     foreach(cell, list2)
                   +  + ]
    1434                 :             :     {
    1435         [ +  + ]:        4164 :         if (!list_member_ptr(list1, lfirst(cell)))
    1436                 :        2081 :             list1 = lappend(list1, lfirst(cell));
    1437                 :             :     }
    1438                 :             : 
    1439                 :             :     check_list_invariants(list1);
    1440                 :        1721 :     return list1;
    1441                 :             : }
    1442                 :             : 
    1443                 :             : /*
    1444                 :             :  * This variant of list_concat_unique() operates upon lists of integers.
    1445                 :             :  */
    1446                 :             : List *
    1447                 :           0 : list_concat_unique_int(List *list1, const List *list2)
    1448                 :             : {
    1449                 :             :     ListCell   *cell;
    1450                 :             : 
    1451                 :             :     Assert(IsIntegerList(list1));
    1452                 :             :     Assert(IsIntegerList(list2));
    1453                 :             : 
    1454   [ #  #  #  #  :           0 :     foreach(cell, list2)
                   #  # ]
    1455                 :             :     {
    1456         [ #  # ]:           0 :         if (!list_member_int(list1, lfirst_int(cell)))
    1457                 :           0 :             list1 = lappend_int(list1, lfirst_int(cell));
    1458                 :             :     }
    1459                 :             : 
    1460                 :             :     check_list_invariants(list1);
    1461                 :           0 :     return list1;
    1462                 :             : }
    1463                 :             : 
    1464                 :             : /*
    1465                 :             :  * This variant of list_concat_unique() operates upon lists of OIDs.
    1466                 :             :  */
    1467                 :             : List *
    1468                 :       17006 : list_concat_unique_oid(List *list1, const List *list2)
    1469                 :             : {
    1470                 :             :     ListCell   *cell;
    1471                 :             : 
    1472                 :             :     Assert(IsOidList(list1));
    1473                 :             :     Assert(IsOidList(list2));
    1474                 :             : 
    1475   [ +  +  +  +  :       18926 :     foreach(cell, list2)
                   +  + ]
    1476                 :             :     {
    1477         [ +  + ]:        1920 :         if (!list_member_oid(list1, lfirst_oid(cell)))
    1478                 :        1406 :             list1 = lappend_oid(list1, lfirst_oid(cell));
    1479                 :             :     }
    1480                 :             : 
    1481                 :             :     check_list_invariants(list1);
    1482                 :       17006 :     return list1;
    1483                 :             : }
    1484                 :             : 
    1485                 :             : /*
    1486                 :             :  * Remove adjacent duplicates in a list of OIDs.
    1487                 :             :  *
    1488                 :             :  * It is caller's responsibility to have sorted the list to bring duplicates
    1489                 :             :  * together, perhaps via list_sort(list, list_oid_cmp).
    1490                 :             :  *
    1491                 :             :  * Note that this takes time proportional to the length of the list.
    1492                 :             :  */
    1493                 :             : void
    1494                 :        1305 : list_deduplicate_oid(List *list)
    1495                 :             : {
    1496                 :             :     int         len;
    1497                 :             : 
    1498                 :             :     Assert(IsOidList(list));
    1499                 :        1305 :     len = list_length(list);
    1500         [ +  + ]:        1305 :     if (len > 1)
    1501                 :             :     {
    1502                 :         176 :         ListCell   *elements = list->elements;
    1503                 :         176 :         int         i = 0;
    1504                 :             : 
    1505         [ +  + ]:         492 :         for (int j = 1; j < len; j++)
    1506                 :             :         {
    1507         [ +  + ]:         316 :             if (elements[i].oid_value != elements[j].oid_value)
    1508                 :         281 :                 elements[++i].oid_value = elements[j].oid_value;
    1509                 :             :         }
    1510                 :         176 :         list->length = i + 1;
    1511                 :             :     }
    1512                 :             :     check_list_invariants(list);
    1513                 :        1305 : }
    1514                 :             : 
    1515                 :             : /*
    1516                 :             :  * Free all storage in a list, and optionally the pointed-to elements
    1517                 :             :  */
    1518                 :             : static void
    1519                 :    19523484 : list_free_private(List *list, bool deep)
    1520                 :             : {
    1521         [ +  + ]:    19523484 :     if (list == NIL)
    1522                 :    14926411 :         return;                 /* nothing to do */
    1523                 :             : 
    1524                 :             :     check_list_invariants(list);
    1525                 :             : 
    1526         [ +  + ]:     4597073 :     if (deep)
    1527                 :             :     {
    1528         [ +  + ]:     1352761 :         for (int i = 0; i < list->length; i++)
    1529                 :     1071560 :             pfree(lfirst(&list->elements[i]));
    1530                 :             :     }
    1531         [ +  + ]:     4597073 :     if (list->elements != list->initial_elements)
    1532                 :      109989 :         pfree(list->elements);
    1533                 :     4597073 :     pfree(list);
    1534                 :             : }
    1535                 :             : 
    1536                 :             : /*
    1537                 :             :  * Free all the cells of the list, as well as the list itself. Any
    1538                 :             :  * objects that are pointed-to by the cells of the list are NOT
    1539                 :             :  * free'd.
    1540                 :             :  *
    1541                 :             :  * On return, the argument to this function has been freed, so the
    1542                 :             :  * caller would be wise to set it to NIL for safety's sake.
    1543                 :             :  */
    1544                 :             : void
    1545                 :    17587864 : list_free(List *list)
    1546                 :             : {
    1547                 :    17587864 :     list_free_private(list, false);
    1548                 :    17587864 : }
    1549                 :             : 
    1550                 :             : /*
    1551                 :             :  * Free all the cells of the list, the list itself, and all the
    1552                 :             :  * objects pointed-to by the cells of the list (each element in the
    1553                 :             :  * list must contain a pointer to a palloc()'d region of memory!)
    1554                 :             :  *
    1555                 :             :  * On return, the argument to this function has been freed, so the
    1556                 :             :  * caller would be wise to set it to NIL for safety's sake.
    1557                 :             :  */
    1558                 :             : void
    1559                 :     1935620 : list_free_deep(List *list)
    1560                 :             : {
    1561                 :             :     /*
    1562                 :             :      * A "deep" free operation only makes sense on a list of pointers.
    1563                 :             :      */
    1564                 :             :     Assert(IsPointerList(list));
    1565                 :     1935620 :     list_free_private(list, true);
    1566                 :     1935620 : }
    1567                 :             : 
    1568                 :             : /*
    1569                 :             :  * Return a shallow copy of the specified list.
    1570                 :             :  */
    1571                 :             : List *
    1572                 :     8516468 : list_copy(const List *oldlist)
    1573                 :             : {
    1574                 :             :     List       *newlist;
    1575                 :             : 
    1576         [ +  + ]:     8516468 :     if (oldlist == NIL)
    1577                 :     1860582 :         return NIL;
    1578                 :             : 
    1579                 :     6655886 :     newlist = new_list(oldlist->type, oldlist->length);
    1580                 :     6655886 :     memcpy(newlist->elements, oldlist->elements,
    1581                 :     6655886 :            newlist->length * sizeof(ListCell));
    1582                 :             : 
    1583                 :             :     check_list_invariants(newlist);
    1584                 :     6655886 :     return newlist;
    1585                 :             : }
    1586                 :             : 
    1587                 :             : /*
    1588                 :             :  * Return a shallow copy of the specified list containing only the first 'len'
    1589                 :             :  * elements.  If oldlist is shorter than 'len' then we copy the entire list.
    1590                 :             :  */
    1591                 :             : List *
    1592                 :      983412 : list_copy_head(const List *oldlist, int len)
    1593                 :             : {
    1594                 :             :     List       *newlist;
    1595                 :             : 
    1596   [ +  -  +  + ]:      983412 :     if (oldlist == NIL || len <= 0)
    1597                 :      832685 :         return NIL;
    1598                 :             : 
    1599                 :      150727 :     len = Min(oldlist->length, len);
    1600                 :             : 
    1601                 :      150727 :     newlist = new_list(oldlist->type, len);
    1602                 :      150727 :     memcpy(newlist->elements, oldlist->elements, len * sizeof(ListCell));
    1603                 :             : 
    1604                 :             :     check_list_invariants(newlist);
    1605                 :      150727 :     return newlist;
    1606                 :             : }
    1607                 :             : 
    1608                 :             : /*
    1609                 :             :  * Return a shallow copy of the specified list, without the first N elements.
    1610                 :             :  */
    1611                 :             : List *
    1612                 :       71133 : list_copy_tail(const List *oldlist, int nskip)
    1613                 :             : {
    1614                 :             :     List       *newlist;
    1615                 :             : 
    1616         [ -  + ]:       71133 :     if (nskip < 0)
    1617                 :           0 :         nskip = 0;              /* would it be better to elog? */
    1618                 :             : 
    1619   [ +  -  +  + ]:       71133 :     if (oldlist == NIL || nskip >= oldlist->length)
    1620                 :        1534 :         return NIL;
    1621                 :             : 
    1622                 :       69599 :     newlist = new_list(oldlist->type, oldlist->length - nskip);
    1623                 :       69599 :     memcpy(newlist->elements, &oldlist->elements[nskip],
    1624                 :       69599 :            newlist->length * sizeof(ListCell));
    1625                 :             : 
    1626                 :             :     check_list_invariants(newlist);
    1627                 :       69599 :     return newlist;
    1628                 :             : }
    1629                 :             : 
    1630                 :             : /*
    1631                 :             :  * Return a deep copy of the specified list.
    1632                 :             :  *
    1633                 :             :  * The list elements are copied via copyObject(), so that this function's
    1634                 :             :  * idea of a "deep" copy is considerably deeper than what list_free_deep()
    1635                 :             :  * means by the same word.
    1636                 :             :  */
    1637                 :             : List *
    1638                 :    15324591 : list_copy_deep(const List *oldlist)
    1639                 :             : {
    1640                 :             :     List       *newlist;
    1641                 :             : 
    1642         [ -  + ]:    15324591 :     if (oldlist == NIL)
    1643                 :           0 :         return NIL;
    1644                 :             : 
    1645                 :             :     /* This is only sensible for pointer Lists */
    1646                 :             :     Assert(IsA(oldlist, List));
    1647                 :             : 
    1648                 :    15324591 :     newlist = new_list(oldlist->type, oldlist->length);
    1649         [ +  + ]:    64020125 :     for (int i = 0; i < newlist->length; i++)
    1650                 :    48695534 :         lfirst(&newlist->elements[i]) =
    1651                 :    48695534 :             copyObjectImpl(lfirst(&oldlist->elements[i]));
    1652                 :             : 
    1653                 :             :     check_list_invariants(newlist);
    1654                 :    15324591 :     return newlist;
    1655                 :             : }
    1656                 :             : 
    1657                 :             : /*
    1658                 :             :  * Sort a list according to the specified comparator function.
    1659                 :             :  *
    1660                 :             :  * The list is sorted in-place.
    1661                 :             :  *
    1662                 :             :  * The comparator function is declared to receive arguments of type
    1663                 :             :  * const ListCell *; this allows it to use lfirst() and variants
    1664                 :             :  * without casting its arguments.  Otherwise it behaves the same as
    1665                 :             :  * the comparator function for standard qsort().
    1666                 :             :  *
    1667                 :             :  * Like qsort(), this provides no guarantees about sort stability
    1668                 :             :  * for equal keys.
    1669                 :             :  *
    1670                 :             :  * This is based on qsort(), so it likewise has O(N log N) runtime.
    1671                 :             :  */
    1672                 :             : void
    1673                 :      366844 : list_sort(List *list, list_sort_comparator cmp)
    1674                 :             : {
    1675                 :             :     typedef int (*qsort_comparator) (const void *a, const void *b);
    1676                 :             :     int         len;
    1677                 :             : 
    1678                 :             :     check_list_invariants(list);
    1679                 :             : 
    1680                 :             :     /* Nothing to do if there's less than two elements */
    1681                 :      366844 :     len = list_length(list);
    1682         [ +  + ]:      366844 :     if (len > 1)
    1683                 :      129223 :         qsort(list->elements, len, sizeof(ListCell), (qsort_comparator) cmp);
    1684                 :      366844 : }
    1685                 :             : 
    1686                 :             : /*
    1687                 :             :  * list_sort comparator for sorting a list into ascending int order.
    1688                 :             :  */
    1689                 :             : int
    1690                 :          66 : list_int_cmp(const ListCell *p1, const ListCell *p2)
    1691                 :             : {
    1692                 :          66 :     int         v1 = lfirst_int(p1);
    1693                 :          66 :     int         v2 = lfirst_int(p2);
    1694                 :             : 
    1695                 :          66 :     return pg_cmp_s32(v1, v2);
    1696                 :             : }
    1697                 :             : 
    1698                 :             : /*
    1699                 :             :  * list_sort comparator for sorting a list into ascending OID order.
    1700                 :             :  */
    1701                 :             : int
    1702                 :      151874 : list_oid_cmp(const ListCell *p1, const ListCell *p2)
    1703                 :             : {
    1704                 :      151874 :     Oid         v1 = lfirst_oid(p1);
    1705                 :      151874 :     Oid         v2 = lfirst_oid(p2);
    1706                 :             : 
    1707                 :      151874 :     return pg_cmp_u32(v1, v2);
    1708                 :             : }
        

Generated by: LCOV version 2.0-1