vitess.io/vitess@v0.16.2/go/vt/vtgate/vindexes/numeric.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package vindexes 18 19 import ( 20 "bytes" 21 "context" 22 "encoding/binary" 23 "fmt" 24 25 "vitess.io/vitess/go/vt/vtgate/evalengine" 26 27 "vitess.io/vitess/go/sqltypes" 28 "vitess.io/vitess/go/vt/key" 29 ) 30 31 var ( 32 _ SingleColumn = (*Numeric)(nil) 33 _ Reversible = (*Numeric)(nil) 34 _ Hashing = (*Numeric)(nil) 35 ) 36 37 // Numeric defines a bit-pattern mapping of a uint64 to the KeyspaceId. 38 // It's Unique and Reversible. 39 type Numeric struct { 40 name string 41 } 42 43 // NewNumeric creates a Numeric vindex. 44 func NewNumeric(name string, _ map[string]string) (Vindex, error) { 45 return &Numeric{name: name}, nil 46 } 47 48 // String returns the name of the vindex. 49 func (vind *Numeric) String() string { 50 return vind.name 51 } 52 53 // Cost returns the cost of this vindex as 0. 54 func (*Numeric) Cost() int { 55 return 0 56 } 57 58 // IsUnique returns true since the Vindex is unique. 59 func (*Numeric) IsUnique() bool { 60 return true 61 } 62 63 // NeedsVCursor satisfies the Vindex interface. 64 func (*Numeric) NeedsVCursor() bool { 65 return false 66 } 67 68 // Verify returns true if ids and ksids match. 69 func (vind *Numeric) Verify(ctx context.Context, vcursor VCursor, ids []sqltypes.Value, ksids [][]byte) ([]bool, error) { 70 out := make([]bool, 0, len(ids)) 71 for i, id := range ids { 72 ksid, err := vind.Hash(id) 73 if err != nil { 74 return nil, err 75 } 76 out = append(out, bytes.Equal(ksid, ksids[i])) 77 } 78 return out, nil 79 } 80 81 // Map can map ids to key.Destination objects. 82 func (vind *Numeric) Map(ctx context.Context, vcursor VCursor, ids []sqltypes.Value) ([]key.Destination, error) { 83 out := make([]key.Destination, 0, len(ids)) 84 for _, id := range ids { 85 ksid, err := vind.Hash(id) 86 if err != nil { 87 out = append(out, key.DestinationNone{}) 88 continue 89 } 90 out = append(out, key.DestinationKeyspaceID(ksid)) 91 } 92 return out, nil 93 } 94 95 // ReverseMap returns the associated ids for the ksids. 96 func (*Numeric) ReverseMap(_ VCursor, ksids [][]byte) ([]sqltypes.Value, error) { 97 var reverseIds = make([]sqltypes.Value, len(ksids)) 98 for i, keyspaceID := range ksids { 99 if len(keyspaceID) != 8 { 100 return nil, fmt.Errorf("Numeric.ReverseMap: length of keyspaceId is not 8: %d", len(keyspaceID)) 101 } 102 val := binary.BigEndian.Uint64(keyspaceID) 103 reverseIds[i] = sqltypes.NewUint64(val) 104 } 105 return reverseIds, nil 106 } 107 108 func (*Numeric) Hash(id sqltypes.Value) ([]byte, error) { 109 num, err := evalengine.ToUint64(id) 110 if err != nil { 111 return nil, err 112 } 113 var keybytes [8]byte 114 binary.BigEndian.PutUint64(keybytes[:], num) 115 return keybytes[:], nil 116 } 117 118 func init() { 119 Register("numeric", NewNumeric) 120 }