Merge pull request #7765 from influxdata/js-7553-modulo-operator

Add modulo operator to the query language
pull/7990/head
Jonathan A. Sternberg 2017-02-10 11:46:24 -06:00 committed by GitHub
commit 5395bd3bcf
7 changed files with 43 additions and 0 deletions

View File

@ -4,6 +4,7 @@
- [#7776](https://github.com/influxdata/influxdb/issues/7776): Add system information to /debug/vars.
- [#7948](https://github.com/influxdata/influxdb/pull/7948): Reduce memory allocations by reusing gzip.Writers across requests
- [#7553](https://github.com/influxdata/influxdb/issues/7553): Add modulo operator to the query language.
## v1.2.1 [unreleased]

View File

@ -4,6 +4,7 @@ import (
"bytes"
"errors"
"fmt"
"math"
"regexp"
"regexp/syntax"
"sort"
@ -4301,6 +4302,11 @@ func evalBinaryExpr(expr *BinaryExpr, m map[string]interface{}) interface{} {
return float64(0)
}
return lhs / rhs
case MOD:
if !ok {
return nil
}
return math.Mod(lhs, rhs)
}
case int64:
// Try as a float64 to see if a float cast is required.
@ -4332,6 +4338,8 @@ func evalBinaryExpr(expr *BinaryExpr, m map[string]interface{}) interface{} {
return float64(0)
}
return lhs / rhs
case MOD:
return math.Mod(lhs, rhs)
}
} else {
rhs, ok := rhs.(int64)
@ -4370,6 +4378,13 @@ func evalBinaryExpr(expr *BinaryExpr, m map[string]interface{}) interface{} {
return float64(0)
}
return lhs / rhs
case MOD:
if !ok {
return nil
} else if rhs == 0 {
return int64(0)
}
return lhs % rhs
}
}
case string:
@ -4709,6 +4724,11 @@ func reduceBinaryExprIntegerLHS(op Token, lhs *IntegerLiteral, rhs Expr) Expr {
return &NumberLiteral{Val: 0}
}
return &NumberLiteral{Val: float64(lhs.Val) / float64(rhs.Val)}
case MOD:
if rhs.Val == 0 {
return &IntegerLiteral{Val: 0}
}
return &IntegerLiteral{Val: lhs.Val % rhs.Val}
case EQ:
return &BooleanLiteral{Val: lhs.Val == rhs.Val}
case NEQ:
@ -4775,6 +4795,8 @@ func reduceBinaryExprNumberLHS(op Token, lhs *NumberLiteral, rhs Expr) Expr {
return &NumberLiteral{Val: 0}
}
return &NumberLiteral{Val: lhs.Val / rhs.Val}
case MOD:
return &NumberLiteral{Val: math.Mod(lhs.Val, rhs.Val)}
case EQ:
return &BooleanLiteral{Val: lhs.Val == rhs.Val}
case NEQ:
@ -4801,6 +4823,8 @@ func reduceBinaryExprNumberLHS(op Token, lhs *NumberLiteral, rhs Expr) Expr {
return &NumberLiteral{Val: 0}
}
return &NumberLiteral{Val: lhs.Val / float64(rhs.Val)}
case MOD:
return &NumberLiteral{Val: math.Mod(lhs.Val, float64(rhs.Val))}
case EQ:
return &BooleanLiteral{Val: lhs.Val == float64(rhs.Val)}
case NEQ:

View File

@ -1175,6 +1175,10 @@ func TestReduce(t *testing.T) {
{in: `foo(bar(2 + 3), 4)`, out: `foo(bar(5), 4)`},
{in: `4 / 0`, out: `0.000`},
{in: `1 / 2`, out: `0.500`},
{in: `2 % 3`, out: `2`},
{in: `5 % 2`, out: `1`},
{in: `2 % 0`, out: `0`},
{in: `2.5 % 0`, out: `NaN`},
{in: `4 = 4`, out: `true`},
{in: `4 <> 4`, out: `false`},
{in: `6 > 4`, out: `true`},

View File

@ -65,6 +65,8 @@ func (s *Scanner) Scan() (tok Token, pos Pos, lit string) {
return MUL, pos, ""
case '/':
return DIV, pos, ""
case '%':
return MOD, pos, ""
case '=':
if ch1, _ := s.r.read(); ch1 == '~' {
return EQREGEX, pos, ""

View File

@ -34,6 +34,7 @@ func TestScanner_Scan(t *testing.T) {
{s: `-`, tok: influxql.SUB},
{s: `*`, tok: influxql.MUL},
{s: `/`, tok: influxql.DIV},
{s: `%`, tok: influxql.MOD},
// Logical operators
{s: `AND`, tok: influxql.AND},

View File

@ -3,6 +3,7 @@ package influxql
import (
"errors"
"fmt"
"math"
"sort"
"time"
)
@ -1482,6 +1483,8 @@ func floatBinaryExprFunc(op Token) interface{} {
}
return lhs / rhs
}
case MOD:
return func(lhs, rhs float64) float64 { return math.Mod(lhs, rhs) }
case EQ:
return func(lhs, rhs float64) bool { return lhs == rhs }
case NEQ:
@ -1513,6 +1516,13 @@ func integerBinaryExprFunc(op Token) interface{} {
}
return float64(lhs) / float64(rhs)
}
case MOD:
return func(lhs, rhs int64) int64 {
if rhs == 0 {
return int64(0)
}
return lhs % rhs
}
case EQ:
return func(lhs, rhs int64) bool { return lhs == rhs }
case NEQ:

View File

@ -36,6 +36,7 @@ const (
SUB // -
MUL // *
DIV // /
MOD // %
AND // AND
OR // OR