github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/kv/index_iter.go (about) 1 // Copyright 2015 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package kv 15 16 import ( 17 "bytes" 18 "encoding/binary" 19 "io" 20 21 "github.com/insionng/yougam/libraries/juju/errors" 22 "github.com/insionng/yougam/libraries/pingcap/tidb/util/codec" 23 "github.com/insionng/yougam/libraries/pingcap/tidb/util/types" 24 ) 25 26 var ( 27 _ Index = (*kvIndex)(nil) 28 _ IndexIterator = (*indexIter)(nil) 29 ) 30 31 // IndexIterator is the interface for iterator of index data on KV store. 32 type IndexIterator interface { 33 Next() (k []types.Datum, h int64, err error) 34 Close() 35 } 36 37 // Index is the interface for index data on KV store. 38 type Index interface { 39 // Create supports insert into statement. 40 Create(rm RetrieverMutator, indexedValues []types.Datum, h int64) error 41 // Delete supports delete from statement. 42 Delete(m Mutator, indexedValues []types.Datum, h int64) error 43 // Drop supports drop table, drop index statements. 44 Drop(rm RetrieverMutator) error 45 // Exist supports check index exists or not. 46 Exist(rm RetrieverMutator, indexedValues []types.Datum, h int64) (bool, int64, error) 47 // GenIndexKey generates an index key. 48 GenIndexKey(indexedValues []types.Datum, h int64) (key []byte, distinct bool, err error) 49 // Seek supports where clause. 50 Seek(r Retriever, indexedValues []types.Datum) (iter IndexIterator, hit bool, err error) 51 // SeekFirst supports aggregate min and ascend order by. 52 SeekFirst(r Retriever) (iter IndexIterator, err error) 53 } 54 55 func encodeHandle(h int64) []byte { 56 buf := &bytes.Buffer{} 57 err := binary.Write(buf, binary.BigEndian, h) 58 if err != nil { 59 panic(err) 60 } 61 return buf.Bytes() 62 } 63 64 func decodeHandle(data []byte) (int64, error) { 65 var h int64 66 buf := bytes.NewBuffer(data) 67 err := binary.Read(buf, binary.BigEndian, &h) 68 return h, errors.Trace(err) 69 } 70 71 // indexIter is for KV store index iterator. 72 type indexIter struct { 73 it Iterator 74 idx *kvIndex 75 prefix Key 76 } 77 78 // Close does the clean up works when KV store index iterator is closed. 79 func (c *indexIter) Close() { 80 if c.it != nil { 81 c.it.Close() 82 c.it = nil 83 } 84 } 85 86 // Next returns current key and moves iterator to the next step. 87 func (c *indexIter) Next() (val []types.Datum, h int64, err error) { 88 if !c.it.Valid() { 89 return nil, 0, errors.Trace(io.EOF) 90 } 91 if !c.it.Key().HasPrefix(c.prefix) { 92 return nil, 0, errors.Trace(io.EOF) 93 } 94 // get indexedValues 95 buf := c.it.Key()[len(c.prefix):] 96 vv, err := codec.Decode(buf) 97 if err != nil { 98 return nil, 0, errors.Trace(err) 99 } 100 // if index is *not* unique, the handle is in keybuf 101 if !c.idx.unique { 102 h = vv[len(vv)-1].GetInt64() 103 val = vv[0 : len(vv)-1] 104 } else { 105 // otherwise handle is value 106 h, err = decodeHandle(c.it.Value()) 107 if err != nil { 108 return nil, 0, errors.Trace(err) 109 } 110 val = vv 111 } 112 // update new iter to next 113 err = c.it.Next() 114 if err != nil { 115 return nil, 0, errors.Trace(err) 116 } 117 return 118 } 119 120 // kvIndex is the data structure for index data in the KV store. 121 type kvIndex struct { 122 indexName string 123 indexID int64 124 unique bool 125 prefix Key 126 } 127 128 // GenIndexPrefix generates the index prefix. 129 func GenIndexPrefix(indexPrefix Key, indexID int64) Key { 130 buf := make([]byte, 0, len(indexPrefix)+8) 131 buf = append(buf, indexPrefix...) 132 buf = codec.EncodeInt(buf, indexID) 133 return buf 134 } 135 136 // NewKVIndex builds a new kvIndex object. 137 func NewKVIndex(indexPrefix Key, indexName string, indexID int64, unique bool) Index { 138 index := &kvIndex{ 139 indexName: indexName, 140 indexID: indexID, 141 unique: unique, 142 prefix: GenIndexPrefix(indexPrefix, indexID), 143 } 144 145 return index 146 } 147 148 // GenIndexKey generates storage key for index values. Returned distinct indicates whether the 149 // indexed values should be distinct in storage (i.e. whether handle is encoded in the key). 150 func (c *kvIndex) GenIndexKey(indexedValues []types.Datum, h int64) (key []byte, distinct bool, err error) { 151 if c.unique { 152 // See: https://dev.mysql.com/doc/refman/5.7/en/create-index.html 153 // A UNIQUE index creates a constraint such that all values in the index must be distinct. 154 // An error occurs if you try to add a new row with a key value that matches an existing row. 155 // For all engines, a UNIQUE index permits multiple NULL values for columns that can contain NULL. 156 distinct = true 157 for _, cv := range indexedValues { 158 if cv.Kind() == types.KindNull { 159 distinct = false 160 break 161 } 162 } 163 } 164 165 key = append(key, c.prefix...) 166 if distinct { 167 key, err = codec.EncodeKey(key, indexedValues...) 168 } else { 169 key, err = codec.EncodeKey(key, append(indexedValues, types.NewDatum(h))...) 170 } 171 if err != nil { 172 return nil, false, errors.Trace(err) 173 } 174 return 175 } 176 177 // Create creates a new entry in the kvIndex data. 178 // If the index is unique and there is an existing entry with the same key, Create will return ErrKeyExists. 179 func (c *kvIndex) Create(rm RetrieverMutator, indexedValues []types.Datum, h int64) error { 180 key, distinct, err := c.GenIndexKey(indexedValues, h) 181 if err != nil { 182 return errors.Trace(err) 183 } 184 if !distinct { 185 // TODO: reconsider value 186 err = rm.Set(key, []byte("timestamp?")) 187 return errors.Trace(err) 188 } 189 190 _, err = rm.Get(key) 191 if IsErrNotFound(err) { 192 err = rm.Set(key, encodeHandle(h)) 193 return errors.Trace(err) 194 } 195 196 return errors.Trace(ErrKeyExists) 197 } 198 199 // Delete removes the entry for handle h and indexdValues from KV index. 200 func (c *kvIndex) Delete(m Mutator, indexedValues []types.Datum, h int64) error { 201 key, _, err := c.GenIndexKey(indexedValues, h) 202 if err != nil { 203 return errors.Trace(err) 204 } 205 err = m.Delete(key) 206 return errors.Trace(err) 207 } 208 209 // Drop removes the KV index from store. 210 func (c *kvIndex) Drop(rm RetrieverMutator) error { 211 it, err := rm.Seek(c.prefix) 212 if err != nil { 213 return errors.Trace(err) 214 } 215 defer it.Close() 216 217 // remove all indices 218 for it.Valid() { 219 if !it.Key().HasPrefix(c.prefix) { 220 break 221 } 222 err := rm.Delete(it.Key()) 223 if err != nil { 224 return errors.Trace(err) 225 } 226 err = it.Next() 227 if err != nil { 228 return errors.Trace(err) 229 } 230 } 231 return nil 232 } 233 234 // Seek searches KV index for the entry with indexedValues. 235 func (c *kvIndex) Seek(r Retriever, indexedValues []types.Datum) (iter IndexIterator, hit bool, err error) { 236 key, _, err := c.GenIndexKey(indexedValues, 0) 237 if err != nil { 238 return nil, false, errors.Trace(err) 239 } 240 it, err := r.Seek(key) 241 if err != nil { 242 return nil, false, errors.Trace(err) 243 } 244 // check if hit 245 hit = false 246 if it.Valid() && it.Key().Cmp(key) == 0 { 247 hit = true 248 } 249 return &indexIter{it: it, idx: c, prefix: c.prefix}, hit, nil 250 } 251 252 // SeekFirst returns an iterator which points to the first entry of the KV index. 253 func (c *kvIndex) SeekFirst(r Retriever) (iter IndexIterator, err error) { 254 it, err := r.Seek(c.prefix) 255 if err != nil { 256 return nil, errors.Trace(err) 257 } 258 return &indexIter{it: it, idx: c, prefix: c.prefix}, nil 259 } 260 261 func (c *kvIndex) Exist(rm RetrieverMutator, indexedValues []types.Datum, h int64) (bool, int64, error) { 262 key, distinct, err := c.GenIndexKey(indexedValues, h) 263 if err != nil { 264 return false, 0, errors.Trace(err) 265 } 266 267 value, err := rm.Get(key) 268 if IsErrNotFound(err) { 269 return false, 0, nil 270 } 271 if err != nil { 272 return false, 0, errors.Trace(err) 273 } 274 275 // For distinct index, the value of key is handle. 276 if distinct { 277 handle, err := decodeHandle(value) 278 if err != nil { 279 return false, 0, errors.Trace(err) 280 } 281 282 if handle != h { 283 return true, handle, errors.Trace(ErrKeyExists) 284 } 285 286 return true, handle, nil 287 } 288 289 return true, h, nil 290 }