From e49ba016fa9e3f29d7bb284532da68859dd95410 Mon Sep 17 00:00:00 2001 From: "Jonathan A. Sternberg" Date: Thu, 2 Feb 2017 13:30:09 -0600 Subject: [PATCH] Fix incorrect math when aggregates that emit different times are used When using `non_negative_derivative()` and `last()` in a math aggregate with each other, the math would not be matched with each other because one of those aggregates would emit one fewer point than the others. The math iterators have been modified so they now track the name and tags of a point and match based on those. This isn't necessarily ideal and may come to bite us in the future. We don't necessarily have a defined structure for all iterators so it can be difficult to know which of two points is supposed to come first in the ordering. This uses the common ordering that usually makes sense, but the query engine is getting complicated enough where I am not 100% certain that this is correct in all circumstances. --- CHANGELOG.md | 1 + cmd/influxd/run/server_test.go | 14 + influxql/iterator.gen.go | 1056 +++++++++++++++++++++----------- influxql/iterator.gen.go.tmpl | 66 +- 4 files changed, 763 insertions(+), 374 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6708fd2d77..557c5d9461 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - [#7910](https://github.com/influxdata/influxdb/issues/7910): Fix EvalType when a parenthesis expression is used. - [#7929](https://github.com/influxdata/influxdb/issues/7929): Fix series tag iteration segfault. (#7922) - [#7906](https://github.com/influxdata/influxdb/issues/7906): Anchors not working as expected with case-insensitive regex +- [#7895](https://github.com/influxdata/influxdb/issues/7895): Fix incorrect math when aggregates that emit different times are used. ## v1.2.0 [2017-01-24] diff --git a/cmd/influxd/run/server_test.go b/cmd/influxd/run/server_test.go index 74d63977de..79e976dac8 100644 --- a/cmd/influxd/run/server_test.go +++ b/cmd/influxd/run/server_test.go @@ -1684,6 +1684,15 @@ func TestServer_Query_SelectGroupByTimeDerivative(t *testing.T) { cpu value=15 1278010021000000000 cpu value=20 1278010022000000000 cpu value=25 1278010023000000000 + +cpu0,host=server01 ticks=10,total=100 1278010020000000000 +cpu0,host=server01 ticks=30,total=100 1278010021000000000 +cpu0,host=server01 ticks=32,total=100 1278010022000000000 +cpu0,host=server01 ticks=47,total=100 1278010023000000000 +cpu0,host=server02 ticks=40,total=100 1278010020000000000 +cpu0,host=server02 ticks=45,total=100 1278010021000000000 +cpu0,host=server02 ticks=84,total=100 1278010022000000000 +cpu0,host=server02 ticks=101,total=100 1278010023000000000 `)}, } @@ -1789,6 +1798,11 @@ cpu value=25 1278010023000000000 command: `SELECT derivative(percentile(value, 50), 4s) from db0.rp0.cpu where time >= '2010-07-01 18:47:00' and time <= '2010-07-01 18:47:03' group by time(2s)`, exp: `{"results":[{"statement_id":0,"series":[{"name":"cpu","columns":["time","derivative"],"values":[["2010-07-01T18:47:02Z",20]]}]}]}`, }, + &Query{ + name: "calculate derivative of ticks divided by aggregate", + command: `SELECT non_negative_derivative(mean(ticks), 1s) / last(total) * 100 AS usage FROM db0.rp0.cpu0 WHERE time >= '2010-07-01 18:47:00' AND time <= '2010-07-01 18:47:03' GROUP BY host, time(1s)`, + exp: `{"results":[{"statement_id":0,"series":[{"name":"cpu0","tags":{"host":"server01"},"columns":["time","usage"],"values":[["2010-07-01T18:47:00Z",null],["2010-07-01T18:47:01Z",20],["2010-07-01T18:47:02Z",2],["2010-07-01T18:47:03Z",15]]},{"name":"cpu0","tags":{"host":"server02"},"columns":["time","usage"],"values":[["2010-07-01T18:47:00Z",null],["2010-07-01T18:47:01Z",5],["2010-07-01T18:47:02Z",39],["2010-07-01T18:47:03Z",17]]}]}]}`, + }, }...) for i, query := range test.queries { diff --git a/influxql/iterator.gen.go b/influxql/iterator.gen.go index 9ebb5d712b..665b2f838d 100644 --- a/influxql/iterator.gen.go +++ b/influxql/iterator.gen.go @@ -1258,30 +1258,10 @@ func (itr *floatExprIterator) Close() error { func (itr *floatExprIterator) Next() (*FloatPoint, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -1322,6 +1302,48 @@ func (itr *floatExprIterator) Next() (*FloatPoint, error) { } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *floatExprIterator) next() (a, b *FloatPoint, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // floatExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at @@ -1598,30 +1620,10 @@ func (itr *floatIntegerExprIterator) Close() error { func (itr *floatIntegerExprIterator) Next() (*IntegerPoint, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -1666,6 +1668,48 @@ func (itr *floatIntegerExprIterator) Next() (*IntegerPoint, error) { } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *floatIntegerExprIterator) next() (a, b *FloatPoint, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // floatIntegerExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at @@ -1942,30 +1986,10 @@ func (itr *floatStringExprIterator) Close() error { func (itr *floatStringExprIterator) Next() (*StringPoint, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -2010,6 +2034,48 @@ func (itr *floatStringExprIterator) Next() (*StringPoint, error) { } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *floatStringExprIterator) next() (a, b *FloatPoint, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // floatStringExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at @@ -2286,30 +2352,10 @@ func (itr *floatBooleanExprIterator) Close() error { func (itr *floatBooleanExprIterator) Next() (*BooleanPoint, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -2354,6 +2400,48 @@ func (itr *floatBooleanExprIterator) Next() (*BooleanPoint, error) { } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *floatBooleanExprIterator) next() (a, b *FloatPoint, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // floatBooleanExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at @@ -3798,30 +3886,10 @@ func (itr *integerFloatExprIterator) Close() error { func (itr *integerFloatExprIterator) Next() (*FloatPoint, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -3866,6 +3934,48 @@ func (itr *integerFloatExprIterator) Next() (*FloatPoint, error) { } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *integerFloatExprIterator) next() (a, b *IntegerPoint, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // integerFloatExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at @@ -4142,30 +4252,10 @@ func (itr *integerExprIterator) Close() error { func (itr *integerExprIterator) Next() (*IntegerPoint, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -4206,6 +4296,48 @@ func (itr *integerExprIterator) Next() (*IntegerPoint, error) { } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *integerExprIterator) next() (a, b *IntegerPoint, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // integerExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at @@ -4482,30 +4614,10 @@ func (itr *integerStringExprIterator) Close() error { func (itr *integerStringExprIterator) Next() (*StringPoint, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -4550,6 +4662,48 @@ func (itr *integerStringExprIterator) Next() (*StringPoint, error) { } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *integerStringExprIterator) next() (a, b *IntegerPoint, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // integerStringExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at @@ -4826,30 +4980,10 @@ func (itr *integerBooleanExprIterator) Close() error { func (itr *integerBooleanExprIterator) Next() (*BooleanPoint, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -4894,6 +5028,48 @@ func (itr *integerBooleanExprIterator) Next() (*BooleanPoint, error) { } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *integerBooleanExprIterator) next() (a, b *IntegerPoint, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // integerBooleanExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at @@ -6323,30 +6499,10 @@ func (itr *stringFloatExprIterator) Close() error { func (itr *stringFloatExprIterator) Next() (*FloatPoint, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -6391,6 +6547,48 @@ func (itr *stringFloatExprIterator) Next() (*FloatPoint, error) { } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *stringFloatExprIterator) next() (a, b *StringPoint, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // stringFloatExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at @@ -6667,30 +6865,10 @@ func (itr *stringIntegerExprIterator) Close() error { func (itr *stringIntegerExprIterator) Next() (*IntegerPoint, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -6735,6 +6913,48 @@ func (itr *stringIntegerExprIterator) Next() (*IntegerPoint, error) { } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *stringIntegerExprIterator) next() (a, b *StringPoint, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // stringIntegerExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at @@ -7011,30 +7231,10 @@ func (itr *stringExprIterator) Close() error { func (itr *stringExprIterator) Next() (*StringPoint, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -7075,6 +7275,48 @@ func (itr *stringExprIterator) Next() (*StringPoint, error) { } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *stringExprIterator) next() (a, b *StringPoint, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // stringExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at @@ -7351,30 +7593,10 @@ func (itr *stringBooleanExprIterator) Close() error { func (itr *stringBooleanExprIterator) Next() (*BooleanPoint, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -7419,6 +7641,48 @@ func (itr *stringBooleanExprIterator) Next() (*BooleanPoint, error) { } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *stringBooleanExprIterator) next() (a, b *StringPoint, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // stringBooleanExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at @@ -8848,30 +9112,10 @@ func (itr *booleanFloatExprIterator) Close() error { func (itr *booleanFloatExprIterator) Next() (*FloatPoint, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -8916,6 +9160,48 @@ func (itr *booleanFloatExprIterator) Next() (*FloatPoint, error) { } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *booleanFloatExprIterator) next() (a, b *BooleanPoint, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // booleanFloatExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at @@ -9192,30 +9478,10 @@ func (itr *booleanIntegerExprIterator) Close() error { func (itr *booleanIntegerExprIterator) Next() (*IntegerPoint, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -9260,6 +9526,48 @@ func (itr *booleanIntegerExprIterator) Next() (*IntegerPoint, error) { } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *booleanIntegerExprIterator) next() (a, b *BooleanPoint, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // booleanIntegerExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at @@ -9536,30 +9844,10 @@ func (itr *booleanStringExprIterator) Close() error { func (itr *booleanStringExprIterator) Next() (*StringPoint, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -9604,6 +9892,48 @@ func (itr *booleanStringExprIterator) Next() (*StringPoint, error) { } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *booleanStringExprIterator) next() (a, b *BooleanPoint, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // booleanStringExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at @@ -9880,30 +10210,10 @@ func (itr *booleanExprIterator) Close() error { func (itr *booleanExprIterator) Next() (*BooleanPoint, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -9944,6 +10254,48 @@ func (itr *booleanExprIterator) Next() (*BooleanPoint, error) { } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *booleanExprIterator) next() (a, b *BooleanPoint, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // booleanExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at diff --git a/influxql/iterator.gen.go.tmpl b/influxql/iterator.gen.go.tmpl index ce12a9b326..61d32c46af 100644 --- a/influxql/iterator.gen.go.tmpl +++ b/influxql/iterator.gen.go.tmpl @@ -1259,30 +1259,10 @@ func (itr *{{$k.name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprIterator) C func (itr *{{$k.name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprIterator) Next() (*{{$v.Name}}Point, error) { for { - a, err := itr.left.Next() - if err != nil { + a, b, err := itr.next() + if err != nil || (a == nil && b == nil) { return nil, err } - b, err := itr.right.Next() - if err != nil { - return nil, err - } - - if a == nil && b == nil { - return nil, nil - } else if itr.points == nil && (a == nil || b == nil ) { - return nil, nil - } - - if a != nil && b != nil { - if a.Time > b.Time { - itr.left.unread(a) - a = nil - } else if a.Time < b.Time { - itr.right.unread(b) - b = nil - } - } if a == nil || a.Nil { if itr.points == nil { @@ -1336,6 +1316,48 @@ func (itr *{{$k.name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprIterator) N } } +// next returns the next points within each iterator. If the iterators are +// uneven, it organizes them so only matching points are returned. +func (itr *{{$k.name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprIterator) next() (a, b *{{$k.Name}}Point, err error) { + // Retrieve the next value for both the left and right. + a, err = itr.left.Next() + if err != nil { + return nil, nil, err + } + b, err = itr.right.Next() + if err != nil { + return nil, nil, err + } + + // If we have a point from both, make sure that they match each other. + if a != nil && b != nil { + if a.Name > b.Name { + itr.left.unread(a) + return nil, b, nil + } else if a.Name < b.Name { + itr.right.unread(b) + return a, nil, nil + } + + if ltags, rtags := a.Tags.ID(), b.Tags.ID(); ltags > rtags { + itr.left.unread(a) + return nil, b, nil + } else if ltags < rtags { + itr.right.unread(b) + return a, nil, nil + } + + if a.Time > b.Time { + itr.left.unread(a) + return nil, b, nil + } else if a.Time < b.Time { + itr.right.unread(b) + return a, nil, nil + } + } + return a, b, nil +} + // {{$k.name}}{{if ne $k.Name $v.Name}}{{$v.Name}}{{end}}ExprFunc creates or modifies a point by combining two // points. The point passed in may be modified and returned rather than // allocating a new point if possible. One of the points may be nil, but at