diff --git a/src/box/memtx_bitset.cc b/src/box/memtx_bitset.cc index 89e7cbe01ee455f783d9e6dc6a42a8683bad08eb..41d4a61963161b6c865d9b57d24fbda6e143fc06 100644 --- a/src/box/memtx_bitset.cc +++ b/src/box/memtx_bitset.cc @@ -419,13 +419,12 @@ MemtxBitset::count(enum iterator_type type, const char *key, return bitset_index_count(&m_index, bit); } else if (type == ITER_BITS_ALL_SET) { /** - * Optimization: for an empty key return the number of items - * in the index. + * Optimization: for an empty key return 0. */ bit_iterator_init(&bit_it, bitset_key, bitset_key_size, true); bit = bit_iterator_next(&bit_it); if (bit == SIZE_MAX) - return bitset_index_size(&m_index); + return 0; /** * Optimiation: for a single bit key use * bitset_index_count(). diff --git a/src/lib/bitset/iterator.c b/src/lib/bitset/iterator.c index b9f7e41652e8a629f96479a0a5a225e674b8b9cd..6c0a8304589b1c759f4b08d52a28f0c0a403e46f 100644 --- a/src/lib/bitset/iterator.c +++ b/src/lib/bitset/iterator.c @@ -208,13 +208,13 @@ bitset_iterator_init(struct bitset_iterator *it, struct bitset_expr *expr, for (size_t c = 0; c < expr->size; c++) { struct bitset_expr_conj *exconj = &expr->conjs[c]; struct bitset_iterator_conj *itconj = &it->conjs[c]; + itconj->page_first_pos = 0; if (bitset_iterator_conj_reserve(it, itconj, exconj->size) != 0) return -1; for (size_t b = 0; b < exconj->size; b++) { assert(exconj->bitset_ids[b] < bitsets_size); - itconj->page_first_pos = 0; assert(p_bitsets[exconj->bitset_ids[b]] != NULL); itconj->bitsets[b] = p_bitsets[exconj->bitset_ids[b]]; itconj->pre_nots[b] = exconj->pre_nots[b]; diff --git a/test/box/bitset.result b/test/box/bitset.result index 444190314bc94c2f104c17855a4e38b73eee83ac..7d2f1feb435e1521ea77be12a62e0c2dd7e91910 100644 --- a/test/box/bitset.result +++ b/test/box/bitset.result @@ -167,7 +167,7 @@ dump(box.index.BITS_ALL_SET, 0) ... box.space.tweedledum.index.bitset:count(0, { iterator = box.index.BITS_ALL_SET}) --- -- 128 +- 0 ... dump(box.index.BITS_ALL_SET, 1) --- @@ -1940,3 +1940,47 @@ s:drop() s = nil --- ... +-- https://github.com/tarantool/tarantool/issues/1946 BITS_ALL_SET crashes +s = box.schema.space.create('test') +--- +... +_ = s:create_index('primary', { type = 'hash', parts = {1, 'num'}, unique = true }) +--- +... +i = s:create_index('bitset', { type = 'bitset', parts = {2, 'num'}, unique = false }) +--- +... +for i=1,10 do s:insert{i, math.random(8)} end +--- +... +good = true +--- +... +function is_good(key, opts) return #i:select({key}, opts) == i:count({key}, opts) end +--- +... +function check(key, opts) good = good and is_good(key, opts) end +--- +... +for j=1,100 do check(math.random(9) - 1) end +--- +... +for j=1,100 do check(math.random(9) - 1, {iterator = box.index.BITS_ANY_SET}) end +--- +... +for j=1,100 do check(math.random(9) - 1, {iterator = box.index.BITS_ALL_SET}) end +--- +... +for j=1,100 do check(math.random(9) - 1, {iterator = box.index.BITS_ALL_NOT_SET}) end +--- +... +good +--- +- true +... +s:drop() +--- +... +s = nil +--- +... diff --git a/test/box/bitset.test.lua b/test/box/bitset.test.lua index 656f311c927b7083a9133f23c69d76518cb748c8..850f056d29af6767426e0c2f7eb15bbdefe1bff5 100644 --- a/test/box/bitset.test.lua +++ b/test/box/bitset.test.lua @@ -132,3 +132,19 @@ s:insert{9, 8} i:count(7, {iterator = box.index.BITS_ANY_SET}) s:drop() s = nil + +-- https://github.com/tarantool/tarantool/issues/1946 BITS_ALL_SET crashes +s = box.schema.space.create('test') +_ = s:create_index('primary', { type = 'hash', parts = {1, 'num'}, unique = true }) +i = s:create_index('bitset', { type = 'bitset', parts = {2, 'num'}, unique = false }) +for i=1,10 do s:insert{i, math.random(8)} end +good = true +function is_good(key, opts) return #i:select({key}, opts) == i:count({key}, opts) end +function check(key, opts) good = good and is_good(key, opts) end +for j=1,100 do check(math.random(9) - 1) end +for j=1,100 do check(math.random(9) - 1, {iterator = box.index.BITS_ANY_SET}) end +for j=1,100 do check(math.random(9) - 1, {iterator = box.index.BITS_ALL_SET}) end +for j=1,100 do check(math.random(9) - 1, {iterator = box.index.BITS_ALL_NOT_SET}) end +good +s:drop() +s = nil