mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-09-07 17:15:56 +00:00
fix min/max bug for decimal fields
This commit is contained in:
parent
963affcc30
commit
513edeae9c
3 changed files with 85 additions and 3 deletions
|
|
@ -34,6 +34,7 @@ import (
|
|||
"github.com/pilosa/pilosa/v2"
|
||||
"github.com/pilosa/pilosa/v2/boltdb"
|
||||
"github.com/pilosa/pilosa/v2/http"
|
||||
"github.com/pilosa/pilosa/v2/pql"
|
||||
"github.com/pilosa/pilosa/v2/server"
|
||||
"github.com/pilosa/pilosa/v2/test"
|
||||
"github.com/pkg/errors"
|
||||
|
|
@ -1463,6 +1464,63 @@ func TestExecutor_Execute_MinMax(t *testing.T) {
|
|||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Decimal", func(t *testing.T) {
|
||||
c := test.MustRunCluster(t, 1)
|
||||
defer c.Close()
|
||||
hldr := test.Holder{Holder: c[0].Server.Holder()}
|
||||
|
||||
idx, err := hldr.CreateIndex("i", pilosa.IndexOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
scale int64
|
||||
min int64
|
||||
max int64
|
||||
set pql.Decimal
|
||||
}{
|
||||
{2, 10, 20, pql.Decimal{false, 115, 1}},
|
||||
{2, -10, 20, pql.Decimal{false, 115, 1}},
|
||||
{2, -10, 20, pql.Decimal{true, 95, 1}},
|
||||
{2, -20, -10, pql.Decimal{true, 115, 1}},
|
||||
}
|
||||
for i, test := range tests {
|
||||
fld := fmt.Sprintf("f%d", i)
|
||||
t.Run("MinMaxField_"+fld, func(t *testing.T) {
|
||||
if _, err := idx.CreateField(fld, pilosa.OptFieldTypeDecimal(test.scale, test.min, test.max)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: fmt.Sprintf(`
|
||||
Set(10, %s=%s)
|
||||
`, fld, test.set)}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var pql string
|
||||
|
||||
t.Run("Min", func(t *testing.T) {
|
||||
pql = fmt.Sprintf(`Min(field=%s)`, fld)
|
||||
if result, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: pql}); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !reflect.DeepEqual(result.Results[0], pilosa.ValCount{FloatVal: test.set.Float64(), Count: 1}) {
|
||||
t.Fatalf("unexpected min result, test %d: %s", i, spew.Sdump(result))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Max", func(t *testing.T) {
|
||||
pql = fmt.Sprintf(`Max(field=%s)`, fld)
|
||||
if result, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: pql}); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !reflect.DeepEqual(result.Results[0], pilosa.ValCount{FloatVal: test.set.Float64(), Count: 1}) {
|
||||
t.Fatalf("unexpected max result, test %d: %s", i, spew.Sdump(result))
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("ColumnID", func(t *testing.T) {
|
||||
|
|
|
|||
16
field.go
16
field.go
|
|
@ -194,6 +194,10 @@ func OptFieldTypeDecimal(scale int64, minmax ...int64) FieldOption {
|
|||
fo.Max = math.MaxInt64
|
||||
if len(minmax) == 2 {
|
||||
min, max := minmax[0], minmax[1]
|
||||
if scale != 0 {
|
||||
min = int64(float64(min) * math.Pow10(int(scale)))
|
||||
max = int64(float64(max) * math.Pow10(int(scale)))
|
||||
}
|
||||
if min > max {
|
||||
return errors.Errorf("decimal field min cannot be greater than max, got %d, %d", min, max)
|
||||
}
|
||||
|
|
@ -202,7 +206,13 @@ func OptFieldTypeDecimal(scale int64, minmax ...int64) FieldOption {
|
|||
} else if len(minmax) > 2 {
|
||||
return errors.Errorf("unknown extra parameters beyond min and max: %v", minmax)
|
||||
} else if len(minmax) == 1 {
|
||||
fo.Min = minmax[0]
|
||||
// It's not necessary to handle the scale==0 case separately,
|
||||
// but it avoids the type conversion.
|
||||
if scale == 0 {
|
||||
fo.Min = minmax[0]
|
||||
} else {
|
||||
fo.Min = int64(float64(minmax[0]) * math.Pow10(int(scale)))
|
||||
}
|
||||
}
|
||||
fo.Type = FieldTypeDecimal
|
||||
fo.Base = bsiBase(fo.Min, fo.Max)
|
||||
|
|
@ -1447,7 +1457,7 @@ func (f *Field) MaxForShard(shard uint64, filter *Row) (ValCount, error) {
|
|||
valCount := ValCount{Count: int64(cnt)}
|
||||
|
||||
if f.Options().Type == FieldTypeDecimal {
|
||||
valCount.FloatVal = float64(max) / math.Pow10(int(bsig.Scale))
|
||||
valCount.FloatVal = float64(max+bsig.Base) / math.Pow10(int(bsig.Scale))
|
||||
} else {
|
||||
valCount.Val = max + bsig.Base
|
||||
}
|
||||
|
|
@ -1482,7 +1492,7 @@ func (f *Field) MinForShard(shard uint64, filter *Row) (ValCount, error) {
|
|||
valCount := ValCount{Count: int64(cnt)}
|
||||
|
||||
if f.Options().Type == FieldTypeDecimal {
|
||||
valCount.FloatVal = float64(min) / math.Pow10(int(bsig.Scale))
|
||||
valCount.FloatVal = float64(min+bsig.Base) / math.Pow10(int(bsig.Scale))
|
||||
} else {
|
||||
valCount.Val = min + bsig.Base
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,20 @@ func (d Decimal) ToInt64(scale int64) int64 {
|
|||
return ret
|
||||
}
|
||||
|
||||
// Float64 returns d as a float64.
|
||||
func (d Decimal) Float64() float64 {
|
||||
var ret float64
|
||||
if d.Scale == 0 {
|
||||
ret = float64(d.Value)
|
||||
} else {
|
||||
ret = float64(d.Value) / math.Pow10(int(d.Scale))
|
||||
}
|
||||
if d.Sign {
|
||||
ret *= -1
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// String returns the string representation of the decimal.
|
||||
func (d Decimal) String() string {
|
||||
var s string
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue