PostgreSQL Source Code git master
Loading...
Searching...
No Matches
list.c File Reference
#include "postgres.h"
#include "common/int.h"
#include "nodes/pg_list.h"
#include "port/pg_bitutils.h"
#include "utils/memdebug.h"
#include "utils/memutils.h"
Include dependency graph for list.c:

Go to the source code of this file.

Macros

#define LIST_HEADER_OVERHEAD    ((int) ((offsetof(List, initial_elements) - 1) / sizeof(ListCell) + 1))
 
#define IsPointerList(l)   ((l) == NIL || IsA((l), List))
 
#define IsIntegerList(l)   ((l) == NIL || IsA((l), IntList))
 
#define IsOidList(l)   ((l) == NIL || IsA((l), OidList))
 
#define IsXidList(l)   ((l) == NIL || IsA((l), XidList))
 
#define check_list_invariants(l)   ((void) 0)
 

Functions

static Listnew_list (NodeTag type, int min_size)
 
static void enlarge_list (List *list, int min_size)
 
Listlist_make1_impl (NodeTag t, ListCell datum1)
 
Listlist_make2_impl (NodeTag t, ListCell datum1, ListCell datum2)
 
Listlist_make3_impl (NodeTag t, ListCell datum1, ListCell datum2, ListCell datum3)
 
Listlist_make4_impl (NodeTag t, ListCell datum1, ListCell datum2, ListCell datum3, ListCell datum4)
 
Listlist_make5_impl (NodeTag t, ListCell datum1, ListCell datum2, ListCell datum3, ListCell datum4, ListCell datum5)
 
static void new_head_cell (List *list)
 
static void new_tail_cell (List *list)
 
Listlappend (List *list, void *datum)
 
Listlappend_int (List *list, int datum)
 
Listlappend_oid (List *list, Oid datum)
 
Listlappend_xid (List *list, TransactionId datum)
 
static ListCellinsert_new_cell (List *list, int pos)
 
Listlist_insert_nth (List *list, int pos, void *datum)
 
Listlist_insert_nth_int (List *list, int pos, int datum)
 
Listlist_insert_nth_oid (List *list, int pos, Oid datum)
 
Listlcons (void *datum, List *list)
 
Listlcons_int (int datum, List *list)
 
Listlcons_oid (Oid datum, List *list)
 
Listlist_concat (List *list1, const List *list2)
 
Listlist_concat_copy (const List *list1, const List *list2)
 
Listlist_truncate (List *list, int new_size)
 
bool list_member (const List *list, const void *datum)
 
bool list_member_ptr (const List *list, const void *datum)
 
bool list_member_int (const List *list, int datum)
 
bool list_member_oid (const List *list, Oid datum)
 
bool list_member_xid (const List *list, TransactionId datum)
 
Listlist_delete_nth_cell (List *list, int n)
 
Listlist_delete_cell (List *list, ListCell *cell)
 
Listlist_delete (List *list, void *datum)
 
Listlist_delete_ptr (List *list, void *datum)
 
Listlist_delete_int (List *list, int datum)
 
Listlist_delete_oid (List *list, Oid datum)
 
Listlist_delete_first (List *list)
 
Listlist_delete_last (List *list)
 
Listlist_delete_first_n (List *list, int n)
 
Listlist_union (const List *list1, const List *list2)
 
Listlist_union_ptr (const List *list1, const List *list2)
 
Listlist_union_int (const List *list1, const List *list2)
 
Listlist_union_oid (const List *list1, const List *list2)
 
Listlist_intersection (const List *list1, const List *list2)
 
Listlist_intersection_int (const List *list1, const List *list2)
 
Listlist_difference (const List *list1, const List *list2)
 
Listlist_difference_ptr (const List *list1, const List *list2)
 
Listlist_difference_int (const List *list1, const List *list2)
 
Listlist_difference_oid (const List *list1, const List *list2)
 
Listlist_append_unique (List *list, void *datum)
 
Listlist_append_unique_ptr (List *list, void *datum)
 
Listlist_append_unique_int (List *list, int datum)
 
Listlist_append_unique_oid (List *list, Oid datum)
 
Listlist_concat_unique (List *list1, const List *list2)
 
Listlist_concat_unique_ptr (List *list1, const List *list2)
 
Listlist_concat_unique_int (List *list1, const List *list2)
 
Listlist_concat_unique_oid (List *list1, const List *list2)
 
void list_deduplicate_oid (List *list)
 
static void list_free_private (List *list, bool deep)
 
void list_free (List *list)
 
void list_free_deep (List *list)
 
Listlist_copy (const List *oldlist)
 
Listlist_copy_head (const List *oldlist, int len)
 
Listlist_copy_tail (const List *oldlist, int nskip)
 
Listlist_copy_deep (const List *oldlist)
 
void list_sort (List *list, list_sort_comparator cmp)
 
int list_int_cmp (const ListCell *p1, const ListCell *p2)
 
int list_oid_cmp (const ListCell *p1, const ListCell *p2)
 

Macro Definition Documentation

◆ check_list_invariants

#define check_list_invariants (   l)    ((void) 0)

Definition at line 80 of file list.c.

◆ IsIntegerList

#define IsIntegerList (   l)    ((l) == NIL || IsA((l), IntList))

Definition at line 56 of file list.c.

◆ IsOidList

#define IsOidList (   l)    ((l) == NIL || IsA((l), OidList))

Definition at line 57 of file list.c.

◆ IsPointerList

#define IsPointerList (   l)    ((l) == NIL || IsA((l), List))

Definition at line 55 of file list.c.

◆ IsXidList

#define IsXidList (   l)    ((l) == NIL || IsA((l), XidList))

Definition at line 58 of file list.c.

◆ LIST_HEADER_OVERHEAD

#define LIST_HEADER_OVERHEAD    ((int) ((offsetof(List, initial_elements) - 1) / sizeof(ListCell) + 1))

Definition at line 48 of file list.c.

65{
66 if (list == NIL)
67 return;
68
69 Assert(list->length > 0);
70 Assert(list->length <= list->max_length);
71 Assert(list->elements != NULL);
72
73 Assert(list->type == T_List ||
74 list->type == T_IntList ||
75 list->type == T_OidList ||
76 list->type == T_XidList);
77}
78#else
79#define check_list_invariants(l) ((void) 0)
80#endif /* USE_ASSERT_CHECKING */
81
82/*
83 * Return a freshly allocated List with room for at least min_size cells.
84 *
85 * Since empty non-NIL lists are invalid, new_list() sets the initial length
86 * to min_size, effectively marking that number of cells as valid; the caller
87 * is responsible for filling in their data.
88 */
89static List *
91{
93 int max_size;
94
95 Assert(min_size > 0);
96
97 /*
98 * We allocate all the requested cells, and possibly some more, as part of
99 * the same palloc request as the List header. This is a big win for the
100 * typical case of short fixed-length lists. It can lose if we allocate a
101 * moderately long list and then it gets extended; we'll be wasting more
102 * initial_elements[] space than if we'd made the header small. However,
103 * rounding up the request as we do in the normal code path provides some
104 * defense against small extensions.
105 */
106
107#ifndef DEBUG_LIST_MEMORY_USAGE
108
109 /*
110 * Normally, we set up a list with some extra cells, to allow it to grow
111 * without a repalloc. Prefer cell counts chosen to make the total
112 * allocation a power-of-2, since palloc would round it up to that anyway.
113 * (That stops being true for very large allocations, but very long lists
114 * are infrequent, so it doesn't seem worth special logic for such cases.)
115 *
116 * The minimum allocation is 8 ListCell units, providing either 4 or 5
117 * available ListCells depending on the machine's word width. Counting
118 * palloc's overhead, this uses the same amount of space as a one-cell
119 * list did in the old implementation, and less space for any longer list.
120 *
121 * We needn't worry about integer overflow; no caller passes min_size
122 * that's more than twice the size of an existing list, so the size limits
123 * within palloc will ensure that we don't overflow here.
124 */
126 max_size -= LIST_HEADER_OVERHEAD;
127#else
128
129 /*
130 * For debugging, don't allow any extra space. This forces any cell
131 * addition to go through enlarge_list() and thus move the existing data.
132 */
133 max_size = min_size;
134#endif
135
136 newlist = (List *) palloc(offsetof(List, initial_elements) +
137 max_size * sizeof(ListCell));
138 newlist->type = type;
139 newlist->length = min_size;
140 newlist->max_length = max_size;
141 newlist->elements = newlist->initial_elements;
142
143 return newlist;
144}
145
146/*
147 * Enlarge an existing non-NIL List to have room for at least min_size cells.
148 *
149 * This does *not* update list->length, as some callers would find that
150 * inconvenient. (list->length had better be the correct number of existing
151 * valid cells, though.)
152 */
153static void
154enlarge_list(List *list, int min_size)
155{
156 int new_max_len;
157
158 Assert(min_size > list->max_length); /* else we shouldn't be here */
159
160#ifndef DEBUG_LIST_MEMORY_USAGE
161
162 /*
163 * As above, we prefer power-of-two total allocations; but here we need
164 * not account for list header overhead.
165 */
166
167 /* clamp the minimum value to 16, a semi-arbitrary small power of 2 */
169
170#else
171 /* As above, don't allocate anything extra */
173#endif
174
175 if (list->elements == list->initial_elements)
176 {
177 /*
178 * Replace original in-line allocation with a separate palloc block.
179 * Ensure it is in the same memory context as the List header. (The
180 * previous List implementation did not offer any guarantees about
181 * keeping all list cells in the same context, but it seems reasonable
182 * to create such a guarantee now.)
183 */
184 list->elements = (ListCell *)
186 new_max_len * sizeof(ListCell));
187 memcpy(list->elements, list->initial_elements,
188 list->length * sizeof(ListCell));
189
190 /*
191 * We must not move the list header, so it's unsafe to try to reclaim
192 * the initial_elements[] space via repalloc. In debugging builds,
193 * however, we can clear that space and/or mark it inaccessible.
194 * (wipe_mem includes VALGRIND_MAKE_MEM_NOACCESS.)
195 */
196#ifdef CLOBBER_FREED_MEMORY
197 wipe_mem(list->initial_elements,
198 list->max_length * sizeof(ListCell));
199#else
200 VALGRIND_MAKE_MEM_NOACCESS(list->initial_elements,
201 list->max_length * sizeof(ListCell));
202#endif
203 }
204 else
205 {
206#ifndef DEBUG_LIST_MEMORY_USAGE
207 /* Normally, let repalloc deal with enlargement */
208 list->elements = (ListCell *) repalloc(list->elements,
209 new_max_len * sizeof(ListCell));
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 */
216
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 list->max_length = new_max_len;
228}
229
230/*
231 * Convenience functions to construct short Lists from given values.
232 * (These are normally invoked via the list_makeN macros.)
233 */
234List *
236{
237 List *list = new_list(t, 1);
238
239 list->elements[0] = datum1;
241 return list;
242}
243
244List *
246{
247 List *list = new_list(t, 2);
248
249 list->elements[0] = datum1;
250 list->elements[1] = datum2;
252 return list;
253}
254
255List *
258{
259 List *list = new_list(t, 3);
260
261 list->elements[0] = datum1;
262 list->elements[1] = datum2;
263 list->elements[2] = datum3;
265 return list;
266}
267
268List *
271{
272 List *list = new_list(t, 4);
273
274 list->elements[0] = datum1;
275 list->elements[1] = datum2;
276 list->elements[2] = datum3;
277 list->elements[3] = datum4;
279 return list;
280}
281
282List *
285{
286 List *list = new_list(t, 5);
287
288 list->elements[0] = datum1;
289 list->elements[1] = datum2;
290 list->elements[2] = datum3;
291 list->elements[3] = datum4;
292 list->elements[4] = datum5;
294 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 */
303static void
304new_head_cell(List *list)
305{
306 /* Enlarge array if necessary */
307 if (list->length >= list->max_length)
308 enlarge_list(list, list->length + 1);
309 /* Now shove the existing data over */
310 memmove(&list->elements[1], &list->elements[0],
311 list->length * sizeof(ListCell));
312 list->length++;
313}
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 */
321static void
322new_tail_cell(List *list)
323{
324 /* Enlarge array if necessary */
325 if (list->length >= list->max_length)
326 enlarge_list(list, list->length + 1);
327 list->length++;
328}
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 */
337List *
338lappend(List *list, void *datum)
339{
340 Assert(IsPointerList(list));
341
342 if (list == NIL)
343 list = new_list(T_List, 1);
344 else
345 new_tail_cell(list);
346
347 llast(list) = datum;
349 return list;
350}
351
352/*
353 * Append an integer to the specified list. See lappend()
354 */
355List *
356lappend_int(List *list, int datum)
357{
358 Assert(IsIntegerList(list));
359
360 if (list == NIL)
361 list = new_list(T_IntList, 1);
362 else
363 new_tail_cell(list);
364
365 llast_int(list) = datum;
367 return list;
368}
369
370/*
371 * Append an OID to the specified list. See lappend()
372 */
373List *
374lappend_oid(List *list, Oid datum)
375{
376 Assert(IsOidList(list));
377
378 if (list == NIL)
379 list = new_list(T_OidList, 1);
380 else
381 new_tail_cell(list);
382
383 llast_oid(list) = datum;
385 return list;
386}
387
388/*
389 * Append a TransactionId to the specified list. See lappend()
390 */
391List *
392lappend_xid(List *list, TransactionId datum)
393{
394 Assert(IsXidList(list));
395
396 if (list == NIL)
397 list = new_list(T_XidList, 1);
398 else
399 new_tail_cell(list);
400
401 llast_xid(list) = datum;
403 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 */
413static ListCell *
414insert_new_cell(List *list, int pos)
415{
416 Assert(pos >= 0 && pos <= list->length);
417
418 /* Enlarge array if necessary */
419 if (list->length >= list->max_length)
420 enlarge_list(list, list->length + 1);
421 /* Now shove the existing data over */
422 if (pos < list->length)
423 memmove(&list->elements[pos + 1], &list->elements[pos],
424 (list->length - pos) * sizeof(ListCell));
425 list->length++;
426
427 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 */
437List *
438list_insert_nth(List *list, int pos, void *datum)
439{
440 if (list == NIL)
441 {
442 Assert(pos == 0);
443 return list_make1(datum);
444 }
445 Assert(IsPointerList(list));
446 lfirst(insert_new_cell(list, pos)) = datum;
448 return list;
449}
450
451List *
452list_insert_nth_int(List *list, int pos, int datum)
453{
454 if (list == NIL)
455 {
456 Assert(pos == 0);
457 return list_make1_int(datum);
458 }
459 Assert(IsIntegerList(list));
460 lfirst_int(insert_new_cell(list, pos)) = datum;
462 return list;
463}
464
465List *
466list_insert_nth_oid(List *list, int pos, Oid datum)
467{
468 if (list == NIL)
469 {
470 Assert(pos == 0);
471 return list_make1_oid(datum);
472 }
473 Assert(IsOidList(list));
474 lfirst_oid(insert_new_cell(list, pos)) = datum;
476 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 */
493List *
494lcons(void *datum, List *list)
495{
496 Assert(IsPointerList(list));
497
498 if (list == NIL)
499 list = new_list(T_List, 1);
500 else
501 new_head_cell(list);
502
503 linitial(list) = datum;
505 return list;
506}
507
508/*
509 * Prepend an integer to the list. See lcons()
510 */
511List *
512lcons_int(int datum, List *list)
513{
514 Assert(IsIntegerList(list));
515
516 if (list == NIL)
517 list = new_list(T_IntList, 1);
518 else
519 new_head_cell(list);
520
521 linitial_int(list) = datum;
523 return list;
524}
525
526/*
527 * Prepend an OID to the list. See lcons()
528 */
529List *
530lcons_oid(Oid datum, List *list)
531{
532 Assert(IsOidList(list));
533
534 if (list == NIL)
535 list = new_list(T_OidList, 1);
536 else
537 new_head_cell(list);
538
539 linitial_oid(list) = datum;
541 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 */
559List *
561{
562 int new_len;
563
564 if (list1 == NIL)
565 return list_copy(list2);
566 if (list2 == NIL)
567 return list1;
568
569 Assert(list1->type == list2->type);
570
571 new_len = list1->length + list2->length;
572 /* Enlarge array if necessary */
573 if (new_len > list1->max_length)
575
576 /* Even if list1 == list2, using memcpy should be safe here */
577 memcpy(&list1->elements[list1->length], &list2->elements[0],
578 list2->length * sizeof(ListCell));
579 list1->length = new_len;
580
582 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 */
596List *
597list_concat_copy(const List *list1, const List *list2)
598{
599 List *result;
600 int new_len;
601
602 if (list1 == NIL)
603 return list_copy(list2);
604 if (list2 == NIL)
605 return list_copy(list1);
606
607 Assert(list1->type == list2->type);
608
609 new_len = list1->length + list2->length;
610 result = new_list(list1->type, new_len);
611 memcpy(result->elements, list1->elements,
612 list1->length * sizeof(ListCell));
613 memcpy(result->elements + list1->length, list2->elements,
614 list2->length * sizeof(ListCell));
615
616 check_list_invariants(result);
617 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 */
629List *
630list_truncate(List *list, int new_size)
631{
632 if (new_size <= 0)
633 return NIL; /* truncate to zero length */
634
635 /* If asked to effectively extend the list, do nothing */
636 if (new_size < list_length(list))
637 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 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 */
659bool
660list_member(const List *list, const void *datum)
661{
662 const ListCell *cell;
663
664 Assert(IsPointerList(list));
666
667 foreach(cell, list)
668 {
669 if (equal(lfirst(cell), datum))
670 return true;
671 }
672
673 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 */
680bool
681list_member_ptr(const List *list, const void *datum)
682{
683 const ListCell *cell;
684
685 Assert(IsPointerList(list));
687
688 foreach(cell, list)
689 {
690 if (lfirst(cell) == datum)
691 return true;
692 }
693
694 return false;
695}
696
697/*
698 * Return true iff the integer 'datum' is a member of the list.
699 */
700bool
701list_member_int(const List *list, int datum)
702{
703 const ListCell *cell;
704
705 Assert(IsIntegerList(list));
707
708 foreach(cell, list)
709 {
710 if (lfirst_int(cell) == datum)
711 return true;
712 }
713
714 return false;
715}
716
717/*
718 * Return true iff the OID 'datum' is a member of the list.
719 */
720bool
721list_member_oid(const List *list, Oid datum)
722{
723 const ListCell *cell;
724
725 Assert(IsOidList(list));
727
728 foreach(cell, list)
729 {
730 if (lfirst_oid(cell) == datum)
731 return true;
732 }
733
734 return false;
735}
736
737/*
738 * Return true iff the TransactionId 'datum' is a member of the list.
739 */
740bool
741list_member_xid(const List *list, TransactionId datum)
742{
743 const ListCell *cell;
744
745 Assert(IsXidList(list));
747
748 foreach(cell, list)
749 {
750 if (lfirst_xid(cell) == datum)
751 return true;
752 }
753
754 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 */
765List *
766list_delete_nth_cell(List *list, int n)
767{
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 if (list->length == 1)
778 {
779 list_free(list);
780 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 memmove(&list->elements[n], &list->elements[n + 1],
791 (list->length - 1 - n) * sizeof(ListCell));
792 list->length--;
793#else
794 {
796 int newmaxlen = list->length - 1;
797
798 newelems = (ListCell *)
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--;
824 }
825#endif
826
827 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 */
839List *
840list_delete_cell(List *list, ListCell *cell)
841{
842 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 */
851List *
852list_delete(List *list, void *datum)
853{
854 ListCell *cell;
855
856 Assert(IsPointerList(list));
858
859 foreach(cell, list)
860 {
861 if (equal(lfirst(cell), datum))
862 return list_delete_cell(list, cell);
863 }
864
865 /* Didn't find a match: return the list unmodified */
866 return list;
867}
868
869/* As above, but use simple pointer equality */
870List *
871list_delete_ptr(List *list, void *datum)
872{
873 ListCell *cell;
874
875 Assert(IsPointerList(list));
877
878 foreach(cell, list)
879 {
880 if (lfirst(cell) == datum)
881 return list_delete_cell(list, cell);
882 }
883
884 /* Didn't find a match: return the list unmodified */
885 return list;
886}
887
888/* As above, but for integers */
889List *
890list_delete_int(List *list, int datum)
891{
892 ListCell *cell;
893
894 Assert(IsIntegerList(list));
896
897 foreach(cell, list)
898 {
899 if (lfirst_int(cell) == datum)
900 return list_delete_cell(list, cell);
901 }
902
903 /* Didn't find a match: return the list unmodified */
904 return list;
905}
906
907/* As above, but for OIDs */
908List *
909list_delete_oid(List *list, Oid datum)
910{
911 ListCell *cell;
912
913 Assert(IsOidList(list));
915
916 foreach(cell, list)
917 {
918 if (lfirst_oid(cell) == datum)
919 return list_delete_cell(list, cell);
920 }
921
922 /* Didn't find a match: return the list unmodified */
923 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 */
941List *
943{
945
946 if (list == NIL)
947 return NIL; /* would an error be better? */
948
949 return list_delete_nth_cell(list, 0);
950}
951
952/*
953 * Delete the last element of the list.
954 */
955List *
957{
959
960 if (list == NIL)
961 return NIL; /* would an error be better? */
962
963 /* list_truncate won't free list if it goes to empty, but this should */
964 if (list_length(list) <= 1)
965 {
966 list_free(list);
967 return NIL;
968 }
969
970 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 */
981List *
982list_delete_first_n(List *list, int n)
983{
985
986 /* No-op request? */
987 if (n <= 0)
988 return list;
989
990 /* Delete whole list? */
991 if (n >= list_length(list))
992 {
993 list_free(list);
994 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 memmove(&list->elements[0], &list->elements[n],
1005 (list->length - n) * sizeof(ListCell));
1006 list->length -= n;
1007#else
1008 {
1010 int newmaxlen = list->length - n;
1011
1012 newelems = (ListCell *)
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;
1036 }
1037#endif
1038
1039 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 */
1064List *
1065list_union(const List *list1, const List *list2)
1066{
1067 List *result;
1068 const ListCell *cell;
1069
1072
1073 result = list_copy(list1);
1074 foreach(cell, list2)
1075 {
1076 if (!list_member(result, lfirst(cell)))
1077 result = lappend(result, lfirst(cell));
1078 }
1079
1080 check_list_invariants(result);
1081 return result;
1082}
1083
1084/*
1085 * This variant of list_union() determines duplicates via simple
1086 * pointer comparison.
1087 */
1088List *
1089list_union_ptr(const List *list1, const List *list2)
1090{
1091 List *result;
1092 const ListCell *cell;
1093
1096
1097 result = list_copy(list1);
1098 foreach(cell, list2)
1099 {
1100 if (!list_member_ptr(result, lfirst(cell)))
1101 result = lappend(result, lfirst(cell));
1102 }
1103
1104 check_list_invariants(result);
1105 return result;
1106}
1107
1108/*
1109 * This variant of list_union() operates upon lists of integers.
1110 */
1111List *
1112list_union_int(const List *list1, const List *list2)
1113{
1114 List *result;
1115 const ListCell *cell;
1116
1119
1120 result = list_copy(list1);
1121 foreach(cell, list2)
1122 {
1123 if (!list_member_int(result, lfirst_int(cell)))
1124 result = lappend_int(result, lfirst_int(cell));
1125 }
1126
1127 check_list_invariants(result);
1128 return result;
1129}
1130
1131/*
1132 * This variant of list_union() operates upon lists of OIDs.
1133 */
1134List *
1135list_union_oid(const List *list1, const List *list2)
1136{
1137 List *result;
1138 const ListCell *cell;
1139
1142
1143 result = list_copy(list1);
1144 foreach(cell, list2)
1145 {
1146 if (!list_member_oid(result, lfirst_oid(cell)))
1147 result = lappend_oid(result, lfirst_oid(cell));
1148 }
1149
1150 check_list_invariants(result);
1151 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 */
1172List *
1173list_intersection(const List *list1, const List *list2)
1174{
1175 List *result;
1176 const ListCell *cell;
1177
1178 if (list1 == NIL || list2 == NIL)
1179 return NIL;
1180
1183
1184 result = NIL;
1185 foreach(cell, list1)
1186 {
1187 if (list_member(list2, lfirst(cell)))
1188 result = lappend(result, lfirst(cell));
1189 }
1190
1191 check_list_invariants(result);
1192 return result;
1193}
1194
1195/*
1196 * As list_intersection but operates on lists of integers.
1197 */
1198List *
1200{
1201 List *result;
1202 const ListCell *cell;
1203
1204 if (list1 == NIL || list2 == NIL)
1205 return NIL;
1206
1209
1210 result = NIL;
1211 foreach(cell, list1)
1212 {
1213 if (list_member_int(list2, lfirst_int(cell)))
1214 result = lappend_int(result, lfirst_int(cell));
1215 }
1216
1217 check_list_invariants(result);
1218 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 */
1235List *
1236list_difference(const List *list1, const List *list2)
1237{
1238 const ListCell *cell;
1239 List *result = NIL;
1240
1243
1244 if (list2 == NIL)
1245 return list_copy(list1);
1246
1247 foreach(cell, list1)
1248 {
1249 if (!list_member(list2, lfirst(cell)))
1250 result = lappend(result, lfirst(cell));
1251 }
1252
1253 check_list_invariants(result);
1254 return result;
1255}
1256
1257/*
1258 * This variant of list_difference() determines list membership via
1259 * simple pointer equality.
1260 */
1261List *
1262list_difference_ptr(const List *list1, const List *list2)
1263{
1264 const ListCell *cell;
1265 List *result = NIL;
1266
1269
1270 if (list2 == NIL)
1271 return list_copy(list1);
1272
1273 foreach(cell, list1)
1274 {
1275 if (!list_member_ptr(list2, lfirst(cell)))
1276 result = lappend(result, lfirst(cell));
1277 }
1278
1279 check_list_invariants(result);
1280 return result;
1281}
1282
1283/*
1284 * This variant of list_difference() operates upon lists of integers.
1285 */
1286List *
1287list_difference_int(const List *list1, const List *list2)
1288{
1289 const ListCell *cell;
1290 List *result = NIL;
1291
1294
1295 if (list2 == NIL)
1296 return list_copy(list1);
1297
1298 foreach(cell, list1)
1299 {
1300 if (!list_member_int(list2, lfirst_int(cell)))
1301 result = lappend_int(result, lfirst_int(cell));
1302 }
1303
1304 check_list_invariants(result);
1305 return result;
1306}
1307
1308/*
1309 * This variant of list_difference() operates upon lists of OIDs.
1310 */
1311List *
1312list_difference_oid(const List *list1, const List *list2)
1313{
1314 const ListCell *cell;
1315 List *result = NIL;
1316
1319
1320 if (list2 == NIL)
1321 return list_copy(list1);
1322
1323 foreach(cell, list1)
1324 {
1325 if (!list_member_oid(list2, lfirst_oid(cell)))
1326 result = lappend_oid(result, lfirst_oid(cell));
1327 }
1328
1329 check_list_invariants(result);
1330 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 */
1341List *
1342list_append_unique(List *list, void *datum)
1343{
1344 if (list_member(list, datum))
1345 return list;
1346 else
1347 return lappend(list, datum);
1348}
1349
1350/*
1351 * This variant of list_append_unique() determines list membership via
1352 * simple pointer equality.
1353 */
1354List *
1355list_append_unique_ptr(List *list, void *datum)
1356{
1357 if (list_member_ptr(list, datum))
1358 return list;
1359 else
1360 return lappend(list, datum);
1361}
1362
1363/*
1364 * This variant of list_append_unique() operates upon lists of integers.
1365 */
1366List *
1367list_append_unique_int(List *list, int datum)
1368{
1369 if (list_member_int(list, datum))
1370 return list;
1371 else
1372 return lappend_int(list, datum);
1373}
1374
1375/*
1376 * This variant of list_append_unique() operates upon lists of OIDs.
1377 */
1378List *
1379list_append_unique_oid(List *list, Oid datum)
1380{
1381 if (list_member_oid(list, datum))
1382 return list;
1383 else
1384 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 */
1403List *
1405{
1406 ListCell *cell;
1407
1410
1411 foreach(cell, list2)
1412 {
1413 if (!list_member(list1, lfirst(cell)))
1414 list1 = lappend(list1, lfirst(cell));
1415 }
1416
1418 return list1;
1419}
1420
1421/*
1422 * This variant of list_concat_unique() determines list membership via
1423 * simple pointer equality.
1424 */
1425List *
1427{
1428 ListCell *cell;
1429
1432
1433 foreach(cell, list2)
1434 {
1435 if (!list_member_ptr(list1, lfirst(cell)))
1436 list1 = lappend(list1, lfirst(cell));
1437 }
1438
1440 return list1;
1441}
1442
1443/*
1444 * This variant of list_concat_unique() operates upon lists of integers.
1445 */
1446List *
1448{
1449 ListCell *cell;
1450
1453
1454 foreach(cell, list2)
1455 {
1456 if (!list_member_int(list1, lfirst_int(cell)))
1458 }
1459
1461 return list1;
1462}
1463
1464/*
1465 * This variant of list_concat_unique() operates upon lists of OIDs.
1466 */
1467List *
1469{
1470 ListCell *cell;
1471
1474
1475 foreach(cell, list2)
1476 {
1477 if (!list_member_oid(list1, lfirst_oid(cell)))
1479 }
1480
1482 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 */
1493void
1495{
1496 int len;
1497
1498 Assert(IsOidList(list));
1499 len = list_length(list);
1500 if (len > 1)
1501 {
1502 ListCell *elements = list->elements;
1503 int i = 0;
1504
1505 for (int j = 1; j < len; j++)
1506 {
1507 if (elements[i].oid_value != elements[j].oid_value)
1508 elements[++i].oid_value = elements[j].oid_value;
1509 }
1510 list->length = i + 1;
1511 }
1513}
1514
1515/*
1516 * Free all storage in a list, and optionally the pointed-to elements
1517 */
1518static void
1519list_free_private(List *list, bool deep)
1520{
1521 if (list == NIL)
1522 return; /* nothing to do */
1523
1525
1526 if (deep)
1527 {
1528 for (int i = 0; i < list->length; i++)
1529 pfree(lfirst(&list->elements[i]));
1530 }
1531 if (list->elements != list->initial_elements)
1532 pfree(list->elements);
1533 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 */
1544void
1545list_free(List *list)
1546{
1547 list_free_private(list, false);
1548}
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 */
1558void
1559list_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 list_free_private(list, true);
1566}
1567
1568/*
1569 * Return a shallow copy of the specified list.
1570 */
1571List *
1572list_copy(const List *oldlist)
1573{
1574 List *newlist;
1575
1576 if (oldlist == NIL)
1577 return NIL;
1578
1579 newlist = new_list(oldlist->type, oldlist->length);
1580 memcpy(newlist->elements, oldlist->elements,
1581 newlist->length * sizeof(ListCell));
1582
1584 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 */
1591List *
1592list_copy_head(const List *oldlist, int len)
1593{
1594 List *newlist;
1595
1596 if (oldlist == NIL || len <= 0)
1597 return NIL;
1598
1599 len = Min(oldlist->length, len);
1600
1601 newlist = new_list(oldlist->type, len);
1602 memcpy(newlist->elements, oldlist->elements, len * sizeof(ListCell));
1603
1605 return newlist;
1606}
1607
1608/*
1609 * Return a shallow copy of the specified list, without the first N elements.
1610 */
1611List *
1612list_copy_tail(const List *oldlist, int nskip)
1613{
1614 List *newlist;
1615
1616 if (nskip < 0)
1617 nskip = 0; /* would it be better to elog? */
1618
1619 if (oldlist == NIL || nskip >= oldlist->length)
1620 return NIL;
1621
1622 newlist = new_list(oldlist->type, oldlist->length - nskip);
1623 memcpy(newlist->elements, &oldlist->elements[nskip],
1624 newlist->length * sizeof(ListCell));
1625
1627 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 */
1637List *
1639{
1640 List *newlist;
1641
1642 if (oldlist == NIL)
1643 return NIL;
1644
1645 /* This is only sensible for pointer Lists */
1647
1648 newlist = new_list(oldlist->type, oldlist->length);
1649 for (int i = 0; i < newlist->length; i++)
1650 lfirst(&newlist->elements[i]) =
1651 copyObjectImpl(lfirst(&oldlist->elements[i]));
1652
1654 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 */
1672void
1674{
1675 typedef int (*qsort_comparator) (const void *a, const void *b);
1676 int len;
1677
1679
1680 /* Nothing to do if there's less than two elements */
1681 len = list_length(list);
1682 if (len > 1)
1683 qsort(list->elements, len, sizeof(ListCell), (qsort_comparator) cmp);
1684}
1685
1686/*
1687 * list_sort comparator for sorting a list into ascending int order.
1688 */
1689int
1690list_int_cmp(const ListCell *p1, const ListCell *p2)
1691{
1692 int v1 = lfirst_int(p1);
1693 int v2 = lfirst_int(p2);
1694
1695 return pg_cmp_s32(v1, v2);
1696}
1697
1698/*
1699 * list_sort comparator for sorting a list into ascending OID order.
1700 */
1701int
1702list_oid_cmp(const ListCell *p1, const ListCell *p2)
1703{
1704 Oid v1 = lfirst_oid(p1);
1705 Oid v2 = lfirst_oid(p2);
1706
1707 return pg_cmp_u32(v1, v2);
1708}
#define Min(x, y)
Definition c.h:997
#define Max(x, y)
Definition c.h:991
#define Assert(condition)
Definition c.h:873
uint32 TransactionId
Definition c.h:666
void * copyObjectImpl(const void *from)
Definition copyfuncs.c:177
bool equal(const void *a, const void *b)
Definition equalfuncs.c:223
static int pg_cmp_u32(uint32 a, uint32 b)
Definition int.h:719
static int pg_cmp_s32(int32 a, int32 b)
Definition int.h:713
int b
Definition isn.c:74
int a
Definition isn.c:73
int j
Definition isn.c:78
int i
Definition isn.c:77
List * lcons_oid(Oid datum, List *list)
Definition list.c:531
List * list_difference(const List *list1, const List *list2)
Definition list.c:1237
List * list_union_ptr(const List *list1, const List *list2)
Definition list.c:1090
List * list_make4_impl(NodeTag t, ListCell datum1, ListCell datum2, ListCell datum3, ListCell datum4)
Definition list.c:270
static void new_head_cell(List *list)
Definition list.c:305
List * list_delete_ptr(List *list, void *datum)
Definition list.c:872
List * list_copy_deep(const List *oldlist)
Definition list.c:1639
List * list_concat_unique_oid(List *list1, const List *list2)
Definition list.c:1469
List * lappend(List *list, void *datum)
Definition list.c:339
List * list_delete(List *list, void *datum)
Definition list.c:853
void list_sort(List *list, list_sort_comparator cmp)
Definition list.c:1674
List * list_difference_ptr(const List *list1, const List *list2)
Definition list.c:1263
List * list_difference_int(const List *list1, const List *list2)
Definition list.c:1288
List * list_intersection(const List *list1, const List *list2)
Definition list.c:1174
List * list_make3_impl(NodeTag t, ListCell datum1, ListCell datum2, ListCell datum3)
Definition list.c:257
List * list_delete_oid(List *list, Oid datum)
Definition list.c:910
#define IsOidList(l)
Definition list.c:57
List * list_insert_nth_oid(List *list, int pos, Oid datum)
Definition list.c:467
List * list_concat_unique_ptr(List *list1, const List *list2)
Definition list.c:1427
#define IsXidList(l)
Definition list.c:58
static void enlarge_list(List *list, int min_size)
Definition list.c:155
#define LIST_HEADER_OVERHEAD
Definition list.c:48
List * list_append_unique(List *list, void *datum)
Definition list.c:1343
List * lappend_xid(List *list, TransactionId datum)
Definition list.c:393
List * list_copy_tail(const List *oldlist, int nskip)
Definition list.c:1613
List * list_delete_nth_cell(List *list, int n)
Definition list.c:767
List * list_delete_first(List *list)
Definition list.c:943
List * list_difference_oid(const List *list1, const List *list2)
Definition list.c:1313
List * list_concat(List *list1, const List *list2)
Definition list.c:561
static ListCell * insert_new_cell(List *list, int pos)
Definition list.c:415
List * list_delete_cell(List *list, ListCell *cell)
Definition list.c:841
List * list_concat_copy(const List *list1, const List *list2)
Definition list.c:598
List * list_copy(const List *oldlist)
Definition list.c:1573
List * list_union_oid(const List *list1, const List *list2)
Definition list.c:1136
#define IsIntegerList(l)
Definition list.c:56
bool list_member_xid(const List *list, TransactionId datum)
Definition list.c:742
List * lappend_int(List *list, int datum)
Definition list.c:357
static void list_free_private(List *list, bool deep)
Definition list.c:1520
List * list_make1_impl(NodeTag t, ListCell datum1)
Definition list.c:236
List * list_intersection_int(const List *list1, const List *list2)
Definition list.c:1200
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
List * lcons(void *datum, List *list)
Definition list.c:495
#define check_list_invariants(l)
Definition list.c:80
List * list_append_unique_oid(List *list, Oid datum)
Definition list.c:1380
List * lcons_int(int datum, List *list)
Definition list.c:513
List * list_insert_nth_int(List *list, int pos, int datum)
Definition list.c:453
void list_deduplicate_oid(List *list)
Definition list.c:1495
static void new_tail_cell(List *list)
Definition list.c:323
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition list.c:1703
List * list_make2_impl(NodeTag t, ListCell datum1, ListCell datum2)
Definition list.c:246
List * list_delete_int(List *list, int datum)
Definition list.c:891
static List * new_list(NodeTag type, int min_size)
Definition list.c:91
List * list_delete_last(List *list)
Definition list.c:957
bool list_member_ptr(const List *list, const void *datum)
Definition list.c:682
void list_free(List *list)
Definition list.c:1546
bool list_member_int(const List *list, int datum)
Definition list.c:702
bool list_member_oid(const List *list, Oid datum)
Definition list.c:722
List * list_append_unique_int(List *list, int datum)
Definition list.c:1368
int list_int_cmp(const ListCell *p1, const ListCell *p2)
Definition list.c:1691
List * list_delete_first_n(List *list, int n)
Definition list.c:983
List * list_truncate(List *list, int new_size)
Definition list.c:631
bool list_member(const List *list, const void *datum)
Definition list.c:661
List * list_concat_unique_int(List *list1, const List *list2)
Definition list.c:1448
List * list_copy_head(const List *oldlist, int len)
Definition list.c:1593
List * list_union_int(const List *list1, const List *list2)
Definition list.c:1113
List * list_concat_unique(List *list1, const List *list2)
Definition list.c:1405
List * list_make5_impl(NodeTag t, ListCell datum1, ListCell datum2, ListCell datum3, ListCell datum4, ListCell datum5)
Definition list.c:284
#define IsPointerList(l)
Definition list.c:55
List * list_append_unique_ptr(List *list, void *datum)
Definition list.c:1356
void list_free_deep(List *list)
Definition list.c:1560
List * list_insert_nth(List *list, int pos, void *datum)
Definition list.c:439
List * list_union(const List *list1, const List *list2)
Definition list.c:1066
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1232
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1632
void pfree(void *pointer)
Definition mcxt.c:1616
void * palloc(Size size)
Definition mcxt.c:1387
MemoryContext GetMemoryChunkContext(void *pointer)
Definition mcxt.c:756
#define VALGRIND_MAKE_MEM_NOACCESS(addr, size)
Definition memdebug.h:27
#define IsA(nodeptr, _type_)
Definition nodes.h:164
NodeTag
Definition nodes.h:27
static uint32 pg_nextpower2_32(uint32 num)
const void size_t len
#define lfirst(lc)
Definition pg_list.h:172
#define llast_int(l)
Definition pg_list.h:199
#define llast(l)
Definition pg_list.h:198
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
#define lfirst_int(lc)
Definition pg_list.h:173
#define list_make1_oid(x1)
Definition pg_list.h:242
#define list_make1(x1)
Definition pg_list.h:212
#define linitial_int(l)
Definition pg_list.h:179
#define llast_oid(l)
Definition pg_list.h:200
#define linitial(l)
Definition pg_list.h:178
int(* list_sort_comparator)(const ListCell *a, const ListCell *b)
Definition pg_list.h:680
#define list_make1_int(x1)
Definition pg_list.h:227
#define linitial_oid(l)
Definition pg_list.h:180
#define lfirst_oid(lc)
Definition pg_list.h:174
#define llast_xid(l)
Definition pg_list.h:201
#define lfirst_xid(lc)
Definition pg_list.h:175
#define qsort(a, b, c, d)
Definition port.h:495
unsigned int Oid
static int fb(int x)
static int cmp(const chr *x, const chr *y, size_t len)
Definition pg_list.h:54
ListCell * elements
Definition pg_list.h:58
Oid oid_value
Definition pg_list.h:49
const char * type

Function Documentation

◆ enlarge_list()

static void enlarge_list ( List list,
int  min_size 
)
static

Definition at line 155 of file list.c.

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 */
170
171#else
172 /* As above, don't allocate anything extra */
174#endif
175
176 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 list->elements = (ListCell *)
187 new_max_len * sizeof(ListCell));
188 memcpy(list->elements, list->initial_elements,
189 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 list->elements = (ListCell *) repalloc(list->elements,
210 new_max_len * sizeof(ListCell));
211#else
212 /*
213 * repalloc() might enlarge the space in-place, which we don't want
214 * for debugging purposes, so forcibly move the data somewhere else.
215 */
217
220 new_max_len * sizeof(ListCell));
221 memcpy(newelements, list->elements,
222 list->length * sizeof(ListCell));
223 pfree(list->elements);
224 list->elements = newelements;
225#endif
226 }
227
228 list->max_length = new_max_len;
229}

References Assert, fb(), GetMemoryChunkContext(), Max, MemoryContextAlloc(), pfree(), pg_nextpower2_32(), repalloc(), and VALGRIND_MAKE_MEM_NOACCESS.

Referenced by insert_new_cell(), list_concat(), new_head_cell(), and new_tail_cell().

◆ insert_new_cell()

static ListCell * insert_new_cell ( List list,
int  pos 
)
static

Definition at line 415 of file list.c.

416{
417 Assert(pos >= 0 && pos <= list->length);
418
419 /* Enlarge array if necessary */
420 if (list->length >= list->max_length)
421 enlarge_list(list, list->length + 1);
422 /* Now shove the existing data over */
423 if (pos < list->length)
424 memmove(&list->elements[pos + 1], &list->elements[pos],
425 (list->length - pos) * sizeof(ListCell));
426 list->length++;
427
428 return &list->elements[pos];
429}

References Assert, enlarge_list(), and fb().

Referenced by list_insert_nth(), list_insert_nth_int(), and list_insert_nth_oid().

◆ lappend()

List * lappend ( List list,
void datum 
)

Definition at line 339 of file list.c.

340{
341 Assert(IsPointerList(list));
342
343 if (list == NIL)
344 list = new_list(T_List, 1);
345 else
346 new_tail_cell(list);
347
348 llast(list) = datum;
350 return list;
351}

References Assert, check_list_invariants, fb(), IsPointerList, llast, new_list(), new_tail_cell(), and NIL.

Referenced by _SPI_make_plan_non_temp(), _SPI_prepare_oneshot_plan(), _SPI_prepare_plan(), _SPI_save_plan(), accumulate_append_subpath(), AcquireRewriteLocks(), add_base_clause_to_rel(), add_child_eq_member(), add_column_to_pathtarget(), add_dummy_return(), add_eq_member(), add_join_clause_to_rels(), add_join_rel(), add_local_reloption(), add_merged_range_bounds(), add_outer_joins_to_relids(), add_part_relids(), add_paths_to_append_rel(), add_placeholders_to_base_rels(), add_placeholders_to_joinrel(), add_row_identity_var(), add_rte_to_flat_rtable(), add_security_quals(), add_to_flat_tlist(), add_unique_group_var(), add_vars_to_targetlist(), add_with_check_options(), addArc(), AddEventToPendingNotifies(), addFamilyMember(), addFkRecurseReferencing(), addKey(), addKeyToQueue(), addNSItemToQuery(), addRangeTableEntry(), addRangeTableEntryForCTE(), addRangeTableEntryForENR(), addRangeTableEntryForFunction(), addRangeTableEntryForGroup(), addRangeTableEntryForJoin(), addRangeTableEntryForRelation(), addRangeTableEntryForSubquery(), addRangeTableEntryForTableFunc(), addRangeTableEntryForValues(), AddRelationNewConstraints(), AddRelationNotNullConstraints(), addRTEPermissionInfo(), addTargetToGroupList(), addTargetToSortList(), AlterPublicationTables(), AlterSubscription_refresh(), AlterTableMoveAll(), AlterTSDictionary(), analyzeCTE(), analyzeCTETargetList(), append_pathkeys(), apply_child_basequals(), apply_handle_truncate(), apply_scanjoin_target_to_paths(), applyLockingClause(), ApplyRetrieveRule(), array_subscript_transform(), assign_param_for_placeholdervar(), assign_param_for_var(), ATAddCheckNNConstraint(), ATExecAddColumn(), ATExecAlterConstrEnforceability(), ATExecSetExpression(), ATExecSplitPartition(), ATGetQueueEntry(), ATParseTransformCmd(), ATPostAlterTypeCleanup(), ATPostAlterTypeParse(), ATPrepAlterColumnType(), ATPrepCmd(), BaseBackupAddTarget(), btcostestimate(), build_aggregate_finalfn_expr(), build_aggregate_transfn_expr(), build_coercion_expression(), build_index_pathkeys(), build_index_paths(), build_index_tlist(), build_join_rel(), build_joinrel_tlist(), build_partition_pathkeys(), build_path_tlist(), build_physical_tlist(), build_remote_returning(), build_subplan(), BuildEventTriggerCache(), BuildOnConflictExcludedTargetlist(), buildRelationAliases(), cached_scansel(), calc_joinrel_size_estimate(), calculate_partition_bound_for_merge(), can_minmax_aggs(), check_index_predicates(), check_selective_binary_conversion(), check_sql_stmt_retval(), check_tuple_attribute(), CheckAndReportConflict(), CheckDuplicateColumnOrPathNames(), checkInsertTargets(), checkSharedDependencies(), checkWellFormedRecursionWalker(), choose_bitmap_and(), choose_plan_name(), ChooseIndexColumnNames(), classifyConditions(), clauselist_apply_dependencies(), CloneFkReferenced(), CloneFkReferencing(), CloneRowTriggersToPartition(), coerce_fn_result_column(), coerce_record_to_complex(), compute_common_attribute(), compute_semi_anti_join_factors(), compute_semijoin_info(), ComputeIndexAttrs(), ComputePartitionAttrs(), consider_groupingsets_paths(), consider_new_or_clause(), convert_ANY_sublink_to_join(), convert_EXISTS_to_ANY(), convert_subquery_pathkeys(), convert_VALUES_to_ANY(), CopyMultiInsertInfoFlush(), CopyMultiInsertInfoSetupBuffer(), cost_incremental_sort(), create_append_plan(), create_bitmap_scan_plan(), create_bitmap_subplan(), create_ctas_nodata(), create_customscan_plan(), create_degenerate_grouping_paths(), create_edata_for_relation(), create_grouping_expr_infos(), create_groupingsets_plan(), create_hashjoin_plan(), create_index_paths(), create_indexscan_plan(), create_merge_append_plan(), create_nestloop_path(), create_nestloop_plan(), create_one_window_path(), create_partitionwise_grouping_paths(), create_tidrangescan_plan(), create_tidscan_plan(), create_unique_paths(), CreateStatistics(), createTableConstraints(), database_to_xmlschema_internal(), deconstruct_distribute(), deconstruct_recurse(), DefineRelation(), DefineSequence(), DefineTSDictionary(), DefineView(), DefineVirtualRelation(), deparseFromExprForRel(), deparseParam(), deparseVar(), dependencies_object_end(), deserialize_deflist(), DetachPartitionFinalize(), determineRecursiveColTypes(), distribute_qual_to_rels(), distribute_row_identity_vars(), do_pg_backup_start(), DoCopy(), ec_add_derived_clause(), estimate_multivariate_bucketsize(), estimate_multivariate_ndistinct(), estimate_num_groups(), eval_const_expressions_mutator(), EvalPlanQualStart(), EventTriggerAlterTableEnd(), EventTriggerCollectAlterDefPrivs(), EventTriggerCollectAlterOpFam(), EventTriggerCollectAlterTableSubcmd(), EventTriggerCollectAlterTSConfig(), EventTriggerCollectCreateOpClass(), EventTriggerCollectGrant(), EventTriggerCollectSimpleCommand(), ExecAllocTableSlot(), ExecDoInitialPruning(), ExecEvalXmlExpr(), ExecGetAncestorResultRels(), ExecGetTriggerResultRel(), ExecInitExprList(), ExecInitExprRec(), ExecInitInsertProjection(), ExecInitJsonExpr(), ExecInitLockRows(), ExecInitMerge(), ExecInitModifyTable(), ExecInitNode(), ExecInitPartitionInfo(), ExecInitResultRelation(), ExecInitSubPlan(), ExecInitSubPlanExpr(), ExecInsert(), ExecPrepareExprList(), ExecSerializePlan(), ExecuteGrantStmt(), ExecuteTruncate(), ExecuteTruncateGuts(), expand_generated_columns_internal(), expand_grouping_sets(), expand_groupingset_node(), expand_inherited_rtentry(), expand_insert_targetlist(), expand_single_inheritance_child(), expand_vacuum_rel(), expand_virtual_generated_columns(), expandNSItemAttrs(), expandNSItemVars(), ExpandRowReference(), expandRTE(), expandTableLikeClause(), expandTupleDesc(), ExplainNode(), ExportSnapshot(), expr_setup_walker(), expression_tree_mutator_impl(), extract_actual_clauses(), extract_actual_join_clauses(), extract_jsp_path_expr_nodes(), extract_lateral_references(), extract_lateral_vars_from_PHVs(), extract_nonindex_conditions(), extract_or_clause(), extract_rollup_sets(), extract_slot_names(), extractRemainingColumns(), fetch_relation_list(), fetch_remote_slots(), fetch_remote_table_info(), fetch_statentries_for_relation(), fetch_upper_rel(), FetchRelationStates(), file_fdw_validator(), fill_hba_line(), FilterWalSummaries(), find_duplicate_ors(), find_hash_columns(), find_indexpath_quals(), find_list_position(), find_mergeclauses_for_outer_pathkeys(), find_partition_scheme(), find_placeholder_info(), find_window_functions_walker(), find_window_run_conditions(), findTargetlistEntrySQL99(), fireRIRrules(), fireRules(), fix_indexorderby_references(), fix_indexqual_references(), flatten_grouping_sets(), flatten_join_alias_vars_mutator(), flatten_simple_union_all(), fmgr_security_definer(), fmgr_sql_validator(), foreign_grouping_ok(), foreign_join_ok(), format_operator_parts(), format_procedure_parts(), func_get_detail(), gen_partprune_steps_internal(), gen_prune_step_combine(), gen_prune_step_op(), gen_prune_steps_from_opexps(), generate_append_tlist(), generate_bitmap_or_paths(), generate_implied_equalities_for_column(), generate_join_implied_equalities_broken(), generate_join_implied_equalities_normal(), generate_matching_part_pairs(), generate_orderedappend_paths(), generate_partitionwise_join_paths(), generate_setop_tlist(), generate_subquery_params(), generate_subquery_vars(), generate_union_paths(), generateClonedExtStatsStmt(), generateClonedIndexStmt(), generateJsonTablePathName(), generateSerialExtraStmts(), get_actual_clauses(), get_all_vacuum_rels(), get_appendrel_parampathinfo(), get_baserel_parampathinfo(), get_database_list(), get_eclass_for_sort_expr(), get_ext_ver_info(), get_ext_ver_list(), get_extension_control_directories(), get_file_fdw_attribute_options(), get_foreign_key_join_selectivity(), get_func_expr(), get_index_clause_from_support(), get_index_paths(), get_insert_query_def(), get_join_index_paths(), get_joinrel_parampathinfo(), get_local_synced_slots(), get_matching_part_pairs(), get_merge_query_def(), get_op_index_interpretation(), get_policies_for_relation(), get_qual_for_hash(), get_qual_for_list(), get_qual_for_range(), get_quals_from_indexclauses(), get_range_nulltest(), get_rel_sync_entry(), get_relation_constraints(), get_relation_foreign_keys(), get_relation_statistics_worker(), get_rels_with_domain(), get_required_extension(), get_sortgrouplist_exprs(), get_steps_using_prefix_recurse(), get_subscription_list(), get_switched_clauses(), get_tables_to_cluster(), get_tables_to_cluster_partitioned(), get_tlist_exprs(), get_update_query_targetlist_def(), get_useful_ecs_for_relation(), get_useful_group_keys_orderings(), get_useful_pathkeys_for_distinct(), get_useful_pathkeys_for_relation(), get_useful_pathkeys_for_relation(), get_windowfunc_expr_helper(), GetAfterTriggersTableData(), getAttributesList(), getObjectIdentityParts(), getState(), GetSubscriptionRelations(), getTokenTypes(), GetWalSummaries(), gistFindPath(), gistfixsplit(), gistplacetopage(), group_keys_reorder_by_pathkeys(), group_similar_or_args(), grouping_planner(), hash_inner_and_outer(), hashagg_spill_finish(), heap_truncate(), identify_current_nestloop_params(), identify_opfamily_groups(), index_concurrently_create_copy(), infer_arbiter_indexes(), init_grouping_targets(), initialize_target_list(), InitPlan(), injection_points_attach(), InjectionPointList(), innerrel_is_unique_ext(), interpret_AS_clause(), interpret_function_parameter_list(), intorel_startup(), is_innerrel_unique_for(), join_is_removable(), jsonb_ops__extract_nodes(), jsonb_path_ops__extract_nodes(), jsonb_subscript_transform(), JsonTableInitOpaque(), JsonValueListAppend(), list_append_unique(), list_append_unique_ptr(), list_concat_unique(), list_concat_unique_ptr(), list_difference(), list_difference_ptr(), list_intersection(), list_union(), list_union_ptr(), llvm_compile_module(), load_hba(), load_ident(), LoadPublications(), Lock_AF_UNIX(), logicalrep_workers_find(), LogicalRepSyncSequences(), make_bitmap_paths_for_or_group(), make_canonical_pathkey(), make_copy_attnamelist(), make_group_input_target(), make_inh_translation_list(), make_inner_pathkeys_for_merge(), make_modifytable(), make_partial_grouping_target(), make_partition_op_expr(), make_partition_pruneinfo(), make_partitionedrel_pruneinfo(), make_path_rowexpr(), make_pathkeys_for_sortclauses_extended(), make_pathtarget_from_tlist(), make_rel_from_joinlist(), make_row_comparison_op(), make_setop_translation_list(), make_sort_input_target(), make_sub_restrictinfos(), make_tlist_from_pathtarget(), make_window_input_target(), manifest_process_wal_range(), MarkGUCPrefixReserved(), markRelsAsNulledBy(), match_clause_to_index(), match_clause_to_partition_key(), match_foreign_keys_to_quals(), match_network_subset(), match_orclause_to_indexcol(), match_pathkeys_to_index(), match_pattern_prefix(), matchLocks(), mbms_add_member(), mbms_add_members(), merge_clump(), merge_list_bounds(), merge_publications(), MergeAttributes(), MergeCheckConstraint(), ndistinct_object_end(), negate_clause(), next_field_expand(), nodeRead(), ObjectsInPublicationToOids(), OpenTableList(), order_qual_clauses(), pa_launch_parallel_worker(), paraminfo_get_equal_hashops(), parse_hba_line(), parseCheckAggregates(), ParseFuncOrColumn(), PartConstraintImpliedByRelConstraint(), partitions_listdatum_intersection(), perform_base_backup(), pg_available_extension_versions(), pg_available_extensions(), pg_get_backend_memory_contexts(), pg_get_object_address(), pg_get_publication_tables(), pg_logical_slot_get_changes_guts(), pg_plan_queries(), pg_rewrite_query(), pgfdw_abort_cleanup_begin(), pgfdw_finish_abort_cleanup(), pgfdw_finish_pre_commit_cleanup(), pgfdw_subxact_callback(), pgfdw_xact_callback(), pgoutput_row_filter_init(), plan_union_children(), populate_typ_list(), postgresGetForeignPaths(), postgresGetForeignPlan(), postgresImportForeignSchema(), PreCommit_Notify(), prep_domain_constraints(), prepare_next_query(), prepare_sort_from_pathkeys(), preprocess_aggref(), preprocess_groupclause(), preprocess_grouping_sets(), preprocess_rowmarks(), preprocess_targetlist(), process_duplicate_ors(), process_equivalence(), process_pipe_input(), process_sublinks_mutator(), process_subquery_nestloop_params(), ProcessStartupPacket(), pull_ands(), pull_ors(), pull_up_simple_values(), pull_up_sublinks_jointree_recurse(), pull_up_sublinks_qual_recurse(), pull_up_union_leaf_queries(), pull_var_clause_walker(), pull_vars_walker(), query_tree_mutator_impl(), QueryRewrite(), queue_listen(), QueueCheckConstraintValidation(), QueueFKConstraintValidation(), range_table_mutator_impl(), read_tablespace_map(), rebuild_fdw_scan_tlist(), RebuildConstraintComment(), record_plan_function_dependency(), record_plan_type_dependency(), reduce_outer_joins_pass1(), register_ENR(), register_label_provider(), register_partpruneinfo(), register_reloptions_validator(), ReindexRelationConcurrently(), relation_excluded_by_constraints(), relation_has_unique_index_for(), RelationCacheInvalidate(), RelationGetDummyIndexExpressions(), RelationGetFKeyList(), RelationGetNotNullConstraints(), remap_to_groupclause_idx(), RememberConstraintForRebuilding(), RememberIndexForRebuilding(), RememberStatisticsForRebuilding(), RememberSyncRequest(), remove_rel_from_joinlist(), remove_self_join_rel(), remove_useless_groupby_columns(), RemoveInheritance(), reorder_function_arguments(), reparameterize_path(), reparameterize_path_by_child(), reparameterize_pathlist_by_child(), replace_empty_jointree(), replace_nestloop_param_placeholdervar(), replace_nestloop_param_var(), replace_outer_agg(), replace_outer_grouping(), replace_outer_merge_support(), replace_outer_returning(), ReplaceVarFromTargetList(), report_reduced_full_join(), resolve_unique_index_expr(), RewriteQuery(), rewriteSearchAndCycle(), rewriteTargetListIU(), rewriteTargetView(), rewriteValuesRTE(), rewriteValuesRTEToNulls(), RI_Initial_Check(), ScanSourceDatabasePgClassPage(), schema_to_xmlschema_internal(), SearchCatCacheList(), select_active_windows(), select_mergejoin_clauses(), select_outer_pathkeys_for_merge(), sepgsql_set_client_label(), sequence_options(), set_append_rel_pathlist(), set_append_rel_size(), set_cheapest(), set_deparse_for_query(), set_dummy_tlist_references(), set_indexonlyscan_references(), set_joinrel_partition_key_exprs(), set_plan_references(), set_plan_refs(), set_rtable_names(), set_simple_column_names(), set_subquery_pathlist(), set_upper_references(), set_using_names(), show_grouping_set_keys(), show_incremental_sort_group_info(), show_modifytable_info(), show_plan_tlist(), show_sort_group_keys(), show_tablesample(), simplify_and_arguments(), simplify_or_arguments(), split_pathtarget_at_srfs_extended(), split_pathtarget_walker(), split_selfjoin_quals(), SplitDirectoriesString(), SplitGUCList(), SplitIdentifierString(), SplitPartitionMoveRows(), SS_make_initplan_from_plan(), SS_process_ctes(), statext_is_compatible_clause_internal(), statext_mcv_clauselist_selectivity(), stringToQualifiedNameList(), subquery_planner(), table_slot_create(), textarray_to_stringlist(), textarray_to_strvaluelist(), textToQualifiedNameList(), TidExprListCreate(), TidExprListCreate(), TidRangeQualFromRestrictInfoList(), tokenize_auth_file(), tokenize_expand_file(), transform_MERGE_to_join(), transformAExprIn(), transformAggregateCall(), transformAlterTableStmt(), transformArrayExpr(), transformAssignmentIndirection(), transformBoolExpr(), transformCallStmt(), transformCaseExpr(), transformCoalesceExpr(), transformColumnDefinition(), transformCreateSchemaStmtElements(), transformCreateStmt(), transformDistinctClause(), transformDistinctOnClause(), transformExpressionList(), transformFKConstraints(), transformFkeyGetPrimaryKey(), transformFromClause(), transformFromClauseItem(), transformFuncCall(), transformGenericOptions(), transformGroupClause(), transformGroupClauseExpr(), transformGroupingFunc(), transformGroupingSet(), TransformGUCArray(), transformIndexConstraint(), transformIndexConstraints(), transformIndirection(), transformInsertRow(), transformInsertStmt(), transformJoinUsingClause(), transformJsonArrayConstructor(), transformJsonObjectConstructor(), transformJsonPassingArgs(), transformJsonTableColumns(), transformMergeStmt(), transformMinMaxExpr(), transformMultiAssignRef(), transformOfType(), transformPartitionBound(), transformPartitionRangeBounds(), transformPartitionSpec(), transformPLAssignStmt(), transformRangeFunction(), transformRangeTableFunc(), transformRangeTableSample(), transformRowExpr(), transformRuleStmt(), transformSetOperationStmt(), transformSetOperationTree(), transformSubLink(), transformTableConstraint(), transformTableLikeClause(), transformTargetList(), transformValuesClause(), transformWindowDefinitions(), transformWindowFuncCall(), transformWithClause(), transformXmlExpr(), trim_mergeclauses_for_inner_pathkeys(), TS_execute_locations_recurse(), untransformRelOptions(), update_eclasses(), UpdateLogicalMappings(), WaitForLockersMultiple(), WalkInnerWith(), and xmlelement().

◆ lappend_int()

List * lappend_int ( List list,
int  datum 
)

Definition at line 357 of file list.c.

358{
359 Assert(IsIntegerList(list));
360
361 if (list == NIL)
362 list = new_list(T_IntList, 1);
363 else
364 new_tail_cell(list);
365
366 llast_int(list) = datum;
368 return list;
369}

References Assert, check_list_invariants, fb(), IsIntegerList, llast_int, new_list(), new_tail_cell(), and NIL.

Referenced by add_merged_range_bounds(), addRangeTableEntryForCTE(), addRangeTableEntryForENR(), addRangeTableEntryForFunction(), addRangeTableEntryForGroup(), addRangeTableEntryForSubquery(), AddRelationNotNullConstraints(), adjust_inherited_attnums(), adjust_partition_colnos_using_map(), analyzeCTETargetList(), ATRewriteTable(), build_merged_partition_bounds(), build_subplan(), checkInsertTargets(), convert_EXISTS_to_ANY(), copy_sequences(), CopyGetAttnums(), create_grouping_expr_infos(), deparseAnalyzeSql(), deparseExplicitTargetList(), deparseTargetList(), dependencies_scalar(), ExecBuildAggTrans(), ExecBuildGroupingEqual(), ExecBuildHash32Expr(), ExecBuildParamSetEqual(), ExecConstraints(), ExecInitExprRec(), ExecInitJsonExpr(), ExecInitModifyTable(), ExecInitPartitionInfo(), ExecInitQual(), ExecInitSubscriptingRef(), expand_indexqual_rowcompare(), extract_update_targetlist_colnos(), extractRemainingColumns(), fetch_statentries_for_relation(), finalize_grouping_exprs_walker(), find_all_inheritors(), find_compatible_agg(), fix_expr_common(), gen_partprune_steps_internal(), generate_subquery_params(), grouping_planner(), list_append_unique_int(), list_concat_unique_int(), list_difference_int(), list_intersection_int(), list_union_int(), match_pathkeys_to_index(), merge_list_bounds(), ndistinct_scalar(), nodeRead(), plan_union_children(), postgresBeginForeignInsert(), postgresPlanForeignModify(), rel_is_distinct_for(), remap_to_groupclause_idx(), RemoveInheritance(), reorder_grouping_sets(), rewriteSearchAndCycle(), set_plan_refs(), split_pathtarget_at_srfs_extended(), SS_process_ctes(), substitute_grouped_columns_mutator(), TerminateOtherDBBackends(), test_bms_overlap_list(), transformDistinctOnClause(), transformFromClauseItem(), transformGroupClauseList(), transformInsertStmt(), transformJsonTableColumns(), transformRangeTableFunc(), transformSetOperationTree(), and transformValuesClause().

◆ lappend_oid()

List * lappend_oid ( List list,
Oid  datum 
)

Definition at line 375 of file list.c.

376{
377 Assert(IsOidList(list));
378
379 if (list == NIL)
380 list = new_list(T_OidList, 1);
381 else
382 new_tail_cell(list);
383
384 llast_oid(list) = datum;
386 return list;
387}

References Assert, check_list_invariants, fb(), IsOidList, llast_oid, new_list(), new_tail_cell(), and NIL.

Referenced by add_rte_to_flat_rtable(), addRangeTableEntryForCTE(), addRangeTableEntryForENR(), addRangeTableEntryForFunction(), addRangeTableEntryForGroup(), addRangeTableEntryForSubquery(), AfterTriggerSetState(), AlterTableMoveAll(), analyzeCTETargetList(), apply_handle_truncate(), ApplyExtensionUpdates(), assign_collations_walker(), assign_param_for_placeholdervar(), assign_param_for_var(), assign_special_exec_param(), ATExecMergePartitions(), binary_upgrade_create_empty_extension(), check_functional_grouping(), CheckAttributeType(), CloneFkReferenced(), CloneFkReferencing(), compute_semijoin_info(), convert_EXISTS_to_ANY(), create_hashjoin_plan(), create_indexscan_plan(), CreateExtensionInternal(), CreateFunction(), DefineRelation(), DetachPartitionFinalize(), do_autovacuum(), EventTriggerCommonSetup(), ExecAlterDefaultPrivilegesStmt(), ExecInitPartitionInfo(), ExecInsertIndexTuples(), ExecuteGrantStmt(), ExecuteTruncate(), ExecuteTruncateGuts(), expand_indexqual_rowcompare(), extract_query_dependencies_walker(), ExtractExtensionList(), finalNamespacePath(), find_all_inheritors(), find_inheritance_children_extended(), find_typed_table_dependencies(), fireRIRrules(), fix_expr_common(), generate_new_exec_param(), get_index_ref_constraints(), get_mergejoin_opfamilies(), get_partition_ancestors_worker(), get_steps_using_prefix_recurse(), GetAllPublicationRelations(), GetAllTablesPublications(), getAutoExtensionsOfObject(), getOwnedSequences_internal(), GetParentedForeignKeyRefs(), GetPublicationSchemas(), GetPubPartitionOptionRelations(), GetRelationPublications(), getRelationsInNamespace(), GetSchemaPublicationRelations(), GetSchemaPublications(), heap_truncate_check_FKs(), heap_truncate_find_FKs(), index_concurrently_swap(), infer_arbiter_indexes(), InitConflictIndexes(), inline_function(), interpret_function_parameter_list(), list_append_unique_oid(), list_concat_unique_oid(), list_difference_oid(), list_union_oid(), LockViewRecurse(), logicalrep_read_truncate(), make_row_comparison_op(), nodeRead(), objectNamesToOids(), objectsInSchemaToOids(), oid_array_to_list(), OpenTableList(), paraminfo_get_equal_hashops(), PreCommit_on_commit_actions(), preprocessNamespacePath(), query_to_oid_list(), ReindexMultipleTables(), ReindexPartitions(), ReindexRelationConcurrently(), rel_is_distinct_for(), relation_is_updatable(), RelationGetIndexList(), RelationGetStatExtList(), RememberConstraintForRebuilding(), RememberIndexForRebuilding(), RememberStatisticsForRebuilding(), remove_dbtablespaces(), replace_outer_agg(), replace_outer_grouping(), replace_outer_merge_support(), replace_outer_returning(), RestoreReindexState(), rewriteSearchAndCycle(), roles_list_append(), roleSpecsToIds(), transformAggregateCall(), transformInsertStmt(), transformJsonTableColumns(), transformPartitionCmdForMerge(), transformRangeTableFunc(), transformSetOperationTree(), transformValuesClause(), TryReuseForeignKey(), and typeInheritsFrom().

◆ lappend_xid()

List * lappend_xid ( List list,
TransactionId  datum 
)

Definition at line 393 of file list.c.

394{
395 Assert(IsXidList(list));
396
397 if (list == NIL)
398 list = new_list(T_XidList, 1);
399 else
400 new_tail_cell(list);
401
402 llast_xid(list) = datum;
404 return list;
405}

References Assert, check_list_invariants, fb(), IsXidList, llast_xid, new_list(), new_tail_cell(), and NIL.

Referenced by nodeRead(), pa_start_subtrans(), and set_schema_sent_in_streamed_txn().

◆ lcons()

List * lcons ( void datum,
List list 
)

◆ lcons_int()

List * lcons_int ( int  datum,
List list 
)

Definition at line 513 of file list.c.

514{
515 Assert(IsIntegerList(list));
516
517 if (list == NIL)
518 list = new_list(T_IntList, 1);
519 else
520 new_head_cell(list);
521
522 linitial_int(list) = datum;
524 return list;
525}

References Assert, check_list_invariants, fb(), IsIntegerList, linitial_int, new_head_cell(), new_list(), and NIL.

Referenced by ExecInitAgg(), ExplainBeginOutput(), ExplainOpenGroup(), ExplainOpenSetAsideGroup(), ExplainRestoreGroup(), and PutMemoryContextsStatsTupleStore().

◆ lcons_oid()

List * lcons_oid ( Oid  datum,
List list 
)

Definition at line 531 of file list.c.

532{
533 Assert(IsOidList(list));
534
535 if (list == NIL)
536 list = new_list(T_OidList, 1);
537 else
538 new_head_cell(list);
539
540 linitial_oid(list) = datum;
542 return list;
543}

References Assert, check_list_invariants, fb(), IsOidList, linitial_oid, new_head_cell(), new_list(), and NIL.

Referenced by finalNamespacePath(), pg_partition_ancestors(), ReindexMultipleTables(), and RememberConstraintForRebuilding().

◆ list_append_unique()

List * list_append_unique ( List list,
void datum 
)

Definition at line 1343 of file list.c.

1344{
1345 if (list_member(list, datum))
1346 return list;
1347 else
1348 return lappend(list, datum);
1349}

References lappend(), and list_member().

Referenced by add_security_quals(), add_with_check_options(), check_publications_origin_sequences(), check_publications_origin_tables(), create_agg_clause_infos(), and create_index_paths().

◆ list_append_unique_int()

List * list_append_unique_int ( List list,
int  datum 
)

Definition at line 1368 of file list.c.

1369{
1370 if (list_member_int(list, datum))
1371 return list;
1372 else
1373 return lappend_int(list, datum);
1374}

References lappend_int(), and list_member_int().

◆ list_append_unique_oid()

List * list_append_unique_oid ( List list,
Oid  datum 
)

◆ list_append_unique_ptr()

List * list_append_unique_ptr ( List list,
void datum 
)

Definition at line 1356 of file list.c.

1357{
1358 if (list_member_ptr(list, datum))
1359 return list;
1360 else
1361 return lappend(list, datum);
1362}

References lappend(), and list_member_ptr().

Referenced by get_useful_ecs_for_relation(), match_join_clauses_to_index(), postgresGetForeignPaths(), subbuild_joinrel_joinlist(), and subbuild_joinrel_restrictlist().

◆ list_concat()

List * list_concat ( List list1,
const List list2 
)

Definition at line 561 of file list.c.

562{
563 int new_len;
564
565 if (list1 == NIL)
566 return list_copy(list2);
567 if (list2 == NIL)
568 return list1;
569
570 Assert(list1->type == list2->type);
571
572 new_len = list1->length + list2->length;
573 /* Enlarge array if necessary */
574 if (new_len > list1->max_length)
576
577 /* Even if list1 == list2, using memcpy should be safe here */
578 memcpy(&list1->elements[list1->length], &list2->elements[0],
579 list2->length * sizeof(ListCell));
580 list1->length = new_len;
581
583 return list1;
584}

References Assert, check_list_invariants, enlarge_list(), fb(), list_copy(), and NIL.

Referenced by accumulate_append_subpath(), add_predicate_to_index_quals(), addRangeTableEntryForJoin(), addRangeTableEntryForTableFunc(), ATParseTransformCmd(), ATPostAlterTypeParse(), AtSubCommit_Notify(), build_joinrel_restrictlist(), build_paths_for_OR(), calculate_partition_bound_for_merge(), check_index_predicates(), choose_bitmap_and(), clean_up_removed_plan_level(), CombineRangeTables(), consider_groupingsets_paths(), ConstraintImpliedByRelConstraint(), cost_index(), create_agg_clause_infos(), create_append_path(), create_append_plan(), create_bitmap_subplan(), create_index_paths(), create_join_plan(), deconstruct_distribute(), deconstruct_recurse(), DefineRelation(), deparseDirectDeleteSql(), deparseDirectUpdateSql(), deparseFromExprForRel(), ec_add_derived_clauses(), estimate_multivariate_bucketsize(), estimate_path_cost_size(), expand_groupingset_node(), ExpandAllTables(), expandRTE(), extract_or_clause(), extract_rollup_sets(), fileBeginForeignScan(), fileGetOptions(), find_indexpath_quals(), find_mergeclauses_for_outer_pathkeys(), fireRIRrules(), flatten_grouping_sets(), foreign_grouping_ok(), foreign_join_ok(), gen_partprune_steps_internal(), gen_prune_steps_from_opexps(), generate_bitmap_or_paths(), generate_join_implied_equalities(), generate_join_implied_equalities_for_ecs(), generate_join_implied_equalities_normal(), generate_partition_qual(), get_baserel_parampathinfo(), get_batch_size_option(), get_foreign_key_join_selectivity(), get_from_clause_item(), get_index_paths(), get_join_index_paths(), get_joinrel_parampathinfo(), get_relation_constraints(), get_rels_with_domain(), get_steps_using_prefix_recurse(), GetAllSchemaPublicationRelations(), GetPubPartitionOptionRelations(), is_parallel_safe(), objectsInSchemaToOids(), optimize_window_clauses(), paraminfo_get_equal_hashops(), PrepareForIncrementalBackup(), process_equivalence(), process_sublinks_mutator(), ProcessUtilitySlow(), pull_ands(), pull_ors(), pull_up_simple_subquery(), reduce_unique_semijoins(), remove_self_join_rel(), remove_self_joins_one_group(), remove_useless_results_recurse(), reorder_grouping_sets(), RewriteQuery(), rewriteRuleAction(), rewriteTargetListIU(), selectColorTrigrams(), set_joinrel_partition_key_exprs(), set_plan_refs(), split_pathtarget_at_srfs_extended(), split_pathtarget_walker(), subquery_planner(), TidQualFromRestrictInfoList(), transformAExprIn(), transformAlterTableStmt(), transformCreateSchemaStmtElements(), transformCreateStmt(), transformExpressionList(), transformFromClause(), transformFromClauseItem(), transformIndexConstraints(), transformTableLikeClause(), transformTargetList(), TS_execute_locations_recurse(), and vacuum().

◆ list_concat_copy()

List * list_concat_copy ( const List list1,
const List list2 
)

◆ list_concat_unique()

List * list_concat_unique ( List list1,
const List list2 
)

Definition at line 1405 of file list.c.

1406{
1407 ListCell *cell;
1408
1411
1412 foreach(cell, list2)
1413 {
1414 if (!list_member(list1, lfirst(cell)))
1415 list1 = lappend(list1, lfirst(cell));
1416 }
1417
1419 return list1;
1420}

References Assert, check_list_invariants, fb(), IsPointerList, lappend(), lfirst, and list_member().

Referenced by create_bitmap_subplan(), and select_active_windows().

◆ list_concat_unique_int()

List * list_concat_unique_int ( List list1,
const List list2 
)

Definition at line 1448 of file list.c.

1449{
1450 ListCell *cell;
1451
1454
1455 foreach(cell, list2)
1456 {
1457 if (!list_member_int(list1, lfirst_int(cell)))
1459 }
1460
1462 return list1;
1463}

References Assert, check_list_invariants, fb(), IsIntegerList, lappend_int(), lfirst_int, and list_member_int().

◆ list_concat_unique_oid()

List * list_concat_unique_oid ( List list1,
const List list2 
)

Definition at line 1469 of file list.c.

1470{
1471 ListCell *cell;
1472
1475
1476 foreach(cell, list2)
1477 {
1478 if (!list_member_oid(list1, lfirst_oid(cell)))
1480 }
1481
1483 return list1;
1484}

References Assert, check_list_invariants, fb(), IsOidList, lappend_oid(), lfirst_oid, and list_member_oid().

Referenced by AlterPublicationOptions(), GetSchemaPublicationRelations(), InvalidatePubRelSyncCache(), pg_get_publication_tables(), and RelationBuildPublicationDesc().

◆ list_concat_unique_ptr()

List * list_concat_unique_ptr ( List list1,
const List list2 
)

Definition at line 1427 of file list.c.

1428{
1429 ListCell *cell;
1430
1433
1434 foreach(cell, list2)
1435 {
1436 if (!list_member_ptr(list1, lfirst(cell)))
1437 list1 = lappend(list1, lfirst(cell));
1438 }
1439
1441 return list1;
1442}

References Assert, check_list_invariants, fb(), IsPointerList, lappend(), lfirst, and list_member_ptr().

Referenced by get_useful_pathkeys_for_distinct(), and group_keys_reorder_by_pathkeys().

◆ list_copy()

List * list_copy ( const List oldlist)

Definition at line 1573 of file list.c.

1574{
1575 List *newlist;
1576
1577 if (oldlist == NIL)
1578 return NIL;
1579
1580 newlist = new_list(oldlist->type, oldlist->length);
1581 memcpy(newlist->elements, oldlist->elements,
1582 newlist->length * sizeof(ListCell));
1583
1585 return newlist;
1586}

References check_list_invariants, fb(), new_list(), and NIL.

Referenced by addRangeTableEntryForCTE(), adjust_group_pathkeys_for_groupagg(), arrayconst_startup_fn(), arrayexpr_startup_fn(), build_subplan(), check_index_predicates(), check_publications(), consider_groupingsets_paths(), ConstraintImpliedByRelConstraint(), copy_pathtarget(), copyObjectImpl(), CopySearchPathMatcher(), create_nestloop_plan(), estimate_multivariate_bucketsize(), EventTriggerCollectGrant(), ExecuteTruncateGuts(), expression_tree_mutator_impl(), fetch_search_path(), foreign_join_ok(), generate_bitmap_or_paths(), generate_mergejoin_paths(), generateSerialExtraStmts(), get_eclass_for_sort_expr(), get_foreign_key_join_selectivity(), get_query_def(), get_required_extension(), get_steps_using_prefix_recurse(), get_switched_clauses(), get_useful_pathkeys_for_relation(), GetSearchPathMatcher(), heap_truncate_find_FKs(), list_concat(), list_concat_copy(), list_difference(), list_difference_int(), list_difference_oid(), list_difference_ptr(), list_union(), list_union_int(), list_union_oid(), list_union_ptr(), merge_publications(), plpgsql_parse_cwordtype(), preprocess_groupclause(), recomputeNamespacePath(), RelationGetIndexList(), RelationGetStatExtList(), remove_leftjoinrel_from_query(), remove_self_join_rel(), reorder_grouping_sets(), roles_is_member_of(), select_active_windows(), select_outer_pathkeys_for_merge(), set_joinrel_partition_key_exprs(), set_using_names(), SetReindexPending(), simplify_and_arguments(), simplify_or_arguments(), sort_inner_and_outer(), standard_qp_callback(), transformPLAssignStmt(), transformWithClause(), and WalSummariesAreComplete().

◆ list_copy_deep()

List * list_copy_deep ( const List oldlist)

Definition at line 1639 of file list.c.

1640{
1641 List *newlist;
1642
1643 if (oldlist == NIL)
1644 return NIL;
1645
1646 /* This is only sensible for pointer Lists */
1648
1649 newlist = new_list(oldlist->type, oldlist->length);
1650 for (int i = 0; i < newlist->length; i++)
1651 lfirst(&newlist->elements[i]) =
1652 copyObjectImpl(lfirst(&oldlist->elements[i]));
1653
1655 return newlist;
1656}

References Assert, check_list_invariants, copyObjectImpl(), fb(), i, IsA, lfirst, new_list(), and NIL.

Referenced by copyObjectImpl().

◆ list_copy_head()

◆ list_copy_tail()

List * list_copy_tail ( const List oldlist,
int  nskip 
)

Definition at line 1613 of file list.c.

1614{
1615 List *newlist;
1616
1617 if (nskip < 0)
1618 nskip = 0; /* would it be better to elog? */
1619
1620 if (oldlist == NIL || nskip >= oldlist->length)
1621 return NIL;
1622
1623 newlist = new_list(oldlist->type, oldlist->length - nskip);
1624 memcpy(newlist->elements, &oldlist->elements[nskip],
1625 newlist->length * sizeof(ListCell));
1626
1628 return newlist;
1629}

References check_list_invariants, fb(), new_list(), and NIL.

Referenced by accumulate_append_subpath(), addRangeTableEntryForJoin(), addRangeTableEntryForTableFunc(), does_not_exist_skipping(), expandRTE(), get_name_for_var_field(), get_object_address_opcf(), ParseFuncOrColumn(), push_ancestor_plan(), and transformAggregateCall().

◆ list_deduplicate_oid()

void list_deduplicate_oid ( List list)

Definition at line 1495 of file list.c.

1496{
1497 int len;
1498
1499 Assert(IsOidList(list));
1500 len = list_length(list);
1501 if (len > 1)
1502 {
1503 ListCell *elements = list->elements;
1504 int i = 0;
1505
1506 for (int j = 1; j < len; j++)
1507 {
1508 if (elements[i].oid_value != elements[j].oid_value)
1509 elements[++i].oid_value = elements[j].oid_value;
1510 }
1511 list->length = i + 1;
1512 }
1514}

References Assert, check_list_invariants, i, IsOidList, j, len, list_length(), and ListCell::oid_value.

Referenced by GetPublicationRelations(), and heap_truncate_find_FKs().

◆ list_delete()

List * list_delete ( List list,
void datum 
)

Definition at line 853 of file list.c.

854{
855 ListCell *cell;
856
857 Assert(IsPointerList(list));
859
860 foreach(cell, list)
861 {
862 if (equal(lfirst(cell), datum))
863 return list_delete_cell(list, cell);
864 }
865
866 /* Didn't find a match: return the list unmodified */
867 return list;
868}

References Assert, check_list_invariants, equal(), IsPointerList, lfirst, and list_delete_cell().

Referenced by check_publications(), generate_bitmap_or_paths(), injection_points_detach(), postgresGetForeignPlan(), and unregister_ENR().

◆ list_delete_cell()

List * list_delete_cell ( List list,
ListCell cell 
)

◆ list_delete_first()

◆ list_delete_first_n()

List * list_delete_first_n ( List list,
int  n 
)

Definition at line 983 of file list.c.

984{
986
987 /* No-op request? */
988 if (n <= 0)
989 return list;
990
991 /* Delete whole list? */
992 if (n >= list_length(list))
993 {
994 list_free(list);
995 return NIL;
996 }
997
998 /*
999 * Otherwise, we normally just collapse out the removed elements. But for
1000 * debugging purposes, move the whole list contents someplace else.
1001 *
1002 * (Note that we *must* keep the contents in the same memory context.)
1003 */
1004#ifndef DEBUG_LIST_MEMORY_USAGE
1005 memmove(&list->elements[0], &list->elements[n],
1006 (list->length - n) * sizeof(ListCell));
1007 list->length -= n;
1008#else
1009 {
1011 int newmaxlen = list->length - n;
1012
1013 newelems = (ListCell *)
1015 newmaxlen * sizeof(ListCell));
1016 memcpy(newelems, &list->elements[n], newmaxlen * sizeof(ListCell));
1017 if (list->elements != list->initial_elements)
1018 pfree(list->elements);
1019 else
1020 {
1021 /*
1022 * As in enlarge_list(), clear the initial_elements[] space and/or
1023 * mark it inaccessible.
1024 */
1025#ifdef CLOBBER_FREED_MEMORY
1026 wipe_mem(list->initial_elements,
1027 list->max_length * sizeof(ListCell));
1028#else
1029 VALGRIND_MAKE_MEM_NOACCESS(list->initial_elements,
1030 list->max_length * sizeof(ListCell));
1031#endif
1032 }
1033 list->elements = newelems;
1034 list->max_length = newmaxlen;
1035 list->length = newmaxlen;
1037 }
1038#endif
1039
1040 return list;
1041}

References check_list_invariants, fb(), GetMemoryChunkContext(), list_free(), list_length(), MemoryContextAlloc(), NIL, pfree(), and VALGRIND_MAKE_MEM_NOACCESS.

Referenced by add_function_defaults(), func_get_detail(), and SyncPostCheckpoint().

◆ list_delete_int()

List * list_delete_int ( List list,
int  datum 
)

Definition at line 891 of file list.c.

892{
893 ListCell *cell;
894
895 Assert(IsIntegerList(list));
897
898 foreach(cell, list)
899 {
900 if (lfirst_int(cell) == datum)
901 return list_delete_cell(list, cell);
902 }
903
904 /* Didn't find a match: return the list unmodified */
905 return list;
906}

References Assert, check_list_invariants, IsIntegerList, lfirst_int, and list_delete_cell().

Referenced by reorder_grouping_sets().

◆ list_delete_last()

List * list_delete_last ( List list)

Definition at line 957 of file list.c.

958{
960
961 if (list == NIL)
962 return NIL; /* would an error be better? */
963
964 /* list_truncate won't free list if it goes to empty, but this should */
965 if (list_length(list) <= 1)
966 {
967 list_free(list);
968 return NIL;
969 }
970
971 return list_truncate(list, list_length(list) - 1);
972}

References check_list_invariants, list_free(), list_length(), list_truncate(), and NIL.

Referenced by agg_refill_hash_table(), CheckAttributeType(), create_unique_paths(), fireRIRrules(), inline_function(), LockViewRecurse(), plpgsql_parse_cwordtype(), relation_is_updatable(), RewriteQuery(), transformMultiAssignRef(), and transformOnConflictClause().

◆ list_delete_nth_cell()

List * list_delete_nth_cell ( List list,
int  n 
)

Definition at line 767 of file list.c.

768{
770
771 Assert(n >= 0 && n < list->length);
772
773 /*
774 * If we're about to delete the last node from the list, free the whole
775 * list instead and return NIL, which is the only valid representation of
776 * a zero-length list.
777 */
778 if (list->length == 1)
779 {
780 list_free(list);
781 return NIL;
782 }
783
784 /*
785 * Otherwise, we normally just collapse out the removed element. But for
786 * debugging purposes, move the whole list contents someplace else.
787 *
788 * (Note that we *must* keep the contents in the same memory context.)
789 */
790#ifndef DEBUG_LIST_MEMORY_USAGE
791 memmove(&list->elements[n], &list->elements[n + 1],
792 (list->length - 1 - n) * sizeof(ListCell));
793 list->length--;
794#else
795 {
797 int newmaxlen = list->length - 1;
798
799 newelems = (ListCell *)
801 newmaxlen * sizeof(ListCell));
802 memcpy(newelems, list->elements, n * sizeof(ListCell));
803 memcpy(&newelems[n], &list->elements[n + 1],
804 (list->length - 1 - n) * sizeof(ListCell));
805 if (list->elements != list->initial_elements)
806 pfree(list->elements);
807 else
808 {
809 /*
810 * As in enlarge_list(), clear the initial_elements[] space and/or
811 * mark it inaccessible.
812 */
813#ifdef CLOBBER_FREED_MEMORY
814 wipe_mem(list->initial_elements,
815 list->max_length * sizeof(ListCell));
816#else
817 VALGRIND_MAKE_MEM_NOACCESS(list->initial_elements,
818 list->max_length * sizeof(ListCell));
819#endif
820 }
821 list->elements = newelems;
822 list->max_length = newmaxlen;
823 list->length--;
825 }
826#endif
827
828 return list;
829}

References Assert, check_list_invariants, fb(), GetMemoryChunkContext(), list_free(), MemoryContextAlloc(), NIL, pfree(), and VALGRIND_MAKE_MEM_NOACCESS.

Referenced by AddRelationNotNullConstraints(), list_delete_cell(), list_delete_first(), MergeAttributes(), process_equivalence(), reconsider_full_join_clause(), and sort_inner_and_outer().

◆ list_delete_oid()

List * list_delete_oid ( List list,
Oid  datum 
)

Definition at line 910 of file list.c.

911{
912 ListCell *cell;
913
914 Assert(IsOidList(list));
916
917 foreach(cell, list)
918 {
919 if (lfirst_oid(cell) == datum)
920 return list_delete_cell(list, cell);
921 }
922
923 /* Didn't find a match: return the list unmodified */
924 return list;
925}

References Assert, check_list_invariants, IsOidList, lfirst_oid, and list_delete_cell().

Referenced by RemoveReindexPending().

◆ list_delete_ptr()

List * list_delete_ptr ( List list,
void datum 
)

Definition at line 872 of file list.c.

873{
874 ListCell *cell;
875
876 Assert(IsPointerList(list));
878
879 foreach(cell, list)
880 {
881 if (lfirst(cell) == datum)
882 return list_delete_cell(list, cell);
883 }
884
885 /* Didn't find a match: return the list unmodified */
886 return list;
887}

References Assert, check_list_invariants, IsPointerList, lfirst, and list_delete_cell().

Referenced by FreeExprContext(), pa_free_worker_info(), remove_join_clause_from_rels(), and remove_self_join_rel().

◆ list_difference()

List * list_difference ( const List list1,
const List list2 
)

Definition at line 1237 of file list.c.

1238{
1239 const ListCell *cell;
1240 List *result = NIL;
1241
1244
1245 if (list2 == NIL)
1246 return list_copy(list1);
1247
1248 foreach(cell, list1)
1249 {
1250 if (!list_member(list2, lfirst(cell)))
1251 result = lappend(result, lfirst(cell));
1252 }
1253
1254 check_list_invariants(result);
1255 return result;
1256}

References Assert, check_list_invariants, fb(), IsPointerList, lappend(), lfirst, list_copy(), list_member(), and NIL.

Referenced by create_hashjoin_plan(), create_mergejoin_plan(), create_tidscan_plan(), get_useful_group_keys_orderings(), infer_arbiter_indexes(), IsIndexCompatibleAsArbiter(), and process_duplicate_ors().

◆ list_difference_int()

List * list_difference_int ( const List list1,
const List list2 
)

Definition at line 1288 of file list.c.

1289{
1290 const ListCell *cell;
1291 List *result = NIL;
1292
1295
1296 if (list2 == NIL)
1297 return list_copy(list1);
1298
1299 foreach(cell, list1)
1300 {
1301 if (!list_member_int(list2, lfirst_int(cell)))
1302 result = lappend_int(result, lfirst_int(cell));
1303 }
1304
1305 check_list_invariants(result);
1306 return result;
1307}

References Assert, check_list_invariants, fb(), IsIntegerList, lappend_int(), lfirst_int, list_copy(), list_member_int(), and NIL.

Referenced by reorder_grouping_sets().

◆ list_difference_oid()

List * list_difference_oid ( const List list1,
const List list2 
)

Definition at line 1313 of file list.c.

1314{
1315 const ListCell *cell;
1316 List *result = NIL;
1317
1320
1321 if (list2 == NIL)
1322 return list_copy(list1);
1323
1324 foreach(cell, list1)
1325 {
1326 if (!list_member_oid(list2, lfirst_oid(cell)))
1327 result = lappend_oid(result, lfirst_oid(cell));
1328 }
1329
1330 check_list_invariants(result);
1331 return result;
1332}

References Assert, check_list_invariants, fb(), IsOidList, lappend_oid(), lfirst_oid, list_copy(), list_member_oid(), and NIL.

Referenced by AlterPublicationSchemas().

◆ list_difference_ptr()

List * list_difference_ptr ( const List list1,
const List list2 
)

Definition at line 1263 of file list.c.

1264{
1265 const ListCell *cell;
1266 List *result = NIL;
1267
1270
1271 if (list2 == NIL)
1272 return list_copy(list1);
1273
1274 foreach(cell, list1)
1275 {
1276 if (!list_member_ptr(list2, lfirst(cell)))
1277 result = lappend(result, lfirst(cell));
1278 }
1279
1280 check_list_invariants(result);
1281 return result;
1282}

References Assert, check_list_invariants, fb(), IsPointerList, lappend(), lfirst, list_copy(), list_member_ptr(), and NIL.

Referenced by create_bitmap_scan_plan(), ExecuteTruncateGuts(), and get_useful_group_keys_orderings().

◆ list_free()

void list_free ( List list)

Definition at line 1546 of file list.c.

1547{
1548 list_free_private(list, false);
1549}

References list_free_private().

Referenced by AfterTriggerSetState(), AlterIndexNamespaces(), arrayconst_cleanup_fn(), arrayexpr_cleanup_fn(), ATCheckPartitionsNotInUse(), ATExecChangeOwner(), ATExecMergePartitions(), ATExecSetTableSpace(), build_base_rel_tlists(), build_remote_returning(), BuildRelationExtStatistics(), cachedNamespacePath(), calc_joinrel_size_estimate(), calculate_indexes_size(), calculate_partition_bound_for_merge(), calculate_toast_table_size(), check_createrole_self_grant(), check_datestyle(), check_debug_io_direct(), check_log_connections(), check_log_destination(), check_restrict_nonsystem_relation_kind(), check_search_path(), check_synchronized_standby_slots(), check_temp_tablespaces(), check_wal_consistency_checking(), choose_bitmap_and(), compute_semi_anti_join_factors(), CopyFrom(), CopyMultiInsertBufferFlush(), CopyMultiInsertInfoCleanup(), create_agg_clause_infos(), CreateExtensionInternal(), CreateTriggerFiringOn(), current_schema(), current_schemas(), DefineIndex(), DefineRelation(), deparseFromExprForRel(), dependencies_object_end(), distribute_qual_to_rels(), do_analyze_rel(), do_autovacuum(), DropSubscription(), ec_clear_derived_clauses(), EndCopy(), estimate_multivariate_bucketsize(), EventTriggerDDLCommandEnd(), EventTriggerDDLCommandStart(), EventTriggerOnLogin(), EventTriggerSQLDrop(), EventTriggerTableRewrite(), ExecInitPartitionInfo(), ExecInsert(), ExecOpenIndices(), ExecPendingInserts(), ExecResetTupleTable(), ExecSimpleRelationInsert(), ExecSimpleRelationUpdate(), ExecUpdateEpilogue(), expandTableLikeClause(), extract_lateral_references(), extract_lateral_vars_from_PHVs(), ExtractExtensionList(), find_all_inheritors(), find_compatible_agg(), find_computable_ec_member(), find_hash_columns(), find_placeholders_in_expr(), fix_placeholder_input_needed_levels(), generate_base_implied_equalities_no_const(), generate_bitmap_or_paths(), generate_partitionwise_join_paths(), get_rel_sync_entry(), get_relation_info(), get_relation_statistics(), get_steps_using_prefix_recurse(), get_windowclause_startup_tuples(), getIdentitySequence(), GetTopMostAncestorInPublication(), group_keys_reorder_by_pathkeys(), heap_truncate_find_FKs(), index_concurrently_swap(), index_get_partition(), index_unchanged_by_update(), infer_arbiter_indexes(), is_var_in_aggref_only(), list_delete_first_n(), list_delete_last(), list_delete_nth_cell(), llvm_release_context(), logicalrep_worker_detach(), make_group_input_target(), make_partial_grouping_target(), make_SAOP_expr(), make_sort_input_target(), make_window_input_target(), match_orclause_to_indexcol(), max_parallel_hazard_walker(), merge_list_bounds(), merge_range_bounds(), ndistinct_object_end(), ObjectsInPublicationToOids(), OpenTableList(), paraminfo_get_equal_hashops(), parse_hba_auth_opt(), pg_dependencies_in(), pg_ndistinct_in(), pg_partition_root(), plpgsql_extra_checks_check_hook(), pop_ancestor_plan(), PostmasterMain(), PrepareTempTablespaces(), preprocess_targetlist(), preprocessNamespacePath(), process_implied_equality(), ProcessGUCArray(), processState(), ProcessUtilitySlow(), PutMemoryContextsStatsTupleStore(), qual_is_pushdown_safe(), rebuild_eclass_attr_needed(), rebuild_joinclause_attr_needed(), rebuild_placeholder_attr_needed(), recomputeNamespacePath(), refresh_by_match_merge(), RefreshMatViewByOid(), RelationCacheInvalidate(), RelationDestroyRelation(), RelationGetIndexAttrBitmap(), RelationGetIndexList(), RelationGetPrimaryKeyIndex(), RelationGetReplicaIndex(), RelationGetStatExtList(), relationHasPrimaryKey(), remove_dbtablespaces(), remove_self_join_rel(), reorder_grouping_sets(), reparameterize_pathlist_by_child(), roles_is_member_of(), sepgsql_dml_privileges(), simplify_and_arguments(), simplify_or_arguments(), statext_mcv_clauselist_selectivity(), stringToQualifiedNameList(), test_bms_overlap_list(), textToQualifiedNameList(), toast_open_indexes(), transformFkeyCheckAttrs(), transformFkeyGetPrimaryKey(), transformValuesClause(), triggered_change_notification(), typeInheritsFrom(), update_eclasses(), vac_open_indexes(), and WaitForLockers().

◆ list_free_deep()

◆ list_free_private()

static void list_free_private ( List list,
bool  deep 
)
static

Definition at line 1520 of file list.c.

1521{
1522 if (list == NIL)
1523 return; /* nothing to do */
1524
1526
1527 if (deep)
1528 {
1529 for (int i = 0; i < list->length; i++)
1530 pfree(lfirst(&list->elements[i]));
1531 }
1532 if (list->elements != list->initial_elements)
1533 pfree(list->elements);
1534 pfree(list);
1535}

References check_list_invariants, fb(), i, lfirst, NIL, and pfree().

Referenced by list_free(), and list_free_deep().

◆ list_insert_nth()

List * list_insert_nth ( List list,
int  pos,
void datum 
)

Definition at line 439 of file list.c.

440{
441 if (list == NIL)
442 {
443 Assert(pos == 0);
444 return list_make1(datum);
445 }
446 Assert(IsPointerList(list));
447 lfirst(insert_new_cell(list, pos)) = datum;
449 return list;
450}

References Assert, check_list_invariants, insert_new_cell(), IsPointerList, lfirst, list_make1, and NIL.

Referenced by add_partial_path(), add_path(), and merge_clump().

◆ list_insert_nth_int()

List * list_insert_nth_int ( List list,
int  pos,
int  datum 
)

Definition at line 453 of file list.c.

454{
455 if (list == NIL)
456 {
457 Assert(pos == 0);
458 return list_make1_int(datum);
459 }
460 Assert(IsIntegerList(list));
461 lfirst_int(insert_new_cell(list, pos)) = datum;
463 return list;
464}

References Assert, check_list_invariants, insert_new_cell(), IsIntegerList, lfirst_int, list_make1_int, and NIL.

◆ list_insert_nth_oid()

List * list_insert_nth_oid ( List list,
int  pos,
Oid  datum 
)

Definition at line 467 of file list.c.

468{
469 if (list == NIL)
470 {
471 Assert(pos == 0);
472 return list_make1_oid(datum);
473 }
474 Assert(IsOidList(list));
475 lfirst_oid(insert_new_cell(list, pos)) = datum;
477 return list;
478}

References Assert, check_list_invariants, insert_new_cell(), IsOidList, lfirst_oid, list_make1_oid, and NIL.

◆ list_int_cmp()

int list_int_cmp ( const ListCell p1,
const ListCell p2 
)

Definition at line 1691 of file list.c.

1692{
1693 int v1 = lfirst_int(p1);
1694 int v2 = lfirst_int(p2);
1695
1696 return pg_cmp_s32(v1, v2);
1697}

References fb(), lfirst_int, and pg_cmp_s32().

Referenced by expand_grouping_sets().

◆ list_intersection()

List * list_intersection ( const List list1,
const List list2 
)

Definition at line 1174 of file list.c.

1175{
1176 List *result;
1177 const ListCell *cell;
1178
1179 if (list1 == NIL || list2 == NIL)
1180 return NIL;
1181
1184
1185 result = NIL;
1186 foreach(cell, list1)
1187 {
1188 if (list_member(list2, lfirst(cell)))
1189 result = lappend(result, lfirst(cell));
1190 }
1191
1192 check_list_invariants(result);
1193 return result;
1194}

References Assert, check_list_invariants, fb(), IsPointerList, lappend(), lfirst, list_member(), and NIL.

◆ list_intersection_int()

List * list_intersection_int ( const List list1,
const List list2 
)

Definition at line 1200 of file list.c.

1201{
1202 List *result;
1203 const ListCell *cell;
1204
1205 if (list1 == NIL || list2 == NIL)
1206 return NIL;
1207
1210
1211 result = NIL;
1212 foreach(cell, list1)
1213 {
1214 if (list_member_int(list2, lfirst_int(cell)))
1215 result = lappend_int(result, lfirst_int(cell));
1216 }
1217
1218 check_list_invariants(result);
1219 return result;
1220}

References Assert, check_list_invariants, fb(), IsIntegerList, lappend_int(), lfirst_int, list_member_int(), and NIL.

Referenced by parseCheckAggregates().

◆ list_make1_impl()

List * list_make1_impl ( NodeTag  t,
ListCell  datum1 
)

Definition at line 236 of file list.c.

237{
238 List *list = new_list(t, 1);
239
240 list->elements[0] = datum1;
242 return list;
243}

References check_list_invariants, and new_list().

◆ list_make2_impl()

List * list_make2_impl ( NodeTag  t,
ListCell  datum1,
ListCell  datum2 
)

Definition at line 246 of file list.c.

247{
248 List *list = new_list(t, 2);
249
250 list->elements[0] = datum1;
251 list->elements[1] = datum2;
253 return list;
254}

References check_list_invariants, fb(), and new_list().

◆ list_make3_impl()

List * list_make3_impl ( NodeTag  t,
ListCell  datum1,
ListCell  datum2,
ListCell  datum3 
)

Definition at line 257 of file list.c.

259{
260 List *list = new_list(t, 3);
261
262 list->elements[0] = datum1;
263 list->elements[1] = datum2;
264 list->elements[2] = datum3;
266 return list;
267}

References check_list_invariants, fb(), and new_list().

◆ list_make4_impl()

List * list_make4_impl ( NodeTag  t,
ListCell  datum1,
ListCell  datum2,
ListCell  datum3,
ListCell  datum4 
)

Definition at line 270 of file list.c.

272{
273 List *list = new_list(t, 4);
274
275 list->elements[0] = datum1;
276 list->elements[1] = datum2;
277 list->elements[2] = datum3;
278 list->elements[3] = datum4;
280 return list;
281}

References check_list_invariants, fb(), and new_list().

◆ list_make5_impl()

List * list_make5_impl ( NodeTag  t,
ListCell  datum1,
ListCell  datum2,
ListCell  datum3,
ListCell  datum4,
ListCell  datum5 
)

Definition at line 284 of file list.c.

286{
287 List *list = new_list(t, 5);
288
289 list->elements[0] = datum1;
290 list->elements[1] = datum2;
291 list->elements[2] = datum3;
292 list->elements[3] = datum4;
293 list->elements[4] = datum5;
295 return list;
296}

References check_list_invariants, fb(), and new_list().

◆ list_member()

◆ list_member_int()

◆ list_member_oid()

bool list_member_oid ( const List list,
Oid  datum 
)

Definition at line 722 of file list.c.

723{
724 const ListCell *cell;
725
726 Assert(IsOidList(list));
728
729 foreach(cell, list)
730 {
731 if (lfirst_oid(cell) == datum)
732 return true;
733 }
734
735 return false;
736}

References Assert, check_list_invariants, IsOidList, and lfirst_oid.

Referenced by AfterTriggerSaveEvent(), AlterTableMoveAll(), apply_handle_truncate(), ATExecAddInherit(), ATExecAttachPartition(), ATExecMergePartitions(), BeginCopyTo(), CheckAndReportConflict(), CheckAttributeType(), CloneFkReferenced(), CloneFkReferencing(), CollationIsVisibleExt(), ConversionIsVisibleExt(), DefineRelation(), DetachPartitionFinalize(), ec_member_matches_indexcol(), ExecAlterObjectDependsStmt(), ExecCheckIndexConstraints(), ExecInitPartitionInfo(), ExecInsertIndexTuples(), ExecuteTruncate(), exprs_known_equal(), finalNamespacePath(), fireRIRrules(), FunctionIsVisibleExt(), get_rel_sync_entry(), get_transform_fromsql(), get_transform_tosql(), GetTopMostAncestorInPublication(), has_privs_of_role(), hashvalidate(), have_partkey_equi_join(), heap_truncate_check_FKs(), heap_truncate_find_FKs(), inline_function(), is_member_of_role(), is_member_of_role_nosuper(), list_append_unique_oid(), list_concat_unique_oid(), list_difference_oid(), list_union_oid(), LockViewRecurse_walker(), lookup_shippable(), member_can_set_role(), OpclassIsVisibleExt(), OpenTableList(), OperatorIsVisibleExt(), OpfamilyIsVisibleExt(), PlanCacheRelCallback(), ReindexIsProcessingIndex(), relation_has_unique_index_for(), relation_is_updatable(), RelationIsVisibleExt(), RememberConstraintForRebuilding(), RememberIndexForRebuilding(), RememberStatisticsForRebuilding(), roles_list_append(), StatisticsObjIsVisibleExt(), TSConfigIsVisibleExt(), TSDictionaryIsVisibleExt(), TSParserIsVisibleExt(), TSTemplateIsVisibleExt(), typeInheritsFrom(), and TypeIsVisibleExt().

◆ list_member_ptr()

◆ list_member_xid()

bool list_member_xid ( const List list,
TransactionId  datum 
)

Definition at line 742 of file list.c.

743{
744 const ListCell *cell;
745
746 Assert(IsXidList(list));
748
749 foreach(cell, list)
750 {
751 if (lfirst_xid(cell) == datum)
752 return true;
753 }
754
755 return false;
756}

References Assert, check_list_invariants, IsXidList, and lfirst_xid.

Referenced by get_schema_sent_in_streamed_txn(), and pa_start_subtrans().

◆ list_oid_cmp()

int list_oid_cmp ( const ListCell p1,
const ListCell p2 
)

Definition at line 1703 of file list.c.

1704{
1705 Oid v1 = lfirst_oid(p1);
1706 Oid v2 = lfirst_oid(p2);
1707
1708 return pg_cmp_u32(v1, v2);
1709}

References fb(), lfirst_oid, and pg_cmp_u32().

Referenced by GetPublicationRelations(), heap_truncate_find_FKs(), RelationGetIndexList(), and RelationGetStatExtList().

◆ list_sort()

void list_sort ( List list,
list_sort_comparator  cmp 
)

Definition at line 1674 of file list.c.

1675{
1676 typedef int (*qsort_comparator) (const void *a, const void *b);
1677 int len;
1678
1680
1681 /* Nothing to do if there's less than two elements */
1682 len = list_length(list);
1683 if (len > 1)
1684 qsort(list->elements, len, sizeof(ListCell), (qsort_comparator) cmp);
1685}

References a, b, check_list_invariants, cmp(), fb(), len, list_length(), and qsort.

Referenced by create_append_path(), expand_grouping_sets(), GetPublicationRelations(), heap_truncate_find_FKs(), perform_base_backup(), RelationGetIndexList(), RelationGetStatExtList(), sort_policies_by_name(), UpdateLogicalMappings(), and WalSummariesAreComplete().

◆ list_truncate()

List * list_truncate ( List list,
int  new_size 
)

Definition at line 631 of file list.c.

632{
633 if (new_size <= 0)
634 return NIL; /* truncate to zero length */
635
636 /* If asked to effectively extend the list, do nothing */
637 if (new_size < list_length(list))
638 list->length = new_size;
639
640 /*
641 * Note: unlike the individual-list-cell deletion functions, we don't move
642 * the list cells to new storage, even in DEBUG_LIST_MEMORY_USAGE mode.
643 * This is because none of them can move in this operation, so just like
644 * in the old cons-cell-based implementation, this function doesn't
645 * invalidate any pointers to cells of the list. This is also the reason
646 * for not wiping the memory of the deleted cells: the old code didn't
647 * free them either. Perhaps later we'll tighten this up.
648 */
649
650 return list;
651}

References fb(), list_length(), and NIL.

Referenced by choose_bitmap_and(), expand_indexqual_rowcompare(), ExpandIndirectionStar(), expandRTE(), generate_mergejoin_paths(), geqo_eval(), list_delete_last(), mbms_int_members(), pa_stream_abort(), ParseFuncOrColumn(), transformAggregateCall(), transformFromClauseItem(), transformReturningClause(), transformSetOperationStmt(), and transformWholeRowRef().

◆ list_union()

List * list_union ( const List list1,
const List list2 
)

Definition at line 1066 of file list.c.

1067{
1068 List *result;
1069 const ListCell *cell;
1070
1073
1074 result = list_copy(list1);
1075 foreach(cell, list2)
1076 {
1077 if (!list_member(result, lfirst(cell)))
1078 result = lappend(result, lfirst(cell));
1079 }
1080
1081 check_list_invariants(result);
1082 return result;
1083}

References Assert, check_list_invariants, fb(), IsPointerList, lappend(), lfirst, list_copy(), and list_member().

Referenced by AddRelationNewConstraints(), and process_duplicate_ors().

◆ list_union_int()

List * list_union_int ( const List list1,
const List list2 
)

Definition at line 1113 of file list.c.

1114{
1115 List *result;
1116 const ListCell *cell;
1117
1120
1121 result = list_copy(list1);
1122 foreach(cell, list2)
1123 {
1124 if (!list_member_int(result, lfirst_int(cell)))
1125 result = lappend_int(result, lfirst_int(cell));
1126 }
1127
1128 check_list_invariants(result);
1129 return result;
1130}

References Assert, check_list_invariants, fb(), IsIntegerList, lappend_int(), lfirst_int, list_copy(), and list_member_int().

Referenced by expand_grouping_sets().

◆ list_union_oid()

List * list_union_oid ( const List list1,
const List list2 
)

Definition at line 1136 of file list.c.

1137{
1138 List *result;
1139 const ListCell *cell;
1140
1143
1144 result = list_copy(list1);
1145 foreach(cell, list2)
1146 {
1147 if (!list_member_oid(result, lfirst_oid(cell)))
1148 result = lappend_oid(result, lfirst_oid(cell));
1149 }
1150
1151 check_list_invariants(result);
1152 return result;
1153}

References Assert, check_list_invariants, fb(), IsOidList, lappend_oid(), lfirst_oid, list_copy(), and list_member_oid().

◆ list_union_ptr()

List * list_union_ptr ( const List list1,
const List list2 
)

Definition at line 1090 of file list.c.

1091{
1092 List *result;
1093 const ListCell *cell;
1094
1097
1098 result = list_copy(list1);
1099 foreach(cell, list2)
1100 {
1101 if (!list_member_ptr(result, lfirst(cell)))
1102 result = lappend(result, lfirst(cell));
1103 }
1104
1105 check_list_invariants(result);
1106 return result;
1107}

References Assert, check_list_invariants, fb(), IsPointerList, lappend(), lfirst, list_copy(), and list_member_ptr().

◆ new_head_cell()

static void new_head_cell ( List list)
static

Definition at line 305 of file list.c.

306{
307 /* Enlarge array if necessary */
308 if (list->length >= list->max_length)
309 enlarge_list(list, list->length + 1);
310 /* Now shove the existing data over */
311 memmove(&list->elements[1], &list->elements[0],
312 list->length * sizeof(ListCell));
313 list->length++;
314}

References enlarge_list(), and fb().

Referenced by lcons(), lcons_int(), and lcons_oid().

◆ new_list()

static List * new_list ( NodeTag  type,
int  min_size 
)
static

Definition at line 91 of file list.c.

92{
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 */
127 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 newlist = (List *) palloc(offsetof(List, initial_elements) +
138 max_size * sizeof(ListCell));
139 newlist->type = type;
140 newlist->length = min_size;
141 newlist->max_length = max_size;
142 newlist->elements = newlist->initial_elements;
143
144 return newlist;
145}

References Assert, fb(), LIST_HEADER_OVERHEAD, Max, palloc(), pg_nextpower2_32(), and type.

Referenced by lappend(), lappend_int(), lappend_oid(), lappend_xid(), lcons(), lcons_int(), lcons_oid(), list_concat_copy(), list_copy(), list_copy_deep(), list_copy_head(), list_copy_tail(), list_make1_impl(), list_make2_impl(), list_make3_impl(), list_make4_impl(), list_make5_impl(), pg_parse_query(), and pg_rewrite_query().

◆ new_tail_cell()

static void new_tail_cell ( List list)
static

Definition at line 323 of file list.c.

324{
325 /* Enlarge array if necessary */
326 if (list->length >= list->max_length)
327 enlarge_list(list, list->length + 1);
328 list->length++;
329}

References enlarge_list().

Referenced by lappend(), lappend_int(), lappend_oid(), and lappend_xid().