Merge pull request #190 from travisturner/decimal-between

serialize decimal between pql for internode queries
This commit is contained in:
Travis Turner 2020-03-19 11:26:12 -05:00 committed by GitHub
commit 564eee0bdf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 59 deletions

View file

@ -800,54 +800,23 @@ func (cond *Condition) StringWithSubj(subj string) string {
case EQ, NEQ, LT, LTE, GT, GTE:
return fmt.Sprintf("%s%s", subj, cond.String())
case BETWEEN, BTWN_LT_LTE, BTWN_LTE_LT, BTWN_LT_LT:
val, ok := cond.Int64SliceValue() // TODO: this should depend on subj type (int64 vs. uint64)
val, ok := cond.StringSliceValue()
if !ok || len(val) < 2 {
return ""
}
if cond.Op == BETWEEN {
return fmt.Sprintf("%d<=%s<=%d", val[0], subj, val[1])
return fmt.Sprintf("%s<=%s<=%s", val[0], subj, val[1])
} else if cond.Op == BTWN_LT_LTE {
return fmt.Sprintf("%d<%s<=%d", val[0], subj, val[1])
return fmt.Sprintf("%s<%s<=%s", val[0], subj, val[1])
} else if cond.Op == BTWN_LTE_LT {
return fmt.Sprintf("%d<=%s<%d", val[0], subj, val[1])
return fmt.Sprintf("%s<=%s<%s", val[0], subj, val[1])
} else if cond.Op == BTWN_LT_LT {
return fmt.Sprintf("%d<%s<%d", val[0], subj, val[1])
return fmt.Sprintf("%s<%s<%s", val[0], subj, val[1])
}
}
return ""
}
// IntSliceValue reads cond.Value as a slice of uint64.
// If the value is a slice of uint64 it will convert
// it to []int64. Otherwise, if it is not a []int64 it will return an error.
//
// TODO(2.0) this is now only referenced in a test and should probably
// be removed. The functionality was replaced by getCondIntSlice in
// pilosa/executor.go which needed to check for floating point values
// and also have access to the Pilosa field to see if floating point
// values were valid and how they needed to be scaled.
func (cond *Condition) IntSliceValue() ([]int64, error) {
val := cond.Value
switch tval := val.(type) {
case []interface{}:
ret := make([]int64, len(tval))
for i, v := range tval {
switch tv := v.(type) {
case int64:
ret[i] = tv
case uint64:
ret[i] = int64(tv)
default:
return nil, fmt.Errorf("unexpected value type %T in IntSliceValue, val %v", tv, tv)
}
}
return ret, nil
default:
return nil, fmt.Errorf("unexpected type %T in IntSliceValue, val %v", tval, tval)
}
}
func (cond *Condition) Uint64Value() (uint64, bool) {
val := cond.Value
@ -921,6 +890,35 @@ func (cond *Condition) Int64SliceValue() ([]int64, bool) {
return nil, false
}
// StringSliceValue returns the value(s) of the conditional
// as a slice of strings. For example, if cond.Value is
// []int64{-10,20}, this will return []string{"-10","20"}.
// It also returns a bool indicating that the conversion
// succeeded.
func (cond *Condition) StringSliceValue() ([]string, bool) {
val := cond.Value
switch tval := val.(type) {
case []interface{}:
ret := make([]string, len(tval))
for i, v := range tval {
switch tv := v.(type) {
case int64:
ret[i] = strconv.FormatInt(tv, 10)
case uint64:
ret[i] = strconv.FormatUint(tv, 10)
case Decimal:
ret[i] = tv.String()
default:
return nil, false
}
}
return ret, true
}
return nil, false
}
func formatValue(v interface{}) string {
switch v := v.(type) {
case string:

View file

@ -15,7 +15,6 @@
package pql_test
import (
"reflect"
"testing"
"github.com/pilosa/pilosa/v2/pql"
@ -43,27 +42,24 @@ func TestCall_String(t *testing.T) {
})
}
// Ensure condition can handle values for BETWEEN operator.
func TestCondition_Value(t *testing.T) {
t.Run("Between Values", func(t *testing.T) {
for _, tt := range []struct {
val []interface{}
exp []int64
}{
{[]interface{}{int64(4), int64(8)}, []int64{4, 8}},
{[]interface{}{uint64(4), uint64(8)}, []int64{4, 8}},
{[]interface{}{uint64(1), uint64(2), uint64(3)}, []int64{1, 2, 3}},
} {
c := &pql.Condition{
Op: pql.BETWEEN,
Value: tt.val,
}
v, err := c.IntSliceValue()
if err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(v, tt.exp) {
t.Fatalf("invalid between values. expected: %v, got %v", tt.exp, v)
}
// Ensure condition string with subject is correct.
func TestCondition_StringWithSubj(t *testing.T) {
op := pql.BETWEEN
subj := "subj"
for _, tt := range []struct {
val []interface{}
exp string
}{
{[]interface{}{int64(4), int64(8)}, "4<=subj<=8"},
{[]interface{}{uint64(5), uint64(9)}, "5<=subj<=9"},
{[]interface{}{pql.Decimal{Value: -401, Scale: 2}, pql.Decimal{Value: 802, Scale: 1}}, "-4.01<=subj<=80.2"},
} {
c := &pql.Condition{
Op: op,
Value: tt.val,
}
})
if sws := c.StringWithSubj(subj); sws != tt.exp {
t.Fatalf("invalid between string. expected: %s, got %s", tt.exp, sws)
}
}
}