Have division always return a float in the new query engine

Fixes #5892.
pull/5893/head
Jonathan A. Sternberg 2016-03-03 08:15:54 -05:00
parent 2440568b27
commit fabc41dcfb
3 changed files with 59 additions and 7 deletions

View File

@ -1744,7 +1744,7 @@ func (itr *integerReduceSliceIterator) reduce() []IntegerPoint {
// integerReduceSliceFunc is the function called by a IntegerPoint slice reducer. // integerReduceSliceFunc is the function called by a IntegerPoint slice reducer.
type integerReduceSliceFunc func(a []IntegerPoint, opt *reduceOptions) []IntegerPoint type integerReduceSliceFunc func(a []IntegerPoint, opt *reduceOptions) []IntegerPoint
// integerReduceIterator executes a function to modify an existing point for every // integerTransformIterator executes a function to modify an existing point for every
// output of the input iterator. // output of the input iterator.
type integerTransformIterator struct { type integerTransformIterator struct {
input IntegerIterator input IntegerIterator
@ -1768,6 +1768,30 @@ func (itr *integerTransformIterator) Next() *IntegerPoint {
// new point if possible. // new point if possible.
type integerTransformFunc func(p *IntegerPoint) *IntegerPoint type integerTransformFunc func(p *IntegerPoint) *IntegerPoint
// integerFloatTransformIterator executes a function to modify an existing point for every
// output of the input iterator.
type integerFloatTransformIterator struct {
input IntegerIterator
fn integerFloatTransformFunc
}
// Close closes the iterator and all child iterators.
func (itr *integerFloatTransformIterator) Close() error { return itr.input.Close() }
// Next returns the minimum value for the next available interval.
func (itr *integerFloatTransformIterator) Next() *FloatPoint {
p := itr.input.Next()
if p != nil {
return itr.fn(p)
}
return nil
}
// integerFloatTransformFunc creates or modifies a point.
// The point passed in may be modified and returned rather than allocating a
// new point if possible.
type integerFloatTransformFunc func(p *IntegerPoint) *FloatPoint
// integerReduceIterator executes a function to modify an existing point for every // integerReduceIterator executes a function to modify an existing point for every
// output of the input iterator. // output of the input iterator.
type integerBoolTransformIterator struct { type integerBoolTransformIterator struct {

View File

@ -534,6 +534,34 @@ func buildTransformIterator(lhs Iterator, rhs Iterator, op Token, ic IteratorCre
return p return p
}, },
}, nil }, nil
case func(int64, int64) float64:
left, ok := lhs.(IntegerIterator)
if !ok {
return nil, fmt.Errorf("type mismatch on LHS, unable to use %T as a IntegerIterator", lhs)
}
right, ok := rhs.(IntegerIterator)
if !ok {
return nil, fmt.Errorf("type mismatch on RHS, unable to use %T as a IntegerIterator", rhs)
}
return &integerFloatTransformIterator{
input: left,
fn: func(p *IntegerPoint) *FloatPoint {
if p == nil {
return nil
}
p2 := right.Next()
if p2 == nil {
return nil
}
return &FloatPoint{
Name: p.Name,
Tags: p.Tags,
Time: p.Time,
Value: fn(p.Value, p2.Value),
Aux: p.Aux,
}
},
}, nil
case func(int64, int64) int64: case func(int64, int64) int64:
left, ok := lhs.(IntegerIterator) left, ok := lhs.(IntegerIterator)
if !ok { if !ok {
@ -712,11 +740,11 @@ func integerBinaryExprFunc(op Token) interface{} {
case MUL: case MUL:
return func(lhs, rhs int64) int64 { return lhs * rhs } return func(lhs, rhs int64) int64 { return lhs * rhs }
case DIV: case DIV:
return func(lhs, rhs int64) int64 { return func(lhs, rhs int64) float64 {
if rhs == 0 { if rhs == 0 {
return int64(0) return float64(0)
} }
return lhs / rhs return float64(lhs) / float64(rhs)
} }
case EQ: case EQ:
return func(lhs, rhs int64) bool { return lhs == rhs } return func(lhs, rhs int64) bool { return lhs == rhs }

View File

@ -1493,9 +1493,9 @@ func TestSelect_BinaryExpr_Integer(t *testing.T) {
Name: "two variable binary division", Name: "two variable binary division",
Statement: `SELECT value / value FROM cpu`, Statement: `SELECT value / value FROM cpu`,
Points: [][]influxql.Point{ Points: [][]influxql.Point{
{&influxql.IntegerPoint{Name: "cpu", Time: 0 * Second, Value: 1}}, {&influxql.FloatPoint{Name: "cpu", Time: 0 * Second, Value: 1}},
{&influxql.IntegerPoint{Name: "cpu", Time: 5 * Second, Value: 1}}, {&influxql.FloatPoint{Name: "cpu", Time: 5 * Second, Value: 1}},
{&influxql.IntegerPoint{Name: "cpu", Time: 9 * Second, Value: 1}}, {&influxql.FloatPoint{Name: "cpu", Time: 9 * Second, Value: 1}},
}, },
}, },
} { } {