Merge pull request #6047 from influxdata/js-6040-boolean-distinct
Support the distinct() call for booleanspull/6059/head
commit
43a5e84aaf
|
@ -2285,13 +2285,13 @@ func TestServer_Query_Aggregates_IntMany(t *testing.T) {
|
|||
name: "distinct as call - int",
|
||||
params: url.Values{"db": []string{"db0"}},
|
||||
command: `SELECT DISTINCT(value) FROM intmany`,
|
||||
exp: `{"results":[{"series":[{"name":"intmany","columns":["time","distinct"],"values":[["2000-01-01T00:00:00Z",2],["2000-01-01T00:00:10Z",4],["2000-01-01T00:00:40Z",5],["2000-01-01T00:01:00Z",7],["2000-01-01T00:01:10Z",9]]}]}]}`,
|
||||
exp: `{"results":[{"series":[{"name":"intmany","columns":["time","distinct"],"values":[["1970-01-01T00:00:00Z",2],["1970-01-01T00:00:00Z",4],["1970-01-01T00:00:00Z",5],["1970-01-01T00:00:00Z",7],["1970-01-01T00:00:00Z",9]]}]}]}`,
|
||||
},
|
||||
&Query{
|
||||
name: "distinct alt syntax - int",
|
||||
params: url.Values{"db": []string{"db0"}},
|
||||
command: `SELECT DISTINCT value FROM intmany`,
|
||||
exp: `{"results":[{"series":[{"name":"intmany","columns":["time","distinct"],"values":[["2000-01-01T00:00:00Z",2],["2000-01-01T00:00:10Z",4],["2000-01-01T00:00:40Z",5],["2000-01-01T00:01:00Z",7],["2000-01-01T00:01:10Z",9]]}]}]}`,
|
||||
exp: `{"results":[{"series":[{"name":"intmany","columns":["time","distinct"],"values":[["1970-01-01T00:00:00Z",2],["1970-01-01T00:00:00Z",4],["1970-01-01T00:00:00Z",5],["1970-01-01T00:00:00Z",7],["1970-01-01T00:00:00Z",9]]}]}]}`,
|
||||
},
|
||||
&Query{
|
||||
name: "distinct select tag - int",
|
||||
|
@ -2659,13 +2659,13 @@ func TestServer_Query_Aggregates_FloatMany(t *testing.T) {
|
|||
name: "distinct as call - float",
|
||||
params: url.Values{"db": []string{"db0"}},
|
||||
command: `SELECT DISTINCT(value) FROM floatmany`,
|
||||
exp: `{"results":[{"series":[{"name":"floatmany","columns":["time","distinct"],"values":[["2000-01-01T00:00:00Z",2],["2000-01-01T00:00:10Z",4],["2000-01-01T00:00:40Z",5],["2000-01-01T00:01:00Z",7],["2000-01-01T00:01:10Z",9]]}]}]}`,
|
||||
exp: `{"results":[{"series":[{"name":"floatmany","columns":["time","distinct"],"values":[["1970-01-01T00:00:00Z",2],["1970-01-01T00:00:00Z",4],["1970-01-01T00:00:00Z",5],["1970-01-01T00:00:00Z",7],["1970-01-01T00:00:00Z",9]]}]}]}`,
|
||||
},
|
||||
&Query{
|
||||
name: "distinct alt syntax - float",
|
||||
params: url.Values{"db": []string{"db0"}},
|
||||
command: `SELECT DISTINCT value FROM floatmany`,
|
||||
exp: `{"results":[{"series":[{"name":"floatmany","columns":["time","distinct"],"values":[["2000-01-01T00:00:00Z",2],["2000-01-01T00:00:10Z",4],["2000-01-01T00:00:40Z",5],["2000-01-01T00:01:00Z",7],["2000-01-01T00:01:10Z",9]]}]}]}`,
|
||||
exp: `{"results":[{"series":[{"name":"floatmany","columns":["time","distinct"],"values":[["1970-01-01T00:00:00Z",2],["1970-01-01T00:00:00Z",4],["1970-01-01T00:00:00Z",5],["1970-01-01T00:00:00Z",7],["1970-01-01T00:00:00Z",9]]}]}]}`,
|
||||
},
|
||||
&Query{
|
||||
name: "distinct select tag - float",
|
||||
|
@ -3134,7 +3134,7 @@ func TestServer_Query_AggregateSelectors(t *testing.T) {
|
|||
name: "distinct - baseline 30s",
|
||||
params: url.Values{"db": []string{"db0"}},
|
||||
command: `SELECT distinct(rx) FROM network where time >= '2000-01-01T00:00:00Z' AND time <= '2000-01-01T00:01:29Z' group by time(30s)`,
|
||||
exp: `{"results":[{"series":[{"name":"network","columns":["time","distinct"],"values":[["2000-01-01T00:00:00Z",10],["2000-01-01T00:00:10Z",40],["2000-01-01T00:00:30Z",40],["2000-01-01T00:00:40Z",50],["2000-01-01T00:01:00Z",70],["2000-01-01T00:01:10Z",90],["2000-01-01T00:01:20Z",5]]}]}]}`,
|
||||
exp: `{"results":[{"series":[{"name":"network","columns":["time","distinct"],"values":[["2000-01-01T00:00:00Z",10],["2000-01-01T00:00:00Z",40],["2000-01-01T00:00:30Z",40],["2000-01-01T00:00:30Z",50],["2000-01-01T00:01:00Z",70],["2000-01-01T00:01:00Z",90],["2000-01-01T00:01:00Z",5]]}]}]}`,
|
||||
},
|
||||
&Query{
|
||||
name: "distinct - time",
|
||||
|
|
|
@ -379,6 +379,12 @@ func NewDistinctIterator(input Iterator, opt IteratorOptions) (Iterator, error)
|
|||
return fn, fn
|
||||
}
|
||||
return &stringReduceStringIterator{input: newBufStringIterator(input), opt: opt, create: createFn}, nil
|
||||
case BooleanIterator:
|
||||
createFn := func() (BooleanPointAggregator, BooleanPointEmitter) {
|
||||
fn := NewBooleanSliceFuncReducer(BooleanDistinctReduceSlice)
|
||||
return fn, fn
|
||||
}
|
||||
return &booleanReduceBooleanIterator{input: newBufBooleanIterator(input), opt: opt, create: createFn}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported distinct iterator type: %T", input)
|
||||
}
|
||||
|
@ -435,6 +441,23 @@ func StringDistinctReduceSlice(a []StringPoint) []StringPoint {
|
|||
return points
|
||||
}
|
||||
|
||||
// BooleanDistinctReduceSlice returns the distinct value within a window.
|
||||
func BooleanDistinctReduceSlice(a []BooleanPoint) []BooleanPoint {
|
||||
m := make(map[bool]BooleanPoint)
|
||||
for _, p := range a {
|
||||
if _, ok := m[p.Value]; !ok {
|
||||
m[p.Value] = p
|
||||
}
|
||||
}
|
||||
|
||||
points := make([]BooleanPoint, 0, len(m))
|
||||
for _, p := range m {
|
||||
points = append(points, BooleanPoint{Time: p.Time, Value: p.Value})
|
||||
}
|
||||
sort.Sort(booleanPoints(points))
|
||||
return points
|
||||
}
|
||||
|
||||
// newMeanIterator returns an iterator for operating on a mean() call.
|
||||
func newMeanIterator(input Iterator, opt IteratorOptions) (Iterator, error) {
|
||||
switch input := input.(type) {
|
||||
|
|
|
@ -214,7 +214,11 @@ func buildExprIterator(expr Expr, ic IteratorCreator, opt IteratorOptions) (Iter
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewDistinctIterator(input, opt)
|
||||
input, err = NewDistinctIterator(input, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewIntervalIterator(input, opt), nil
|
||||
case "derivative", "non_negative_derivative":
|
||||
input, err := buildExprIterator(expr.Args[0], ic, opt)
|
||||
if err != nil {
|
||||
|
|
|
@ -66,8 +66,8 @@ func TestSelect_Distinct_Float(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
} else if a := Iterators(itrs).ReadAll(); !deep.Equal(a, [][]influxql.Point{
|
||||
{&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Value: 20}},
|
||||
{&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 1 * Second, Value: 19}},
|
||||
{&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 5 * Second, Value: 10}},
|
||||
{&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Value: 19}},
|
||||
{&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 0 * Second, Value: 10}},
|
||||
{&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 10 * Second, Value: 2}},
|
||||
}) {
|
||||
t.Fatalf("unexpected points: %s", spew.Sdump(a))
|
||||
|
@ -95,8 +95,8 @@ func TestSelect_Distinct_Integer(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
} else if a := Iterators(itrs).ReadAll(); !deep.Equal(a, [][]influxql.Point{
|
||||
{&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Value: 20}},
|
||||
{&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 1 * Second, Value: 19}},
|
||||
{&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 5 * Second, Value: 10}},
|
||||
{&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Value: 19}},
|
||||
{&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 0 * Second, Value: 10}},
|
||||
{&influxql.IntegerPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 10 * Second, Value: 2}},
|
||||
}) {
|
||||
t.Fatalf("unexpected points: %s", spew.Sdump(a))
|
||||
|
@ -124,29 +124,41 @@ func TestSelect_Distinct_String(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
} else if a := Iterators(itrs).ReadAll(); !deep.Equal(a, [][]influxql.Point{
|
||||
{&influxql.StringPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Value: "a"}},
|
||||
{&influxql.StringPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 1 * Second, Value: "b"}},
|
||||
{&influxql.StringPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 5 * Second, Value: "c"}},
|
||||
{&influxql.StringPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Value: "b"}},
|
||||
{&influxql.StringPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 0 * Second, Value: "c"}},
|
||||
{&influxql.StringPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 10 * Second, Value: "d"}},
|
||||
}) {
|
||||
t.Fatalf("unexpected points: %s", spew.Sdump(a))
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure a SELECT distinct() query cannot be executed on booleans.
|
||||
// Ensure a SELECT distinct() query can be executed.
|
||||
func TestSelect_Distinct_Boolean(t *testing.T) {
|
||||
var ic IteratorCreator
|
||||
ic.CreateIteratorFn = func(opt influxql.IteratorOptions) (influxql.Iterator, error) {
|
||||
return &BooleanIterator{}, nil
|
||||
return &BooleanIterator{Points: []influxql.BooleanPoint{
|
||||
{Name: "cpu", Tags: ParseTags("region=west,host=A"), Time: 0 * Second, Value: true},
|
||||
{Name: "cpu", Tags: ParseTags("region=west,host=A"), Time: 1 * Second, Value: false},
|
||||
{Name: "cpu", Tags: ParseTags("region=west,host=B"), Time: 5 * Second, Value: false},
|
||||
{Name: "cpu", Tags: ParseTags("region=east,host=A"), Time: 9 * Second, Value: true},
|
||||
{Name: "cpu", Tags: ParseTags("region=east,host=A"), Time: 10 * Second, Value: false},
|
||||
{Name: "cpu", Tags: ParseTags("region=east,host=A"), Time: 11 * Second, Value: false},
|
||||
{Name: "cpu", Tags: ParseTags("region=east,host=A"), Time: 12 * Second, Value: true},
|
||||
}}, nil
|
||||
}
|
||||
|
||||
// Execute selection.
|
||||
itrs, err := influxql.Select(MustParseSelectStatement(`SELECT distinct(value) FROM cpu WHERE time >= '1970-01-01T00:00:00Z' AND time < '1970-01-02T00:00:00Z' GROUP BY time(10s), host fill(none)`), &ic, nil)
|
||||
if err == nil || err.Error() != "unsupported distinct iterator type: *influxql_test.BooleanIterator" {
|
||||
t.Errorf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if itrs != nil {
|
||||
influxql.Iterators(itrs).Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if a := Iterators(itrs).ReadAll(); !deep.Equal(a, [][]influxql.Point{
|
||||
{&influxql.BooleanPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Value: true}},
|
||||
{&influxql.BooleanPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Value: false}},
|
||||
{&influxql.BooleanPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 0 * Second, Value: false}},
|
||||
{&influxql.BooleanPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 10 * Second, Value: false}},
|
||||
{&influxql.BooleanPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 10 * Second, Value: true}},
|
||||
}) {
|
||||
t.Errorf("unexpected points: %s", spew.Sdump(a))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1827,8 +1839,8 @@ func TestSelect_ParenExpr(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
} else if a := Iterators(itrs).ReadAll(); !deep.Equal(a, [][]influxql.Point{
|
||||
{&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Value: 20}},
|
||||
{&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 1 * Second, Value: 19}},
|
||||
{&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 5 * Second, Value: 10}},
|
||||
{&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0 * Second, Value: 19}},
|
||||
{&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=B"), Time: 0 * Second, Value: 10}},
|
||||
{&influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 10 * Second, Value: 2}},
|
||||
}) {
|
||||
t.Fatalf("unexpected points: %s", spew.Sdump(a))
|
||||
|
|
Loading…
Reference in New Issue