Merge pull request #1788 from jaffee/1691-existence-namespace

1691 existence namespace
This commit is contained in:
Matthew Jaffee 2018-12-17 17:02:12 -06:00 committed by GitHub
commit 047b5874ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 32 additions and 18 deletions

View file

@ -18,6 +18,7 @@ import (
"context"
"fmt"
"reflect"
"strings"
"testing"
"github.com/pilosa/pilosa"
@ -48,7 +49,7 @@ func TestAPI_Import(t *testing.T) {
index := "rick"
field := "f"
_, err := m0.API.CreateIndex(ctx, index, pilosa.IndexOptions{Keys: true})
_, err := m0.API.CreateIndex(ctx, index, pilosa.IndexOptions{Keys: true, TrackExistence: true})
if err != nil {
t.Fatalf("creating index: %v", err)
}
@ -99,6 +100,22 @@ func TestAPI_Import(t *testing.T) {
} else if keys := res.Results[0].(*pilosa.Row).Keys; !reflect.DeepEqual(keys, colKeys) {
t.Fatalf("unexpected column keys: %+v", keys)
}
})
// Relies on the previous test creating an index with TrackExistence and
// adding some data.
t.Run("SchemaHasNoExists", func(t *testing.T) {
schema := m1.API.Schema(context.Background())
for _, f := range schema[0].Fields {
if f.Name == "_exists" {
t.Fatalf("found _exists field in schema")
}
if strings.HasPrefix(f.Name, "_") {
t.Fatalf("found internal field '%s' in schema output", f.Name)
}
}
})
t.Run("RowKeyColumnID", func(t *testing.T) {

View file

@ -2163,10 +2163,10 @@ func TestExecutor_Execute_Existence(t *testing.T) {
t.Fatalf("unexpected columns: %+v", bits)
}
if res, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: `Row(exists=0)`}); err != nil {
if res, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: `Not(Row(f=10))`}); err != nil {
t.Fatal(err)
} else if bits := res.Results[0].(*pilosa.Row).Columns(); !reflect.DeepEqual(bits, []uint64{3, ShardWidth + 1, ShardWidth + 2}) {
t.Fatalf("unexpected existence columns: %+v", bits)
} else if bits := res.Results[0].(*pilosa.Row).Columns(); !reflect.DeepEqual(bits, []uint64{ShardWidth + 2}) {
t.Fatalf("unexpected columns after Not: %+v", bits)
}
// Reopen cluster to ensure existence field is reloaded.
@ -2174,10 +2174,10 @@ func TestExecutor_Execute_Existence(t *testing.T) {
t.Fatal(err)
}
if res, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: `Row(exists=0)`}); err != nil {
if res, err := c[0].API.Query(context.Background(), &pilosa.QueryRequest{Index: "i", Query: `Not(Row(f=10))`}); err != nil {
t.Fatal(err)
} else if bits := res.Results[0].(*pilosa.Row).Columns(); !reflect.DeepEqual(bits, []uint64{3, ShardWidth + 1, ShardWidth + 2}) {
t.Fatalf("unexpected existence columns after reopen: %+v", bits)
} else if bits := res.Results[0].(*pilosa.Row).Columns(); !reflect.DeepEqual(bits, []uint64{ShardWidth + 2}) {
t.Fatalf("unexpected columns after reopen: %+v", bits)
}
})
}

View file

@ -43,7 +43,7 @@ const (
fileLimit = 262144 // (512^2)
// existenceFieldName is the name of the internal field used to store existence values.
existenceFieldName = "exists"
existenceFieldName = "_exists"
)
// Holder represents a container for indexes.
@ -289,6 +289,9 @@ func (h *Holder) limitedSchema() []*IndexInfo {
for _, index := range h.Indexes() {
di := &IndexInfo{Name: index.Name(), Options: index.Options()}
for _, field := range index.Fields() {
if strings.HasPrefix(field.name, "_") {
continue
}
fi := &FieldInfo{Name: field.Name(), Options: field.Options()}
di.Fields = append(di.Fields, fi)
}

View file

@ -900,7 +900,7 @@ func TestClient_ImportExistence(t *testing.T) {
}
// Verify existence.
if a := hldr.ReadRow(idxName, "exists", 0).Columns(); !reflect.DeepEqual(a, []uint64{1, 5, 6}) {
if a := hldr.ReadRow(idxName, "_exists", 0).Columns(); !reflect.DeepEqual(a, []uint64{1, 5, 6}) {
t.Fatalf("unexpected existence columns: %+v", a)
}
})
@ -935,7 +935,7 @@ func TestClient_ImportExistence(t *testing.T) {
}
// Verify existence.
if a := hldr.ReadRow(idxName, "exists", 0).Columns(); !reflect.DeepEqual(a, []uint64{1, 2, 3}) {
if a := hldr.ReadRow(idxName, "_exists", 0).Columns(); !reflect.DeepEqual(a, []uint64{1, 2, 3}) {
t.Fatalf("unexpected existence columns: %+v", a)
}
})

View file

@ -49,8 +49,6 @@ var (
ErrName = errors.New("invalid index or field name, must match [a-z0-9_-]")
ErrLabel = errors.New("invalid row or column label, must match [A-Za-z0-9_-]")
ErrReservedName = errors.New("reserved index or field name")
// ErrFragmentNotFound is returned when a fragment does not exist.
ErrFragmentNotFound = errors.New("fragment not found")
ErrQueryRequired = errors.New("query required")
@ -131,9 +129,6 @@ const TimeFormat = "2006-01-02T15:04"
// validateName ensures that the name is a valid format.
func validateName(name string) error {
if name == existenceFieldName {
return ErrReservedName
}
if !nameRegexp.Match([]byte(name)) {
return ErrName
}

View file

@ -20,7 +20,7 @@ import (
func TestValidateName(t *testing.T) {
names := []string{
"a", "ab", "ab1", "b-c", "d_e",
"a", "ab", "ab1", "b-c", "d_e", "exists",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
}
for _, name := range names {
@ -33,8 +33,7 @@ func TestValidateName(t *testing.T) {
func TestValidateNameInvalid(t *testing.T) {
names := []string{
"", "'", "^", "/", "\\", "A", "*", "a:b", "valid?no", "yüce", "1", "_", "-",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1",
"exists",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1", "_exists",
}
for _, name := range names {
if validateName(name) == nil {