YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/postgres/src/backend/nodes/list.c
Line
Count
Source (jump to first uncovered line)
1
/*-------------------------------------------------------------------------
2
 *
3
 * list.c
4
 *    implementation for PostgreSQL generic linked list package
5
 *
6
 *
7
 * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
8
 * Portions Copyright (c) 1994, Regents of the University of California
9
 *
10
 *
11
 * IDENTIFICATION
12
 *    src/backend/nodes/list.c
13
 *
14
 *-------------------------------------------------------------------------
15
 */
16
#include "postgres.h"
17
18
#include "nodes/pg_list.h"
19
20
21
/*
22
 * Routines to simplify writing assertions about the type of a list; a
23
 * NIL list is considered to be an empty list of any type.
24
 */
25
#define IsPointerList(l)    ((l) == NIL || IsA((l), List))
26
#define IsIntegerList(l)    ((l) == NIL || IsA((l), IntList))
27
#define IsOidList(l)      ((l) == NIL || IsA((l), OidList))
28
29
#ifdef USE_ASSERT_CHECKING
30
/*
31
 * Check that the specified List is valid (so far as we can tell).
32
 */
33
static void
34
check_list_invariants(const List *list)
35
238M
{
36
238M
  if (list == NIL)
37
8.52M
    return;
38
39
230M
  Assert(list->length > 0);
40
230M
  Assert(list->head != NULL);
41
230M
  Assert(list->tail != NULL);
42
43
230M
  Assert(list->type == T_List ||
44
230M
       list->type == T_IntList ||
45
230M
       list->type == T_OidList);
46
47
230M
  if (list->length == 1)
48
230M
    Assert(list->head == list->tail);
49
230M
  if (list->length == 2)
50
230M
    Assert(list->head->next == list->tail);
51
230M
  Assert(list->tail->next == NULL);
52
230M
}
53
#else
54
#define check_list_invariants(l)
55
#endif              /* USE_ASSERT_CHECKING */
56
57
/*
58
 * Return a freshly allocated List. Since empty non-NIL lists are
59
 * invalid, new_list() also allocates the head cell of the new list:
60
 * the caller should be sure to fill in that cell's data.
61
 */
62
static List *
63
new_list(NodeTag type)
64
58.3M
{
65
58.3M
  List     *new_list;
66
58.3M
  ListCell   *new_head;
67
68
58.3M
  new_head = (ListCell *) palloc(sizeof(*new_head));
69
58.3M
  new_head->next = NULL;
70
  /* new_head->data is left undefined! */
71
72
58.3M
  new_list = (List *) palloc(sizeof(*new_list));
73
58.3M
  new_list->type = type;
74
58.3M
  new_list->length = 1;
75
58.3M
  new_list->head = new_head;
76
58.3M
  new_list->tail = new_head;
77
78
58.3M
  return new_list;
79
58.3M
}
80
81
/*
82
 * Allocate a new cell and make it the head of the specified
83
 * list. Assumes the list it is passed is non-NIL.
84
 *
85
 * The data in the new head cell is undefined; the caller should be
86
 * sure to fill it in
87
 */
88
static void
89
new_head_cell(List *list)
90
1.28M
{
91
1.28M
  ListCell   *new_head;
92
93
1.28M
  new_head = (ListCell *) palloc(sizeof(*new_head));
94
1.28M
  new_head->next = list->head;
95
96
1.28M
  list->head = new_head;
97
1.28M
  list->length++;
98
1.28M
}
99
100
/*
101
 * Allocate a new cell and make it the tail of the specified
102
 * list. Assumes the list it is passed is non-NIL.
103
 *
104
 * The data in the new tail cell is undefined; the caller should be
105
 * sure to fill it in
106
 */
107
static void
108
new_tail_cell(List *list)
109
151M
{
110
151M
  ListCell   *new_tail;
111
112
151M
  new_tail = (ListCell *) palloc(sizeof(*new_tail));
113
151M
  new_tail->next = NULL;
114
115
151M
  list->tail->next = new_tail;
116
151M
  list->tail = new_tail;
117
151M
  list->length++;
118
151M
}
119
120
/*
121
 * Append a pointer to the list. A pointer to the modified list is
122
 * returned. Note that this function may or may not destructively
123
 * modify the list; callers should always use this function's return
124
 * value, rather than continuing to use the pointer passed as the
125
 * first argument.
126
 */
127
List *
128
lappend(List *list, void *datum)
129
180M
{
130
180M
  Assert(IsPointerList(list));
131
132
180M
  if (list == NIL)
133
32.1M
    list = new_list(T_List);
134
147M
  else
135
147M
    new_tail_cell(list);
136
137
180M
  lfirst(list->tail) = datum;
138
180M
  check_list_invariants(list);
139
180M
  return list;
140
180M
}
141
142
/*
143
 * Append an integer to the specified list. See lappend()
144
 */
145
List *
146
lappend_int(List *list, int datum)
147
2.25M
{
148
2.25M
  Assert(IsIntegerList(list));
149
150
2.25M
  if (list == NIL)
151
898k
    list = new_list(T_IntList);
152
1.35M
  else
153
1.35M
    new_tail_cell(list);
154
155
2.25M
  lfirst_int(list->tail) = datum;
156
2.25M
  check_list_invariants(list);
157
2.25M
  return list;
158
2.25M
}
159
160
/*
161
 * Append an OID to the specified list. See lappend()
162
 */
163
List *
164
lappend_oid(List *list, Oid datum)
165
3.94M
{
166
3.94M
  Assert(IsOidList(list));
167
168
3.94M
  if (list == NIL)
169
1.82M
    list = new_list(T_OidList);
170
2.11M
  else
171
2.11M
    new_tail_cell(list);
172
173
3.94M
  lfirst_oid(list->tail) = datum;
174
3.94M
  check_list_invariants(list);
175
3.94M
  return list;
176
3.94M
}
177
178
/*
179
 * Add a new cell to the list, in the position after 'prev_cell'. The
180
 * data in the cell is left undefined, and must be filled in by the
181
 * caller. 'list' is assumed to be non-NIL, and 'prev_cell' is assumed
182
 * to be non-NULL and a member of 'list'.
183
 */
184
static ListCell *
185
add_new_cell(List *list, ListCell *prev_cell)
186
34.5k
{
187
34.5k
  ListCell   *new_cell;
188
189
34.5k
  new_cell = (ListCell *) palloc(sizeof(*new_cell));
190
  /* new_cell->data is left undefined! */
191
34.5k
  new_cell->next = prev_cell->next;
192
34.5k
  prev_cell->next = new_cell;
193
194
34.5k
  if (list->tail == prev_cell)
195
32.6k
    list->tail = new_cell;
196
197
34.5k
  list->length++;
198
199
34.5k
  return new_cell;
200
34.5k
}
201
202
/*
203
 * Add a new cell to the specified list (which must be non-NIL);
204
 * it will be placed after the list cell 'prev' (which must be
205
 * non-NULL and a member of 'list'). The data placed in the new cell
206
 * is 'datum'. The newly-constructed cell is returned.
207
 */
208
ListCell *
209
lappend_cell(List *list, ListCell *prev, void *datum)
210
15.8k
{
211
15.8k
  ListCell   *new_cell;
212
213
15.8k
  Assert(IsPointerList(list));
214
215
15.8k
  new_cell = add_new_cell(list, prev);
216
15.8k
  lfirst(new_cell) = datum;
217
15.8k
  check_list_invariants(list);
218
15.8k
  return new_cell;
219
15.8k
}
220
221
ListCell *
222
lappend_cell_int(List *list, ListCell *prev, int datum)
223
0
{
224
0
  ListCell   *new_cell;
225
226
0
  Assert(IsIntegerList(list));
227
228
0
  new_cell = add_new_cell(list, prev);
229
0
  lfirst_int(new_cell) = datum;
230
0
  check_list_invariants(list);
231
0
  return new_cell;
232
0
}
233
234
ListCell *
235
lappend_cell_oid(List *list, ListCell *prev, Oid datum)
236
18.7k
{
237
18.7k
  ListCell   *new_cell;
238
239
18.7k
  Assert(IsOidList(list));
240
241
18.7k
  new_cell = add_new_cell(list, prev);
242
18.7k
  lfirst_oid(new_cell) = datum;
243
18.7k
  check_list_invariants(list);
244
18.7k
  return new_cell;
245
18.7k
}
246
247
/*
248
 * Prepend a new element to the list. A pointer to the modified list
249
 * is returned. Note that this function may or may not destructively
250
 * modify the list; callers should always use this function's return
251
 * value, rather than continuing to use the pointer passed as the
252
 * second argument.
253
 *
254
 * Caution: before Postgres 8.0, the original List was unmodified and
255
 * could be considered to retain its separate identity.  This is no longer
256
 * the case.
257
 */
258
List *
259
lcons(void *datum, List *list)
260
20.4M
{
261
20.4M
  Assert(IsPointerList(list));
262
263
20.4M
  if (list == NIL)
264
19.2M
    list = new_list(T_List);
265
1.27M
  else
266
1.27M
    new_head_cell(list);
267
268
20.4M
  lfirst(list->head) = datum;
269
20.4M
  check_list_invariants(list);
270
20.4M
  return list;
271
20.4M
}
272
273
/*
274
 * Prepend an integer to the list. See lcons()
275
 */
276
List *
277
lcons_int(int datum, List *list)
278
404k
{
279
404k
  Assert(IsIntegerList(list));
280
281
404k
  if (list == NIL)
282
397k
    list = new_list(T_IntList);
283
6.88k
  else
284
6.88k
    new_head_cell(list);
285
286
404k
  lfirst_int(list->head) = datum;
287
404k
  check_list_invariants(list);
288
404k
  return list;
289
404k
}
290
291
/*
292
 * Prepend an OID to the list. See lcons()
293
 */
294
List *
295
lcons_oid(Oid datum, List *list)
296
47.7k
{
297
47.7k
  Assert(IsOidList(list));
298
299
47.7k
  if (list == NIL)
300
41.1k
    list = new_list(T_OidList);
301
6.60k
  else
302
6.60k
    new_head_cell(list);
303
304
47.7k
  lfirst_oid(list->head) = datum;
305
47.7k
  check_list_invariants(list);
306
47.7k
  return list;
307
47.7k
}
308
309
/*
310
 * Concatenate list2 to the end of list1, and return list1. list1 is
311
 * destructively changed. Callers should be sure to use the return
312
 * value as the new pointer to the concatenated list: the 'list1'
313
 * input pointer may or may not be the same as the returned pointer.
314
 *
315
 * The nodes in list2 are merely appended to the end of list1 in-place
316
 * (i.e. they aren't copied; the two lists will share some of the same
317
 * storage). Therefore, invoking list_free() on list2 will also
318
 * invalidate a portion of list1.
319
 */
320
List *
321
list_concat(List *list1, List *list2)
322
2.27M
{
323
2.27M
  if (list1 == NIL)
324
1.65M
    return list2;
325
621k
  if (list2 == NIL)
326
489k
    return list1;
327
132k
  if (list1 == list2)
328
0
    elog(ERROR, "cannot list_concat() a list to itself");
329
330
132k
  Assert(list1->type == list2->type);
331
332
132k
  list1->length += list2->length;
333
132k
  list1->tail->next = list2->head;
334
132k
  list1->tail = list2->tail;
335
336
132k
  check_list_invariants(list1);
337
132k
  return list1;
338
132k
}
339
340
/*
341
 * Truncate 'list' to contain no more than 'new_size' elements. This
342
 * modifies the list in-place! Despite this, callers should use the
343
 * pointer returned by this function to refer to the newly truncated
344
 * list -- it may or may not be the same as the pointer that was
345
 * passed.
346
 *
347
 * Note that any cells removed by list_truncate() are NOT pfree'd.
348
 */
349
List *
350
list_truncate(List *list, int new_size)
351
21.9k
{
352
21.9k
  ListCell   *cell;
353
21.9k
  int     n;
354
355
21.9k
  if (new_size <= 0)
356
5.47k
    return NIL;        /* truncate to zero length */
357
358
  /* If asked to effectively extend the list, do nothing */
359
16.4k
  if (new_size >= list_length(list))
360
13.9k
    return list;
361
362
2.47k
  n = 1;
363
2.47k
  foreach(cell, list)
364
5.30k
  {
365
5.30k
    if (n == new_size)
366
2.47k
    {
367
2.47k
      cell->next = NULL;
368
2.47k
      list->tail = cell;
369
2.47k
      list->length = new_size;
370
2.47k
      check_list_invariants(list);
371
2.47k
      return list;
372
2.47k
    }
373
2.83k
    n++;
374
2.83k
  }
375
376
  /* keep the compiler quiet; never reached */
377
0
  Assert(false);
378
0
  return list;
379
0
}
380
381
/*
382
 * Locate the n'th cell (counting from 0) of the list.  It is an assertion
383
 * failure if there is no such cell.
384
 */
385
ListCell *
386
list_nth_cell(const List *list, int n)
387
13.3M
{
388
13.3M
  ListCell   *match;
389
390
13.3M
  Assert(list != NIL);
391
13.3M
  Assert(n >= 0);
392
13.3M
  Assert(n < list->length);
393
13.3M
  check_list_invariants(list);
394
395
  /* Does the caller actually mean to fetch the tail? */
396
13.3M
  if (n == list->length - 1)
397
6.89M
    return list->tail;
398
399
8.73M
  
for (match = list->head; 6.47M
n-- > 0;
match = match->next2.25M
)
400
2.25M
    ;
401
402
6.47M
  return match;
403
13.3M
}
404
405
/*
406
 * Return the data value contained in the n'th element of the
407
 * specified list. (List elements begin at 0.)
408
 */
409
void *
410
list_nth(const List *list, int n)
411
13.3M
{
412
13.3M
  Assert(IsPointerList(list));
413
13.3M
  return lfirst(list_nth_cell(list, n));
414
13.3M
}
415
416
/*
417
 * Return the integer value contained in the n'th element of the
418
 * specified list.
419
 */
420
int
421
list_nth_int(const List *list, int n)
422
15.2k
{
423
15.2k
  Assert(IsIntegerList(list));
424
15.2k
  return lfirst_int(list_nth_cell(list, n));
425
15.2k
}
426
427
/*
428
 * Return the OID value contained in the n'th element of the specified
429
 * list.
430
 */
431
Oid
432
list_nth_oid(const List *list, int n)
433
7.35k
{
434
7.35k
  Assert(IsOidList(list));
435
7.35k
  return lfirst_oid(list_nth_cell(list, n));
436
7.35k
}
437
438
/*
439
 * Return true iff 'datum' is a member of the list. Equality is
440
 * determined via equal(), so callers should ensure that they pass a
441
 * Node as 'datum'.
442
 */
443
bool
444
list_member(const List *list, const void *datum)
445
11.8k
{
446
11.8k
  const ListCell *cell;
447
448
11.8k
  Assert(IsPointerList(list));
449
11.8k
  check_list_invariants(list);
450
451
11.8k
  foreach(cell, list)
452
6.52k
  {
453
6.52k
    if (equal(lfirst(cell), datum))
454
2.59k
      return true;
455
6.52k
  }
456
457
9.27k
  return false;
458
11.8k
}
459
460
/*
461
 * Return true iff 'datum' is a member of the list. Equality is
462
 * determined by using simple pointer comparison.
463
 */
464
bool
465
list_member_ptr(const List *list, const void *datum)
466
417k
{
467
417k
  const ListCell *cell;
468
469
417k
  Assert(IsPointerList(list));
470
417k
  check_list_invariants(list);
471
472
417k
  foreach(cell, list)
473
308k
  {
474
308k
    if (lfirst(cell) == datum)
475
230k
      return true;
476
308k
  }
477
478
187k
  return false;
479
417k
}
480
481
/*
482
 * Return true iff the integer 'datum' is a member of the list.
483
 */
484
bool
485
list_member_int(const List *list, int datum)
486
58.8k
{
487
58.8k
  const ListCell *cell;
488
489
58.8k
  Assert(IsIntegerList(list));
490
58.8k
  check_list_invariants(list);
491
492
58.8k
  foreach(cell, list)
493
11.5k
  {
494
11.5k
    if (lfirst_int(cell) == datum)
495
5.11k
      return true;
496
11.5k
  }
497
498
53.7k
  return false;
499
58.8k
}
500
501
/*
502
 * Return true iff the OID 'datum' is a member of the list.
503
 */
504
bool
505
list_member_oid(const List *list, Oid datum)
506
3.02M
{
507
3.02M
  const ListCell *cell;
508
509
3.02M
  Assert(IsOidList(list));
510
3.02M
  check_list_invariants(list);
511
512
3.02M
  foreach(cell, list)
513
256k
  {
514
256k
    if (lfirst_oid(cell) == datum)
515
80.7k
      return true;
516
256k
  }
517
518
2.94M
  return false;
519
3.02M
}
520
521
/*
522
 * Delete 'cell' from 'list'; 'prev' is the previous element to 'cell'
523
 * in 'list', if any (i.e. prev == NULL iff list->head == cell)
524
 *
525
 * The cell is pfree'd, as is the List header if this was the last member.
526
 */
527
List *
528
list_delete_cell(List *list, ListCell *cell, ListCell *prev)
529
1.42M
{
530
1.42M
  check_list_invariants(list);
531
1.42M
  Assert(prev != NULL ? lnext(prev) == cell : list_head(list) == cell);
532
533
  /*
534
   * If we're about to delete the last node from the list, free the whole
535
   * list instead and return NIL, which is the only valid representation of
536
   * a zero-length list.
537
   */
538
1.42M
  if (list->length == 1)
539
789k
  {
540
789k
    list_free(list);
541
789k
    return NIL;
542
789k
  }
543
544
  /*
545
   * Otherwise, adjust the necessary list links, deallocate the particular
546
   * node we have just removed, and return the list we were given.
547
   */
548
635k
  list->length--;
549
550
635k
  if (prev)
551
7.10k
    prev->next = cell->next;
552
628k
  else
553
628k
    list->head = cell->next;
554
555
635k
  if (list->tail == cell)
556
5.50k
    list->tail = prev;
557
558
635k
  pfree(cell);
559
635k
  return list;
560
1.42M
}
561
562
/*
563
 * Delete the first cell in list that matches datum, if any.
564
 * Equality is determined via equal().
565
 */
566
List *
567
list_delete(List *list, void *datum)
568
0
{
569
0
  ListCell   *cell;
570
0
  ListCell   *prev;
571
572
0
  Assert(IsPointerList(list));
573
0
  check_list_invariants(list);
574
575
0
  prev = NULL;
576
0
  foreach(cell, list)
577
0
  {
578
0
    if (equal(lfirst(cell), datum))
579
0
      return list_delete_cell(list, cell, prev);
580
581
0
    prev = cell;
582
0
  }
583
584
  /* Didn't find a match: return the list unmodified */
585
0
  return list;
586
0
}
587
588
/* As above, but use simple pointer equality */
589
List *
590
list_delete_ptr(List *list, void *datum)
591
800k
{
592
800k
  ListCell   *cell;
593
800k
  ListCell   *prev;
594
595
800k
  Assert(IsPointerList(list));
596
800k
  check_list_invariants(list);
597
598
800k
  prev = NULL;
599
800k
  foreach(cell, list)
600
801k
  {
601
801k
    if (lfirst(cell) == datum)
602
799k
      return list_delete_cell(list, cell, prev);
603
604
1.69k
    prev = cell;
605
1.69k
  }
606
607
  /* Didn't find a match: return the list unmodified */
608
549
  return list;
609
800k
}
610
611
/* As above, but for integers */
612
List *
613
list_delete_int(List *list, int datum)
614
5
{
615
5
  ListCell   *cell;
616
5
  ListCell   *prev;
617
618
5
  Assert(IsIntegerList(list));
619
5
  check_list_invariants(list);
620
621
5
  prev = NULL;
622
5
  foreach(cell, list)
623
5
  {
624
5
    if (lfirst_int(cell) == datum)
625
5
      return list_delete_cell(list, cell, prev);
626
627
0
    prev = cell;
628
0
  }
629
630
  /* Didn't find a match: return the list unmodified */
631
0
  return list;
632
5
}
633
634
/* As above, but for OIDs */
635
List *
636
list_delete_oid(List *list, Oid datum)
637
17
{
638
17
  ListCell   *cell;
639
17
  ListCell   *prev;
640
641
17
  Assert(IsOidList(list));
642
17
  check_list_invariants(list);
643
644
17
  prev = NULL;
645
17
  foreach(cell, list)
646
15
  {
647
15
    if (lfirst_oid(cell) == datum)
648
15
      return list_delete_cell(list, cell, prev);
649
650
0
    prev = cell;
651
0
  }
652
653
  /* Didn't find a match: return the list unmodified */
654
2
  return list;
655
17
}
656
657
/*
658
 * Delete the first element of the list.
659
 *
660
 * This is useful to replace the Lisp-y code "list = lnext(list);" in cases
661
 * where the intent is to alter the list rather than just traverse it.
662
 * Beware that the removed cell is freed, whereas the lnext() coding leaves
663
 * the original list head intact if there's another pointer to it.
664
 */
665
List *
666
list_delete_first(List *list)
667
487k
{
668
487k
  check_list_invariants(list);
669
670
487k
  if (list == NIL)
671
0
    return NIL;       /* would an error be better? */
672
673
487k
  return list_delete_cell(list, list_head(list), NULL);
674
487k
}
675
676
/*
677
 * Generate the union of two lists. This is calculated by copying
678
 * list1 via list_copy(), then adding to it all the members of list2
679
 * that aren't already in list1.
680
 *
681
 * Whether an element is already a member of the list is determined
682
 * via equal().
683
 *
684
 * The returned list is newly-allocated, although the content of the
685
 * cells is the same (i.e. any pointed-to objects are not copied).
686
 *
687
 * NB: this function will NOT remove any duplicates that are present
688
 * in list1 (so it only performs a "union" if list1 is known unique to
689
 * start with).  Also, if you are about to write "x = list_union(x, y)"
690
 * you probably want to use list_concat_unique() instead to avoid wasting
691
 * the list cells of the old x list.
692
 *
693
 * This function could probably be implemented a lot faster if it is a
694
 * performance bottleneck.
695
 */
696
List *
697
list_union(const List *list1, const List *list2)
698
626
{
699
626
  List     *result;
700
626
  const ListCell *cell;
701
702
626
  Assert(IsPointerList(list1));
703
626
  Assert(IsPointerList(list2));
704
705
626
  result = list_copy(list1);
706
626
  foreach(cell, list2)
707
633
  {
708
633
    if (!list_member(result, lfirst(cell)))
709
632
      result = lappend(result, lfirst(cell));
710
633
  }
711
712
626
  check_list_invariants(result);
713
626
  return result;
714
626
}
715
716
/*
717
 * This variant of list_union() determines duplicates via simple
718
 * pointer comparison.
719
 */
720
List *
721
list_union_ptr(const List *list1, const List *list2)
722
0
{
723
0
  List     *result;
724
0
  const ListCell *cell;
725
726
0
  Assert(IsPointerList(list1));
727
0
  Assert(IsPointerList(list2));
728
729
0
  result = list_copy(list1);
730
0
  foreach(cell, list2)
731
0
  {
732
0
    if (!list_member_ptr(result, lfirst(cell)))
733
0
      result = lappend(result, lfirst(cell));
734
0
  }
735
736
0
  check_list_invariants(result);
737
0
  return result;
738
0
}
739
740
/*
741
 * This variant of list_union() operates upon lists of integers.
742
 */
743
List *
744
list_union_int(const List *list1, const List *list2)
745
28
{
746
28
  List     *result;
747
28
  const ListCell *cell;
748
749
28
  Assert(IsIntegerList(list1));
750
28
  Assert(IsIntegerList(list2));
751
752
28
  result = list_copy(list1);
753
28
  foreach(cell, list2)
754
18
  {
755
18
    if (!list_member_int(result, lfirst_int(cell)))
756
18
      result = lappend_int(result, lfirst_int(cell));
757
18
  }
758
759
28
  check_list_invariants(result);
760
28
  return result;
761
28
}
762
763
/*
764
 * This variant of list_union() operates upon lists of OIDs.
765
 */
766
List *
767
list_union_oid(const List *list1, const List *list2)
768
0
{
769
0
  List     *result;
770
0
  const ListCell *cell;
771
772
0
  Assert(IsOidList(list1));
773
0
  Assert(IsOidList(list2));
774
775
0
  result = list_copy(list1);
776
0
  foreach(cell, list2)
777
0
  {
778
0
    if (!list_member_oid(result, lfirst_oid(cell)))
779
0
      result = lappend_oid(result, lfirst_oid(cell));
780
0
  }
781
782
0
  check_list_invariants(result);
783
0
  return result;
784
0
}
785
786
/*
787
 * Return a list that contains all the cells that are in both list1 and
788
 * list2.  The returned list is freshly allocated via palloc(), but the
789
 * cells themselves point to the same objects as the cells of the
790
 * input lists.
791
 *
792
 * Duplicate entries in list1 will not be suppressed, so it's only a true
793
 * "intersection" if list1 is known unique beforehand.
794
 *
795
 * This variant works on lists of pointers, and determines list
796
 * membership via equal().  Note that the list1 member will be pointed
797
 * to in the result.
798
 */
799
List *
800
list_intersection(const List *list1, const List *list2)
801
4.04k
{
802
4.04k
  List     *result;
803
4.04k
  const ListCell *cell;
804
805
4.04k
  if (list1 == NIL || list2 == NIL)
806
3.81k
    return NIL;
807
808
232
  Assert(IsPointerList(list1));
809
232
  Assert(IsPointerList(list2));
810
811
232
  result = NIL;
812
232
  foreach(cell, list1)
813
255
  {
814
255
    if (list_member(list2, lfirst(cell)))
815
17
      result = lappend(result, lfirst(cell));
816
255
  }
817
818
232
  check_list_invariants(result);
819
232
  return result;
820
232
}
821
822
/*
823
 * As list_intersection but operates on lists of integers.
824
 */
825
List *
826
list_intersection_int(const List *list1, const List *list2)
827
2
{
828
2
  List     *result;
829
2
  const ListCell *cell;
830
831
2
  if (list1 == NIL || list2 == NIL)
832
0
    return NIL;
833
834
2
  Assert(IsIntegerList(list1));
835
2
  Assert(IsIntegerList(list2));
836
837
2
  result = NIL;
838
2
  foreach(cell, list1)
839
2
  {
840
2
    if (list_member_int(list2, lfirst_int(cell)))
841
0
      result = lappend_int(result, lfirst_int(cell));
842
2
  }
843
844
2
  check_list_invariants(result);
845
2
  return result;
846
2
}
847
848
/*
849
 * Return a list that contains all the cells in list1 that are not in
850
 * list2. The returned list is freshly allocated via palloc(), but the
851
 * cells themselves point to the same objects as the cells of the
852
 * input lists.
853
 *
854
 * This variant works on lists of pointers, and determines list
855
 * membership via equal()
856
 */
857
List *
858
list_difference(const List *list1, const List *list2)
859
8.86k
{
860
8.86k
  const ListCell *cell;
861
8.86k
  List     *result = NIL;
862
863
8.86k
  Assert(IsPointerList(list1));
864
8.86k
  Assert(IsPointerList(list2));
865
866
8.86k
  if (list2 == NIL)
867
7.36k
    return list_copy(list1);
868
869
1.50k
  foreach(cell, list1)
870
2.11k
  {
871
2.11k
    if (!list_member(list2, lfirst(cell)))
872
354
      result = lappend(result, lfirst(cell));
873
2.11k
  }
874
875
1.50k
  check_list_invariants(result);
876
1.50k
  return result;
877
8.86k
}
878
879
/*
880
 * This variant of list_difference() determines list membership via
881
 * simple pointer equality.
882
 */
883
List *
884
list_difference_ptr(const List *list1, const List *list2)
885
396
{
886
396
  const ListCell *cell;
887
396
  List     *result = NIL;
888
889
396
  Assert(IsPointerList(list1));
890
396
  Assert(IsPointerList(list2));
891
892
396
  if (list2 == NIL)
893
70
    return list_copy(list1);
894
895
326
  foreach(cell, list1)
896
682
  {
897
682
    if (!list_member_ptr(list2, lfirst(cell)))
898
24
      result = lappend(result, lfirst(cell));
899
682
  }
900
901
326
  check_list_invariants(result);
902
326
  return result;
903
396
}
904
905
/*
906
 * This variant of list_difference() operates upon lists of integers.
907
 */
908
List *
909
list_difference_int(const List *list1, const List *list2)
910
14
{
911
14
  const ListCell *cell;
912
14
  List     *result = NIL;
913
914
14
  Assert(IsIntegerList(list1));
915
14
  Assert(IsIntegerList(list2));
916
917
14
  if (list2 == NIL)
918
14
    return list_copy(list1);
919
920
0
  foreach(cell, list1)
921
0
  {
922
0
    if (!list_member_int(list2, lfirst_int(cell)))
923
0
      result = lappend_int(result, lfirst_int(cell));
924
0
  }
925
926
0
  check_list_invariants(result);
927
0
  return result;
928
14
}
929
930
/*
931
 * This variant of list_difference() operates upon lists of OIDs.
932
 */
933
List *
934
list_difference_oid(const List *list1, const List *list2)
935
0
{
936
0
  const ListCell *cell;
937
0
  List     *result = NIL;
938
939
0
  Assert(IsOidList(list1));
940
0
  Assert(IsOidList(list2));
941
942
0
  if (list2 == NIL)
943
0
    return list_copy(list1);
944
945
0
  foreach(cell, list1)
946
0
  {
947
0
    if (!list_member_oid(list2, lfirst_oid(cell)))
948
0
      result = lappend_oid(result, lfirst_oid(cell));
949
0
  }
950
951
0
  check_list_invariants(result);
952
0
  return result;
953
0
}
954
955
/*
956
 * Append datum to list, but only if it isn't already in the list.
957
 *
958
 * Whether an element is already a member of the list is determined
959
 * via equal().
960
 */
961
List *
962
list_append_unique(List *list, void *datum)
963
453
{
964
453
  if (list_member(list, datum))
965
59
    return list;
966
394
  else
967
394
    return lappend(list, datum);
968
453
}
969
970
/*
971
 * This variant of list_append_unique() determines list membership via
972
 * simple pointer equality.
973
 */
974
List *
975
list_append_unique_ptr(List *list, void *datum)
976
139k
{
977
139k
  if (list_member_ptr(list, datum))
978
8.05k
    return list;
979
131k
  else
980
131k
    return lappend(list, datum);
981
139k
}
982
983
/*
984
 * This variant of list_append_unique() operates upon lists of integers.
985
 */
986
List *
987
list_append_unique_int(List *list, int datum)
988
0
{
989
0
  if (list_member_int(list, datum))
990
0
    return list;
991
0
  else
992
0
    return lappend_int(list, datum);
993
0
}
994
995
/*
996
 * This variant of list_append_unique() operates upon lists of OIDs.
997
 */
998
List *
999
list_append_unique_oid(List *list, Oid datum)
1000
247
{
1001
247
  if (list_member_oid(list, datum))
1002
0
    return list;
1003
247
  else
1004
247
    return lappend_oid(list, datum);
1005
247
}
1006
1007
/*
1008
 * Append to list1 each member of list2 that isn't already in list1.
1009
 *
1010
 * Whether an element is already a member of the list is determined
1011
 * via equal().
1012
 *
1013
 * This is almost the same functionality as list_union(), but list1 is
1014
 * modified in-place rather than being copied.  Note also that list2's cells
1015
 * are not inserted in list1, so the analogy to list_concat() isn't perfect.
1016
 */
1017
List *
1018
list_concat_unique(List *list1, List *list2)
1019
16
{
1020
16
  ListCell   *cell;
1021
1022
16
  Assert(IsPointerList(list1));
1023
16
  Assert(IsPointerList(list2));
1024
1025
16
  foreach(cell, list2)
1026
16
  {
1027
16
    if (!list_member(list1, lfirst(cell)))
1028
16
      list1 = lappend(list1, lfirst(cell));
1029
16
  }
1030
1031
16
  check_list_invariants(list1);
1032
16
  return list1;
1033
16
}
1034
1035
/*
1036
 * This variant of list_concat_unique() determines list membership via
1037
 * simple pointer equality.
1038
 */
1039
List *
1040
list_concat_unique_ptr(List *list1, List *list2)
1041
0
{
1042
0
  ListCell   *cell;
1043
1044
0
  Assert(IsPointerList(list1));
1045
0
  Assert(IsPointerList(list2));
1046
1047
0
  foreach(cell, list2)
1048
0
  {
1049
0
    if (!list_member_ptr(list1, lfirst(cell)))
1050
0
      list1 = lappend(list1, lfirst(cell));
1051
0
  }
1052
1053
0
  check_list_invariants(list1);
1054
0
  return list1;
1055
0
}
1056
1057
/*
1058
 * This variant of list_concat_unique() operates upon lists of integers.
1059
 */
1060
List *
1061
list_concat_unique_int(List *list1, List *list2)
1062
0
{
1063
0
  ListCell   *cell;
1064
1065
0
  Assert(IsIntegerList(list1));
1066
0
  Assert(IsIntegerList(list2));
1067
1068
0
  foreach(cell, list2)
1069
0
  {
1070
0
    if (!list_member_int(list1, lfirst_int(cell)))
1071
0
      list1 = lappend_int(list1, lfirst_int(cell));
1072
0
  }
1073
1074
0
  check_list_invariants(list1);
1075
0
  return list1;
1076
0
}
1077
1078
/*
1079
 * This variant of list_concat_unique() operates upon lists of OIDs.
1080
 */
1081
List *
1082
list_concat_unique_oid(List *list1, List *list2)
1083
326
{
1084
326
  ListCell   *cell;
1085
1086
326
  Assert(IsOidList(list1));
1087
326
  Assert(IsOidList(list2));
1088
1089
326
  foreach(cell, list2)
1090
0
  {
1091
0
    if (!list_member_oid(list1, lfirst_oid(cell)))
1092
0
      list1 = lappend_oid(list1, lfirst_oid(cell));
1093
0
  }
1094
1095
326
  check_list_invariants(list1);
1096
326
  return list1;
1097
326
}
1098
1099
/*
1100
 * Free all storage in a list, and optionally the pointed-to elements
1101
 */
1102
static void
1103
list_free_private(List *list, bool deep)
1104
8.10M
{
1105
8.10M
  ListCell   *cell;
1106
1107
8.10M
  check_list_invariants(list);
1108
1109
8.10M
  cell = list_head(list);
1110
12.2M
  while (cell != NULL)
1111
4.15M
  {
1112
4.15M
    ListCell   *tmp = cell;
1113
1114
4.15M
    cell = lnext(cell);
1115
4.15M
    if (deep)
1116
687k
      pfree(lfirst(tmp));
1117
4.15M
    pfree(tmp);
1118
4.15M
  }
1119
1120
8.10M
  if (list)
1121
2.64M
    pfree(list);
1122
8.10M
}
1123
1124
/*
1125
 * Free all the cells of the list, as well as the list itself. Any
1126
 * objects that are pointed-to by the cells of the list are NOT
1127
 * free'd.
1128
 *
1129
 * On return, the argument to this function has been freed, so the
1130
 * caller would be wise to set it to NIL for safety's sake.
1131
 */
1132
void
1133
list_free(List *list)
1134
7.93M
{
1135
7.93M
  list_free_private(list, false);
1136
7.93M
}
1137
1138
/*
1139
 * Free all the cells of the list, the list itself, and all the
1140
 * objects pointed-to by the cells of the list (each element in the
1141
 * list must contain a pointer to a palloc()'d region of memory!)
1142
 *
1143
 * On return, the argument to this function has been freed, so the
1144
 * caller would be wise to set it to NIL for safety's sake.
1145
 */
1146
void
1147
list_free_deep(List *list)
1148
169k
{
1149
  /*
1150
   * A "deep" free operation only makes sense on a list of pointers.
1151
   */
1152
169k
  Assert(IsPointerList(list));
1153
169k
  list_free_private(list, true);
1154
169k
}
1155
1156
/*
1157
 * Return a shallow copy of the specified list.
1158
 */
1159
List *
1160
list_copy(const List *oldlist)
1161
4.45M
{
1162
4.45M
  List     *newlist;
1163
4.45M
  ListCell   *newlist_prev;
1164
4.45M
  ListCell   *oldlist_cur;
1165
1166
4.45M
  if (oldlist == NIL)
1167
583k
    return NIL;
1168
1169
3.86M
  newlist = new_list(oldlist->type);
1170
3.86M
  newlist->length = oldlist->length;
1171
1172
  /*
1173
   * Copy over the data in the first cell; new_list() has already allocated
1174
   * the head cell itself
1175
   */
1176
3.86M
  newlist->head->data = oldlist->head->data;
1177
1178
3.86M
  newlist_prev = newlist->head;
1179
3.86M
  oldlist_cur = oldlist->head->next;
1180
4.90M
  while (oldlist_cur)
1181
1.03M
  {
1182
1.03M
    ListCell   *newlist_cur;
1183
1184
1.03M
    newlist_cur = (ListCell *) palloc(sizeof(*newlist_cur));
1185
1.03M
    newlist_cur->data = oldlist_cur->data;
1186
1.03M
    newlist_prev->next = newlist_cur;
1187
1188
1.03M
    newlist_prev = newlist_cur;
1189
1.03M
    oldlist_cur = oldlist_cur->next;
1190
1.03M
  }
1191
1192
3.86M
  newlist_prev->next = NULL;
1193
3.86M
  newlist->tail = newlist_prev;
1194
1195
3.86M
  check_list_invariants(newlist);
1196
3.86M
  return newlist;
1197
4.45M
}
1198
1199
/*
1200
 * Return a shallow copy of the specified list, without the first N elements.
1201
 */
1202
List *
1203
list_copy_tail(const List *oldlist, int nskip)
1204
7.75k
{
1205
7.75k
  List     *newlist;
1206
7.75k
  ListCell   *newlist_prev;
1207
7.75k
  ListCell   *oldlist_cur;
1208
1209
7.75k
  if (nskip < 0)
1210
0
    nskip = 0;       /* would it be better to elog? */
1211
1212
7.75k
  if (oldlist == NIL || nskip >= oldlist->length)
1213
101
    return NIL;
1214
1215
7.65k
  newlist = new_list(oldlist->type);
1216
7.65k
  newlist->length = oldlist->length - nskip;
1217
1218
  /*
1219
   * Skip over the unwanted elements.
1220
   */
1221
7.65k
  oldlist_cur = oldlist->head;
1222
8.33k
  while (nskip-- > 0)
1223
676
    oldlist_cur = oldlist_cur->next;
1224
1225
  /*
1226
   * Copy over the data in the first remaining cell; new_list() has already
1227
   * allocated the head cell itself
1228
   */
1229
7.65k
  newlist->head->data = oldlist_cur->data;
1230
1231
7.65k
  newlist_prev = newlist->head;
1232
7.65k
  oldlist_cur = oldlist_cur->next;
1233
198k
  while (oldlist_cur)
1234
190k
  {
1235
190k
    ListCell   *newlist_cur;
1236
1237
190k
    newlist_cur = (ListCell *) palloc(sizeof(*newlist_cur));
1238
190k
    newlist_cur->data = oldlist_cur->data;
1239
190k
    newlist_prev->next = newlist_cur;
1240
1241
190k
    newlist_prev = newlist_cur;
1242
190k
    oldlist_cur = oldlist_cur->next;
1243
190k
  }
1244
1245
7.65k
  newlist_prev->next = NULL;
1246
7.65k
  newlist->tail = newlist_prev;
1247
1248
7.65k
  check_list_invariants(newlist);
1249
7.65k
  return newlist;
1250
7.75k
}
1251
1252
/*
1253
 * Sort a list as though by qsort.
1254
 *
1255
 * A new list is built and returned.  Like list_copy, this doesn't make
1256
 * fresh copies of any pointed-to data.
1257
 *
1258
 * The comparator function receives arguments of type ListCell **.
1259
 */
1260
List *
1261
list_qsort(const List *list, list_qsort_comparator cmp)
1262
24
{
1263
24
  int     len = list_length(list);
1264
24
  ListCell  **list_arr;
1265
24
  List     *newlist;
1266
24
  ListCell   *newlist_prev;
1267
24
  ListCell   *cell;
1268
24
  int     i;
1269
1270
  /* Empty list is easy */
1271
24
  if (len == 0)
1272
12
    return NIL;
1273
1274
  /* Flatten list cells into an array, so we can use qsort */
1275
12
  list_arr = (ListCell **) palloc(sizeof(ListCell *) * len);
1276
12
  i = 0;
1277
12
  foreach(cell, list)
1278
36
    list_arr[i++] = cell;
1279
1280
12
  qsort(list_arr, len, sizeof(ListCell *), cmp);
1281
1282
  /* Construct new list (this code is much like list_copy) */
1283
12
  newlist = new_list(list->type);
1284
12
  newlist->length = len;
1285
1286
  /*
1287
   * Copy over the data in the first cell; new_list() has already allocated
1288
   * the head cell itself
1289
   */
1290
12
  newlist->head->data = list_arr[0]->data;
1291
1292
12
  newlist_prev = newlist->head;
1293
36
  for (i = 1; i < len; 
i++24
)
1294
24
  {
1295
24
    ListCell   *newlist_cur;
1296
1297
24
    newlist_cur = (ListCell *) palloc(sizeof(*newlist_cur));
1298
24
    newlist_cur->data = list_arr[i]->data;
1299
24
    newlist_prev->next = newlist_cur;
1300
1301
24
    newlist_prev = newlist_cur;
1302
24
  }
1303
1304
12
  newlist_prev->next = NULL;
1305
12
  newlist->tail = newlist_prev;
1306
1307
  /* Might as well free the workspace array */
1308
12
  pfree(list_arr);
1309
1310
12
  check_list_invariants(newlist);
1311
12
  return newlist;
1312
24
}
1313
1314
/*
1315
 * Temporary compatibility functions
1316
 *
1317
 * In order to avoid warnings for these function definitions, we need
1318
 * to include a prototype here as well as in pg_list.h. That's because
1319
 * we don't enable list API compatibility in list.c, so we
1320
 * don't see the prototypes for these functions.
1321
 */
1322
1323
/*
1324
 * Given a list, return its length. This is merely defined for the
1325
 * sake of backward compatibility: we can't afford to define a macro
1326
 * called "length", so it must be a function. New code should use the
1327
 * list_length() macro in order to avoid the overhead of a function
1328
 * call.
1329
 */
1330
int     length(const List *list);
1331
1332
int
1333
length(const List *list)
1334
0
{
1335
0
  return list_length(list);
1336
0
}