184 lines
4.5 KiB
Go
184 lines
4.5 KiB
Go
package engine
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
|
|
"github.com/influxdb/influxdb/common"
|
|
"github.com/influxdb/influxdb/protocol"
|
|
)
|
|
|
|
type OperatorResult int
|
|
|
|
const (
|
|
MATCH OperatorResult = iota
|
|
NO_MATCH
|
|
INVALID
|
|
)
|
|
|
|
type oldBooleanOperation func(leftValue, rightValues *protocol.FieldValue) (OperatorResult, error)
|
|
type BooleanOperation func(leftValue *protocol.FieldValue, rightValues []*protocol.FieldValue) (OperatorResult, error)
|
|
|
|
func wrapOldBooleanOperation(operation oldBooleanOperation) BooleanOperation {
|
|
return func(leftValue *protocol.FieldValue, rightValues []*protocol.FieldValue) (OperatorResult, error) {
|
|
if len(rightValues) != 1 {
|
|
return INVALID, fmt.Errorf("Expected one value on the right side")
|
|
}
|
|
|
|
if leftValue == nil || rightValues[0] == nil {
|
|
return INVALID, nil
|
|
}
|
|
|
|
return operation(leftValue, rightValues[0])
|
|
}
|
|
}
|
|
|
|
var (
|
|
registeredOperators = map[string]BooleanOperation{}
|
|
)
|
|
|
|
func init() {
|
|
registeredOperators["="] = wrapOldBooleanOperation(EqualityOperator)
|
|
registeredOperators["<>"] = not(wrapOldBooleanOperation(EqualityOperator))
|
|
registeredOperators[">="] = wrapOldBooleanOperation(GreaterThanOrEqualOperator)
|
|
registeredOperators[">"] = wrapOldBooleanOperation(GreaterThanOperator)
|
|
registeredOperators["<"] = not(wrapOldBooleanOperation(GreaterThanOrEqualOperator))
|
|
registeredOperators["<="] = not(wrapOldBooleanOperation(GreaterThanOperator))
|
|
registeredOperators["=~"] = wrapOldBooleanOperation(RegexMatcherOperator)
|
|
registeredOperators["!~"] = not(wrapOldBooleanOperation(RegexMatcherOperator))
|
|
registeredOperators["in"] = InOperator
|
|
}
|
|
|
|
func not(op BooleanOperation) BooleanOperation {
|
|
return func(leftValue *protocol.FieldValue, rightValue []*protocol.FieldValue) (OperatorResult, error) {
|
|
ok, err := op(leftValue, rightValue)
|
|
switch ok {
|
|
case MATCH:
|
|
return NO_MATCH, err
|
|
case NO_MATCH:
|
|
return MATCH, err
|
|
default:
|
|
return INVALID, err
|
|
}
|
|
}
|
|
}
|
|
|
|
func EqualityOperator(leftValue, rightValue *protocol.FieldValue) (OperatorResult, error) {
|
|
v1, v2, cType := common.CoerceValues(leftValue, rightValue)
|
|
|
|
switch cType {
|
|
case common.TYPE_STRING:
|
|
if v1.(string) == v2.(string) {
|
|
return MATCH, nil
|
|
}
|
|
return NO_MATCH, nil
|
|
case common.TYPE_INT:
|
|
if v1.(int64) == v2.(int64) {
|
|
return MATCH, nil
|
|
}
|
|
return NO_MATCH, nil
|
|
case common.TYPE_DOUBLE:
|
|
if v1.(float64) == v2.(float64) {
|
|
return MATCH, nil
|
|
}
|
|
return NO_MATCH, nil
|
|
case common.TYPE_BOOL:
|
|
if v1.(bool) == v2.(bool) {
|
|
return MATCH, nil
|
|
}
|
|
return NO_MATCH, nil
|
|
default:
|
|
return INVALID, nil
|
|
}
|
|
}
|
|
|
|
func RegexMatcherOperator(leftValue, rightValue *protocol.FieldValue) (OperatorResult, error) {
|
|
v1, v2, cType := common.CoerceValues(leftValue, rightValue)
|
|
|
|
switch cType {
|
|
case common.TYPE_STRING:
|
|
// TODO: assume that the regex is valid
|
|
if ok, _ := regexp.MatchString(v2.(string), v1.(string)); ok {
|
|
return MATCH, nil
|
|
}
|
|
return NO_MATCH, nil
|
|
default:
|
|
return INVALID, nil
|
|
}
|
|
}
|
|
|
|
func GreaterThanOrEqualOperator(leftValue, rightValue *protocol.FieldValue) (OperatorResult, error) {
|
|
v1, v2, cType := common.CoerceValues(leftValue, rightValue)
|
|
|
|
switch cType {
|
|
case common.TYPE_STRING:
|
|
if v1.(string) >= v2.(string) {
|
|
return MATCH, nil
|
|
}
|
|
return NO_MATCH, nil
|
|
case common.TYPE_INT:
|
|
if v1.(int64) >= v2.(int64) {
|
|
return MATCH, nil
|
|
}
|
|
return NO_MATCH, nil
|
|
case common.TYPE_DOUBLE:
|
|
if v1.(float64) >= v2.(float64) {
|
|
return MATCH, nil
|
|
}
|
|
return NO_MATCH, nil
|
|
default:
|
|
return INVALID, nil
|
|
}
|
|
}
|
|
|
|
func GreaterThanOperator(leftValue, rightValue *protocol.FieldValue) (OperatorResult, error) {
|
|
v1, v2, cType := common.CoerceValues(leftValue, rightValue)
|
|
|
|
switch cType {
|
|
case common.TYPE_STRING:
|
|
if v1.(string) > v2.(string) {
|
|
return MATCH, nil
|
|
}
|
|
return NO_MATCH, nil
|
|
case common.TYPE_INT:
|
|
if v1.(int64) > v2.(int64) {
|
|
return MATCH, nil
|
|
}
|
|
return NO_MATCH, nil
|
|
case common.TYPE_DOUBLE:
|
|
if v1.(float64) > v2.(float64) {
|
|
return MATCH, nil
|
|
}
|
|
return NO_MATCH, nil
|
|
default:
|
|
return INVALID, nil
|
|
}
|
|
}
|
|
|
|
func InOperator(leftValue *protocol.FieldValue, rightValue []*protocol.FieldValue) (OperatorResult, error) {
|
|
for _, v := range rightValue {
|
|
v1, v2, cType := common.CoerceValues(leftValue, v)
|
|
|
|
var result bool
|
|
|
|
switch cType {
|
|
case common.TYPE_STRING:
|
|
result = v1.(string) == v2.(string)
|
|
case common.TYPE_INT:
|
|
result = v1.(int64) == v2.(int64)
|
|
case common.TYPE_DOUBLE:
|
|
result = v1.(float64) == v2.(float64)
|
|
case common.TYPE_BOOL:
|
|
result = v1.(bool) == v2.(bool)
|
|
default:
|
|
return INVALID, nil
|
|
}
|
|
|
|
if result {
|
|
return MATCH, nil
|
|
}
|
|
}
|
|
|
|
return NO_MATCH, nil
|
|
}
|