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

Go to the source code of this file.

Macros

#define WORDNUM(x)   ((x) / BITS_PER_BITMAPWORD)
 
#define BITNUM(x)   ((x) % BITS_PER_BITMAPWORD)
 
#define BITMAPSET_SIZE(nwords)    (offsetof(Bitmapset, words) + (nwords) * sizeof(bitmapword))
 
#define RIGHTMOST_ONE(x)   ((signedbitmapword) (x) & -((signedbitmapword) (x)))
 
#define HAS_MULTIPLE_ONES(x)   ((bitmapword) RIGHTMOST_ONE(x) != (x))
 

Functions

Bitmapsetbms_copy (const Bitmapset *a)
 
bool bms_equal (const Bitmapset *a, const Bitmapset *b)
 
int bms_compare (const Bitmapset *a, const Bitmapset *b)
 
Bitmapsetbms_make_singleton (int x)
 
void bms_free (Bitmapset *a)
 
Bitmapsetbms_union (const Bitmapset *a, const Bitmapset *b)
 
Bitmapsetbms_intersect (const Bitmapset *a, const Bitmapset *b)
 
Bitmapsetbms_difference (const Bitmapset *a, const Bitmapset *b)
 
Bitmapsetbms_offset_members (const Bitmapset *a, int offset)
 
bool bms_is_subset (const Bitmapset *a, const Bitmapset *b)
 
BMS_Comparison bms_subset_compare (const Bitmapset *a, const Bitmapset *b)
 
bool bms_is_member (int x, const Bitmapset *a)
 
int bms_member_index (Bitmapset *a, int x)
 
bool bms_overlap (const Bitmapset *a, const Bitmapset *b)
 
bool bms_overlap_list (const Bitmapset *a, const List *b)
 
bool bms_nonempty_difference (const Bitmapset *a, const Bitmapset *b)
 
int bms_singleton_member (const Bitmapset *a)
 
bool bms_get_singleton_member (const Bitmapset *a, int *member)
 
int bms_num_members (const Bitmapset *a)
 
BMS_Membership bms_membership (const Bitmapset *a)
 
Bitmapsetbms_add_member (Bitmapset *a, int x)
 
Bitmapsetbms_del_member (Bitmapset *a, int x)
 
Bitmapsetbms_add_members (Bitmapset *a, const Bitmapset *b)
 
Bitmapsetbms_replace_members (Bitmapset *a, const Bitmapset *b)
 
Bitmapsetbms_add_range (Bitmapset *a, int lower, int upper)
 
Bitmapsetbms_int_members (Bitmapset *a, const Bitmapset *b)
 
Bitmapsetbms_del_members (Bitmapset *a, const Bitmapset *b)
 
Bitmapsetbms_join (Bitmapset *a, Bitmapset *b)
 
int bms_next_member (const Bitmapset *a, int prevbit)
 
int bms_prev_member (const Bitmapset *a, int prevbit)
 
uint32 bms_hash_value (const Bitmapset *a)
 
uint32 bitmap_hash (const void *key, Size keysize)
 
int bitmap_match (const void *key1, const void *key2, Size keysize)
 

Macro Definition Documentation

◆ BITMAPSET_SIZE

#define BITMAPSET_SIZE (   nwords)     (offsetof(Bitmapset, words) + (nwords) * sizeof(bitmapword))

Definition at line 51 of file bitmapset.c.

80{
81 /* NULL is the correct representation of an empty set */
82 if (a == NULL)
83 return true;
84
85 /* check the node tag is set correctly. pfree'd pointer, maybe? */
86 if (!IsA(a, Bitmapset))
87 return false;
88
89 /* trailing zero words are not allowed */
90 if (a->words[a->nwords - 1] == 0)
91 return false;
92
93 return true;
94}
95#endif
96
97#ifdef REALLOCATE_BITMAPSETS
98/*
99 * bms_copy_and_free
100 * Only required in REALLOCATE_BITMAPSETS builds. Provide a simple way
101 * to return a freshly allocated set and pfree the original.
102 *
103 * Note: callers which accept multiple sets must be careful when calling this
104 * function to clone one parameter as other parameters may point to the same
105 * set. A good option is to call this just before returning the resulting
106 * set.
107 */
108static Bitmapset *
110{
111 Bitmapset *c = bms_copy(a);
112
113 bms_free(a);
114 return c;
115}
116#endif
117
118/*
119 * bms_copy - make a palloc'd copy of a bitmapset
120 */
121Bitmapset *
122bms_copy(const Bitmapset *a)
123{
125 size_t size;
126
128
129 if (a == NULL)
130 return NULL;
131
132 size = BITMAPSET_SIZE(a->nwords);
133 result = (Bitmapset *) palloc(size);
134 memcpy(result, a, size);
135 return result;
136}
137
138/*
139 * bms_equal - are two bitmapsets equal? or both NULL?
140 */
141bool
142bms_equal(const Bitmapset *a, const Bitmapset *b)
143{
144 int i;
145
148
149 /* Handle cases where either input is NULL */
150 if (a == NULL)
151 {
152 if (b == NULL)
153 return true;
154 return false;
155 }
156 else if (b == NULL)
157 return false;
158
159 /* can't be equal if the word counts don't match */
160 if (a->nwords != b->nwords)
161 return false;
162
163 /* check each word matches */
164 i = 0;
165 do
166 {
167 if (a->words[i] != b->words[i])
168 return false;
169 } while (++i < a->nwords);
170
171 return true;
172}
173
174/*
175 * bms_compare - qsort-style comparator for bitmapsets
176 *
177 * This guarantees to report values as equal iff bms_equal would say they are
178 * equal. Otherwise, the highest-numbered bit that is set in one value but
179 * not the other determines the result. (This rule means that, for example,
180 * {6} is greater than {5}, which seems plausible.)
181 */
182int
183bms_compare(const Bitmapset *a, const Bitmapset *b)
184{
185 int i;
186
189
190 /* Handle cases where either input is NULL */
191 if (a == NULL)
192 return (b == NULL) ? 0 : -1;
193 else if (b == NULL)
194 return +1;
195
196 /* the set with the most words must be greater */
197 if (a->nwords != b->nwords)
198 return (a->nwords > b->nwords) ? +1 : -1;
199
200 i = a->nwords - 1;
201 do
202 {
203 bitmapword aw = a->words[i];
204 bitmapword bw = b->words[i];
205
206 if (aw != bw)
207 return (aw > bw) ? +1 : -1;
208 } while (--i >= 0);
209 return 0;
210}
211
212/*
213 * bms_make_singleton - build a bitmapset containing a single member
214 */
215Bitmapset *
217{
219 int wordnum,
220 bitnum;
221
222 if (x < 0)
223 elog(ERROR, "negative bitmapset member not allowed");
224 wordnum = WORDNUM(x);
225 bitnum = BITNUM(x);
227 result->type = T_Bitmapset;
228 result->nwords = wordnum + 1;
229 result->words[wordnum] = ((bitmapword) 1 << bitnum);
230 return result;
231}
232
233/*
234 * bms_free - free a bitmapset
235 *
236 * Same as pfree except for allowing NULL input
237 */
238void
240{
241 if (a)
242 pfree(a);
243}
244
245
246/*
247 * bms_union - create and return a new set containing all members from both
248 * input sets. Both inputs are left unmodified.
249 */
250Bitmapset *
251bms_union(const Bitmapset *a, const Bitmapset *b)
252{
254 const Bitmapset *other;
255 int otherlen;
256 int i;
257
260
261 /* Handle cases where either input is NULL */
262 if (a == NULL)
263 return bms_copy(b);
264 if (b == NULL)
265 return bms_copy(a);
266 /* Identify shorter and longer input; copy the longer one */
267 if (a->nwords <= b->nwords)
268 {
269 result = bms_copy(b);
270 other = a;
271 }
272 else
273 {
274 result = bms_copy(a);
275 other = b;
276 }
277 /* And union the shorter input into the result */
278 otherlen = other->nwords;
279 i = 0;
280 do
281 {
282 result->words[i] |= other->words[i];
283 } while (++i < otherlen);
284 return result;
285}
286
287/*
288 * bms_intersect - create and return a new set containing members which both
289 * input sets have in common. Both inputs are left unmodified.
290 */
291Bitmapset *
292bms_intersect(const Bitmapset *a, const Bitmapset *b)
293{
295 const Bitmapset *other;
296 int lastnonzero;
297 int resultlen;
298 int i;
299
302
303 /* Handle cases where either input is NULL */
304 if (a == NULL || b == NULL)
305 return NULL;
306
307 /* Identify shorter and longer input; copy the shorter one */
308 if (a->nwords <= b->nwords)
309 {
310 result = bms_copy(a);
311 other = b;
312 }
313 else
314 {
315 result = bms_copy(b);
316 other = a;
317 }
318 /* And intersect the longer input with the result */
319 resultlen = result->nwords;
320 lastnonzero = -1;
321 i = 0;
322 do
323 {
324 result->words[i] &= other->words[i];
325
326 if (result->words[i] != 0)
327 lastnonzero = i;
328 } while (++i < resultlen);
329 /* If we computed an empty result, we must return NULL */
330 if (lastnonzero == -1)
331 {
332 pfree(result);
333 return NULL;
334 }
335
336 /* get rid of trailing zero words */
337 result->nwords = lastnonzero + 1;
338 return result;
339}
340
341/*
342 * bms_difference - create and return a new set containing all the members of
343 * 'a' without the members of 'b'.
344 */
345Bitmapset *
346bms_difference(const Bitmapset *a, const Bitmapset *b)
347{
349 int i;
350
353
354 /* Handle cases where either input is NULL */
355 if (a == NULL)
356 return NULL;
357 if (b == NULL)
358 return bms_copy(a);
359
360 /*
361 * In Postgres' usage, an empty result is a very common case, so it's
362 * worth optimizing for that by testing bms_nonempty_difference(). This
363 * saves us a palloc/pfree cycle compared to checking after-the-fact.
364 */
366 return NULL;
367
368 /* Copy the left input */
369 result = bms_copy(a);
370
371 /* And remove b's bits from result */
372 if (result->nwords > b->nwords)
373 {
374 /*
375 * We'll never need to remove trailing zero words when 'a' has more
376 * words than 'b' as the additional words must be non-zero.
377 */
378 i = 0;
379 do
380 {
381 result->words[i] &= ~b->words[i];
382 } while (++i < b->nwords);
383 }
384 else
385 {
386 int lastnonzero = -1;
387
388 /* we may need to remove trailing zero words from the result. */
389 i = 0;
390 do
391 {
392 result->words[i] &= ~b->words[i];
393
394 /* remember the last non-zero word */
395 if (result->words[i] != 0)
396 lastnonzero = i;
397 } while (++i < result->nwords);
398
399 /* trim off trailing zero words */
400 result->nwords = lastnonzero + 1;
401 }
402 Assert(result->nwords != 0);
403
404 /* Need not check for empty result, since we handled that case above */
405 return result;
406}
407
408/*
409 * bms_offset_members
410 * Creates a new Bitmapset with all members of 'a' adjusted to add the
411 * value of 'offset' to each member.
412 *
413 * Members that would become negative as a result of a negative offset will
414 * be removed from the set, whereas too large an offset, which would result in
415 * a member going > INT_MAX, will result in an ERROR.
416 */
417Bitmapset *
418bms_offset_members(const Bitmapset *a, int offset)
419{
421 int offset_words;
422 int offset_bits;
423 int new_nwords;
424 int old_nwords;
426 int old_highest;
427 int new_highest;
428
430
431 /* nothing to do for empty sets */
432 if (a == NULL)
433 return NULL;
434
435 old_nwords = a->nwords;
436 offset_words = WORDNUM(offset);
437 offset_bits = BITNUM(offset);
438 high_bit = bmw_leftmost_one_pos(a->words[a->nwords - 1]);
440
441 /* don't create a set with a member that doesn't fit into an int32 */
443 elog(ERROR, "bitmapset overflow");
444 /* return NULL if the new set would be empty */
445 else if (new_highest < 0)
446 return NULL;
447
450 result->type = T_Bitmapset;
451 result->nwords = new_nwords;
452
453 /* handle zero and positive offsets (bitshift left) */
454 if (offset >= 0)
455 {
456 /*
457 * We special-case offsetting only by whole words, so we don't have to
458 * special-case bitshifting by BITS_PER_BITMAPWORD places, which has
459 * an undefined behavior.
460 */
461 if (offset_bits == 0)
462 {
463 int i = 0;
464
465 /*
466 * The old set is guaranteed to have at least 1 word, so use
467 * do/while to save the redundant initial loop bounds check.
468 */
469 do
470 {
472 result->words[i + offset_words] = a->words[i];
473 } while (++i < old_nwords);
474 }
475 else
476 {
479 int i = 0;
480
481 do
482 {
483 bitmapword carry = (a->words[i] >> carry_bits);
484
486 /* shift bits up and carry bits from the previous word */
487 result->words[i + offset_words] = (a->words[i] << offset_bits) | prev_carry;
489 } while (++i < old_nwords);
490 result->words[new_nwords - 1] |= prev_carry;
491 }
492 }
493
494 /* handle negative offset (bitshift right) */
495 else
496 {
497 /* make the negative offset_words and offset_bits positive */
500
501 /* as above, special case shifting only by whole words */
502 if (offset_bits == 0)
503 {
504 int i = 0;
505
506 do
507 {
509 result->words[i] = a->words[i + offset_words];
510 } while (++i < new_nwords);
511 }
512 else
513 {
516 int i = new_nwords - 1;
517
518 /* carry bits from any word just above where the loop starts */
521
522 /*
523 * We loop backward over the array so we correctly carry bits from
524 * higher words.
525 */
526 do
527 {
528 bitmapword carry = (a->words[i + offset_words] << carry_bits);
529
531
532 /* shift bits down and carry bits from the previous word */
533 result->words[i] = (a->words[i + offset_words] >> offset_bits) | prev_carry;
535 } while (--i >= 0);
536 }
537 }
538
539 return result;
540}
541
542/*
543 * bms_is_subset - is A a subset of B?
544 */
545bool
546bms_is_subset(const Bitmapset *a, const Bitmapset *b)
547{
548 int i;
549
552
553 /* Handle cases where either input is NULL */
554 if (a == NULL)
555 return true; /* empty set is a subset of anything */
556 if (b == NULL)
557 return false;
558
559 /* 'a' can't be a subset of 'b' if it contains more words */
560 if (a->nwords > b->nwords)
561 return false;
562
563 /* Check all 'a' members are set in 'b' */
564 i = 0;
565 do
566 {
567 if ((a->words[i] & ~b->words[i]) != 0)
568 return false;
569 } while (++i < a->nwords);
570 return true;
571}
572
573/*
574 * bms_subset_compare - compare A and B for equality/subset relationships
575 *
576 * This is more efficient than testing bms_is_subset in both directions.
577 */
580{
582 int shortlen;
583 int i;
584
587
588 /* Handle cases where either input is NULL */
589 if (a == NULL)
590 {
591 if (b == NULL)
592 return BMS_EQUAL;
593 return BMS_SUBSET1;
594 }
595 if (b == NULL)
596 return BMS_SUBSET2;
597
598 /* Check common words */
599 result = BMS_EQUAL; /* status so far */
600 shortlen = Min(a->nwords, b->nwords);
601 i = 0;
602 do
603 {
604 bitmapword aword = a->words[i];
605 bitmapword bword = b->words[i];
606
607 if ((aword & ~bword) != 0)
608 {
609 /* a is not a subset of b */
610 if (result == BMS_SUBSET1)
611 return BMS_DIFFERENT;
613 }
614 if ((bword & ~aword) != 0)
615 {
616 /* b is not a subset of a */
617 if (result == BMS_SUBSET2)
618 return BMS_DIFFERENT;
620 }
621 } while (++i < shortlen);
622 /* Check extra words */
623 if (a->nwords > b->nwords)
624 {
625 /* if a has more words then a is not a subset of b */
626 if (result == BMS_SUBSET1)
627 return BMS_DIFFERENT;
628 return BMS_SUBSET2;
629 }
630 else if (a->nwords < b->nwords)
631 {
632 /* if b has more words then b is not a subset of a */
633 if (result == BMS_SUBSET2)
634 return BMS_DIFFERENT;
635 return BMS_SUBSET1;
636 }
637 return result;
638}
639
640/*
641 * bms_is_member - is X a member of A?
642 */
643bool
644bms_is_member(int x, const Bitmapset *a)
645{
646 int wordnum,
647 bitnum;
648
650
651 /* XXX better to just return false for x<0 ? */
652 if (x < 0)
653 elog(ERROR, "negative bitmapset member not allowed");
654 if (a == NULL)
655 return false;
656
657 wordnum = WORDNUM(x);
658 bitnum = BITNUM(x);
659 if (wordnum >= a->nwords)
660 return false;
661 if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
662 return true;
663 return false;
664}
665
666/*
667 * bms_member_index
668 * determine 0-based index of member x in the bitmap
669 *
670 * Returns (-1) when x is not a member.
671 */
672int
674{
675 int bitnum;
676 int wordnum;
677 int result = 0;
678 bitmapword mask;
679
681
682 /* return -1 if not a member of the bitmap */
683 if (!bms_is_member(x, a))
684 return -1;
685
686 wordnum = WORDNUM(x);
687 bitnum = BITNUM(x);
688
689 /* count bits in preceding words */
690 result += pg_popcount((const char *) a->words,
691 wordnum * sizeof(bitmapword));
692
693 /*
694 * Now add bits of the last word, but only those before the item. We can
695 * do that by applying a mask and then using popcount again. To get
696 * 0-based index, we want to count only preceding bits, not the item
697 * itself, so we subtract 1.
698 */
699 mask = ((bitmapword) 1 << bitnum) - 1;
700 result += bmw_popcount(a->words[wordnum] & mask);
701
702 return result;
703}
704
705/*
706 * bms_overlap - do sets overlap (ie, have a nonempty intersection)?
707 */
708bool
709bms_overlap(const Bitmapset *a, const Bitmapset *b)
710{
711 int shortlen;
712 int i;
713
716
717 /* Handle cases where either input is NULL */
718 if (a == NULL || b == NULL)
719 return false;
720 /* Check words in common */
721 shortlen = Min(a->nwords, b->nwords);
722 i = 0;
723 do
724 {
725 if ((a->words[i] & b->words[i]) != 0)
726 return true;
727 } while (++i < shortlen);
728 return false;
729}
730
731/*
732 * bms_overlap_list - does a set overlap an integer list?
733 */
734bool
735bms_overlap_list(const Bitmapset *a, const List *b)
736{
737 ListCell *lc;
738 int wordnum,
739 bitnum;
740
742
743 if (a == NULL || b == NIL)
744 return false;
745
746 foreach(lc, b)
747 {
748 int x = lfirst_int(lc);
749
750 if (x < 0)
751 elog(ERROR, "negative bitmapset member not allowed");
752 wordnum = WORDNUM(x);
753 bitnum = BITNUM(x);
754 if (wordnum < a->nwords)
755 if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
756 return true;
757 }
758
759 return false;
760}
761
762/*
763 * bms_nonempty_difference - do sets have a nonempty difference?
764 *
765 * i.e., are any members set in 'a' that are not also set in 'b'.
766 */
767bool
769{
770 int i;
771
774
775 /* Handle cases where either input is NULL */
776 if (a == NULL)
777 return false;
778 if (b == NULL)
779 return true;
780 /* if 'a' has more words then it must contain additional members */
781 if (a->nwords > b->nwords)
782 return true;
783 /* Check all 'a' members are set in 'b' */
784 i = 0;
785 do
786 {
787 if ((a->words[i] & ~b->words[i]) != 0)
788 return true;
789 } while (++i < a->nwords);
790 return false;
791}
792
793/*
794 * bms_singleton_member - return the sole integer member of set
795 *
796 * Raises error if |a| is not 1.
797 */
798int
800{
801 int result = -1;
802 int nwords;
803 int wordnum;
804
806
807 if (a == NULL)
808 elog(ERROR, "bitmapset is empty");
809
810 nwords = a->nwords;
811 wordnum = 0;
812 do
813 {
814 bitmapword w = a->words[wordnum];
815
816 if (w != 0)
817 {
818 if (result >= 0 || HAS_MULTIPLE_ONES(w))
819 elog(ERROR, "bitmapset has multiple members");
822 }
823 } while (++wordnum < nwords);
824
825 /* we don't expect non-NULL sets to be empty */
826 Assert(result >= 0);
827 return result;
828}
829
830/*
831 * bms_get_singleton_member
832 *
833 * Test whether the given set is a singleton.
834 * If so, set *member to the value of its sole member, and return true.
835 * If not, return false, without changing *member.
836 *
837 * This is more convenient and faster than calling bms_membership() and then
838 * bms_singleton_member(), if we don't care about distinguishing empty sets
839 * from multiple-member sets.
840 */
841bool
842bms_get_singleton_member(const Bitmapset *a, int *member)
843{
844 int result = -1;
845 int nwords;
846 int wordnum;
847
849
850 if (a == NULL)
851 return false;
852
853 nwords = a->nwords;
854 wordnum = 0;
855 do
856 {
857 bitmapword w = a->words[wordnum];
858
859 if (w != 0)
860 {
861 if (result >= 0 || HAS_MULTIPLE_ONES(w))
862 return false;
865 }
866 } while (++wordnum < nwords);
867
868 /* we don't expect non-NULL sets to be empty */
869 Assert(result >= 0);
870 *member = result;
871 return true;
872}
873
874/*
875 * bms_num_members - count members of set
876 */
877int
879{
881
882 if (a == NULL)
883 return 0;
884
885 /* fast-path for common case */
886 if (a->nwords == 1)
887 return bmw_popcount(a->words[0]);
888
889 return pg_popcount((const char *) a->words,
890 a->nwords * sizeof(bitmapword));
891}
892
893/*
894 * bms_membership - does a set have zero, one, or multiple members?
895 *
896 * This is faster than making an exact count with bms_num_members().
897 */
900{
902 int nwords;
903 int wordnum;
904
906
907 if (a == NULL)
908 return BMS_EMPTY_SET;
909
910 nwords = a->nwords;
911 wordnum = 0;
912 do
913 {
914 bitmapword w = a->words[wordnum];
915
916 if (w != 0)
917 {
919 return BMS_MULTIPLE;
921 }
922 } while (++wordnum < nwords);
923 return result;
924}
925
926
927/*
928 * bms_add_member - add a specified member to set
929 *
930 * 'a' is recycled when possible.
931 */
932Bitmapset *
934{
935 int wordnum,
936 bitnum;
937
939
940 if (x < 0)
941 elog(ERROR, "negative bitmapset member not allowed");
942 if (a == NULL)
943 return bms_make_singleton(x);
944
945 wordnum = WORDNUM(x);
946 bitnum = BITNUM(x);
947
948 /* enlarge the set if necessary */
949 if (wordnum >= a->nwords)
950 {
951 int oldnwords = a->nwords;
952 int i;
953
955 a->nwords = wordnum + 1;
956 /* zero out the enlarged portion */
957 i = oldnwords;
958 do
959 {
960 a->words[i] = 0;
961 } while (++i < a->nwords);
962 }
963
964 a->words[wordnum] |= ((bitmapword) 1 << bitnum);
965
966#ifdef REALLOCATE_BITMAPSETS
967
968 /*
969 * There's no guarantee that the repalloc returned a new pointer, so copy
970 * and free unconditionally here.
971 */
973#endif
974
975 return a;
976}
977
978/*
979 * bms_del_member - remove a specified member from set
980 *
981 * No error if x is not currently a member of set
982 *
983 * 'a' is recycled when possible.
984 */
985Bitmapset *
987{
988 int wordnum,
989 bitnum;
990
992
993 if (x < 0)
994 elog(ERROR, "negative bitmapset member not allowed");
995 if (a == NULL)
996 return NULL;
997
998 wordnum = WORDNUM(x);
999 bitnum = BITNUM(x);
1000
1001#ifdef REALLOCATE_BITMAPSETS
1003#endif
1004
1005 /* member can't exist. Return 'a' unmodified */
1006 if (unlikely(wordnum >= a->nwords))
1007 return a;
1008
1009 a->words[wordnum] &= ~((bitmapword) 1 << bitnum);
1010
1011 /* when last word becomes empty, trim off all trailing empty words */
1012 if (a->words[wordnum] == 0 && wordnum == a->nwords - 1)
1013 {
1014 /* find the last non-empty word and make that the new final word */
1015 for (int i = wordnum - 1; i >= 0; i--)
1016 {
1017 if (a->words[i] != 0)
1018 {
1019 a->nwords = i + 1;
1020 return a;
1021 }
1022 }
1023
1024 /* the set is now empty */
1025 pfree(a);
1026 return NULL;
1027 }
1028 return a;
1029}
1030
1031/*
1032 * bms_add_members - like bms_union, but left input is recycled when possible
1033 */
1034Bitmapset *
1036{
1038 const Bitmapset *other;
1039 int otherlen;
1040 int i;
1041
1044
1045 /* Handle cases where either input is NULL */
1046 if (a == NULL)
1047 return bms_copy(b);
1048 if (b == NULL)
1049 {
1050#ifdef REALLOCATE_BITMAPSETS
1052#endif
1053
1054 return a;
1055 }
1056 /* Identify shorter and longer input; copy the longer one if needed */
1057 if (a->nwords < b->nwords)
1058 {
1059 result = bms_copy(b);
1060 other = a;
1061 }
1062 else
1063 {
1064 result = a;
1065 other = b;
1066 }
1067 /* And union the shorter input into the result */
1068 otherlen = other->nwords;
1069 i = 0;
1070 do
1071 {
1072 result->words[i] |= other->words[i];
1073 } while (++i < otherlen);
1074 if (result != a)
1075 pfree(a);
1076#ifdef REALLOCATE_BITMAPSETS
1077 else
1079#endif
1080
1081 return result;
1082}
1083
1084/*
1085 * bms_replace_members
1086 * Remove all existing members from 'a' and repopulate the set with members
1087 * from 'b', recycling 'a', when possible.
1088 */
1089Bitmapset *
1091{
1092 int i;
1093
1096
1097 if (a == NULL)
1098 return bms_copy(b);
1099 if (b == NULL)
1100 {
1101 pfree(a);
1102 return NULL;
1103 }
1104
1105 if (a->nwords < b->nwords)
1106 a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(b->nwords));
1107
1108 i = 0;
1109 do
1110 {
1111 a->words[i] = b->words[i];
1112 } while (++i < b->nwords);
1113
1114 a->nwords = b->nwords;
1115
1116#ifdef REALLOCATE_BITMAPSETS
1117
1118 /*
1119 * There's no guarantee that the repalloc returned a new pointer, so copy
1120 * and free unconditionally here.
1121 */
1123#endif
1124
1125 return a;
1126}
1127
1128/*
1129 * bms_add_range
1130 * Add members in the range of 'lower' to 'upper' to the set.
1131 *
1132 * Note this could also be done by calling bms_add_member in a loop, however,
1133 * using this function will be faster when the range is large as we work at
1134 * the bitmapword level rather than at bit level.
1135 */
1136Bitmapset *
1138{
1139 int lwordnum,
1140 lbitnum,
1141 uwordnum,
1142 ushiftbits,
1143 wordnum;
1144
1146
1147 /* do nothing if nothing is called for, without further checking */
1148 if (upper < lower)
1149 {
1150#ifdef REALLOCATE_BITMAPSETS
1152#endif
1153
1154 return a;
1155 }
1156
1157 if (lower < 0)
1158 elog(ERROR, "negative bitmapset member not allowed");
1160
1161 if (a == NULL)
1162 {
1164 a->type = T_Bitmapset;
1165 a->nwords = uwordnum + 1;
1166 }
1167 else if (uwordnum >= a->nwords)
1168 {
1169 int oldnwords = a->nwords;
1170 int i;
1171
1172 /* ensure we have enough words to store the upper bit */
1174 a->nwords = uwordnum + 1;
1175 /* zero out the enlarged portion */
1176 i = oldnwords;
1177 do
1178 {
1179 a->words[i] = 0;
1180 } while (++i < a->nwords);
1181 }
1182
1184
1185 lbitnum = BITNUM(lower);
1187
1188 /*
1189 * Special case when lwordnum is the same as uwordnum we must perform the
1190 * upper and lower masking on the word.
1191 */
1192 if (lwordnum == uwordnum)
1193 {
1194 a->words[lwordnum] |= ~(bitmapword) (((bitmapword) 1 << lbitnum) - 1)
1195 & (~(bitmapword) 0) >> ushiftbits;
1196 }
1197 else
1198 {
1199 /* turn on lbitnum and all bits left of it */
1200 a->words[wordnum++] |= ~(bitmapword) (((bitmapword) 1 << lbitnum) - 1);
1201
1202 /* turn on all bits for any intermediate words */
1203 while (wordnum < uwordnum)
1204 a->words[wordnum++] = ~(bitmapword) 0;
1205
1206 /* turn on upper's bit and all bits right of it. */
1207 a->words[uwordnum] |= (~(bitmapword) 0) >> ushiftbits;
1208 }
1209
1210#ifdef REALLOCATE_BITMAPSETS
1211
1212 /*
1213 * There's no guarantee that the repalloc returned a new pointer, so copy
1214 * and free unconditionally here.
1215 */
1217#endif
1218
1219 return a;
1220}
1221
1222/*
1223 * bms_int_members - like bms_intersect, but left input is recycled when
1224 * possible
1225 */
1226Bitmapset *
1228{
1229 int lastnonzero;
1230 int shortlen;
1231 int i;
1232
1235
1236 /* Handle cases where either input is NULL */
1237 if (a == NULL)
1238 return NULL;
1239 if (b == NULL)
1240 {
1241 pfree(a);
1242 return NULL;
1243 }
1244
1245 /* Intersect b into a; we need never copy */
1246 shortlen = Min(a->nwords, b->nwords);
1247 lastnonzero = -1;
1248 i = 0;
1249 do
1250 {
1251 a->words[i] &= b->words[i];
1252
1253 if (a->words[i] != 0)
1254 lastnonzero = i;
1255 } while (++i < shortlen);
1256
1257 /* If we computed an empty result, we must return NULL */
1258 if (lastnonzero == -1)
1259 {
1260 pfree(a);
1261 return NULL;
1262 }
1263
1264 /* get rid of trailing zero words */
1265 a->nwords = lastnonzero + 1;
1266
1267#ifdef REALLOCATE_BITMAPSETS
1269#endif
1270
1271 return a;
1272}
1273
1274/*
1275 * bms_del_members - delete members in 'a' that are set in 'b'. 'a' is
1276 * recycled when possible.
1277 */
1278Bitmapset *
1280{
1281 int i;
1282
1285
1286 /* Handle cases where either input is NULL */
1287 if (a == NULL)
1288 return NULL;
1289 if (b == NULL)
1290 {
1291#ifdef REALLOCATE_BITMAPSETS
1293#endif
1294
1295 return a;
1296 }
1297
1298 /* Remove b's bits from a; we need never copy */
1299 if (a->nwords > b->nwords)
1300 {
1301 /*
1302 * We'll never need to remove trailing zero words when 'a' has more
1303 * words than 'b'.
1304 */
1305 i = 0;
1306 do
1307 {
1308 a->words[i] &= ~b->words[i];
1309 } while (++i < b->nwords);
1310 }
1311 else
1312 {
1313 int lastnonzero = -1;
1314
1315 /* we may need to remove trailing zero words from the result. */
1316 i = 0;
1317 do
1318 {
1319 a->words[i] &= ~b->words[i];
1320
1321 /* remember the last non-zero word */
1322 if (a->words[i] != 0)
1323 lastnonzero = i;
1324 } while (++i < a->nwords);
1325
1326 /* check if 'a' has become empty */
1327 if (lastnonzero == -1)
1328 {
1329 pfree(a);
1330 return NULL;
1331 }
1332
1333 /* trim off any trailing zero words */
1334 a->nwords = lastnonzero + 1;
1335 }
1336
1337#ifdef REALLOCATE_BITMAPSETS
1339#endif
1340
1341 return a;
1342}
1343
1344/*
1345 * bms_join - like bms_union, but *either* input *may* be recycled
1346 */
1347Bitmapset *
1349{
1352 int otherlen;
1353 int i;
1354
1357
1358 /* Handle cases where either input is NULL */
1359 if (a == NULL)
1360 {
1361#ifdef REALLOCATE_BITMAPSETS
1363#endif
1364
1365 return b;
1366 }
1367 if (b == NULL)
1368 {
1369#ifdef REALLOCATE_BITMAPSETS
1371#endif
1372
1373 return a;
1374 }
1375
1376 /* Identify shorter and longer input; use longer one as result */
1377 if (a->nwords < b->nwords)
1378 {
1379 result = b;
1380 other = a;
1381 }
1382 else
1383 {
1384 result = a;
1385 other = b;
1386 }
1387 /* And union the shorter input into the result */
1388 otherlen = other->nwords;
1389 i = 0;
1390 do
1391 {
1392 result->words[i] |= other->words[i];
1393 } while (++i < otherlen);
1394 if (other != result) /* pure paranoia */
1395 pfree(other);
1396
1397#ifdef REALLOCATE_BITMAPSETS
1399#endif
1400
1401 return result;
1402}
1403
1404/*
1405 * bms_next_member - find next member of a set
1406 *
1407 * Returns smallest member greater than "prevbit", or -2 if there is none.
1408 * "prevbit" must NOT be less than -1, or the behavior is unpredictable.
1409 *
1410 * This is intended as support for iterating through the members of a set.
1411 * The typical pattern is
1412 *
1413 * x = -1;
1414 * while ((x = bms_next_member(inputset, x)) >= 0)
1415 * process member x;
1416 *
1417 * Notice that when there are no more members, we return -2, not -1 as you
1418 * might expect. The rationale for that is to allow distinguishing the
1419 * loop-not-started state (x == -1) from the loop-completed state (x == -2).
1420 * It makes no difference in simple loop usage, but complex iteration logic
1421 * might need such an ability.
1422 */
1423int
1425{
1426 unsigned int currbit = prevbit;
1427 int nwords;
1428 bitmapword mask;
1429
1431
1432 if (a == NULL)
1433 return -2;
1434 nwords = a->nwords;
1435
1436 /* use an unsigned int to avoid the risk that int overflows */
1437 currbit++;
1438 mask = (~(bitmapword) 0) << BITNUM(currbit);
1439 for (int wordnum = WORDNUM(currbit); wordnum < nwords; wordnum++)
1440 {
1441 bitmapword w = a->words[wordnum];
1442
1443 /* ignore bits before currbit */
1444 w &= mask;
1445
1446 if (w != 0)
1447 {
1448 int result;
1449
1452 return result;
1453 }
1454
1455 /* in subsequent words, consider all bits */
1456 mask = (~(bitmapword) 0);
1457 }
1458 return -2;
1459}
1460
1461/*
1462 * bms_prev_member - find prev member of a set
1463 *
1464 * Returns largest member less than "prevbit", or -2 if there is none.
1465 * "prevbit" must NOT be more than one above the highest possible bit that can
1466 * be set in the Bitmapset at its current size.
1467 *
1468 * To ease finding the highest set bit for the initial loop, the special
1469 * prevbit value of -1 can be passed to have the function find the highest
1470 * valued member in the set.
1471 *
1472 * This is intended as support for iterating through the members of a set in
1473 * reverse. The typical pattern is
1474 *
1475 * x = -1;
1476 * while ((x = bms_prev_member(inputset, x)) >= 0)
1477 * process member x;
1478 *
1479 * Notice that when there are no more members, we return -2, not -1 as you
1480 * might expect. The rationale for that is to allow distinguishing the
1481 * loop-not-started state (x == -1) from the loop-completed state (x == -2).
1482 * It makes no difference in simple loop usage, but complex iteration logic
1483 * might need such an ability.
1484 */
1485int
1487{
1488 unsigned int currbit;
1489 int ushiftbits;
1490 bitmapword mask;
1491
1493
1494 /*
1495 * If set is NULL or if there are no more bits to the right then we've
1496 * nothing to do.
1497 */
1498 if (a == NULL || prevbit == 0)
1499 return -2;
1500
1501 /* Validate callers didn't give us something out of range */
1502 Assert(prevbit < 0 || prevbit <= (unsigned int) (a->nwords * BITS_PER_BITMAPWORD));
1503
1504 /*
1505 * Transform -1 (or any negative number) to the highest possible bit we
1506 * could have set. We do this in unsigned math to avoid the risk of
1507 * overflowing a signed int.
1508 */
1509 if (prevbit < 0)
1510 currbit = (unsigned int) a->nwords * BITS_PER_BITMAPWORD - 1;
1511 else
1512 currbit = prevbit - 1;
1513
1515 mask = (~(bitmapword) 0) >> ushiftbits;
1516 for (int wordnum = WORDNUM(currbit); wordnum >= 0; wordnum--)
1517 {
1518 bitmapword w = a->words[wordnum];
1519
1520 /* mask out bits left of currbit */
1521 w &= mask;
1522
1523 if (w != 0)
1524 {
1525 int result;
1526
1529 return result;
1530 }
1531
1532 /* in subsequent words, consider all bits */
1533 mask = (~(bitmapword) 0);
1534 }
1535 return -2;
1536}
1537
1538/*
1539 * bms_hash_value - compute a hash key for a Bitmapset
1540 */
1541uint32
1543{
1545
1546 if (a == NULL)
1547 return 0; /* All empty sets hash to 0 */
1548 return DatumGetUInt32(hash_any((const unsigned char *) a->words,
1549 a->nwords * sizeof(bitmapword)));
1550}
1551
1552/*
1553 * bitmap_hash - hash function for keys that are (pointers to) Bitmapsets
1554 *
1555 * Note: don't forget to specify bitmap_match as the match function!
1556 */
1557uint32
1558bitmap_hash(const void *key, Size keysize)
1559{
1560 Assert(keysize == sizeof(Bitmapset *));
1561 return bms_hash_value(*((const Bitmapset *const *) key));
1562}
1563
1564/*
1565 * bitmap_match - match function to use with bitmap_hash
1566 */
1567int
1568bitmap_match(const void *key1, const void *key2, Size keysize)
1569{
1570 Assert(keysize == sizeof(Bitmapset *));
1571 return !bms_equal(*((const Bitmapset *const *) key1),
1572 *((const Bitmapset *const *) key2));
1573}
#define BITMAPSET_SIZE(nwords)
Definition bitmapset.c:51
Bitmapset * bms_replace_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:1091
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:347
int bms_prev_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1487
Bitmapset * bms_make_singleton(int x)
Definition bitmapset.c:217
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:1228
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:293
uint32 bitmap_hash(const void *key, Size keysize)
Definition bitmapset.c:1559
#define WORDNUM(x)
Definition bitmapset.c:48
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:143
BMS_Comparison bms_subset_compare(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:580
int bms_next_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1425
uint32 bms_hash_value(const Bitmapset *a)
Definition bitmapset.c:1543
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:1280
Bitmapset * bms_add_range(Bitmapset *a, int lower, int upper)
Definition bitmapset.c:1138
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition bitmapset.c:987
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:547
int bms_singleton_member(const Bitmapset *a)
Definition bitmapset.c:800
void bms_free(Bitmapset *a)
Definition bitmapset.c:240
int bms_num_members(const Bitmapset *a)
Definition bitmapset.c:879
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:645
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:934
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:1036
#define BITNUM(x)
Definition bitmapset.c:49
Bitmapset * bms_offset_members(const Bitmapset *a, int offset)
Definition bitmapset.c:419
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:252
#define HAS_MULTIPLE_ONES(x)
Definition bitmapset.c:73
int bitmap_match(const void *key1, const void *key2, Size keysize)
Definition bitmapset.c:1569
BMS_Membership bms_membership(const Bitmapset *a)
Definition bitmapset.c:900
int bms_member_index(Bitmapset *a, int x)
Definition bitmapset.c:674
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:710
int bms_compare(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:184
bool bms_get_singleton_member(const Bitmapset *a, int *member)
Definition bitmapset.c:843
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition bitmapset.c:1349
bool bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:769
Bitmapset * bms_copy(const Bitmapset *a)
Definition bitmapset.c:123
bool bms_overlap_list(const Bitmapset *a, const List *b)
Definition bitmapset.c:736
#define bmw_rightmost_one_pos(w)
Definition bitmapset.h:79
#define bmw_leftmost_one_pos(w)
Definition bitmapset.h:78
BMS_Comparison
Definition bitmapset.h:61
@ BMS_DIFFERENT
Definition bitmapset.h:65
@ BMS_SUBSET1
Definition bitmapset.h:63
@ BMS_EQUAL
Definition bitmapset.h:62
@ BMS_SUBSET2
Definition bitmapset.h:64
BMS_Membership
Definition bitmapset.h:70
@ BMS_SINGLETON
Definition bitmapset.h:72
@ BMS_EMPTY_SET
Definition bitmapset.h:71
@ BMS_MULTIPLE
Definition bitmapset.h:73
uint32 bitmapword
Definition bitmapset.h:44
#define BITS_PER_BITMAPWORD
Definition bitmapset.h:43
#define bmw_popcount(w)
Definition bitmapset.h:80
#define Min(x, y)
Definition c.h:1131
#define Assert(condition)
Definition c.h:1002
int32_t int32
Definition c.h:679
#define unlikely(x)
Definition c.h:497
uint32_t uint32
Definition c.h:683
size_t Size
Definition c.h:748
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
static Datum hash_any(const unsigned char *k, int keylen)
Definition hashfn.h:31
static bool pg_add_s32_overflow(int32 a, int32 b, int32 *result)
Definition int.h:151
int b
Definition isn.c:74
int x
Definition isn.c:75
int a
Definition isn.c:73
int i
Definition isn.c:77
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1635
void pfree(void *pointer)
Definition mcxt.c:1619
void * palloc0(Size size)
Definition mcxt.c:1420
void * palloc(Size size)
Definition mcxt.c:1390
#define IsA(nodeptr, _type_)
Definition nodes.h:162
Datum lower(PG_FUNCTION_ARGS)
Datum upper(PG_FUNCTION_ARGS)
static uint64 pg_popcount(const char *buf, int bytes)
#define NIL
Definition pg_list.h:68
#define lfirst_int(lc)
Definition pg_list.h:173
static uint32 DatumGetUInt32(Datum X)
Definition postgres.h:222
char * c
static int fb(int x)
Definition pg_list.h:54

◆ BITNUM

#define BITNUM (   x)    ((x) % BITS_PER_BITMAPWORD)

Definition at line 49 of file bitmapset.c.

◆ HAS_MULTIPLE_ONES

#define HAS_MULTIPLE_ONES (   x)    ((bitmapword) RIGHTMOST_ONE(x) != (x))

Definition at line 73 of file bitmapset.c.

◆ RIGHTMOST_ONE

#define RIGHTMOST_ONE (   x)    ((signedbitmapword) (x) & -((signedbitmapword) (x)))

Definition at line 71 of file bitmapset.c.

◆ WORDNUM

#define WORDNUM (   x)    ((x) / BITS_PER_BITMAPWORD)

Definition at line 48 of file bitmapset.c.

Function Documentation

◆ bitmap_hash()

uint32 bitmap_hash ( const void key,
Size  keysize 
)

Definition at line 1559 of file bitmapset.c.

1560{
1561 Assert(keysize == sizeof(Bitmapset *));
1562 return bms_hash_value(*((const Bitmapset *const *) key));
1563}

References Assert, and bms_hash_value().

Referenced by build_join_rel_hash(), and test_bitmap_hash().

◆ bitmap_match()

int bitmap_match ( const void key1,
const void key2,
Size  keysize 
)

Definition at line 1569 of file bitmapset.c.

1570{
1571 Assert(keysize == sizeof(Bitmapset *));
1572 return !bms_equal(*((const Bitmapset *const *) key1),
1573 *((const Bitmapset *const *) key2));
1574}

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

Referenced by build_join_rel_hash(), and test_bitmap_match().

◆ bms_add_member()

Bitmapset * bms_add_member ( Bitmapset a,
int  x 
)

Definition at line 934 of file bitmapset.c.

935{
936 int wordnum,
937 bitnum;
938
940
941 if (x < 0)
942 elog(ERROR, "negative bitmapset member not allowed");
943 if (a == NULL)
944 return bms_make_singleton(x);
945
946 wordnum = WORDNUM(x);
947 bitnum = BITNUM(x);
948
949 /* enlarge the set if necessary */
950 if (wordnum >= a->nwords)
951 {
952 int oldnwords = a->nwords;
953 int i;
954
956 a->nwords = wordnum + 1;
957 /* zero out the enlarged portion */
958 i = oldnwords;
959 do
960 {
961 a->words[i] = 0;
962 } while (++i < a->nwords);
963 }
964
965 a->words[wordnum] |= ((bitmapword) 1 << bitnum);
966
967#ifdef REALLOCATE_BITMAPSETS
968
969 /*
970 * There's no guarantee that the repalloc returned a new pointer, so copy
971 * and free unconditionally here.
972 */
974#endif
975
976 return a;
977}

References a, Assert, BITMAPSET_SIZE, BITNUM, bms_make_singleton(), elog, ERROR, fb(), i, repalloc(), WORDNUM, and x.

Referenced by _readBitmapset(), add_child_eq_member(), add_outer_joins_to_relids(), add_row_identity_var(), add_rte_to_flat_rtable(), adjust_child_relids(), adjust_group_pathkeys_for_groupagg(), adjust_relid_set(), adjust_view_column_set(), alias_relid_set(), all_rows_selectable(), apply_handle_update(), build_joinrel_tlist(), build_subplan(), buildGroupedVar(), check_functional_grouping(), check_index_only(), checkInsertTargets(), classify_index_clause_usage(), clauselist_apply_dependencies(), convert_EXISTS_sublink_to_join(), create_lateral_join_info(), create_list_bounds(), CreatePartitionPruneState(), DecodeTextArrayToBitmapset(), deconstruct_distribute_oj_quals(), deconstruct_recurse(), deparseColumnRef(), dependencies_clauselist_selectivity(), DiscreteKnapsack(), DoCopy(), dropconstraint_internal(), estimate_multivariate_ndistinct(), EvalPlanQualBegin(), ExecAsyncAppendResponse(), ExecBuildUpdateProjection(), ExecCheckPermissions(), ExecInitAgg(), ExecInitAppend(), ExecInitGenerated(), ExecInitModifyTable(), ExecNestLoop(), ExecRecursiveUnion(), ExecReScanGather(), ExecReScanGatherMerge(), ExecReScanRecursiveUnion(), ExecReScanSetParamPlan(), ExecScanSubPlan(), execute_attr_map_cols(), expand_single_inheritance_child(), ExplainPreScanNode(), ExplainSubPlans(), extract_rollup_sets(), extractRemainingColumns(), fetch_remote_table_info(), fetch_statentries_for_relation(), finalize_plan(), finalize_primnode(), find_childrel_parents(), find_cols(), find_cols_walker(), find_hash_columns(), find_having_conflicts(), find_matching_subplans_recurse(), find_window_run_conditions(), findDefaultOnlyColumns(), fixup_inherited_columns(), fixup_whole_row_references(), func_get_detail(), gen_partprune_steps_internal(), generate_base_implied_equalities(), generate_query_for_graph_path(), get_baserel_parampathinfo(), get_dependent_generated_columns(), get_eclass_for_sort_expr(), get_matching_partitions(), get_nullingrels_recurse(), get_param_path_clause_serials(), get_primary_key_attnos(), get_relation_constraint_attnos(), get_relation_notnullatts(), get_relation_statistics(), get_relids_in_jointree(), HeapDetermineColumnsInfo(), infer_arbiter_indexes(), InitExecPartitionPruneContexts(), initialize_change_context(), is_var_needed_by_join(), join_is_removable(), load_enum_cache_data(), logicalrep_read_attrs(), logicalrep_rel_open(), make_datum_param(), make_modifytable(), make_outerjoininfo(), make_partition_pruneinfo(), make_partitionedrel_pruneinfo(), make_row_comparison_op(), make_window_input_target(), makeDependencyGraphWalker(), mark_rels_nulled_by_join(), mark_stmt(), markRelsAsNulledBy(), markRTEForSelectPriv(), mbms_add_member(), mbms_overlap_sets(), MergeAttributes(), nodeRead(), pgpa_filter_out_join_relids(), pgpa_plan_walker(), pgpa_planner_apply_join_path_advice(), pgpa_planner_apply_joinrel_advice(), pgpa_planner_apply_scan_advice(), pgpa_qf_add_rti(), pgpa_trove_add_to_hash(), pgpa_trove_slice_lookup(), pgpa_walker_join_order_matches_member(), pgpa_walker_would_advise(), plpgsql_mark_local_assignment_targets(), preprocess_grouping_sets(), pub_collist_to_bitmapset(), pub_collist_validate(), pub_form_cols_map(), pull_exec_paramids_walker(), pull_paramids_walker(), pull_up_sublinks_jointree_recurse(), pull_varattnos_walker(), pull_varnos_walker(), rebuild_joinclause_attr_needed(), reduce_outer_joins_pass2(), register_partpruneinfo(), RelationGetIdentityKeyBitmap(), RelationGetIndexAttrBitmap(), remove_leftjoinrel_from_query(), remove_rel_from_phvs(), remove_rel_from_query(), remove_self_join_rel(), remove_self_joins_one_group(), remove_self_joins_recurse(), remove_useless_groupby_columns(), remove_useless_results_recurse(), rewriteTargetListIU(), rewriteTargetView(), RI_Initial_Check(), set_join_column_names(), set_param_references(), SS_identify_outer_params(), standard_planner(), stat_covers_expressions(), statext_is_compatible_clause_internal(), statext_mcv_clauselist_selectivity(), test_bms_add_member(), test_random_offset_operations(), test_random_operations(), transformForPortionOfClause(), transformGroupClause(), transformGroupClauseList(), transformInsertStmt(), transformMergeStmt(), transformRangeTableFunc(), transformUpdateTargetList(), translate_col_privs(), try_partitionwise_join(), use_physical_tlist(), validate_va_cols_list(), and view_cols_are_auto_updatable().

◆ bms_add_members()

Bitmapset * bms_add_members ( Bitmapset a,
const Bitmapset b 
)

Definition at line 1036 of file bitmapset.c.

1037{
1039 const Bitmapset *other;
1040 int otherlen;
1041 int i;
1042
1045
1046 /* Handle cases where either input is NULL */
1047 if (a == NULL)
1048 return bms_copy(b);
1049 if (b == NULL)
1050 {
1051#ifdef REALLOCATE_BITMAPSETS
1053#endif
1054
1055 return a;
1056 }
1057 /* Identify shorter and longer input; copy the longer one if needed */
1058 if (a->nwords < b->nwords)
1059 {
1060 result = bms_copy(b);
1061 other = a;
1062 }
1063 else
1064 {
1065 result = a;
1066 other = b;
1067 }
1068 /* And union the shorter input into the result */
1069 otherlen = other->nwords;
1070 i = 0;
1071 do
1072 {
1073 result->words[i] |= other->words[i];
1074 } while (++i < otherlen);
1075 if (result != a)
1076 pfree(a);
1077#ifdef REALLOCATE_BITMAPSETS
1078 else
1080#endif
1081
1082 return result;
1083}

References a, Assert, b, bms_copy(), fb(), i, pfree(), and result.

Referenced by add_child_join_rel_equivalences(), add_child_rel_equivalences(), add_eq_member(), add_outer_joins_to_relids(), add_part_relids(), add_paths_to_joinrel(), add_placeholders_to_joinrel(), add_vars_to_attr_needed(), add_vars_to_targetlist(), adjust_appendrel_attrs_mutator(), adjust_standard_join_alias_expression(), build_index_paths(), choose_best_statistics(), choose_bitmap_and(), create_agg_clause_infos(), create_bitmap_and_path(), create_bitmap_or_path(), create_join_clause(), create_lateral_join_info(), CreatePartitionPruneState(), deconstruct_distribute(), deconstruct_recurse(), ExecDoInitialPruning(), ExecFindMatchingSubPlans(), ExecInitAgg(), expand_partitioned_rtentry(), ExplainPreScanNode(), finalize_plan(), find_nonnullable_rels_walker(), foreign_join_ok(), generate_union_paths(), get_eclass_indexes_for_relids(), get_param_path_clause_serials(), get_placeholder_nulling_relids(), heap_update(), join_is_legal(), make_outerjoininfo(), mbms_add_members(), perform_pruning_combine_step(), pgpa_build_scan(), pgpa_classify_alternative_subplans(), pgpa_process_unrolled_join(), pgpa_qf_add_rtis(), pull_varnos_walker(), pullup_replace_vars_callback(), reduce_outer_joins_pass1(), reduce_outer_joins_pass2(), remove_leftjoinrel_from_query(), remove_self_join_rel(), remove_self_joins_recurse(), test_bms_add_members(), transformOnConflictArbiter(), and try_partitionwise_join().

◆ bms_add_range()

Bitmapset * bms_add_range ( Bitmapset a,
int  lower,
int  upper 
)

Definition at line 1138 of file bitmapset.c.

1139{
1140 int lwordnum,
1141 lbitnum,
1142 uwordnum,
1143 ushiftbits,
1144 wordnum;
1145
1147
1148 /* do nothing if nothing is called for, without further checking */
1149 if (upper < lower)
1150 {
1151#ifdef REALLOCATE_BITMAPSETS
1153#endif
1154
1155 return a;
1156 }
1157
1158 if (lower < 0)
1159 elog(ERROR, "negative bitmapset member not allowed");
1161
1162 if (a == NULL)
1163 {
1165 a->type = T_Bitmapset;
1166 a->nwords = uwordnum + 1;
1167 }
1168 else if (uwordnum >= a->nwords)
1169 {
1170 int oldnwords = a->nwords;
1171 int i;
1172
1173 /* ensure we have enough words to store the upper bit */
1175 a->nwords = uwordnum + 1;
1176 /* zero out the enlarged portion */
1177 i = oldnwords;
1178 do
1179 {
1180 a->words[i] = 0;
1181 } while (++i < a->nwords);
1182 }
1183
1185
1186 lbitnum = BITNUM(lower);
1188
1189 /*
1190 * Special case when lwordnum is the same as uwordnum we must perform the
1191 * upper and lower masking on the word.
1192 */
1193 if (lwordnum == uwordnum)
1194 {
1195 a->words[lwordnum] |= ~(bitmapword) (((bitmapword) 1 << lbitnum) - 1)
1196 & (~(bitmapword) 0) >> ushiftbits;
1197 }
1198 else
1199 {
1200 /* turn on lbitnum and all bits left of it */
1201 a->words[wordnum++] |= ~(bitmapword) (((bitmapword) 1 << lbitnum) - 1);
1202
1203 /* turn on all bits for any intermediate words */
1204 while (wordnum < uwordnum)
1205 a->words[wordnum++] = ~(bitmapword) 0;
1206
1207 /* turn on upper's bit and all bits right of it. */
1208 a->words[uwordnum] |= (~(bitmapword) 0) >> ushiftbits;
1209 }
1210
1211#ifdef REALLOCATE_BITMAPSETS
1212
1213 /*
1214 * There's no guarantee that the repalloc returned a new pointer, so copy
1215 * and free unconditionally here.
1216 */
1218#endif
1219
1220 return a;
1221}

References a, Assert, BITMAPSET_SIZE, BITNUM, BITS_PER_BITMAPWORD, elog, ERROR, fb(), i, lower(), palloc0(), repalloc(), upper(), and WORDNUM.

Referenced by add_setop_child_rel_equivalences(), ComputePartitionAttrs(), DoCopy(), ExecInitAppend(), ExecInitMergeAppend(), ExecInitPartitionExecPruning(), get_matching_hash_bounds(), get_matching_list_bounds(), get_matching_partitions(), get_matching_range_bounds(), logicalrep_rel_open(), make_partition_pruneinfo(), perform_pruning_combine_step(), prune_append_rel_partitions(), test_bms_add_range(), and test_random_operations().

◆ bms_compare()

int bms_compare ( const Bitmapset a,
const Bitmapset b 
)

Definition at line 184 of file bitmapset.c.

185{
186 int i;
187
190
191 /* Handle cases where either input is NULL */
192 if (a == NULL)
193 return (b == NULL) ? 0 : -1;
194 else if (b == NULL)
195 return +1;
196
197 /* the set with the most words must be greater */
198 if (a->nwords != b->nwords)
199 return (a->nwords > b->nwords) ? +1 : -1;
200
201 i = a->nwords - 1;
202 do
203 {
204 bitmapword aw = a->words[i];
205 bitmapword bw = b->words[i];
206
207 if (aw != bw)
208 return (aw > bw) ? +1 : -1;
209 } while (--i >= 0);
210 return 0;
211}

References a, Assert, b, fb(), and i.

Referenced by append_startup_cost_compare(), append_total_cost_compare(), and test_bms_compare().

◆ bms_copy()

Bitmapset * bms_copy ( const Bitmapset a)

Definition at line 123 of file bitmapset.c.

124{
126 size_t size;
127
129
130 if (a == NULL)
131 return NULL;
132
133 size = BITMAPSET_SIZE(a->nwords);
134 result = (Bitmapset *) palloc(size);
135 memcpy(result, a, size);
136 return result;
137}

References a, Assert, BITMAPSET_SIZE, fb(), memcpy(), palloc(), and result.

Referenced by _copyBitmapset(), add_nullingrels_if_needed(), add_outer_joins_to_relids(), adjust_child_relids(), adjust_relid_set(), afterTriggerCopyBitmap(), bms_add_members(), bms_difference(), bms_intersect(), bms_replace_members(), bms_union(), build_child_join_rel(), build_index_paths(), build_join_rel(), build_simple_grouped_rel(), calc_nestloop_required_outer(), choose_bitmap_and(), create_lateral_join_info(), CreatePartitionPruneState(), deconstruct_distribute_oj_quals(), deconstruct_recurse(), DiscreteKnapsack(), distribute_qual_to_rels(), ExecFindMatchingSubPlans(), fetch_upper_rel(), finalize_plan(), finalize_primnode(), find_hash_columns(), find_placeholder_info(), fixup_whole_row_references(), get_join_domain_min_rels(), get_nullingrels_recurse(), get_param_path_clause_serials(), get_relation_statistics_worker(), InitPlan(), innerrel_is_unique_ext(), is_var_needed_by_join(), join_is_legal(), join_is_removable(), load_enum_cache_data(), logicalrep_partition_open(), logicalrep_relmap_update(), make_grouped_join_rel(), make_outerjoininfo(), make_partition_pruneinfo(), mark_nullable_by_grouping(), mark_stmt(), partition_bounds_copy(), perform_pruning_combine_step(), pgpa_process_unrolled_join(), reconsider_full_join_clause(), reconsider_outer_join_clause(), RelationGetIdentityKeyBitmap(), RelationGetIndexAttrBitmap(), remove_rel_from_eclass(), remove_rel_from_query(), remove_rel_from_restrictinfo(), reparameterize_path_by_child(), and test_bms_copy().

◆ bms_del_member()

Bitmapset * bms_del_member ( Bitmapset a,
int  x 
)

Definition at line 987 of file bitmapset.c.

988{
989 int wordnum,
990 bitnum;
991
993
994 if (x < 0)
995 elog(ERROR, "negative bitmapset member not allowed");
996 if (a == NULL)
997 return NULL;
998
999 wordnum = WORDNUM(x);
1000 bitnum = BITNUM(x);
1001
1002#ifdef REALLOCATE_BITMAPSETS
1004#endif
1005
1006 /* member can't exist. Return 'a' unmodified */
1007 if (unlikely(wordnum >= a->nwords))
1008 return a;
1009
1010 a->words[wordnum] &= ~((bitmapword) 1 << bitnum);
1011
1012 /* when last word becomes empty, trim off all trailing empty words */
1013 if (a->words[wordnum] == 0 && wordnum == a->nwords - 1)
1014 {
1015 /* find the last non-empty word and make that the new final word */
1016 for (int i = wordnum - 1; i >= 0; i--)
1017 {
1018 if (a->words[i] != 0)
1019 {
1020 a->nwords = i + 1;
1021 return a;
1022 }
1023 }
1024
1025 /* the set is now empty */
1026 pfree(a);
1027 return NULL;
1028 }
1029 return a;
1030}

References a, Assert, BITNUM, elog, ERROR, fb(), i, pfree(), unlikely, WORDNUM, and x.

Referenced by add_nullingrels_if_needed(), adjust_child_relids(), adjust_group_pathkeys_for_groupagg(), adjust_relid_set(), build_index_paths(), BuildParameterizedTidPaths(), ComputePartitionAttrs(), deconstruct_distribute_oj_quals(), dependencies_clauselist_selectivity(), DiscreteKnapsack(), DoCopy(), expand_partitioned_rtentry(), finalize_plan(), finalize_primnode(), find_hash_columns(), findDefaultOnlyColumns(), fixup_whole_row_references(), get_join_domain_min_rels(), get_matching_list_bounds(), logicalrep_rel_open(), make_outerjoininfo(), postgresGetForeignPaths(), preprocess_rowmarks(), remove_rel_from_eclass(), remove_rel_from_query(), remove_rel_from_restrictinfo(), remove_self_joins_recurse(), substitute_phv_relids_walker(), test_bms_del_member(), test_random_operations(), and TopologicalSort().

◆ bms_del_members()

Bitmapset * bms_del_members ( Bitmapset a,
const Bitmapset b 
)

Definition at line 1280 of file bitmapset.c.

1281{
1282 int i;
1283
1286
1287 /* Handle cases where either input is NULL */
1288 if (a == NULL)
1289 return NULL;
1290 if (b == NULL)
1291 {
1292#ifdef REALLOCATE_BITMAPSETS
1294#endif
1295
1296 return a;
1297 }
1298
1299 /* Remove b's bits from a; we need never copy */
1300 if (a->nwords > b->nwords)
1301 {
1302 /*
1303 * We'll never need to remove trailing zero words when 'a' has more
1304 * words than 'b'.
1305 */
1306 i = 0;
1307 do
1308 {
1309 a->words[i] &= ~b->words[i];
1310 } while (++i < b->nwords);
1311 }
1312 else
1313 {
1314 int lastnonzero = -1;
1315
1316 /* we may need to remove trailing zero words from the result. */
1317 i = 0;
1318 do
1319 {
1320 a->words[i] &= ~b->words[i];
1321
1322 /* remember the last non-zero word */
1323 if (a->words[i] != 0)
1324 lastnonzero = i;
1325 } while (++i < a->nwords);
1326
1327 /* check if 'a' has become empty */
1328 if (lastnonzero == -1)
1329 {
1330 pfree(a);
1331 return NULL;
1332 }
1333
1334 /* trim off any trailing zero words */
1335 a->nwords = lastnonzero + 1;
1336 }
1337
1338#ifdef REALLOCATE_BITMAPSETS
1340#endif
1341
1342 return a;
1343}

References a, Assert, b, fb(), i, and pfree().

Referenced by adjust_group_pathkeys_for_groupagg(), build_join_rel(), calc_nestloop_required_outer(), check_index_predicates(), classify_matching_subplans(), finalize_plan(), get_join_domain_min_rels(), get_placeholder_nulling_relids(), make_outerjoininfo(), make_partition_pruneinfo(), min_join_parameterization(), NumRelids(), pullup_replace_vars_callback(), remove_self_joins_recurse(), and test_bms_del_members().

◆ bms_difference()

Bitmapset * bms_difference ( const Bitmapset a,
const Bitmapset b 
)

Definition at line 347 of file bitmapset.c.

348{
350 int i;
351
354
355 /* Handle cases where either input is NULL */
356 if (a == NULL)
357 return NULL;
358 if (b == NULL)
359 return bms_copy(a);
360
361 /*
362 * In Postgres' usage, an empty result is a very common case, so it's
363 * worth optimizing for that by testing bms_nonempty_difference(). This
364 * saves us a palloc/pfree cycle compared to checking after-the-fact.
365 */
367 return NULL;
368
369 /* Copy the left input */
370 result = bms_copy(a);
371
372 /* And remove b's bits from result */
373 if (result->nwords > b->nwords)
374 {
375 /*
376 * We'll never need to remove trailing zero words when 'a' has more
377 * words than 'b' as the additional words must be non-zero.
378 */
379 i = 0;
380 do
381 {
382 result->words[i] &= ~b->words[i];
383 } while (++i < b->nwords);
384 }
385 else
386 {
387 int lastnonzero = -1;
388
389 /* we may need to remove trailing zero words from the result. */
390 i = 0;
391 do
392 {
393 result->words[i] &= ~b->words[i];
394
395 /* remember the last non-zero word */
396 if (result->words[i] != 0)
397 lastnonzero = i;
398 } while (++i < result->nwords);
399
400 /* trim off trailing zero words */
401 result->nwords = lastnonzero + 1;
402 }
403 Assert(result->nwords != 0);
404
405 /* Need not check for empty result, since we handled that case above */
406 return result;
407}

References a, Assert, b, bms_copy(), bms_nonempty_difference(), fb(), i, and result.

Referenced by add_child_join_rel_equivalences(), add_child_rel_equivalences(), add_paths_to_joinrel(), check_index_predicates(), consider_new_or_clause(), create_foreignscan_plan(), create_hashjoin_plan(), create_mergejoin_plan(), create_nestloop_plan(), examine_variable(), finalize_plan(), find_placeholder_info(), make_plain_restrictinfo(), pull_varnos_walker(), remove_nulling_relids_mutator(), remove_rel_from_phvs_mutator(), remove_rel_from_query(), remove_useless_groupby_columns(), standard_planner(), and test_bms_difference().

◆ bms_equal()

bool bms_equal ( const Bitmapset a,
const Bitmapset b 
)

Definition at line 143 of file bitmapset.c.

144{
145 int i;
146
149
150 /* Handle cases where either input is NULL */
151 if (a == NULL)
152 {
153 if (b == NULL)
154 return true;
155 return false;
156 }
157 else if (b == NULL)
158 return false;
159
160 /* can't be equal if the word counts don't match */
161 if (a->nwords != b->nwords)
162 return false;
163
164 /* check each word matches */
165 i = 0;
166 do
167 {
168 if (a->words[i] != b->words[i])
169 return false;
170 } while (++i < a->nwords);
171
172 return true;
173}

References a, Assert, b, fb(), and i.

Referenced by _equalBitmapset(), add_non_redundant_clauses(), add_path_precheck(), add_paths_to_append_rel(), afterTriggerAddEvent(), AlterPublicationTables(), assign_param_for_var(), bitmap_match(), choose_bitmap_and(), create_append_path(), create_merge_append_path(), create_unique_paths(), deconstruct_distribute_oj_quals(), deconstruct_jointree(), ExecInitPartitionExecPruning(), extract_lateral_vars_from_PHVs(), extract_rollup_sets(), fetch_upper_rel(), find_dependent_phvs_walker(), find_join_rel(), find_param_path_info(), generate_grouped_paths(), generate_implied_equalities_for_column(), generate_partitionwise_join_paths(), get_cheapest_parameterized_child_path(), get_eclass_for_sort_expr(), get_join_domain_min_rels(), has_join_restriction(), infer_arbiter_indexes(), innerrel_is_unique_ext(), is_safe_restriction_clause_for(), join_is_legal(), make_grouped_join_rel(), make_one_rel(), make_partitionedrel_pruneinfo(), mark_nullable_by_grouping(), match_pathkeys_to_index(), merge_clump(), pgoutput_column_list_init(), pgpa_walker_contains_feature(), pgpa_walker_contains_join(), pgpa_walker_find_scan(), pgpa_walker_join_order_matches_member(), populate_joinrel_with_paths(), pull_varnos_walker(), search_indexed_tlist_for_phv(), search_indexed_tlist_for_var(), set_rel_pathlist(), standard_join_search(), test_bms_equal(), test_random_offset_operations(), and try_partitionwise_join().

◆ bms_free()

◆ bms_get_singleton_member()

bool bms_get_singleton_member ( const Bitmapset a,
int member 
)

Definition at line 843 of file bitmapset.c.

844{
845 int result = -1;
846 int nwords;
847 int wordnum;
848
850
851 if (a == NULL)
852 return false;
853
854 nwords = a->nwords;
855 wordnum = 0;
856 do
857 {
858 bitmapword w = a->words[wordnum];
859
860 if (w != 0)
861 {
862 if (result >= 0 || HAS_MULTIPLE_ONES(w))
863 return false;
866 }
867 } while (++wordnum < nwords);
868
869 /* we don't expect non-NULL sets to be empty */
870 Assert(result >= 0);
871 *member = result;
872 return true;
873}

References a, Assert, BITS_PER_BITMAPWORD, bmw_rightmost_one_pos, fb(), HAS_MULTIPLE_ONES, and result.

Referenced by add_placeholders_to_base_rels(), create_lateral_join_info(), distribute_restrictinfo_to_rels(), estimate_multivariate_bucketsize(), examine_variable(), find_join_input_rel(), find_single_rel_for_clauses(), generate_base_implied_equalities_no_const(), get_common_eclass_indexes(), join_is_removable(), reduce_unique_semijoins(), replace_relid_callback(), set_base_rel_consider_startup(), statext_is_compatible_clause(), and test_bms_get_singleton_member().

◆ bms_hash_value()

uint32 bms_hash_value ( const Bitmapset a)

Definition at line 1543 of file bitmapset.c.

1544{
1546
1547 if (a == NULL)
1548 return 0; /* All empty sets hash to 0 */
1549 return DatumGetUInt32(hash_any((const unsigned char *) a->words,
1550 a->nwords * sizeof(bitmapword)));
1551}

References a, Assert, DatumGetUInt32(), fb(), and hash_any().

Referenced by bitmap_hash(), and test_bms_hash_value().

◆ bms_int_members()

Bitmapset * bms_int_members ( Bitmapset a,
const Bitmapset b 
)

Definition at line 1228 of file bitmapset.c.

1229{
1230 int lastnonzero;
1231 int shortlen;
1232 int i;
1233
1236
1237 /* Handle cases where either input is NULL */
1238 if (a == NULL)
1239 return NULL;
1240 if (b == NULL)
1241 {
1242 pfree(a);
1243 return NULL;
1244 }
1245
1246 /* Intersect b into a; we need never copy */
1247 shortlen = Min(a->nwords, b->nwords);
1248 lastnonzero = -1;
1249 i = 0;
1250 do
1251 {
1252 a->words[i] &= b->words[i];
1253
1254 if (a->words[i] != 0)
1255 lastnonzero = i;
1256 } while (++i < shortlen);
1257
1258 /* If we computed an empty result, we must return NULL */
1259 if (lastnonzero == -1)
1260 {
1261 pfree(a);
1262 return NULL;
1263 }
1264
1265 /* get rid of trailing zero words */
1266 a->nwords = lastnonzero + 1;
1267
1268#ifdef REALLOCATE_BITMAPSETS
1270#endif
1271
1272 return a;
1273}

References a, Assert, b, fb(), i, Min, and pfree().

Referenced by find_nonnullable_rels_walker(), find_placeholder_info(), get_common_eclass_indexes(), get_param_path_clause_serials(), make_outerjoininfo(), make_row_comparison_op(), mbms_int_members(), perform_pruning_combine_step(), relation_is_updatable(), and test_bms_int_members().

◆ bms_intersect()

Bitmapset * bms_intersect ( const Bitmapset a,
const Bitmapset b 
)

Definition at line 293 of file bitmapset.c.

294{
296 const Bitmapset *other;
297 int lastnonzero;
298 int resultlen;
299 int i;
300
303
304 /* Handle cases where either input is NULL */
305 if (a == NULL || b == NULL)
306 return NULL;
307
308 /* Identify shorter and longer input; copy the shorter one */
309 if (a->nwords <= b->nwords)
310 {
311 result = bms_copy(a);
312 other = b;
313 }
314 else
315 {
316 result = bms_copy(b);
317 other = a;
318 }
319 /* And intersect the longer input with the result */
320 resultlen = result->nwords;
321 lastnonzero = -1;
322 i = 0;
323 do
324 {
325 result->words[i] &= other->words[i];
326
327 if (result->words[i] != 0)
328 lastnonzero = i;
329 } while (++i < resultlen);
330 /* If we computed an empty result, we must return NULL */
331 if (lastnonzero == -1)
332 {
333 pfree(result);
334 return NULL;
335 }
336
337 /* get rid of trailing zero words */
338 result->nwords = lastnonzero + 1;
339 return result;
340}

References a, Assert, b, bms_copy(), fb(), i, pfree(), and result.

Referenced by build_joinrel_tlist(), classify_matching_subplans(), create_lateral_join_info(), distribute_qual_to_rels(), find_dependent_phvs_walker(), find_em_for_rel(), get_matching_part_pairs(), identify_current_nestloop_params(), make_outerjoininfo(), match_eclasses_to_foreign_key_col(), pullup_replace_vars_callback(), rebuild_joinclause_attr_needed(), set_param_references(), test_bms_intersect(), test_random_operations(), and UpdateChangedParamSet().

◆ bms_is_member()

bool bms_is_member ( int  x,
const Bitmapset a 
)

Definition at line 645 of file bitmapset.c.

646{
647 int wordnum,
648 bitnum;
649
651
652 /* XXX better to just return false for x<0 ? */
653 if (x < 0)
654 elog(ERROR, "negative bitmapset member not allowed");
655 if (a == NULL)
656 return false;
657
658 wordnum = WORDNUM(x);
659 bitnum = BITNUM(x);
660 if (wordnum >= a->nwords)
661 return false;
662 if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
663 return true;
664 return false;
665}

References a, Assert, BITNUM, elog, ERROR, fb(), WORDNUM, and x.

Referenced by add_non_redundant_clauses(), add_nulling_relids_mutator(), add_outer_joins_to_relids(), add_row_identity_var(), adjust_appendrel_attrs_mutator(), adjust_child_relids(), adjust_relid_set(), adjust_rowcount_for_semijoins(), bms_member_index(), build_joinrel_tlist(), check_index_predicates(), check_redundant_nullability_qual(), check_relation_privileges(), checkInsertTargets(), clause_selectivity_ext(), clauselist_selectivity_ext(), clauselist_selectivity_or(), ComputePartitionAttrs(), consider_groupingsets_paths(), contain_invalid_rfcolumn_walker(), contain_placeholder_references_walker(), cost_incremental_sort(), create_foreignscan_plan(), create_lateral_join_info(), create_nestloop_path(), createTableConstraints(), deconstruct_distribute_oj_quals(), DefineIndex(), deparseFromExprForRel(), deparseLockingClause(), deparseRangeTblRef(), deparseTargetList(), deparseVar(), dependencies_clauselist_selectivity(), dependency_is_fully_matched(), DoCopy(), dropconstraint_internal(), enum_known_sorted(), estimate_multivariate_ndistinct(), examine_variable(), ExecBuildSlotValueDescription(), ExecBuildUpdateProjection(), ExecCheckPermissions(), ExecEvalGroupingFunc(), ExecGetRangeTableRelation(), ExecInitLockRows(), ExecInitModifyTable(), ExecRelationIsTargetRelation(), ExecScanFetch(), execute_attr_map_cols(), expand_indexqual_rowcompare(), expand_single_inheritance_child(), ExplainSubPlans(), extract_lateral_vars_from_PHVs(), extractRemainingColumns(), ExtractReplicaIdentity(), fetch_remote_table_info(), filter_event_trigger(), find_hash_columns(), find_modifytable_subplan(), fixup_whole_row_references(), foreign_expr_walker(), func_get_detail(), gen_partprune_steps_internal(), gen_prune_steps_from_opexps(), generate_base_implied_equalities(), get_eclass_for_sort_expr(), get_eclass_indexes_for_relids(), get_expression_sortgroupref(), get_foreign_key_join_selectivity(), get_join_domain_min_rels(), get_matching_hash_bounds(), get_memoize_path(), get_placeholder_nulling_relids(), get_translated_update_targetlist(), get_variable(), get_xmltable(), group_similar_or_args(), has_notnull_forced_var(), has_partition_attrs(), hashagg_spill_tuple(), HeapDetermineColumnsInfo(), identify_current_nestloop_params(), index_expression_changed_walker(), index_unchanged_by_update(), InitPartitionPruneContext(), InitPlan(), is_foreign_param(), is_pseudo_constant_for_index(), is_subquery_var(), is_var_in_aggref_only(), IsBinaryTidClause(), isPlainForeignVar(), IsTidEqualAnyClause(), join_clause_is_movable_to(), join_is_removable(), lo_manage(), logicalrep_rel_mark_updatable(), logicalrep_should_publish_column(), logicalrep_write_attrs(), make_outerjoininfo(), make_window_input_target(), mark_expr(), mark_invalid_subplans_as_finished(), mark_rels_nulled_by_join(), match_opclause_to_indexcol(), match_orclause_to_indexcol(), match_rowcompare_to_indexcol(), match_saopclause_to_indexcol(), mbms_is_member(), MergeAttributes(), partitions_are_ordered(), perform_pruning_base_step(), pgpa_classify_alternative_subplans(), plpgsql_param_fetch(), postgresExplainForeignScan(), prepare_projection_slot(), preprocess_rowmarks(), process_subquery_nestloop_params(), pub_collist_validate(), pub_contains_invalid_column(), pullup_replace_vars_callback(), rangeTableEntry_used_walker(), rebuild_joinclause_attr_needed(), RememberWholeRowDependentForRebuilding(), remove_leftjoinrel_from_query(), remove_nulling_relids_mutator(), remove_rel_from_eclass(), remove_rel_from_query(), remove_self_join_rel(), remove_self_joins_one_group(), remove_self_joins_recurse(), remove_unused_subquery_outputs(), remove_useless_groupby_columns(), replace_nestloop_params_mutator(), replace_relid_callback(), rewriteTargetListIU(), rewriteValuesRTE(), ScanRelIsReadOnly(), semijoin_target_ok(), set_join_column_names(), set_rtable_names(), show_modifytable_info(), statext_mcv_clauselist_selectivity(), subquery_planner(), substitute_phv_relids_walker(), test_bms_is_member(), test_random_operations(), tfuncLoadRows(), transformGroupClauseExpr(), translate_col_privs(), TriggerEnabled(), try_hashjoin_path(), try_mergejoin_path(), try_nestloop_path(), tsvector_update_trigger(), tuples_equal(), update_eclasses(), use_physical_tlist(), validate_va_cols_list(), var_is_nonnullable(), and view_cols_are_auto_updatable().

◆ bms_is_subset()

bool bms_is_subset ( const Bitmapset a,
const Bitmapset b 
)

Definition at line 547 of file bitmapset.c.

548{
549 int i;
550
553
554 /* Handle cases where either input is NULL */
555 if (a == NULL)
556 return true; /* empty set is a subset of anything */
557 if (b == NULL)
558 return false;
559
560 /* 'a' can't be a subset of 'b' if it contains more words */
561 if (a->nwords > b->nwords)
562 return false;
563
564 /* Check all 'a' members are set in 'b' */
565 i = 0;
566 do
567 {
568 if ((a->words[i] & ~b->words[i]) != 0)
569 return false;
570 } while (++i < a->nwords);
571 return true;
572}

References a, Assert, b, fb(), and i.

Referenced by add_child_rel_equivalences(), add_outer_joins_to_relids(), add_paths_to_joinrel(), add_placeholders_to_joinrel(), add_vars_to_attr_needed(), add_vars_to_targetlist(), build_joinrel_tlist(), check_functional_grouping(), check_index_only(), choose_best_statistics(), clause_sides_match_join(), compute_semijoin_info(), convert_ANY_sublink_to_join(), convert_EXISTS_sublink_to_join(), create_agg_clause_infos(), create_index_paths(), distribute_qual_to_rels(), eager_aggregation_possible_for_relation(), eclass_already_used(), eclass_useful_for_merging(), extract_lateral_vars_from_PHVs(), extract_rollup_sets(), final_cost_hashjoin(), finalize_plan(), find_computable_ec_member(), find_ec_member_matching_expr(), find_em_for_rel(), find_join_domain(), foreign_join_ok(), generate_implied_equalities_for_column(), generate_join_implied_equalities_broken(), generate_join_implied_equalities_normal(), get_appendrel_parampathinfo(), get_baserel_parampathinfo(), get_cheapest_fractional_path_for_pathkeys(), get_cheapest_parameterized_child_path(), get_cheapest_path_for_pathkeys(), get_join_index_paths(), get_join_variables(), get_joinrel_parampathinfo(), get_switched_clauses(), has_join_restriction(), has_relevant_eclass_joinclause(), have_join_order_restriction(), have_partkey_equi_join(), identify_current_nestloop_params(), initial_cost_mergejoin(), innerrel_is_unique_ext(), is_simple_subquery(), join_clause_is_movable_into(), join_is_legal(), join_is_removable(), jointree_contains_lateral_outer_refs(), make_grouped_join_rel(), make_outerjoininfo(), pg_get_expr_worker(), pgpa_walker_contains_no_gather(), populate_joinrel_with_paths(), process_implied_equality(), process_subquery_nestloop_params(), pullup_replace_vars_callback(), remove_rel_from_query(), reparameterize_path(), replace_nestloop_params_mutator(), search_indexed_tlist_for_phv(), search_indexed_tlist_for_var(), statext_mcv_clauselist_selectivity(), subbuild_joinrel_joinlist(), subbuild_joinrel_restrictlist(), test_bms_is_subset(), try_partial_nestloop_path(), and use_physical_tlist().

◆ bms_join()

Bitmapset * bms_join ( Bitmapset a,
Bitmapset b 
)

Definition at line 1349 of file bitmapset.c.

1350{
1353 int otherlen;
1354 int i;
1355
1358
1359 /* Handle cases where either input is NULL */
1360 if (a == NULL)
1361 {
1362#ifdef REALLOCATE_BITMAPSETS
1364#endif
1365
1366 return b;
1367 }
1368 if (b == NULL)
1369 {
1370#ifdef REALLOCATE_BITMAPSETS
1372#endif
1373
1374 return a;
1375 }
1376
1377 /* Identify shorter and longer input; use longer one as result */
1378 if (a->nwords < b->nwords)
1379 {
1380 result = b;
1381 other = a;
1382 }
1383 else
1384 {
1385 result = a;
1386 other = b;
1387 }
1388 /* And union the shorter input into the result */
1389 otherlen = other->nwords;
1390 i = 0;
1391 do
1392 {
1393 result->words[i] |= other->words[i];
1394 } while (++i < otherlen);
1395 if (other != result) /* pure paranoia */
1396 pfree(other);
1397
1398#ifdef REALLOCATE_BITMAPSETS
1400#endif
1401
1402 return result;
1403}

References a, Assert, b, fb(), i, pfree(), and result.

Referenced by add_paths_to_joinrel(), alias_relid_set(), build_joinrel_tlist(), finalize_primnode(), find_nonnullable_rels_walker(), get_partkey_exec_paramids(), get_relids_in_jointree(), make_partition_pruneinfo(), process_equivalence(), pull_up_sublinks_jointree_recurse(), pull_varnos_walker(), test_bms_join(), and UpdateChangedParamSet().

◆ bms_make_singleton()

Bitmapset * bms_make_singleton ( int  x)

Definition at line 217 of file bitmapset.c.

218{
220 int wordnum,
221 bitnum;
222
223 if (x < 0)
224 elog(ERROR, "negative bitmapset member not allowed");
225 wordnum = WORDNUM(x);
226 bitnum = BITNUM(x);
228 result->type = T_Bitmapset;
229 result->nwords = wordnum + 1;
230 result->words[wordnum] = ((bitmapword) 1 << bitnum);
231 return result;
232}

References BITMAPSET_SIZE, BITNUM, elog, ERROR, fb(), palloc0(), result, WORDNUM, and x.

Referenced by add_row_identity_var(), ATExecDropColumn(), ATPrepAlterColumnType(), bms_add_member(), build_base_rel_tlists(), build_simple_rel(), CopyFrom(), create_edata_for_relation(), create_estate_for_relation(), deconstruct_distribute_oj_quals(), deconstruct_recurse(), deparseReturningList(), DiscreteKnapsack(), examine_simple_variable(), expand_inherited_rtentry(), extract_lateral_references(), find_dependent_phvs(), find_dependent_phvs_in_jointree(), find_nonnullable_rels_walker(), get_matching_hash_bounds(), get_matching_list_bounds(), get_matching_range_bounds(), get_relids_in_jointree(), initialize_change_context(), load_enum_cache_data(), make_group_input_target(), make_pathkeys_for_sortclauses_extended(), mark_nullable_by_grouping(), pg_column_is_updatable(), pg_get_expr_worker(), pgpa_build_scan(), pgpa_walker_join_order_matches_member(), pgpa_walker_would_advise(), pull_up_sublinks_jointree_recurse(), pullup_replace_vars_callback(), rebuild_lateral_attr_needed(), reconsider_full_join_clause(), reduce_outer_joins(), reduce_outer_joins_pass1(), remove_rel_from_phvs(), remove_rel_from_query(), rewriteTargetView(), set_subqueryscan_references(), set_upper_references(), split_pathtarget_walker(), subquery_planner(), test_bms_make_singleton(), and transform_MERGE_to_join().

◆ bms_member_index()

int bms_member_index ( Bitmapset a,
int  x 
)

Definition at line 674 of file bitmapset.c.

675{
676 int bitnum;
677 int wordnum;
678 int result = 0;
679 bitmapword mask;
680
682
683 /* return -1 if not a member of the bitmap */
684 if (!bms_is_member(x, a))
685 return -1;
686
687 wordnum = WORDNUM(x);
688 bitnum = BITNUM(x);
689
690 /* count bits in preceding words */
691 result += pg_popcount((const char *) a->words,
692 wordnum * sizeof(bitmapword));
693
694 /*
695 * Now add bits of the last word, but only those before the item. We can
696 * do that by applying a mask and then using popcount again. To get
697 * 0-based index, we want to count only preceding bits, not the item
698 * itself, so we subtract 1.
699 */
700 mask = ((bitmapword) 1 << bitnum) - 1;
701 result += bmw_popcount(a->words[wordnum] & mask);
702
703 return result;
704}

References a, Assert, BITNUM, bms_is_member(), bmw_popcount, fb(), pg_popcount(), result, WORDNUM, and x.

Referenced by clauselist_apply_dependencies(), mcv_get_match_bitmap(), mcv_match_expression(), and test_bms_member_index().

◆ bms_membership()

BMS_Membership bms_membership ( const Bitmapset a)

Definition at line 900 of file bitmapset.c.

901{
903 int nwords;
904 int wordnum;
905
907
908 if (a == NULL)
909 return BMS_EMPTY_SET;
910
911 nwords = a->nwords;
912 wordnum = 0;
913 do
914 {
915 bitmapword w = a->words[wordnum];
916
917 if (w != 0)
918 {
920 return BMS_MULTIPLE;
922 }
923 } while (++wordnum < nwords);
924 return result;
925}

References a, Assert, BMS_EMPTY_SET, BMS_MULTIPLE, BMS_SINGLETON, fb(), HAS_MULTIPLE_ONES, and result.

Referenced by add_base_clause_to_rel(), add_child_join_rel_equivalences(), deparseFromExpr(), deparseLockingClause(), deparseVar(), dependencies_clauselist_selectivity(), dependency_is_compatible_clause(), dependency_is_compatible_expression(), distribute_qual_to_rels(), extract_lateral_vars_from_PHVs(), find_nonnullable_rels_walker(), generate_base_implied_equalities(), generate_base_implied_equalities_broken(), get_foreign_key_join_selectivity(), grouping_planner(), overexplain_bitmapset_list(), pgpa_build_scan(), pgpa_join_path_setup(), pgpa_joinrel_setup(), pgpa_output_join_member(), pgpa_output_query_feature(), pgpa_output_scan_strategy(), pgpa_output_simple_strategy(), process_implied_equality(), rebuild_joinclause_attr_needed(), relation_has_unique_index_for(), remove_self_join_rel(), remove_self_joins_recurse(), remove_useless_groupby_columns(), replace_relid_callback(), set_subquery_pathlist(), set_tablesample_rel_pathlist(), setup_eager_aggregation(), split_selfjoin_quals(), statext_mcv_clauselist_selectivity(), and test_bms_membership().

◆ bms_next_member()

int bms_next_member ( const Bitmapset a,
int  prevbit 
)

Definition at line 1425 of file bitmapset.c.

1426{
1427 unsigned int currbit = prevbit;
1428 int nwords;
1429 bitmapword mask;
1430
1432
1433 if (a == NULL)
1434 return -2;
1435 nwords = a->nwords;
1436
1437 /* use an unsigned int to avoid the risk that int overflows */
1438 currbit++;
1439 mask = (~(bitmapword) 0) << BITNUM(currbit);
1440 for (int wordnum = WORDNUM(currbit); wordnum < nwords; wordnum++)
1441 {
1442 bitmapword w = a->words[wordnum];
1443
1444 /* ignore bits before currbit */
1445 w &= mask;
1446
1447 if (w != 0)
1448 {
1449 int result;
1450
1453 return result;
1454 }
1455
1456 /* in subsequent words, consider all bits */
1457 mask = (~(bitmapword) 0);
1458 }
1459 return -2;
1460}

References a, Assert, BITNUM, BITS_PER_BITMAPWORD, bmw_rightmost_one_pos, fb(), result, and WORDNUM.

Referenced by add_child_join_rel_equivalences(), add_child_rel_equivalences(), add_join_clause_to_rels(), add_part_relids(), adjust_group_pathkeys_for_groupagg(), adjust_view_column_set(), alias_relid_set(), all_rows_selectable(), apply_scanjoin_target_to_paths(), approximate_joinrel_size(), attnumstoint2vector(), build_attnums_array(), check_relation_privileges(), check_selective_binary_conversion(), choose_next_subplan_for_worker(), choose_next_subplan_locally(), clauselist_apply_dependencies(), ComputePartitionAttrs(), convert_EXISTS_sublink_to_join(), create_lateral_join_info(), create_partitionwise_grouping_paths(), CreatePartitionPruneState(), CreateStatistics(), DefineIndex(), deparseLockingClause(), dependencies_clauselist_selectivity(), DoCopy(), eager_aggregation_possible_for_relation(), eclass_member_iterator_next(), EstimateParamExecSpace(), ExecAppendAsyncBegin(), ExecAppendAsyncEventWait(), ExecAppendAsyncRequest(), ExecCheckOneRelPerms(), ExecCheckPermissionsModified(), ExecInitAgg(), ExecInitAppend(), ExecInitMergeAppend(), ExecMergeAppend(), ExecReScanAppend(), ExecScanReScan(), ExecSetParamPlanMulti(), expand_partitioned_rtentry(), find_appinfos_by_relids(), find_dependent_phvs_in_jointree(), find_hash_columns(), find_matching_subplans_recurse(), fixup_inherited_columns(), format_expr_params(), generate_base_implied_equalities(), generate_implied_equalities_for_column(), generate_join_implied_equalities(), get_eclass_for_sort_expr(), get_eclass_indexes_for_relids(), get_loop_count(), get_matching_partitions(), get_placeholder_nulling_relids(), grouping_planner(), has_notnull_forced_var(), has_relevant_eclass_joinclause(), have_relevant_eclass_joinclause(), HeapDetermineColumnsInfo(), InitExecPartitionPruneContexts(), logicalrep_get_attrs_str(), logicalrep_rel_mark_updatable(), lookup_var_attr_stats(), make_build_data(), make_partitionedrel_pruneinfo(), make_row_comparison_op(), mark_rels_nulled_by_join(), match_eclasses_to_foreign_key_col(), outBitmapset(), overexplain_bitmapset(), overexplain_bitmapset_list(), pgpa_bms_to_cstring(), pgpa_compute_identifiers_by_relids(), pgpa_filter_out_join_relids(), pgpa_output_relations(), pgpa_plan_walker(), pgpa_planner_apply_join_path_advice(), pgpa_planner_apply_joinrel_advice(), pgpa_planner_apply_scan_advice(), pgpa_trove_set_flags(), pgpa_trove_slice_lookup(), postgresBeginForeignScan(), postgresExplainForeignScan(), postgresPlanForeignModify(), pub_contains_invalid_column(), publication_add_relation(), pullup_replace_vars_callback(), remove_join_clause_from_rels(), remove_self_join_rel(), remove_self_joins_one_group(), remove_self_joins_recurse(), remove_useless_results_recurse(), remove_useless_self_joins(), SerializeParamExecParams(), show_result_replacement_info(), test_bms_next_member(), test_random_offset_operations(), test_random_operations(), and unique_nonjoin_rtekind().

◆ bms_nonempty_difference()

bool bms_nonempty_difference ( const Bitmapset a,
const Bitmapset b 
)

Definition at line 769 of file bitmapset.c.

770{
771 int i;
772
775
776 /* Handle cases where either input is NULL */
777 if (a == NULL)
778 return false;
779 if (b == NULL)
780 return true;
781 /* if 'a' has more words then it must contain additional members */
782 if (a->nwords > b->nwords)
783 return true;
784 /* Check all 'a' members are set in 'b' */
785 i = 0;
786 do
787 {
788 if ((a->words[i] & ~b->words[i]) != 0)
789 return true;
790 } while (++i < a->nwords);
791 return false;
792}

References a, Assert, b, fb(), and i.

Referenced by add_placeholders_to_base_rels(), add_placeholders_to_joinrel(), allow_star_schema_join(), bms_difference(), build_joinrel_tlist(), ExecReScanMemoize(), foreign_join_ok(), is_var_needed_by_join(), test_bms_nonempty_difference(), and use_physical_tlist().

◆ bms_num_members()

◆ bms_offset_members()

Bitmapset * bms_offset_members ( const Bitmapset a,
int  offset 
)

Definition at line 419 of file bitmapset.c.

420{
422 int offset_words;
423 int offset_bits;
424 int new_nwords;
425 int old_nwords;
427 int old_highest;
428 int new_highest;
429
431
432 /* nothing to do for empty sets */
433 if (a == NULL)
434 return NULL;
435
436 old_nwords = a->nwords;
437 offset_words = WORDNUM(offset);
438 offset_bits = BITNUM(offset);
439 high_bit = bmw_leftmost_one_pos(a->words[a->nwords - 1]);
441
442 /* don't create a set with a member that doesn't fit into an int32 */
444 elog(ERROR, "bitmapset overflow");
445 /* return NULL if the new set would be empty */
446 else if (new_highest < 0)
447 return NULL;
448
451 result->type = T_Bitmapset;
452 result->nwords = new_nwords;
453
454 /* handle zero and positive offsets (bitshift left) */
455 if (offset >= 0)
456 {
457 /*
458 * We special-case offsetting only by whole words, so we don't have to
459 * special-case bitshifting by BITS_PER_BITMAPWORD places, which has
460 * an undefined behavior.
461 */
462 if (offset_bits == 0)
463 {
464 int i = 0;
465
466 /*
467 * The old set is guaranteed to have at least 1 word, so use
468 * do/while to save the redundant initial loop bounds check.
469 */
470 do
471 {
473 result->words[i + offset_words] = a->words[i];
474 } while (++i < old_nwords);
475 }
476 else
477 {
480 int i = 0;
481
482 do
483 {
484 bitmapword carry = (a->words[i] >> carry_bits);
485
487 /* shift bits up and carry bits from the previous word */
488 result->words[i + offset_words] = (a->words[i] << offset_bits) | prev_carry;
490 } while (++i < old_nwords);
491 result->words[new_nwords - 1] |= prev_carry;
492 }
493 }
494
495 /* handle negative offset (bitshift right) */
496 else
497 {
498 /* make the negative offset_words and offset_bits positive */
501
502 /* as above, special case shifting only by whole words */
503 if (offset_bits == 0)
504 {
505 int i = 0;
506
507 do
508 {
510 result->words[i] = a->words[i + offset_words];
511 } while (++i < new_nwords);
512 }
513 else
514 {
517 int i = new_nwords - 1;
518
519 /* carry bits from any word just above where the loop starts */
522
523 /*
524 * We loop backward over the array so we correctly carry bits from
525 * higher words.
526 */
527 do
528 {
529 bitmapword carry = (a->words[i + offset_words] << carry_bits);
530
532
533 /* shift bits down and carry bits from the previous word */
534 result->words[i] = (a->words[i + offset_words] >> offset_bits) | prev_carry;
536 } while (--i >= 0);
537 }
538 }
539
540 return result;
541}

References a, Assert, BITMAPSET_SIZE, BITNUM, BITS_PER_BITMAPWORD, bmw_leftmost_one_pos, elog, ERROR, fb(), i, palloc0(), pg_add_s32_overflow(), result, and WORDNUM.

Referenced by has_notnull_forced_var(), offset_relid_set(), OffsetVarNodes_walker(), statext_is_compatible_clause(), test_bms_offset_members(), and test_random_offset_operations().

◆ bms_overlap()

bool bms_overlap ( const Bitmapset a,
const Bitmapset b 
)

Definition at line 710 of file bitmapset.c.

711{
712 int shortlen;
713 int i;
714
717
718 /* Handle cases where either input is NULL */
719 if (a == NULL || b == NULL)
720 return false;
721 /* Check words in common */
722 shortlen = Min(a->nwords, b->nwords);
723 i = 0;
724 do
725 {
726 if ((a->words[i] & b->words[i]) != 0)
727 return true;
728 } while (++i < shortlen);
729 return false;
730}

References a, Assert, b, fb(), i, and Min.

Referenced by add_child_join_rel_equivalences(), add_nulling_relids_mutator(), add_paths_to_joinrel(), adjust_child_relids_multilevel(), allow_star_schema_join(), calc_nestloop_required_outer(), calc_non_nestloop_required_outer(), choose_bitmap_and(), classify_matching_subplans(), compute_semijoin_info(), create_nestloop_path(), distribute_qual_to_rels(), eager_aggregation_possible_for_relation(), eclass_useful_for_merging(), examine_variable(), ExecInitGenerated(), ExecReScanAgg(), ExecReScanAppend(), ExecReScanFunctionScan(), ExecReScanMergeAppend(), ExecUpdateLockMode(), extract_lateral_vars_from_PHVs(), generate_implied_equalities_for_column(), generate_join_implied_equalities(), generate_join_implied_equalities_for_ecs(), get_appendrel_parampathinfo(), get_baserel_parampathinfo(), get_dependent_generated_columns(), get_joinrel_parampathinfo(), get_useful_ecs_for_relation(), has_join_restriction(), has_legal_joinclause(), has_notnull_forced_var(), has_partition_attrs(), have_join_order_restriction(), have_partkey_equi_join(), have_relevant_eclass_joinclause(), have_relevant_joinclause(), heap_update(), identify_current_nestloop_params(), join_clause_is_movable_into(), join_clause_is_movable_to(), join_is_legal(), join_is_removable(), join_search_one_level(), make_join_rel(), make_outerjoininfo(), make_plain_restrictinfo(), make_rels_by_clause_joins(), make_rels_by_clauseless_joins(), mbms_overlap_sets(), partitions_are_ordered(), path_is_reparameterizable_by_child(), pullup_replace_vars_callback(), reduce_outer_joins_pass2(), remove_nulling_relids_mutator(), remove_self_joins_recurse(), reparameterize_path_by_child(), select_outer_pathkeys_for_merge(), set_append_rel_size(), subbuild_joinrel_restrictlist(), test_bms_overlap(), try_hashjoin_path(), try_mergejoin_path(), try_nestloop_path(), and try_partitionwise_join().

◆ bms_overlap_list()

bool bms_overlap_list ( const Bitmapset a,
const List b 
)

Definition at line 736 of file bitmapset.c.

737{
738 ListCell *lc;
739 int wordnum,
740 bitnum;
741
743
744 if (a == NULL || b == NIL)
745 return false;
746
747 foreach(lc, b)
748 {
749 int x = lfirst_int(lc);
750
751 if (x < 0)
752 elog(ERROR, "negative bitmapset member not allowed");
753 wordnum = WORDNUM(x);
754 bitnum = BITNUM(x);
755 if (wordnum < a->nwords)
756 if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
757 return true;
758 }
759
760 return false;
761}

References a, Assert, b, BITNUM, elog, ERROR, fb(), lfirst_int, NIL, WORDNUM, and x.

Referenced by preprocess_grouping_sets(), and test_bms_overlap_list().

◆ bms_prev_member()

int bms_prev_member ( const Bitmapset a,
int  prevbit 
)

Definition at line 1487 of file bitmapset.c.

1488{
1489 unsigned int currbit;
1490 int ushiftbits;
1491 bitmapword mask;
1492
1494
1495 /*
1496 * If set is NULL or if there are no more bits to the right then we've
1497 * nothing to do.
1498 */
1499 if (a == NULL || prevbit == 0)
1500 return -2;
1501
1502 /* Validate callers didn't give us something out of range */
1503 Assert(prevbit < 0 || prevbit <= (unsigned int) (a->nwords * BITS_PER_BITMAPWORD));
1504
1505 /*
1506 * Transform -1 (or any negative number) to the highest possible bit we
1507 * could have set. We do this in unsigned math to avoid the risk of
1508 * overflowing a signed int.
1509 */
1510 if (prevbit < 0)
1511 currbit = (unsigned int) a->nwords * BITS_PER_BITMAPWORD - 1;
1512 else
1513 currbit = prevbit - 1;
1514
1516 mask = (~(bitmapword) 0) >> ushiftbits;
1517 for (int wordnum = WORDNUM(currbit); wordnum >= 0; wordnum--)
1518 {
1519 bitmapword w = a->words[wordnum];
1520
1521 /* mask out bits left of currbit */
1522 w &= mask;
1523
1524 if (w != 0)
1525 {
1526 int result;
1527
1530 return result;
1531 }
1532
1533 /* in subsequent words, consider all bits */
1534 mask = (~(bitmapword) 0);
1535 }
1536 return -2;
1537}

References a, Assert, BITNUM, BITS_PER_BITMAPWORD, bmw_leftmost_one_pos, fb(), result, and WORDNUM.

Referenced by choose_next_subplan_locally(), and test_bms_prev_member().

◆ bms_replace_members()

Bitmapset * bms_replace_members ( Bitmapset a,
const Bitmapset b 
)

Definition at line 1091 of file bitmapset.c.

1092{
1093 int i;
1094
1097
1098 if (a == NULL)
1099 return bms_copy(b);
1100 if (b == NULL)
1101 {
1102 pfree(a);
1103 return NULL;
1104 }
1105
1106 if (a->nwords < b->nwords)
1107 a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(b->nwords));
1108
1109 i = 0;
1110 do
1111 {
1112 a->words[i] = b->words[i];
1113 } while (++i < b->nwords);
1114
1115 a->nwords = b->nwords;
1116
1117#ifdef REALLOCATE_BITMAPSETS
1118
1119 /*
1120 * There's no guarantee that the repalloc returned a new pointer, so copy
1121 * and free unconditionally here.
1122 */
1124#endif
1125
1126 return a;
1127}

References a, Assert, b, BITMAPSET_SIZE, bms_copy(), fb(), i, pfree(), and repalloc().

Referenced by DiscreteKnapsack(), and test_bms_replace_members().

◆ bms_singleton_member()

int bms_singleton_member ( const Bitmapset a)

Definition at line 800 of file bitmapset.c.

801{
802 int result = -1;
803 int nwords;
804 int wordnum;
805
807
808 if (a == NULL)
809 elog(ERROR, "bitmapset is empty");
810
811 nwords = a->nwords;
812 wordnum = 0;
813 do
814 {
815 bitmapword w = a->words[wordnum];
816
817 if (w != 0)
818 {
819 if (result >= 0 || HAS_MULTIPLE_ONES(w))
820 elog(ERROR, "bitmapset has multiple members");
823 }
824 } while (++wordnum < nwords);
825
826 /* we don't expect non-NULL sets to be empty */
827 Assert(result >= 0);
828 return result;
829}

References a, Assert, BITS_PER_BITMAPWORD, bmw_rightmost_one_pos, elog, ERROR, fb(), HAS_MULTIPLE_ONES, and result.

Referenced by fix_append_rel_relids(), get_matching_part_pairs(), overexplain_bitmapset_list(), remove_useless_joins(), split_selfjoin_quals(), and test_bms_singleton_member().

◆ bms_subset_compare()

BMS_Comparison bms_subset_compare ( const Bitmapset a,
const Bitmapset b 
)

Definition at line 580 of file bitmapset.c.

581{
583 int shortlen;
584 int i;
585
588
589 /* Handle cases where either input is NULL */
590 if (a == NULL)
591 {
592 if (b == NULL)
593 return BMS_EQUAL;
594 return BMS_SUBSET1;
595 }
596 if (b == NULL)
597 return BMS_SUBSET2;
598
599 /* Check common words */
600 result = BMS_EQUAL; /* status so far */
601 shortlen = Min(a->nwords, b->nwords);
602 i = 0;
603 do
604 {
605 bitmapword aword = a->words[i];
606 bitmapword bword = b->words[i];
607
608 if ((aword & ~bword) != 0)
609 {
610 /* a is not a subset of b */
611 if (result == BMS_SUBSET1)
612 return BMS_DIFFERENT;
614 }
615 if ((bword & ~aword) != 0)
616 {
617 /* b is not a subset of a */
618 if (result == BMS_SUBSET2)
619 return BMS_DIFFERENT;
621 }
622 } while (++i < shortlen);
623 /* Check extra words */
624 if (a->nwords > b->nwords)
625 {
626 /* if a has more words then a is not a subset of b */
627 if (result == BMS_SUBSET1)
628 return BMS_DIFFERENT;
629 return BMS_SUBSET2;
630 }
631 else if (a->nwords < b->nwords)
632 {
633 /* if b has more words then b is not a subset of a */
634 if (result == BMS_SUBSET2)
635 return BMS_DIFFERENT;
636 return BMS_SUBSET1;
637 }
638 return result;
639}

References a, Assert, b, BMS_DIFFERENT, BMS_EQUAL, BMS_SUBSET1, BMS_SUBSET2, fb(), i, Min, and result.

Referenced by add_path(), consider_index_join_outer_rels(), remove_useless_groupby_columns(), set_cheapest(), and test_bms_subset_compare().

◆ bms_union()

Bitmapset * bms_union ( const Bitmapset a,
const Bitmapset b 
)

Definition at line 252 of file bitmapset.c.

253{
255 const Bitmapset *other;
256 int otherlen;
257 int i;
258
261
262 /* Handle cases where either input is NULL */
263 if (a == NULL)
264 return bms_copy(b);
265 if (b == NULL)
266 return bms_copy(a);
267 /* Identify shorter and longer input; copy the longer one */
268 if (a->nwords <= b->nwords)
269 {
270 result = bms_copy(b);
271 other = a;
272 }
273 else
274 {
275 result = bms_copy(a);
276 other = b;
277 }
278 /* And union the shorter input into the result */
279 otherlen = other->nwords;
280 i = 0;
281 do
282 {
283 result->words[i] |= other->words[i];
284 } while (++i < otherlen);
285 return result;
286}

References a, Assert, b, bms_copy(), fb(), i, and result.

Referenced by add_nulling_relids_mutator(), build_join_rel(), build_joinrel_restrictlist(), BuildParameterizedTidPaths(), calc_nestloop_required_outer(), calc_non_nestloop_required_outer(), check_index_predicates(), check_relation_privileges(), compute_semijoin_info(), consider_index_join_outer_rels(), create_hashjoin_plan(), create_join_clause(), create_mergejoin_plan(), create_nestloop_plan(), deconstruct_distribute(), deconstruct_distribute_oj_quals(), deconstruct_jointree(), deconstruct_recurse(), ExecConstraints(), ExecGetAllUpdatedCols(), ExecPartitionCheckEmitError(), ExecWithCheckOptions(), finalize_plan(), find_hash_columns(), foreign_join_ok(), generate_join_implied_equalities(), generate_join_implied_equalities_for_ecs(), generate_nonunion_paths(), generate_recursion_path(), get_baserel_parampathinfo(), get_joinrel_parampathinfo(), get_rel_all_updated_cols(), get_tuple_desc(), has_legal_joinclause(), identify_current_nestloop_params(), index_unchanged_by_update(), join_is_removable(), make_join_rel(), make_outerjoininfo(), make_plain_restrictinfo(), markNullableIfNeeded(), min_join_parameterization(), pgpa_trove_lookup(), postgresGetForeignPaths(), pull_up_sublinks_jointree_recurse(), reduce_outer_joins_pass1(), reduce_unique_semijoins(), remove_leftjoinrel_from_query(), ReportNotNullViolationError(), resolve_special_varno(), rewriteTargetView(), substitute_phv_relids_walker(), test_bms_union(), test_random_operations(), and try_partitionwise_join().