Merge pull request #1156 from jaten-molecula/container_key_span

RoaringIterator.ContainerKeySpan method
This commit is contained in:
tgruben 2020-12-01 16:22:57 -06:00 committed by GitHub
commit dd856378d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 83 additions and 0 deletions

View file

@ -1756,6 +1756,14 @@ type RoaringIterator interface {
// Clone copies the iterator, preserving it at this point in the iteration.
// It may well share much underlying data.
Clone() RoaringIterator
// ContainerKeySpan provides the smallest and largest
// container keys that the iterator will return.
// The current implementation requires that the underlying header
// lists the keys in ascending order.
// Iff there no keys, then empty will be returned true.
// If there is only a single key, then ckeyLast will equal ckeyFirst.
ContainerKeySpan() (ckeyFirst, ckeyLast uint64, empty bool)
}
// baseRoaringIterator holds values used by both Pilosa and official Roaring
@ -1924,6 +1932,22 @@ func (r *baseRoaringIterator) Done(err error) {
r.currentDataOffset = 0
}
func (r *baseRoaringIterator) ContainerKeySpan() (ckeyFirst, ckeyLast uint64, empty bool) {
n := r.keys
if n == 0 {
empty = true
return
}
ckeyFirst = binary.LittleEndian.Uint64(r.headers[0:8])
if n == 1 {
ckeyLast = ckeyFirst
return
}
beg := (n - 1) * 12
ckeyLast = binary.LittleEndian.Uint64(r.headers[beg : beg+8])
return
}
// Len() indicates the total number of containers the iterator expects to have.
func (r *baseRoaringIterator) Len() int64 {
return r.keys

View file

@ -4430,6 +4430,17 @@ func TestCloneRoaringIterator(t *testing.T) {
itr2 := itr.Clone()
firstCkey, lastCkey, empty := itr2.ContainerKeySpan()
if empty {
t.Fatalf("should not be empty")
}
if firstCkey != 0 {
t.Fatalf("firstCkey should be 0")
}
if lastCkey != 10001 {
t.Fatalf("lastCkey should be 10001")
}
var keys []uint64
for itrKey, synthC := itr.NextContainer(); synthC != nil; itrKey, synthC = itr.NextContainer() {
keys = append(keys, itrKey)
@ -4446,6 +4457,54 @@ func TestCloneRoaringIterator(t *testing.T) {
}
}
func TestRoaringIteratorContainerKeySpan(t *testing.T) {
ca := NewContainerArray([]uint16{1, 10, 100, 1000})
ba := NewFileBitmap()
ba.Containers.Put(101, ca)
ba.Containers.Put(10, ca)
ba.Containers.Put(10001, ca)
var buf bytes.Buffer
_, err := ba.WriteTo(&buf)
if err != nil {
t.Fatalf("error writing: %v", err)
}
itr, err := NewRoaringIterator(buf.Bytes())
if err != nil {
t.Fatalf("error NewRoaringIterator(buf.Bytes()): %v", err)
}
firstCkey, lastCkey, empty := itr.ContainerKeySpan()
if empty {
t.Fatalf("should not be empty")
}
if firstCkey != 10 {
t.Fatalf("firstCkey should be 10")
}
if lastCkey != 10001 {
t.Fatalf("lastCkey should be 10001")
}
// make and check empty bitmap
baEmpty := NewFileBitmap()
var bufEmpty bytes.Buffer
_, err = baEmpty.WriteTo(&bufEmpty)
if err != nil {
t.Fatalf("error writing: %v", err)
}
itrEmpty, err := NewRoaringIterator(bufEmpty.Bytes())
if err != nil {
t.Fatalf("error NewRoaringIterator(bufEmpty.Bytes()): %v", err)
}
_, _, empty = itrEmpty.ContainerKeySpan()
if !empty {
t.Fatalf("should be empty")
}
}
// we were seeing unionInterval16InPlace() returning too
// large an run container, which was causing problems when
// we write to the transactional backends. Verify that