mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
Add min/max constraints
This commit is contained in:
parent
7ed9fba335
commit
d4de122549
13 changed files with 185 additions and 152 deletions
|
|
@ -17,6 +17,7 @@ package pilosa_test
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
|
@ -198,7 +199,7 @@ func TestAPI_ImportValue(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("creating index: %v", err)
|
||||
}
|
||||
_, err = m0.API.CreateField(ctx, index, field, pilosa.OptFieldTypeInt(0))
|
||||
_, err = m0.API.CreateField(ctx, index, field, pilosa.OptFieldTypeInt(0, math.MinInt64, math.MaxInt64))
|
||||
if err != nil {
|
||||
t.Fatalf("creating field: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -798,6 +798,8 @@ func decodeFieldOptions(options *internal.FieldOptions, m *pilosa.FieldOptions)
|
|||
m.Type = options.Type
|
||||
m.CacheType = options.CacheType
|
||||
m.CacheSize = options.CacheSize
|
||||
m.Min = options.Min
|
||||
m.Max = options.Max
|
||||
m.Base = options.Base
|
||||
m.BitDepth = uint(options.BitDepth)
|
||||
m.TimeQuantum = pilosa.TimeQuantum(options.TimeQuantum)
|
||||
|
|
|
|||
|
|
@ -1408,7 +1408,6 @@ func (e *executor) executeRowBSIGroupShard(ctx context.Context, index string, c
|
|||
return frag.notNull()
|
||||
|
||||
} else if cond.Op == pql.BETWEEN {
|
||||
|
||||
predicates, err := cond.IntSliceValue()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getting condition value")
|
||||
|
|
@ -1442,7 +1441,7 @@ func (e *executor) executeRowBSIGroupShard(ctx context.Context, index string, c
|
|||
|
||||
// If the query is asking for the entire valid range, just return
|
||||
// the not-null bitmap for the bsiGroup.
|
||||
if predicates[0] <= bsig.Min() && predicates[1] >= bsig.Max() {
|
||||
if predicates[0] <= bsig.Min && predicates[1] >= bsig.Max {
|
||||
return frag.notNull()
|
||||
}
|
||||
|
||||
|
|
@ -1474,8 +1473,8 @@ func (e *executor) executeRowBSIGroupShard(ctx context.Context, index string, c
|
|||
}
|
||||
|
||||
// LT[E] and GT[E] should return all not-null if selected range fully encompasses valid bsiGroup range.
|
||||
if (cond.Op == pql.LT && value > bsig.Max()) || (cond.Op == pql.LTE && value >= bsig.Max()) ||
|
||||
(cond.Op == pql.GT && value < bsig.Min()) || (cond.Op == pql.GTE && value <= bsig.Min()) {
|
||||
if (cond.Op == pql.LT && value > bsig.Max) || (cond.Op == pql.LTE && value >= bsig.Max) ||
|
||||
(cond.Op == pql.GT && value < bsig.Min) || (cond.Op == pql.GTE && value <= bsig.Min) {
|
||||
return frag.notNull()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
|
@ -769,7 +770,7 @@ func TestExecutor_Execute_SetValue(t *testing.T) {
|
|||
|
||||
// Create fields.
|
||||
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
|
||||
if _, err := index.CreateFieldIfNotExists("f", pilosa.OptFieldTypeInt(0)); err != nil {
|
||||
if _, err := index.CreateFieldIfNotExists("f", pilosa.OptFieldTypeInt(0, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if _, err := index.CreateFieldIfNotExists("xxx", pilosa.OptFieldTypeDefault()); err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
@ -806,7 +807,7 @@ func TestExecutor_Execute_SetValue(t *testing.T) {
|
|||
hldr := test.Holder{Holder: c[0].Server.Holder()}
|
||||
|
||||
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
|
||||
if _, err := index.CreateFieldIfNotExists("f", pilosa.OptFieldTypeInt(0)); err != nil {
|
||||
if _, err := index.CreateFieldIfNotExists("f", pilosa.OptFieldTypeInt(0, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
@ -1214,7 +1215,7 @@ func TestExecutor_Execute_MinMax(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := idx.CreateField("f", pilosa.OptFieldTypeInt(-10)); err != nil {
|
||||
if _, err := idx.CreateField("f", pilosa.OptFieldTypeInt(-10, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
@ -1278,7 +1279,7 @@ func TestExecutor_Execute_MinMax(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := idx.CreateField("f", pilosa.OptFieldTypeInt(-10)); err != nil {
|
||||
if _, err := idx.CreateField("f", pilosa.OptFieldTypeInt(-10, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
@ -1371,15 +1372,15 @@ func TestExecutor_Execute_Sum(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := idx.CreateField("foo", pilosa.OptFieldTypeInt(10)); err != nil {
|
||||
if _, err := idx.CreateField("foo", pilosa.OptFieldTypeInt(10, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := idx.CreateField("bar", pilosa.OptFieldTypeInt(0)); err != nil {
|
||||
if _, err := idx.CreateField("bar", pilosa.OptFieldTypeInt(0, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := idx.CreateField("other", pilosa.OptFieldTypeInt(0)); err != nil {
|
||||
if _, err := idx.CreateField("other", pilosa.OptFieldTypeInt(0, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
@ -1429,15 +1430,15 @@ func TestExecutor_Execute_Sum(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := idx.CreateField("foo", pilosa.OptFieldTypeInt(10)); err != nil {
|
||||
if _, err := idx.CreateField("foo", pilosa.OptFieldTypeInt(10, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := idx.CreateField("bar", pilosa.OptFieldTypeInt(0)); err != nil {
|
||||
if _, err := idx.CreateField("bar", pilosa.OptFieldTypeInt(0, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := idx.CreateField("other", pilosa.OptFieldTypeInt(0)); err != nil {
|
||||
if _, err := idx.CreateField("other", pilosa.OptFieldTypeInt(0, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
@ -1831,19 +1832,19 @@ func TestExecutor_Execute_Row_BSIGroup(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := idx.CreateField("foo", pilosa.OptFieldTypeInt(10)); err != nil {
|
||||
if _, err := idx.CreateField("foo", pilosa.OptFieldTypeInt(10, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := idx.CreateField("bar", pilosa.OptFieldTypeInt(0)); err != nil {
|
||||
if _, err := idx.CreateField("bar", pilosa.OptFieldTypeInt(0, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := idx.CreateField("other", pilosa.OptFieldTypeInt(0)); err != nil {
|
||||
if _, err := idx.CreateField("other", pilosa.OptFieldTypeInt(0, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := idx.CreateField("edge", pilosa.OptFieldTypeInt(-100)); err != nil {
|
||||
if _, err := idx.CreateField("edge", pilosa.OptFieldTypeInt(-100, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
@ -1942,7 +1943,7 @@ func TestExecutor_Execute_Row_BSIGroup(t *testing.T) {
|
|||
{q: `Row(1000 < other <= 1000)`, exp: false},
|
||||
|
||||
{q: `Row(1000 < other < 2000)`, exp: false},
|
||||
{q: `Row(1000 <= other < 2000)`, exp: true},
|
||||
{q: `Row(1000 <= other < 20000)`, exp: true},
|
||||
{q: `Row(1000 <= other <= 2000)`, exp: true},
|
||||
{q: `Row(1000 < other <= 2000)`, exp: false},
|
||||
}
|
||||
|
|
@ -1955,7 +1956,7 @@ func TestExecutor_Execute_Row_BSIGroup(t *testing.T) {
|
|||
if result, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: test.q}); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !reflect.DeepEqual(expected, result.Results[0].(*pilosa.Row).Columns()) {
|
||||
t.Fatalf("unexpected result for query: %s", test.q)
|
||||
t.Fatalf("unexpected result for query: %s (%#v)", test.q, result.Results[0].(*pilosa.Row).Columns())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -2025,19 +2026,19 @@ func TestExecutor_Execute_Range_BSIGroup_Deprecated(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := idx.CreateField("foo", pilosa.OptFieldTypeInt(10)); err != nil {
|
||||
if _, err := idx.CreateField("foo", pilosa.OptFieldTypeInt(10, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := idx.CreateField("bar", pilosa.OptFieldTypeInt(0)); err != nil {
|
||||
if _, err := idx.CreateField("bar", pilosa.OptFieldTypeInt(0, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := idx.CreateField("other", pilosa.OptFieldTypeInt(0)); err != nil {
|
||||
if _, err := idx.CreateField("other", pilosa.OptFieldTypeInt(0, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := idx.CreateField("edge", pilosa.OptFieldTypeInt(-100)); err != nil {
|
||||
if _, err := idx.CreateField("edge", pilosa.OptFieldTypeInt(-100, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
@ -2795,7 +2796,7 @@ func TestExecutor_Execute_ClearRow(t *testing.T) {
|
|||
defer c.Close()
|
||||
hldr := test.Holder{Holder: c[0].Server.Holder()}
|
||||
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{TrackExistence: true})
|
||||
_, err := index.CreateField("f", pilosa.OptFieldTypeInt(0))
|
||||
_, err := index.CreateField("f", pilosa.OptFieldTypeInt(0, math.MinInt64, math.MaxInt64))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
|||
83
field.go
83
field.go
|
|
@ -130,13 +130,15 @@ func OptFieldTypeSet(cacheType string, cacheSize uint32) FieldOption {
|
|||
// OptFieldTypeInt is a functional option on FieldOptions
|
||||
// used to specify the field as being type `int` and to
|
||||
// provide any respective configuration values.
|
||||
func OptFieldTypeInt(base int64) FieldOption {
|
||||
func OptFieldTypeInt(base, min, max int64) FieldOption {
|
||||
return func(fo *FieldOptions) error {
|
||||
if fo.Type != "" {
|
||||
return errors.Errorf("field type is already set to: %s", fo.Type)
|
||||
}
|
||||
fo.Type = FieldTypeInt
|
||||
fo.Base = base
|
||||
fo.Min = min
|
||||
fo.Max = max
|
||||
fo.BitDepth = 1
|
||||
return nil
|
||||
}
|
||||
|
|
@ -485,16 +487,21 @@ func (f *Field) loadMeta() error {
|
|||
}
|
||||
}
|
||||
|
||||
// Convert min/max from deprecated v1 int type.
|
||||
if pb.Min != 0 || pb.Max != 0 {
|
||||
// Initialize "base" to "min" when upgrading from v1 BSI format.
|
||||
if pb.BitDepth == 0 {
|
||||
pb.Base = pb.Min
|
||||
pb.BitDepth = uint64(bitDepth(uint64(pb.Max - pb.Min)))
|
||||
pb.BitDepth = uint64(bitDepthInt64(pb.Max - pb.Min))
|
||||
if pb.BitDepth == 0 {
|
||||
pb.BitDepth = 1
|
||||
}
|
||||
}
|
||||
|
||||
// Copy metadata fields.
|
||||
f.options.Type = pb.Type
|
||||
f.options.CacheType = pb.CacheType
|
||||
f.options.CacheSize = pb.CacheSize
|
||||
f.options.Min = pb.Min
|
||||
f.options.Max = pb.Max
|
||||
f.options.Base = pb.Base
|
||||
f.options.BitDepth = uint(pb.BitDepth)
|
||||
f.options.TimeQuantum = TimeQuantum(pb.TimeQuantum)
|
||||
|
|
@ -540,6 +547,8 @@ func (f *Field) applyOptions(opt FieldOptions) error {
|
|||
f.options.CacheSize = opt.CacheSize
|
||||
}
|
||||
}
|
||||
f.options.Min = 0
|
||||
f.options.Max = 0
|
||||
f.options.Base = 0
|
||||
f.options.BitDepth = 0
|
||||
f.options.TimeQuantum = ""
|
||||
|
|
@ -548,6 +557,8 @@ func (f *Field) applyOptions(opt FieldOptions) error {
|
|||
f.options.Type = opt.Type
|
||||
f.options.CacheType = CacheTypeNone
|
||||
f.options.CacheSize = 0
|
||||
f.options.Min = opt.Min
|
||||
f.options.Max = opt.Max
|
||||
f.options.Base = opt.Base
|
||||
f.options.BitDepth = opt.BitDepth
|
||||
f.options.TimeQuantum = ""
|
||||
|
|
@ -557,6 +568,8 @@ func (f *Field) applyOptions(opt FieldOptions) error {
|
|||
bsig := &bsiGroup{
|
||||
Name: f.name,
|
||||
Type: bsiGroupTypeInt,
|
||||
Min: opt.Min,
|
||||
Max: opt.Max,
|
||||
Base: opt.Base,
|
||||
BitDepth: opt.BitDepth,
|
||||
}
|
||||
|
|
@ -571,6 +584,8 @@ func (f *Field) applyOptions(opt FieldOptions) error {
|
|||
f.options.Type = opt.Type
|
||||
f.options.CacheType = CacheTypeNone
|
||||
f.options.CacheSize = 0
|
||||
f.options.Min = 0
|
||||
f.options.Max = 0
|
||||
f.options.Base = 0
|
||||
f.options.BitDepth = 0
|
||||
f.options.Keys = opt.Keys
|
||||
|
|
@ -584,6 +599,8 @@ func (f *Field) applyOptions(opt FieldOptions) error {
|
|||
f.options.Type = FieldTypeBool
|
||||
f.options.CacheType = CacheTypeNone
|
||||
f.options.CacheSize = 0
|
||||
f.options.Min = 0
|
||||
f.options.Max = 0
|
||||
f.options.Base = 0
|
||||
f.options.BitDepth = 0
|
||||
f.options.TimeQuantum = ""
|
||||
|
|
@ -995,7 +1012,7 @@ func (f *Field) Value(columnID uint64) (value int64, exists bool, err error) {
|
|||
|
||||
// SetValue sets a field value for a column.
|
||||
func (f *Field) SetValue(columnID uint64, value int64) (changed bool, err error) {
|
||||
// Fetch bsiGroup.
|
||||
// Fetch bsiGroup & validate min/max.
|
||||
bsig := f.bsiGroup(f.name)
|
||||
if bsig == nil {
|
||||
return false, ErrBSIGroupNotFound
|
||||
|
|
@ -1003,9 +1020,10 @@ func (f *Field) SetValue(columnID uint64, value int64) (changed bool, err error)
|
|||
|
||||
// Determine base value to store.
|
||||
baseValue := int64(value - bsig.Base)
|
||||
requiredBitDepth := bitDepthInt64(baseValue)
|
||||
|
||||
// Increase bit depth value if the unsigned value is greater.
|
||||
if value < bsig.Min() || value > bsig.Max() {
|
||||
if requiredBitDepth > bsig.BitDepth {
|
||||
if err := func() error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
|
|
@ -1099,7 +1117,7 @@ func (f *Field) Range(name string, op pql.Token, predicate int64) (*Row, error)
|
|||
bsig := f.bsiGroup(name)
|
||||
if bsig == nil {
|
||||
return nil, ErrBSIGroupNotFound
|
||||
} else if predicate < bsig.Min() || predicate > bsig.Max() {
|
||||
} else if predicate < bsig.Min || predicate > bsig.Max {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
|
@ -1365,6 +1383,8 @@ func encodeFieldOptions(o *FieldOptions) *internal.FieldOptions {
|
|||
Type: o.Type,
|
||||
CacheType: o.CacheType,
|
||||
CacheSize: o.CacheSize,
|
||||
Min: o.Min,
|
||||
Max: o.Max,
|
||||
Base: o.Base,
|
||||
BitDepth: uint64(o.BitDepth),
|
||||
TimeQuantum: string(o.TimeQuantum),
|
||||
|
|
@ -1454,20 +1474,12 @@ func isValidBSIGroupType(v string) bool {
|
|||
type bsiGroup struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Min int64 `json:"min,omitempty"`
|
||||
Max int64 `json:"max,omitempty"`
|
||||
Base int64 `json:"base,omitempty"`
|
||||
BitDepth uint `json:"bitDepth,omitempty"`
|
||||
}
|
||||
|
||||
// Min returns the lowest possible value for the group based on current bit depth.
|
||||
func (b *bsiGroup) Min() int64 {
|
||||
return b.Base - (1 << b.BitDepth) + 1
|
||||
}
|
||||
|
||||
// Max returns the highest possible value for the group based on current bit depth.
|
||||
func (b *bsiGroup) Max() int64 {
|
||||
return b.Base + (1 << b.BitDepth) - 1
|
||||
}
|
||||
|
||||
// baseValue adjusts the value to align with the range for Field for a certain
|
||||
// operation type.
|
||||
// Note: There is an edge case for GT and LT where this returns a baseValue
|
||||
|
|
@ -1481,7 +1493,7 @@ func (b *bsiGroup) Max() int64 {
|
|||
// Executor.executeBSIGroupRangeShard() takes this into account and returns
|
||||
// `frag.FieldNotNull(bsig.BitDepth())` in such instances.
|
||||
func (b *bsiGroup) baseValue(op pql.Token, value int64) (baseValue int64, outOfRange bool) {
|
||||
min, max := b.Min(), b.Max()
|
||||
min, max := b.bitDepthMin(), b.bitDepthMax()
|
||||
|
||||
if op == pql.GT || op == pql.GTE {
|
||||
if value > max {
|
||||
|
|
@ -1507,23 +1519,20 @@ func (b *bsiGroup) baseValue(op pql.Token, value int64) (baseValue int64, outOfR
|
|||
}
|
||||
|
||||
// baseValueBetween adjusts the min/max value to align with the range for Field.
|
||||
func (b *bsiGroup) baseValueBetween(min, max int64) (baseValueMin, baseValueMax int64, outOfRange bool) {
|
||||
bsiMin, bsiMax := b.Min(), b.Max()
|
||||
func (b *bsiGroup) baseValueBetween(lo, hi int64) (baseValueLo, baseValueHi int64, outOfRange bool) {
|
||||
min, max := b.bitDepthMin(), b.bitDepthMax()
|
||||
if hi < min || lo > max {
|
||||
return 0, 0, true
|
||||
}
|
||||
|
||||
if max < bsiMin || min > bsiMax {
|
||||
return baseValueMin, baseValueMax, true
|
||||
// Limit lo/hi to possible bit range.
|
||||
if lo < min {
|
||||
lo = min
|
||||
}
|
||||
// Adjust min/max to range.
|
||||
if min > bsiMin {
|
||||
baseValueMin = int64(min - b.Base)
|
||||
if hi > max {
|
||||
hi = max
|
||||
}
|
||||
// Make sure the high value of the BETWEEN does not exceed BitDepth.
|
||||
if max > bsiMax {
|
||||
baseValueMax = int64(bsiMax - b.Base)
|
||||
} else if max > bsiMin {
|
||||
baseValueMax = int64(max - b.Base)
|
||||
}
|
||||
return baseValueMin, baseValueMax, false
|
||||
return lo - b.Base, hi - b.Base, false
|
||||
}
|
||||
|
||||
func (b *bsiGroup) validate() error {
|
||||
|
|
@ -1535,6 +1544,16 @@ func (b *bsiGroup) validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// bitDepthMin returns the minimum value possible for the current bit depth.
|
||||
func (b *bsiGroup) bitDepthMin() int64 {
|
||||
return b.Base - (1 << b.BitDepth) + 1
|
||||
}
|
||||
|
||||
// bitDepthMax returns the maximum value possible for the current bit depth.
|
||||
func (b *bsiGroup) bitDepthMax() int64 {
|
||||
return b.Base + (1 << b.BitDepth) - 1
|
||||
}
|
||||
|
||||
// Cache types.
|
||||
const (
|
||||
CacheTypeLRU = "lru"
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@
|
|||
package pilosa
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
|
@ -32,19 +34,24 @@ func TestBSIGroup_BaseValue(t *testing.T) {
|
|||
Type: bsiGroupTypeInt,
|
||||
Base: -100,
|
||||
BitDepth: 10,
|
||||
Min: -1000,
|
||||
Max: 1000,
|
||||
}
|
||||
b1 := &bsiGroup{
|
||||
Name: "b1",
|
||||
Type: bsiGroupTypeInt,
|
||||
Base: 0,
|
||||
BitDepth: 8,
|
||||
Min: -255,
|
||||
Max: 255,
|
||||
}
|
||||
|
||||
b2 := &bsiGroup{
|
||||
Name: "b2",
|
||||
Type: bsiGroupTypeInt,
|
||||
Base: 100,
|
||||
BitDepth: 11,
|
||||
Min: math.MinInt64,
|
||||
Max: math.MaxInt64,
|
||||
}
|
||||
|
||||
t.Run("Normal Condition", func(t *testing.T) {
|
||||
|
|
@ -104,10 +111,12 @@ func TestBSIGroup_BaseValue(t *testing.T) {
|
|||
{b2, pql.EQ, 105, 5, false},
|
||||
{b2, pql.EQ, 1105, 1005, false},
|
||||
} {
|
||||
bv, oor := tt.f.baseValue(tt.op, tt.val)
|
||||
if oor != tt.expOutOfRange || !reflect.DeepEqual(bv, tt.expBaseValue) {
|
||||
t.Errorf("%d. %s) baseValue(%s, %v)=(%v, %v), expected (%v, %v)", i, tt.f.Name, tt.op, tt.val, bv, oor, tt.expBaseValue, tt.expOutOfRange)
|
||||
}
|
||||
t.Run(fmt.Sprint(i), func(t *testing.T) {
|
||||
bv, oor := tt.f.baseValue(tt.op, tt.val)
|
||||
if oor != tt.expOutOfRange || !reflect.DeepEqual(bv, tt.expBaseValue) {
|
||||
t.Errorf("%s) baseValue(%s, %v)=(%v, %v), expected (%v, %v)", tt.f.Name, tt.op, tt.val, bv, oor, tt.expBaseValue, tt.expOutOfRange)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ package pilosa_test
|
|||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
|
@ -30,7 +31,7 @@ func TestField_SetValue(t *testing.T) {
|
|||
idx := test.MustOpenIndex()
|
||||
defer idx.Close()
|
||||
|
||||
f, err := idx.CreateField("f", pilosa.OptFieldTypeInt(0))
|
||||
f, err := idx.CreateField("f", pilosa.OptFieldTypeInt(0, math.MinInt64, math.MaxInt64))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -63,7 +64,7 @@ func TestField_SetValue(t *testing.T) {
|
|||
idx := test.MustOpenIndex()
|
||||
defer idx.Close()
|
||||
|
||||
f, err := idx.CreateField("f", pilosa.OptFieldTypeInt(0))
|
||||
f, err := idx.CreateField("f", pilosa.OptFieldTypeInt(0, math.MinInt64, math.MaxInt64))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1273,7 +1273,7 @@ func (f *fragment) rangeBetweenUnsigned(filter *Row, bitDepth uint, predicateMin
|
|||
}
|
||||
}
|
||||
|
||||
// LTE predicateMin
|
||||
// LTE predicateMax
|
||||
// If bit is zero then remove all set bits not in excluded bitmap.
|
||||
if bit2 == 0 {
|
||||
filter = filter.Difference(row.Difference(keep2))
|
||||
|
|
@ -2492,9 +2492,9 @@ func upgradeRoaringBSIv2(f *fragment, bitDepth uint) (string, error) {
|
|||
f.storage.ForEach(func(i uint64) {
|
||||
rowID, columnID := i/ShardWidth, (f.shard*ShardWidth)+(i%ShardWidth)
|
||||
if rowID == uint64(bitDepth) {
|
||||
other.Add(pos(bsiExistsBit, columnID)) // move exists bit to beginning
|
||||
_, _ = other.Add(pos(bsiExistsBit, columnID)) // move exists bit to beginning
|
||||
} else {
|
||||
other.Add(pos(rowID+bsiOffsetBit, columnID)) // move other bits up
|
||||
_, _ = other.Add(pos(rowID+bsiOffsetBit, columnID)) // move other bits up
|
||||
}
|
||||
})
|
||||
}()
|
||||
|
|
|
|||
|
|
@ -705,7 +705,7 @@ func TestClient_ImportKeys(t *testing.T) {
|
|||
|
||||
// Load bitmap into cache to ensure cache gets updated.
|
||||
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{Keys: true})
|
||||
field, err := index.CreateFieldIfNotExists(fldName, pilosa.OptFieldTypeInt(-100, 100))
|
||||
field, err := index.CreateFieldIfNotExists(fldName, pilosa.OptFieldTypeInt(0, -100, 100))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -790,7 +790,7 @@ func TestClient_ImportValue(t *testing.T) {
|
|||
|
||||
// Load bitmap into cache to ensure cache gets updated.
|
||||
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
|
||||
field, err := index.CreateFieldIfNotExists(fldName, pilosa.OptFieldTypeInt(-100, 100))
|
||||
field, err := index.CreateFieldIfNotExists(fldName, pilosa.OptFieldTypeInt(0, -100, 100))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -933,7 +933,7 @@ func TestClient_ImportExistence(t *testing.T) {
|
|||
fldName := "fint"
|
||||
|
||||
index := hldr.MustCreateIndexIfNotExists(idxName, pilosa.IndexOptions{TrackExistence: true})
|
||||
field, err := index.CreateFieldIfNotExists(fldName, pilosa.OptFieldTypeInt(-100, 100))
|
||||
field, err := index.CreateFieldIfNotExists(fldName, pilosa.OptFieldTypeInt(0, -100, 100))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"net"
|
||||
"net/http"
|
||||
_ "net/http/pprof" // Imported for its side-effect of registering pprof endpoints with the server.
|
||||
|
|
@ -764,7 +765,7 @@ func (h *Handler) handlePostField(w http.ResponseWriter, r *http.Request) {
|
|||
} else if v := req.Options.Min; v != nil {
|
||||
base = *v
|
||||
}
|
||||
fos = append(fos, pilosa.OptFieldTypeInt(base))
|
||||
fos = append(fos, pilosa.OptFieldTypeInt(base, math.MinInt64, math.MaxInt64))
|
||||
case pilosa.FieldTypeTime:
|
||||
fos = append(fos, pilosa.OptFieldTypeTime(*req.Options.TimeQuantum, req.Options.NoStandardView))
|
||||
case pilosa.FieldTypeMutex:
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ package pilosa_test
|
|||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
|
|
@ -93,7 +94,7 @@ func TestIndex_CreateField(t *testing.T) {
|
|||
defer index.Close()
|
||||
|
||||
// Create field with schema and verify it exists.
|
||||
if f, err := index.CreateField("f", pilosa.OptFieldTypeInt(10)); err != nil {
|
||||
if f, err := index.CreateField("f", pilosa.OptFieldTypeInt(10, math.MinInt64, math.MaxInt64)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !reflect.DeepEqual(f.Type(), pilosa.FieldTypeInt) {
|
||||
t.Fatalf("unexpected type: %#v", f.Type())
|
||||
|
|
|
|||
|
|
@ -8,17 +8,16 @@ message IndexMeta {
|
|||
}
|
||||
|
||||
message FieldOptions {
|
||||
string Type = 8;
|
||||
string Type = 8;
|
||||
string CacheType = 3;
|
||||
uint32 CacheSize = 4;
|
||||
string TimeQuantum = 5;
|
||||
bool Keys = 11;
|
||||
bool NoStandardView = 12;
|
||||
int64 Base = 13;
|
||||
uint64 BitDepth = 14;
|
||||
|
||||
int64 Min = 9 [deprecated=true];
|
||||
int64 Max = 10 [deprecated=true];
|
||||
int64 Min = 9;
|
||||
int64 Max = 10;
|
||||
bool Keys = 11;
|
||||
bool NoStandardView = 12;
|
||||
int64 Base = 13;
|
||||
uint64 BitDepth = 14;
|
||||
}
|
||||
|
||||
message ImportResponse {
|
||||
|
|
@ -43,154 +42,154 @@ message Cache {
|
|||
}
|
||||
|
||||
message MaxShards {
|
||||
map<string, uint64> Standard = 1;
|
||||
map<string, uint64> Standard = 1;
|
||||
}
|
||||
|
||||
message CreateShardMessage {
|
||||
string Index = 1;
|
||||
string Field = 3;
|
||||
uint64 Shard = 2;
|
||||
string Index = 1;
|
||||
string Field = 3;
|
||||
uint64 Shard = 2;
|
||||
}
|
||||
|
||||
message DeleteIndexMessage {
|
||||
string Index = 1;
|
||||
string Index = 1;
|
||||
}
|
||||
|
||||
message CreateIndexMessage {
|
||||
string Index = 1;
|
||||
IndexMeta Meta = 2;
|
||||
string Index = 1;
|
||||
IndexMeta Meta = 2;
|
||||
}
|
||||
|
||||
message CreateFieldMessage {
|
||||
string Index = 1;
|
||||
string Field = 2;
|
||||
FieldOptions Meta = 3;
|
||||
string Index = 1;
|
||||
string Field = 2;
|
||||
FieldOptions Meta = 3;
|
||||
}
|
||||
|
||||
message DeleteFieldMessage {
|
||||
string Index = 1;
|
||||
string Field = 2;
|
||||
string Index = 1;
|
||||
string Field = 2;
|
||||
}
|
||||
|
||||
message DeleteAvailableShardMessage {
|
||||
string Index = 1;
|
||||
string Field = 2;
|
||||
uint64 ShardID = 3;
|
||||
string Index = 1;
|
||||
string Field = 2;
|
||||
uint64 ShardID = 3;
|
||||
}
|
||||
|
||||
message Field {
|
||||
string Name = 1;
|
||||
FieldOptions Meta = 2;
|
||||
repeated string Views = 3;
|
||||
string Name = 1;
|
||||
FieldOptions Meta = 2;
|
||||
repeated string Views = 3;
|
||||
}
|
||||
|
||||
message Schema {
|
||||
repeated Index Indexes = 1;
|
||||
repeated Index Indexes = 1;
|
||||
}
|
||||
|
||||
message Index {
|
||||
string Name = 1;
|
||||
repeated Field Fields = 4;
|
||||
string Name = 1;
|
||||
repeated Field Fields = 4;
|
||||
}
|
||||
|
||||
message URI {
|
||||
string Scheme = 1;
|
||||
string Host = 2;
|
||||
uint32 Port = 3;
|
||||
string Scheme = 1;
|
||||
string Host = 2;
|
||||
uint32 Port = 3;
|
||||
}
|
||||
|
||||
message Node {
|
||||
string ID = 1;
|
||||
URI URI = 2;
|
||||
bool IsCoordinator = 3;
|
||||
string State = 4;
|
||||
string ID = 1;
|
||||
URI URI = 2;
|
||||
bool IsCoordinator = 3;
|
||||
string State = 4;
|
||||
}
|
||||
|
||||
message NodeStateMessage {
|
||||
string NodeID = 1;
|
||||
string State = 2;
|
||||
string NodeID = 1;
|
||||
string State = 2;
|
||||
}
|
||||
|
||||
message NodeEventMessage {
|
||||
uint32 Event = 1;
|
||||
Node Node = 2;
|
||||
uint32 Event = 1;
|
||||
Node Node = 2;
|
||||
}
|
||||
|
||||
message NodeStatus {
|
||||
Node Node = 1;
|
||||
Schema Schema = 3;
|
||||
repeated IndexStatus Indexes = 4;
|
||||
Node Node = 1;
|
||||
Schema Schema = 3;
|
||||
repeated IndexStatus Indexes = 4;
|
||||
}
|
||||
|
||||
message IndexStatus {
|
||||
string Name = 1;
|
||||
repeated FieldStatus Fields = 2;
|
||||
string Name = 1;
|
||||
repeated FieldStatus Fields = 2;
|
||||
}
|
||||
|
||||
message FieldStatus {
|
||||
string Name = 1;
|
||||
repeated uint64 AvailableShards = 2;
|
||||
string Name = 1;
|
||||
repeated uint64 AvailableShards = 2;
|
||||
}
|
||||
|
||||
message ClusterStatus {
|
||||
string ClusterID = 1;
|
||||
string State = 2;
|
||||
repeated Node Nodes = 3;
|
||||
string ClusterID = 1;
|
||||
string State = 2;
|
||||
repeated Node Nodes = 3;
|
||||
}
|
||||
|
||||
message BSIGroup {
|
||||
string Name = 1;
|
||||
string Type = 2;
|
||||
int64 Min = 3;
|
||||
int64 Max = 4;
|
||||
string Name = 1;
|
||||
string Type = 2;
|
||||
int64 Min = 3;
|
||||
int64 Max = 4;
|
||||
}
|
||||
|
||||
message CreateViewMessage {
|
||||
string Index = 1;
|
||||
string Field = 2;
|
||||
string View = 3;
|
||||
string Index = 1;
|
||||
string Field = 2;
|
||||
string View = 3;
|
||||
}
|
||||
|
||||
message DeleteViewMessage {
|
||||
string Index = 1;
|
||||
string Field = 2;
|
||||
string View = 3;
|
||||
string Index = 1;
|
||||
string Field = 2;
|
||||
string View = 3;
|
||||
}
|
||||
|
||||
message ResizeInstruction {
|
||||
int64 JobID = 1;
|
||||
Node Node = 2;
|
||||
Node Coordinator = 3;
|
||||
repeated ResizeSource Sources = 4;
|
||||
NodeStatus NodeStatus = 7;
|
||||
ClusterStatus ClusterStatus = 6;
|
||||
int64 JobID = 1;
|
||||
Node Node = 2;
|
||||
Node Coordinator = 3;
|
||||
repeated ResizeSource Sources = 4;
|
||||
NodeStatus NodeStatus = 7;
|
||||
ClusterStatus ClusterStatus = 6;
|
||||
}
|
||||
|
||||
message ResizeSource {
|
||||
Node Node = 1;
|
||||
string Index = 2;
|
||||
string Field = 3;
|
||||
string View = 4;
|
||||
uint64 Shard = 5;
|
||||
Node Node = 1;
|
||||
string Index = 2;
|
||||
string Field = 3;
|
||||
string View = 4;
|
||||
uint64 Shard = 5;
|
||||
}
|
||||
|
||||
message ResizeInstructionComplete {
|
||||
int64 JobID = 1;
|
||||
Node Node = 2;
|
||||
string Error = 3;
|
||||
int64 JobID = 1;
|
||||
Node Node = 2;
|
||||
string Error = 3;
|
||||
}
|
||||
|
||||
message SetCoordinatorMessage {
|
||||
Node New = 1;
|
||||
Node New = 1;
|
||||
}
|
||||
|
||||
message UpdateCoordinatorMessage {
|
||||
Node New = 1;
|
||||
Node New = 1;
|
||||
}
|
||||
|
||||
message Topology {
|
||||
string ClusterID = 1;
|
||||
repeated string NodeIDs = 2;
|
||||
string ClusterID = 1;
|
||||
repeated string NodeIDs = 2;
|
||||
}
|
||||
|
||||
message RecalculateCaches {}
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ func TestHandler_Endpoints(t *testing.T) {
|
|||
|
||||
t.Run("ImportRoaringFieldTypeFail", func(t *testing.T) {
|
||||
// Roaring import into a non-set field should fail.
|
||||
if _, err := i0.CreateFieldIfNotExists("int-field", pilosa.OptFieldTypeInt(0, 1)); err != nil {
|
||||
if _, err := i0.CreateFieldIfNotExists("int-field", pilosa.OptFieldTypeInt(0, 0, 1)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
w := httptest.NewRecorder()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue