Remove bms_first_member().

This function has been semi-deprecated ever since we invented
bms_next_member().  Its habit of scribbling on the input bitmapset
isn't great, plus for sufficiently large bitmapsets it would take
O(N^2) time to complete a loop.  Now we have the additional problem
that reducing the input to empty while leaving it still accessible
would violate a planned invariant.  So let's just get rid of it,
after updating the few extant callers to use bms_next_member().

Patch by me; thanks to Nathan Bossart and Richard Guo for review.

Discussion: https://postgr.es/m/1159933.1677621588@sss.pgh.pa.us
This commit is contained in:
Tom Lane 2023-03-02 11:34:29 -05:00
parent 2f80c95740
commit 462bb7f128
9 changed files with 23 additions and 70 deletions

View File

@ -858,7 +858,7 @@ check_selective_binary_conversion(RelOptInfo *baserel,
ListCell *lc; ListCell *lc;
Relation rel; Relation rel;
TupleDesc tupleDesc; TupleDesc tupleDesc;
AttrNumber attnum; int attidx;
Bitmapset *attrs_used = NULL; Bitmapset *attrs_used = NULL;
bool has_wholerow = false; bool has_wholerow = false;
int numattrs; int numattrs;
@ -901,10 +901,11 @@ check_selective_binary_conversion(RelOptInfo *baserel,
rel = table_open(foreigntableid, AccessShareLock); rel = table_open(foreigntableid, AccessShareLock);
tupleDesc = RelationGetDescr(rel); tupleDesc = RelationGetDescr(rel);
while ((attnum = bms_first_member(attrs_used)) >= 0) attidx = -1;
while ((attidx = bms_next_member(attrs_used, attidx)) >= 0)
{ {
/* Adjust for system attributes. */ /* attidx is zero-based, attnum is the normal attribute number */
attnum += FirstLowInvalidHeapAttributeNumber; AttrNumber attnum = attidx + FirstLowInvalidHeapAttributeNumber;
if (attnum == 0) if (attnum == 0)
{ {

View File

@ -231,7 +231,8 @@ check_relation_privileges(Oid relOid,
updated = fixup_whole_row_references(relOid, updated); updated = fixup_whole_row_references(relOid, updated);
columns = bms_union(selected, bms_union(inserted, updated)); columns = bms_union(selected, bms_union(inserted, updated));
while ((index = bms_first_member(columns)) >= 0) index = -1;
while ((index = bms_next_member(columns, index)) >= 0)
{ {
AttrNumber attnum; AttrNumber attnum;
uint32 column_perms = 0; uint32 column_perms = 0;

View File

@ -3859,9 +3859,6 @@ heap_attr_equals(TupleDesc tupdesc, int attrnum, Datum value1, Datum value2,
* has_external indicates if any of the unmodified attributes (from those * has_external indicates if any of the unmodified attributes (from those
* listed as interesting) of the old tuple is a member of external_cols and is * listed as interesting) of the old tuple is a member of external_cols and is
* stored externally. * stored externally.
*
* The input interesting_cols bitmapset is destructively modified; that is OK
* since this is invoked at most once in heap_update.
*/ */
static Bitmapset * static Bitmapset *
HeapDetermineColumnsInfo(Relation relation, HeapDetermineColumnsInfo(Relation relation,
@ -3870,19 +3867,20 @@ HeapDetermineColumnsInfo(Relation relation,
HeapTuple oldtup, HeapTuple newtup, HeapTuple oldtup, HeapTuple newtup,
bool *has_external) bool *has_external)
{ {
int attrnum; int attidx;
Bitmapset *modified = NULL; Bitmapset *modified = NULL;
TupleDesc tupdesc = RelationGetDescr(relation); TupleDesc tupdesc = RelationGetDescr(relation);
while ((attrnum = bms_first_member(interesting_cols)) >= 0) attidx = -1;
while ((attidx = bms_next_member(interesting_cols, attidx)) >= 0)
{ {
/* attidx is zero-based, attrnum is the normal attribute number */
AttrNumber attrnum = attidx + FirstLowInvalidHeapAttributeNumber;
Datum value1, Datum value1,
value2; value2;
bool isnull1, bool isnull1,
isnull2; isnull2;
attrnum += FirstLowInvalidHeapAttributeNumber;
/* /*
* If it's a whole-tuple reference, say "not equal". It's not really * If it's a whole-tuple reference, say "not equal". It's not really
* worth supporting this case, since it could only succeed after a * worth supporting this case, since it could only succeed after a
@ -3890,9 +3888,7 @@ HeapDetermineColumnsInfo(Relation relation,
*/ */
if (attrnum == 0) if (attrnum == 0)
{ {
modified = bms_add_member(modified, modified = bms_add_member(modified, attidx);
attrnum -
FirstLowInvalidHeapAttributeNumber);
continue; continue;
} }
@ -3905,9 +3901,7 @@ HeapDetermineColumnsInfo(Relation relation,
{ {
if (attrnum != TableOidAttributeNumber) if (attrnum != TableOidAttributeNumber)
{ {
modified = bms_add_member(modified, modified = bms_add_member(modified, attidx);
attrnum -
FirstLowInvalidHeapAttributeNumber);
continue; continue;
} }
} }
@ -3924,9 +3918,7 @@ HeapDetermineColumnsInfo(Relation relation,
if (!heap_attr_equals(tupdesc, attrnum, value1, if (!heap_attr_equals(tupdesc, attrnum, value1,
value2, isnull1, isnull2)) value2, isnull1, isnull2))
{ {
modified = bms_add_member(modified, modified = bms_add_member(modified, attidx);
attrnum -
FirstLowInvalidHeapAttributeNumber);
continue; continue;
} }
@ -3943,8 +3935,7 @@ HeapDetermineColumnsInfo(Relation relation,
* member of external_cols. * member of external_cols.
*/ */
if (VARATT_IS_EXTERNAL((struct varlena *) DatumGetPointer(value1)) && if (VARATT_IS_EXTERNAL((struct varlena *) DatumGetPointer(value1)) &&
bms_is_member(attrnum - FirstLowInvalidHeapAttributeNumber, bms_is_member(attidx, external_cols))
external_cols))
*has_external = true; *has_external = true;
} }

View File

@ -1646,7 +1646,8 @@ find_hash_columns(AggState *aggstate)
} }
/* and add the remaining columns */ /* and add the remaining columns */
while ((i = bms_first_member(colnos)) >= 0) i = -1;
while ((i = bms_next_member(colnos, i)) >= 0)
{ {
perhash->hashGrpColIdxInput[perhash->numhashGrpCols] = i; perhash->hashGrpColIdxInput[perhash->numhashGrpCols] = i;
perhash->numhashGrpCols++; perhash->numhashGrpCols++;

View File

@ -982,48 +982,6 @@ bms_join(Bitmapset *a, Bitmapset *b)
return result; return result;
} }
/*
* bms_first_member - find and remove first member of a set
*
* Returns -1 if set is empty. NB: set is destructively modified!
*
* This is intended as support for iterating through the members of a set.
* The typical pattern is
*
* while ((x = bms_first_member(inputset)) >= 0)
* process member x;
*
* CAUTION: this destroys the content of "inputset". If the set must
* not be modified, use bms_next_member instead.
*/
int
bms_first_member(Bitmapset *a)
{
int nwords;
int wordnum;
if (a == NULL)
return -1;
nwords = a->nwords;
for (wordnum = 0; wordnum < nwords; wordnum++)
{
bitmapword w = a->words[wordnum];
if (w != 0)
{
int result;
w = RIGHTMOST_ONE(w);
a->words[wordnum] &= ~w;
result = wordnum * BITS_PER_BITMAPWORD;
result += bmw_rightmost_one_pos(w);
return result;
}
}
return -1;
}
/* /*
* bms_next_member - find next member of a set * bms_next_member - find next member of a set
* *

View File

@ -1481,7 +1481,8 @@ convert_EXISTS_sublink_to_join(PlannerInfo *root, SubLink *sublink,
*/ */
clause_varnos = pull_varnos(root, whereClause); clause_varnos = pull_varnos(root, whereClause);
upper_varnos = NULL; upper_varnos = NULL;
while ((varno = bms_first_member(clause_varnos)) >= 0) varno = -1;
while ((varno = bms_next_member(clause_varnos, varno)) >= 0)
{ {
if (varno <= rtoffset) if (varno <= rtoffset)
upper_varnos = bms_add_member(upper_varnos, varno); upper_varnos = bms_add_member(upper_varnos, varno);

View File

@ -2759,7 +2759,7 @@ make_row_comparison_op(ParseState *pstate, List *opname,
* them ... this coding arbitrarily picks the lowest btree strategy * them ... this coding arbitrarily picks the lowest btree strategy
* number. * number.
*/ */
i = bms_first_member(strats); i = bms_next_member(strats, -1);
if (i < 0) if (i < 0)
{ {
/* No common interpretation, so fail */ /* No common interpretation, so fail */

View File

@ -227,7 +227,8 @@ logicalrep_report_missing_attrs(LogicalRepRelation *remoterel,
initStringInfo(&missingattsbuf); initStringInfo(&missingattsbuf);
while ((i = bms_first_member(missingatts)) >= 0) i = -1;
while ((i = bms_next_member(missingatts, i)) >= 0)
{ {
missingattcnt++; missingattcnt++;
if (missingattcnt == 1) if (missingattcnt == 1)

View File

@ -115,7 +115,6 @@ extern Bitmapset *bms_del_members(Bitmapset *a, const Bitmapset *b);
extern Bitmapset *bms_join(Bitmapset *a, Bitmapset *b); extern Bitmapset *bms_join(Bitmapset *a, Bitmapset *b);
/* support for iterating through the integer elements of a set: */ /* support for iterating through the integer elements of a set: */
extern int bms_first_member(Bitmapset *a);
extern int bms_next_member(const Bitmapset *a, int prevbit); extern int bms_next_member(const Bitmapset *a, int prevbit);
extern int bms_prev_member(const Bitmapset *a, int prevbit); extern int bms_prev_member(const Bitmapset *a, int prevbit);