importValue only considers the last instance of a column id

included test demonstrates bug
This commit is contained in:
Matt Jaffee 2019-03-28 15:07:16 -05:00
parent 80930de295
commit cde954e12f
No known key found for this signature in database
GPG key ID: 08A3DFFF987B11BF
2 changed files with 50 additions and 1 deletions

View file

@ -1743,6 +1743,7 @@ func (f *fragment) importValue(columnIDs, values []uint64, bitDepth uint, clear
var toSet, toClear []uint64
smallWrite := false
var colSet map[uint64]struct{}
if len(columnIDs)*int(bitDepth+1)+f.opN < f.MaxOpN {
smallWrite = true
@ -1753,6 +1754,7 @@ func (f *fragment) importValue(columnIDs, values []uint64, bitDepth uint, clear
// slightly more than half of that to try to avoid reallocation.
toSet = make([]uint64, 0, len(columnIDs)*int(bitDepth+1)*(5/8))
toClear = make([]uint64, 0, len(columnIDs)*int(bitDepth+1)*(5/8))
colSet = make(map[uint64]struct{})
}
if !smallWrite {
@ -1762,9 +1764,13 @@ func (f *fragment) importValue(columnIDs, values []uint64, bitDepth uint, clear
// Process every value.
// If an error occurs then reopen the storage.
if err := func() (err error) {
for i := range columnIDs {
for i := len(columnIDs) - 1; i >= 0; i-- {
columnID, value := columnIDs[i], values[i]
if smallWrite {
if _, ok := colSet[columnID]; ok {
continue
}
colSet[columnID] = struct{}{}
toSet, toClear, err = f.positionsForValue(columnID, bitDepth, value, clear, toSet, toClear)
if err != nil {
return errors.Wrap(err, "getting positions for value")

View file

@ -3070,3 +3070,46 @@ func TestImportValueConcurrent(t *testing.T) {
t.Fatalf("concurrently importing values: %v", err)
}
}
func TestImportMultipleValues(t *testing.T) {
tests := []struct {
cols []uint64
vals []uint64
checkCols []uint64
checkVals []uint64
depth uint
}{
{
cols: []uint64{0, 0},
vals: []uint64{97, 100},
depth: 7,
checkCols: []uint64{0},
checkVals: []uint64{100},
},
}
for i, test := range tests {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
f := mustOpenFragment("i", "f", viewBSIGroupPrefix+"foo", 0, CacheTypeNone)
err := f.importValue(test.cols, test.vals, test.depth, false)
if err != nil {
t.Fatalf("importing values: %v", err)
}
for i := range test.checkCols {
cc, cv := test.checkCols[i], test.checkVals[i]
n, exists, err := f.value(cc, test.depth)
if err != nil {
t.Fatalf("getting value: %v", err)
}
if !exists {
t.Errorf("column %d should exist", cc)
}
if n != 100 {
t.Errorf("wrong value: %d is not %d", n, cv)
}
}
})
}
}