fix oversized rangeEQ

This commit is contained in:
Jaden Weiss 2020-07-20 19:58:24 -04:00
parent 6c506f1138
commit dcdcf1356f
No known key found for this signature in database
GPG key ID: 177F065773634B67
2 changed files with 35 additions and 13 deletions

View file

@ -1230,12 +1230,18 @@ func (f *fragment) rangeEQ(bitDepth uint, predicate int64) (*Row, error) {
// Start with set of columns with values set.
b := f.row(bsiExistsBit)
// Filter to only positive/negative numbers.
upredicate := absInt64(predicate)
if uint(bits.Len64(upredicate)) > bitDepth {
// Predicate is out of range.
return NewRow(), nil
}
// Filter to only positive/negative numbers.
r := f.row(bsiSignBit)
if predicate < 0 {
b = b.Intersect(f.row(bsiSignBit)) // only negatives
b = b.Intersect(r) // only negatives
} else {
b = b.Difference(f.row(bsiSignBit)) // only positives
b = b.Difference(r) // only positives
}
// Filter any bits that don't match the current bit value.
@ -1308,18 +1314,10 @@ func (f *fragment) rangeLT(bitDepth uint, predicate int64, allowEquality bool) (
}
}
// msb gives the 1-indexed position (counting from lsb) of the most
// significant bit. E.G. for 1 it would return 1, for 2 2, for 3 2,
// for 4 3, for 8 4, etc.
func msb(x uint64) uint {
lz := bits.LeadingZeros64(x)
return 64 - uint(lz)
}
// rangeLTUnsigned returns all bits LT/LTE the predicate without considering the sign bit.
func (f *fragment) rangeLTUnsigned(filter *Row, bitDepth uint, predicate uint64, allowEquality bool) (*Row, error) {
switch {
case msb(predicate) > bitDepth:
case uint(bits.Len64(predicate)) > bitDepth:
fallthrough
case predicate == (1<<bitDepth)-1 && allowEquality:
// This query matches all possible values.
@ -1498,7 +1496,7 @@ func (f *fragment) rangeBetweenUnsigned(filter *Row, bitDepth uint, predicateMin
}
// Clear the bits we just compared.
equalMask := (^uint64(0)) << diffLen
equalMask := (^uint64(0)) << uint(diffLen)
predicateMin &^= equalMask
predicateMax &^= equalMask

View file

@ -538,6 +538,30 @@ func TestFragment_Range(t *testing.T) {
}
})
t.Run("EQOversizeRegression", func(t *testing.T) {
f := mustOpenFragment("i", "f", viewStandard, 0, "")
defer f.Clean(t)
// Set values.
if _, err := f.setValue(1000, 1, 0); err != nil {
t.Fatal(err)
} else if _, err := f.setValue(2000, 1, 1); err != nil {
t.Fatal(err)
}
// Query for equality.
if b, err := f.rangeOp(pql.EQ, 1, 3); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(b.Columns(), []uint64{}) {
t.Fatalf("unexpected columns: %+v", b.Columns())
}
if b, err := f.rangeOp(pql.EQ, 1, 4); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(b.Columns(), []uint64{}) {
t.Fatalf("unexpected columns: %+v", b.Columns())
}
})
t.Run("NEQ", func(t *testing.T) {
f := mustOpenFragment("i", "f", viewStandard, 0, "")
defer f.Clean(t)