Merge pull request #6510 from influxdata/js-5890-return-time-with-selector

Return the time with a selector when there is no group by interval
pull/6523/head
Jonathan A. Sternberg 2016-04-29 17:39:20 -04:00
commit 8f876d0f3c
3 changed files with 46 additions and 32 deletions

View File

@ -52,6 +52,7 @@
- [#6468](https://github.com/influxdata/influxdb/issues/6468): Panic with truncated wal segments
- [#6480](https://github.com/influxdata/influxdb/issues/6480): Fix SHOW statements' rewriting bug
- [#6505](https://github.com/influxdata/influxdb/issues/6505): Add regex literal to InfluxQL spec for FROM clause.
- [#5890](https://github.com/influxdata/influxdb/issues/5890): Return the time with a selector when there is no group by interval.
## v0.12.2 [2016-04-20]

View File

@ -2615,19 +2615,19 @@ func TestServer_Query_Aggregates_IntMany(t *testing.T) {
name: "first - int",
params: url.Values{"db": []string{"db0"}},
command: `SELECT FIRST(value) FROM intmany`,
exp: `{"results":[{"series":[{"name":"intmany","columns":["time","first"],"values":[["1970-01-01T00:00:00Z",2]]}]}]}`,
exp: `{"results":[{"series":[{"name":"intmany","columns":["time","first"],"values":[["2000-01-01T00:00:00Z",2]]}]}]}`,
},
&Query{
name: "first - int - epoch ms",
params: url.Values{"db": []string{"db0"}, "epoch": []string{"ms"}},
command: `SELECT FIRST(value) FROM intmany`,
exp: fmt.Sprintf(`{"results":[{"series":[{"name":"intmany","columns":["time","first"],"values":[[%d,2]]}]}]}`, mustParseTime(time.RFC3339Nano, "1970-01-01T00:00:00Z").UnixNano()/int64(time.Millisecond)),
exp: fmt.Sprintf(`{"results":[{"series":[{"name":"intmany","columns":["time","first"],"values":[[%d,2]]}]}]}`, mustParseTime(time.RFC3339Nano, "2000-01-01T00:00:00Z").UnixNano()/int64(time.Millisecond)),
},
&Query{
name: "last - int",
params: url.Values{"db": []string{"db0"}},
command: `SELECT LAST(value) FROM intmany`,
exp: `{"results":[{"series":[{"name":"intmany","columns":["time","last"],"values":[["1970-01-01T00:00:00Z",9]]}]}]}`,
exp: `{"results":[{"series":[{"name":"intmany","columns":["time","last"],"values":[["2000-01-01T00:01:10Z",9]]}]}]}`,
},
&Query{
name: "spread - int",
@ -2995,13 +2995,13 @@ func TestServer_Query_Aggregates_FloatMany(t *testing.T) {
name: "first - float",
params: url.Values{"db": []string{"db0"}},
command: `SELECT FIRST(value) FROM floatmany`,
exp: `{"results":[{"series":[{"name":"floatmany","columns":["time","first"],"values":[["1970-01-01T00:00:00Z",2]]}]}]}`,
exp: `{"results":[{"series":[{"name":"floatmany","columns":["time","first"],"values":[["2000-01-01T00:00:00Z",2]]}]}]}`,
},
&Query{
name: "last - float",
params: url.Values{"db": []string{"db0"}},
command: `SELECT LAST(value) FROM floatmany`,
exp: `{"results":[{"series":[{"name":"floatmany","columns":["time","last"],"values":[["1970-01-01T00:00:00Z",9]]}]}]}`,
exp: `{"results":[{"series":[{"name":"floatmany","columns":["time","last"],"values":[["2000-01-01T00:01:10Z",9]]}]}]}`,
},
&Query{
name: "spread - float",
@ -3826,14 +3826,14 @@ func TestServer_Query_Aggregates_IdenticalTime(t *testing.T) {
name: "last from multiple series with identical timestamp",
params: url.Values{"db": []string{"db0"}},
command: `SELECT last(value) FROM "series"`,
exp: `{"results":[{"series":[{"name":"series","columns":["time","last"],"values":[["1970-01-01T00:00:00Z",5]]}]}]}`,
exp: `{"results":[{"series":[{"name":"series","columns":["time","last"],"values":[["2000-01-01T00:00:00Z",5]]}]}]}`,
repeat: 100,
},
&Query{
name: "first from multiple series with identical timestamp",
params: url.Values{"db": []string{"db0"}},
command: `SELECT first(value) FROM "series"`,
exp: `{"results":[{"series":[{"name":"series","columns":["time","first"],"values":[["1970-01-01T00:00:00Z",5]]}]}]}`,
exp: `{"results":[{"series":[{"name":"series","columns":["time","first"],"values":[["2000-01-01T00:00:00Z",5]]}]}]}`,
repeat: 100,
},
}...)

View File

@ -78,7 +78,18 @@ func Select(stmt *SelectStatement, ic IteratorCreator, sopt *SelectOptions) ([]I
}
}
return buildFieldIterators(fields, ic, opt)
// Determine if there is one call and it is a selector.
selector := false
if len(info.calls) == 1 {
for call := range info.calls {
switch call.Name {
case "first", "last", "min", "max", "percentile":
selector = true
}
}
}
return buildFieldIterators(fields, ic, opt, selector)
}
// buildAuxIterators creates a set of iterators from a single combined auxilary iterator.
@ -117,7 +128,7 @@ func buildAuxIterators(fields Fields, ic IteratorCreator, opt IteratorOptions) (
case *VarRef:
itrs[i] = aitr.Iterator(expr.Val)
case *BinaryExpr:
itr, err := buildExprIterator(expr, aitr, opt)
itr, err := buildExprIterator(expr, aitr, opt, false)
if err != nil {
return fmt.Errorf("error constructing iterator for field '%s': %s", f.String(), err)
}
@ -140,7 +151,7 @@ func buildAuxIterators(fields Fields, ic IteratorCreator, opt IteratorOptions) (
}
// buildFieldIterators creates an iterator for each field expression.
func buildFieldIterators(fields Fields, ic IteratorCreator, opt IteratorOptions) ([]Iterator, error) {
func buildFieldIterators(fields Fields, ic IteratorCreator, opt IteratorOptions, selector bool) ([]Iterator, error) {
// Create iterators from fields against the iterator creator.
itrs := make([]Iterator, len(fields))
@ -158,7 +169,7 @@ func buildFieldIterators(fields Fields, ic IteratorCreator, opt IteratorOptions)
}
expr := Reduce(f.Expr, nil)
itr, err := buildExprIterator(expr, ic, opt)
itr, err := buildExprIterator(expr, ic, opt, selector)
if err != nil {
return err
}
@ -185,7 +196,7 @@ func buildFieldIterators(fields Fields, ic IteratorCreator, opt IteratorOptions)
}
expr := Reduce(f.Expr, nil)
itr, err := buildExprIterator(expr, aitr, opt)
itr, err := buildExprIterator(expr, aitr, opt, false)
if err != nil {
return err
}
@ -210,7 +221,7 @@ func buildFieldIterators(fields Fields, ic IteratorCreator, opt IteratorOptions)
}
// buildExprIterator creates an iterator for an expression.
func buildExprIterator(expr Expr, ic IteratorCreator, opt IteratorOptions) (Iterator, error) {
func buildExprIterator(expr Expr, ic IteratorCreator, opt IteratorOptions, selector bool) (Iterator, error) {
opt.Expr = expr
switch expr := expr.(type) {
@ -221,7 +232,7 @@ func buildExprIterator(expr Expr, ic IteratorCreator, opt IteratorOptions) (Iter
switch expr.Name {
case "distinct":
input, err := buildExprIterator(expr.Args[0].(*VarRef), ic, opt)
input, err := buildExprIterator(expr.Args[0].(*VarRef), ic, opt, selector)
if err != nil {
return nil, err
}
@ -239,7 +250,7 @@ func buildExprIterator(expr Expr, ic IteratorCreator, opt IteratorOptions) (Iter
}
}
input, err := buildExprIterator(expr.Args[0], ic, opt)
input, err := buildExprIterator(expr.Args[0], ic, opt, selector)
if err != nil {
return nil, err
}
@ -273,7 +284,7 @@ func buildExprIterator(expr Expr, ic IteratorCreator, opt IteratorOptions) (Iter
switch arg := expr.Args[0].(type) {
case *Call:
if arg.Name == "distinct" {
input, err := buildExprIterator(arg, ic, opt)
input, err := buildExprIterator(arg, ic, opt, selector)
if err != nil {
return nil, err
}
@ -284,20 +295,20 @@ func buildExprIterator(expr Expr, ic IteratorCreator, opt IteratorOptions) (Iter
case "min", "max", "sum", "first", "last", "mean":
return ic.CreateIterator(opt)
case "median":
input, err := buildExprIterator(expr.Args[0].(*VarRef), ic, opt)
input, err := buildExprIterator(expr.Args[0].(*VarRef), ic, opt, false)
if err != nil {
return nil, err
}
return newMedianIterator(input, opt)
case "stddev":
input, err := buildExprIterator(expr.Args[0].(*VarRef), ic, opt)
input, err := buildExprIterator(expr.Args[0].(*VarRef), ic, opt, false)
if err != nil {
return nil, err
}
return newStddevIterator(input, opt)
case "spread":
// OPTIMIZE(benbjohnson): convert to map/reduce
input, err := buildExprIterator(expr.Args[0].(*VarRef), ic, opt)
input, err := buildExprIterator(expr.Args[0].(*VarRef), ic, opt, false)
if err != nil {
return nil, err
}
@ -320,7 +331,7 @@ func buildExprIterator(expr Expr, ic IteratorCreator, opt IteratorOptions) (Iter
}
}
input, err := buildExprIterator(expr.Args[0].(*VarRef), ic, opt)
input, err := buildExprIterator(expr.Args[0].(*VarRef), ic, opt, false)
if err != nil {
return nil, err
}
@ -344,14 +355,14 @@ func buildExprIterator(expr Expr, ic IteratorCreator, opt IteratorOptions) (Iter
}
}
input, err := buildExprIterator(expr.Args[0].(*VarRef), ic, opt)
input, err := buildExprIterator(expr.Args[0].(*VarRef), ic, opt, false)
if err != nil {
return nil, err
}
n := expr.Args[len(expr.Args)-1].(*IntegerLiteral)
return newBottomIterator(input, opt, n, tags)
case "percentile":
input, err := buildExprIterator(expr.Args[0].(*VarRef), ic, opt)
input, err := buildExprIterator(expr.Args[0].(*VarRef), ic, opt, false)
if err != nil {
return nil, err
}
@ -372,11 +383,13 @@ func buildExprIterator(expr Expr, ic IteratorCreator, opt IteratorOptions) (Iter
return nil, err
}
if expr.Name != "top" && expr.Name != "bottom" {
itr = NewIntervalIterator(itr, opt)
}
if !opt.Interval.IsZero() && opt.Fill != NoFill {
itr = NewFillIterator(itr, expr, opt)
if !selector || !opt.Interval.IsZero() {
if expr.Name != "top" && expr.Name != "bottom" {
itr = NewIntervalIterator(itr, opt)
}
if !opt.Interval.IsZero() && opt.Fill != NoFill {
itr = NewFillIterator(itr, expr, opt)
}
}
if opt.InterruptCh != nil {
itr = NewInterruptIterator(itr, opt.InterruptCh)
@ -392,31 +405,31 @@ func buildExprIterator(expr Expr, ic IteratorCreator, opt IteratorOptions) (Iter
return nil, fmt.Errorf("unable to construct an iterator from two literals: LHS: %T, RHS: %T", lhs, rhs)
}
lhs, err := buildExprIterator(expr.LHS, ic, opt)
lhs, err := buildExprIterator(expr.LHS, ic, opt, false)
if err != nil {
return nil, err
}
return buildRHSTransformIterator(lhs, rhs, expr.Op, ic, opt)
} else if lhs, ok := expr.LHS.(Literal); ok {
rhs, err := buildExprIterator(expr.RHS, ic, opt)
rhs, err := buildExprIterator(expr.RHS, ic, opt, false)
if err != nil {
return nil, err
}
return buildLHSTransformIterator(lhs, rhs, expr.Op, ic, opt)
} else {
// We have two iterators. Combine them into a single iterator.
lhs, err := buildExprIterator(expr.LHS, ic, opt)
lhs, err := buildExprIterator(expr.LHS, ic, opt, false)
if err != nil {
return nil, err
}
rhs, err := buildExprIterator(expr.RHS, ic, opt)
rhs, err := buildExprIterator(expr.RHS, ic, opt, false)
if err != nil {
return nil, err
}
return buildTransformIterator(lhs, rhs, expr.Op, ic, opt)
}
case *ParenExpr:
return buildExprIterator(expr.Expr, ic, opt)
return buildExprIterator(expr.Expr, ic, opt, selector)
default:
return nil, fmt.Errorf("invalid expression type: %T", expr)
}