diff --git a/api.go b/api.go index af468914f..a3fdc3b93 100644 --- a/api.go +++ b/api.go @@ -1083,6 +1083,25 @@ func (api *API) ImportValue(ctx context.Context, req *ImportValueRequest, opts . } req.Shard = math.MaxUint64 } + + // Translate values when the field has a ForeignIndex with keys. + if fidx := field.Options().ForeignIndex; fidx != "" { + foreignIndex := api.holder.Index(fidx) + if foreignIndex == nil { + return errors.Errorf("foreign index does not exist: %s", fidx) + } + uints, err := foreignIndex.translateStore.TranslateKeys(req.StringValues) + if err != nil { + return errors.Wrap(err, "translating string values") + } + // Because the BSI field supports negative value, we have to + // convert the slice of uint64 keys to a slice of int64. + ints := make([]int64, len(uints)) + for i := range uints { + ints[i] = int64(uints[i]) + } + req.Values = ints + } } if !options.Presorted { diff --git a/api_test.go b/api_test.go index b6cfa8d07..7e94ebee1 100644 --- a/api_test.go +++ b/api_test.go @@ -536,6 +536,61 @@ func TestAPI_ImportValue(t *testing.T) { } }) + + t.Run("ValStringField", func(t *testing.T) { + ctx := context.Background() + index := "valstr" + field := "fstr" + + fgnIndex := "fgnvalstr" + + _, err := m0.API.CreateIndex(ctx, index, pilosa.IndexOptions{}) + if err != nil { + t.Fatalf("creating index: %v", err) + } + + _, err = m0.API.CreateIndex(ctx, fgnIndex, pilosa.IndexOptions{Keys: true}) + if err != nil { + t.Fatalf("creating foreign index: %v", err) + } + _, err = m0.API.CreateField(ctx, index, field, + pilosa.OptFieldTypeInt(0, math.MaxInt64), + pilosa.OptFieldForeignIndex(fgnIndex), + ) + if err != nil { + t.Fatalf("creating field: %v", err) + } + + // Generate some keyed records. + values := []string{} + colIDs := []uint64{} + for i := 0; i < 10; i++ { + value := fmt.Sprintf("strval-%d", (i)*100+10) + values = append(values, value) + colIDs = append(colIDs, uint64(i)) + } + + // Import data with keys to the coordinator (node0) and verify that it gets + // translated and forwarded to the owner of shard 0 (node1; because of offsetModHasher) + req := &pilosa.ImportValueRequest{ + Index: index, + Field: field, + ColumnIDs: colIDs, + StringValues: values, + } + if err := m0.API.ImportValue(ctx, req); err != nil { + t.Fatal(err) + } + + pql := fmt.Sprintf(`Row(%s=="strval-110")`, field) + + // Query node0. + if res, err := m0.API.Query(ctx, &pilosa.QueryRequest{Index: index, Query: pql}); err != nil { + t.Fatal(err) + } else if ids := res.Results[0].(*pilosa.Row).Columns(); !reflect.DeepEqual(ids, []uint64{1}) { + t.Fatalf("unexpected columns: %+v", ids) + } + }) } // offsetModHasher represents a simple, mod-based hashing offset by 1. diff --git a/encoding/proto/proto.go b/encoding/proto/proto.go index c1644ed58..a1352990b 100644 --- a/encoding/proto/proto.go +++ b/encoding/proto/proto.go @@ -567,16 +567,17 @@ func encodeFieldOptions(o *pilosa.FieldOptions) *internal.FieldOptions { return nil } return &internal.FieldOptions{ - Type: o.Type, - CacheType: o.CacheType, - CacheSize: o.CacheSize, - Min: o.Min, - Max: o.Max, - Base: o.Base, - Scale: o.Scale, - BitDepth: uint64(o.BitDepth), - TimeQuantum: string(o.TimeQuantum), - Keys: o.Keys, + Type: o.Type, + CacheType: o.CacheType, + CacheSize: o.CacheSize, + Min: o.Min, + Max: o.Max, + Base: o.Base, + Scale: o.Scale, + BitDepth: uint64(o.BitDepth), + TimeQuantum: string(o.TimeQuantum), + Keys: o.Keys, + ForeignIndex: o.ForeignIndex, } } @@ -848,6 +849,7 @@ func decodeFieldOptions(options *internal.FieldOptions, m *pilosa.FieldOptions) m.BitDepth = uint(options.BitDepth) m.TimeQuantum = pilosa.TimeQuantum(options.TimeQuantum) m.Keys = options.Keys + m.ForeignIndex = options.ForeignIndex } func decodeNodes(a []*internal.Node, m []*pilosa.Node) { diff --git a/executor.go b/executor.go index db53dad27..a17897793 100644 --- a/executor.go +++ b/executor.go @@ -3620,17 +3620,20 @@ func (e *executor) translateCall(index string, idx *Index, c *pql.Call) error { c.Args[rowKey] = rowID } } else if field.keys() { - if c.Args[rowKey] != nil && !isString(c.Args[rowKey]) { - // allow passing row id directly (this can come in handy, but make sure it is a valid row id) - if !isValidID(c.Args[rowKey]) { - return errors.Errorf("row value must be a string or non-negative integer, but got: %v of %[1]T", c.Args[rowKey]) + if err := e.translateRowKey(c, field.translateStore, rowKey); err != nil { + return errors.Wrap(err, "translating rowkey") + } + } else if field.Options().ForeignIndex != "" { + // Get the foreign index. + fidx := field.Options().ForeignIndex + foreignIndex := e.Holder.Index(fidx) + if foreignIndex == nil { + return errors.Errorf("foreign index does not exist: %s", fidx) + } + if foreignIndex.Keys() { + if err := e.translateRowKey(c, foreignIndex.translateStore, rowKey); err != nil { + return errors.Wrap(err, "translating rowkey") } - } else if value := callArgString(c, rowKey); value != "" { - id, err := field.translateStore.TranslateKey(value) - if err != nil { - return err - } - c.Args[rowKey] = id } } else { if isString(c.Args[rowKey]) { @@ -3662,6 +3665,42 @@ func (e *executor) translateCall(index string, idx *Index, c *pql.Call) error { return nil } +func (e *executor) translateRowKey(c *pql.Call, store TranslateStore, rowKey string) error { + if c.Args[rowKey] != nil && isCondition(c.Args[rowKey]) { + // In the case where a field has a foreign index with keys, + // allow `== "key"` or `!= "key"` to be used against the BSI + // field. + cond := c.Args[rowKey].(*pql.Condition) + if isString(cond.Value) { + switch cond.Op { + case pql.EQ, pql.NEQ: + id, err := store.TranslateKey(cond.Value.(string)) + if err != nil { + return errors.Wrap(err, "translating key") + } + c.Args[rowKey] = &pql.Condition{ + Op: cond.Op, + Value: id, + } + default: + return errors.Errorf("conditional is not supported with string predicates: %s", cond.Op) + } + } + } else if c.Args[rowKey] != nil && !isString(c.Args[rowKey]) { + // allow passing row id directly (this can come in handy, but make sure it is a valid row id) + if !isValidID(c.Args[rowKey]) { + return errors.Errorf("row value must be a string or non-negative integer, but got: %v of %[1]T", c.Args[rowKey]) + } + } else if value := callArgString(c, rowKey); value != "" { + id, err := store.TranslateKey(value) + if err != nil { + return errors.Wrap(err, "translating key") + } + c.Args[rowKey] = id + } + return nil +} + func (e *executor) translateGroupByCall(index string, idx *Index, c *pql.Call) error { if c.Name != "GroupBy" { panic("translateGroupByCall called with '" + c.Name + "'") @@ -3767,6 +3806,47 @@ func (e *executor) translateResult(index string, idx *Index, call *pql.Call, res return other, nil } + // TODO: instead of supporting SignedRow here, we may be able to + // make the return type for an int field with a ForeignIndex be + // a *Row instead (because it should always be positive). + case SignedRow: + var store TranslateStore + + if fieldName := callArgString(call, "field"); fieldName != "" { + field := idx.Field(fieldName) + if field != nil { + // Get the foreign index. + if fidx := field.Options().ForeignIndex; fidx != "" { + foreignIndex := e.Holder.Index(fidx) + if foreignIndex == nil { + return nil, errors.Errorf("foreign index does not exist: %s", fidx) + } + store = foreignIndex.translateStore + } + } + } + + // In the case where a field/foreignIndex doesn't exist, + // fall back to using the index translateStore. + if store == nil && idx.Keys() { + store = idx.translateStore + } + + if store != nil { + rslt := result.Pos + other := &Row{Attrs: rslt.Attrs} + for _, segment := range rslt.Segments() { + for _, col := range segment.Columns() { + key, err := store.TranslateID(col) + if err != nil { + return nil, err + } + other.Keys = append(other.Keys, key) + } + } + return SignedRow{Pos: other}, nil + } + case PairField: if fieldName := callArgString(call, "field"); fieldName != "" { field := idx.Field(fieldName) @@ -4066,6 +4146,11 @@ func isString(v interface{}) bool { return ok } +func isCondition(v interface{}) bool { + _, ok := v.(*pql.Condition) + return ok +} + // isValidID returns whether v can be interpreted as a valid row or // column ID. In short, is v a non-negative integer? I think the int64 // and default cases are the only ones actually used since the PQL diff --git a/executor_test.go b/executor_test.go index ec8865c8a..9af38856f 100644 --- a/executor_test.go +++ b/executor_test.go @@ -3854,6 +3854,70 @@ func TestExecutor_Execute_Rows_Keys(t *testing.T) { } +func TestExecutor_ForeignIndex(t *testing.T) { + c := test.MustRunCluster(t, 1) + defer c.Close() + + c.CreateField(t, "parent", pilosa.IndexOptions{Keys: true}, "general") + c.CreateField(t, "child", pilosa.IndexOptions{}, "parent_id", + pilosa.OptFieldTypeInt(0, math.MaxInt64), + pilosa.OptFieldForeignIndex("parent"), + ) + c.CreateField(t, "child", pilosa.IndexOptions{}, "color", + pilosa.OptFieldKeys(), + ) + + // Populate parent data. + c.Query(t, "parent", ` + Set("one", general=1) + Set("two", general=1) + Set("three", general=1) + + Set("twenty-one", general=2) + Set("twenty-two", general=2) + Set("twenty-three", general=2) + + Set("one", general=3) + Set("twenty-one", general=3) + `) + + // Populate child data. + c.Query(t, "child", ` + Set(1, parent_id="one") + Set(2, parent_id="two") + Set(3, parent_id="one") + Set(4, parent_id="twenty-one") + `) + + // Populate color data. + c.Query(t, "child", ` + Set(1, color="red") + Set(2, color="blue") + Set(3, color="blue") + Set(4, color="red") + `) + + distinct := c.Query(t, "child", `Distinct(index="child", field="parent_id")`).Results[0].(pilosa.SignedRow) + if !reflect.DeepEqual(distinct.Pos.Keys, []string{"one", "two", "twenty-one"}) { + t.Fatalf("unexpected keys: %v", distinct.Pos.Keys) + } + + eq := c.Query(t, "child", `Row(parent_id=="one")`).Results[0].(*pilosa.Row) + if !reflect.DeepEqual(eq.Columns(), []uint64{1, 3}) { + t.Fatalf("unexpected columns: %v", eq.Columns()) + } + + neq := c.Query(t, "child", `Row(parent_id!="one")`).Results[0].(*pilosa.Row) + if !reflect.DeepEqual(neq.Columns(), []uint64{2, 4}) { + t.Fatalf("unexpected columns: %v", neq.Columns()) + } + + join := c.Query(t, "parent", `Intersect(Row(general=3), Distinct(Row(color="blue"), index="child", field="parent_id"))`).Results[0].(*pilosa.Row) + if !reflect.DeepEqual(join.Keys, []string{"one"}) { + t.Fatalf("unexpected keys: %v", join.Keys) + } +} + func TestExecutor_Execute_GroupBy(t *testing.T) { groupByTest := func(t *testing.T, clusterSize int) { c := test.MustRunCluster(t, 1) diff --git a/field.go b/field.go index 86c5204a8..ffaacb39a 100644 --- a/field.go +++ b/field.go @@ -108,6 +108,17 @@ func OptFieldKeys() FieldOption { } } +// OptFieldForeignIndex marks this field as a foreign key to another +// index. That is, the values of this field should be interpreted as +// referencing records (Pilosa columns) in another index. TODO explain +// where/how this is used by Pilosa. +func OptFieldForeignIndex(index string) FieldOption { + return func(fo *FieldOptions) error { + fo.ForeignIndex = index + return nil + } +} + // OptFieldTypeDefault is a functional option on FieldOptions // used to set the field type and cache setting to the default values. func OptFieldTypeDefault() FieldOption { @@ -230,6 +241,11 @@ func OptFieldTypeBool() FieldOption { } // NewField returns a new instance of field. +// NOTE: This function is only used in tests, which is why +// it only takes a single `FieldOption` (the assumption being +// that it's of the type `OptFieldType*`). This means +// this function couldn't be used to set, for example, +// `FieldOptions.Keys`. func NewField(path, index, name string, opts FieldOption) (*Field, error) { err := validateName(name) if err != nil { @@ -594,6 +610,7 @@ func (f *Field) loadMeta() error { f.options.TimeQuantum = TimeQuantum(pb.TimeQuantum) f.options.Keys = pb.Keys f.options.NoStandardView = pb.NoStandardView + f.options.ForeignIndex = pb.ForeignIndex return nil } @@ -647,6 +664,7 @@ func (f *Field) applyOptions(opt FieldOptions) error { f.options.BitDepth = 0 f.options.TimeQuantum = "" f.options.Keys = opt.Keys + f.options.ForeignIndex = "" case FieldTypeInt, FieldTypeDecimal: f.options.Type = opt.Type f.options.CacheType = CacheTypeNone @@ -658,6 +676,7 @@ func (f *Field) applyOptions(opt FieldOptions) error { f.options.BitDepth = opt.BitDepth f.options.TimeQuantum = "" f.options.Keys = opt.Keys + f.options.ForeignIndex = opt.ForeignIndex // Create new bsiGroup. bsig := &bsiGroup{ @@ -691,6 +710,7 @@ func (f *Field) applyOptions(opt FieldOptions) error { f.Close() return errors.Wrap(err, "setting time quantum") } + f.options.ForeignIndex = "" case FieldTypeBool: f.options.Type = FieldTypeBool f.options.CacheType = CacheTypeNone @@ -701,6 +721,7 @@ func (f *Field) applyOptions(opt FieldOptions) error { f.options.BitDepth = 0 f.options.TimeQuantum = "" f.options.Keys = false + f.options.ForeignIndex = "" default: return errors.New("invalid field type") } @@ -1580,6 +1601,7 @@ type FieldOptions struct { CacheType string `json:"cacheType,omitempty"` Type string `json:"type,omitempty"` TimeQuantum TimeQuantum `json:"timeQuantum,omitempty"` + ForeignIndex string `json:"foreignIndex"` } // applyDefaultOptions returns a new FieldOptions object diff --git a/go.mod b/go.mod index 9366e18cd..97c1a420d 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/gorilla/mux v1.7.0 github.com/hashicorp/memberlist v0.1.3 github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/molecula/ext v0.0.0-20191202195653-240f38a75171 + github.com/molecula/ext v0.0.0-20200103203257-8a458a73e8c2 github.com/molecula/extensions v0.0.0-20191218165536-562244600fd4 github.com/opentracing/opentracing-go v1.1.0 github.com/pelletier/go-toml v1.2.0 diff --git a/go.sum b/go.sum index 1b1b7af2f..cc8233904 100644 --- a/go.sum +++ b/go.sum @@ -91,6 +91,8 @@ github.com/molecula/apophenia v0.0.0-20190827192002-68b7a14a478b h1:cZADDaNYM7xn github.com/molecula/apophenia v0.0.0-20190827192002-68b7a14a478b/go.mod h1:uXd1BiH7xLmgkhVmspdJLENv6uGWrTL/MQX2TN7Yz9s= github.com/molecula/ext v0.0.0-20191202195653-240f38a75171 h1:4VK7u/RM+54Yaz8aRB9vIaDSnbKi3M0NQYg5tsZvOT4= github.com/molecula/ext v0.0.0-20191202195653-240f38a75171/go.mod h1:r6EIj0GH8dx5xxFLW6Voi1/mX3wXOUkJu6AoEE/xvGQ= +github.com/molecula/ext v0.0.0-20200103203257-8a458a73e8c2 h1:XOImsA5XhGklFj8Y0TxSm1qWZzEwYxom2JOXiu9GMq0= +github.com/molecula/ext v0.0.0-20200103203257-8a458a73e8c2/go.mod h1:r6EIj0GH8dx5xxFLW6Voi1/mX3wXOUkJu6AoEE/xvGQ= github.com/molecula/extensions v0.0.0-20191218165536-562244600fd4 h1:mDB/dicofRVFuRYcCVPk+JBiVKXlfbzMahuqHvrYqu4= github.com/molecula/extensions v0.0.0-20191218165536-562244600fd4/go.mod h1:QQgN5OFjuBAi4Q2UYVMzfvi4k9yvg/qqC+MNFB4I9JI= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= diff --git a/handler.go b/handler.go index 19fcbac44..cc3625c1a 100644 --- a/handler.go +++ b/handler.go @@ -116,11 +116,12 @@ type ImportValueRequest struct { Field string // if Shard is MaxUint64 (an impossible shard value), this // indicates that the column IDs may come from multiple shards. - Shard uint64 - ColumnIDs []uint64 - ColumnKeys []string - Values []int64 - FloatValues []float64 + Shard uint64 + ColumnIDs []uint64 + ColumnKeys []string + Values []int64 + FloatValues []float64 + StringValues []string } func (ivr *ImportValueRequest) Len() int { return len(ivr.ColumnIDs) } @@ -134,15 +135,26 @@ func (ivr *ImportValueRequest) Swap(i, j int) { } } -func (i *ImportValueRequest) Validate() error { - if i.Index == "" || i.Field == "" { - return errors.Errorf("index and field required, but got '%s' and '%s'", i.Index, i.Field) +// Validate ensures that the payload of the request is valid. +func (ivr *ImportValueRequest) Validate() error { + if ivr.Index == "" || ivr.Field == "" { + return errors.Errorf("index and field required, but got '%s' and '%s'", ivr.Index, ivr.Field) } - if len(i.ColumnIDs) != 0 && len(i.ColumnKeys) != 0 { + if len(ivr.ColumnIDs) != 0 && len(ivr.ColumnKeys) != 0 { return errors.Errorf("must pass either column ids or keys, but not both") } - if len(i.Values) != 0 && len(i.FloatValues) != 0 { - return errors.Errorf("must pass ints or floats but not both") + var valueSetCount int + if len(ivr.Values) != 0 { + valueSetCount++ + } + if len(ivr.FloatValues) != 0 { + valueSetCount++ + } + if len(ivr.StringValues) != 0 { + valueSetCount++ + } + if valueSetCount > 1 { + return errors.Errorf("must pass ints, floats, or strings but not multiple") } return nil } diff --git a/http/handler.go b/http/handler.go index ba7877222..1ea09cd09 100644 --- a/http/handler.go +++ b/http/handler.go @@ -807,6 +807,9 @@ func (h *Handler) handlePostField(w http.ResponseWriter, r *http.Request) { fos = append(fos, pilosa.OptFieldKeys()) } } + if req.Options.ForeignIndex != nil { + fos = append(fos, pilosa.OptFieldForeignIndex(*req.Options.ForeignIndex)) + } _, err = h.api.CreateField(r.Context(), indexName, fieldName, fos...) if _, ok := err.(pilosa.BadRequestError); ok { @@ -832,6 +835,7 @@ type fieldOptions struct { TimeQuantum *pilosa.TimeQuantum `json:"timeQuantum,omitempty"` Keys *bool `json:"keys,omitempty"` NoStandardView bool `json:"noStandardView,omitempty"` + ForeignIndex *string `json:"foreignIndex,omitempty"` } func (o *fieldOptions) validate() error { @@ -859,6 +863,8 @@ func (o *fieldOptions) validate() error { return pilosa.NewBadRequestError(errors.New("max does not apply to field type set")) } else if o.TimeQuantum != nil { return pilosa.NewBadRequestError(errors.New("timeQuantum does not apply to field type set")) + } else if o.ForeignIndex != nil { + return pilosa.NewBadRequestError(errors.New("set field cannot be a foreign key")) } case pilosa.FieldTypeInt, pilosa.FieldTypeDecimal: if o.CacheType != nil { @@ -867,6 +873,8 @@ func (o *fieldOptions) validate() error { return pilosa.NewBadRequestError(errors.New("cacheSize does not apply to field type int")) } else if o.TimeQuantum != nil { return pilosa.NewBadRequestError(errors.New("timeQuantum does not apply to field type int")) + } else if o.ForeignIndex != nil && o.Type == pilosa.FieldTypeDecimal { + return pilosa.NewBadRequestError(errors.New("decimal field cannot be a foreign key")) } case pilosa.FieldTypeTime: if o.CacheType != nil { @@ -879,6 +887,8 @@ func (o *fieldOptions) validate() error { return pilosa.NewBadRequestError(errors.New("max does not apply to field type time")) } else if o.TimeQuantum == nil { return pilosa.NewBadRequestError(errors.New("timeQuantum is required for field type time")) + } else if o.ForeignIndex != nil { + return pilosa.NewBadRequestError(errors.New("time field cannot be a foreign key")) } case pilosa.FieldTypeMutex: if o.CacheType == nil { @@ -893,6 +903,8 @@ func (o *fieldOptions) validate() error { return pilosa.NewBadRequestError(errors.New("max does not apply to field type mutex")) } else if o.TimeQuantum != nil { return pilosa.NewBadRequestError(errors.New("timeQuantum does not apply to field type mutex")) + } else if o.ForeignIndex != nil { + return pilosa.NewBadRequestError(errors.New("mutex field cannot be a foreign key")) } case pilosa.FieldTypeBool: if o.CacheType != nil { @@ -907,6 +919,8 @@ func (o *fieldOptions) validate() error { return pilosa.NewBadRequestError(errors.New("timeQuantum does not apply to field type bool")) } else if o.Keys != nil { return pilosa.NewBadRequestError(errors.New("keys does not apply to field type bool")) + } else if o.ForeignIndex != nil { + return pilosa.NewBadRequestError(errors.New("bool field cannot be a foreign key")) } default: return errors.Errorf("invalid field type: %s", o.Type) diff --git a/index.go b/index.go index c96e3bd5f..a6a9e3070 100644 --- a/index.go +++ b/index.go @@ -432,6 +432,9 @@ func (i *Index) createField(name string, opt FieldOptions) (*Field, error) { } // Apply field options. + // This is already happening in f.Open() just before this, but in + // that case, the options being applied are those read from the meta + // file on disk. if err := f.applyOptions(opt); err != nil { f.Close() return nil, errors.Wrap(err, "applying options") diff --git a/internal/private.pb.go b/internal/private.pb.go index d42e410cf..f64f9b5b7 100644 --- a/internal/private.pb.go +++ b/internal/private.pb.go @@ -32,7 +32,7 @@ func (m *IndexMeta) Reset() { *m = IndexMeta{} } func (m *IndexMeta) String() string { return proto.CompactTextString(m) } func (*IndexMeta) ProtoMessage() {} func (*IndexMeta) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{0} + return fileDescriptor_private_54a82f4803638cdd, []int{0} } func (m *IndexMeta) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -87,6 +87,7 @@ type FieldOptions struct { Base int64 `protobuf:"varint,13,opt,name=Base,proto3" json:"Base,omitempty"` BitDepth uint64 `protobuf:"varint,14,opt,name=BitDepth,proto3" json:"BitDepth,omitempty"` Scale int64 `protobuf:"varint,15,opt,name=Scale,proto3" json:"Scale,omitempty"` + ForeignIndex string `protobuf:"bytes,16,opt,name=ForeignIndex,proto3" json:"ForeignIndex,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -96,7 +97,7 @@ func (m *FieldOptions) Reset() { *m = FieldOptions{} } func (m *FieldOptions) String() string { return proto.CompactTextString(m) } func (*FieldOptions) ProtoMessage() {} func (*FieldOptions) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{1} + return fileDescriptor_private_54a82f4803638cdd, []int{1} } func (m *FieldOptions) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -202,6 +203,13 @@ func (m *FieldOptions) GetScale() int64 { return 0 } +func (m *FieldOptions) GetForeignIndex() string { + if m != nil { + return m.ForeignIndex + } + return "" +} + type ImportResponse struct { Err string `protobuf:"bytes,1,opt,name=Err,proto3" json:"Err,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -213,7 +221,7 @@ func (m *ImportResponse) Reset() { *m = ImportResponse{} } func (m *ImportResponse) String() string { return proto.CompactTextString(m) } func (*ImportResponse) ProtoMessage() {} func (*ImportResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{2} + return fileDescriptor_private_54a82f4803638cdd, []int{2} } func (m *ImportResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -264,7 +272,7 @@ func (m *BlockDataRequest) Reset() { *m = BlockDataRequest{} } func (m *BlockDataRequest) String() string { return proto.CompactTextString(m) } func (*BlockDataRequest) ProtoMessage() {} func (*BlockDataRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{3} + return fileDescriptor_private_54a82f4803638cdd, []int{3} } func (m *BlockDataRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -340,7 +348,7 @@ func (m *BlockDataResponse) Reset() { *m = BlockDataResponse{} } func (m *BlockDataResponse) String() string { return proto.CompactTextString(m) } func (*BlockDataResponse) ProtoMessage() {} func (*BlockDataResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{4} + return fileDescriptor_private_54a82f4803638cdd, []int{4} } func (m *BlockDataResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -394,7 +402,7 @@ func (m *Cache) Reset() { *m = Cache{} } func (m *Cache) String() string { return proto.CompactTextString(m) } func (*Cache) ProtoMessage() {} func (*Cache) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{5} + return fileDescriptor_private_54a82f4803638cdd, []int{5} } func (m *Cache) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -441,7 +449,7 @@ func (m *MaxShards) Reset() { *m = MaxShards{} } func (m *MaxShards) String() string { return proto.CompactTextString(m) } func (*MaxShards) ProtoMessage() {} func (*MaxShards) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{6} + return fileDescriptor_private_54a82f4803638cdd, []int{6} } func (m *MaxShards) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -490,7 +498,7 @@ func (m *CreateShardMessage) Reset() { *m = CreateShardMessage{} } func (m *CreateShardMessage) String() string { return proto.CompactTextString(m) } func (*CreateShardMessage) ProtoMessage() {} func (*CreateShardMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{7} + return fileDescriptor_private_54a82f4803638cdd, []int{7} } func (m *CreateShardMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -551,7 +559,7 @@ func (m *DeleteIndexMessage) Reset() { *m = DeleteIndexMessage{} } func (m *DeleteIndexMessage) String() string { return proto.CompactTextString(m) } func (*DeleteIndexMessage) ProtoMessage() {} func (*DeleteIndexMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{8} + return fileDescriptor_private_54a82f4803638cdd, []int{8} } func (m *DeleteIndexMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -599,7 +607,7 @@ func (m *CreateIndexMessage) Reset() { *m = CreateIndexMessage{} } func (m *CreateIndexMessage) String() string { return proto.CompactTextString(m) } func (*CreateIndexMessage) ProtoMessage() {} func (*CreateIndexMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{9} + return fileDescriptor_private_54a82f4803638cdd, []int{9} } func (m *CreateIndexMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -655,7 +663,7 @@ func (m *CreateFieldMessage) Reset() { *m = CreateFieldMessage{} } func (m *CreateFieldMessage) String() string { return proto.CompactTextString(m) } func (*CreateFieldMessage) ProtoMessage() {} func (*CreateFieldMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{10} + return fileDescriptor_private_54a82f4803638cdd, []int{10} } func (m *CreateFieldMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -717,7 +725,7 @@ func (m *DeleteFieldMessage) Reset() { *m = DeleteFieldMessage{} } func (m *DeleteFieldMessage) String() string { return proto.CompactTextString(m) } func (*DeleteFieldMessage) ProtoMessage() {} func (*DeleteFieldMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{11} + return fileDescriptor_private_54a82f4803638cdd, []int{11} } func (m *DeleteFieldMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -773,7 +781,7 @@ func (m *DeleteAvailableShardMessage) Reset() { *m = DeleteAvailableShar func (m *DeleteAvailableShardMessage) String() string { return proto.CompactTextString(m) } func (*DeleteAvailableShardMessage) ProtoMessage() {} func (*DeleteAvailableShardMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{12} + return fileDescriptor_private_54a82f4803638cdd, []int{12} } func (m *DeleteAvailableShardMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -836,7 +844,7 @@ func (m *Field) Reset() { *m = Field{} } func (m *Field) String() string { return proto.CompactTextString(m) } func (*Field) ProtoMessage() {} func (*Field) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{13} + return fileDescriptor_private_54a82f4803638cdd, []int{13} } func (m *Field) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -897,7 +905,7 @@ func (m *Schema) Reset() { *m = Schema{} } func (m *Schema) String() string { return proto.CompactTextString(m) } func (*Schema) ProtoMessage() {} func (*Schema) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{14} + return fileDescriptor_private_54a82f4803638cdd, []int{14} } func (m *Schema) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -945,7 +953,7 @@ func (m *Index) Reset() { *m = Index{} } func (m *Index) String() string { return proto.CompactTextString(m) } func (*Index) ProtoMessage() {} func (*Index) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{15} + return fileDescriptor_private_54a82f4803638cdd, []int{15} } func (m *Index) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1001,7 +1009,7 @@ func (m *URI) Reset() { *m = URI{} } func (m *URI) String() string { return proto.CompactTextString(m) } func (*URI) ProtoMessage() {} func (*URI) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{16} + return fileDescriptor_private_54a82f4803638cdd, []int{16} } func (m *URI) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1065,7 +1073,7 @@ func (m *Node) Reset() { *m = Node{} } func (m *Node) String() string { return proto.CompactTextString(m) } func (*Node) ProtoMessage() {} func (*Node) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{17} + return fileDescriptor_private_54a82f4803638cdd, []int{17} } func (m *Node) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1134,7 +1142,7 @@ func (m *NodeStateMessage) Reset() { *m = NodeStateMessage{} } func (m *NodeStateMessage) String() string { return proto.CompactTextString(m) } func (*NodeStateMessage) ProtoMessage() {} func (*NodeStateMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{18} + return fileDescriptor_private_54a82f4803638cdd, []int{18} } func (m *NodeStateMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1189,7 +1197,7 @@ func (m *NodeEventMessage) Reset() { *m = NodeEventMessage{} } func (m *NodeEventMessage) String() string { return proto.CompactTextString(m) } func (*NodeEventMessage) ProtoMessage() {} func (*NodeEventMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{19} + return fileDescriptor_private_54a82f4803638cdd, []int{19} } func (m *NodeEventMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1245,7 +1253,7 @@ func (m *NodeStatus) Reset() { *m = NodeStatus{} } func (m *NodeStatus) String() string { return proto.CompactTextString(m) } func (*NodeStatus) ProtoMessage() {} func (*NodeStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{20} + return fileDescriptor_private_54a82f4803638cdd, []int{20} } func (m *NodeStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1307,7 +1315,7 @@ func (m *IndexStatus) Reset() { *m = IndexStatus{} } func (m *IndexStatus) String() string { return proto.CompactTextString(m) } func (*IndexStatus) ProtoMessage() {} func (*IndexStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{21} + return fileDescriptor_private_54a82f4803638cdd, []int{21} } func (m *IndexStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1362,7 +1370,7 @@ func (m *FieldStatus) Reset() { *m = FieldStatus{} } func (m *FieldStatus) String() string { return proto.CompactTextString(m) } func (*FieldStatus) ProtoMessage() {} func (*FieldStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{22} + return fileDescriptor_private_54a82f4803638cdd, []int{22} } func (m *FieldStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1418,7 +1426,7 @@ func (m *ClusterStatus) Reset() { *m = ClusterStatus{} } func (m *ClusterStatus) String() string { return proto.CompactTextString(m) } func (*ClusterStatus) ProtoMessage() {} func (*ClusterStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{23} + return fileDescriptor_private_54a82f4803638cdd, []int{23} } func (m *ClusterStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1482,7 +1490,7 @@ func (m *BSIGroup) Reset() { *m = BSIGroup{} } func (m *BSIGroup) String() string { return proto.CompactTextString(m) } func (*BSIGroup) ProtoMessage() {} func (*BSIGroup) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{24} + return fileDescriptor_private_54a82f4803638cdd, []int{24} } func (m *BSIGroup) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1552,7 +1560,7 @@ func (m *CreateViewMessage) Reset() { *m = CreateViewMessage{} } func (m *CreateViewMessage) String() string { return proto.CompactTextString(m) } func (*CreateViewMessage) ProtoMessage() {} func (*CreateViewMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{25} + return fileDescriptor_private_54a82f4803638cdd, []int{25} } func (m *CreateViewMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1615,7 +1623,7 @@ func (m *DeleteViewMessage) Reset() { *m = DeleteViewMessage{} } func (m *DeleteViewMessage) String() string { return proto.CompactTextString(m) } func (*DeleteViewMessage) ProtoMessage() {} func (*DeleteViewMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{26} + return fileDescriptor_private_54a82f4803638cdd, []int{26} } func (m *DeleteViewMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1681,7 +1689,7 @@ func (m *ResizeInstruction) Reset() { *m = ResizeInstruction{} } func (m *ResizeInstruction) String() string { return proto.CompactTextString(m) } func (*ResizeInstruction) ProtoMessage() {} func (*ResizeInstruction) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{27} + return fileDescriptor_private_54a82f4803638cdd, []int{27} } func (m *ResizeInstruction) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1767,7 +1775,7 @@ func (m *ResizeSource) Reset() { *m = ResizeSource{} } func (m *ResizeSource) String() string { return proto.CompactTextString(m) } func (*ResizeSource) ProtoMessage() {} func (*ResizeSource) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{28} + return fileDescriptor_private_54a82f4803638cdd, []int{28} } func (m *ResizeSource) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1844,7 +1852,7 @@ func (m *ResizeInstructionComplete) Reset() { *m = ResizeInstructionComp func (m *ResizeInstructionComplete) String() string { return proto.CompactTextString(m) } func (*ResizeInstructionComplete) ProtoMessage() {} func (*ResizeInstructionComplete) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{29} + return fileDescriptor_private_54a82f4803638cdd, []int{29} } func (m *ResizeInstructionComplete) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1905,7 +1913,7 @@ func (m *SetCoordinatorMessage) Reset() { *m = SetCoordinatorMessage{} } func (m *SetCoordinatorMessage) String() string { return proto.CompactTextString(m) } func (*SetCoordinatorMessage) ProtoMessage() {} func (*SetCoordinatorMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{30} + return fileDescriptor_private_54a82f4803638cdd, []int{30} } func (m *SetCoordinatorMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1952,7 +1960,7 @@ func (m *UpdateCoordinatorMessage) Reset() { *m = UpdateCoordinatorMessa func (m *UpdateCoordinatorMessage) String() string { return proto.CompactTextString(m) } func (*UpdateCoordinatorMessage) ProtoMessage() {} func (*UpdateCoordinatorMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{31} + return fileDescriptor_private_54a82f4803638cdd, []int{31} } func (m *UpdateCoordinatorMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2000,7 +2008,7 @@ func (m *Topology) Reset() { *m = Topology{} } func (m *Topology) String() string { return proto.CompactTextString(m) } func (*Topology) ProtoMessage() {} func (*Topology) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{32} + return fileDescriptor_private_54a82f4803638cdd, []int{32} } func (m *Topology) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2053,7 +2061,7 @@ func (m *RecalculateCaches) Reset() { *m = RecalculateCaches{} } func (m *RecalculateCaches) String() string { return proto.CompactTextString(m) } func (*RecalculateCaches) ProtoMessage() {} func (*RecalculateCaches) Descriptor() ([]byte, []int) { - return fileDescriptor_private_e6d12fddb5948a73, []int{33} + return fileDescriptor_private_54a82f4803638cdd, []int{33} } func (m *RecalculateCaches) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2243,6 +2251,14 @@ func (m *FieldOptions) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintPrivate(dAtA, i, uint64(m.Scale)) } + if len(m.ForeignIndex) > 0 { + dAtA[i] = 0x82 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintPrivate(dAtA, i, uint64(len(m.ForeignIndex))) + i += copy(dAtA[i:], m.ForeignIndex) + } if m.XXX_unrecognized != nil { i += copy(dAtA[i:], m.XXX_unrecognized) } @@ -3625,6 +3641,10 @@ func (m *FieldOptions) Size() (n int) { if m.Scale != 0 { n += 1 + sovPrivate(uint64(m.Scale)) } + l = len(m.ForeignIndex) + if l > 0 { + n += 2 + l + sovPrivate(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -4725,6 +4745,35 @@ func (m *FieldOptions) Unmarshal(dAtA []byte) error { break } } + case 16: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ForeignIndex", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPrivate + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthPrivate + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ForeignIndex = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipPrivate(dAtA[iNdEx:]) @@ -8982,82 +9031,83 @@ var ( ErrIntOverflowPrivate = fmt.Errorf("proto: integer overflow") ) -func init() { proto.RegisterFile("private.proto", fileDescriptor_private_e6d12fddb5948a73) } +func init() { proto.RegisterFile("private.proto", fileDescriptor_private_54a82f4803638cdd) } -var fileDescriptor_private_e6d12fddb5948a73 = []byte{ - // 1174 bytes of a gzipped FileDescriptorProto +var fileDescriptor_private_54a82f4803638cdd = []byte{ + // 1192 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0xdb, 0x6e, 0x1b, 0x45, - 0x18, 0x66, 0x0f, 0x71, 0xec, 0xdf, 0x71, 0x0e, 0xdb, 0x36, 0x6c, 0x0b, 0x0a, 0x66, 0x54, 0x51, - 0x53, 0x89, 0x50, 0xb5, 0x5c, 0x70, 0xaa, 0x54, 0x1c, 0x87, 0xb2, 0x94, 0x84, 0x32, 0x4e, 0x72, - 0xc7, 0xc5, 0xc4, 0x1e, 0x35, 0xab, 0xac, 0x77, 0xcc, 0xee, 0x6c, 0x12, 0xf7, 0x82, 0x5b, 0x90, - 0x78, 0x01, 0x9e, 0xa0, 0xcf, 0xc2, 0x25, 0x8f, 0x80, 0xc2, 0x8b, 0xa0, 0xf9, 0x67, 0xf6, 0x60, - 0xc7, 0x21, 0x51, 0xe0, 0x6e, 0xfe, 0xd3, 0xf7, 0x9f, 0x7f, 0xaf, 0xa1, 0x35, 0x4e, 0xc2, 0x13, - 0x26, 0xf9, 0xe6, 0x38, 0x11, 0x52, 0x78, 0xf5, 0x30, 0x96, 0x3c, 0x89, 0x59, 0x44, 0x9e, 0x43, - 0x23, 0x88, 0x87, 0xfc, 0x6c, 0x87, 0x4b, 0xe6, 0x79, 0xe0, 0xbe, 0xe0, 0x93, 0xd4, 0x77, 0xda, - 0x56, 0xa7, 0x4e, 0xf1, 0xed, 0x7d, 0x00, 0xcb, 0x7b, 0x09, 0x1b, 0x1c, 0x6f, 0x9f, 0x85, 0xa9, - 0xe4, 0xf1, 0x80, 0xfb, 0x2e, 0x4a, 0x67, 0xb8, 0xe4, 0x8d, 0x0d, 0x4b, 0x5f, 0x87, 0x3c, 0x1a, - 0x7e, 0x3f, 0x96, 0xa1, 0x88, 0x53, 0xef, 0x5d, 0x68, 0x6c, 0xb1, 0xc1, 0x11, 0xdf, 0x9b, 0x8c, - 0x39, 0x22, 0x36, 0x68, 0xc9, 0x28, 0xa4, 0xfd, 0xf0, 0xb5, 0x46, 0x6c, 0xd1, 0x92, 0xe1, 0xb5, - 0xa1, 0xb9, 0x17, 0x8e, 0xf8, 0x0f, 0x19, 0x8b, 0x65, 0x36, 0xf2, 0x17, 0xd0, 0xba, 0xca, 0x52, - 0xa1, 0x22, 0x70, 0x1d, 0x45, 0xf8, 0xf6, 0x56, 0xc1, 0xd9, 0x09, 0x63, 0xbf, 0xd1, 0xb6, 0x3a, - 0x0e, 0x55, 0x4f, 0xe4, 0xb0, 0x33, 0x1f, 0x0c, 0x87, 0x9d, 0x15, 0x29, 0x36, 0xa7, 0x53, 0xdc, - 0x15, 0x7d, 0xc9, 0xe2, 0x21, 0x4b, 0x86, 0x07, 0x21, 0x3f, 0xf5, 0x97, 0x74, 0x8a, 0xd3, 0x5c, - 0x65, 0xdb, 0x65, 0x29, 0xf7, 0x5b, 0x08, 0x87, 0x6f, 0xef, 0x1e, 0xd4, 0xbb, 0xa1, 0xec, 0xf1, - 0xb1, 0x3c, 0xf2, 0x97, 0xdb, 0x56, 0xc7, 0xa5, 0x05, 0xed, 0xdd, 0x86, 0x85, 0xfe, 0x80, 0x45, - 0xdc, 0x5f, 0x41, 0x03, 0x4d, 0x10, 0x02, 0xcb, 0xc1, 0x68, 0x2c, 0x12, 0x49, 0x79, 0x3a, 0x16, - 0x71, 0x8a, 0x71, 0x6f, 0x27, 0x89, 0x6f, 0x61, 0x2a, 0xea, 0x49, 0x7e, 0x86, 0xd5, 0x6e, 0x24, - 0x06, 0xc7, 0x3d, 0x26, 0x19, 0xe5, 0x3f, 0x65, 0x3c, 0x95, 0x0a, 0x0d, 0x3b, 0x65, 0xf4, 0x34, - 0xa1, 0xb8, 0x58, 0x75, 0xdf, 0xd6, 0x5c, 0x24, 0x14, 0x17, 0xed, 0xb1, 0xee, 0x2e, 0xd5, 0x04, - 0xc6, 0x73, 0xc4, 0x92, 0x21, 0xd6, 0xdb, 0xa5, 0x9a, 0x50, 0x59, 0x61, 0xce, 0xba, 0xc8, 0xf8, - 0x26, 0x01, 0xac, 0x55, 0xfc, 0x9b, 0x30, 0xd7, 0xa1, 0x46, 0xc5, 0x69, 0xd0, 0x4b, 0x7d, 0xab, - 0xed, 0x74, 0x5c, 0x6a, 0x28, 0x6c, 0xa5, 0x88, 0xb2, 0x51, 0xac, 0x44, 0x36, 0x8a, 0x4a, 0x06, - 0xb9, 0x0b, 0x0b, 0xd8, 0x57, 0x95, 0x65, 0x69, 0xab, 0x9e, 0xe4, 0x17, 0x0b, 0x1a, 0x3b, 0xec, - 0x0c, 0xc3, 0x48, 0xbd, 0xa7, 0x50, 0xcf, 0xab, 0x8d, 0x4a, 0xcd, 0xc7, 0xef, 0x6f, 0xe6, 0x63, - 0xba, 0x59, 0xa8, 0x6d, 0xe6, 0x3a, 0xdb, 0xb1, 0x4c, 0x26, 0xb4, 0x30, 0xb9, 0xf7, 0x05, 0xb4, - 0xa6, 0x44, 0xca, 0xdf, 0x31, 0x9f, 0xe4, 0x55, 0x3d, 0xe6, 0x13, 0x95, 0xff, 0x09, 0x8b, 0x32, - 0x8e, 0xb5, 0x72, 0xa9, 0x26, 0x3e, 0xb7, 0x3f, 0xb5, 0xc8, 0x01, 0x78, 0x5b, 0x09, 0x67, 0x92, - 0xa3, 0x93, 0x1d, 0x9e, 0xa6, 0xec, 0x15, 0xbf, 0xbc, 0xe2, 0xba, 0x8a, 0x76, 0xb5, 0x8a, 0x45, - 0x1f, 0x9c, 0x4a, 0x1f, 0xc8, 0x43, 0xf0, 0x7a, 0x3c, 0xe2, 0x92, 0x9b, 0x1d, 0xfb, 0x17, 0x5c, - 0xd2, 0xcf, 0x63, 0xb8, 0x5a, 0xd7, 0x7b, 0x00, 0xae, 0x5a, 0x58, 0x0c, 0xa1, 0xf9, 0xf8, 0x56, - 0x59, 0xa7, 0x62, 0x97, 0x29, 0x2a, 0x90, 0x28, 0x07, 0xc5, 0x78, 0xae, 0x4c, 0x6c, 0xce, 0x28, - 0x3d, 0x34, 0xae, 0x1c, 0x74, 0xb5, 0x5e, 0xba, 0xaa, 0x2e, 0xbb, 0xf1, 0xf6, 0x2c, 0x4f, 0xf7, - 0xa6, 0xde, 0xc8, 0x00, 0xde, 0xd1, 0x08, 0x5f, 0x9d, 0xb0, 0x30, 0x62, 0x87, 0xd1, 0x35, 0x3b, - 0x32, 0x27, 0x70, 0x1f, 0x16, 0xd1, 0x36, 0xe8, 0x99, 0x2d, 0xc8, 0x49, 0xf2, 0xa3, 0xd1, 0x57, - 0xa3, 0xbf, 0xcb, 0x46, 0xdc, 0xa0, 0xe1, 0xbb, 0xc8, 0xd7, 0xbe, 0x3a, 0x5f, 0xe5, 0x58, 0xad, - 0x8b, 0x3a, 0x98, 0x8e, 0x72, 0x8c, 0x04, 0x79, 0x02, 0xb5, 0xfe, 0xe0, 0x88, 0x8f, 0x98, 0xf7, - 0x21, 0x2c, 0x62, 0x84, 0x3c, 0x35, 0x13, 0xbd, 0x32, 0xd3, 0x29, 0x9a, 0xcb, 0x49, 0xcf, 0x64, - 0x36, 0x37, 0xa6, 0x07, 0x50, 0x43, 0xef, 0xa9, 0xef, 0xce, 0xc2, 0x20, 0x9f, 0x1a, 0x31, 0xd9, - 0x06, 0x67, 0x9f, 0x06, 0x6a, 0x53, 0x31, 0x82, 0x1c, 0xc5, 0x50, 0x0a, 0xfb, 0x1b, 0x91, 0x4a, - 0x53, 0x27, 0x7c, 0x2b, 0xde, 0x4b, 0x91, 0x48, 0xac, 0x51, 0x8b, 0xe2, 0x9b, 0xa4, 0xe0, 0xee, - 0x8a, 0x21, 0xf7, 0x96, 0xc1, 0x0e, 0x7a, 0x06, 0xc3, 0x0e, 0x7a, 0xde, 0x7b, 0x08, 0x6f, 0x4a, - 0xd3, 0x2a, 0x83, 0xd8, 0xa7, 0x01, 0x45, 0xc7, 0xf7, 0xa1, 0x15, 0xa4, 0x5b, 0x42, 0x24, 0xc3, - 0x30, 0x66, 0x52, 0x24, 0xe6, 0x97, 0x64, 0x9a, 0x89, 0x1b, 0x24, 0x99, 0xd4, 0x77, 0xbf, 0x41, - 0x35, 0x41, 0x9e, 0xc1, 0xaa, 0x72, 0x8a, 0x44, 0xde, 0xef, 0x75, 0xa8, 0x29, 0x5e, 0x11, 0x84, - 0xa1, 0x4a, 0x04, 0xbb, 0x8a, 0xf0, 0x9d, 0x46, 0xd8, 0x3e, 0xe1, 0xb1, 0xac, 0x4c, 0x0c, 0xd2, - 0x08, 0xd0, 0xa2, 0x9a, 0xf0, 0x88, 0x4e, 0xd0, 0x64, 0xb2, 0x5c, 0x66, 0xa2, 0xb8, 0x14, 0x65, - 0xe4, 0x37, 0x0b, 0x20, 0x0f, 0x28, 0x4b, 0x0b, 0x13, 0xeb, 0x72, 0x13, 0xaf, 0x93, 0x77, 0xde, - 0x6c, 0xcb, 0x6a, 0xa9, 0xa5, 0xf9, 0x34, 0x9f, 0x8c, 0x8f, 0xcb, 0xc9, 0xd0, 0x2d, 0xbd, 0x33, - 0x33, 0x19, 0xda, 0x6b, 0x39, 0x1f, 0x2f, 0xa1, 0x59, 0xe1, 0xcf, 0x9d, 0x92, 0x8f, 0x8a, 0x29, - 0xb1, 0x67, 0x21, 0x91, 0x6f, 0x20, 0xf3, 0x59, 0x79, 0x01, 0xcd, 0x0a, 0x7b, 0x2e, 0x62, 0x07, - 0x56, 0xa6, 0xf7, 0x30, 0xbf, 0xef, 0xb3, 0x6c, 0x12, 0x42, 0x6b, 0x2b, 0xca, 0x52, 0xc9, 0x13, - 0x03, 0xa7, 0x7e, 0x14, 0x34, 0xa3, 0x68, 0x5e, 0xc9, 0x98, 0xdf, 0x3f, 0xef, 0x3e, 0x2c, 0xa8, - 0x32, 0xea, 0x75, 0xba, 0x58, 0x63, 0x2d, 0x24, 0x07, 0x50, 0xef, 0xf6, 0x83, 0xe7, 0x89, 0xc8, - 0xc6, 0x73, 0x83, 0xce, 0xbf, 0x0c, 0xec, 0x8b, 0x5f, 0x06, 0xce, 0x85, 0x2f, 0x03, 0xb7, 0xf8, - 0x32, 0x20, 0x7d, 0x58, 0xd3, 0xa7, 0x52, 0x6d, 0xf1, 0x4d, 0x0e, 0x4e, 0xfe, 0x43, 0xea, 0x54, - 0x7e, 0x48, 0xfb, 0xb0, 0xa6, 0xef, 0xd9, 0xff, 0x09, 0xfa, 0xc6, 0x86, 0x35, 0xca, 0xd3, 0xf0, - 0x35, 0x0f, 0xe2, 0x54, 0x26, 0xd9, 0x40, 0xdd, 0x24, 0x65, 0xff, 0xad, 0x38, 0x34, 0xd5, 0x76, - 0xa8, 0x26, 0xae, 0x33, 0xe9, 0xde, 0x23, 0x68, 0xce, 0xee, 0xec, 0x45, 0xd5, 0xaa, 0x8a, 0xf7, - 0x08, 0x16, 0xfb, 0x22, 0x4b, 0x06, 0xc5, 0xf8, 0x56, 0xee, 0xa4, 0x8e, 0x4c, 0x8b, 0x69, 0xae, - 0xe6, 0x3d, 0x9d, 0x19, 0x10, 0xbf, 0x86, 0x5e, 0xde, 0x2e, 0xed, 0xa6, 0xc4, 0x74, 0x66, 0x9c, - 0x3e, 0xa9, 0xee, 0xa2, 0xbf, 0x88, 0xb6, 0xb7, 0xa7, 0x23, 0x34, 0x86, 0x15, 0x3d, 0xf2, 0xab, - 0x05, 0x4b, 0xd5, 0x70, 0xae, 0xb5, 0xc4, 0x45, 0x77, 0xec, 0xb9, 0xdd, 0x71, 0xe6, 0x75, 0xc7, - 0x2d, 0xbb, 0x53, 0x7e, 0x1f, 0x2c, 0x54, 0xbe, 0x0f, 0xc8, 0x31, 0xdc, 0xbd, 0xd0, 0xb2, 0x2d, - 0x31, 0x1a, 0xab, 0xd9, 0xf8, 0x0f, 0xad, 0x53, 0xe7, 0x2d, 0x49, 0x4c, 0xd3, 0x1a, 0x54, 0x13, - 0xe4, 0x33, 0xb8, 0xd3, 0xe7, 0xb2, 0xd2, 0xb0, 0x7c, 0xf2, 0xda, 0xe0, 0xec, 0xf2, 0xd3, 0x4b, - 0xd2, 0x57, 0x22, 0xf2, 0x25, 0xf8, 0xfb, 0xe3, 0x21, 0x93, 0xfc, 0x46, 0xd6, 0x5d, 0xa8, 0xef, - 0x89, 0xb1, 0x88, 0xc4, 0xab, 0xc9, 0x15, 0x17, 0xc0, 0x87, 0x45, 0x7d, 0xcb, 0xf5, 0x49, 0x69, - 0xd0, 0x9c, 0x24, 0xb7, 0xd4, 0x70, 0x0f, 0x58, 0x34, 0xc8, 0x22, 0x15, 0x86, 0xfa, 0x76, 0x4c, - 0xbb, 0xab, 0x7f, 0x9c, 0x6f, 0x58, 0x7f, 0x9e, 0x6f, 0x58, 0x7f, 0x9d, 0x6f, 0x58, 0xbf, 0xff, - 0xbd, 0xf1, 0xd6, 0x61, 0x0d, 0xff, 0xc9, 0x3c, 0xf9, 0x27, 0x00, 0x00, 0xff, 0xff, 0xb4, 0x70, - 0x9a, 0xfe, 0xda, 0x0c, 0x00, 0x00, + 0x18, 0x66, 0x0f, 0x71, 0xec, 0xdf, 0x71, 0xe2, 0x6c, 0xdb, 0xb0, 0x2d, 0x28, 0x98, 0x51, 0x45, + 0x4d, 0x25, 0x42, 0xd5, 0x72, 0xc1, 0xa9, 0x52, 0x71, 0x9c, 0x96, 0xa5, 0x24, 0x94, 0x71, 0x92, + 0x3b, 0x2e, 0x26, 0xf6, 0x28, 0x59, 0x65, 0xbd, 0x63, 0x76, 0xc7, 0x49, 0xdc, 0x0b, 0x6e, 0x41, + 0xe2, 0x05, 0x78, 0x02, 0x9e, 0x05, 0x71, 0xc5, 0x23, 0xa0, 0xf0, 0x22, 0x68, 0xfe, 0x99, 0x3d, + 0xd8, 0x71, 0x48, 0x14, 0x7a, 0x37, 0xff, 0xf9, 0xf0, 0xfd, 0xff, 0xec, 0x2c, 0x34, 0x46, 0x49, + 0x78, 0xc2, 0x24, 0xdf, 0x18, 0x25, 0x42, 0x0a, 0xaf, 0x1a, 0xc6, 0x92, 0x27, 0x31, 0x8b, 0xc8, + 0x0b, 0xa8, 0x05, 0xf1, 0x80, 0x9f, 0x6d, 0x73, 0xc9, 0x3c, 0x0f, 0xdc, 0x97, 0x7c, 0x92, 0xfa, + 0x4e, 0xcb, 0x6a, 0x57, 0x29, 0x9e, 0xbd, 0x0f, 0x60, 0x79, 0x37, 0x61, 0xfd, 0xe3, 0xad, 0xb3, + 0x30, 0x95, 0x3c, 0xee, 0x73, 0xdf, 0x45, 0xe9, 0x0c, 0x97, 0xfc, 0x69, 0xc3, 0xd2, 0xf3, 0x90, + 0x47, 0x83, 0xef, 0x46, 0x32, 0x14, 0x71, 0xea, 0xbd, 0x0b, 0xb5, 0x4d, 0xd6, 0x3f, 0xe2, 0xbb, + 0x93, 0x11, 0x47, 0x8f, 0x35, 0x5a, 0x30, 0x72, 0x69, 0x2f, 0x7c, 0xad, 0x3d, 0x36, 0x68, 0xc1, + 0xf0, 0x5a, 0x50, 0xdf, 0x0d, 0x87, 0xfc, 0xfb, 0x31, 0x8b, 0xe5, 0x78, 0xe8, 0x2f, 0xa0, 0x75, + 0x99, 0xa5, 0x52, 0x45, 0xc7, 0x55, 0x14, 0xe1, 0xd9, 0x6b, 0x82, 0xb3, 0x1d, 0xc6, 0x7e, 0xad, + 0x65, 0xb5, 0x1d, 0xaa, 0x8e, 0xc8, 0x61, 0x67, 0x3e, 0x18, 0x0e, 0x3b, 0xcb, 0x4b, 0xac, 0x4f, + 0x97, 0xb8, 0x23, 0x7a, 0x92, 0xc5, 0x03, 0x96, 0x0c, 0xf6, 0x43, 0x7e, 0xea, 0x2f, 0xe9, 0x12, + 0xa7, 0xb9, 0xca, 0xb6, 0xc3, 0x52, 0xee, 0x37, 0xd0, 0x1d, 0x9e, 0xbd, 0x7b, 0x50, 0xed, 0x84, + 0xb2, 0xcb, 0x47, 0xf2, 0xc8, 0x5f, 0x6e, 0x59, 0x6d, 0x97, 0xe6, 0xb4, 0x77, 0x1b, 0x16, 0x7a, + 0x7d, 0x16, 0x71, 0x7f, 0x05, 0x0d, 0x34, 0xe1, 0x11, 0x58, 0x7a, 0x2e, 0x12, 0x1e, 0x1e, 0xc6, + 0xd8, 0x78, 0xbf, 0x89, 0x15, 0x4c, 0xf1, 0x08, 0x81, 0xe5, 0x60, 0x38, 0x12, 0x89, 0xa4, 0x3c, + 0x1d, 0x89, 0x38, 0xc5, 0xda, 0xb6, 0x92, 0xc4, 0xb7, 0x50, 0x59, 0x1d, 0xc9, 0x4f, 0xd0, 0xec, + 0x44, 0xa2, 0x7f, 0xdc, 0x65, 0x92, 0x51, 0xfe, 0xe3, 0x98, 0xa7, 0x52, 0x45, 0xd4, 0x4e, 0xb5, + 0x9e, 0x26, 0x14, 0x17, 0x91, 0xf1, 0x6d, 0xcd, 0x45, 0x42, 0x71, 0xd1, 0x1e, 0xb1, 0x71, 0xa9, + 0x26, 0x30, 0xe7, 0x23, 0x96, 0x0c, 0x10, 0x13, 0x97, 0x6a, 0x42, 0x55, 0x8e, 0x7d, 0xd1, 0x40, + 0xe0, 0x99, 0x04, 0xb0, 0x5a, 0x8a, 0x6f, 0xd2, 0x5c, 0x83, 0x0a, 0x15, 0xa7, 0x41, 0x37, 0xf5, + 0xad, 0x96, 0xd3, 0x76, 0xa9, 0xa1, 0x10, 0x6e, 0x11, 0x8d, 0x87, 0xb1, 0x12, 0xd9, 0x28, 0x2a, + 0x18, 0xe4, 0x2e, 0x2c, 0x20, 0xf6, 0xaa, 0xca, 0xc2, 0x56, 0x1d, 0xc9, 0xcf, 0x16, 0xd4, 0xb6, + 0xd9, 0x19, 0xa6, 0x91, 0x7a, 0x4f, 0xa1, 0x9a, 0x21, 0x82, 0x4a, 0xf5, 0xc7, 0xef, 0x6f, 0x64, + 0xa3, 0xbc, 0x91, 0xab, 0x6d, 0x64, 0x3a, 0x5b, 0xb1, 0x4c, 0x26, 0x34, 0x37, 0xb9, 0xf7, 0x05, + 0x34, 0xa6, 0x44, 0x2a, 0xde, 0x31, 0x9f, 0x64, 0x5d, 0x3d, 0xe6, 0x13, 0x55, 0xff, 0x09, 0x8b, + 0xc6, 0x1c, 0x7b, 0xe5, 0x52, 0x4d, 0x7c, 0x6e, 0x7f, 0x6a, 0x91, 0x7d, 0xf0, 0x36, 0x13, 0xce, + 0x24, 0xc7, 0x20, 0xdb, 0x3c, 0x4d, 0xd9, 0x21, 0xbf, 0xbc, 0xe3, 0xba, 0x8b, 0x76, 0xb9, 0x8b, + 0x39, 0x0e, 0x4e, 0x09, 0x07, 0xf2, 0x10, 0xbc, 0x2e, 0x8f, 0xb8, 0xe4, 0x66, 0x0f, 0xff, 0xc3, + 0x2f, 0xe9, 0x65, 0x39, 0x5c, 0xad, 0xeb, 0x3d, 0x00, 0x57, 0x2d, 0x35, 0xa6, 0x50, 0x7f, 0x7c, + 0xab, 0xe8, 0x53, 0xbe, 0xef, 0x14, 0x15, 0x48, 0x94, 0x39, 0xc5, 0x7c, 0xae, 0x2c, 0x6c, 0xce, + 0x28, 0x3d, 0x34, 0xa1, 0x1c, 0x0c, 0xb5, 0x56, 0x84, 0x2a, 0x5f, 0x08, 0x26, 0xda, 0xb3, 0xac, + 0xdc, 0x9b, 0x46, 0x23, 0x7d, 0x78, 0x47, 0x7b, 0xf8, 0xea, 0x84, 0x85, 0x11, 0x3b, 0x88, 0xae, + 0x89, 0xc8, 0x9c, 0xc4, 0x7d, 0x58, 0x44, 0xdb, 0xa0, 0x6b, 0xb6, 0x20, 0x23, 0xc9, 0x0f, 0x46, + 0x5f, 0x8d, 0xfe, 0x0e, 0x1b, 0x72, 0xe3, 0x0d, 0xcf, 0x79, 0xbd, 0xf6, 0xd5, 0xf5, 0xaa, 0xc0, + 0x6a, 0x5d, 0xd4, 0xa5, 0xea, 0xa8, 0xc0, 0x48, 0x90, 0x27, 0x50, 0xe9, 0xf5, 0x8f, 0xf8, 0x90, + 0x79, 0x1f, 0xc2, 0x22, 0x66, 0xc8, 0x53, 0x33, 0xd1, 0x2b, 0x33, 0x48, 0xd1, 0x4c, 0x4e, 0xba, + 0xa6, 0xb2, 0xb9, 0x39, 0x3d, 0x80, 0x0a, 0x46, 0x4f, 0x7d, 0x77, 0xd6, 0x0d, 0xf2, 0xa9, 0x11, + 0x93, 0x2d, 0x70, 0xf6, 0x68, 0xa0, 0x36, 0x15, 0x33, 0xc8, 0xbc, 0x18, 0x4a, 0xf9, 0xfe, 0x5a, + 0xa4, 0xd2, 0xf4, 0x09, 0xcf, 0x8a, 0xf7, 0x4a, 0x24, 0x12, 0x7b, 0xd4, 0xa0, 0x78, 0x26, 0x29, + 0xb8, 0x3b, 0x62, 0xc0, 0xbd, 0x65, 0xb0, 0x83, 0xae, 0xf1, 0x61, 0x07, 0x5d, 0xef, 0x3d, 0x74, + 0x6f, 0x5a, 0xd3, 0x28, 0x92, 0xd8, 0xa3, 0x01, 0xc5, 0xc0, 0xf7, 0xa1, 0x11, 0xa4, 0x9b, 0x42, + 0x24, 0x83, 0x30, 0x66, 0x52, 0x24, 0xe6, 0x6b, 0x33, 0xcd, 0xc4, 0x0d, 0x92, 0x4c, 0xea, 0x6f, + 0x43, 0x8d, 0x6a, 0x82, 0x3c, 0x83, 0xa6, 0x0a, 0x8a, 0x44, 0x86, 0xf7, 0x1a, 0x54, 0x14, 0x2f, + 0x4f, 0xc2, 0x50, 0x85, 0x07, 0xbb, 0xec, 0xe1, 0x5b, 0xed, 0x61, 0xeb, 0x84, 0xc7, 0xb2, 0x34, + 0x31, 0x48, 0xa3, 0x83, 0x06, 0xd5, 0x84, 0x47, 0x74, 0x81, 0xa6, 0x92, 0xe5, 0xa2, 0x12, 0xc5, + 0xa5, 0x28, 0x23, 0xbf, 0x5a, 0x00, 0x59, 0x42, 0xe3, 0x34, 0x37, 0xb1, 0x2e, 0x37, 0xf1, 0xda, + 0x19, 0xf2, 0x66, 0x5b, 0x9a, 0x85, 0x96, 0xe6, 0xd3, 0x6c, 0x32, 0x3e, 0x2e, 0x26, 0x43, 0x43, + 0x7a, 0x67, 0x66, 0x32, 0x74, 0xd4, 0x62, 0x3e, 0x5e, 0x41, 0xbd, 0xc4, 0x9f, 0x3b, 0x25, 0x1f, + 0xe5, 0x53, 0x62, 0xcf, 0xba, 0x44, 0xbe, 0x71, 0x99, 0xcd, 0xca, 0x4b, 0xa8, 0x97, 0xd8, 0x73, + 0x3d, 0xb6, 0x61, 0x65, 0x7a, 0x0f, 0xb3, 0xfb, 0x7d, 0x96, 0x4d, 0x42, 0x68, 0x6c, 0x46, 0xe3, + 0x54, 0xf2, 0xc4, 0xb8, 0x53, 0x1f, 0x05, 0xcd, 0xc8, 0xc1, 0x2b, 0x18, 0xf3, 0xf1, 0xf3, 0xee, + 0xc3, 0x82, 0x6a, 0xa3, 0x5e, 0xa7, 0x8b, 0x3d, 0xd6, 0x42, 0xb2, 0x0f, 0xd5, 0x4e, 0x2f, 0x78, + 0x91, 0x88, 0xf1, 0x68, 0x6e, 0xd2, 0xd9, 0xeb, 0xc1, 0xbe, 0xf8, 0x7a, 0x70, 0x2e, 0xbc, 0x1e, + 0xdc, 0xfc, 0xf5, 0x40, 0x7a, 0xb0, 0xaa, 0xaf, 0x4a, 0xb5, 0xc5, 0x37, 0xb9, 0x70, 0xb2, 0x0f, + 0xa9, 0x53, 0xfa, 0x90, 0xf6, 0x60, 0x55, 0xdf, 0x67, 0x6f, 0xd2, 0xe9, 0xef, 0x36, 0xac, 0x52, + 0x9e, 0x86, 0xaf, 0x79, 0x10, 0xa7, 0x32, 0x19, 0xf7, 0xd5, 0x9d, 0xa4, 0xec, 0xbf, 0x11, 0x07, + 0xa6, 0xdb, 0x0e, 0xd5, 0xc4, 0x75, 0x26, 0xdd, 0x7b, 0x04, 0xf5, 0xd9, 0x9d, 0xbd, 0xa8, 0x5a, + 0x56, 0xf1, 0x1e, 0xc1, 0x62, 0x4f, 0x8c, 0x93, 0x7e, 0x3e, 0xbe, 0xa5, 0x7b, 0x52, 0x67, 0xa6, + 0xc5, 0x34, 0x53, 0xf3, 0x9e, 0xce, 0x0c, 0x88, 0x5f, 0xc1, 0x28, 0x6f, 0x17, 0x76, 0x53, 0x62, + 0x3a, 0x33, 0x4e, 0x9f, 0x94, 0x77, 0xd1, 0x5f, 0x44, 0xdb, 0xdb, 0xd3, 0x19, 0x1a, 0xc3, 0x92, + 0x1e, 0xf9, 0xc5, 0x82, 0xa5, 0x72, 0x3a, 0xd7, 0x5a, 0xe2, 0x1c, 0x1d, 0x7b, 0x2e, 0x3a, 0xce, + 0x3c, 0x74, 0xdc, 0x02, 0x9d, 0xe2, 0x7d, 0xb0, 0x50, 0x7a, 0x1f, 0x90, 0x63, 0xb8, 0x7b, 0x01, + 0xb2, 0x4d, 0x31, 0x1c, 0xa9, 0xd9, 0xf8, 0x1f, 0xd0, 0xa9, 0xeb, 0x2d, 0x49, 0x0c, 0x68, 0x35, + 0xaa, 0x09, 0xf2, 0x19, 0xdc, 0xe9, 0x71, 0x59, 0x02, 0x2c, 0x9b, 0xbc, 0x16, 0x38, 0x3b, 0xfc, + 0xf4, 0x92, 0xf2, 0x95, 0x88, 0x7c, 0x09, 0xfe, 0xde, 0x68, 0xc0, 0x24, 0xbf, 0x91, 0x75, 0x07, + 0xaa, 0xbb, 0x62, 0x24, 0x22, 0x71, 0x38, 0xb9, 0xe2, 0x06, 0xf0, 0x61, 0x51, 0xdf, 0xe5, 0xfa, + 0x4a, 0xa9, 0xd1, 0x8c, 0x24, 0xb7, 0xd4, 0x70, 0xf7, 0x59, 0xd4, 0x1f, 0x47, 0x2a, 0x0d, 0xf5, + 0x76, 0x4c, 0x3b, 0xcd, 0x3f, 0xce, 0xd7, 0xad, 0xbf, 0xce, 0xd7, 0xad, 0xbf, 0xcf, 0xd7, 0xad, + 0xdf, 0xfe, 0x59, 0x7f, 0xeb, 0xa0, 0x82, 0x7f, 0x3b, 0x4f, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, + 0xf4, 0x25, 0x10, 0xc0, 0xfe, 0x0c, 0x00, 0x00, } diff --git a/internal/private.proto b/internal/private.proto index d36527f63..381fe5adb 100644 --- a/internal/private.proto +++ b/internal/private.proto @@ -19,6 +19,7 @@ message FieldOptions { int64 Base = 13; uint64 BitDepth = 14; int64 Scale = 15; + string ForeignIndex = 16; } message ImportResponse { diff --git a/server.go b/server.go index 96a4d5cde..d253fab4d 100644 --- a/server.go +++ b/server.go @@ -380,7 +380,7 @@ func NewServer(opts ...ServerOption) (*Server, error) { s.cluster.broadcaster = s s.cluster.maxWritesPerRequest = s.maxWritesPerRequest s.holder.broadcaster = s - err = s.loadExtensions() + err = s.loadAllExtensions() if err != nil { s.logger.Printf("not all plugins loaded successfully") } @@ -417,8 +417,18 @@ func (s *Server) InternalClient() InternalClient { return s.defaultClient } -func (s *Server) loadExtensions() error { - exts := ext.NewExtensions() +// loadNewExtensions loads extensions that have been +// registered since the last call to loadNewExtensions. +func (s *Server) loadNewExtensions() error { + return s.loadExtensions(ext.NewExtensions()) +} + +// loadAllExtensions loads all extensions. +func (s *Server) loadAllExtensions() error { + return s.loadExtensions(ext.AllExtensions()) +} + +func (s *Server) loadExtensions(exts []*ext.ExtensionInfo) error { var lastError error for _, extension := range exts { if err := s.loadExtension(extension); err != nil {