Merge pull request #17610 from influxdata/fix-cursor-buffer-read

fix(storage): Fix query cursor read that caused cursor truncation.
pull/17634/head
Ben Johnson 2020-04-06 15:20:55 -06:00 committed by GitHub
commit 59f683e586
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 94 additions and 12 deletions

View File

@ -55,8 +55,6 @@ func (c *floatArrayFilterCursor) Next() *cursors.FloatArray {
if c.tmp.Len() > 0 {
a = c.tmp
c.tmp.Timestamps = nil
c.tmp.Values = nil
} else {
a = c.FloatArrayCursor.Next()
}
@ -76,6 +74,12 @@ LOOP:
}
}
}
// Clear bufferred timestamps & values if we make it through a cursor.
// The break above will skip this if a cursor is partially read.
c.tmp.Timestamps = nil
c.tmp.Values = nil
a = c.FloatArrayCursor.Next()
}
@ -271,8 +275,6 @@ func (c *integerArrayFilterCursor) Next() *cursors.IntegerArray {
if c.tmp.Len() > 0 {
a = c.tmp
c.tmp.Timestamps = nil
c.tmp.Values = nil
} else {
a = c.IntegerArrayCursor.Next()
}
@ -292,6 +294,12 @@ LOOP:
}
}
}
// Clear bufferred timestamps & values if we make it through a cursor.
// The break above will skip this if a cursor is partially read.
c.tmp.Timestamps = nil
c.tmp.Values = nil
a = c.IntegerArrayCursor.Next()
}
@ -487,8 +495,6 @@ func (c *unsignedArrayFilterCursor) Next() *cursors.UnsignedArray {
if c.tmp.Len() > 0 {
a = c.tmp
c.tmp.Timestamps = nil
c.tmp.Values = nil
} else {
a = c.UnsignedArrayCursor.Next()
}
@ -508,6 +514,12 @@ LOOP:
}
}
}
// Clear bufferred timestamps & values if we make it through a cursor.
// The break above will skip this if a cursor is partially read.
c.tmp.Timestamps = nil
c.tmp.Values = nil
a = c.UnsignedArrayCursor.Next()
}
@ -703,8 +715,6 @@ func (c *stringArrayFilterCursor) Next() *cursors.StringArray {
if c.tmp.Len() > 0 {
a = c.tmp
c.tmp.Timestamps = nil
c.tmp.Values = nil
} else {
a = c.StringArrayCursor.Next()
}
@ -724,6 +734,12 @@ LOOP:
}
}
}
// Clear bufferred timestamps & values if we make it through a cursor.
// The break above will skip this if a cursor is partially read.
c.tmp.Timestamps = nil
c.tmp.Values = nil
a = c.StringArrayCursor.Next()
}
@ -879,8 +895,6 @@ func (c *booleanArrayFilterCursor) Next() *cursors.BooleanArray {
if c.tmp.Len() > 0 {
a = c.tmp
c.tmp.Timestamps = nil
c.tmp.Values = nil
} else {
a = c.BooleanArrayCursor.Next()
}
@ -900,6 +914,12 @@ LOOP:
}
}
}
// Clear bufferred timestamps & values if we make it through a cursor.
// The break above will skip this if a cursor is partially read.
c.tmp.Timestamps = nil
c.tmp.Values = nil
a = c.BooleanArrayCursor.Next()
}

View File

@ -54,8 +54,6 @@ func (c *{{$type}}) Next() {{$arrayType}} {
if c.tmp.Len() > 0 {
a = c.tmp
c.tmp.Timestamps = nil
c.tmp.Values = nil
} else {
a = c.{{.Name}}ArrayCursor.Next()
}
@ -75,6 +73,12 @@ LOOP:
}
}
}
// Clear bufferred timestamps & values if we make it through a cursor.
// The break above will skip this if a cursor is partially read.
c.tmp.Timestamps = nil
c.tmp.Values = nil
a = c.{{.Name}}ArrayCursor.Next()
}

View File

@ -0,0 +1,58 @@
package reads
import (
"testing"
"github.com/influxdata/influxdb/v2/tsdb/cursors"
)
func TestIntegerFilterArrayCursor(t *testing.T) {
var i int
expr := MockExpression{
EvalBoolFunc: func(v Valuer) bool {
i++
return i%2 == 0
},
}
var resultN int
ac := MockIntegerArrayCursor{
CloseFunc: func() {},
ErrFunc: func() error { return nil },
StatsFunc: func() cursors.CursorStats { return cursors.CursorStats{} },
NextFunc: func() *cursors.IntegerArray {
resultN++
if resultN == 4 {
return cursors.NewIntegerArrayLen(0)
}
return cursors.NewIntegerArrayLen(900)
},
}
c := newIntegerFilterArrayCursor(&expr)
c.reset(&ac)
if got, want := len(c.Next().Timestamps), 1000; got != want {
t.Fatalf("len(Next())=%d, want %d", got, want)
} else if got, want := len(c.Next().Timestamps), 350; got != want {
t.Fatalf("len(Next())=%d, want %d", got, want)
}
}
type MockIntegerArrayCursor struct {
CloseFunc func()
ErrFunc func() error
StatsFunc func() cursors.CursorStats
NextFunc func() *cursors.IntegerArray
}
func (c *MockIntegerArrayCursor) Close() { c.CloseFunc() }
func (c *MockIntegerArrayCursor) Err() error { return c.ErrFunc() }
func (c *MockIntegerArrayCursor) Stats() cursors.CursorStats { return c.StatsFunc() }
func (c *MockIntegerArrayCursor) Next() *cursors.IntegerArray { return c.NextFunc() }
type MockExpression struct {
EvalBoolFunc func(v Valuer) bool
}
func (e *MockExpression) EvalBool(v Valuer) bool { return e.EvalBoolFunc(v) }