feat(storage): add mean aggregate array cursor and tests (#19019)

pull/19041/head
Christopher M. Wolff 2020-07-23 09:49:53 -07:00 committed by GitHub
parent d3c86e8f4c
commit 8b106bcee1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1221 additions and 214 deletions

View File

@ -1528,6 +1528,149 @@ from(bucket: v.bucket)
,result,table,_value,_field,_measurement,k
,,0,67,f,m0,k0
`,
},
{
name: "bare mean",
data: []string{
"m0,k=k0,kk=kk0 f=5 0",
"m0,k=k0,kk=kk0 f=6 5000000000",
"m0,k=k0,kk=kk0 f=7 10000000000",
"m0,k=k0,kk=kk0 f=9 15000000000",
},
query: `
from(bucket: v.bucket)
|> range(start: 0)
|> mean()
|> keep(columns: ["_value"])
`,
op: "readWindow(mean)",
want: `
#datatype,string,long,double
#group,false,false,false
#default,_result,,
,result,table,_value
,,0,6.75
`,
},
{
name: "window mean",
data: []string{
"m0,k=k0 f=1i 5000000000",
"m0,k=k0 f=2i 6000000000",
"m0,k=k0 f=3i 7000000000",
"m0,k=k0 f=4i 8000000000",
"m0,k=k0 f=5i 9000000000",
"m0,k=k0 f=6i 10000000000",
"m0,k=k0 f=7i 11000000000",
"m0,k=k0 f=8i 12000000000",
"m0,k=k0 f=9i 13000000000",
"m0,k=k0 f=10i 14000000000",
"m0,k=k0 f=11i 15000000000",
"m0,k=k0 f=12i 16000000000",
"m0,k=k0 f=13i 17000000000",
"m0,k=k0 f=14i 18000000000",
"m0,k=k0 f=16i 19000000000",
"m0,k=k0 f=17i 20000000000",
},
query: `
from(bucket: v.bucket)
|> range(start: 1970-01-01T00:00:05Z, stop: 1970-01-01T00:00:20Z)
|> aggregateWindow(fn: mean, every: 5s)
|> keep(columns: ["_time", "_value"])
`,
op: "readWindow(mean)",
want: `
#datatype,string,long,dateTime:RFC3339,double
#group,false,false,false,false
#default,_result,,,
,result,table,_time,_value
,,0,1970-01-01T00:00:10Z,3
,,0,1970-01-01T00:00:15Z,8
,,0,1970-01-01T00:00:20Z,13.2
`,
},
{
name: "window mean offset",
data: []string{
"m0,k=k0 f=1i 5000000000",
"m0,k=k0 f=2i 6000000000",
"m0,k=k0 f=3i 7000000000",
"m0,k=k0 f=4i 8000000000",
"m0,k=k0 f=5i 9000000000",
"m0,k=k0 f=6i 10000000000",
"m0,k=k0 f=7i 11000000000",
"m0,k=k0 f=8i 12000000000",
"m0,k=k0 f=9i 13000000000",
"m0,k=k0 f=10i 14000000000",
"m0,k=k0 f=11i 15000000000",
"m0,k=k0 f=12i 16000000000",
"m0,k=k0 f=13i 17000000000",
"m0,k=k0 f=14i 18000000000",
"m0,k=k0 f=16i 19000000000",
"m0,k=k0 f=17i 20000000000",
},
query: `
from(bucket: v.bucket)
|> range(start: 1970-01-01T00:00:05Z, stop: 1970-01-01T00:00:20Z)
|> window(every: 5s, offset: 1s)
|> mean()
`,
op: "readWindow(mean)",
want: `
#datatype,string,long,dateTime:RFC3339,dateTime:RFC3339,string,string,string,double
#group,false,false,true,true,true,true,true,false
#default,_result,,,,,,,
,result,table,_start,_stop,_field,_measurement,k,_value
,,0,1970-01-01T00:00:05Z,1970-01-01T00:00:06Z,f,m0,k0,1
,,1,1970-01-01T00:00:06Z,1970-01-01T00:00:11Z,f,m0,k0,4
,,2,1970-01-01T00:00:11Z,1970-01-01T00:00:16Z,f,m0,k0,9
,,3,1970-01-01T00:00:16Z,1970-01-01T00:00:20Z,f,m0,k0,13.75
`,
},
{
name: "window mean offset with duplicate and unwindow",
data: []string{
"m0,k=k0 f=1i 5000000000",
"m0,k=k0 f=2i 6000000000",
"m0,k=k0 f=3i 7000000000",
"m0,k=k0 f=4i 8000000000",
"m0,k=k0 f=5i 9000000000",
"m0,k=k0 f=6i 10000000000",
"m0,k=k0 f=7i 11000000000",
"m0,k=k0 f=8i 12000000000",
"m0,k=k0 f=9i 13000000000",
"m0,k=k0 f=10i 14000000000",
"m0,k=k0 f=11i 15000000000",
"m0,k=k0 f=12i 16000000000",
"m0,k=k0 f=13i 17000000000",
"m0,k=k0 f=14i 18000000000",
"m0,k=k0 f=16i 19000000000",
"m0,k=k0 f=17i 20000000000",
},
query: `
from(bucket: v.bucket)
|> range(start: 1970-01-01T00:00:05Z, stop: 1970-01-01T00:00:20Z)
|> window(every: 5s, offset: 1s)
|> mean()
|> duplicate(column: "_stop", as: "_time")
|> window(every: inf)
|> keep(columns: ["_time", "_value"])
`,
op: "readWindow(mean)",
want: `
#datatype,string,long,dateTime:RFC3339,double
#group,false,false,false,false
#default,_result,,,
,result,table,_time,_value
,,0,1970-01-01T00:00:06Z,1
,,0,1970-01-01T00:00:11Z,4
,,0,1970-01-01T00:00:16Z,9
,,0,1970-01-01T00:00:20Z,13.75
`,
},
{
name: "group first",
@ -1826,6 +1969,7 @@ from(bucket: v.bucket)
l := launcher.RunTestLauncherOrFail(t, ctx, mock.NewFlagger(map[feature.Flag]interface{}{
feature.PushDownWindowAggregateCount(): true,
feature.PushDownWindowAggregateSum(): true,
feature.PushDownWindowAggregateMean(): true,
}))
l.SetupOrFail(t)

View File

@ -167,6 +167,12 @@ var FluxEndToEndFeatureFlags = PerTestFeatureFlagMap{
"bare_sum_push": {
"pushDownWindowAggregateSum": "true",
},
"bare_mean_push": {
"pushDownWindowAggregateMean": "true",
},
"window_mean_push": {
"pushDownWindowAggregateMean": "true",
},
"merge_filters": {
"mergeFilterRule": "true",
},

View File

@ -625,6 +625,7 @@ const (
LastKind = "last"
MinKind = "min"
MaxKind = "max"
MeanKind = "mean"
)
// isSelector returns true if given a procedure kind that represents a selector operator.

View File

@ -15,6 +15,8 @@ import (
"github.com/influxdata/flux"
"github.com/influxdata/flux/execute"
"github.com/influxdata/flux/execute/executetest"
"github.com/influxdata/flux/execute/table"
"github.com/influxdata/flux/execute/table/static"
"github.com/influxdata/flux/memory"
"github.com/influxdata/flux/plan"
"github.com/influxdata/flux/values"
@ -1189,6 +1191,202 @@ func TestStorageReader_ReadWindowAggregate_TruncatedBoundsCreateEmpty(t *testing
}
}
func TestStorageReader_ReadWindowAggregate_Mean(t *testing.T) {
reader := NewStorageReader(t, func(org, bucket influxdb.ID) (gen.SeriesGenerator, gen.TimeRange) {
tagsSpec := &gen.TagsSpec{
Tags: []*gen.TagValuesSpec{
{
TagKey: "t0",
Values: func() gen.CountableSequence {
return gen.NewCounterByteSequence("a%s", 0, 1)
},
},
},
}
spec := gen.Spec{
OrgID: org,
BucketID: bucket,
Measurements: []gen.MeasurementSpec{
{
Name: "m0",
TagsSpec: tagsSpec,
FieldValuesSpec: &gen.FieldValuesSpec{
Name: "f0",
TimeSequenceSpec: gen.TimeSequenceSpec{
Count: math.MaxInt32,
Delta: 5 * time.Second,
},
DataType: models.Integer,
Values: func(spec gen.TimeSequenceSpec) gen.TimeValuesSequence {
return gen.NewTimeIntegerValuesSequence(
spec.Count,
gen.NewTimestampSequenceFromSpec(spec),
gen.NewIntegerArrayValuesSequence([]int64{1, 2, 3, 4}),
)
},
},
},
},
}
tr := gen.TimeRange{
Start: mustParseTime("2019-11-25T00:00:00Z"),
End: mustParseTime("2019-11-25T00:01:00Z"),
}
return gen.NewSeriesGeneratorFromSpec(&spec, tr), tr
})
defer reader.Close()
t.Run("unwindowed mean", func(t *testing.T) {
mem := &memory.Allocator{}
ti, err := reader.ReadWindowAggregate(context.Background(), query.ReadWindowAggregateSpec{
ReadFilterSpec: query.ReadFilterSpec{
OrganizationID: reader.Org,
BucketID: reader.Bucket,
Bounds: reader.Bounds,
},
WindowEvery: math.MaxInt64,
Aggregates: []plan.ProcedureKind{
storageflux.MeanKind,
},
}, mem)
if err != nil {
t.Fatal(err)
}
want := static.Table{
static.StringKey("_measurement", "m0"),
static.StringKey("_field", "f0"),
static.StringKey("t0", "a0"),
static.TimeKey("_start", "2019-11-25T00:00:00Z"),
static.TimeKey("_stop", "2019-11-25T00:01:00Z"),
static.Floats("_value", 2.5),
}
if diff := table.Diff(want, ti); diff != "" {
t.Fatalf("table iterators do not match; -want/+got:\n%s", diff)
}
})
t.Run("windowed mean", func(t *testing.T) {
mem := &memory.Allocator{}
ti, err := reader.ReadWindowAggregate(context.Background(), query.ReadWindowAggregateSpec{
ReadFilterSpec: query.ReadFilterSpec{
OrganizationID: reader.Org,
BucketID: reader.Bucket,
Bounds: reader.Bounds,
},
WindowEvery: int64(10 * time.Second),
Aggregates: []plan.ProcedureKind{
storageflux.MeanKind,
},
}, mem)
if err != nil {
t.Fatal(err)
}
want := static.TableGroup{
static.StringKey("_measurement", "m0"),
static.StringKey("_field", "f0"),
static.StringKey("t0", "a0"),
static.Table{
static.TimeKey("_start", "2019-11-25T00:00:00Z"),
static.TimeKey("_stop", "2019-11-25T00:00:10Z"),
static.Floats("_value", 1.5),
},
static.Table{
static.TimeKey("_start", "2019-11-25T00:00:10Z"),
static.TimeKey("_stop", "2019-11-25T00:00:20Z"),
static.Floats("_value", 3.5),
},
static.Table{
static.TimeKey("_start", "2019-11-25T00:00:20Z"),
static.TimeKey("_stop", "2019-11-25T00:00:30Z"),
static.Floats("_value", 1.5),
},
static.Table{
static.TimeKey("_start", "2019-11-25T00:00:30Z"),
static.TimeKey("_stop", "2019-11-25T00:00:40Z"),
static.Floats("_value", 3.5),
},
static.Table{
static.TimeKey("_start", "2019-11-25T00:00:40Z"),
static.TimeKey("_stop", "2019-11-25T00:00:50Z"),
static.Floats("_value", 1.5),
},
static.Table{
static.TimeKey("_start", "2019-11-25T00:00:50Z"),
static.TimeKey("_stop", "2019-11-25T00:01:00Z"),
static.Floats("_value", 3.5),
},
}
if diff := table.Diff(want, ti); diff != "" {
t.Fatalf("table iterators do not match; -want/+got:\n%s", diff)
}
})
t.Run("windowed mean with offset", func(t *testing.T) {
mem := &memory.Allocator{}
ti, err := reader.ReadWindowAggregate(context.Background(), query.ReadWindowAggregateSpec{
ReadFilterSpec: query.ReadFilterSpec{
OrganizationID: reader.Org,
BucketID: reader.Bucket,
Bounds: reader.Bounds,
},
WindowEvery: int64(10 * time.Second),
Offset: int64(2 * time.Second),
Aggregates: []plan.ProcedureKind{
storageflux.MeanKind,
},
}, mem)
if err != nil {
t.Fatal(err)
}
want := static.TableGroup{
static.StringKey("_measurement", "m0"),
static.StringKey("_field", "f0"),
static.StringKey("t0", "a0"),
static.Table{
static.TimeKey("_start", "2019-11-25T00:00:00Z"),
static.TimeKey("_stop", "2019-11-25T00:00:02Z"),
static.Floats("_value", 1.0),
},
static.Table{
static.TimeKey("_start", "2019-11-25T00:00:02Z"),
static.TimeKey("_stop", "2019-11-25T00:00:12Z"),
static.Floats("_value", 2.5),
},
static.Table{
static.TimeKey("_start", "2019-11-25T00:00:12Z"),
static.TimeKey("_stop", "2019-11-25T00:00:22Z"),
static.Floats("_value", 2.5),
},
static.Table{
static.TimeKey("_start", "2019-11-25T00:00:22Z"),
static.TimeKey("_stop", "2019-11-25T00:00:32Z"),
static.Floats("_value", 2.5),
},
static.Table{
static.TimeKey("_start", "2019-11-25T00:00:32Z"),
static.TimeKey("_stop", "2019-11-25T00:00:42Z"),
static.Floats("_value", 2.5),
},
static.Table{
static.TimeKey("_start", "2019-11-25T00:00:42Z"),
static.TimeKey("_stop", "2019-11-25T00:00:52Z"),
static.Floats("_value", 2.5),
},
static.Table{
static.TimeKey("_start", "2019-11-25T00:00:52Z"),
static.TimeKey("_stop", "2019-11-25T00:01:00Z"),
static.Floats("_value", 4),
},
}
if diff := table.Diff(want, ti); diff != "" {
t.Fatalf("table iterators do not match; -want/+got:\n%s", diff)
}
})
}
func TestStorageReader_ReadWindowFirst(t *testing.T) {
reader := NewStorageReader(t, func(org, bucket influxdb.ID) (gen.SeriesGenerator, gen.TimeRange) {
tagsSpec := &gen.TagsSpec{

View File

@ -170,6 +170,23 @@ func newWindowMaxArrayCursor(cur cursors.Cursor, every, offset int64) cursors.Cu
}
}
func newWindowMeanArrayCursor(cur cursors.Cursor, every, offset int64) cursors.Cursor {
switch cur := cur.(type) {
case cursors.FloatArrayCursor:
return newFloatWindowMeanArrayCursor(cur, every, offset)
case cursors.IntegerArrayCursor:
return newIntegerWindowMeanArrayCursor(cur, every, offset)
case cursors.UnsignedArrayCursor:
return newUnsignedWindowMeanArrayCursor(cur, every, offset)
default:
panic(fmt.Sprintf("unsupported for aggregate mean: %T", cur))
}
}
// ********************
// Float Array Cursor
@ -929,6 +946,122 @@ WINDOWS:
return c.res
}
type floatWindowMeanArrayCursor struct {
cursors.FloatArrayCursor
every, offset int64
res *cursors.FloatArray
tmp *cursors.FloatArray
}
func newFloatWindowMeanArrayCursor(cur cursors.FloatArrayCursor, every, offset int64) *floatWindowMeanArrayCursor {
resLen := MaxPointsPerBlock
if every == 0 {
resLen = 1
}
return &floatWindowMeanArrayCursor{
FloatArrayCursor: cur,
every: every,
offset: offset,
res: cursors.NewFloatArrayLen(resLen),
tmp: &cursors.FloatArray{},
}
}
func (c *floatWindowMeanArrayCursor) Stats() cursors.CursorStats {
return c.FloatArrayCursor.Stats()
}
func (c *floatWindowMeanArrayCursor) Next() *cursors.FloatArray {
pos := 0
c.res.Timestamps = c.res.Timestamps[:cap(c.res.Timestamps)]
c.res.Values = c.res.Values[:cap(c.res.Values)]
var a *cursors.FloatArray
if c.tmp.Len() > 0 {
a = c.tmp
} else {
a = c.FloatArrayCursor.Next()
}
if a.Len() == 0 {
return &cursors.FloatArray{}
}
rowIdx := 0
var sum float64
var count int64
var windowEnd int64
if c.every != 0 {
windowEnd = WindowStop(a.Timestamps[rowIdx], c.every, c.offset)
} else {
windowEnd = math.MaxInt64
}
windowHasPoints := false
// enumerate windows
WINDOWS:
for {
for ; rowIdx < a.Len(); rowIdx++ {
ts := a.Timestamps[rowIdx]
if c.every != 0 && ts >= windowEnd {
// new window detected, close the current window
// do not generate a point for empty windows
if windowHasPoints {
c.res.Timestamps[pos] = windowEnd
c.res.Values[pos] = sum / float64(count)
pos++
if pos >= MaxPointsPerBlock {
// the output array is full,
// save the remaining points in the input array in tmp.
// they will be processed in the next call to Next()
c.tmp.Timestamps = a.Timestamps[rowIdx:]
c.tmp.Values = a.Values[rowIdx:]
break WINDOWS
}
}
// start the new window
sum = 0
count = 0
windowEnd = WindowStop(a.Timestamps[rowIdx], c.every, c.offset)
windowHasPoints = false
continue WINDOWS
} else {
sum += a.Values[rowIdx]
count++
windowHasPoints = true
}
}
// Clear buffered 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
// get the next chunk
a = c.FloatArrayCursor.Next()
if a.Len() == 0 {
// write the final point
// do not generate a point for empty windows
if windowHasPoints {
c.res.Timestamps[pos] = windowEnd
c.res.Values[pos] = sum / float64(count)
pos++
}
break WINDOWS
}
rowIdx = 0
}
c.res.Timestamps = c.res.Timestamps[:pos]
c.res.Values = c.res.Values[:pos]
return c.res
}
type floatEmptyArrayCursor struct {
res cursors.FloatArray
}
@ -1699,6 +1832,122 @@ WINDOWS:
return c.res
}
type integerWindowMeanArrayCursor struct {
cursors.IntegerArrayCursor
every, offset int64
res *cursors.FloatArray
tmp *cursors.IntegerArray
}
func newIntegerWindowMeanArrayCursor(cur cursors.IntegerArrayCursor, every, offset int64) *integerWindowMeanArrayCursor {
resLen := MaxPointsPerBlock
if every == 0 {
resLen = 1
}
return &integerWindowMeanArrayCursor{
IntegerArrayCursor: cur,
every: every,
offset: offset,
res: cursors.NewFloatArrayLen(resLen),
tmp: &cursors.IntegerArray{},
}
}
func (c *integerWindowMeanArrayCursor) Stats() cursors.CursorStats {
return c.IntegerArrayCursor.Stats()
}
func (c *integerWindowMeanArrayCursor) Next() *cursors.FloatArray {
pos := 0
c.res.Timestamps = c.res.Timestamps[:cap(c.res.Timestamps)]
c.res.Values = c.res.Values[:cap(c.res.Values)]
var a *cursors.IntegerArray
if c.tmp.Len() > 0 {
a = c.tmp
} else {
a = c.IntegerArrayCursor.Next()
}
if a.Len() == 0 {
return &cursors.FloatArray{}
}
rowIdx := 0
var sum int64
var count int64
var windowEnd int64
if c.every != 0 {
windowEnd = WindowStop(a.Timestamps[rowIdx], c.every, c.offset)
} else {
windowEnd = math.MaxInt64
}
windowHasPoints := false
// enumerate windows
WINDOWS:
for {
for ; rowIdx < a.Len(); rowIdx++ {
ts := a.Timestamps[rowIdx]
if c.every != 0 && ts >= windowEnd {
// new window detected, close the current window
// do not generate a point for empty windows
if windowHasPoints {
c.res.Timestamps[pos] = windowEnd
c.res.Values[pos] = float64(sum) / float64(count)
pos++
if pos >= MaxPointsPerBlock {
// the output array is full,
// save the remaining points in the input array in tmp.
// they will be processed in the next call to Next()
c.tmp.Timestamps = a.Timestamps[rowIdx:]
c.tmp.Values = a.Values[rowIdx:]
break WINDOWS
}
}
// start the new window
sum = 0
count = 0
windowEnd = WindowStop(a.Timestamps[rowIdx], c.every, c.offset)
windowHasPoints = false
continue WINDOWS
} else {
sum += a.Values[rowIdx]
count++
windowHasPoints = true
}
}
// Clear buffered 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
// get the next chunk
a = c.IntegerArrayCursor.Next()
if a.Len() == 0 {
// write the final point
// do not generate a point for empty windows
if windowHasPoints {
c.res.Timestamps[pos] = windowEnd
c.res.Values[pos] = float64(sum) / float64(count)
pos++
}
break WINDOWS
}
rowIdx = 0
}
c.res.Timestamps = c.res.Timestamps[:pos]
c.res.Values = c.res.Values[:pos]
return c.res
}
type integerEmptyArrayCursor struct {
res cursors.IntegerArray
}
@ -2469,6 +2718,122 @@ WINDOWS:
return c.res
}
type unsignedWindowMeanArrayCursor struct {
cursors.UnsignedArrayCursor
every, offset int64
res *cursors.FloatArray
tmp *cursors.UnsignedArray
}
func newUnsignedWindowMeanArrayCursor(cur cursors.UnsignedArrayCursor, every, offset int64) *unsignedWindowMeanArrayCursor {
resLen := MaxPointsPerBlock
if every == 0 {
resLen = 1
}
return &unsignedWindowMeanArrayCursor{
UnsignedArrayCursor: cur,
every: every,
offset: offset,
res: cursors.NewFloatArrayLen(resLen),
tmp: &cursors.UnsignedArray{},
}
}
func (c *unsignedWindowMeanArrayCursor) Stats() cursors.CursorStats {
return c.UnsignedArrayCursor.Stats()
}
func (c *unsignedWindowMeanArrayCursor) Next() *cursors.FloatArray {
pos := 0
c.res.Timestamps = c.res.Timestamps[:cap(c.res.Timestamps)]
c.res.Values = c.res.Values[:cap(c.res.Values)]
var a *cursors.UnsignedArray
if c.tmp.Len() > 0 {
a = c.tmp
} else {
a = c.UnsignedArrayCursor.Next()
}
if a.Len() == 0 {
return &cursors.FloatArray{}
}
rowIdx := 0
var sum uint64
var count int64
var windowEnd int64
if c.every != 0 {
windowEnd = WindowStop(a.Timestamps[rowIdx], c.every, c.offset)
} else {
windowEnd = math.MaxInt64
}
windowHasPoints := false
// enumerate windows
WINDOWS:
for {
for ; rowIdx < a.Len(); rowIdx++ {
ts := a.Timestamps[rowIdx]
if c.every != 0 && ts >= windowEnd {
// new window detected, close the current window
// do not generate a point for empty windows
if windowHasPoints {
c.res.Timestamps[pos] = windowEnd
c.res.Values[pos] = float64(sum) / float64(count)
pos++
if pos >= MaxPointsPerBlock {
// the output array is full,
// save the remaining points in the input array in tmp.
// they will be processed in the next call to Next()
c.tmp.Timestamps = a.Timestamps[rowIdx:]
c.tmp.Values = a.Values[rowIdx:]
break WINDOWS
}
}
// start the new window
sum = 0
count = 0
windowEnd = WindowStop(a.Timestamps[rowIdx], c.every, c.offset)
windowHasPoints = false
continue WINDOWS
} else {
sum += a.Values[rowIdx]
count++
windowHasPoints = true
}
}
// Clear buffered 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
// get the next chunk
a = c.UnsignedArrayCursor.Next()
if a.Len() == 0 {
// write the final point
// do not generate a point for empty windows
if windowHasPoints {
c.res.Timestamps[pos] = windowEnd
c.res.Values[pos] = float64(sum) / float64(count)
pos++
}
break WINDOWS
}
rowIdx = 0
}
c.res.Timestamps = c.res.Timestamps[:pos]
c.res.Values = c.res.Values[:pos]
return c.res
}
type unsignedEmptyArrayCursor struct {
res cursors.UnsignedArray
}

View File

@ -112,6 +112,22 @@ func newWindowMaxArrayCursor(cur cursors.Cursor, every, offset int64) cursors.Cu
panic(fmt.Sprintf("unsupported for aggregate max: %T", cur))
}
}
func newWindowMeanArrayCursor(cur cursors.Cursor, every, offset int64) cursors.Cursor {
switch cur := cur.(type) {
{{range .}}
{{$Type := .Name}}
{{range .Aggs}}
{{if eq .Name "Mean"}}
case cursors.{{$Type}}ArrayCursor:
return new{{$Type}}WindowMeanArrayCursor(cur, every, offset)
{{end}}
{{end}}{{/* for each supported agg fn */}}
{{end}}{{/* for each field type */}}
default:
panic(fmt.Sprintf("unsupported for aggregate mean: %T", cur))
}
}
{{range .}}
{{$arrayType := print "*cursors." .Name "Array"}}
{{$type := print .name "ArrayFilterCursor"}}

View File

@ -35,6 +35,14 @@
"Accumulate":"if !windowHasPoints || a.Values[rowIdx] > acc { acc = a.Values[rowIdx]; tsAcc = a.Timestamps[rowIdx] }",
"AccEmit":"c.res.Timestamps[pos] = tsAcc; c.res.Values[pos] = acc",
"AccReset":"acc = -math.MaxFloat64"
},
{
"Name":"Mean",
"OutputTypeName":"Float",
"AccDecls":"var sum float64; var count int64",
"Accumulate":"sum += a.Values[rowIdx]; count++",
"AccEmit":"c.res.Timestamps[pos] = windowEnd; c.res.Values[pos] = sum / float64(count)",
"AccReset":"sum = 0; count = 0"
}
]
},
@ -74,6 +82,14 @@
"Accumulate":"if !windowHasPoints || a.Values[rowIdx] > acc { acc = a.Values[rowIdx]; tsAcc = a.Timestamps[rowIdx] }",
"AccEmit":"c.res.Timestamps[pos] = tsAcc; c.res.Values[pos] = acc",
"AccReset":"acc = math.MinInt64"
},
{
"Name":"Mean",
"OutputTypeName":"Float",
"AccDecls":"var sum int64; var count int64",
"Accumulate":"sum += a.Values[rowIdx]; count++",
"AccEmit":"c.res.Timestamps[pos] = windowEnd; c.res.Values[pos] = float64(sum) / float64(count)",
"AccReset":"sum = 0; count = 0"
}
]
},
@ -113,6 +129,14 @@
"Accumulate":"if !windowHasPoints || a.Values[rowIdx] > acc { acc = a.Values[rowIdx]; tsAcc = a.Timestamps[rowIdx] }",
"AccEmit":"c.res.Timestamps[pos] = tsAcc; c.res.Values[pos] = acc",
"AccReset":"acc = 0"
},
{
"Name":"Mean",
"OutputTypeName":"Float",
"AccDecls":"var sum uint64; var count int64",
"Accumulate":"sum += a.Values[rowIdx]; count++",
"AccEmit":"c.res.Timestamps[pos] = windowEnd; c.res.Values[pos] = float64(sum) / float64(count)",
"AccReset":"sum = 0; count = 0"
}
]
},

View File

@ -42,6 +42,8 @@ func newWindowAggregateArrayCursor(ctx context.Context, agg *datatypes.Aggregate
return newWindowMinArrayCursor(cursor, every, offset)
case datatypes.AggregateTypeMax:
return newWindowMaxArrayCursor(cursor, every, offset)
case datatypes.AggregateTypeMean:
return newWindowMeanArrayCursor(cursor, every, offset)
default:
// TODO(sgc): should be validated higher up
panic("invalid aggregate")

View File

@ -102,6 +102,24 @@ func TestNewAggregateArrayCursor_Float(t *testing.T) {
}
})
t.Run("Mean", func(t *testing.T) {
want := &floatWindowMeanArrayCursor{
FloatArrayCursor: &MockFloatArrayCursor{},
res: cursors.NewFloatArrayLen(1),
tmp: &cursors.FloatArray{},
}
agg := &datatypes.Aggregate{
Type: datatypes.AggregateTypeMean,
}
got := newAggregateArrayCursor(context.Background(), agg, &MockFloatArrayCursor{})
if diff := cmp.Diff(got, want, cmp.AllowUnexported(floatWindowMeanArrayCursor{})); diff != "" {
t.Fatalf("did not get expected cursor; -got/+want:\n%v", diff)
}
})
}
func TestNewWindowAggregateArrayCursor_Float(t *testing.T) {
@ -182,6 +200,25 @@ func TestNewWindowAggregateArrayCursor_Float(t *testing.T) {
}
})
t.Run("Mean", func(t *testing.T) {
want := &floatWindowMeanArrayCursor{
FloatArrayCursor: &MockFloatArrayCursor{},
every: int64(time.Hour),
res: cursors.NewFloatArrayLen(MaxPointsPerBlock),
tmp: &cursors.FloatArray{},
}
agg := &datatypes.Aggregate{
Type: datatypes.AggregateTypeMean,
}
got := newWindowAggregateArrayCursor(context.Background(), agg, int64(time.Hour), 0, &MockFloatArrayCursor{})
if diff := cmp.Diff(got, want, cmp.AllowUnexported(floatWindowMeanArrayCursor{})); diff != "" {
t.Fatalf("did not get expected cursor; -got/+want:\n%v", diff)
}
})
}
type MockIntegerArrayCursor struct {
@ -270,6 +307,24 @@ func TestNewAggregateArrayCursor_Integer(t *testing.T) {
}
})
t.Run("Mean", func(t *testing.T) {
want := &integerWindowMeanArrayCursor{
IntegerArrayCursor: &MockIntegerArrayCursor{},
res: cursors.NewFloatArrayLen(1),
tmp: &cursors.IntegerArray{},
}
agg := &datatypes.Aggregate{
Type: datatypes.AggregateTypeMean,
}
got := newAggregateArrayCursor(context.Background(), agg, &MockIntegerArrayCursor{})
if diff := cmp.Diff(got, want, cmp.AllowUnexported(integerWindowMeanArrayCursor{})); diff != "" {
t.Fatalf("did not get expected cursor; -got/+want:\n%v", diff)
}
})
}
func TestNewWindowAggregateArrayCursor_Integer(t *testing.T) {
@ -350,6 +405,25 @@ func TestNewWindowAggregateArrayCursor_Integer(t *testing.T) {
}
})
t.Run("Mean", func(t *testing.T) {
want := &integerWindowMeanArrayCursor{
IntegerArrayCursor: &MockIntegerArrayCursor{},
every: int64(time.Hour),
res: cursors.NewFloatArrayLen(MaxPointsPerBlock),
tmp: &cursors.IntegerArray{},
}
agg := &datatypes.Aggregate{
Type: datatypes.AggregateTypeMean,
}
got := newWindowAggregateArrayCursor(context.Background(), agg, int64(time.Hour), 0, &MockIntegerArrayCursor{})
if diff := cmp.Diff(got, want, cmp.AllowUnexported(integerWindowMeanArrayCursor{})); diff != "" {
t.Fatalf("did not get expected cursor; -got/+want:\n%v", diff)
}
})
}
type MockUnsignedArrayCursor struct {
@ -438,6 +512,24 @@ func TestNewAggregateArrayCursor_Unsigned(t *testing.T) {
}
})
t.Run("Mean", func(t *testing.T) {
want := &unsignedWindowMeanArrayCursor{
UnsignedArrayCursor: &MockUnsignedArrayCursor{},
res: cursors.NewFloatArrayLen(1),
tmp: &cursors.UnsignedArray{},
}
agg := &datatypes.Aggregate{
Type: datatypes.AggregateTypeMean,
}
got := newAggregateArrayCursor(context.Background(), agg, &MockUnsignedArrayCursor{})
if diff := cmp.Diff(got, want, cmp.AllowUnexported(unsignedWindowMeanArrayCursor{})); diff != "" {
t.Fatalf("did not get expected cursor; -got/+want:\n%v", diff)
}
})
}
func TestNewWindowAggregateArrayCursor_Unsigned(t *testing.T) {
@ -518,6 +610,25 @@ func TestNewWindowAggregateArrayCursor_Unsigned(t *testing.T) {
}
})
t.Run("Mean", func(t *testing.T) {
want := &unsignedWindowMeanArrayCursor{
UnsignedArrayCursor: &MockUnsignedArrayCursor{},
every: int64(time.Hour),
res: cursors.NewFloatArrayLen(MaxPointsPerBlock),
tmp: &cursors.UnsignedArray{},
}
agg := &datatypes.Aggregate{
Type: datatypes.AggregateTypeMean,
}
got := newWindowAggregateArrayCursor(context.Background(), agg, int64(time.Hour), 0, &MockUnsignedArrayCursor{})
if diff := cmp.Diff(got, want, cmp.AllowUnexported(unsignedWindowMeanArrayCursor{})); diff != "" {
t.Fatalf("did not get expected cursor; -got/+want:\n%v", diff)
}
})
}
type MockStringArrayCursor struct {

View File

@ -56,6 +56,20 @@ func makeIntegerArray(n int, tsStart time.Time, tsStep time.Duration, valueFn fu
return ia
}
func makeFloatArray(n int, tsStart time.Time, tsStep time.Duration, valueFn func(i int64) float64) *cursors.FloatArray {
fa := &cursors.FloatArray{
Timestamps: make([]int64, n),
Values: make([]float64, n),
}
for i := 0; i < n; i++ {
fa.Timestamps[i] = tsStart.UnixNano() + int64(i)*int64(tsStep)
fa.Values[i] = valueFn(int64(i))
}
return fa
}
func mustParseTime(ts string) time.Time {
t, err := time.Parse(time.RFC3339, ts)
if err != nil {
@ -71,13 +85,21 @@ func copyIntegerArray(src *cursors.IntegerArray) *cursors.IntegerArray {
return dst
}
func copyFloatArray(src *cursors.FloatArray) *cursors.FloatArray {
dst := cursors.NewFloatArrayLen(src.Len())
copy(dst.Timestamps, src.Timestamps)
copy(dst.Values, src.Values)
return dst
}
type aggArrayCursorTest struct {
name string
createCursorFn func(cur cursors.IntegerArrayCursor, every, offset int64) cursors.IntegerArrayCursor
createCursorFn func(cur cursors.IntegerArrayCursor, every, offset int64) cursors.Cursor
every time.Duration
offset time.Duration
inputArrays []*cursors.IntegerArray
want []*cursors.IntegerArray
wantIntegers []*cursors.IntegerArray
wantFloats []*cursors.FloatArray
}
func (a *aggArrayCursorTest) run(t *testing.T) {
@ -97,16 +119,29 @@ func (a *aggArrayCursorTest) run(t *testing.T) {
return &cursors.IntegerArray{}
},
}
cursor := a.createCursorFn(mc, int64(a.every), int64(a.offset))
got := make([]*cursors.IntegerArray, 0, len(a.want))
for a := cursor.Next(); a.Len() != 0; a = cursor.Next() {
got = append(got, copyIntegerArray(a))
}
c := a.createCursorFn(mc, int64(a.every), int64(a.offset))
switch cursor := c.(type) {
case cursors.IntegerArrayCursor:
got := make([]*cursors.IntegerArray, 0, len(a.wantIntegers))
for a := cursor.Next(); a.Len() != 0; a = cursor.Next() {
got = append(got, copyIntegerArray(a))
}
if diff := cmp.Diff(got, a.want); diff != "" {
t.Fatalf("did not get expected result from count array cursor; -got/+want:\n%v", diff)
}
if diff := cmp.Diff(got, a.wantIntegers); diff != "" {
t.Fatalf("did not get expected result from count array cursor; -got/+want:\n%v", diff)
}
case cursors.FloatArrayCursor:
got := make([]*cursors.FloatArray, 0, len(a.wantFloats))
for a := cursor.Next(); a.Len() != 0; a = cursor.Next() {
got = append(got, copyFloatArray(a))
}
if diff := cmp.Diff(got, a.wantFloats); diff != "" {
t.Fatalf("did not get expected result from count array cursor; -got/+want:\n%v", diff)
}
default:
t.Fatalf("unsupported cursor type: %T", cursor)
}
})
}
@ -163,7 +198,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
4,
mustParseTime("2010-01-01T00:00:00Z"), 15*time.Minute,
@ -182,7 +217,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
{
Timestamps: []int64{
mustParseTime("2010-01-01T00:00:00Z").UnixNano(),
@ -205,7 +240,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
4,
mustParseTime("2010-01-01T00:00:00Z"), 15*time.Minute,
@ -224,7 +259,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
4,
mustParseTime("2010-01-01T00:00:00Z"), 15*time.Minute,
@ -242,7 +277,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
4,
mustParseTime("2010-01-01T00:00:30Z"), 15*time.Minute,
@ -261,7 +296,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
{
Timestamps: []int64{
mustParseTime("2010-01-01T00:00:30Z").UnixNano(),
@ -284,7 +319,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
{
Timestamps: []int64{
mustParseTime("2010-01-01T00:01:30Z").UnixNano(),
@ -312,7 +347,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return 60 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
8,
mustParseTime("2010-01-01T00:00:00Z"), 15*time.Minute,
@ -336,7 +371,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return 60 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
{
Timestamps: []int64{
mustParseTime("2010-01-01T00:00:00Z").UnixNano(),
@ -364,7 +399,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return 60 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
3,
mustParseTime("2010-01-01T00:00:00Z"), 40*time.Minute,
@ -388,7 +423,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return 60 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
{
Timestamps: []int64{
mustParseTime("2010-01-01T00:00:00Z").UnixNano(),
@ -420,7 +455,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return 2000 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
1000,
mustParseTime("2010-01-01T00:00:00.000Z"), 2*time.Millisecond,
@ -454,7 +489,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return 2000 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
func() *cursors.IntegerArray {
arr := makeIntegerArray(
999,
@ -482,7 +517,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return 100 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
1,
mustParseTime("2010-01-01T00:00:00Z"), time.Minute,
@ -491,9 +526,9 @@ func TestWindowFirstArrayCursor(t *testing.T) {
},
},
{
name: "whole series no points",
inputArrays: []*cursors.IntegerArray{{}},
want: []*cursors.IntegerArray{},
name: "whole series no points",
inputArrays: []*cursors.IntegerArray{{}},
wantIntegers: []*cursors.IntegerArray{},
},
{
name: "whole series two arrays",
@ -509,7 +544,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return 70 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
1,
mustParseTime("2010-01-01T00:00:00Z"), time.Minute,
@ -526,7 +561,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return 100 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
1,
mustParseTime("1969-12-31T23:00:00Z"), time.Minute,
@ -548,7 +583,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
func(i int64) int64 { return 160 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
1,
mustParseTime("1969-12-31T23:00:00Z"), time.Minute,
@ -564,7 +599,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
Values: []int64{12},
},
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
{
Timestamps: []int64{math.MaxInt64},
Values: []int64{12},
@ -573,7 +608,7 @@ func TestWindowFirstArrayCursor(t *testing.T) {
},
}
for _, tc := range testcases {
tc.createCursorFn = func(cur cursors.IntegerArrayCursor, every, offset int64) cursors.IntegerArrayCursor {
tc.createCursorFn = func(cur cursors.IntegerArrayCursor, every, offset int64) cursors.Cursor {
if every == 0 {
return newIntegerLimitArrayCursor(cur)
}
@ -595,7 +630,7 @@ func TestWindowLastArrayCursor(t *testing.T) {
func(i int64) int64 { return i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
4,
mustParseTime("2010-01-01T00:14:00Z"), 15*time.Minute,
@ -613,7 +648,7 @@ func TestWindowLastArrayCursor(t *testing.T) {
func(i int64) int64 { return i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
4,
mustParseTime("2010-01-01T00:00:00Z"), 15*time.Minute,
@ -631,7 +666,7 @@ func TestWindowLastArrayCursor(t *testing.T) {
func(i int64) int64 { return i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
4,
mustParseTime("2010-01-01T00:14:30Z"), 15*time.Minute,
@ -649,7 +684,7 @@ func TestWindowLastArrayCursor(t *testing.T) {
func(i int64) int64 { return i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
{
Timestamps: []int64{
mustParseTime("2010-01-01T00:14:30Z").UnixNano(),
@ -677,7 +712,7 @@ func TestWindowLastArrayCursor(t *testing.T) {
func(i int64) int64 { return 60 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
8,
mustParseTime("2010-01-01T00:14:00Z"), 15*time.Minute,
@ -700,7 +735,7 @@ func TestWindowLastArrayCursor(t *testing.T) {
func(i int64) int64 { return 60 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
3,
mustParseTime("2010-01-01T00:39:00Z"), 40*time.Minute,
@ -728,7 +763,7 @@ func TestWindowLastArrayCursor(t *testing.T) {
func(i int64) int64 { return 2000 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
1000,
mustParseTime("2010-01-01T00:00:00.001Z"), 2*time.Millisecond,
@ -756,7 +791,7 @@ func TestWindowLastArrayCursor(t *testing.T) {
func(i int64) int64 { return 1000 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
1000,
mustParseTime("2010-01-01T00:00:00Z"), time.Millisecond,
@ -771,7 +806,7 @@ func TestWindowLastArrayCursor(t *testing.T) {
},
}
for _, tc := range testcases {
tc.createCursorFn = func(cur cursors.IntegerArrayCursor, every, offset int64) cursors.IntegerArrayCursor {
tc.createCursorFn = func(cur cursors.IntegerArrayCursor, every, offset int64) cursors.Cursor {
return newIntegerWindowLastArrayCursor(cur, every, offset)
}
tc.run(t)
@ -792,7 +827,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return 100 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(4, mustParseTime("2010-01-01T00:15:00Z"), 15*time.Minute, func(int64) int64 { return 15 }),
},
},
@ -807,7 +842,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(5, mustParseTime("2010-01-01T00:01:00Z"), 15*time.Minute, func(i int64) int64 {
switch i {
case 0:
@ -830,7 +865,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return 100 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
4,
mustParseTime("2010-01-01T00:01:00Z"), 15*time.Minute,
@ -849,7 +884,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return 100 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
4,
mustParseTime("2010-01-01T00:01:00Z"), 15*time.Minute,
@ -867,7 +902,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return 100 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
4,
mustParseTime("2010-01-01T00:15:00Z"), 15*time.Minute,
@ -887,7 +922,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
5,
mustParseTime("2010-01-01T00:00:45Z"), 15*time.Minute,
@ -913,7 +948,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return 100 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
5,
mustParseTime("2010-01-01T00:15:00Z"), 15*time.Minute,
@ -944,7 +979,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return 200 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(8, mustParseTime("2010-01-01T00:15:00Z"), 15*time.Minute, func(int64) int64 { return 15 }),
},
},
@ -964,7 +999,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return 60 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(5, mustParseTime("2010-01-01T00:27:00Z"), 30*time.Minute, func(i int64) int64 {
switch i {
case 0:
@ -992,7 +1027,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return 200 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(3, mustParseTime("2010-01-01T00:40:00Z"), 40*time.Minute, func(int64) int64 { return 40 }),
},
},
@ -1012,7 +1047,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return 60 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(4, mustParseTime("2010-01-01T00:10:00Z"), 40*time.Minute, func(i int64) int64 {
switch i {
case 0:
@ -1045,7 +1080,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
1000,
mustParseTime("2010-01-01T00:00:00.002Z"), 2*time.Millisecond,
@ -1079,7 +1114,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return 2000 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
1000,
mustParseTime("2010-01-01T00:00:00.001Z"), 2*time.Millisecond,
@ -1115,14 +1150,14 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return 100 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(1, maxTimestamp, 40*time.Minute, func(i int64) int64 { return 60 }),
},
},
{
name: "whole series no points",
inputArrays: []*cursors.IntegerArray{{}},
want: []*cursors.IntegerArray{},
name: "whole series no points",
inputArrays: []*cursors.IntegerArray{{}},
wantIntegers: []*cursors.IntegerArray{},
},
{
name: "whole series two arrays",
@ -1138,7 +1173,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return 100 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(1, maxTimestamp, 40*time.Minute, func(int64) int64 { return 120 }),
},
},
@ -1151,7 +1186,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return 100 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(1, maxTimestamp, 40*time.Minute, func(int64) int64 { return 120 }),
},
},
@ -1169,7 +1204,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
func(i int64) int64 { return 100 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(1, maxTimestamp, 40*time.Minute, func(int64) int64 { return 120 }),
},
},
@ -1181,7 +1216,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
Values: []int64{0},
},
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
{
Timestamps: []int64{math.MaxInt64},
Values: []int64{1},
@ -1190,7 +1225,7 @@ func TestIntegerCountArrayCursor(t *testing.T) {
},
}
for _, tc := range testcases {
tc.createCursorFn = func(cur cursors.IntegerArrayCursor, every, offset int64) cursors.IntegerArrayCursor {
tc.createCursorFn = func(cur cursors.IntegerArrayCursor, every, offset int64) cursors.Cursor {
return newIntegerWindowCountArrayCursor(cur, every, offset)
}
tc.run(t)
@ -1211,7 +1246,7 @@ func TestIntegerSumArrayCursor(t *testing.T) {
func(i int64) int64 { return 2 },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(4, mustParseTime("2010-01-01T00:15:00Z"), 15*time.Minute, func(int64) int64 { return 30 }),
},
},
@ -1225,7 +1260,7 @@ func TestIntegerSumArrayCursor(t *testing.T) {
func(i int64) int64 { return 100 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
4,
mustParseTime("2010-01-01T00:01:00Z"), 15*time.Minute,
@ -1243,7 +1278,7 @@ func TestIntegerSumArrayCursor(t *testing.T) {
func(i int64) int64 { return 2 },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
4,
mustParseTime("2010-01-01T00:15:00Z"), 15*time.Minute,
@ -1262,7 +1297,7 @@ func TestIntegerSumArrayCursor(t *testing.T) {
func(i int64) int64 { return 2 },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
5,
mustParseTime("2010-01-01T00:15:00Z"), 15*time.Minute,
@ -1293,7 +1328,7 @@ func TestIntegerSumArrayCursor(t *testing.T) {
func(i int64) int64 { return 3 },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(8, mustParseTime("2010-01-01T00:15:00Z"), 15*time.Minute,
func(i int64) int64 {
if i < 4 {
@ -1319,7 +1354,7 @@ func TestIntegerSumArrayCursor(t *testing.T) {
func(i int64) int64 { return 3 },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(3, mustParseTime("2010-01-01T00:40:00Z"), 40*time.Minute,
func(i int64) int64 {
switch i {
@ -1354,7 +1389,7 @@ func TestIntegerSumArrayCursor(t *testing.T) {
func(i int64) int64 { return 4 },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(
1000,
mustParseTime("2010-01-01T00:00:00.002Z"), 2*time.Millisecond,
@ -1382,14 +1417,14 @@ func TestIntegerSumArrayCursor(t *testing.T) {
func(i int64) int64 { return 2 },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(1, maxTimestamp, 40*time.Minute, func(i int64) int64 { return 120 }),
},
},
{
name: "whole series no points",
inputArrays: []*cursors.IntegerArray{{}},
want: []*cursors.IntegerArray{},
name: "whole series no points",
inputArrays: []*cursors.IntegerArray{{}},
wantIntegers: []*cursors.IntegerArray{},
},
{
name: "whole series two arrays",
@ -1405,7 +1440,7 @@ func TestIntegerSumArrayCursor(t *testing.T) {
func(i int64) int64 { return 3 },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(1, maxTimestamp, 40*time.Minute,
func(int64) int64 {
return 300
@ -1421,7 +1456,7 @@ func TestIntegerSumArrayCursor(t *testing.T) {
func(i int64) int64 { return 2 },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(1, maxTimestamp, 40*time.Minute, func(int64) int64 { return 240 }),
},
},
@ -1439,7 +1474,7 @@ func TestIntegerSumArrayCursor(t *testing.T) {
func(i int64) int64 { return 3 },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(1, maxTimestamp, 40*time.Minute, func(int64) int64 { return 300 }),
},
},
@ -1451,7 +1486,7 @@ func TestIntegerSumArrayCursor(t *testing.T) {
Values: []int64{100},
},
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
{
Timestamps: []int64{math.MaxInt64},
Values: []int64{100},
@ -1460,7 +1495,7 @@ func TestIntegerSumArrayCursor(t *testing.T) {
},
}
for _, tc := range testcases {
tc.createCursorFn = func(cur cursors.IntegerArrayCursor, every, offset int64) cursors.IntegerArrayCursor {
tc.createCursorFn = func(cur cursors.IntegerArrayCursor, every, offset int64) cursors.Cursor {
return newIntegerWindowSumArrayCursor(cur, every, offset)
}
tc.run(t)
@ -1479,7 +1514,7 @@ func TestWindowMinArrayCursor(t *testing.T) {
func(i int64) int64 { return 100 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(1, mustParseTime("2010-01-01T00:00:00Z"), 0, func(int64) int64 { return 100 }),
},
},
@ -1498,7 +1533,7 @@ func TestWindowMinArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(1, mustParseTime("2010-01-01T00:00:00Z"), 0, func(int64) int64 { return math.MinInt64 }),
},
},
@ -1517,7 +1552,7 @@ func TestWindowMinArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(1, mustParseTime("2010-01-01T00:01:00Z"), 0, func(int64) int64 { return 0 }),
},
},
@ -1535,7 +1570,7 @@ func TestWindowMinArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(4, mustParseTime("2010-01-01T00:00:00Z"), time.Hour,
func(i int64) int64 { return i * 100 }),
},
@ -1555,7 +1590,7 @@ func TestWindowMinArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
{
Timestamps: []int64{
mustParseTime("2010-01-01T00:00:00Z").UnixNano(),
@ -1582,7 +1617,7 @@ func TestWindowMinArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(4, mustParseTime("2010-01-01T00:45:00Z"), time.Hour,
func(i int64) int64 { return i*100 + 15 }),
},
@ -1602,7 +1637,7 @@ func TestWindowMinArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
{
Timestamps: []int64{
mustParseTime("2010-01-01T00:15:00Z").UnixNano(),
@ -1627,7 +1662,7 @@ func TestWindowMinArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(4, mustParseTime("2010-01-01T00:00:00Z"), time.Hour,
func(i int64) int64 { return math.MinInt64 }),
},
@ -1644,7 +1679,7 @@ func TestWindowMinArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(4, mustParseTime("2010-01-01T00:00:00Z"), time.Hour,
func(i int64) int64 { return math.MaxInt64 }),
},
@ -1661,14 +1696,14 @@ func TestWindowMinArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(2, mustParseTime("2010-01-01T00:05:00Z"), 30*time.Minute,
func(i int64) int64 { return 100 + i }),
},
},
}
for _, tc := range testcases {
tc.createCursorFn = func(cur cursors.IntegerArrayCursor, every, offset int64) cursors.IntegerArrayCursor {
tc.createCursorFn = func(cur cursors.IntegerArrayCursor, every, offset int64) cursors.Cursor {
return newIntegerWindowMinArrayCursor(cur, every, offset)
}
tc.run(t)
@ -1687,7 +1722,7 @@ func TestWindowMaxArrayCursor(t *testing.T) {
func(i int64) int64 { return 100 + i },
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(1, mustParseTime("2010-01-01T00:59:00Z"), 0, func(int64) int64 { return 159 }),
},
},
@ -1706,7 +1741,7 @@ func TestWindowMaxArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(1, mustParseTime("2010-01-01T00:01:00Z"), 0, func(int64) int64 { return 0 }),
},
},
@ -1725,7 +1760,7 @@ func TestWindowMaxArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(1, mustParseTime("2010-01-01T00:00:00Z"), 0, func(int64) int64 { return math.MaxInt64 }),
},
},
@ -1743,7 +1778,7 @@ func TestWindowMaxArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(4, mustParseTime("2010-01-01T00:45:00Z"), time.Hour,
func(i int64) int64 { return i*100 + 45 }),
},
@ -1763,7 +1798,7 @@ func TestWindowMaxArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
{
Timestamps: []int64{
mustParseTime("2010-01-01T00:15:00Z").UnixNano(),
@ -1790,7 +1825,7 @@ func TestWindowMaxArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(4, mustParseTime("2010-01-01T00:00:00Z"), time.Hour,
func(i int64) int64 { return i*100 + 60 }),
},
@ -1810,7 +1845,7 @@ func TestWindowMaxArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
{
Timestamps: []int64{
mustParseTime("2010-01-01T00:00:00Z").UnixNano(),
@ -1835,7 +1870,7 @@ func TestWindowMaxArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(4, mustParseTime("2010-01-01T00:00:00Z"), time.Hour,
func(i int64) int64 { return math.MinInt64 }),
},
@ -1852,7 +1887,7 @@ func TestWindowMaxArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(4, mustParseTime("2010-01-01T00:00:00Z"), time.Hour,
func(i int64) int64 { return math.MaxInt64 }),
},
@ -1869,20 +1904,119 @@ func TestWindowMaxArrayCursor(t *testing.T) {
},
),
},
want: []*cursors.IntegerArray{
wantIntegers: []*cursors.IntegerArray{
makeIntegerArray(2, mustParseTime("2010-01-01T00:05:00Z"), 30*time.Minute,
func(i int64) int64 { return 100 + i }),
},
},
}
for _, tc := range testcases {
tc.createCursorFn = func(cur cursors.IntegerArrayCursor, every, offset int64) cursors.IntegerArrayCursor {
tc.createCursorFn = func(cur cursors.IntegerArrayCursor, every, offset int64) cursors.Cursor {
return newIntegerWindowMaxArrayCursor(cur, every, offset)
}
tc.run(t)
}
}
func TestWindowMeanArrayCursor(t *testing.T) {
maxTimestamp := time.Unix(0, math.MaxInt64)
testcases := []aggArrayCursorTest{
{
name: "no window",
every: 0,
inputArrays: []*cursors.IntegerArray{
makeIntegerArray(
5,
mustParseTime("2010-01-01T00:00:00Z"), time.Minute,
func(i int64) int64 { return i + 1 },
),
},
wantFloats: []*cursors.FloatArray{
makeFloatArray(1, maxTimestamp, 0, func(int64) float64 { return 3.0 }),
},
},
{
name: "no window fraction result",
every: 0,
inputArrays: []*cursors.IntegerArray{
makeIntegerArray(
6,
mustParseTime("2010-01-01T00:00:00Z"), time.Minute,
func(i int64) int64 { return i + 1 },
),
},
wantFloats: []*cursors.FloatArray{
makeFloatArray(1, maxTimestamp, 0, func(int64) float64 { return 3.5 }),
},
},
{
name: "no window empty",
every: 0,
inputArrays: []*cursors.IntegerArray{},
wantFloats: []*cursors.FloatArray{},
},
{
name: "window",
every: 30 * time.Minute,
inputArrays: []*cursors.IntegerArray{
makeIntegerArray(
8,
mustParseTime("2010-01-01T00:00:00Z"), 15*time.Minute,
func(i int64) int64 {
return i
},
),
},
wantFloats: []*cursors.FloatArray{
makeFloatArray(4, mustParseTime("2010-01-01T00:30:00Z"), 30*time.Minute,
func(i int64) float64 { return 0.5 + float64(i)*2 }),
},
},
{
name: "window offset",
every: 30 * time.Minute,
offset: 5 * time.Minute,
inputArrays: []*cursors.IntegerArray{
makeIntegerArray(
8,
mustParseTime("2010-01-01T00:00:00Z"), 15*time.Minute,
func(i int64) int64 {
return i
},
),
},
wantFloats: []*cursors.FloatArray{
makeFloatArray(5, mustParseTime("2010-01-01T00:05:00Z"), 30*time.Minute,
func(i int64) float64 { return []float64{0, 1.5, 3.5, 5.5, 7}[i] }),
},
},
{
name: "empty window",
every: 15 * time.Minute,
inputArrays: []*cursors.IntegerArray{
makeIntegerArray(
2,
mustParseTime("2010-01-01T00:05:00Z"), 30*time.Minute,
func(i int64) int64 {
return 100 + i
},
),
},
wantFloats: []*cursors.FloatArray{
makeFloatArray(2, mustParseTime("2010-01-01T00:15:00Z"), 30*time.Minute,
func(i int64) float64 { return 100 + float64(i) }),
},
},
}
for _, tc := range testcases {
tc.createCursorFn = func(cur cursors.IntegerArrayCursor, every, offset int64) cursors.Cursor {
return newIntegerWindowMeanArrayCursor(cur, every, offset)
}
tc.run(t)
}
}
type MockExpression struct {
EvalBoolFunc func(v Valuer) bool
}

View File

@ -99,6 +99,7 @@ const (
AggregateTypeMax Aggregate_AggregateType = 4
AggregateTypeFirst Aggregate_AggregateType = 5
AggregateTypeLast Aggregate_AggregateType = 6
AggregateTypeMean Aggregate_AggregateType = 7
)
var Aggregate_AggregateType_name = map[int32]string{
@ -109,6 +110,7 @@ var Aggregate_AggregateType_name = map[int32]string{
4: "MAX",
5: "FIRST",
6: "LAST",
7: "MEAN",
}
var Aggregate_AggregateType_value = map[string]int32{
@ -119,6 +121,7 @@ var Aggregate_AggregateType_value = map[string]int32{
"MAX": 4,
"FIRST": 5,
"LAST": 6,
"MEAN": 7,
}
func (x Aggregate_AggregateType) String() string {
@ -1404,119 +1407,120 @@ func init() {
func init() { proto.RegisterFile("storage_common.proto", fileDescriptor_715e4bf4cdf1f73d) }
var fileDescriptor_715e4bf4cdf1f73d = []byte{
// 1787 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x58, 0xcd, 0x6f, 0x23, 0x49,
0x15, 0x77, 0xfb, 0x2b, 0xe9, 0x67, 0xc7, 0xd3, 0xa9, 0x0d, 0xb3, 0x99, 0x9e, 0x1d, 0xbb, 0xd7,
0xc0, 0x6e, 0x24, 0x06, 0x47, 0xca, 0x2e, 0xd2, 0x6a, 0x60, 0x25, 0xe2, 0x8c, 0x13, 0x9b, 0x89,
0xed, 0xa8, 0xec, 0x2c, 0x1f, 0x17, 0x53, 0x89, 0xcb, 0xbd, 0xad, 0xb5, 0xbb, 0x4d, 0x77, 0x7b,
0x18, 0x4b, 0x5c, 0xb8, 0xad, 0x7c, 0x02, 0x09, 0x2e, 0x48, 0x3e, 0x71, 0xe4, 0xce, 0xdf, 0x30,
0x48, 0x1c, 0x56, 0x1c, 0x10, 0x27, 0x0b, 0x3c, 0x12, 0x12, 0x57, 0x6e, 0x0c, 0x17, 0x54, 0x1f,
0xdd, 0x6e, 0x67, 0x42, 0xd6, 0x1e, 0xcd, 0x61, 0x34, 0x7b, 0xab, 0x7a, 0xef, 0xd5, 0xef, 0xd5,
0x7b, 0xfd, 0xbe, 0xba, 0x60, 0xc7, 0xf3, 0x1d, 0x97, 0x98, 0xb4, 0x73, 0xe9, 0x0c, 0x06, 0x8e,
0x5d, 0x1a, 0xba, 0x8e, 0xef, 0xa0, 0xbb, 0x96, 0xdd, 0xeb, 0x8f, 0x9e, 0x74, 0x89, 0x4f, 0x4a,
0xc3, 0x3e, 0xf1, 0x7b, 0x8e, 0x3b, 0x28, 0x49, 0x49, 0x7d, 0xc7, 0x74, 0x4c, 0x87, 0xcb, 0xed,
0xb3, 0x95, 0x38, 0xa2, 0xdf, 0x31, 0x1d, 0xc7, 0xec, 0xd3, 0x7d, 0xbe, 0xbb, 0x18, 0xf5, 0xf6,
0x89, 0x3d, 0x96, 0xac, 0x5b, 0x43, 0x97, 0x76, 0xad, 0x4b, 0xe2, 0x53, 0x41, 0x28, 0xfe, 0x4b,
0x81, 0x6d, 0x4c, 0x49, 0xf7, 0xd8, 0xea, 0xfb, 0xd4, 0xc5, 0xf4, 0x67, 0x23, 0xea, 0xf9, 0xa8,
0x02, 0x19, 0x97, 0x92, 0x6e, 0xc7, 0x73, 0x46, 0xee, 0x25, 0xdd, 0x55, 0x0c, 0x65, 0x2f, 0x73,
0xb0, 0x53, 0x12, 0xb8, 0xa5, 0x00, 0xb7, 0x74, 0x68, 0x8f, 0xcb, 0xb9, 0xf9, 0xac, 0x00, 0x0c,
0xa1, 0xc5, 0x65, 0x31, 0xb8, 0xe1, 0x1a, 0x9d, 0x40, 0xca, 0x25, 0xb6, 0x49, 0x77, 0xe3, 0x1c,
0xe0, 0x5b, 0xa5, 0x1b, 0x6c, 0x29, 0xb5, 0xad, 0x01, 0xf5, 0x7c, 0x32, 0x18, 0x62, 0x76, 0xa4,
0x9c, 0x7c, 0x3a, 0x2b, 0xc4, 0xb0, 0x38, 0x8f, 0x1e, 0x82, 0x1a, 0x5e, 0x7c, 0x37, 0xc1, 0xc1,
0xde, 0xbb, 0x11, 0xec, 0x2c, 0x90, 0xc6, 0x8b, 0x83, 0xc5, 0x3f, 0xa7, 0x40, 0x63, 0x37, 0x3d,
0x71, 0x9d, 0xd1, 0xf0, 0x8d, 0x36, 0x15, 0xdd, 0x07, 0x30, 0x99, 0x95, 0x9d, 0xcf, 0xe8, 0xd8,
0xdb, 0x4d, 0x1a, 0x89, 0x3d, 0xb5, 0xbc, 0x35, 0x9f, 0x15, 0x54, 0x6e, 0xfb, 0x23, 0x3a, 0xf6,
0xb0, 0x6a, 0x06, 0x4b, 0x54, 0x83, 0x14, 0xdf, 0xec, 0xa6, 0x0c, 0x65, 0x2f, 0x77, 0xf0, 0xc1,
0x8d, 0xfa, 0xae, 0x7a, 0xb0, 0x24, 0x36, 0x02, 0x81, 0x5d, 0x9f, 0x98, 0xa6, 0x4b, 0x4d, 0x76,
0xfd, 0xf4, 0x0a, 0xd7, 0x3f, 0x0c, 0xa4, 0xf1, 0xe2, 0x20, 0xba, 0x0f, 0xa9, 0x4f, 0x2d, 0xdb,
0xf7, 0x76, 0x37, 0x0c, 0x65, 0x6f, 0xa3, 0x7c, 0x7b, 0x3e, 0x2b, 0xa4, 0xaa, 0x8c, 0xf0, 0x7c,
0x56, 0x50, 0xd9, 0xe2, 0xb8, 0x4f, 0x4c, 0x0f, 0x0b, 0xa1, 0xe2, 0x09, 0xa4, 0xf8, 0x1d, 0xd0,
0x3d, 0x80, 0x13, 0xdc, 0x3c, 0x3f, 0xeb, 0x34, 0x9a, 0x8d, 0x8a, 0x16, 0xd3, 0xb7, 0x26, 0x53,
0x43, 0x58, 0xdc, 0x70, 0x6c, 0x8a, 0xee, 0xc0, 0xa6, 0x60, 0x97, 0x7f, 0xac, 0xc5, 0xf5, 0xcc,
0x64, 0x6a, 0x6c, 0x70, 0x66, 0x79, 0xac, 0x27, 0x3f, 0xff, 0x7d, 0x3e, 0x56, 0xfc, 0x83, 0x02,
0x0b, 0x74, 0x74, 0x17, 0xd4, 0x6a, 0xad, 0xd1, 0x0e, 0xc0, 0xb2, 0x93, 0xa9, 0xb1, 0xc9, 0xb8,
0x1c, 0xeb, 0x1b, 0x90, 0x93, 0xcc, 0xce, 0x59, 0xb3, 0xd6, 0x68, 0xb7, 0x34, 0x45, 0xd7, 0x26,
0x53, 0x23, 0x2b, 0x24, 0xce, 0x1c, 0x76, 0xb3, 0xa8, 0x54, 0xab, 0x82, 0x6b, 0x95, 0x96, 0x16,
0x8f, 0x4a, 0xb5, 0xa8, 0x6b, 0x51, 0x0f, 0xed, 0xc3, 0x0e, 0x97, 0x6a, 0x1d, 0x55, 0x2b, 0xf5,
0xc3, 0xce, 0xe1, 0xe9, 0x69, 0xa7, 0x5d, 0xab, 0x57, 0xb4, 0xa4, 0xfe, 0xb5, 0xc9, 0xd4, 0xd8,
0x66, 0xb2, 0xad, 0xcb, 0x4f, 0xe9, 0x80, 0x1c, 0xf6, 0xfb, 0x2c, 0x74, 0xe4, 0x6d, 0xff, 0x12,
0x07, 0x35, 0xf4, 0x1e, 0xaa, 0x42, 0xd2, 0x1f, 0x0f, 0x45, 0x00, 0xe7, 0x0e, 0x3e, 0x5c, 0xcd,
0xe7, 0x8b, 0x55, 0x7b, 0x3c, 0xa4, 0x98, 0x23, 0x14, 0x9f, 0x2b, 0xb0, 0xb5, 0x44, 0x47, 0x05,
0x48, 0x4a, 0x27, 0xf0, 0x0b, 0x2d, 0x31, 0xb9, 0x37, 0xee, 0x41, 0xa2, 0x75, 0x5e, 0xd7, 0x14,
0x7d, 0x67, 0x32, 0x35, 0xb4, 0x25, 0x7e, 0x6b, 0x34, 0x40, 0xef, 0x42, 0xea, 0xa8, 0x79, 0xde,
0x68, 0x6b, 0x71, 0xfd, 0xf6, 0x64, 0x6a, 0xa0, 0x25, 0x81, 0x23, 0x67, 0x64, 0xfb, 0x0c, 0xa1,
0x5e, 0x6b, 0x68, 0x89, 0x6b, 0x10, 0xea, 0x96, 0xcd, 0xd9, 0x87, 0x3f, 0xd2, 0x92, 0xd7, 0xb1,
0xc9, 0x13, 0xa6, 0xe0, 0xb8, 0x86, 0x5b, 0x6d, 0x2d, 0x75, 0x8d, 0x82, 0x63, 0xcb, 0xf5, 0x7c,
0x66, 0xc3, 0xe9, 0x61, 0xab, 0xad, 0xa5, 0xaf, 0xb1, 0xe1, 0x94, 0x78, 0xbe, 0x74, 0xea, 0xb7,
0x21, 0xd1, 0x26, 0x26, 0xd2, 0x20, 0xf1, 0x19, 0x1d, 0x73, 0x67, 0x66, 0x31, 0x5b, 0xa2, 0x1d,
0x48, 0x3d, 0x26, 0xfd, 0x91, 0x48, 0xf0, 0x2c, 0x16, 0x9b, 0xe2, 0xaf, 0x73, 0x90, 0x65, 0x09,
0x81, 0xa9, 0x37, 0x74, 0x6c, 0x8f, 0xa2, 0x3a, 0xa4, 0x7b, 0x2e, 0x19, 0x50, 0x6f, 0x57, 0x31,
0x12, 0x7b, 0x99, 0x83, 0xfd, 0x2f, 0xcd, 0xa5, 0xe0, 0x68, 0xe9, 0x98, 0x9d, 0x93, 0xc5, 0x40,
0x82, 0xe8, 0x9f, 0xa7, 0x21, 0xc5, 0xe9, 0xe8, 0x34, 0xc8, 0xd1, 0x0d, 0x9e, 0x54, 0x1f, 0xae,
0x8e, 0xcb, 0x63, 0x9c, 0x83, 0x54, 0x63, 0x41, 0x9a, 0x36, 0x21, 0xed, 0xf1, 0xe0, 0x93, 0x05,
0xef, 0x3b, 0xab, 0xc3, 0x89, 0xa0, 0x0d, 0xf0, 0x24, 0x0c, 0x1a, 0x42, 0xb6, 0xd7, 0x77, 0x88,
0xdf, 0x19, 0xf2, 0xc8, 0x97, 0x65, 0xf0, 0xc1, 0x1a, 0xd6, 0xb3, 0xd3, 0x22, 0x6d, 0x84, 0x23,
0x6e, 0xcd, 0x67, 0x85, 0x4c, 0x84, 0x5a, 0x8d, 0xe1, 0x4c, 0x6f, 0xb1, 0x45, 0x4f, 0x20, 0x67,
0xd9, 0x3e, 0x35, 0xa9, 0x1b, 0xe8, 0x14, 0xd5, 0xf2, 0x7b, 0xab, 0xeb, 0xac, 0x89, 0xf3, 0x51,
0xad, 0xdb, 0xf3, 0x59, 0x61, 0x6b, 0x89, 0x5e, 0x8d, 0xe1, 0x2d, 0x2b, 0x4a, 0x40, 0xbf, 0x80,
0x5b, 0x23, 0xdb, 0xb3, 0x4c, 0x9b, 0x76, 0x03, 0xd5, 0x49, 0xae, 0xfa, 0xe3, 0xd5, 0x55, 0x9f,
0x4b, 0x80, 0xa8, 0x6e, 0x34, 0x9f, 0x15, 0x72, 0xcb, 0x8c, 0x6a, 0x0c, 0xe7, 0x46, 0x4b, 0x14,
0x66, 0xf7, 0x85, 0xe3, 0xf4, 0x29, 0xb1, 0x03, 0xe5, 0xa9, 0x75, 0xed, 0x2e, 0x8b, 0xf3, 0x2f,
0xd8, 0xbd, 0x44, 0x67, 0x76, 0x5f, 0x44, 0x09, 0xc8, 0x87, 0x2d, 0xcf, 0x77, 0x2d, 0xdb, 0x0c,
0x14, 0x8b, 0xfa, 0xfe, 0xdd, 0x35, 0x62, 0x87, 0x1f, 0x8f, 0xea, 0xd5, 0xe6, 0xb3, 0x42, 0x36,
0x4a, 0xae, 0xc6, 0x70, 0xd6, 0x8b, 0xec, 0xcb, 0x69, 0x48, 0x32, 0x64, 0xfd, 0x09, 0xc0, 0x22,
0x92, 0xd1, 0x7b, 0xb0, 0xe9, 0x13, 0x53, 0xb4, 0x37, 0x96, 0x69, 0xd9, 0x72, 0x66, 0x3e, 0x2b,
0x6c, 0xb4, 0x89, 0xc9, 0x9b, 0xdb, 0x86, 0x2f, 0x16, 0xa8, 0x0c, 0x68, 0x48, 0x5c, 0xdf, 0xf2,
0x2d, 0xc7, 0x66, 0xd2, 0x9d, 0xc7, 0xa4, 0xcf, 0xa2, 0x93, 0x9d, 0xd8, 0x99, 0xcf, 0x0a, 0xda,
0x59, 0xc0, 0x7d, 0x44, 0xc7, 0x9f, 0x90, 0xbe, 0x87, 0xb5, 0xe1, 0x15, 0x8a, 0xfe, 0x3b, 0x05,
0x32, 0x91, 0xa8, 0x47, 0x0f, 0x20, 0xe9, 0x13, 0x33, 0xc8, 0x70, 0xe3, 0xe6, 0x56, 0x4f, 0x4c,
0x99, 0xd2, 0xfc, 0x0c, 0x6a, 0x82, 0xca, 0x04, 0x3b, 0xbc, 0x56, 0xc7, 0x79, 0xad, 0x3e, 0x58,
0xdd, 0x7f, 0x0f, 0x89, 0x4f, 0x78, 0xa5, 0xde, 0xec, 0xca, 0x95, 0xfe, 0x03, 0xd0, 0xae, 0xa6,
0x0e, 0xca, 0x03, 0xf8, 0xc1, 0x88, 0x21, 0xae, 0xa9, 0xe1, 0x08, 0x05, 0xdd, 0x86, 0x34, 0x2f,
0x5f, 0xc2, 0x11, 0x0a, 0x96, 0x3b, 0xfd, 0x14, 0xd0, 0x8b, 0x29, 0xb1, 0x26, 0x5a, 0x22, 0x44,
0xab, 0xc3, 0x5b, 0xd7, 0x44, 0xf9, 0x9a, 0x70, 0xc9, 0xe8, 0xe5, 0x5e, 0x8c, 0xdb, 0x35, 0xd1,
0x36, 0x43, 0xb4, 0x47, 0xb0, 0xfd, 0x42, 0x30, 0xae, 0x09, 0xa6, 0x06, 0x60, 0xc5, 0x16, 0xa8,
0x1c, 0x40, 0x36, 0xcb, 0xb4, 0xec, 0xf5, 0x31, 0xfd, 0xad, 0xc9, 0xd4, 0xb8, 0x15, 0xb2, 0x64,
0xbb, 0x2f, 0x40, 0x3a, 0x1c, 0x19, 0x96, 0x05, 0xc4, 0x5d, 0x64, 0x27, 0xfa, 0xa3, 0x02, 0x9b,
0xc1, 0xf7, 0x46, 0xef, 0x40, 0xea, 0xf8, 0xb4, 0x79, 0xd8, 0xd6, 0x62, 0xfa, 0xf6, 0x64, 0x6a,
0x6c, 0x05, 0x0c, 0xfe, 0xe9, 0x91, 0x01, 0x1b, 0xb5, 0x46, 0xbb, 0x72, 0x52, 0xc1, 0x01, 0x64,
0xc0, 0x97, 0x9f, 0x13, 0x15, 0x61, 0xf3, 0xbc, 0xd1, 0xaa, 0x9d, 0x34, 0x2a, 0x0f, 0xb5, 0xb8,
0x68, 0xa2, 0x81, 0x48, 0xf0, 0x8d, 0x18, 0x4a, 0xb9, 0xd9, 0x3c, 0xad, 0x1c, 0xb2, 0x36, 0xbc,
0x84, 0x22, 0xfd, 0x8e, 0xf2, 0x90, 0x6e, 0xb5, 0x71, 0xad, 0x71, 0xa2, 0x25, 0x75, 0x34, 0x99,
0x1a, 0xb9, 0x40, 0x40, 0xb8, 0x52, 0x5e, 0x7c, 0x0f, 0xe0, 0x88, 0x0c, 0xc9, 0x85, 0xd5, 0xb7,
0xfc, 0x31, 0xd2, 0x61, 0xb3, 0x47, 0x89, 0x3f, 0x72, 0x65, 0x4b, 0x54, 0x71, 0xb8, 0x2f, 0xfe,
0x49, 0x81, 0x9d, 0x50, 0xd4, 0xa2, 0x5e, 0xd8, 0x45, 0x9b, 0x90, 0xbc, 0x24, 0xc3, 0x20, 0xc3,
0x6e, 0x2e, 0x30, 0xd7, 0x01, 0x30, 0xa2, 0x57, 0xb1, 0x7d, 0x77, 0x8c, 0x39, 0x90, 0xfe, 0x53,
0x50, 0x43, 0x52, 0xb4, 0xb9, 0xab, 0xa2, 0xb9, 0x7f, 0x1c, 0x6d, 0xee, 0x99, 0x83, 0xf7, 0x57,
0x53, 0x38, 0x96, 0x53, 0xc0, 0x83, 0xf8, 0x47, 0x4a, 0xf1, 0x23, 0xc8, 0x2d, 0x8f, 0xf5, 0x6c,
0x62, 0xf0, 0x7c, 0xe2, 0xfa, 0x5c, 0x51, 0x02, 0x8b, 0x0d, 0x53, 0x4e, 0xed, 0x2e, 0x57, 0x94,
0xc0, 0x6c, 0x59, 0xfc, 0xa7, 0x02, 0xb9, 0xa0, 0x6e, 0x2d, 0x7e, 0x4a, 0x58, 0xb5, 0x58, 0xf9,
0xa7, 0xa4, 0x4d, 0x4c, 0x2f, 0xf8, 0x29, 0xf1, 0xc3, 0xf5, 0xeb, 0xf6, 0xff, 0xf5, 0xcb, 0x38,
0x68, 0x6d, 0x62, 0x7e, 0xc2, 0x93, 0xe6, 0x8d, 0x36, 0x15, 0xbd, 0x0d, 0x1b, 0xb2, 0x3d, 0xf1,
0xd1, 0x40, 0xc5, 0x69, 0xd1, 0x90, 0x8a, 0x25, 0xd8, 0x11, 0xc9, 0x12, 0x78, 0x41, 0x46, 0xfc,
0xa2, 0xb4, 0xf0, 0x6e, 0x16, 0x96, 0x96, 0xbf, 0x2a, 0xf0, 0x76, 0x9d, 0x12, 0x6f, 0xe4, 0xd2,
0x01, 0xb5, 0xfd, 0x06, 0x9b, 0x0a, 0x03, 0xd7, 0xdd, 0x87, 0xf4, 0x97, 0x7b, 0x0d, 0x4b, 0x99,
0xd7, 0x2d, 0x18, 0x9e, 0x2b, 0x70, 0x27, 0x62, 0xd8, 0x95, 0x04, 0x58, 0xcf, 0x34, 0x03, 0x32,
0x83, 0x05, 0x14, 0x37, 0x50, 0xc5, 0x51, 0xd2, 0xc2, 0xf8, 0xc4, 0xab, 0x34, 0x3e, 0xf9, 0xb2,
0xc6, 0xff, 0x36, 0x0e, 0x77, 0x97, 0x8d, 0x5f, 0x4e, 0x8a, 0x57, 0x6d, 0x7e, 0x24, 0x1c, 0x13,
0xd1, 0x70, 0x5c, 0xf8, 0x25, 0xf9, 0x2a, 0xfd, 0x92, 0x7a, 0x59, 0xbf, 0xfc, 0x47, 0x81, 0xdd,
0x88, 0x5f, 0x8e, 0x2d, 0xda, 0xef, 0x7e, 0x55, 0x62, 0xe2, 0xbf, 0x89, 0xa5, 0x84, 0x08, 0x6c,
0x97, 0xf5, 0x81, 0x40, 0xba, 0xc7, 0x29, 0xb2, 0x27, 0x1e, 0xdd, 0xa8, 0xe0, 0xff, 0xe2, 0x94,
0xea, 0xd4, 0xf3, 0x88, 0x49, 0x39, 0x35, 0xfc, 0xd7, 0xe4, 0x22, 0xfa, 0x6f, 0x14, 0xc8, 0x46,
0xd9, 0xd7, 0xf4, 0xc9, 0xb6, 0x7c, 0x64, 0x10, 0x83, 0xeb, 0xf7, 0x5f, 0xf2, 0x0e, 0x7c, 0xbb,
0x78, 0x70, 0x40, 0xef, 0x80, 0x1a, 0x0e, 0x59, 0xfc, 0x63, 0x68, 0x78, 0x41, 0x28, 0x3e, 0x53,
0x40, 0x0d, 0x4f, 0xa0, 0x7b, 0x8b, 0x41, 0x88, 0x4f, 0x20, 0x21, 0x47, 0x4c, 0x42, 0xef, 0x46,
0x27, 0x21, 0x3e, 0xe6, 0x84, 0x02, 0xc1, 0x28, 0xf4, 0xf5, 0xa5, 0x51, 0x88, 0x3f, 0x06, 0x84,
0x32, 0xe1, 0x2c, 0x54, 0x08, 0x27, 0x1d, 0x39, 0x0a, 0x85, 0x22, 0xa2, 0x7a, 0x33, 0x45, 0xc1,
0xb0, 0x94, 0xbc, 0xa2, 0x28, 0x98, 0x96, 0xbe, 0x09, 0xea, 0x79, 0xe3, 0x61, 0xe5, 0xb8, 0xc6,
0x34, 0xc9, 0x87, 0x89, 0x88, 0xa6, 0x2e, 0xed, 0x59, 0x36, 0xed, 0xca, 0xa1, 0xe9, 0xdf, 0x71,
0xd0, 0xd9, 0xa8, 0xff, 0x43, 0xcb, 0xee, 0x3a, 0x3f, 0x5f, 0x3c, 0x8a, 0xbd, 0xd1, 0xaf, 0x94,
0x06, 0x64, 0x84, 0xbd, 0x95, 0xc7, 0xd4, 0x15, 0x9d, 0x32, 0x81, 0xa3, 0x24, 0xd6, 0x16, 0x9b,
0xbd, 0x9e, 0x47, 0x7d, 0xfe, 0xaf, 0x99, 0xc0, 0x72, 0xb7, 0xfc, 0xcc, 0x98, 0xe2, 0x19, 0xb1,
0xfe, 0x33, 0x63, 0xf9, 0xfd, 0xa7, 0xff, 0xc8, 0xc7, 0x9e, 0xce, 0xf3, 0xca, 0x17, 0xf3, 0xbc,
0xf2, 0xf7, 0x79, 0x5e, 0xf9, 0xd5, 0xb3, 0x7c, 0xec, 0x8b, 0x67, 0xf9, 0xd8, 0xdf, 0x9e, 0xe5,
0x63, 0x3f, 0xe1, 0x3f, 0x6a, 0x2c, 0x40, 0xbd, 0x8b, 0x34, 0xf7, 0xf0, 0x07, 0xff, 0x0b, 0x00,
0x00, 0xff, 0xff, 0x78, 0x6a, 0xb2, 0x8f, 0xa3, 0x17, 0x00, 0x00,
// 1797 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x58, 0xcd, 0x8f, 0x23, 0x47,
0x15, 0x77, 0xfb, 0x73, 0xfa, 0xd9, 0xe3, 0xed, 0xa9, 0x98, 0xcd, 0x6c, 0x6f, 0xd6, 0xee, 0x18,
0x48, 0x46, 0x62, 0xf1, 0x48, 0x93, 0x20, 0x45, 0x0b, 0x91, 0xb0, 0x67, 0x3d, 0x63, 0xb3, 0x63,
0x7b, 0x54, 0xf6, 0x84, 0x8f, 0x8b, 0xa9, 0x19, 0x97, 0x3b, 0xad, 0xd8, 0xdd, 0xa6, 0xbb, 0xbd,
0xac, 0x25, 0x2e, 0xdc, 0x22, 0x9f, 0x40, 0x82, 0x0b, 0xc8, 0x27, 0x8e, 0xdc, 0xf9, 0x1b, 0x16,
0x89, 0x43, 0x4e, 0x88, 0x93, 0x05, 0x5e, 0x09, 0x89, 0x2b, 0x9c, 0x08, 0x17, 0x54, 0x55, 0xdd,
0xed, 0xf6, 0x8c, 0x99, 0xd8, 0xab, 0x3d, 0x44, 0xcb, 0xad, 0xea, 0xbd, 0x57, 0xbf, 0x57, 0xef,
0xf5, 0xfb, 0xea, 0x82, 0x9c, 0xe3, 0x5a, 0x36, 0xd1, 0x69, 0xf7, 0xca, 0x1a, 0x0e, 0x2d, 0xb3,
0x34, 0xb2, 0x2d, 0xd7, 0x42, 0xf7, 0x0d, 0xb3, 0x3f, 0x18, 0x3f, 0xeb, 0x11, 0x97, 0x94, 0x46,
0x03, 0xe2, 0xf6, 0x2d, 0x7b, 0x58, 0xf2, 0x24, 0xd5, 0x9c, 0x6e, 0xe9, 0x16, 0x97, 0x3b, 0x64,
0x2b, 0x71, 0x44, 0xbd, 0xa7, 0x5b, 0x96, 0x3e, 0xa0, 0x87, 0x7c, 0x77, 0x39, 0xee, 0x1f, 0x12,
0x73, 0xe2, 0xb1, 0xee, 0x8c, 0x6c, 0xda, 0x33, 0xae, 0x88, 0x4b, 0x05, 0xa1, 0xf8, 0x0f, 0x09,
0xf6, 0x30, 0x25, 0xbd, 0x13, 0x63, 0xe0, 0x52, 0x1b, 0xd3, 0x9f, 0x8c, 0xa9, 0xe3, 0xa2, 0x2a,
0xa4, 0x6d, 0x4a, 0x7a, 0x5d, 0xc7, 0x1a, 0xdb, 0x57, 0x74, 0x5f, 0xd2, 0xa4, 0x83, 0xf4, 0x51,
0xae, 0x24, 0x70, 0x4b, 0x3e, 0x6e, 0xa9, 0x6c, 0x4e, 0x2a, 0xd9, 0xc5, 0xbc, 0x00, 0x0c, 0xa1,
0xcd, 0x65, 0x31, 0xd8, 0xc1, 0x1a, 0x9d, 0x42, 0xc2, 0x26, 0xa6, 0x4e, 0xf7, 0xa3, 0x1c, 0xe0,
0x1b, 0xa5, 0x5b, 0x6c, 0x29, 0x75, 0x8c, 0x21, 0x75, 0x5c, 0x32, 0x1c, 0x61, 0x76, 0xa4, 0x12,
0x7f, 0x3e, 0x2f, 0x44, 0xb0, 0x38, 0x8f, 0x1e, 0x83, 0x1c, 0x5c, 0x7c, 0x3f, 0xc6, 0xc1, 0xde,
0xb9, 0x15, 0xec, 0xdc, 0x97, 0xc6, 0xcb, 0x83, 0xc5, 0x3f, 0x25, 0x40, 0x61, 0x37, 0x3d, 0xb5,
0xad, 0xf1, 0xe8, 0xb5, 0x36, 0x15, 0x3d, 0x04, 0xd0, 0x99, 0x95, 0xdd, 0x4f, 0xe8, 0xc4, 0xd9,
0x8f, 0x6b, 0xb1, 0x03, 0xb9, 0xb2, 0xbb, 0x98, 0x17, 0x64, 0x6e, 0xfb, 0x13, 0x3a, 0x71, 0xb0,
0xac, 0xfb, 0x4b, 0x54, 0x87, 0x04, 0xdf, 0xec, 0x27, 0x34, 0xe9, 0x20, 0x7b, 0xf4, 0xde, 0xad,
0xfa, 0xae, 0x7b, 0xb0, 0x24, 0x36, 0x02, 0x81, 0x5d, 0x9f, 0xe8, 0xba, 0x4d, 0x75, 0x76, 0xfd,
0xe4, 0x06, 0xd7, 0x2f, 0xfb, 0xd2, 0x78, 0x79, 0x10, 0x3d, 0x84, 0xc4, 0xc7, 0x86, 0xe9, 0x3a,
0xfb, 0x29, 0x4d, 0x3a, 0x48, 0x55, 0xee, 0x2e, 0xe6, 0x85, 0x44, 0x8d, 0x11, 0x3e, 0x9f, 0x17,
0x64, 0xb6, 0x38, 0x19, 0x10, 0xdd, 0xc1, 0x42, 0xa8, 0x78, 0x0a, 0x09, 0x7e, 0x07, 0xf4, 0x00,
0xe0, 0x14, 0xb7, 0x2e, 0xce, 0xbb, 0xcd, 0x56, 0xb3, 0xaa, 0x44, 0xd4, 0xdd, 0xe9, 0x4c, 0x13,
0x16, 0x37, 0x2d, 0x93, 0xa2, 0x7b, 0xb0, 0x23, 0xd8, 0x95, 0x1f, 0x2a, 0x51, 0x35, 0x3d, 0x9d,
0x69, 0x29, 0xce, 0xac, 0x4c, 0xd4, 0xf8, 0xa7, 0xbf, 0xcb, 0x47, 0x8a, 0xbf, 0x97, 0x60, 0x89,
0x8e, 0xee, 0x83, 0x5c, 0xab, 0x37, 0x3b, 0x3e, 0x58, 0x66, 0x3a, 0xd3, 0x76, 0x18, 0x97, 0x63,
0x7d, 0x0d, 0xb2, 0x1e, 0xb3, 0x7b, 0xde, 0xaa, 0x37, 0x3b, 0x6d, 0x45, 0x52, 0x95, 0xe9, 0x4c,
0xcb, 0x08, 0x89, 0x73, 0x8b, 0xdd, 0x2c, 0x2c, 0xd5, 0xae, 0xe2, 0x7a, 0xb5, 0xad, 0x44, 0xc3,
0x52, 0x6d, 0x6a, 0x1b, 0xd4, 0x41, 0x87, 0x90, 0xe3, 0x52, 0xed, 0xe3, 0x5a, 0xb5, 0x51, 0xee,
0x96, 0xcf, 0xce, 0xba, 0x9d, 0x7a, 0xa3, 0xaa, 0xc4, 0xd5, 0xaf, 0x4c, 0x67, 0xda, 0x1e, 0x93,
0x6d, 0x5f, 0x7d, 0x4c, 0x87, 0xa4, 0x3c, 0x18, 0xb0, 0xd0, 0xf1, 0x6e, 0xfb, 0xaf, 0x28, 0xc8,
0x81, 0xf7, 0x50, 0x0d, 0xe2, 0xee, 0x64, 0x24, 0x02, 0x38, 0x7b, 0xf4, 0xfe, 0x66, 0x3e, 0x5f,
0xae, 0x3a, 0x93, 0x11, 0xc5, 0x1c, 0xa1, 0xf8, 0xdb, 0x28, 0xec, 0xae, 0xd0, 0x51, 0x01, 0xe2,
0x9e, 0x13, 0xf8, 0x85, 0x56, 0x98, 0xdc, 0x1b, 0x0f, 0x20, 0xd6, 0xbe, 0x68, 0x28, 0x92, 0x9a,
0x9b, 0xce, 0x34, 0x65, 0x85, 0xdf, 0x1e, 0x0f, 0xd1, 0xdb, 0x90, 0x38, 0x6e, 0x5d, 0x34, 0x3b,
0x4a, 0x54, 0xbd, 0x3b, 0x9d, 0x69, 0x68, 0x45, 0xe0, 0xd8, 0x1a, 0x9b, 0x2e, 0x43, 0x68, 0xd4,
0x9b, 0x4a, 0x6c, 0x0d, 0x42, 0xc3, 0x30, 0x39, 0xbb, 0xfc, 0x03, 0x25, 0xbe, 0x8e, 0x4d, 0x9e,
0x31, 0x05, 0x27, 0x75, 0xdc, 0xee, 0x28, 0x89, 0x35, 0x0a, 0x4e, 0x0c, 0xdb, 0x71, 0x99, 0x0d,
0x67, 0xe5, 0x76, 0x47, 0x49, 0xae, 0xb1, 0xe1, 0x8c, 0x08, 0x81, 0x46, 0xb5, 0xdc, 0x54, 0x52,
0x6b, 0x04, 0x1a, 0x94, 0x98, 0x9e, 0xd7, 0xbf, 0x09, 0xb1, 0x0e, 0xd1, 0x91, 0x02, 0xb1, 0x4f,
0xe8, 0x84, 0x7b, 0x3b, 0x83, 0xd9, 0x12, 0xe5, 0x20, 0xf1, 0x94, 0x0c, 0xc6, 0xa2, 0x02, 0x64,
0xb0, 0xd8, 0x14, 0x7f, 0x99, 0x85, 0x0c, 0xcb, 0x18, 0x4c, 0x9d, 0x91, 0x65, 0x3a, 0x14, 0x35,
0x20, 0xd9, 0xb7, 0xc9, 0x90, 0x3a, 0xfb, 0x92, 0x16, 0x3b, 0x48, 0x1f, 0x1d, 0x7e, 0x61, 0xb2,
0xf9, 0x47, 0x4b, 0x27, 0xec, 0x9c, 0x57, 0x2d, 0x3c, 0x10, 0xf5, 0xd3, 0x24, 0x24, 0x38, 0x1d,
0x9d, 0xf9, 0x49, 0x9c, 0xe2, 0x59, 0xf7, 0xfe, 0xe6, 0xb8, 0x3c, 0x09, 0x38, 0x48, 0x2d, 0xe2,
0xe7, 0x71, 0x0b, 0x92, 0x0e, 0x8f, 0x4e, 0xaf, 0x22, 0x7e, 0x6b, 0x73, 0x38, 0x11, 0xd5, 0x3e,
0x9e, 0x07, 0x83, 0x46, 0x90, 0xe9, 0x0f, 0x2c, 0xe2, 0x76, 0x47, 0x3c, 0x35, 0xbc, 0x3a, 0xf9,
0x68, 0x0b, 0xeb, 0xd9, 0x69, 0x91, 0x57, 0xc2, 0x11, 0x77, 0x16, 0xf3, 0x42, 0x3a, 0x44, 0xad,
0x45, 0x70, 0xba, 0xbf, 0xdc, 0xa2, 0x67, 0x90, 0x35, 0x4c, 0x97, 0xea, 0xd4, 0xf6, 0x75, 0x8a,
0x72, 0xfa, 0x9d, 0xcd, 0x75, 0xd6, 0xc5, 0xf9, 0xb0, 0xd6, 0xbd, 0xc5, 0xbc, 0xb0, 0xbb, 0x42,
0xaf, 0x45, 0xf0, 0xae, 0x11, 0x26, 0xa0, 0x9f, 0xc1, 0x9d, 0xb1, 0xe9, 0x18, 0xba, 0x49, 0x7b,
0xbe, 0xea, 0x38, 0x57, 0xfd, 0xe1, 0xe6, 0xaa, 0x2f, 0x3c, 0x80, 0xb0, 0x6e, 0xb4, 0x98, 0x17,
0xb2, 0xab, 0x8c, 0x5a, 0x04, 0x67, 0xc7, 0x2b, 0x14, 0x66, 0xf7, 0xa5, 0x65, 0x0d, 0x28, 0x31,
0x7d, 0xe5, 0x89, 0x6d, 0xed, 0xae, 0x88, 0xf3, 0x37, 0xec, 0x5e, 0xa1, 0x33, 0xbb, 0x2f, 0xc3,
0x04, 0xe4, 0xc2, 0xae, 0xe3, 0xda, 0x86, 0xa9, 0xfb, 0x8a, 0x45, 0x03, 0xf8, 0xf6, 0x16, 0xb1,
0xc3, 0x8f, 0x87, 0xf5, 0x2a, 0x8b, 0x79, 0x21, 0x13, 0x26, 0xd7, 0x22, 0x38, 0xe3, 0x84, 0xf6,
0x95, 0x24, 0xc4, 0x19, 0xb2, 0xfa, 0x0c, 0x60, 0x19, 0xc9, 0xe8, 0x1d, 0xd8, 0x71, 0x89, 0x2e,
0xfa, 0x1f, 0xcb, 0xb4, 0x4c, 0x25, 0xbd, 0x98, 0x17, 0x52, 0x1d, 0xa2, 0xf3, 0xee, 0x97, 0x72,
0xc5, 0x02, 0x55, 0x00, 0x8d, 0x88, 0xed, 0x1a, 0xae, 0x61, 0x99, 0x4c, 0xba, 0xfb, 0x94, 0x0c,
0x58, 0x74, 0xb2, 0x13, 0xb9, 0xc5, 0xbc, 0xa0, 0x9c, 0xfb, 0xdc, 0x27, 0x74, 0xf2, 0x11, 0x19,
0x38, 0x58, 0x19, 0x5d, 0xa3, 0xa8, 0xbf, 0x91, 0x20, 0x1d, 0x8a, 0x7a, 0xf4, 0x08, 0xe2, 0x2e,
0xd1, 0xfd, 0x0c, 0xd7, 0x6e, 0x9f, 0x05, 0x88, 0xee, 0xa5, 0x34, 0x3f, 0x83, 0x5a, 0x20, 0x33,
0xc1, 0x2e, 0x2f, 0xe6, 0x51, 0x5e, 0xcc, 0x8f, 0x36, 0xf7, 0xdf, 0x63, 0xe2, 0x12, 0x5e, 0xca,
0x77, 0x7a, 0xde, 0x4a, 0xfd, 0x1e, 0x28, 0xd7, 0x53, 0x07, 0xe5, 0x01, 0x5c, 0x7f, 0x06, 0x11,
0xd7, 0x54, 0x70, 0x88, 0x82, 0xee, 0x42, 0x92, 0x97, 0x2f, 0xe1, 0x08, 0x09, 0x7b, 0x3b, 0xf5,
0x0c, 0xd0, 0xcd, 0x94, 0xd8, 0x12, 0x2d, 0x16, 0xa0, 0x35, 0xe0, 0x8d, 0x35, 0x51, 0xbe, 0x25,
0x5c, 0x3c, 0x7c, 0xb9, 0x9b, 0x71, 0xbb, 0x25, 0xda, 0x4e, 0x80, 0xf6, 0x04, 0xf6, 0x6e, 0x04,
0xe3, 0x96, 0x60, 0xb2, 0x0f, 0x56, 0x6c, 0x83, 0xcc, 0x01, 0xbc, 0x6e, 0x9a, 0xf4, 0x86, 0x81,
0x88, 0xfa, 0xc6, 0x74, 0xa6, 0xdd, 0x09, 0x58, 0xde, 0x3c, 0x50, 0x80, 0x64, 0x30, 0x53, 0xac,
0x0a, 0x88, 0xbb, 0x78, 0x9d, 0xe8, 0x0f, 0x12, 0xec, 0xf8, 0xdf, 0x1b, 0xbd, 0x05, 0x89, 0x93,
0xb3, 0x56, 0xb9, 0xa3, 0x44, 0xd4, 0xbd, 0xe9, 0x4c, 0xdb, 0xf5, 0x19, 0xfc, 0xd3, 0x23, 0x0d,
0x52, 0xf5, 0x66, 0xa7, 0x7a, 0x5a, 0xc5, 0x3e, 0xa4, 0xcf, 0xf7, 0x3e, 0x27, 0x2a, 0xc2, 0xce,
0x45, 0xb3, 0x5d, 0x3f, 0x6d, 0x56, 0x1f, 0x2b, 0x51, 0xd1, 0x65, 0x7d, 0x11, 0xff, 0x1b, 0x31,
0x94, 0x4a, 0xab, 0x75, 0xc6, 0x9a, 0x64, 0x6c, 0x15, 0xc5, 0xf3, 0x3b, 0xca, 0x43, 0xb2, 0xdd,
0xc1, 0xf5, 0xe6, 0xa9, 0x12, 0x57, 0xd1, 0x74, 0xa6, 0x65, 0x7d, 0x01, 0xe1, 0x4a, 0xef, 0xe2,
0x07, 0x00, 0xc7, 0x64, 0x44, 0x2e, 0x8d, 0x81, 0xe1, 0x4e, 0x90, 0x0a, 0x3b, 0x7d, 0x4a, 0xdc,
0xb1, 0xed, 0xb5, 0x44, 0x19, 0x07, 0xfb, 0xe2, 0x1f, 0x25, 0xc8, 0x05, 0xa2, 0x06, 0x75, 0x82,
0x2e, 0xda, 0x82, 0xf8, 0x15, 0x19, 0xf9, 0x19, 0x76, 0x7b, 0x81, 0x59, 0x07, 0xc0, 0x88, 0x4e,
0xd5, 0x74, 0xed, 0x09, 0xe6, 0x40, 0xea, 0x8f, 0x41, 0x0e, 0x48, 0xe1, 0xe6, 0x2e, 0x8b, 0xe6,
0xfe, 0x61, 0xb8, 0xb9, 0xa7, 0x8f, 0xde, 0xdd, 0x4c, 0xe1, 0xc4, 0x9b, 0x02, 0x1e, 0x45, 0x3f,
0x90, 0x8a, 0x1f, 0x40, 0x76, 0x75, 0xee, 0x67, 0x13, 0x83, 0xe3, 0x12, 0xdb, 0xe5, 0x8a, 0x62,
0x58, 0x6c, 0x98, 0x72, 0x6a, 0xf6, 0xb8, 0xa2, 0x18, 0x66, 0xcb, 0xe2, 0xdf, 0x25, 0xc8, 0xfa,
0x75, 0x6b, 0xf9, 0xd7, 0xc2, 0xaa, 0xc5, 0xc6, 0x7f, 0x2d, 0x1d, 0xa2, 0x3b, 0xfe, 0x5f, 0x8b,
0x1b, 0xac, 0xbf, 0x6c, 0x3f, 0x68, 0x3f, 0x8f, 0x82, 0xd2, 0x21, 0xfa, 0x47, 0x3c, 0x69, 0x5e,
0x6b, 0x53, 0xd1, 0x9b, 0x90, 0xf2, 0xda, 0x13, 0x1f, 0x0d, 0x64, 0x9c, 0x14, 0x0d, 0xa9, 0x58,
0x82, 0x9c, 0x48, 0x16, 0xdf, 0x0b, 0x5e, 0xc4, 0x2f, 0x4b, 0x0b, 0xef, 0x66, 0x41, 0x69, 0xf9,
0xb3, 0x04, 0x6f, 0x36, 0x28, 0x71, 0xc6, 0x36, 0x1d, 0x52, 0xd3, 0x6d, 0xb2, 0xa9, 0xd0, 0x77,
0xdd, 0x43, 0x48, 0x7e, 0xb1, 0xd7, 0xb0, 0x27, 0xf3, 0x65, 0x0b, 0x86, 0xcf, 0x25, 0xb8, 0x17,
0x32, 0xec, 0x5a, 0x02, 0x6c, 0x67, 0x9a, 0x06, 0xe9, 0xe1, 0x12, 0x8a, 0x1b, 0x28, 0xe3, 0x30,
0x69, 0x69, 0x7c, 0xec, 0x55, 0x1a, 0x1f, 0x7f, 0x59, 0xe3, 0x7f, 0x1d, 0x85, 0xfb, 0xab, 0xc6,
0xaf, 0x26, 0xc5, 0xab, 0x36, 0x3f, 0x14, 0x8e, 0xb1, 0x70, 0x38, 0x2e, 0xfd, 0x12, 0x7f, 0x95,
0x7e, 0x49, 0xbc, 0xac, 0x5f, 0xfe, 0x2d, 0xc1, 0x7e, 0xc8, 0x2f, 0x27, 0x06, 0x1d, 0xf4, 0xfe,
0x5f, 0x62, 0xe2, 0x3f, 0xb1, 0x95, 0x84, 0xf0, 0x6d, 0xf7, 0xea, 0x03, 0x81, 0x64, 0x9f, 0x53,
0xbc, 0x9e, 0x78, 0x7c, 0xab, 0x82, 0xff, 0x89, 0x53, 0x6a, 0x50, 0xc7, 0x21, 0x3a, 0xe5, 0xd4,
0xe0, 0x5f, 0x93, 0x8b, 0xa8, 0xbf, 0x92, 0x20, 0x13, 0x66, 0xaf, 0xe9, 0x93, 0x1d, 0xef, 0x15,
0x42, 0x0c, 0xae, 0xdf, 0x7d, 0xc9, 0x3b, 0xf0, 0xed, 0xf2, 0x45, 0x02, 0xbd, 0x05, 0x72, 0x30,
0x64, 0xf1, 0x8f, 0xa1, 0xe0, 0x25, 0xa1, 0xf8, 0x42, 0x02, 0x39, 0x38, 0x81, 0x1e, 0x2c, 0x07,
0x21, 0x3e, 0x81, 0x04, 0x1c, 0x31, 0x09, 0xbd, 0x1d, 0x9e, 0x84, 0xf8, 0x98, 0x13, 0x08, 0xf8,
0xa3, 0xd0, 0x57, 0x57, 0x46, 0x21, 0xfe, 0x18, 0x10, 0xc8, 0x04, 0xb3, 0x50, 0x21, 0x98, 0x74,
0xbc, 0x51, 0x28, 0x10, 0x11, 0xd5, 0x9b, 0x29, 0xf2, 0x87, 0xa5, 0xf8, 0x35, 0x45, 0xfe, 0xb4,
0xf4, 0x75, 0x90, 0x2f, 0x9a, 0x8f, 0xab, 0x27, 0x75, 0xa6, 0xc9, 0x7b, 0xb9, 0x08, 0x69, 0xea,
0xd1, 0xbe, 0x61, 0xd2, 0x9e, 0x37, 0x34, 0xfd, 0x33, 0x0a, 0x2a, 0x1b, 0xf5, 0xbf, 0x6f, 0x98,
0x3d, 0xeb, 0xa7, 0xcb, 0x57, 0xb3, 0xd7, 0xfa, 0x19, 0x53, 0x83, 0xb4, 0xb0, 0xb7, 0xfa, 0x94,
0xda, 0xa2, 0x53, 0xc6, 0x70, 0x98, 0xc4, 0xda, 0x62, 0xab, 0xdf, 0x77, 0xa8, 0xcb, 0xff, 0x35,
0x63, 0xd8, 0xdb, 0xad, 0xbe, 0x43, 0x26, 0x78, 0x46, 0x6c, 0xff, 0x0e, 0x59, 0x79, 0xf7, 0xf9,
0xdf, 0xf2, 0x91, 0xe7, 0x8b, 0xbc, 0xf4, 0xd9, 0x22, 0x2f, 0xfd, 0x75, 0x91, 0x97, 0x7e, 0xf1,
0x22, 0x1f, 0xf9, 0xec, 0x45, 0x3e, 0xf2, 0x97, 0x17, 0xf9, 0xc8, 0x8f, 0xf8, 0x8f, 0x1a, 0x0b,
0x50, 0xe7, 0x32, 0xc9, 0x3d, 0xfc, 0xde, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x85, 0x82, 0x53,
0x01, 0xc4, 0x17, 0x00, 0x00,
}
func (m *ReadFilterRequest) Marshal() (dAtA []byte, err error) {

View File

@ -67,6 +67,7 @@ message Aggregate {
MAX = 4 [(gogoproto.enumvalue_customname) = "AggregateTypeMax"];
FIRST = 5 [(gogoproto.enumvalue_customname) = "AggregateTypeFirst"];
LAST = 6 [(gogoproto.enumvalue_customname) = "AggregateTypeLast"];
MEAN = 7 [(gogoproto.enumvalue_customname) = "AggregateTypeMean"];
}
AggregateType type = 1;

View File

@ -38,6 +38,7 @@ func NewStore(viewer reads.Viewer) reads.Store {
Last: true,
Min: true,
Max: true,
Mean: true,
Offset: true,
},
}