fix rangeBetween when there are nonzero common upper bits and oversized rangeGT

This commit is contained in:
Jaden Weiss 2020-07-17 17:49:11 -04:00
parent b2092e4395
commit 6c506f1138
No known key found for this signature in database
GPG key ID: 177F065773634B67
2 changed files with 49 additions and 4 deletions

View file

@ -1395,6 +1395,7 @@ func (f *fragment) rangeGT(bitDepth uint, predicate int64, allowEquality bool) (
}
func (f *fragment) rangeGTUnsigned(filter *Row, bitDepth uint, predicate uint64, allowEquality bool) (*Row, error) {
prep:
switch {
case predicate == 0 && allowEquality:
// This query matches all possible values.
@ -1407,8 +1408,13 @@ func (f *fragment) rangeGTUnsigned(filter *Row, bitDepth uint, predicate uint64,
matches = matches.Union(filter.Intersect(row))
}
return matches, nil
case !allowEquality && uint(bits.Len64(predicate)) > bitDepth:
// The predicate is bigger than the BSI width, so nothing can be bigger.
return NewRow(), nil
case allowEquality:
predicate--
allowEquality = false
goto prep
}
// Compare intermediate bits.
@ -1479,9 +1485,9 @@ func (f *fragment) rangeBetweenUnsigned(filter *Row, bitDepth uint, predicateMin
}
// Compare any upper bits which are equal.
firstDiff := int(msb(predicateMax^predicateMin)) - 1
diffLen := bits.Len64(predicateMax ^ predicateMin)
remaining := filter
for i := int(bitDepth - 1); i > firstDiff; i-- {
for i := int(bitDepth - 1); i >= diffLen; i-- {
row := f.row(uint64(bsiOffsetBit + i))
switch (predicateMin >> uint(i)) & 1 {
case 1:
@ -1491,12 +1497,17 @@ func (f *fragment) rangeBetweenUnsigned(filter *Row, bitDepth uint, predicateMin
}
}
// Clear the bits we just compared.
equalMask := (^uint64(0)) << diffLen
predicateMin &^= equalMask
predicateMax &^= equalMask
var err error
remaining, err = f.rangeGTUnsigned(remaining, uint(firstDiff+1), predicateMin, true)
remaining, err = f.rangeGTUnsigned(remaining, uint(diffLen), predicateMin, true)
if err != nil {
return nil, err
}
remaining, err = f.rangeLTUnsigned(remaining, uint(firstDiff+1), predicateMax, true)
remaining, err = f.rangeLTUnsigned(remaining, uint(diffLen), predicateMax, true)
if err != nil {
return nil, err
}

View file

@ -706,6 +706,23 @@ func TestFragment_Range(t *testing.T) {
}
})
t.Run("GTOversizeRegression", func(t *testing.T) {
f := mustOpenFragment("i", "f", viewStandard, 0, "")
defer f.Clean(t)
if _, err := f.setValue(1, 2, 0); err != nil {
t.Fatal(err)
} else if _, err := f.setValue(2, 2, 1); err != nil {
t.Fatal(err)
}
if b, err := f.rangeGTUnsigned(NewRow(1, 2), 2, 4, false); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(b.Columns(), []uint64{}) {
t.Fatalf("unepxected coulmns: %+v", b.Columns())
}
})
t.Run("BETWEEN", func(t *testing.T) {
f := mustOpenFragment("i", "f", viewStandard, 0, "")
defer f.Clean(t)
@ -753,6 +770,23 @@ func TestFragment_Range(t *testing.T) {
t.Fatalf("unexpected columns: %+v", b.Columns())
}
})
t.Run("BetweenCommonBitsRegression", func(t *testing.T) {
f := mustOpenFragment("i", "f", viewStandard, 0, "")
defer f.Clean(t)
if _, err := f.setValue(1, 64, 0xf0); err != nil {
t.Fatal(err)
} else if _, err := f.setValue(2, 64, 0xf1); err != nil {
t.Fatal(err)
}
if b, err := f.rangeBetweenUnsigned(NewRow(1, 2), 64, 0xf0, 0xf1); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(b.Columns(), []uint64{1, 2}) {
t.Fatalf("unepxected coulmns: %+v", b.Columns())
}
})
}
// benchmarkSetValues is a helper function to explore, very roughly, the cost