Merge branch 'develop' into core-structs

This commit is contained in:
Matt Jaffee 2018-07-05 16:38:14 -05:00
commit 0a94d2f10d
No known key found for this signature in database
GPG key ID: 08A3DFFF987B11BF
28 changed files with 216 additions and 309 deletions

71
api.go
View file

@ -242,16 +242,18 @@ func (api *API) DeleteIndex(ctx context.Context, indexName string) error {
// CreateField makes the named field in the named index with the given options.
// This method currently only takes a single functional option, but that may be
// changed in the future to support multiple options.
func (api *API) CreateField(ctx context.Context, indexName string, fieldName string, opts FieldOption) (*Field, error) {
func (api *API) CreateField(ctx context.Context, indexName string, fieldName string, opts ...FieldOption) (*Field, error) {
if err := api.validate(apiCreateField); err != nil {
return nil, errors.Wrap(err, "validating api method")
}
// Apply functional option.
// Apply functional options.
fo := FieldOptions{}
err := opts(&fo)
if err != nil {
return nil, errors.Wrap(err, "applying option")
for _, opt := range opts {
err := opt(&fo)
if err != nil {
return nil, errors.Wrap(err, "applying option")
}
}
// Find index.
@ -261,7 +263,7 @@ func (api *API) CreateField(ctx context.Context, indexName string, fieldName str
}
// Create field.
field, err := index.CreateField(fieldName, fo)
field, err := index.CreateField(fieldName, opts...)
if err != nil {
return nil, errors.Wrap(err, "creating field")
}
@ -374,55 +376,6 @@ func (api *API) ShardNodes(ctx context.Context, indexName string, shard uint64)
return api.cluster.shardNodes(indexName, shard), nil
}
// MarshalFragment returns an object which can write the specified fragment's data
// to an io.Writer. The serialized data can be read back into a fragment with
// the UnmarshalFragment API call.
func (api *API) MarshalFragment(ctx context.Context, indexName string, fieldName string, shard uint64) (io.WriterTo, error) {
if err := api.validate(apiMarshalFragment); err != nil {
return nil, errors.Wrap(err, "validating api method")
}
// Retrieve fragment from holder.
f := api.holder.fragment(indexName, fieldName, viewStandard, shard)
if f == nil {
return nil, ErrFragmentNotFound
}
return f, nil
}
// UnmarshalFragment creates a new fragment (if necessary) and reads data from a
// Reader which was previously written by MarshalFragment to populate the
// fragment's data.
func (api *API) UnmarshalFragment(ctx context.Context, indexName string, fieldName string, shard uint64, reader io.ReadCloser) error {
if err := api.validate(apiUnmarshalFragment); err != nil {
return errors.Wrap(err, "validating api method")
}
// Retrieve field.
f := api.holder.Field(indexName, fieldName)
if f == nil {
return ErrFieldNotFound
}
// Retrieve view.
view, err := f.createViewIfNotExists(viewStandard)
if err != nil {
return errors.Wrap(err, "creating view")
}
// Retrieve fragment from field.
frag, err := view.CreateFragmentIfNotExists(shard)
if err != nil {
return errors.Wrap(err, "creating fragment")
}
// Read fragment in from request body.
if _, err := frag.ReadFrom(reader); err != nil {
return errors.Wrap(err, "reading fragment")
}
return nil
}
// FragmentBlockData is an endpoint for internal usage. It is not guaranteed to
// return anything useful. Currently it returns protobuf encoded row and column
// ids from a "block" which is a subdivision of a fragment.
@ -894,7 +847,6 @@ const (
apiIndexAttrDiff
//apiLocalID // not implemented
//apiLongQueryTime // not implemented
apiMarshalFragment
//apiMaxShards // not implemented
apiQuery
apiRecalculateCaches
@ -905,15 +857,13 @@ const (
apiShardNodes
//apiState // not implemented
//apiStatsWithTags // not implemented
apiUnmarshalFragment
//apiVersion // not implemented
apiViews
)
var methodsCommon = map[apiMethod]struct{}{
apiClusterMessage: struct{}{},
apiMarshalFragment: struct{}{},
apiSetCoordinator: struct{}{},
apiClusterMessage: struct{}{},
apiSetCoordinator: struct{}{},
}
var methodsResizing = map[apiMethod]struct{}{
@ -939,6 +889,5 @@ var methodsNormal = map[apiMethod]struct{}{
apiRecalculateCaches: struct{}{},
apiRemoveNode: struct{}{},
apiShardNodes: struct{}{},
apiUnmarshalFragment: struct{}{},
apiViews: struct{}{},
}

View file

@ -4,9 +4,9 @@ package pilosa
import "strconv"
const _apiMethod_name = "apiClusterMessageapiCreateFieldapiCreateIndexapiDeleteFieldapiDeleteIndexapiDeleteViewapiExportCSVapiFragmentBlockDataapiFragmentBlocksapiFieldapiFieldAttrDiffapiImportapiImportValueapiIndexapiIndexAttrDiffapiMarshalFragmentapiQueryapiRecalculateCachesapiRemoveNodeapiResizeAbortapiSetCoordinatorapiShardNodesapiUnmarshalFragmentapiViews"
const _apiMethod_name = "apiClusterMessageapiCreateFieldapiCreateIndexapiDeleteFieldapiDeleteIndexapiDeleteViewapiExportCSVapiFragmentBlockDataapiFragmentBlocksapiFieldapiFieldAttrDiffapiImportapiImportValueapiIndexapiIndexAttrDiffapiQueryapiRecalculateCachesapiRemoveNodeapiResizeAbortapiSetCoordinatorapiShardNodesapiViews"
var _apiMethod_index = [...]uint16{0, 17, 31, 45, 59, 73, 86, 98, 118, 135, 143, 159, 168, 182, 190, 206, 224, 232, 252, 265, 279, 296, 309, 329, 337}
var _apiMethod_index = [...]uint16{0, 17, 31, 45, 59, 73, 86, 98, 118, 135, 143, 159, 168, 182, 190, 206, 214, 234, 247, 261, 278, 291, 299}
func (i apiMethod) String() string {
if i < 0 || i >= apiMethod(len(_apiMethod_index)-1) {

View file

@ -45,8 +45,7 @@ const (
ClusterStateResizing = "RESIZING"
// NodeState represents the state of a node during startup.
NodeStateLoading = "LOADING"
NodeStateReady = "READY"
NodeStateReady = "READY"
// resizeJob states.
resizeJobStateRunning = "RUNNING"

View file

@ -149,7 +149,7 @@ func TestFragSources(t *testing.T) {
c5.addNodeBasicSorted(node3)
idx := newIndexWithTempPath("i")
field, err := idx.CreateFieldIfNotExists("f", FieldOptions{})
field, err := idx.CreateFieldIfNotExists("f", OptFieldTypeDefault())
if err != nil {
t.Fatal(err)
}
@ -696,7 +696,7 @@ func TestCluster_ResizeStates(t *testing.T) {
}
// Add Bit Data to node0.
if err := tc.CreateField("i", "f", FieldOptions{}); err != nil {
if err := tc.CreateField("i", "f", OptFieldTypeDefault()); err != nil {
t.Fatal(err)
}
tc.SetBit("i", "f", 1, 101, nil)

View file

@ -39,7 +39,7 @@ func TestExecutor_Execute_Bitmap(t *testing.T) {
defer c.Close()
hldr := test.Holder{Holder: c[0].Server.Holder()}
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
f, err := index.CreateField("f", pilosa.FieldOptions{})
f, err := index.CreateField("f", pilosa.OptFieldTypeDefault())
if err != nil {
t.Fatal(err)
}
@ -89,7 +89,7 @@ func TestExecutor_Execute_Bitmap(t *testing.T) {
hldr := test.Holder{Holder: c[0].Server.Holder()}
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
if _, err := index.CreateField("f", pilosa.FieldOptions{}); err != nil {
if _, err := index.CreateField("f", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
}
@ -112,7 +112,7 @@ func TestExecutor_Execute_Bitmap(t *testing.T) {
hldr := test.Holder{Holder: c[0].Server.Holder()}
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{Keys: true})
if _, err := index.CreateField("f", pilosa.FieldOptions{Keys: true}); err != nil {
if _, err := index.CreateField("f", pilosa.OptFieldTypeDefault(), pilosa.OptFieldKeys()); err != nil {
t.Fatal(err)
}
@ -354,7 +354,7 @@ func TestExecutor_Execute_SetBit(t *testing.T) {
if err := index.DeleteField("f"); err != nil {
t.Fatal(err)
}
if _, err := index.CreateField("f", pilosa.FieldOptions{}); err != nil {
if _, err := index.CreateField("f", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
}
@ -365,7 +365,7 @@ func TestExecutor_Execute_SetBit(t *testing.T) {
t.Run("ErrInvalidRowValueType", func(t *testing.T) {
index := hldr.MustCreateIndexIfNotExists("inokey", pilosa.IndexOptions{})
if _, err := index.CreateField("f", pilosa.FieldOptions{Keys: true}); err != nil {
if _, err := index.CreateField("f", pilosa.OptFieldTypeDefault(), pilosa.OptFieldKeys()); err != nil {
t.Fatal(err)
}
if _, err := cmd.API.Query(context.Background(), &pilosa.QueryRequest{Index: "inokey", Query: `Set(2, f=1)`}); err == nil || errors.Cause(err).Error() != `row value must be a string when field 'keys' option enabled` {
@ -398,13 +398,9 @@ func TestExecutor_Execute_SetValue(t *testing.T) {
// Create felds.
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
if _, err := index.CreateFieldIfNotExists("f", pilosa.FieldOptions{
Type: pilosa.FieldTypeInt,
Min: 0,
Max: 50,
}); err != nil {
if _, err := index.CreateFieldIfNotExists("f", pilosa.OptFieldTypeInt(0, 50)); err != nil {
t.Fatal(err)
} else if _, err := index.CreateFieldIfNotExists("xxx", pilosa.FieldOptions{}); err != nil {
} else if _, err := index.CreateFieldIfNotExists("xxx", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
}
@ -439,11 +435,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.FieldOptions{
Type: pilosa.FieldTypeInt,
Min: 0,
Max: 100,
}); err != nil {
if _, err := index.CreateFieldIfNotExists("f", pilosa.OptFieldTypeInt(0, 100)); err != nil {
t.Fatal(err)
}
@ -475,9 +467,9 @@ func TestExecutor_Execute_SetRowAttrs(t *testing.T) {
// Create fields.
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
if _, err := index.CreateFieldIfNotExists("f", pilosa.FieldOptions{}); err != nil {
if _, err := index.CreateFieldIfNotExists("f", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
} else if _, err := index.CreateFieldIfNotExists("xxx", pilosa.FieldOptions{}); err != nil {
} else if _, err := index.CreateFieldIfNotExists("xxx", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
}
@ -514,9 +506,9 @@ func TestExecutor_Execute_TopN(t *testing.T) {
// Set columns for rows 0, 10, & 20 across two shards.
if idx, err := hldr.CreateIndex("i", pilosa.IndexOptions{}); err != nil {
t.Fatal(err)
} else if _, err := idx.CreateField("f", pilosa.FieldOptions{}); err != nil {
} else if _, err := idx.CreateField("f", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
} else if _, err := idx.CreateField("other", pilosa.FieldOptions{}); err != nil {
} else if _, err := idx.CreateField("other", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
} else if _, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: `
Set(0, f=0)
@ -555,9 +547,9 @@ func TestExecutor_Execute_TopN(t *testing.T) {
// Set columns for rows 0, 10, & 20 across two shards.
if idx, err := hldr.CreateIndex("i", pilosa.IndexOptions{Keys: true}); err != nil {
t.Fatal(err)
} else if _, err := idx.CreateField("f", pilosa.FieldOptions{Keys: true}); err != nil {
} else if _, err := idx.CreateField("f", pilosa.OptFieldTypeDefault(), pilosa.OptFieldKeys()); err != nil {
t.Fatal(err)
} else if _, err := idx.CreateField("other", pilosa.FieldOptions{Keys: true}); err != nil {
} else if _, err := idx.CreateField("other", pilosa.OptFieldTypeDefault(), pilosa.OptFieldKeys()); err != nil {
t.Fatal(err)
} else if _, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: `
Set("a", f="foo")
@ -741,15 +733,11 @@ func TestExecutor_Execute_MinMax(t *testing.T) {
t.Fatal(err)
}
if _, err := idx.CreateField("x", pilosa.FieldOptions{}); err != nil {
if _, err := idx.CreateField("x", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
}
if _, err := idx.CreateField("f", pilosa.FieldOptions{
Type: pilosa.FieldTypeInt,
Min: -10,
Max: 100,
}); err != nil {
if _, err := idx.CreateField("f", pilosa.OptFieldTypeInt(-10, 100)); err != nil {
t.Fatal(err)
}
@ -836,31 +824,19 @@ func TestExecutor_Execute_Sum(t *testing.T) {
t.Fatal(err)
}
if _, err := idx.CreateField("x", pilosa.FieldOptions{}); err != nil {
if _, err := idx.CreateField("x", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
}
if _, err := idx.CreateField("foo", pilosa.FieldOptions{
Type: pilosa.FieldTypeInt,
Min: 10,
Max: 100,
}); err != nil {
if _, err := idx.CreateField("foo", pilosa.OptFieldTypeInt(10, 100)); err != nil {
t.Fatal(err)
}
if _, err := idx.CreateField("bar", pilosa.FieldOptions{
Type: pilosa.FieldTypeInt,
Min: 0,
Max: 100000,
}); err != nil {
if _, err := idx.CreateField("bar", pilosa.OptFieldTypeInt(0, 100000)); err != nil {
t.Fatal(err)
}
if _, err := idx.CreateField("other", pilosa.FieldOptions{
Type: pilosa.FieldTypeInt,
Min: 0,
Max: 1000,
}); err != nil {
if _, err := idx.CreateField("other", pilosa.OptFieldTypeInt(0, 1000)); err != nil {
t.Fatal(err)
}
@ -906,10 +882,7 @@ func TestExecutor_Execute_Range(t *testing.T) {
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
// Create field.
if _, err := index.CreateFieldIfNotExists("f", pilosa.FieldOptions{
Type: pilosa.FieldTypeTime,
TimeQuantum: pilosa.TimeQuantum("YMDH"),
}); err != nil {
if _, err := index.CreateFieldIfNotExists("f", pilosa.OptFieldTypeTime(pilosa.TimeQuantum("YMDH"))); err != nil {
t.Fatal(err)
}
@ -962,39 +935,23 @@ func TestExecutor_Execute_BSIGroupRange(t *testing.T) {
t.Fatal(err)
}
if _, err := idx.CreateField("f", pilosa.FieldOptions{}); err != nil {
if _, err := idx.CreateField("f", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
}
if _, err := idx.CreateField("foo", pilosa.FieldOptions{
Type: pilosa.FieldTypeInt,
Min: 10,
Max: 100,
}); err != nil {
if _, err := idx.CreateField("foo", pilosa.OptFieldTypeInt(10, 100)); err != nil {
t.Fatal(err)
}
if _, err := idx.CreateField("bar", pilosa.FieldOptions{
Type: pilosa.FieldTypeInt,
Min: 0,
Max: 100000,
}); err != nil {
if _, err := idx.CreateField("bar", pilosa.OptFieldTypeInt(0, 100000)); err != nil {
t.Fatal(err)
}
if _, err := idx.CreateField("other", pilosa.FieldOptions{
Type: pilosa.FieldTypeInt,
Min: 0,
Max: 1000,
}); err != nil {
if _, err := idx.CreateField("other", pilosa.OptFieldTypeInt(0, 1000)); err != nil {
t.Fatal(err)
}
if _, err := idx.CreateField("edge", pilosa.FieldOptions{
Type: pilosa.FieldTypeInt,
Min: -100,
Max: 100,
}); err != nil {
if _, err := idx.CreateField("edge", pilosa.OptFieldTypeInt(-100, 100)); err != nil {
t.Fatal(err)
}
@ -1268,7 +1225,7 @@ func TestExecutor_SetColumnAttrs_ExcludeField(t *testing.T) {
hldr := test.Holder{Holder: c[0].Server.Holder()}
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
_, err := index.CreateField("f", pilosa.FieldOptions{})
_, err := index.CreateField("f", pilosa.OptFieldTypeDefault())
if err != nil {
t.Fatalf("creating field: %v", err)
}
@ -1352,10 +1309,7 @@ func TestExecutor_Time_Clear_Quantums(t *testing.T) {
indexName := strings.ToLower(string(tt.quantum))
index := hldr.MustCreateIndexIfNotExists(indexName, pilosa.IndexOptions{})
// Create field.
if _, err := index.CreateFieldIfNotExists("f", pilosa.FieldOptions{
Type: pilosa.FieldTypeTime,
TimeQuantum: tt.quantum,
}); err != nil {
if _, err := index.CreateFieldIfNotExists("f", pilosa.OptFieldTypeTime(tt.quantum)); err != nil {
t.Fatal(err)
}
// Populate

View file

@ -75,9 +75,28 @@ type Field struct {
Logger Logger
}
// FieldOption is a functional option type for pilosa.FieldOptions.
// FieldOption is a functional option type for pilosa.fieldOptions.
type FieldOption func(fo *FieldOptions) error
func OptFieldKeys() FieldOption {
return func(fo *FieldOptions) error {
fo.Keys = true
return nil
}
}
func OptFieldTypeDefault() FieldOption {
return func(fo *FieldOptions) error {
if fo.Type != "" {
return errors.Errorf("field type is already set to: %s", fo.Type)
}
fo.Type = FieldTypeSet
fo.CacheType = DefaultCacheType
fo.CacheSize = DefaultCacheSize
return nil
}
}
func OptFieldTypeSet(cacheType string, cacheSize uint32) FieldOption {
return func(fo *FieldOptions) error {
if fo.Type != "" {
@ -120,12 +139,19 @@ func OptFieldTypeTime(timeQuantum TimeQuantum) FieldOption {
}
// NewField returns a new instance of field.
func NewField(path, index, name string, options FieldOptions) (*Field, error) {
func NewField(path, index, name string, opts FieldOption) (*Field, error) {
err := validateName(name)
if err != nil {
return nil, err
}
// Apply functional option.
fo := FieldOptions{}
err = opts(&fo)
if err != nil {
return nil, errors.Wrap(err, "applying option")
}
f := &Field{
path: path,
index: index,
@ -138,7 +164,7 @@ func NewField(path, index, name string, options FieldOptions) (*Field, error) {
broadcaster: NopBroadcaster,
Stats: NopStatsClient,
options: applyDefaultOptions(options),
options: applyDefaultOptions(fo),
Logger: NopLogger,
}
@ -178,13 +204,6 @@ func (f *Field) Type() string {
return f.options.Type
}
// CacheType returns the caching mode for the field.
func (f *Field) CacheType() string {
f.mu.RLock()
defer f.mu.RUnlock()
return f.options.CacheType
}
// SetCacheSize sets the cache size for ranked fames. Persists to meta file on update.
// defaults to DefaultCacheSize 50000
func (f *Field) SetCacheSize(v uint32) error {

View file

@ -153,7 +153,7 @@ func TestBSIGroup_BaseValue(t *testing.T) {
// Ensure field can open and retrieve a view.
func TestField_DeleteView(t *testing.T) {
f := MustOpenField(FieldOptions{})
f := MustOpenField(OptFieldTypeDefault())
defer f.Close()
viewName := viewStandard + "_v"
@ -190,12 +190,12 @@ type TestField struct {
}
// NewTestField returns a new instance of TestField d/0.
func NewTestField(options FieldOptions) *TestField {
func NewTestField(opts FieldOption) *TestField {
path, err := ioutil.TempDir("", "pilosa-field-")
if err != nil {
panic(err)
}
field, err := NewField(path, "i", "f", options)
field, err := NewField(path, "i", "f", opts)
if err != nil {
panic(err)
}
@ -203,8 +203,8 @@ func NewTestField(options FieldOptions) *TestField {
}
// MustOpenField returns a new, opened field at a temporary path. Panic on error.
func MustOpenField(options FieldOptions) *TestField {
f := NewTestField(options)
func MustOpenField(opts FieldOption) *TestField {
f := NewTestField(opts)
if err := f.Open(); err != nil {
panic(err)
}
@ -225,7 +225,7 @@ func (f *TestField) Reopen() error {
}
path, index, name := f.Path(), f.Index(), f.Name()
f.Field, err = NewField(path, index, name, FieldOptions{})
f.Field, err = NewField(path, index, name, OptFieldTypeDefault())
if err != nil {
return err
}
@ -253,7 +253,7 @@ func (f *TestField) MustSetBit(row, col uint64, ts ...time.Time) {
// Ensure field can open and retrieve a view.
func TestField_CreateViewIfNotExists(t *testing.T) {
f := MustOpenField(FieldOptions{})
f := MustOpenField(OptFieldTypeDefault())
defer f.Close()
// Create view.
@ -278,7 +278,7 @@ func TestField_CreateViewIfNotExists(t *testing.T) {
}
func TestField_SetTimeQuantum(t *testing.T) {
f := MustOpenField(FieldOptions{Type: FieldTypeTime})
f := MustOpenField(OptFieldTypeTime(TimeQuantum("")))
defer f.Close()
// Set & retrieve time quantum.
@ -297,7 +297,7 @@ func TestField_SetTimeQuantum(t *testing.T) {
}
func TestField_RowTime(t *testing.T) {
f := MustOpenField(FieldOptions{Type: FieldTypeTime})
f := MustOpenField(OptFieldTypeTime(TimeQuantum("")))
defer f.Close()
if err := f.SetTimeQuantum(TimeQuantum("YMDH")); err != nil {

View file

@ -28,11 +28,7 @@ func TestField_SetValue(t *testing.T) {
idx := test.MustOpenIndex()
defer idx.Close()
f, err := idx.CreateField("f", pilosa.FieldOptions{
Type: pilosa.FieldTypeInt,
Min: 0,
Max: 30,
})
f, err := idx.CreateField("f", pilosa.OptFieldTypeInt(0, 30))
if err != nil {
t.Fatal(err)
}
@ -65,11 +61,7 @@ func TestField_SetValue(t *testing.T) {
idx := test.MustOpenIndex()
defer idx.Close()
f, err := idx.CreateField("f", pilosa.FieldOptions{
Type: pilosa.FieldTypeInt,
Min: 0,
Max: 30,
})
f, err := idx.CreateField("f", pilosa.OptFieldTypeInt(0, 30))
if err != nil {
t.Fatal(err)
}
@ -102,9 +94,7 @@ func TestField_SetValue(t *testing.T) {
idx := test.MustOpenIndex()
defer idx.Close()
f, err := idx.CreateField("f", pilosa.FieldOptions{
Type: pilosa.FieldTypeSet,
})
f, err := idx.CreateField("f", pilosa.OptFieldTypeDefault())
if err != nil {
t.Fatal(err)
}
@ -119,11 +109,7 @@ func TestField_SetValue(t *testing.T) {
idx := test.MustOpenIndex()
defer idx.Close()
f, err := idx.CreateField("f", pilosa.FieldOptions{
Type: pilosa.FieldTypeInt,
Min: 20,
Max: 30,
})
f, err := idx.CreateField("f", pilosa.OptFieldTypeInt(20, 30))
if err != nil {
t.Fatal(err)
}
@ -138,11 +124,7 @@ func TestField_SetValue(t *testing.T) {
idx := test.MustOpenIndex()
defer idx.Close()
f, err := idx.CreateField("f", pilosa.FieldOptions{
Type: pilosa.FieldTypeInt,
Min: 20,
Max: 30,
})
f, err := idx.CreateField("f", pilosa.OptFieldTypeInt(20, 30))
if err != nil {
t.Fatal(err)
}
@ -159,7 +141,7 @@ func TestField_NameRestriction(t *testing.T) {
if err != nil {
panic(err)
}
field, err := pilosa.NewField(path, "i", ".meta", pilosa.FieldOptions{})
field, err := pilosa.NewField(path, "i", ".meta", pilosa.OptFieldTypeDefault())
if field != nil {
t.Fatalf("unexpected field name %s", err)
}
@ -191,13 +173,13 @@ func TestField_NameValidation(t *testing.T) {
panic(err)
}
for _, name := range validFieldNames {
_, err := pilosa.NewField(path, "i", name, pilosa.FieldOptions{})
_, err := pilosa.NewField(path, "i", name, pilosa.OptFieldTypeDefault())
if err != nil {
t.Fatalf("unexpected field name: %s %s", name, err)
}
}
for _, name := range invalidFieldNames {
_, err := pilosa.NewField(path, "i", name, pilosa.FieldOptions{})
_, err := pilosa.NewField(path, "i", name, pilosa.OptFieldTypeDefault())
if err == nil {
t.Fatalf("expected error on field name: %s", name)
}

View file

@ -750,7 +750,7 @@ func TestFragment_TopN_CacheSize(t *testing.T) {
defer index.Close()
// Create field.
field, err := index.CreateFieldIfNotExists("f", FieldOptions{CacheType: CacheTypeRanked, CacheSize: cacheSize})
field, err := index.CreateFieldIfNotExists("f", OptFieldTypeSet(CacheTypeRanked, cacheSize))
if err != nil {
t.Fatal(err)
}
@ -916,7 +916,7 @@ func TestFragment_RankCache_Persistence(t *testing.T) {
defer index.Close()
// Create field.
field, err := index.CreateFieldIfNotExists("f", FieldOptions{CacheType: CacheTypeRanked})
field, err := index.CreateFieldIfNotExists("f", OptFieldTypeSet(CacheTypeRanked, DefaultCacheSize))
if err != nil {
t.Fatal(err)
}

View file

@ -239,7 +239,7 @@ func (h *Holder) applySchema(schema *Schema) error {
}
// Create fields that don't exist.
for _, f := range index.Fields {
field, err := idx.CreateFieldIfNotExists(f.Name, f.Options)
field, err := idx.createFieldIfNotExists(f.Name, f.Options)
if err != nil {
return errors.Wrap(err, "creating field")
}

View file

@ -60,7 +60,7 @@ func newHolder() *tHolder {
// MustCreateFieldIfNotExists returns a given field. Panic on error.
func (h *tHolder) MustCreateFieldIfNotExists(index, field string) *Field {
f, err := h.MustCreateIndexIfNotExists(index, IndexOptions{}).CreateFieldIfNotExists(field, FieldOptions{})
f, err := h.MustCreateIndexIfNotExists(index, IndexOptions{}).CreateFieldIfNotExists(field, OptFieldTypeDefault())
if err != nil {
panic(err)
}
@ -105,7 +105,7 @@ func TestHolder_Optn(t *testing.T) {
if idx, err := h.CreateIndex("foo", IndexOptions{}); err != nil {
t.Fatal(err)
} else if field, err := idx.CreateField("bar", FieldOptions{}); err != nil {
} else if field, err := idx.CreateField("bar", OptFieldTypeDefault()); err != nil {
t.Fatal(err)
} else if _, err := field.createViewIfNotExists(viewStandard); err != nil {
t.Fatal(err)
@ -129,7 +129,7 @@ func TestHolder_Optn(t *testing.T) {
if idx, err := h.CreateIndex("foo", IndexOptions{}); err != nil {
t.Fatal(err)
} else if field, err := idx.CreateField("bar", FieldOptions{}); err != nil {
} else if field, err := idx.CreateField("bar", OptFieldTypeDefault()); err != nil {
t.Fatal(err)
} else if _, err := field.createViewIfNotExists(viewStandard); err != nil {
t.Fatal(err)
@ -154,7 +154,7 @@ func TestHolder_Optn(t *testing.T) {
if idx, err := h.CreateIndex("foo", IndexOptions{}); err != nil {
t.Fatal(err)
} else if field, err := idx.CreateField("bar", FieldOptions{}); err != nil {
} else if field, err := idx.CreateField("bar", OptFieldTypeDefault()); err != nil {
t.Fatal(err)
} else if view, err := field.createViewIfNotExists(viewStandard); err != nil {
t.Fatal(err)

View file

@ -98,7 +98,7 @@ func TestHolder_Open(t *testing.T) {
if idx, err := h.CreateIndex("foo", pilosa.IndexOptions{}); err != nil {
t.Fatal(err)
} else if _, err := idx.CreateField("bar", pilosa.FieldOptions{}); err != nil {
} else if _, err := idx.CreateField("bar", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
} else if err := h.Holder.Close(); err != nil {
t.Fatal(err)
@ -117,7 +117,7 @@ func TestHolder_Open(t *testing.T) {
if idx, err := h.CreateIndex("foo", pilosa.IndexOptions{}); err != nil {
t.Fatal(err)
} else if _, err := idx.CreateField("bar", pilosa.FieldOptions{}); err != nil {
} else if _, err := idx.CreateField("bar", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
} else if err := h.Holder.Close(); err != nil {
t.Fatal(err)
@ -135,7 +135,7 @@ func TestHolder_Open(t *testing.T) {
if idx, err := h.CreateIndex("foo", pilosa.IndexOptions{}); err != nil {
t.Fatal(err)
} else if _, err := idx.CreateField("bar", pilosa.FieldOptions{}); err != nil {
} else if _, err := idx.CreateField("bar", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
} else if err := h.Holder.Close(); err != nil {
t.Fatal(err)
@ -157,7 +157,7 @@ func TestHolder_Open(t *testing.T) {
if idx, err := h.CreateIndex("foo", pilosa.IndexOptions{}); err != nil {
t.Fatal(err)
} else if field, err := idx.CreateField("bar", pilosa.FieldOptions{}); err != nil {
} else if field, err := idx.CreateField("bar", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
} else if _, err := field.SetBit(0, 0, nil); err != nil {
t.Fatal(err)
@ -178,7 +178,7 @@ func TestHolder_Open(t *testing.T) {
if idx, err := h.CreateIndex("foo", pilosa.IndexOptions{}); err != nil {
t.Fatal(err)
} else if field, err := idx.CreateField("bar", pilosa.FieldOptions{}); err != nil {
} else if field, err := idx.CreateField("bar", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
} else if _, err := field.SetBit(0, 0, nil); err != nil {
t.Fatal(err)

View file

@ -217,15 +217,10 @@ func TestClient_ImportValue(t *testing.T) {
hldr := test.Holder{Holder: holder}
fldName := "f"
fo := pilosa.FieldOptions{
Type: pilosa.FieldTypeInt,
Min: -100,
Max: 100,
}
// Load bitmap into cache to ensure cache gets updated.
index := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
field, err := index.CreateFieldIfNotExists(fldName, fo)
field, err := index.CreateFieldIfNotExists(fldName, pilosa.OptFieldTypeInt(-100, 100))
if err != nil {
t.Fatal(err)
}

View file

@ -651,17 +651,22 @@ func (h *Handler) handlePostField(w http.ResponseWriter, r *http.Request) {
}
// Convert json options into functional options.
var fos pilosa.FieldOption
var fos []pilosa.FieldOption
switch req.Options.Type {
case pilosa.FieldTypeSet:
fos = pilosa.OptFieldTypeSet(*req.Options.CacheType, *req.Options.CacheSize)
fos = append(fos, pilosa.OptFieldTypeSet(*req.Options.CacheType, *req.Options.CacheSize))
case pilosa.FieldTypeInt:
fos = pilosa.OptFieldTypeInt(*req.Options.Min, *req.Options.Max)
fos = append(fos, pilosa.OptFieldTypeInt(*req.Options.Min, *req.Options.Max))
case pilosa.FieldTypeTime:
fos = pilosa.OptFieldTypeTime(*req.Options.TimeQuantum)
fos = append(fos, pilosa.OptFieldTypeTime(*req.Options.TimeQuantum))
}
if req.Options.Keys != nil {
if *req.Options.Keys {
fos = append(fos, pilosa.OptFieldKeys())
}
}
_, err = h.API.CreateField(r.Context(), indexName, fieldName, fos)
_, err = h.API.CreateField(r.Context(), indexName, fieldName, fos...)
resp.write(w, err)
}

View file

@ -287,7 +287,7 @@ func (i *Index) RecalculateCaches() {
}
// CreateField creates a field.
func (i *Index) CreateField(name string, opt FieldOptions) (*Field, error) {
func (i *Index) CreateField(name string, opts ...FieldOption) (*Field, error) {
i.mu.Lock()
defer i.mu.Unlock()
@ -295,11 +295,40 @@ func (i *Index) CreateField(name string, opt FieldOptions) (*Field, error) {
if i.fields[name] != nil {
return nil, NewConflictError(ErrFieldExists)
}
return i.createField(name, opt)
// Apply functional options.
fo := FieldOptions{}
for _, opt := range opts {
err := opt(&fo)
if err != nil {
return nil, errors.Wrap(err, "applying option")
}
}
return i.createField(name, fo)
}
// CreateFieldIfNotExists creates a field with the given options if it doesn't exist.
func (i *Index) CreateFieldIfNotExists(name string, opt FieldOptions) (*Field, error) {
func (i *Index) CreateFieldIfNotExists(name string, opts FieldOption) (*Field, error) {
i.mu.Lock()
defer i.mu.Unlock()
// Find field in cache first.
if f := i.fields[name]; f != nil {
return f, nil
}
// Apply functional option.
fo := FieldOptions{}
err := opts(&fo)
if err != nil {
return nil, errors.Wrap(err, "applying option")
}
return i.createField(name, fo)
}
func (i *Index) createFieldIfNotExists(name string, opt FieldOptions) (*Field, error) {
i.mu.Lock()
defer i.mu.Unlock()
@ -347,7 +376,7 @@ func (i *Index) createField(name string, opt FieldOptions) (*Field, error) {
}
func (i *Index) newField(path, name string) (*Field, error) {
f, err := NewField(path, i.name, name, FieldOptions{}) // TODO: NewField should be un-exported along with FieldOptions
f, err := NewField(path, i.name, name, OptFieldTypeDefault())
if err != nil {
return nil, err
}

View file

@ -33,7 +33,7 @@ func TestIndex_CreateFieldIfNotExists(t *testing.T) {
defer index.Close()
// Create field.
f, err := index.CreateFieldIfNotExists("f", pilosa.FieldOptions{})
f, err := index.CreateFieldIfNotExists("f", pilosa.OptFieldTypeDefault())
if err != nil {
t.Fatal(err)
} else if f == nil {
@ -41,7 +41,7 @@ func TestIndex_CreateFieldIfNotExists(t *testing.T) {
}
// Retrieve existing field.
other, err := index.CreateFieldIfNotExists("f", pilosa.FieldOptions{})
other, err := index.CreateFieldIfNotExists("f", pilosa.OptFieldTypeDefault())
if err != nil {
t.Fatal(err)
} else if f.Field != other.Field {
@ -61,10 +61,7 @@ func TestIndex_CreateField(t *testing.T) {
defer index.Close()
// Create field with explicit quantum.
f, err := index.CreateField("f", pilosa.FieldOptions{
Type: pilosa.FieldTypeTime,
TimeQuantum: pilosa.TimeQuantum("YMDH"),
})
f, err := index.CreateField("f", pilosa.OptFieldTypeTime(pilosa.TimeQuantum("YMDH")))
if err != nil {
t.Fatal(err)
} else if q := f.TimeQuantum(); q != pilosa.TimeQuantum("YMDH") {
@ -80,11 +77,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.FieldOptions{
Type: pilosa.FieldTypeInt,
Min: 10,
Max: 20,
}); err != nil {
if f, err := index.CreateField("f", pilosa.OptFieldTypeInt(10, 20)); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(f.Type(), pilosa.FieldTypeInt) {
t.Fatalf("unexpected type: %#v", f.Type())
@ -184,7 +177,7 @@ func TestIndex_DeleteField(t *testing.T) {
defer index.Close()
// Create field.
if _, err := index.CreateFieldIfNotExists("f", pilosa.FieldOptions{}); err != nil {
if _, err := index.CreateFieldIfNotExists("f", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
}

46
row.go
View file

@ -18,6 +18,7 @@ import (
"encoding/json"
"sort"
"github.com/pilosa/pilosa/internal"
"github.com/pilosa/pilosa/roaring"
)
@ -215,25 +216,6 @@ func (r *Row) InvalidateCount() {
}
}
// IncrementCount increments the row cached counter, note this is an optimization that assumes that the caller is aware the size increased.
func (r *Row) IncrementCount(i uint64) {
seg := r.segment(i / ShardWidth)
if seg != nil {
seg.n++
}
}
// DecrementCount decrements the row cached counter.
func (r *Row) DecrementCount(i uint64) {
seg := r.segment(i / ShardWidth)
if seg != nil {
if seg.n > 0 {
seg.n--
}
}
}
// Count returns the number of columns in the row.
func (r *Row) Count() uint64 {
var n uint64
@ -279,6 +261,32 @@ func Union(rows []*Row) *Row {
return other
}
// EncodeRow converts r into its internal representation.
func EncodeRow(r *Row) *internal.Row {
if r == nil {
return nil
}
return &internal.Row{
Columns: r.Columns(),
Attrs: encodeAttrs(r.Attrs),
}
}
// DecodeRow converts r from its internal representation.
func DecodeRow(pr *internal.Row) *Row {
if pr == nil {
return nil
}
r := NewRow()
r.Attrs = decodeAttrs(pr.Attrs)
for _, v := range pr.Columns {
r.SetBit(v)
}
return r
}
// RowSegment holds a subset of a row.
// This could point to a mmapped roaring bitmap or an in-memory bitmap. The
// width of the segment will always match the shard width.

View file

@ -461,7 +461,7 @@ func (s *Server) receiveMessage(m Message) error {
return fmt.Errorf("Local Index not found: %s", obj.Index)
}
opt := obj.Meta
_, err := idx.CreateField(obj.Field, *opt)
_, err := idx.createField(obj.Field, *opt)
if err != nil {
return err
}

View file

@ -60,17 +60,17 @@ func TestHandler_Endpoints(t *testing.T) {
i0 := hldr.MustCreateIndexIfNotExists("i0", pilosa.IndexOptions{})
i1 := hldr.MustCreateIndexIfNotExists("i1", pilosa.IndexOptions{})
if f, err := i0.CreateFieldIfNotExists("f1", pilosa.FieldOptions{}); err != nil {
if f, err := i0.CreateFieldIfNotExists("f1", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
} else if _, err := f.SetBit(0, 0, nil); err != nil {
t.Fatal(err)
}
if f, err := i1.CreateFieldIfNotExists("f0", pilosa.FieldOptions{}); err != nil {
if f, err := i1.CreateFieldIfNotExists("f0", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
} else if _, err := f.SetBit(0, 0, nil); err != nil {
t.Fatal(err)
}
if _, err := i0.CreateFieldIfNotExists("f0", pilosa.FieldOptions{}); err != nil {
if _, err := i0.CreateFieldIfNotExists("f0", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
}
@ -393,7 +393,7 @@ func TestHandler_Endpoints(t *testing.T) {
t.Run("Field delete", func(t *testing.T) {
i := hldr.MustCreateIndexIfNotExists("i", pilosa.IndexOptions{})
if _, err := i.CreateFieldIfNotExists("f1", pilosa.FieldOptions{}); err != nil {
if _, err := i.CreateFieldIfNotExists("f1", pilosa.OptFieldTypeDefault()); err != nil {
t.Fatal(err)
}
w := httptest.NewRecorder()
@ -445,7 +445,7 @@ func TestHandler_Endpoints(t *testing.T) {
}
})
meta, err := i.CreateFieldIfNotExists("meta", pilosa.FieldOptions{})
meta, err := i.CreateFieldIfNotExists("meta", pilosa.OptFieldTypeDefault())
if err != nil {
t.Fatal(err)
}

View file

@ -28,12 +28,12 @@ type Field struct {
}
// NewField returns a new instance of Field d/0.
func NewField(options pilosa.FieldOptions) *Field {
func NewField(opts pilosa.FieldOption) *Field {
path, err := ioutil.TempDir("", "pilosa-field-")
if err != nil {
panic(err)
}
field, err := pilosa.NewField(path, "i", "f", options)
field, err := pilosa.NewField(path, "i", "f", opts)
if err != nil {
panic(err)
}
@ -41,8 +41,8 @@ func NewField(options pilosa.FieldOptions) *Field {
}
// MustOpenField returns a new, opened field at a temporary path. Panic on error.
func MustOpenField(options pilosa.FieldOptions) *Field {
f := NewField(options)
func MustOpenField(opts pilosa.FieldOption) *Field {
f := NewField(opts)
if err := f.Open(); err != nil {
panic(err)
}
@ -63,7 +63,7 @@ func (f *Field) Reopen() error {
}
path, index, name := f.Path(), f.Index(), f.Name()
f.Field, err = pilosa.NewField(path, index, name, pilosa.FieldOptions{})
f.Field, err = pilosa.NewField(path, index, name, pilosa.OptFieldTypeDefault())
if err != nil {
return err
}
@ -76,7 +76,7 @@ func (f *Field) Reopen() error {
// Ensure field can set its cache
func TestField_SetCacheSize(t *testing.T) {
f := MustOpenField(pilosa.FieldOptions{})
f := MustOpenField(pilosa.OptFieldTypeDefault())
defer f.Close()
cacheSize := uint32(100)

View file

@ -83,7 +83,7 @@ func (h *Holder) MustCreateIndexIfNotExists(index string, opt pilosa.IndexOption
// MustCreateFieldIfNotExists returns a given field. Panic on error.
func (h *Holder) MustCreateFieldIfNotExists(index, field string) *Field {
f, err := h.MustCreateIndexIfNotExists(index, pilosa.IndexOptions{}).CreateFieldIfNotExists(field, pilosa.FieldOptions{})
f, err := h.MustCreateIndexIfNotExists(index, pilosa.IndexOptions{}).CreateFieldIfNotExists(field, pilosa.OptFieldTypeDefault())
if err != nil {
panic(err)
}
@ -93,7 +93,7 @@ func (h *Holder) MustCreateFieldIfNotExists(index, field string) *Field {
// Row returns a Row for a given field.
func (h *Holder) Row(index, field string, rowID uint64) *pilosa.Row {
idx := h.MustCreateIndexIfNotExists(index, pilosa.IndexOptions{})
f, err := idx.CreateFieldIfNotExists(field, pilosa.FieldOptions{})
f, err := idx.CreateFieldIfNotExists(field, pilosa.OptFieldTypeDefault())
if err != nil {
panic(err)
}
@ -106,7 +106,7 @@ func (h *Holder) Row(index, field string, rowID uint64) *pilosa.Row {
func (h *Holder) RowAttrStore(index, field string) pilosa.AttrStore {
idx := h.MustCreateIndexIfNotExists(index, pilosa.IndexOptions{})
f, err := idx.CreateFieldIfNotExists(field, pilosa.FieldOptions{})
f, err := idx.CreateFieldIfNotExists(field, pilosa.OptFieldTypeDefault())
if err != nil {
panic(err)
}
@ -115,7 +115,7 @@ func (h *Holder) RowAttrStore(index, field string) pilosa.AttrStore {
func (h *Holder) RowTime(index, field string, rowID uint64, t time.Time, quantum string) *pilosa.Row {
idx := h.MustCreateIndexIfNotExists(index, pilosa.IndexOptions{})
f, err := idx.CreateFieldIfNotExists(field, pilosa.FieldOptions{})
f, err := idx.CreateFieldIfNotExists(field, pilosa.OptFieldTypeDefault())
if err != nil {
panic(err)
}
@ -129,7 +129,7 @@ func (h *Holder) RowTime(index, field string, rowID uint64, t time.Time, quantum
// SetBit clears a bit on the given field.
func (h *Holder) SetBit(index, field string, rowID, columnID uint64) {
idx := h.MustCreateIndexIfNotExists(index, pilosa.IndexOptions{})
f, err := idx.CreateFieldIfNotExists(field, pilosa.FieldOptions{})
f, err := idx.CreateFieldIfNotExists(field, pilosa.OptFieldTypeDefault())
if err != nil {
panic(err)
}
@ -142,7 +142,7 @@ func (h *Holder) SetBit(index, field string, rowID, columnID uint64) {
// ClearBit clears a bit on the given field.
func (h *Holder) ClearBit(index, field string, rowID, columnID uint64) {
idx := h.MustCreateIndexIfNotExists(index, pilosa.IndexOptions{})
f, err := idx.CreateFieldIfNotExists(field, pilosa.FieldOptions{})
f, err := idx.CreateFieldIfNotExists(field, pilosa.OptFieldTypeDefault())
if err != nil {
panic(err)
}

View file

@ -74,8 +74,8 @@ func (i *Index) Reopen() error {
}
// CreateField creates a field with the given options.
func (i *Index) CreateField(name string, opt pilosa.FieldOptions) (*Field, error) {
f, err := i.Index.CreateField(name, opt)
func (i *Index) CreateField(name string, opts ...pilosa.FieldOption) (*Field, error) {
f, err := i.Index.CreateField(name, opts...)
if err != nil {
return nil, err
}
@ -83,8 +83,8 @@ func (i *Index) CreateField(name string, opt pilosa.FieldOptions) (*Field, error
}
// CreateFieldIfNotExists creates a field with the given options if it doesn't exist.
func (i *Index) CreateFieldIfNotExists(name string, opt pilosa.FieldOptions) (*Field, error) {
f, err := i.Index.CreateFieldIfNotExists(name, opt)
func (i *Index) CreateFieldIfNotExists(name string, opts pilosa.FieldOption) (*Field, error) {
f, err := i.Index.CreateFieldIfNotExists(name, opts)
if err != nil {
return nil, err
}

View file

@ -63,11 +63,6 @@ func NewCommand(opts ...server.CommandOption) *Command {
m.Command.Stdout = &m.Stdout
m.Command.Stderr = &m.Stderr
err = m.SetupServer()
if err != nil {
panic(err)
}
if testing.Verbose() {
m.Command.Stdout = io.MultiWriter(os.Stdout, m.Command.Stdout)
m.Command.Stderr = io.MultiWriter(os.Stderr, m.Command.Stderr)
@ -117,10 +112,6 @@ func (m *Command) Reopen() error {
config := m.Command.Config
m.Command = server.NewCommand(os.Stdin, os.Stdout, os.Stderr, m.commandOptions...)
m.Command.Config = config
err := m.SetupServer()
if err != nil {
return errors.Wrap(err, "setting up server")
}
// Run new program.
if err := m.Start(); err != nil {

View file

@ -70,15 +70,6 @@ func (q TimeQuantum) Type() string {
return "TimeQuantum"
}
// ParseTimeQuantum parses v into a time quantum.
func ParseTimeQuantum(v string) (TimeQuantum, error) {
q := TimeQuantum(strings.ToUpper(v))
if !q.Valid() {
return "", ErrInvalidTimeQuantum
}
return q, nil
}
// viewByTimeUnit returns the view name for time with a given quantum unit.
func viewByTimeUnit(name string, t time.Time, unit rune) string {
switch unit {

View file

@ -16,6 +16,7 @@ package pilosa
import (
"reflect"
"strings"
"testing"
"time"
)
@ -23,7 +24,7 @@ import (
// Ensure string can be parsed into time quantum.
func TestParseTimeQuantum(t *testing.T) {
t.Run("OK", func(t *testing.T) {
if q, err := ParseTimeQuantum("YMDH"); err != nil {
if q, err := parseTimeQuantum("YMDH"); err != nil {
t.Fatalf("unexpected error: %s", err)
} else if q != TimeQuantum("YMDH") {
t.Fatalf("unexpected quantum: %#v", q)
@ -31,7 +32,7 @@ func TestParseTimeQuantum(t *testing.T) {
})
t.Run("ErrInvalidTimeQuantum", func(t *testing.T) {
if _, err := ParseTimeQuantum("BADQUANTUM"); err != ErrInvalidTimeQuantum {
if _, err := parseTimeQuantum("BADQUANTUM"); err != ErrInvalidTimeQuantum {
t.Fatalf("unexpected error: %s", err)
}
})
@ -160,9 +161,18 @@ func mustParseTime(value string) time.Time {
// mustParseTimeQuantum parses v into a time quantum. Panic on error.
func mustParseTimeQuantum(v string) TimeQuantum {
q, err := ParseTimeQuantum(v)
q, err := parseTimeQuantum(v)
if err != nil {
panic(err)
}
return q
}
// parseTimeQuantum parses v into a time quantum.
func parseTimeQuantum(v string) (TimeQuantum, error) {
q := TimeQuantum(strings.ToUpper(v))
if !q.Valid() {
return "", ErrInvalidTimeQuantum
}
return q, nil
}

12
uri.go
View file

@ -147,14 +147,6 @@ func (u URI) String() string {
return fmt.Sprintf("%s://%s:%d", u.Scheme, u.Host, u.Port)
}
// Equals returns true if the checked URI is equivalent to this URI.
func (u URI) Equals(other *URI) bool {
if other == nil {
return false
}
return u == *other
}
// Path returns URI with path
func (u *URI) Path(path string) string {
return fmt.Sprintf("%s%s", u.Normalize(), path)
@ -162,7 +154,7 @@ func (u *URI) Path(path string) string {
// The following methods are required to implement pflag Value interface.
// Set sets the time quantum value.
// Set sets the uri value.
func (u *URI) Set(value string) error {
uri, err := NewURIFromAddress(value)
if err != nil {
@ -172,7 +164,7 @@ func (u *URI) Set(value string) error {
return nil
}
// Type returns the type of a time quantum value.
// Type returns the type of a uri.
func (u URI) Type() string {
return "URI"
}

View file

@ -76,16 +76,6 @@ func TestURIPath(t *testing.T) {
}
}
func TestEquals(t *testing.T) {
uri1 := DefaultURI()
if uri1.Equals(nil) {
t.Fatalf("URI should not be equal to nil")
}
if !uri1.Equals(DefaultURI()) {
t.Fatalf("URI should be equal to another URI with the same scheme, host and port")
}
}
func TestSetScheme(t *testing.T) {
uri := DefaultURI()
target := "fun"

View file

@ -103,13 +103,13 @@ func (t *ClusterCluster) CreateIndex(name string) error {
return nil
}
func (t *ClusterCluster) CreateField(index, field string, opt FieldOptions) error {
func (t *ClusterCluster) CreateField(index, field string, opts FieldOption) error {
for _, c := range t.Clusters {
idx, err := c.holder.CreateIndexIfNotExists(index, IndexOptions{})
if err != nil {
return err
}
if _, err := idx.CreateField(field, opt); err != nil {
if _, err := idx.CreateField(field, opts); err != nil {
return err
}
}